chipweinberger / flutter_blue_plus

Flutter plugin for connecting and communicationg with Bluetooth Low Energy devices, on Android, iOS, macOS
Other
727 stars 442 forks source link

[Feature]: Windows Support #6

Closed FXschwartz closed 3 weeks ago

FXschwartz commented 2 years ago

It would great to eventually be cross-platform with all platforms Flutter supports.

Original Flutter_Blue Issue

rzr commented 2 years ago

Relate to: https://github.com/woodemi/quick_blue/pull/63

fuzzybinary commented 1 year ago

I've been thinking about playing around with Windows support for this package but I was wondering if there are plans to convert this to a Federated plugin first?

chipweinberger commented 1 year ago

@fuzzybinary would be awesome. QuickBlue has a good reference implementation.

No i don't want the complexity of federated! Forking is simple enough if people needed to do something custom.

chan150 commented 11 months ago

flutter_blue_plus_windows packages can be helpful for someone:

pub.dev repository

chipweinberger commented 11 months ago

@chan150 wow!

when you are ready, feel free to open a PR

however it should not be a "wrapper" but "properly coded"

Shunt22 commented 10 months ago

Any updates on Windows support? It would be amazing to have it, considering that this plugin is only one activly developing.

chipweinberger commented 10 months ago

i'm not going to implement windows, but someone else could

kokroo commented 7 months ago

What needs to be done to add Windows and Linux support? If I am not wrong Flutter already has those APIs?

chipweinberger commented 7 months ago

you just need to write the windows C++ code.

reference code: https://github.com/woodemi/quick_blue/blob/master/quick_blue_windows/windows/quick_blue_windows_plugin.cpp

I suggest you make a new flutter_blue_plus_for_windows package on pub.dev.

Then in flutter_blue_plus_for_windows you can create a platform channel using the existing flutter_blue_plus/methods name.

flutter::MethodChannel<EncodableValue>>(
          registrar->messenger(), "flutter_blue_plus/methods",
          &flutter::StandardMethodCodec::GetInstance());

and of course you then need to implement the fbp platform channel methods, i.e.

                case "flutterHotRestart":
                case "connectedCount":
                case "setLogLevel":
                case "isSupported":
                case "getAdapterName":
                case "getAdapterState":
                case "turnOn":
                case "turnOff":
                case "startScan":
                case "stopScan":
                case "getSystemDevices":
                case "connect":
                case "disconnect":
                case "discoverServices":
                case "readCharacteristic":
                case "writeCharacteristic":
                case "readDescriptor":
                case "writeDescriptor":
                .... among others.....

Users would then specify both packages in their pubspec.yaml

dependencies:
  flutter_blue_plus: ^1.31.13
  flutter_blue_plus_for_windows: ^1.0.0

Fbp will find the platform channel by name, and it should "just work".

Doing it this way:

  1. FBP does not need to use federated plugins
  2. someone else other than me will be responsible for windows support, and github issues will be handled by them
  3. unlike flutter_blue_plus_windows, you don't need to make a huge wrapper around fbp

Eventually, after all of the bugs are fixed in Windows support, I'll merge it into the FBP main repo.

stuartmorgan commented 7 months ago

I suggest you make a new flutter_blue_plus_for_windows package on pub.dev.

Then in flutter_blue_plus_for_windows you can create a platform channel using the existing flutter_blue_plus/methods name.

[...]

Doing it this way:

  1. FBP does not need to use federated plugins
  2. someone else other than me will be responsible for windows support
  3. unlike flutter_blue_plus_windows, you don't need to make a huge wrapper around fbp

As I noted in a related discussion, this list is missing:

  1. subjects clients of the proposed flutter_blue_plus_for_windows to potential breakage (including potentially crashing, unless all the platform channel code in the plugin is written extremely defensively) without warning any time internal implementation details of flutter_blue_plus change.

I would caution anyone making such a plugin to consider carefully whether they would actually want to publish it on pub.dev given that caveat.

chipweinberger commented 7 months ago

It's worth noting that FBP is pretty stable at this point.

To prevent breakage, the flutter_blue_plus_windows author should specify the exact flutter_blue_plus versions their library is compatible with in their pubspec.yaml

