diff --git a/CHANGELOG.md b/CHANGELOG.md index f4706f6..2d25179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.9.5 +* Windows support has graduated from beta to stable +* Support filtering by manufacturer data +* Unify web's optionalServices API with filtering API +* Implement requestMtu in Linux +* Fix wrong manufacturer data in Windows release builds +* Improve logging + ## 0.9.4 * Fix Windows crash when no Bluetooth adapter is present diff --git a/README.md b/README.md index 1d4f678..3d4260a 100644 --- a/README.md +++ b/README.md @@ -19,20 +19,20 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE ### API Support Matrix -| API | Android | iOS | macOS | Windows (beta) | Linux (beta) | Web | -| :------------------- | :-----: | :-: | :---: | :------------: | :----------: | :-: | -| startScan/stopScan | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| connect/disconnect | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| getConnectedDevices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | -| discoverServices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| readValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| writeValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| setNotifiable | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| pair/unPair | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | -| onPairingStateChange | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | -| enableBluetooth | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | -| onAvailabilityChange | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| requestMtu | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | +| API | Android | iOS | macOS | Windows | Linux (beta) | Web | +| :------------------- | :-----: | :-: | :---: | :-----: | :----------: | :-: | +| startScan/stopScan | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| connect/disconnect | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| getConnectedDevices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | +| discoverServices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| readValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| writeValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| setNotifiable | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| pair/unPair | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | +| onPairingStateChange | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | +| enableBluetooth | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ | +| onAvailabilityChange | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| requestMtu | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ## Getting Started @@ -63,7 +63,8 @@ UniversalBle.startScan(); // Or optionally add a scan filter UniversalBle.startScan( scanFilter: ScanFilter( - withServices: ["SERVICE_UUID"], + withServices: ["SERVICE_UUID"], + withManufacturerData: ["MANUFACTURER_DATA"] ) ); @@ -71,6 +72,26 @@ UniversalBle.startScan( UniversalBle.stopScan(); ``` +Before initiating a scan, ensure that Bluetooth is available: +```dart +AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState() +// Start scan only if Bluetooth is powered on +if (state != AvailabilityState.poweredOn) { + UniversalBle.startScan(); +} + +// Or listen to bluetooth availability changes +UniversalBle.onAvailabilityChange = (state) { + if (state == AvailabilityState.poweredOn) { + UniversalBle.startScan(); + } +}; +``` + +See the [Bluetooth Availability](#bluetooth-availability) section for more. + +#### Connected Devices + Already connected devices, either through previous sessions or connected through system settings, won't show up as scan results. You can list those devices using `getConnectedDevices()`. You still need to explicitly connect before using them. @@ -79,6 +100,26 @@ You can list those devices using `getConnectedDevices()`. You still need to expl await UniversalBle.getConnectedDevices(withServices: []); ``` +#### Scan Filter + +You can optionally set filters when scanning. + +##### With Services + +When setting this parameter, the scan results will only include devices that advertize any of the specified services. This is the primary filter. All devices are first filtered by services, then further filtered by other criteria. This parameter is mandatory on [web](#web) if you want to access those services. + +```dart +List withServices; +``` + +##### With ManufacturerData + +Use the `withManufacturerData` parameter to filter devices by manufacturer data. When you pass a list of `ManufacturerDataFilter` objects to this parameter, the scan results will only include devices that contain any of the specified manufacturer data. + +```dart +List withManufacturerData; +``` + ### Connecting ```dart @@ -209,15 +250,13 @@ Add the `Bluetooth` capability to the macOS app from Xcode. When publishing on Windows you need to declare the following [capabilities](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations): `bluetooth, radios` ### Web -` -On web, you have to add filters and specify optional services when scanning for devices. The parameter is ignored on other platforms. + +On web, the `withServices` parameter in the ScanFilter is used as [optional_services](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice#optionalservices) as well as a services filter. On web you have to set this parameter to ensure that you can access the specified services after connecting to the device. You can leave it empty for the rest of the platforms if your device does not advertize services. ```dart -UniversalBle.startScan( - webRequestOptions: WebRequestOptionsBuilder.acceptAllDevices( - optionalServices: ["SERVICE_UUID"], - ), -); +ScanFilter( + withServices: kIsWeb ? ["SERVICE_UUID"] : [], +) ``` ## Customizing Platform Implementation of UniversalBle diff --git a/example/lib/home/home.dart b/example/lib/home/home.dart index ee3d8ed..f0ff19b 100644 --- a/example/lib/home/home.dart +++ b/example/lib/home/home.dart @@ -75,18 +75,12 @@ class _MyAppState extends State { scanFilter: ScanFilter( withServices: kIsWeb ? _services : [], withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x012D, - data: Uint8List.fromList( - [0x03, 0x00, 0x64, 0x00], - ), - ), - ManufacturerDataFilter( - companyIdentifier: 0x012D, - data: Uint8List.fromList( - [0x03, 0x00, 0x65, 0x00], - ), - ), + // ManufacturerDataFilter( + // companyIdentifier: 0x012D, + // data: Uint8List.fromList( + // [0x03, 0x00, 0x64, 0x00], + // ), + // ), ], ), ); diff --git a/example/pubspec.lock b/example/pubspec.lock index d309065..3e94b40 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" flutter: dependency: "direct main" description: flutter @@ -191,6 +191,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -211,34 +235,34 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" permission_handler: dependency: "direct main" description: @@ -291,10 +315,10 @@ packages: dependency: transitive description: name: platform - sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: @@ -307,10 +331,10 @@ packages: dependency: transitive description: name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "5.0.2" sky_engine: dependency: transitive description: flutter @@ -386,7 +410,7 @@ packages: path: ".." relative: true source: path - version: "0.9.4" + version: "0.9.5" vector_math: dependency: transitive description: @@ -399,26 +423,18 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.10.0" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" + version: "13.0.0" webdriver: dependency: transitive description: name: webdriver - sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" win32: dependency: transitive description: @@ -444,5 +460,5 @@ packages: source: hosted version: "6.3.0" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.2.0-0 <4.0.0" flutter: ">=3.10.0" diff --git a/lib/src/universal_ble_web/universal_ble_web.dart b/lib/src/universal_ble_web/universal_ble_web.dart index 8b28d3e..d940911 100644 --- a/lib/src/universal_ble_web/universal_ble_web.dart +++ b/lib/src/universal_ble_web/universal_ble_web.dart @@ -111,6 +111,13 @@ class UniversalBleWeb extends UniversalBlePlatform { Future startScan({ ScanFilter? scanFilter, }) async { + if (scanFilter == null || scanFilter.withServices.isEmpty) { + UniversalBlePlatform.logInfo( + "Service list empty: on web you have to specify services in the ScanFilter in order to be able to access those after connecting", + isError: true, + ); + } + BluetoothDevice device = await FlutterWebBluetooth.instance.requestDevice( scanFilter?.toRequestOptionsBuilder() ?? RequestOptionsBuilder.acceptAllDevices(), diff --git a/pubspec.yaml b/pubspec.yaml index 1e4f2c5..cf81314 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: universal_ble description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter -version: 0.9.4 +version: 0.9.5 homepage: https://navideck.com repository: https://github.com/Navideck/universal_ble issue_tracker: https://github.com/Navideck/universal_ble/issues diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index f78fba8..f01c79e 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -16,7 +16,7 @@ FetchContent_Declare(nuget find_program(NUGET nuget) if(NOT NUGET) - message("Nuget.exe not found, trying to download or use cached version.") + # message("Nuget.exe not found, trying to download or use cached version.") FetchContent_MakeAvailable(nuget) set(NUGET ${nuget_SOURCE_DIR}/nuget.exe) endif()