name: flutter_blue_plus_for_windows
description: windows support for FlutterBluePlus
version: 1.0.0

dependencies:
  flutter_blue_plus: ">=1.29.0 <1.40.0"
tototo23 commented 7 months ago

Hi, I've seen that an other fork from FlutterBlue made Windows support : https://pub.dev/packages/flutter_blue_plugin Has anyone tried it? It's not maintained for almost 2 years, but maybe the Windows part in cpp was good ?

Flutter Blue Plus is by far the most stable BLE lib i found for Flutter, congrats @chipweinberger ! I join other comments, it would be awesome if Windows could be supported too ! (I tried flutter_blue_plus_windows but I don't have the same bahaviour/stability than Android/iOS for now on Windows, with Dialog protocol, ending with GATT_REQUEST_NOT_SUPPORTED)

ChaseGuru commented 2 months ago
  1. subjects clients of the proposed flutter_blue_plus_for_windows to potential breakage (including potentially crashing, unless all the platform channel code in the plugin is written extremely defensively) without warning any time internal implementation details of flutter_blue_plus change.

I would caution anyone making such a plugin to consider carefully whether they would actually want to publish it on pub.dev given that caveat. @stuartmorgan

Yeah as the maintainer nicely hinted, this isn't really true, for several reasons:

So this concern seems to represent a fundamental misunderstanding of how flutter versioning (or any versioning that involves a lock file) works. If you upgrade your packages (via flutter pub upgrade or the like) and deploy a new version of your app and it's broken, that's not random, and it's because of failures on multiple levels.

If you meant to say, it's annoying because developers may be held back from upgrading to the latest FBP because the windows package may not be maintained actively enough or lags behind some amount of time so you'd rather FBP just maintain it first party, then sure. But FBP isn't going to do the work now (fair, it's a free open source package you can't just expect people to do everything for you), and an fbp_windows package existing is better than not, as at least you have the option to either use an older FBP version with it (or if you did upgrade to the latest FBP and it was incompatible it would only break windows). You can also forcefully ignore the fbp_windows dependency constraints by specifing an override for the fbp version if you think fbp_windows may be compatible with newer fbp versions (but they haven't updated the pubspec and deployed a new version) and knowing the "risk" of doing so you should test that it works. Presuming it does, then nothing that worked should randomly break (unless you later upgrade again at which point you should test again). You also have the power to fork fbp windows and made the presumably small compatibility changes needed to upgrade it.

Luckily the FBP guy even said he'd adopt it eventually assuming it was written properly and become stable enough.

To summarize the FBP maintainer has done a lot of documenting to help someone do the initial windows work if they want, and if so app developers are still subject to how stable and well maintained that package is (like any package), but at least they'd have the option and with testing it could indeed be a stable solution.

stuartmorgan commented 2 months ago
  • The desktop package maintainer could and should use version constraints that block using newer versions that are likely to be incompatible probably allowing patch but not minor version updates

Allowing patch updates only works if the base plugin always versions any change to the platform channel de-facto API as at least a minor change. Which would be a very non-standard thing—if it's considered part of the public interface then changes would be major per semver, and if it's not then it would easy to forget to use a minor version instead of a bugfix version for a very minor change that touched the platform interface.

And while a desktop maintainer should use very specific constraints, that is also non-standard, and would only work if the two sides explicitly agreed on the versioning protocol you described. Or if they didn't, only if the Windows package maintainer doesn't allow even bugfix changes beyond the last tested version (and in doing so, significantly increase the potential for resolver failures, which is an area that, in practice, causes a lot of confusion for package clients).

In practice, constraint mistakes aren't all that uncommon even in much simpler cases. It's possible to make that work, but only if everything goes exactly right.

since that's what the maintainer suggested

A suggestion that was made after my comment. I would argue that the fact that a critical failure point wasn't considered until I raised it supports my point that the suggested approach is hard to get right, and thus something a potential author should weigh carefully.

  • The app developer could specify version constraints preventing upgrade to possibly incompatible versions if they wanted.

They could, yes, but in practice most wouldn't, and a substantial number wouldn't even know how to do so correctly without a lot of investigation into the internals of the packages. Version resolution and version management are complex, and many developers do not understand it well enough to effectively manage it.

  • Your packages are cached on your machine and are bundled with your compiled application, so I'm not sure something breaking after you upgrade packages and/or deployed counts as "without warning at any time".
  • Flutter uses a lock file to help give control over changes in resolved dependencies. Essentially it exists so what you're saying should not happen unless - you have to choose to upgrade not just install. flutter pub get should not cause unexpected package changes as it will use your lock file as long as you haven't added new dependencies it can't resolve.

A non-trivial number of people do not use, or know they should be using, lock files.

Also, the IDE plugins prompt to suggest upgrade after Flutter updates; many people are going to accept it without being fully aware of the distinction (in fact, that prompting happens precisely because a significant number of people didn't know they should ever be upgrade-ing in the first place, causing a lot of issues with continuing to use old versions of packages that weren't compatible with newer versions of Flutter).

So this concern seems to represent a fundamental misunderstanding of how flutter versioning (or any versioning that involves a lock file) works.

I'm the technical lead for ecosystem on the Flutter team; I understand how versioning works. But I also have years of experience with the actual problems people encounter with the package ecosystem, and the way things fail, in practice, for large numbers of users. My concern does not represent a fundamental misunderstanding of versioning, it represents an understanding—based on a substantial amount of real-world experience in seeing the kinds of problems people encounter—that the theoretical ideal of how versioning could work does not map directly to what many developers experience.

If you meant to say, it's annoying because developers may be held back from upgrading to the latest FBP because the windows package may not be maintained actively enough or lags behind some amount of time

If I had meant that, I would have said that. What I meant is what I actually said in my comment.

so you'd rather FBP just maintain it first party

I was not expression an opinion about what flutter_blue_plus maintainers should do. I was cautioning anyone considering publishing a flutter_blue_plus_windows on pub.dev using the approach described in the comment I was replying to that doing so has potential dangers that they should be aware of before deciding to do so.

ChaseGuru commented 2 months ago

@stuartmorgan Again a lot of this is untrue. You should look more into the documented standards for package management, but put simply: As noted here: https://dart.dev/tools/pub/pubspec#version

When you select a version, follow semantic versioning.

Or here: https://dart.dev/tools/pub/dependencies#version-constraints The Dart community uses semantic versioning1.

Or here: https://dart.dev/tools/pub/dependencies#caret-syntax

Or a full description on it here: https://dart.dev/tools/pub/dependencies#caret-syntax

Semantic versioning is an accepted standard, though I will conceded some people aren't aware of the difference between 0.x.x packages and >1.x.x packages. The ^ symbol that is generally used in pub files intelligently locks to "backwards compatible versions" adjusting for if packages are major version 0 or 1. People don't like to upgrade the major version as often as they should probably because it feels bad for whatever reason that perhaps eventually their package version might be 23.x.x (they could also just stay in 0.x longer).

So, I suppose I will say, I'm glad you don't think it's a good idea to make a package, since you don't know much about the standards you're expected to follow when making them. But most people who bother to make packages do, and/or these problems apply to any package and it's maintainer, not just the one you're specifically saying is bad.

A suggestion that was made after my comment.

Yes if you understand semantic versioning and dart package management then there's no reason someone would feel the need to go our of their way to say "oh and if the package maintainer has no idea what their doing, and an app developer has no idea what their doing, they may think their app "randomly broke" because they didn't test their app after upgrading packages".

A non-trivial number of people do not use, or know they should be using, lock files.

This is just false. Lock files are done for you. There is no way with flutter/dart pub to remove the function of a lock file. The same is true if I'm not mistaken for nodejs, and pipenv for example. Perhaps you have explicitly gone against documented standards and added pubspec.lock to your .gitignore? If so I suppose it's not surprising you think packages can "randomly break", since you explicitly disabled the feature that prevents it.

This may be good reading for you perhaps, it summarizes a lot of this. https://medium.com/codingmountain-blog/what-is-pubspec-lock-and-why-should-flutter-devs-care-86ab4d0b47fc

Also, the IDE plugins prompt to suggest upgrade after Flutter updates

Ah yes, so because some developers have no concept of the idea that "upgrade packages" might break something, you are saying people shouldn't develop a package, because it might break when upgraded. As a developer who isn't ignorant, I could care less if someone's app breaks because they don't understand that upgrading packages upgrades things and that could break something.

I'm the technical lead for ecosystem on the Flutter team; I understand how versioning works. But I also have years of experience with the actual problems people encounter with the package ecosystem, and the way things fail, in practice, for large numbers of users

So impressive. I've been at a dev shop for about 10 years, and I serve a mentoring role and act as a tech lead and manager on a variety of projects. Our company has around 40-50 developers now, and I've mentored as Juniors many of our developers. I've spearheaded our company using flutter in early 2018 right after it hit beta.

Our pubspec.lock is updated frequently sure. Very occasionally something does break because a dependency changed or whatever else. That's kind of what happens when you upgrade packages though, and if we want our app to be stable, we test it via automated or manual tests. 9 times out of 10 though, newly introduced bugs are one of the app developers fault, not some package maintainer.

I'm the technical lead for ecosystem on the Flutter team; I understand how versioning works Clearly. You totally understand semantic versioning after I told you about it, even though you complaints fly in the face of semantic versioning and lock files.

If I had meant that, I would have said that. What I meant is what I actually said in my comment.

I was considering alternatives just in case you weren't actually making such an invalid argument.

And ok, so you know what flutter pub upgrade does versus flutter pub get, but you stand by: "subjects clients of the proposed flutter_blue_plus_for_windows to potential breakage (including potentially crashing, unless all the platform channel code in the plugin is written extremely defensively) without warning any time internal implementation details of flutter_blue_plus change"

But you've changed your argument as I've proven it wrong from "potential breakage without warning at any time" to "people don't understand what upgrade means when their IDE says it, so stuff sometimes breaks unexpectedly for them".

If you actually understood all this, you should have said "If someone does create this package we should ensure that FBP follows semantic versioning correctly, and that package uses proper dependency constraints to prevent bugs due to pub resolving incompatible versions.

publishing a flutter_blue_plus_windows on pub.dev using the approach described in the comment I was replying to that doing so has potential dangers that they should be aware of before deciding to do so.

Again, you want to keep stuff away from people just in case they are incompetent. I suppose you're the kind of person who never wanted a "files" app on his iphone, it's too dangerous and complex to have access to manage your own files. How you're an engineer, I don't know.

Apology I've attacked your knowledge and credibility in a way I probably shouldn't have. I'm sorry. I just don't like that you're telling people not to release or share code that could be useful. I have used flutter_blue/plus a lot, and flutter_reactive_ble on one project. I've never used universal_ble, so I am not sure if I like it as an alternative yet. If someone made a _windows fbp package, I'd consider using it. There's certainly plenty of chance for it to be bad, so I'd make a determination if it looks well created, stable and maintained when choosing to use it, but I'd love to have that choice, rather than not because someone is telling people not to share their code because they are afraid their subordinates will misuse it.

ChaseGuru commented 2 months ago

It's also important any package that depends on other packages uses correct dependency constraints and that semantic versioning is followed correctly. So that's important in all packages.

For example even if fbp made the windows package themselves (which means they come out at the same time so upgrading should probably resolve the matching versions) if I locked versions of my packages using ^ correctly and I ran flutter pub ugprade flutter_blue_plus it could possibly upgrade FBP but not the _windows package, causing "random crashes" if version constraints aren't setup right.

I get, and I suppose it represents some insight that since platform channels are loosely typed it's more likely for there to be potentially crashing problems that are not caught at compile time. But the solution isn't to rely on releasing packages at the same time to make sure people resolve the compatible versions of them. The solution is to manage dependencies correctly. Perhaps another solution is a stronger typed platform channel option, I haven't looked into if flutter has one yet, I know they had a couple new things.

ChaseGuru commented 2 months ago

Even if you don't know the versioning scheme a package uses, you can also just limit the version to the highest tested version.

stuartmorgan commented 2 months ago

these problems apply to any package and it's maintainer

I have never seen another instance of a package maintainer explicitly encouraging people to publish packages that use internal implementation details of their package, which they do not treat as public API for the purposes of making semver evaluations in their versioning, as the package's API surface.

Anyone who doesn't think that's fundamentally different from normal package development, and thus something that warrants significant extra care and consideration before proceeding, is obviously free to ignore my comment.

I just don't like that you're telling people not to release or share code that could be useful.

I didn't tell anyone not to release their code, nor would I presume to have any authority to do so. What people choose to do with my suggestion of evaluating such a release more carefully than usual (whether that's consider it, dismiss it, or—as you've demonstrated—actively attack both it and me as ignorant) is entirely up to them.

(If anyone planning on making an implementation package does have questions about the differences between a federated plugin and the approach suggested in this thread, and how those differences would impact development and maintenance of such a package, feel free to reach out to me in the #package-authors channel on the Flutter team's Discord server; this issue does not appear to be a good forum for constructive discussion of that topic.)

ChaseGuru commented 2 months ago

I have never seen another instance of a package maintainer explicitly encouraging people to publish packages that use internal implementation details of their package, which they do not treat as public API for the purposes of making semver evaluations in their versioning, as the package's API surface.

I don't know if the package maintainer explicitly asked them to do it but the firebase_core_desktop and the associated auth/and functions packages implement native implementaions of the first party platform channels and are maintained in the FirebaseExtended github group which explicitly states they are volunteers and not googlers. So it is not first party, but yes, it does implement FirebasePlatform and comply to their platform channels code.

You can see in their pubspec.yaml, they appropriately rely on firebase_core_platform_interface: ^4.5.0 to ensure their platform channel implementation allow unsupported versions of the dart platform channel implementation.

Open source package maintainers very frequently encourage community work or support in all manner of things. I am pretty sure I've heard a few flutter package maintainers mention people could add support for certain platforms versions or the like before - which would implicitly mean they have to add a platform package. I wouldn't be surprised if firebase isn't the only time it's happened.

You also call it a "private API" but I don't know what is "private" about a publicly pushed and open source code base.

Anyone who doesn't think that's fundamentally different from normal package development, and thus something that warrants significant extra care and consideration before proceeding, is obviously free to ignore my comment.

We very clearly all believe dependency constraints should be setup correctly. If your stance is now to just make sure you don't write it bad, that's fine by me, I just didn't like implication that publishing publicly could be a bad thing.

StarLumos commented 2 months ago

Hi there, I'm new to Flutter and wanted to clarify if flutter_blue_plus is supported on Ubuntu? I'm currently getting this error message, among others:

$ flutter run
Launching lib/main.dart on Linux in debug mode...
Building Linux application...
✓ Built build/linux/x64/debug/bundle/bluetooth_detector
flutter: [FBP] <setLogLevel> args: 5
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method flutterRestart on channel flutter_blue_plus/methods)
#0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
<asynchronous suspension>
#1      FlutterBluePlus._initFlutterBluePlus (package:flutter_blue_plus/src/flutter_blue_plus.dart:417:10)
<asynchronous suspension>

My hunch was that this has to do with my being on Ubuntu (24.02 LTS), and after finding this thread, it seems like this is the problem. If anyone could confirm, that would be great! Thank you!

Shunt22 commented 2 months ago

Hi there, I'm new to Flutter and wanted to clarify if flutter_blue_plus is supported on Ubuntu?

It does not. At least for now.

You can check supported plaftroms on pub.dev page of any package. (Look for plaftorms section at the top of the page) https://pub.dev/packages/flutter_blue_plus

If you need more cross-plaftorm BLE package consider looking into: https://pub.dev/packages/bluetooth_low_energy

StarLumos commented 2 months ago

It does not. At least for now.

Alright, thank you for confirming!

ChaseGuru commented 2 months ago

For completeness I will mention there is also this package which supports other platforms - and also includes web (unlike the other) https://pub.dev/packages/universal_ble

In addition to: https://pub.dev/packages/bluetooth_low_energy

I haven't used either and have no idea how good either one is.

chipweinberger commented 3 weeks ago

flutter_blue_plus_windows is now the official package for windows support.

I've linked to it in the README

I'll open a new issue for Linux support