diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..320e54ff --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.{kt,kts}] +max_line_length=210 +ktlint_standard_property-naming=disabled diff --git a/.github/workflows/ktlint.yml b/.github/workflows/ktlint.yml new file mode 100644 index 00000000..a4d4b347 --- /dev/null +++ b/.github/workflows/ktlint.yml @@ -0,0 +1,17 @@ +name: ktlint +on: [pull_request] +jobs: + ktlint: + name: Check Code Quality + runs-on: ubuntu-latest + + steps: + - name: Clone repo + uses: actions/checkout@master + with: + fetch-depth: 1 + - name: ktlint + uses: ScaCap/action-ktlint@master + with: + github_token: ${{ secrets.github_token }} + reporter: github-pr-review # Change reporter diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..c18dd9aa --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,59 @@ +name: "Build" + +on: + pull_request: + push: + branches: + - master + +jobs: + build: + name: Build + runs-on: macos-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set Up Java + uses: actions/setup-java@v3.12.0 + with: + distribution: 'oracle' + java-version: '19.0.2' + + - name: Set Up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.16.3' + channel: 'stable' + + - name: Set up debug keystore + run: | + rm -f ~/.android/debug.keystore + keytool -genkeypair \ + -alias androiddebugkey \ + -keypass android \ + -keystore ~/.android/debug.keystore \ + -storepass android \ + -dname 'CN=Android Debug,O=Android,C=US' \ + -keyalg 'RSA' \ + -keysize 2048 \ + -validity 10000 + + - name: Quality checks monorepo + run: | + ./bin/quality_checks.sh + + - name: Android native tests + run: | + #!/bin/bash -ex + cd example/android && ls && ./gradlew detekt && ./gradlew testDebugUnitTest + + - name: Build android app + run: | + cd example && flutter build apk --debug + + - name: Build iOS app + run: | + find . -name "Podfile" -execdir pod install \; + cd example && flutter build ios --debug --no-codesign diff --git a/README.md b/README.md index 9799508e..dd3f554f 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ Setup melos to point to the dependencies in your local folder: `melos bootstrap` ### Android -Library requires kotlin version `1.5.31`. +Library requires kotlin version `1.8.21`. ### Update kotlin version -To update the kotlin version open Android studio and go to `Tools > Kotlin > Configure Kotlin plugin updates` and update `Update channel` to `1.5.x`. +To update the kotlin version open Android studio and go to `Tools > Kotlin > Configure Kotlin plugin updates` and update `Update channel` to `1.8.x`. ## Features diff --git a/analysis_options.yaml b/analysis_options.yaml index fa444051..6333ee51 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,9 +1,10 @@ include: package:flutter_lints/flutter.yaml analyzer: - strong-mode: - implicit-casts: false - implicit-dynamic: false + language: + # strict-casts: true -- DISABLED: was introduced in Dart 2.16 + strict-inference: true + strict-raw-types: true exclude: - "bin/cache/**" - "**/*.freezed.dart" @@ -27,8 +28,7 @@ linter: - empty_statements - hash_and_equals - invariant_booleans - - iterable_contains_unrelated_type - - list_remove_unrelated_type + - collection_methods_unrelated_type - literal_only_boolean_expressions - no_adjacent_strings_in_list - no_duplicate_case_values diff --git a/bin/quality_checks.sh b/bin/quality_checks.sh index 25a89370..5c9c7deb 100755 --- a/bin/quality_checks.sh +++ b/bin/quality_checks.sh @@ -1,8 +1,6 @@ #!/bin/bash -ex -#workaround for codemagic CI since melos is not in bash -echo 'export PATH="$PATH":"$FLUTTER_ROOT/.pub-cache/bin"' >>~/.bashrc -echo 'export PATH="$PATH":"$FLUTTER_ROOT/bin"' >>~/.bashrc -source ~/.bashrc +export PATH="$PATH:$FLUTTER_ROOT/.pub-cache/bin" +export PATH="$PATH:$FLUTTER_ROOT/bin" dart pub global activate melos diff --git a/codemagic.yaml b/codemagic.yaml deleted file mode 100644 index 9780b112..00000000 --- a/codemagic.yaml +++ /dev/null @@ -1,58 +0,0 @@ -# Automatically generated on 2021-04-24 UTC from https://codemagic.io/app/60825d341cde02a9c11af464/settings -# Note that this configuration is not an exact match to UI settings. Review and adjust as necessary. - -workflows: - ble-workflow: - name: Ble Workflow - max_build_duration: 60 - instance_type: mac_mini_m1 - environment: - flutter: stable - xcode: 13.3 - cocoapods: default - cache: - cache_paths: [] - triggering: - events: - - pull_request - branch_patterns: - - pattern: master - include: true - source: false - tag_patterns: - - pattern: '*' - include: true - scripts: - - | - # set up debug keystore - rm -f ~/.android/debug.keystore - keytool -genkeypair \ - -alias androiddebugkey \ - -keypass android \ - -keystore ~/.android/debug.keystore \ - -storepass android \ - -dname 'CN=Android Debug,O=Android,C=US' \ - -keyalg 'RSA' \ - -keysize 2048 \ - -validity 10000 - - name: setup local properties - script: | - # set up local properties - echo "flutter.sdk=$HOME/programs/flutter" > "$FCI_BUILD_DIR/example/android/local.properties" - - name: Quality checks monorepo - script: | - ./bin/quality_checks.sh - - name: Android native tests - script: | - #!/bin/bash -ex - cd example/android && ls && ./gradlew detekt && ./gradlew testDebugUnitTest - - name: Build android app - script: cd example && flutter build apk --debug - - name: Build iOS app - script: | - find . -name "Podfile" -execdir pod install \; - cd example && flutter build ios --debug --no-codesign - artifacts: - - example/build/**/outputs/**/*.apk - - example/build/**/outputs/**/mapping.txt - - example/build/ios/ipa/*.ipa diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 0e4d7063..986ee288 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,9 +32,6 @@ android { main.java.srcDirs += 'src/main/kotlin' } - lintOptions { - disable 'InvalidPackage' - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -48,7 +45,7 @@ android { defaultConfig { applicationId "com.signify.hue.reactivebleexample" minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -59,6 +56,11 @@ android { signingConfig signingConfigs.debug } } + namespace 'com.signify.hue.reactivebleexample' + + lint { + disable 'InvalidPackage' + } } flutter { diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 2c78d45c..c9ff4a89 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/example/android/app/src/main/kotlin/com/signify/hue/reactivebleexample/MainActivity.kt b/example/android/app/src/main/kotlin/com/signify/hue/reactivebleexample/MainActivity.kt index 6a6f0e2f..36dfe989 100644 --- a/example/android/app/src/main/kotlin/com/signify/hue/reactivebleexample/MainActivity.kt +++ b/example/android/app/src/main/kotlin/com/signify/hue/reactivebleexample/MainActivity.kt @@ -1,14 +1,14 @@ package com.signify.hue.reactivebleexample - import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugins.GeneratedPluginRegistrant - -class MainActivity: FlutterActivity(){ - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine) - } +class MainActivity : FlutterActivity() { + override fun configureFlutterEngine( + @NonNull flutterEngine: FlutterEngine, + ) { + GeneratedPluginRegistrant.registerWith(flutterEngine) + } } diff --git a/example/android/build.gradle b/example/android/build.gradle index d1fc4db5..0bfccf6a 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.5.31' + ext.kotlin_version = '1.8.21' repositories { mavenCentral() google() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:8.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 53ae0ae4..07577223 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,6 @@ -android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.enableJetifier=false +android.nonFinalResIds=false +android.nonTransitiveRClass=false android.useAndroidX=true org.gradle.jvmargs=-Xmx1536M diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index ffed3a25..8bc9958a 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 5a2f14fb..44e62bcf 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/lib/main.dart b/example/lib/main.dart index 1e55b696..82e028f0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -24,12 +24,12 @@ void main() { logMessage: _bleLogger.addToLog, ); final _serviceDiscoverer = BleDeviceInteractor( - bleDiscoverServices: _ble.discoverServices, - readCharacteristic: _ble.readCharacteristic, - writeWithResponse: _ble.writeCharacteristicWithResponse, - writeWithOutResponse: _ble.writeCharacteristicWithoutResponse, - subscribeToCharacteristic: _ble.subscribeToCharacteristic, + bleDiscoverServices: (deviceId) async { + await _ble.discoverAllServices(deviceId); + return _ble.getDiscoveredServices(deviceId); + }, logMessage: _bleLogger.addToLog, + readRssi: _ble.readRssi, ); runApp( MultiProvider( diff --git a/example/lib/src/ble/ble_device_connector.dart b/example/lib/src/ble/ble_device_connector.dart index 9494149c..536ff8b0 100644 --- a/example/lib/src/ble/ble_device_connector.dart +++ b/example/lib/src/ble/ble_device_connector.dart @@ -6,7 +6,7 @@ import 'package:flutter_reactive_ble_example/src/ble/reactive_state.dart'; class BleDeviceConnector extends ReactiveState { BleDeviceConnector({ required FlutterReactiveBle ble, - required Function(String message) logMessage, + required void Function(String message) logMessage, }) : _ble = ble, _logMessage = logMessage; diff --git a/example/lib/src/ble/ble_device_interactor.dart b/example/lib/src/ble/ble_device_interactor.dart index 3d09b509..5be0a789 100644 --- a/example/lib/src/ble/ble_device_interactor.dart +++ b/example/lib/src/ble/ble_device_interactor.dart @@ -4,107 +4,27 @@ import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; class BleDeviceInteractor { BleDeviceInteractor({ - required Future> Function(String deviceId) - bleDiscoverServices, - required Future> Function(QualifiedCharacteristic characteristic) - readCharacteristic, - required Future Function(QualifiedCharacteristic characteristic, - {required List value}) - writeWithResponse, - required Future Function(QualifiedCharacteristic characteristic, - {required List value}) - writeWithOutResponse, + required Future> Function(String deviceId) bleDiscoverServices, required void Function(String message) logMessage, - required Stream> Function(QualifiedCharacteristic characteristic) - subscribeToCharacteristic, + required this.readRssi, }) : _bleDiscoverServices = bleDiscoverServices, - _readCharacteristic = readCharacteristic, - _writeWithResponse = writeWithResponse, - _writeWithoutResponse = writeWithOutResponse, - _subScribeToCharacteristic = subscribeToCharacteristic, _logMessage = logMessage; - final Future> Function(String deviceId) - _bleDiscoverServices; + final Future> Function(String deviceId) _bleDiscoverServices; - final Future> Function(QualifiedCharacteristic characteristic) - _readCharacteristic; - - final Future Function(QualifiedCharacteristic characteristic, - {required List value}) _writeWithResponse; - - final Future Function(QualifiedCharacteristic characteristic, - {required List value}) _writeWithoutResponse; - - final Stream> Function(QualifiedCharacteristic characteristic) - _subScribeToCharacteristic; + final Future Function(String deviceId) readRssi; final void Function(String message) _logMessage; - Future> discoverServices(String deviceId) async { + Future> discoverServices(String deviceId) async { try { _logMessage('Start discovering services for: $deviceId'); final result = await _bleDiscoverServices(deviceId); _logMessage('Discovering services finished'); return result; } on Exception catch (e) { - _logMessage('Error occured when discovering services: $e'); - rethrow; - } - } - - Future> readCharacteristic( - QualifiedCharacteristic characteristic) async { - try { - final result = await _readCharacteristic(characteristic); - - _logMessage('Read ${characteristic.characteristicId}: value = $result'); - return result; - } on Exception catch (e, s) { - _logMessage( - 'Error occured when reading ${characteristic.characteristicId} : $e', - ); - // ignore: avoid_print - print(s); - rethrow; - } - } - - Future writeCharacterisiticWithResponse( - QualifiedCharacteristic characteristic, List value) async { - try { - _logMessage( - 'Write with response value : $value to ${characteristic.characteristicId}'); - await _writeWithResponse(characteristic, value: value); - } on Exception catch (e, s) { - _logMessage( - 'Error occured when writing ${characteristic.characteristicId} : $e', - ); - // ignore: avoid_print - print(s); + _logMessage('Error occurred when discovering services: $e'); rethrow; } } - - Future writeCharacterisiticWithoutResponse( - QualifiedCharacteristic characteristic, List value) async { - try { - await _writeWithoutResponse(characteristic, value: value); - _logMessage( - 'Write without response value: $value to ${characteristic.characteristicId}'); - } on Exception catch (e, s) { - _logMessage( - 'Error occured when writing ${characteristic.characteristicId} : $e', - ); - // ignore: avoid_print - print(s); - rethrow; - } - } - - Stream> subScribeToCharacteristic( - QualifiedCharacteristic characteristic) { - _logMessage('Subscribing to: ${characteristic.characteristicId} '); - return _subScribeToCharacteristic(characteristic); - } } diff --git a/example/lib/src/ble/ble_scanner.dart b/example/lib/src/ble/ble_scanner.dart index 5efff29b..465e5e64 100644 --- a/example/lib/src/ble/ble_scanner.dart +++ b/example/lib/src/ble/ble_scanner.dart @@ -7,7 +7,7 @@ import 'package:meta/meta.dart'; class BleScanner implements ReactiveState { BleScanner({ required FlutterReactiveBle ble, - required Function(String message) logMessage, + required void Function(String message) logMessage, }) : _ble = ble, _logMessage = logMessage; @@ -59,7 +59,7 @@ class BleScanner implements ReactiveState { await _stateStreamController.close(); } - StreamSubscription? _subscription; + StreamSubscription? _subscription; } @immutable diff --git a/example/lib/src/ui/device_detail/characteristic_interaction_dialog.dart b/example/lib/src/ui/device_detail/characteristic_interaction_dialog.dart index d2a252f5..17f09231 100644 --- a/example/lib/src/ui/device_detail/characteristic_interaction_dialog.dart +++ b/example/lib/src/ui/device_detail/characteristic_interaction_dialog.dart @@ -10,51 +10,27 @@ class CharacteristicInteractionDialog extends StatelessWidget { required this.characteristic, Key? key, }) : super(key: key); - final QualifiedCharacteristic characteristic; + final Characteristic characteristic; @override Widget build(BuildContext context) => Consumer( - builder: (context, interactor, _) => _CharacteristicInteractionDialog( - characteristic: characteristic, - readCharacteristic: interactor.readCharacteristic, - writeWithResponse: interactor.writeCharacterisiticWithResponse, - writeWithoutResponse: - interactor.writeCharacterisiticWithoutResponse, - subscribeToCharacteristic: interactor.subScribeToCharacteristic, - )); + builder: (context, interactor, _) => _CharacteristicInteractionDialog(characteristic: characteristic), + ); } class _CharacteristicInteractionDialog extends StatefulWidget { const _CharacteristicInteractionDialog({ required this.characteristic, - required this.readCharacteristic, - required this.writeWithResponse, - required this.writeWithoutResponse, - required this.subscribeToCharacteristic, Key? key, }) : super(key: key); - final QualifiedCharacteristic characteristic; - final Future> Function(QualifiedCharacteristic characteristic) - readCharacteristic; - final Future Function( - QualifiedCharacteristic characteristic, List value) - writeWithResponse; - - final Stream> Function(QualifiedCharacteristic characteristic) - subscribeToCharacteristic; - - final Future Function( - QualifiedCharacteristic characteristic, List value) - writeWithoutResponse; + final Characteristic characteristic; @override - _CharacteristicInteractionDialogState createState() => - _CharacteristicInteractionDialogState(); + _CharacteristicInteractionDialogState createState() => _CharacteristicInteractionDialogState(); } -class _CharacteristicInteractionDialogState - extends State<_CharacteristicInteractionDialog> { +class _CharacteristicInteractionDialogState extends State<_CharacteristicInteractionDialog> { late String readOutput; late String writeOutput; late String subscribeOutput; @@ -72,13 +48,13 @@ class _CharacteristicInteractionDialogState @override void dispose() { + textEditingController.dispose(); subscribeStream?.cancel(); super.dispose(); } Future subscribeCharacteristic() async { - subscribeStream = - widget.subscribeToCharacteristic(widget.characteristic).listen((event) { + subscribeStream = widget.characteristic.subscribe().listen((event) { setState(() { subscribeOutput = event.toString(); }); @@ -89,28 +65,23 @@ class _CharacteristicInteractionDialogState } Future readCharacteristic() async { - final result = await widget.readCharacteristic(widget.characteristic); + final result = await widget.characteristic.read(); setState(() { readOutput = result.toString(); }); } - List _parseInput() => textEditingController.text - .split(',') - .map( - int.parse, - ) - .toList(); + List _parseInput() => textEditingController.text.split(',').map(int.parse).toList(); Future writeCharacteristicWithResponse() async { - await widget.writeWithResponse(widget.characteristic, _parseInput()); + await widget.characteristic.write(_parseInput()); setState(() { writeOutput = 'Ok'; }); } Future writeCharacteristicWithoutResponse() async { - await widget.writeWithoutResponse(widget.characteristic, _parseInput()); + await widget.characteristic.write(_parseInput(), withResponse: false); setState(() { writeOutput = 'Done'; }); @@ -203,7 +174,7 @@ class _CharacteristicInteractionDialogState Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( - widget.characteristic.characteristicId.toString(), + widget.characteristic.id.toString(), ), ), divider, @@ -218,8 +189,9 @@ class _CharacteristicInteractionDialogState child: Padding( padding: const EdgeInsets.only(top: 20.0), child: ElevatedButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('close')), + onPressed: () => Navigator.of(context).pop(), + child: const Text('close'), + ), ), ) ], diff --git a/example/lib/src/ui/device_detail/device_detail_screen.dart b/example/lib/src/ui/device_detail/device_detail_screen.dart index b5e50369..d92e89d6 100644 --- a/example/lib/src/ui/device_detail/device_detail_screen.dart +++ b/example/lib/src/ui/device_detail/device_detail_screen.dart @@ -30,10 +30,10 @@ class _DeviceDetail extends StatelessWidget { final DiscoveredDevice device; final void Function(String deviceId) disconnect; @override - Widget build(BuildContext context) => WillPopScope( - onWillPop: () async { + Widget build(BuildContext context) => PopScope( + canPop: true, + onPopInvoked: (_) async { disconnect(device.id); - return true; }, child: DefaultTabController( length: 2, diff --git a/example/lib/src/ui/device_detail/device_interaction_tab.dart b/example/lib/src/ui/device_detail/device_interaction_tab.dart index 0fa648a5..02a2fb98 100644 --- a/example/lib/src/ui/device_detail/device_interaction_tab.dart +++ b/example/lib/src/ui/device_detail/device_interaction_tab.dart @@ -8,29 +8,28 @@ import 'package:provider/provider.dart'; import 'characteristic_interaction_dialog.dart'; part 'device_interaction_tab.g.dart'; -//ignore_for_file: annotate_overrides -class DeviceInteractionTab extends StatelessWidget { - final DiscoveredDevice device; +// ignore_for_file: annotate_overrides +class DeviceInteractionTab extends StatelessWidget { const DeviceInteractionTab({ required this.device, Key? key, }) : super(key: key); + final DiscoveredDevice device; + @override - Widget build(BuildContext context) => - Consumer3( - builder: (_, deviceConnector, connectionStateUpdate, serviceDiscoverer, - __) => - _DeviceInteractionTab( + Widget build(BuildContext context) => Consumer3( + builder: (_, deviceConnector, connectionStateUpdate, serviceDiscoverer, __) => _DeviceInteractionTab( viewModel: DeviceInteractionViewModel( - deviceId: device.id, - connectableStatus: device.connectable, - connectionStatus: connectionStateUpdate.connectionState, - deviceConnector: deviceConnector, - discoverServices: () => - serviceDiscoverer.discoverServices(device.id)), + deviceId: device.id, + connectableStatus: device.connectable, + connectionStatus: connectionStateUpdate.connectionState, + deviceConnector: deviceConnector, + discoverServices: () => serviceDiscoverer.discoverServices(device.id), + readRssi: () => serviceDiscoverer.readRssi(device.id), + ), ), ); } @@ -44,17 +43,19 @@ class DeviceInteractionViewModel extends $DeviceInteractionViewModel { required this.connectionStatus, required this.deviceConnector, required this.discoverServices, + required this.readRssi, }); final String deviceId; final Connectable connectableStatus; final DeviceConnectionState connectionStatus; final BleDeviceConnector deviceConnector; + final Future Function() readRssi; + @CustomEquality(Ignore()) - final Future> Function() discoverServices; + final Future> Function() discoverServices; - bool get deviceConnected => - connectionStatus == DeviceConnectionState.connected; + bool get deviceConnected => connectionStatus == DeviceConnectionState.connected; void connect() { deviceConnector.connect(deviceId); @@ -78,7 +79,9 @@ class _DeviceInteractionTab extends StatefulWidget { } class _DeviceInteractionTabState extends State<_DeviceInteractionTab> { - late List discoveredServices; + late List discoveredServices; + + int _rssi = 0; @override void initState() { @@ -93,6 +96,13 @@ class _DeviceInteractionTabState extends State<_DeviceInteractionTab> { }); } + Future readRssi() async { + final rssi = await widget.viewModel.readRssi(); + setState(() { + _rssi = rssi; + }); + } + @override Widget build(BuildContext context) => CustomScrollView( slivers: [ @@ -100,8 +110,7 @@ class _DeviceInteractionTabState extends State<_DeviceInteractionTab> { delegate: SliverChildListDelegate.fixed( [ Padding( - padding: const EdgeInsetsDirectional.only( - top: 8.0, bottom: 16.0, start: 16.0), + padding: const EdgeInsetsDirectional.only(top: 8.0, bottom: 16.0, start: 16.0), child: Text( "ID: ${widget.viewModel.deviceId}", style: const TextStyle(fontWeight: FontWeight.bold), @@ -121,28 +130,35 @@ class _DeviceInteractionTabState extends State<_DeviceInteractionTab> { style: const TextStyle(fontWeight: FontWeight.bold), ), ), + Padding( + padding: const EdgeInsetsDirectional.only(start: 16.0), + child: Text( + "Rssi: $_rssi dB", + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), Padding( padding: const EdgeInsets.only(top: 16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + child: Wrap( + alignment: WrapAlignment.spaceEvenly, children: [ ElevatedButton( - onPressed: !widget.viewModel.deviceConnected - ? widget.viewModel.connect - : null, + onPressed: !widget.viewModel.deviceConnected ? widget.viewModel.connect : null, child: const Text("Connect"), ), ElevatedButton( - onPressed: widget.viewModel.deviceConnected - ? widget.viewModel.disconnect - : null, + onPressed: widget.viewModel.deviceConnected ? widget.viewModel.disconnect : null, child: const Text("Disconnect"), ), + ElevatedButton( + onPressed: widget.viewModel.deviceConnected ? discoverServices : null, + child: const Text("Discover Services"), + ), ElevatedButton( onPressed: widget.viewModel.deviceConnected - ? discoverServices + ? readRssi : null, - child: const Text("Discover Services"), + child: const Text("Get RSSI"), ), ], ), @@ -167,7 +183,7 @@ class _ServiceDiscoveryList extends StatefulWidget { }) : super(key: key); final String deviceId; - final List discoveredServices; + final List discoveredServices; @override _ServiceDiscoveryListState createState() => _ServiceDiscoveryListState(); @@ -182,7 +198,7 @@ class _ServiceDiscoveryListState extends State<_ServiceDiscoveryList> { super.initState(); } - String _charactisticsSummary(DiscoveredCharacteristic c) { + String _characteristicSummary(Characteristic c) { final props = []; if (c.isReadable) { props.add("read"); @@ -203,19 +219,13 @@ class _ServiceDiscoveryListState extends State<_ServiceDiscoveryList> { return props.join("\n"); } - Widget _characteristicTile( - DiscoveredCharacteristic characteristic, String deviceId) => - ListTile( + Widget _characteristicTile(Characteristic characteristic) => ListTile( onTap: () => showDialog( - context: context, - builder: (context) => CharacteristicInteractionDialog( - characteristic: QualifiedCharacteristic( - characteristicId: characteristic.characteristicId, - serviceId: characteristic.serviceId, - deviceId: deviceId), - )), + context: context, + builder: (context) => CharacteristicInteractionDialog(characteristic: characteristic), + ), title: Text( - '${characteristic.characteristicId}\n(${_charactisticsSummary(characteristic)})', + '${characteristic.id}\n(${_characteristicSummary(characteristic)})', style: const TextStyle( fontSize: 14, ), @@ -241,19 +251,15 @@ class _ServiceDiscoveryListState extends State<_ServiceDiscoveryList> { ), ), ), - ListView.builder( - shrinkWrap: true, - itemBuilder: (context, index) => _characteristicTile( - service.characteristics[index], - widget.deviceId, - ), - itemCount: service.characteristicIds.length, + Column( + mainAxisSize: MainAxisSize.min, + children: service.characteristics.map(_characteristicTile).toList(), ), ], ), headerBuilder: (context, isExpanded) => ListTile( title: Text( - '${service.serviceId}', + '${service.id}', style: const TextStyle(fontSize: 14), ), ), @@ -268,15 +274,16 @@ class _ServiceDiscoveryListState extends State<_ServiceDiscoveryList> { @override Widget build(BuildContext context) => widget.discoveredServices.isEmpty ? const SizedBox() - : Padding( - padding: const EdgeInsetsDirectional.only( - top: 20.0, - start: 20.0, - end: 20.0, - ), - child: ExpansionPanelList( - expansionCallback: (int index, bool isExpanded) { - setState(() { + : SafeArea( + top: false, + child: Padding( + padding: const EdgeInsetsDirectional.only( + top: 20.0, + start: 20.0, + end: 20.0, + ), + child: ExpansionPanelList( + expansionCallback: (int index, bool isExpanded) { setState(() { if (isExpanded) { _expandedItems.remove(index); @@ -284,11 +291,9 @@ class _ServiceDiscoveryListState extends State<_ServiceDiscoveryList> { _expandedItems.add(index); } }); - }); - }, - children: [ - ...buildPanels(), - ], + }, + children: buildPanels(), + ), ), ); } diff --git a/example/lib/src/ui/device_detail/device_interaction_tab.g.dart b/example/lib/src/ui/device_detail/device_interaction_tab.g.dart index 4a87f0c4..b4f78b7c 100644 --- a/example/lib/src/ui/device_detail/device_interaction_tab.g.dart +++ b/example/lib/src/ui/device_detail/device_interaction_tab.g.dart @@ -13,20 +13,23 @@ abstract class $DeviceInteractionViewModel { Connectable get connectableStatus; DeviceConnectionState get connectionStatus; BleDeviceConnector get deviceConnector; - Future> Function() get discoverServices; + Future Function() get readRssi; + Future> Function() get discoverServices; DeviceInteractionViewModel copyWith({ String? deviceId, Connectable? connectableStatus, DeviceConnectionState? connectionStatus, BleDeviceConnector? deviceConnector, - Future> Function()? discoverServices, + Future Function()? readRssi, + Future> Function()? discoverServices, }) => DeviceInteractionViewModel( deviceId: deviceId ?? this.deviceId, connectableStatus: connectableStatus ?? this.connectableStatus, connectionStatus: connectionStatus ?? this.connectionStatus, deviceConnector: deviceConnector ?? this.deviceConnector, + readRssi: readRssi ?? this.readRssi, discoverServices: discoverServices ?? this.discoverServices, ); @@ -37,6 +40,7 @@ abstract class $DeviceInteractionViewModel { this.connectableStatus, this.connectionStatus, this.deviceConnector, + this.readRssi, this.discoverServices, ); mutator(change); @@ -45,13 +49,14 @@ abstract class $DeviceInteractionViewModel { connectableStatus: change.connectableStatus, connectionStatus: change.connectionStatus, deviceConnector: change.deviceConnector, + readRssi: change.readRssi, discoverServices: change.discoverServices, ); } @override String toString() => - "DeviceInteractionViewModel(deviceId: $deviceId, connectableStatus: $connectableStatus, connectionStatus: $connectionStatus, deviceConnector: $deviceConnector, discoverServices: $discoverServices)"; + "DeviceInteractionViewModel(deviceId: $deviceId, connectableStatus: $connectableStatus, connectionStatus: $connectionStatus, deviceConnector: $deviceConnector, readRssi: $readRssi, discoverServices: $discoverServices)"; @override // ignore: avoid_equals_and_hash_code_on_mutable_classes @@ -62,6 +67,7 @@ abstract class $DeviceInteractionViewModel { connectableStatus == other.connectableStatus && connectionStatus == other.connectionStatus && deviceConnector == other.deviceConnector && + readRssi == other.readRssi && const Ignore().equals(discoverServices, other.discoverServices); @override @@ -72,6 +78,7 @@ abstract class $DeviceInteractionViewModel { result = 37 * result + connectableStatus.hashCode; result = 37 * result + connectionStatus.hashCode; result = 37 * result + deviceConnector.hashCode; + result = 37 * result + readRssi.hashCode; result = 37 * result + const Ignore().hash(discoverServices); return result; } @@ -83,6 +90,7 @@ class DeviceInteractionViewModel$Change { this.connectableStatus, this.connectionStatus, this.deviceConnector, + this.readRssi, this.discoverServices, ); @@ -90,7 +98,8 @@ class DeviceInteractionViewModel$Change { Connectable connectableStatus; DeviceConnectionState connectionStatus; BleDeviceConnector deviceConnector; - Future> Function() discoverServices; + Future Function() readRssi; + Future> Function() discoverServices; } // ignore: avoid_classes_with_only_static_members @@ -124,8 +133,15 @@ class DeviceInteractionViewModel$ { deviceConnectorContainer.copyWith(deviceConnector: deviceConnector), ); - static final discoverServices = Lens> Function()>( + static final readRssi = + Lens Function()>( + (readRssiContainer) => readRssiContainer.readRssi, + (readRssiContainer, readRssi) => + readRssiContainer.copyWith(readRssi: readRssi), + ); + + static final discoverServices = + Lens> Function()>( (discoverServicesContainer) => discoverServicesContainer.discoverServices, (discoverServicesContainer, discoverServices) => discoverServicesContainer.copyWith(discoverServices: discoverServices), diff --git a/example/pubspec.lock b/example/pubspec.lock index 9c3c21b7..19487965 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -61,34 +61,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.10" + version: "7.3.0" built_collection: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.9.2" characters: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.10.0" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: transitive description: @@ -165,18 +165,18 @@ packages: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" dependency_validator: dependency: "direct dev" description: name: dependency_validator - sha256: "08349175533ed0bd06eb9b6043cde66c45b2bfc7ebc222a7542cdb1324f1bf03" + sha256: f727a5627aa405965fab4aef4f468e50a9b632ba0737fd2f98c932fec6d712b9 url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.3" fake_async: dependency: transitive description: @@ -207,7 +207,7 @@ packages: source: sdk version: "0.0.0" flutter_lints: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_lints sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 @@ -220,7 +220,7 @@ packages: path: "../packages/flutter_reactive_ble" relative: true source: path - version: "5.1.1" + version: "5.3.1" flutter_test: dependency: "direct dev" description: flutter @@ -230,10 +230,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" functional_data: dependency: "direct main" description: @@ -302,10 +302,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -314,6 +314,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + 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: @@ -334,34 +358,34 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" nested: dependency: transitive description: @@ -382,18 +406,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pool: dependency: transitive description: @@ -414,10 +438,10 @@ packages: dependency: "direct main" description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.2" pub_semver: dependency: transitive description: @@ -440,14 +464,14 @@ packages: path: "../packages/reactive_ble_mobile" relative: true source: path - version: "5.1.1" + version: "5.3.1" reactive_ble_platform_interface: dependency: "direct overridden" description: path: "../packages/reactive_ble_platform_interface" relative: true source: path - version: "5.1.1" + version: "5.3.1" shelf: dependency: transitive description: @@ -473,34 +497,34 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.5.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -529,10 +553,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" timing: dependency: transitive description: @@ -557,6 +581,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -565,14 +597,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" yaml: dependency: transitive description: @@ -582,5 +622,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" - flutter: ">=1.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=2.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 71c109ad..1b1e9a29 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,17 +1,16 @@ name: flutter_reactive_ble_example description: Demonstrates how to use the flutter_reactive_ble plugin. -version: 5.1.1 +version: 5.3.1 publish_to: 'none' environment: sdk: '>=2.17.0 <3.0.0' - flutter: ">=1.10.0" + flutter: ">=2.0.0" dependencies: flutter: sdk: flutter - flutter_lints: ^1.0.4 - flutter_reactive_ble: ^5.1.1 + flutter_reactive_ble: ^5.3.1 functional_data: ^1.0.0 intl: ^0.17.0 @@ -20,9 +19,18 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 dependency_validator: ^3.1.0 + flutter_lints: ^1.0.4 flutter_test: sdk: flutter functional_data_generator: ^1.1.2 +dependency_overrides: + flutter_reactive_ble: + path: ../packages/flutter_reactive_ble + reactive_ble_mobile: + path: ../packages/reactive_ble_mobile + reactive_ble_platform_interface: + path: ../packages/reactive_ble_platform_interface + flutter: uses-material-design: true diff --git a/melos.yaml b/melos.yaml index dcc622ef..efff1b40 100644 --- a/melos.yaml +++ b/melos.yaml @@ -9,6 +9,8 @@ scripts: get: melos exec -- flutter pub get + upgrade: melos exec -- flutter packages upgrade + unittest: run: melos exec -- flutter test diff --git a/packages/flutter_reactive_ble/CHANGELOG.md b/packages/flutter_reactive_ble/CHANGELOG.md index 190808e2..1d9b3bc0 100644 --- a/packages/flutter_reactive_ble/CHANGELOG.md +++ b/packages/flutter_reactive_ble/CHANGELOG.md @@ -1,3 +1,27 @@ +## 5.3.1 + +* Use proper platform_interface dependency version #837 + +## 5.3.0 + +* Readd accidentally removed version constraint #789 +* Add a placeholder implementation for non-mobile platforms #688 +* Add Github actions and Migrate to latest Android SDK, AGP and protobuf plugin #830 +* Include packages lock-files #797 +* Update Kotlin version in README #831 +* Migrate away from deprecated strong mode analysis options #832 +* Read RSSI #796 + +## 5.2.0 + +* Bump the minimum requirement to Dart 2.17 and upgrade melos to 3.1.0 in #762 +* swiftlint config and inital formatting pass in #765 +* Cancel subscription when a disconnect event has been thrown in #769 +* Fix typos in #778 +* Update CI config to use Xcode 14 in #786 +* Support multiple services or characteristics with the same id in #776 +* Breaking change: If a device has multiple characteristics with the same ID, `readCharacteristic`, `writeCharacteristic` and `subscribeToCharacteristic` used to select the first of those characteristics. Now they will fail in this case. Use `resolve` or `getDiscoveredServices` instead. + ## 5.1.1 * Make Connectable backwards compatible #757, #750 diff --git a/packages/flutter_reactive_ble/lib/flutter_reactive_ble.dart b/packages/flutter_reactive_ble/lib/flutter_reactive_ble.dart index a1214cf6..4f834ac9 100644 --- a/packages/flutter_reactive_ble/lib/flutter_reactive_ble.dart +++ b/packages/flutter_reactive_ble/lib/flutter_reactive_ble.dart @@ -1,6 +1,6 @@ library flutter_reactive_ble; -export 'package:reactive_ble_platform_interface/reactive_ble_platform_interface.dart'; +export 'package:reactive_ble_platform_interface/reactive_ble_platform_interface.dart' hide CharacteristicInstance; export 'src/reactive_ble.dart'; export 'src/rx_ext/repeater.dart'; diff --git a/packages/flutter_reactive_ble/lib/src/connected_device_operation.dart b/packages/flutter_reactive_ble/lib/src/connected_device_operation.dart index ed171e3a..da007bd7 100644 --- a/packages/flutter_reactive_ble/lib/src/connected_device_operation.dart +++ b/packages/flutter_reactive_ble/lib/src/connected_device_operation.dart @@ -1,23 +1,24 @@ import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'package:meta/meta.dart'; +import 'package:reactive_ble_platform_interface/reactive_ble_platform_interface.dart'; abstract class ConnectedDeviceOperation { Stream get characteristicValueStream; - Future> readCharacteristic(QualifiedCharacteristic characteristic); + Future> readCharacteristic(CharacteristicInstance characteristic); Future writeCharacteristicWithResponse( - QualifiedCharacteristic characteristic, { + CharacteristicInstance characteristic, { required List value, }); Future writeCharacteristicWithoutResponse( - QualifiedCharacteristic characteristic, { + CharacteristicInstance characteristic, { required List value, }); Stream> subscribeToCharacteristic( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, Future isDisconnected, ); @@ -25,6 +26,8 @@ abstract class ConnectedDeviceOperation { Future> discoverServices(String deviceId); + Future> getDiscoverServices(String deviceId); + Future requestConnectionPriority( String deviceId, ConnectionPriority priority); } @@ -40,7 +43,7 @@ class ConnectedDeviceOperationImpl implements ConnectedDeviceOperation { _blePlatform.charValueUpdateStream; @override - Future> readCharacteristic(QualifiedCharacteristic characteristic) { + Future> readCharacteristic(CharacteristicInstance characteristic) { final specificCharacteristicValueStream = characteristicValueStream .where((update) => update.characteristic == characteristic) .map((update) => update.result.dematerialize()); @@ -54,7 +57,7 @@ class ConnectedDeviceOperationImpl implements ConnectedDeviceOperation { @override Future writeCharacteristicWithResponse( - QualifiedCharacteristic characteristic, { + CharacteristicInstance characteristic, { required List value, }) async => _blePlatform @@ -63,7 +66,7 @@ class ConnectedDeviceOperationImpl implements ConnectedDeviceOperation { @override Future writeCharacteristicWithoutResponse( - QualifiedCharacteristic characteristic, { + CharacteristicInstance characteristic, { required List value, }) async => _blePlatform @@ -72,7 +75,7 @@ class ConnectedDeviceOperationImpl implements ConnectedDeviceOperation { @override Stream> subscribeToCharacteristic( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, Future isDisconnected, ) { final specificCharacteristicValueStream = characteristicValueStream @@ -103,6 +106,10 @@ class ConnectedDeviceOperationImpl implements ConnectedDeviceOperation { Future> discoverServices(String deviceId) => _blePlatform.discoverServices(deviceId); + @override + Future> getDiscoverServices(String deviceId) => + _blePlatform.getDiscoverServices(deviceId); + @override Future requestConnectionPriority( String deviceId, ConnectionPriority priority) async => diff --git a/packages/flutter_reactive_ble/lib/src/reactive_ble.dart b/packages/flutter_reactive_ble/lib/src/reactive_ble.dart index 31572fa7..d15c869d 100644 --- a/packages/flutter_reactive_ble/lib/src/reactive_ble.dart +++ b/packages/flutter_reactive_ble/lib/src/reactive_ble.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:collection'; import 'dart:io'; import 'package:flutter_reactive_ble/src/connected_device_operation.dart'; @@ -18,7 +19,7 @@ class FlutterReactiveBle { factory FlutterReactiveBle() => _sharedInstance; - ///Create a new instance where injected depedencies are used. + ///Create a new instance where injected dependencies are used. @visibleForTesting FlutterReactiveBle.witDependencies({ required DeviceScanner deviceScanner, @@ -59,8 +60,7 @@ class FlutterReactiveBle { BleStatus get status => _status; /// A stream providing connection updates for all the connected BLE devices. - Stream get connectedDeviceStream => - Repeater(onListenEmitFrom: () async* { + Stream get connectedDeviceStream => Repeater(onListenEmitFrom: () async* { await initialize(); yield* _deviceConnector.deviceConnectionStateUpdateStream; }).stream.asBroadcastStream() @@ -104,10 +104,12 @@ class FlutterReactiveBle { print, ); - ReactiveBlePlatform.instance = - const ReactiveBleMobilePlatformFactory().create( - logger: _debugLogger, - ); + if (Platform.isAndroid || Platform.isIOS) { + ReactiveBlePlatform.instance = + const ReactiveBleMobilePlatformFactory().create( + logger: _debugLogger, + ); + } _blePlatform = ReactiveBlePlatform.instance; @@ -143,6 +145,8 @@ class FlutterReactiveBle { Future deinitialize() async { if (_initialization != null) { _initialization = null; + await _disconnectionUpdates?.cancel(); + _disconnectionUpdates = null; await _blePlatform.deinitialize(); } } @@ -154,24 +158,28 @@ class FlutterReactiveBle { /// Be aware that a read request could be satisfied by a notification delivered /// for the same characteristic via [characteristicValueStream] before the actual /// read response arrives (due to the design of iOS BLE API). - Future> readCharacteristic( - QualifiedCharacteristic characteristic) async { + /// + /// This method assumes there is a single characteristic with the ids specified in [characteristic]. If there are + /// multiple characteristics with the same id on a device, use [resolve] to find them all. Or use + /// [getDiscoveredServices] to select the [Service]s and [Characteristic]s you're interested in. + Future> readCharacteristic(QualifiedCharacteristic characteristic) async { await initialize(); - return _connectedDeviceOperator.readCharacteristic(characteristic); + return (await resolveSingle(characteristic)).read(); } /// Writes a value to the specified characteristic awaiting for an acknowledgement. /// /// The returned future completes with an error in case of a failure during writing. + /// + /// This method assumes there is a single characteristic with the ids specified in [characteristic]. If there are + /// multiple characteristics with the same id on a device, use [resolve] to find them all. Or use + /// [getDiscoveredServices] to select the [Service]s and [Characteristic]s you're interested in. Future writeCharacteristicWithResponse( QualifiedCharacteristic characteristic, { required List value, }) async { await initialize(); - return _connectedDeviceOperator.writeCharacteristicWithResponse( - characteristic, - value: value, - ); + await (await resolveSingle(characteristic)).write(value, withResponse: true); } /// Writes a value to the specified characteristic without waiting for an acknowledgement. @@ -182,15 +190,16 @@ class FlutterReactiveBle { /// the BLE device is still responsive. /// /// The returned future completes with an error in case of a failure during writing. + /// + /// This method assumes there is a single characteristic with the ids specified in [characteristic]. If there are + /// multiple characteristics with the same id on a device, use [resolve] to find them all. Or use + /// [getDiscoveredServices] to select the [Service]s and [Characteristic]s you're interested in. Future writeCharacteristicWithoutResponse( QualifiedCharacteristic characteristic, { required List value, }) async { await initialize(); - return _connectedDeviceOperator.writeCharacteristicWithoutResponse( - characteristic, - value: value, - ); + await (await resolveSingle(characteristic)).write(value, withResponse: false); } /// Request a specific MTU for a connected device. @@ -209,12 +218,10 @@ class FlutterReactiveBle { /// Requests for a connection parameter update on the connected device. /// /// Always completes with an error on iOS, as there is no way (and no need) to perform this operation on iOS. - Future requestConnectionPriority( - {required String deviceId, required ConnectionPriority priority}) async { + Future requestConnectionPriority({required String deviceId, required ConnectionPriority priority}) async { await initialize(); - return _connectedDeviceOperator.requestConnectionPriority( - deviceId, priority); + return _connectedDeviceOperator.requestConnectionPriority(deviceId, priority); } Future launchCompanionWorkflow({ @@ -265,13 +272,15 @@ class FlutterReactiveBle { /// Disconnecting the device is achieved by cancelling the stream subscription. /// /// [id] is the unique device id of the BLE device: in iOS this is a uuid and on Android this is - /// a Mac-Adress. + /// a Mac-Address. /// Use [servicesWithCharacteristicsToDiscover] to scan only for the specific services mentioned in this map, /// this can improve the connection speed on iOS since no full service discovery will be executed. On Android /// this variable is ignored since partial discovery is not possible. /// If [connectionTimeout] parameter is supplied and a connection is not established before [connectionTimeout] expires, /// the pending connection attempt will be cancelled and a [TimeoutException] error will be emitted into the returned stream. - /// On Android when no timeout is specified the `autoConnect` flag is set in the [connectGatt()](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)) call, otherwise it is cleared. + /// On Android when no timeout is specified the `autoConnect` flag is set in the + /// [connectGatt()](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)) + /// call, otherwise it is cleared. Stream connectToDevice({ required String id, Map>? servicesWithCharacteristicsToDiscover, @@ -280,8 +289,7 @@ class FlutterReactiveBle { initialize().asStream().asyncExpand( (_) => _deviceConnector.connect( id: id, - servicesWithCharacteristicsToDiscover: - servicesWithCharacteristicsToDiscover, + servicesWithCharacteristicsToDiscover: servicesWithCharacteristicsToDiscover, connectionTimeout: connectionTimeout, ), ); @@ -304,13 +312,15 @@ class FlutterReactiveBle { /// /// Disconnecting the device is achieved by cancelling the stream subscription. /// - /// The [prescanDuration] is the amount of time BLE disovery should run in order to find the device. + /// The [prescanDuration] is the amount of time BLE discovery should run in order to find the device. /// Use [servicesWithCharacteristicsToDiscover] to scan only for the specific services mentioned in this map, /// this can improve the connection speed on iOS since no full service discovery will be executed. On Android /// this variable is ignored since partial discovery is not possible. /// If [connectionTimeout] parameter is supplied and a connection is not established before [connectionTimeout] expires, /// the pending connection attempt will be cancelled and a [TimeoutException] error will be emitted into the returned stream. - /// On Android when no timeout is specified the `autoConnect` flag is set in the [connectGatt()](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)) call, otherwise it is cleared. + /// On Android when no timeout is specified the `autoConnect` flag is set in the + /// [connectGatt()](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)) + /// call, otherwise it is cleared. Stream connectToAdvertisingDevice({ required String id, required List withServices, @@ -323,8 +333,7 @@ class FlutterReactiveBle { id: id, withServices: withServices, prescanDuration: prescanDuration, - servicesWithCharacteristicsToDiscover: - servicesWithCharacteristicsToDiscover, + servicesWithCharacteristicsToDiscover: servicesWithCharacteristicsToDiscover, connectionTimeout: connectionTimeout, ), ); @@ -332,45 +341,295 @@ class FlutterReactiveBle { /// Performs service discovery on the peripheral and returns the discovered services. /// /// When discovery fails this method throws an [Exception]. + @Deprecated("Use `discoverAllServices` and `getDiscoverServices`") Future> discoverServices(String deviceId) => _connectedDeviceOperator.discoverServices(deviceId); + /// Performs service discovery on the peripheral. + /// + /// When discovery fails this method throws an [Exception]. + /// + /// Use [getDiscoveredServices] to get the discovered services + Future discoverAllServices(String deviceId) => _connectedDeviceOperator.discoverServices(deviceId); + + /// Services can be discovered by: + /// - specify `servicesWithCharacteristicsToDiscover` in [connectToDevice] or [connectToAdvertisingDevice]. Or, + /// - by calling [discoverAllServices] + /// + /// Discovered services and charactersitcs remain valid for as long as the device stays connected. After reconnecting + /// to a device, [getDiscoveredServices] must be called again to get updated services and characteristics. + /// + /// Note: On Android, this method performs service discovery if one was done yet after connecting the device. + Future> getDiscoveredServices(String deviceId) async { + _disconnectionUpdates ??= connectedDeviceStream + .where((update) => update.connectionState == DeviceConnectionState.disconnected) + .listen((update) { + _services[update.deviceId]?.forEach((service) => service._markInvalid()); + _services[update.deviceId]?.clear(); + }); + + final discoveredServices = await _connectedDeviceOperator.getDiscoverServices(deviceId); + + final services = _services[deviceId] ?? []; + + for (final discoveredService in discoveredServices) { + final service = services.firstWhere( + (service) => _isMatchingService(service, discoveredService), + orElse: () { + final newService = Service._( + id: discoveredService.serviceId, + instanceId: discoveredService.serviceInstanceId, + deviceId: deviceId, + ); + services.add(newService); + return newService; + }, + ); + + for (final discoveredCharacteristic in discoveredService.characteristics) { + if (!service._characteristics.any((char) => _isMatchingCharacteristic(char, discoveredCharacteristic))) { + service._characteristics.add(Characteristic._( + id: discoveredCharacteristic.characteristicId, + instanceId: discoveredCharacteristic.characteristicInstanceId, + service: service, + lib: this, + isReadable: discoveredCharacteristic.isReadable, + isWritableWithoutResponse: discoveredCharacteristic.isWritableWithoutResponse, + isWritableWithResponse: discoveredCharacteristic.isWritableWithResponse, + isNotifiable: discoveredCharacteristic.isNotifiable, + isIndicatable: discoveredCharacteristic.isIndicatable, + )); + } + } + service._characteristics.removeWhere((char) => !discoveredService.characteristics.any( + (discoveredCharacteristic) => _isMatchingCharacteristic(char, discoveredCharacteristic), + )); + } + services.removeWhere( + (service) => !discoveredServices.any((discoveredService) => _isMatchingService(service, discoveredService)), + ); + + return UnmodifiableListView(services); + } + + StreamSubscription? _disconnectionUpdates; + + bool _isMatchingService(Service service, DiscoveredService discoveredService) => + service.id == discoveredService.serviceId && service._instanceId == discoveredService.serviceInstanceId; + + bool _isMatchingCharacteristic(Characteristic char, DiscoveredCharacteristic discoveredCharacteristic) => + char.id == discoveredCharacteristic.characteristicId && + char._instanceId == discoveredCharacteristic.characteristicInstanceId; + + final _services = >{}; + /// Clears GATT attribute cache on Android using undocumented API. Completes with an error in case of a failure. /// /// Always completes with an error on iOS, as there is no way (and no need) to perform this operation on iOS. /// /// The connection may need to be reestablished after successful GATT attribute cache clearing. - Future clearGattCache(String deviceId) => _blePlatform - .clearGattCache(deviceId) - .then((info) => info.dematerialize()); + Future clearGattCache(String deviceId) => + _blePlatform.clearGattCache(deviceId).then((info) => info.dematerialize()); + + /// Reads the RSSI of the of the peripheral with the given device ID. + /// The peripheral must be connected, otherwise a [PlatformException] will be + /// thrown + Future readRssi(String deviceId) async => + _blePlatform.readRssi(deviceId); + + /// Subscribes to updates from the characteristic specified. + /// + /// This stream terminates automatically when the device is disconnected. + /// + /// This method assumes there is a single characteristic with the ids specified in [characteristic]. If there are + /// multiple characteristics with the same id on a device, use [resolve] to find them all. Or use + /// [getDiscoveredServices] to select the [Service]s and [Characteristic]s you're interested in. + Stream> subscribeToCharacteristic(QualifiedCharacteristic characteristic) async* { + yield* (await resolveSingle(characteristic)).subscribe(); + } + + Future> resolve(QualifiedCharacteristic characteristic) async { + final services = await getDiscoveredServices(characteristic.deviceId); + return services + .withId(characteristic.serviceId) + .expand((service) => service.characteristics.withId(characteristic.characteristicId)); + } + + Future resolveSingle(QualifiedCharacteristic characteristic) async { + final chars = await resolve(characteristic); + if (chars.isEmpty) throw Exception("Characteristic not found or discovered: $characteristic"); + if (chars.length > 1) throw Exception("Multiple matching characteristics found: $characteristic"); + return chars.single; + } + + /// Sets the verbosity of debug output. + /// + /// Use [LogLevel.verbose] for full debug output. Make sure to run this only for debugging purposes. + /// Use [LogLevel.none] to disable logging. This is also the default. + set logLevel(LogLevel logLevel) => _debugLogger.logLevel = logLevel; + + LogLevel get logLevel => _debugLogger.logLevel; +} + +/// An instance of this object should not be used after its device has lost its connection. +class Service { + Service._({ + required this.id, + required String instanceId, + required this.deviceId, + }) : _instanceId = instanceId; + + final Uuid id; + + // Not exposed as it may be different each time a device is connected to, so it should not be used to identify + // services. Instead, services have to be discovered after connecting and looked up via + // [FlutterReactiveBle.getDiscoverServices] + final String _instanceId; + + final String deviceId; + + /// Discovered characteristics + List get characteristics => UnmodifiableListView(_characteristics); + + final List _characteristics = []; + + // A Service becomes invalid when its device gets disconnected. After reconnecting to the device, services have to be + // rediscovered + void _markInvalid() { + for (final characteristic in _characteristics) { + characteristic._markInvalid(); + } + } + + @override + String toString() => "Service($id)"; +} + +/// An instance of this object should not be used after its device has lost its connection. +class Characteristic { + Characteristic._({ + required this.id, + required String instanceId, + required this.service, + required FlutterReactiveBle lib, + required this.isReadable, + required this.isWritableWithoutResponse, + required this.isWritableWithResponse, + required this.isNotifiable, + required this.isIndicatable, + }) : _instanceId = instanceId, + _lib = lib; + + final Uuid id; + + /// The service containing this characteristic + final Service service; + + // Not exposed as it may be different each time a device is connected to, so it should not be used to identify + // characteristics. Instead, characteristics have to be discovered after connecting and looked up via + // [FlutterReactiveBle.getDiscoverServices] + final String _instanceId; + + final bool isReadable; + final bool isWritableWithoutResponse; + final bool isWritableWithResponse; + final bool isNotifiable; + final bool isIndicatable; + + /// Reads the value of the specified characteristic. + /// + /// The returned future completes with an error in case of a failure during reading. + /// + /// Be aware that a read request could be satisfied by a notification delivered + /// for the same characteristic via [FlutterReactiveBle.characteristicValueStream] before the actual + /// read response arrives (due to the design of iOS BLE API). + Future> read() { + _assertValidity(); + return _lib._connectedDeviceOperator.readCharacteristic(_ids); + } + + /// Writes a value to the specified characteristic. + /// + /// When [withResponse] is false, writing is done without waiting for an acknowledgement. + /// Use this in case client does not need an acknowledgement + /// that the write was successfully performed. For consequitive write operations it is + /// recommended to execute a write with [withResponse] true each n times to make sure + /// the BLE device is still responsive. + /// + /// The returned future completes with an error in case of a failure during writing. + Future write(List value, {bool withResponse = true}) async { + _assertValidity(); + + if (withResponse) { + await _lib._connectedDeviceOperator.writeCharacteristicWithResponse(_ids, value: value); + } else { + await _lib._connectedDeviceOperator.writeCharacteristicWithoutResponse(_ids, value: value); + } + } /// Subscribes to updates from the characteristic specified. /// /// This stream terminates automatically when the device is disconnected. - Stream> subscribeToCharacteristic( - QualifiedCharacteristic characteristic, - ) { - final isDisconnected = connectedDeviceStream + Stream> subscribe() { + _assertValidity(); + + final isDisconnected = _lib.connectedDeviceStream .where((update) => - update.deviceId == characteristic.deviceId && + update.deviceId == service.deviceId && (update.connectionState == DeviceConnectionState.disconnecting || update.connectionState == DeviceConnectionState.disconnected)) .cast() .firstWhere((_) => true, orElse: () {}); - return initialize().asStream().asyncExpand( - (_) => _connectedDeviceOperator.subscribeToCharacteristic( - characteristic, + return _lib.initialize().asStream().asyncExpand( + (_) => _lib._connectedDeviceOperator.subscribeToCharacteristic( + CharacteristicInstance( + characteristicId: id, + characteristicInstanceId: _instanceId, + serviceId: service.id, + serviceInstanceId: service._instanceId, + deviceId: service.deviceId, + ), isDisconnected, ), ); } - /// Sets the verbosity of debug output. - /// - /// Use [LogLevel.verbose] for full debug output. Make sure to run this only for debugging purposes. - /// Use [LogLevel.none] to disable logging. This is also the default. - set logLevel(LogLevel logLevel) => _debugLogger.logLevel = logLevel; + // A Characteristic becomes invalid when its device gets disconnected. After reconnecting to the device, + // services and characteristics have to be rediscovered + bool _valid = true; - LogLevel get logLevel => _debugLogger.logLevel; + void _markInvalid() { + _valid = false; + } + + void _assertValidity() { + if (!_valid) { + throw Exception( + "Characteristic no longer valid. Characteristics lose their validity after a device gets disconnected. " + "Rediscover services and characteristics after reconnecting to the device.", + ); + } + } + + final FlutterReactiveBle _lib; + + CharacteristicInstance get _ids => CharacteristicInstance( + characteristicId: id, + characteristicInstanceId: _instanceId, + serviceId: service.id, + serviceInstanceId: service._instanceId, + deviceId: service.deviceId, + ); + + @override + String toString() => "Characteristic($id; $_instanceId; ${service._instanceId})"; +} + +extension ServiceWithId on Iterable { + Iterable withId(Uuid id) => where((s) => s.id.expanded == id.expanded); +} + +extension CharacteristicWithId on Iterable { + Iterable withId(Uuid id) => where((c) => c.id.expanded == id.expanded); } diff --git a/packages/flutter_reactive_ble/lib/src/rx_ext/serial_disposable.dart b/packages/flutter_reactive_ble/lib/src/rx_ext/serial_disposable.dart index 18e3b862..39381eb8 100644 --- a/packages/flutter_reactive_ble/lib/src/rx_ext/serial_disposable.dart +++ b/packages/flutter_reactive_ble/lib/src/rx_ext/serial_disposable.dart @@ -40,11 +40,11 @@ class _SerialAlreadyDisposed extends Error { String toString() => "An instance of $_type has already been disposed"; } -/// A [SerialDisposable] that constains an underlying stream subscription. -class StreamSubscriptionSerialDisposable - extends SerialDisposable { +/// A [SerialDisposable] that contains an underlying stream subscription. +class StreamSubscriptionSerialDisposable + extends SerialDisposable> { StreamSubscriptionSerialDisposable() - : super((StreamSubscription subscription) async { + : super((StreamSubscription subscription) async { await subscription.cancel(); return const Unit(); }); diff --git a/packages/flutter_reactive_ble/pubspec.lock b/packages/flutter_reactive_ble/pubspec.lock index 0c0ed6a7..30dbafc6 100644 --- a/packages/flutter_reactive_ble/pubspec.lock +++ b/packages/flutter_reactive_ble/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -61,34 +61,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.10" + version: "7.3.0" built_collection: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.9.2" characters: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.10.0" collection: dependency: "direct main" description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" fake_async: dependency: transitive description: @@ -215,10 +215,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" functional_data: dependency: "direct main" description: @@ -279,10 +279,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -291,6 +291,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + 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: @@ -311,42 +335,42 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" mockito: dependency: "direct dev" description: name: mockito - sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" url: "https://pub.dev" source: hosted - version: "5.4.2" + version: "5.4.4" package_config: dependency: transitive description: @@ -359,18 +383,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pool: dependency: transitive description: @@ -409,14 +433,14 @@ packages: path: "../reactive_ble_mobile" relative: true source: path - version: "5.1.1" + version: "5.3.1" reactive_ble_platform_interface: dependency: "direct main" description: path: "../reactive_ble_platform_interface" relative: true source: path - version: "5.1.1" + version: "5.3.1" shelf: dependency: transitive description: @@ -442,34 +466,34 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.5.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -498,10 +522,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" timing: dependency: transitive description: @@ -526,6 +550,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -534,14 +566,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" yaml: dependency: transitive description: @@ -551,5 +591,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=2.0.0" diff --git a/packages/flutter_reactive_ble/pubspec.yaml b/packages/flutter_reactive_ble/pubspec.yaml index bbeb1388..8e44d537 100644 --- a/packages/flutter_reactive_ble/pubspec.yaml +++ b/packages/flutter_reactive_ble/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_reactive_ble description: Reactive Bluetooth Low Energy (BLE) plugin that can communicate with multiple devices -version: 5.1.1 +version: 5.3.1 homepage: https://github.com/PhilipsHue/flutter_reactive_ble environment: @@ -21,8 +21,15 @@ dependencies: sdk: flutter functional_data: ^1.0.0 meta: ^1.3.0 - reactive_ble_mobile: ^5.1.1 - reactive_ble_platform_interface: ^5.1.1 + reactive_ble_mobile: ^5.3.1 + reactive_ble_platform_interface: ^5.3.1 + +dependency_overrides: + reactive_ble_mobile: + path: ../reactive_ble_mobile + reactive_ble_platform_interface: + path: ../reactive_ble_platform_interface + dev_dependencies: build_runner: ^2.3.3 flutter_lints: ^1.0.4 diff --git a/packages/flutter_reactive_ble/test/connected_device_operation_test.dart b/packages/flutter_reactive_ble/test/connected_device_operation_test.dart index 4cccdbf1..4320c915 100644 --- a/packages/flutter_reactive_ble/test/connected_device_operation_test.dart +++ b/packages/flutter_reactive_ble/test/connected_device_operation_test.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'package:flutter_reactive_ble/src/connected_device_operation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; @@ -26,9 +25,11 @@ void main() { setUp(() { valueUpdate = CharacteristicValue( - characteristic: QualifiedCharacteristic( + characteristic: CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ), result: const Result.success([1]), @@ -47,30 +48,36 @@ void main() { }); group('Read characteristic', () { - late QualifiedCharacteristic charDevice; - QualifiedCharacteristic charOtherSameDevice; - QualifiedCharacteristic charOtherDevice; + late CharacteristicInstance charDevice; + CharacteristicInstance charOtherSameDevice; + CharacteristicInstance charOtherDevice; CharacteristicValue? valueUpdate; CharacteristicValue? valueUpdateOtherDevice; CharacteristicValue? valueUpdateSameDeviceOtherChar; List? result; setUp(() { - charDevice = QualifiedCharacteristic( + charDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); - charOtherSameDevice = QualifiedCharacteristic( + charOtherSameDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FAFF'), + serviceInstanceId: "101", deviceId: '123', ); - charOtherDevice = QualifiedCharacteristic( + charOtherDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '456', ); @@ -132,14 +139,16 @@ void main() { }); group('Write characteristic', () { - late QualifiedCharacteristic characteristic; + late CharacteristicInstance characteristic; WriteCharacteristicInfo info; const value = [1, 0]; setUp(() { - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); }); @@ -246,9 +255,9 @@ void main() { }); group('Subscribe to characteristic', () { - late QualifiedCharacteristic charDevice; - QualifiedCharacteristic charOtherSameDevice; - QualifiedCharacteristic charOtherDevice; + late CharacteristicInstance charDevice; + CharacteristicInstance charOtherSameDevice; + CharacteristicInstance charOtherDevice; late CharacteristicValue valueUpdate1; late CharacteristicValue valueUpdate2; late CharacteristicValue valueUpdateOtherDevice; @@ -259,21 +268,27 @@ void main() { setUp(() { terminateCompleter = Completer(); - charDevice = QualifiedCharacteristic( + charDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); - charOtherSameDevice = QualifiedCharacteristic( + charOtherSameDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FAFF'), + serviceInstanceId: "101", deviceId: '123', ); - charOtherDevice = QualifiedCharacteristic( + charOtherDevice = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '456', ); diff --git a/packages/flutter_reactive_ble/test/connected_device_operation_test.mocks.dart b/packages/flutter_reactive_ble/test/connected_device_operation_test.mocks.dart index a3362f4a..0fbe78ff 100644 --- a/packages/flutter_reactive_ble/test/connected_device_operation_test.mocks.dart +++ b/packages/flutter_reactive_ble/test/connected_device_operation_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in flutter_reactive_ble/test/connected_device_operation_test.dart. // Do not manually edit this file. @@ -14,6 +14,8 @@ import 'package:reactive_ble_platform_interface/src/reactive_ble_platform_interf // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -68,23 +70,27 @@ class MockReactiveBlePlatform extends _i1.Mock Invocation.getter(#scanStream), returnValue: _i4.Stream<_i2.ScanResult>.empty(), ) as _i4.Stream<_i2.ScanResult>); + @override _i4.Stream<_i2.BleStatus> get bleStatusStream => (super.noSuchMethod( Invocation.getter(#bleStatusStream), returnValue: _i4.Stream<_i2.BleStatus>.empty(), ) as _i4.Stream<_i2.BleStatus>); + @override _i4.Stream<_i2.ConnectionStateUpdate> get connectionUpdateStream => (super.noSuchMethod( Invocation.getter(#connectionUpdateStream), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Stream<_i2.CharacteristicValue> get charValueUpdateStream => (super.noSuchMethod( Invocation.getter(#charValueUpdateStream), returnValue: _i4.Stream<_i2.CharacteristicValue>.empty(), ) as _i4.Stream<_i2.CharacteristicValue>); + @override _i4.Future initialize() => (super.noSuchMethod( Invocation.method( @@ -94,6 +100,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future deinitialize() => (super.noSuchMethod( Invocation.method( @@ -103,6 +110,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future<_i2.DeviceAssociationInfo?> launchCompanionWorkflow({ required String? pattern, @@ -121,6 +129,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream scanForDevices({ required List<_i2.Uuid>? withServices, @@ -139,6 +148,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>> clearGattCache(String? deviceId) => (super.noSuchMethod( @@ -158,8 +168,9 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future< - _i2.Result<_i2.Unit, - _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + _i2 + .Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + @override _i4.Future<_i2.BondingStatus> establishBonding(String? deviceId) => (super.noSuchMethod( @@ -170,6 +181,16 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future<_i2.BondingStatus>.value(_i2.BondingStatus.none), ) as _i4.Future<_i2.BondingStatus>); + + @override + _i4.Future readRssi(String? deviceId) => (super.noSuchMethod( + Invocation.method( + #readRssi, + [deviceId], + ), + returnValue: _i4.Future.value(0), + ) as _i4.Future); + @override _i4.Stream connectToDevice( String? id, @@ -187,6 +208,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future retrieveDeviceName(String? id) => (super.noSuchMethod( Invocation.method( @@ -195,6 +217,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future disconnectDevice(String? deviceId) => (super.noSuchMethod( Invocation.method( @@ -204,6 +227,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future> discoverServices(String? deviceId) => (super.noSuchMethod( @@ -214,9 +238,22 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future>.value( <_i2.DiscoveredService>[]), ) as _i4.Future>); + + @override + _i4.Future> getDiscoverServices( + String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #getDiscoverServices, + [deviceId], + ), + returnValue: _i4.Future>.value( + <_i2.DiscoveredService>[]), + ) as _i4.Future>); + @override _i4.Stream readCharacteristic( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #readCharacteristic, @@ -224,9 +261,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -249,9 +287,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithoutResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -274,9 +313,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Stream subscribeToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #subscribeToNotifications, @@ -284,9 +324,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future stopSubscribingToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #stopSubscribingToNotifications, @@ -295,6 +336,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future requestMtuSize( String? deviceId, @@ -310,6 +352,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future<_i2.ConnectionPriorityInfo> requestConnectionPriority( String? deviceId, diff --git a/packages/flutter_reactive_ble/test/device_connector_test.mocks.dart b/packages/flutter_reactive_ble/test/device_connector_test.mocks.dart index 48710408..186f62df 100644 --- a/packages/flutter_reactive_ble/test/device_connector_test.mocks.dart +++ b/packages/flutter_reactive_ble/test/device_connector_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in flutter_reactive_ble/test/device_connector_test.dart. // Do not manually edit this file. @@ -16,6 +16,8 @@ import 'package:reactive_ble_platform_interface/src/models.dart' as _i2; // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -80,23 +82,27 @@ class MockReactiveBlePlatform extends _i1.Mock Invocation.getter(#scanStream), returnValue: _i4.Stream<_i2.ScanResult>.empty(), ) as _i4.Stream<_i2.ScanResult>); + @override _i4.Stream<_i2.BleStatus> get bleStatusStream => (super.noSuchMethod( Invocation.getter(#bleStatusStream), returnValue: _i4.Stream<_i2.BleStatus>.empty(), ) as _i4.Stream<_i2.BleStatus>); + @override _i4.Stream<_i2.ConnectionStateUpdate> get connectionUpdateStream => (super.noSuchMethod( Invocation.getter(#connectionUpdateStream), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Stream<_i2.CharacteristicValue> get charValueUpdateStream => (super.noSuchMethod( Invocation.getter(#charValueUpdateStream), returnValue: _i4.Stream<_i2.CharacteristicValue>.empty(), ) as _i4.Stream<_i2.CharacteristicValue>); + @override _i4.Future initialize() => (super.noSuchMethod( Invocation.method( @@ -106,6 +112,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future deinitialize() => (super.noSuchMethod( Invocation.method( @@ -115,6 +122,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future<_i2.DeviceAssociationInfo?> launchCompanionWorkflow({ required String? pattern, @@ -133,6 +141,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream scanForDevices({ required List<_i2.Uuid>? withServices, @@ -151,6 +160,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>> clearGattCache(String? deviceId) => (super.noSuchMethod( @@ -170,8 +180,9 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future< - _i2.Result<_i2.Unit, - _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + _i2 + .Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + @override _i4.Future<_i2.BondingStatus> establishBonding(String? deviceId) => (super.noSuchMethod( @@ -182,6 +193,16 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future<_i2.BondingStatus>.value(_i2.BondingStatus.none), ) as _i4.Future<_i2.BondingStatus>); + + @override + _i4.Future readRssi(String? deviceId) => (super.noSuchMethod( + Invocation.method( + #readRssi, + [deviceId], + ), + returnValue: _i4.Future.value(0), + ) as _i4.Future); + @override _i4.Stream connectToDevice( String? id, @@ -199,6 +220,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future retrieveDeviceName(String? id) => (super.noSuchMethod( Invocation.method( @@ -207,6 +229,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future disconnectDevice(String? deviceId) => (super.noSuchMethod( Invocation.method( @@ -216,6 +239,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future> discoverServices(String? deviceId) => (super.noSuchMethod( @@ -226,9 +250,22 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future>.value( <_i2.DiscoveredService>[]), ) as _i4.Future>); + + @override + _i4.Future> getDiscoverServices( + String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #getDiscoverServices, + [deviceId], + ), + returnValue: _i4.Future>.value( + <_i2.DiscoveredService>[]), + ) as _i4.Future>); + @override _i4.Stream readCharacteristic( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #readCharacteristic, @@ -236,9 +273,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -261,9 +299,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithoutResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -286,9 +325,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Stream subscribeToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #subscribeToNotifications, @@ -296,9 +336,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future stopSubscribingToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #stopSubscribingToNotifications, @@ -307,6 +348,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future requestMtuSize( String? deviceId, @@ -322,6 +364,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future<_i2.ConnectionPriorityInfo> requestConnectionPriority( String? deviceId, @@ -375,6 +418,7 @@ class MockDeviceScanner extends _i1.Mock implements _i5.DeviceScanner { ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream<_i2.DiscoveredDevice> scanForDevices({ required List<_i2.Uuid>? withServices, @@ -412,6 +456,7 @@ class MockDiscoveredDevicesRegistry extends _i1.Mock Invocation.getter(#getTimestamp), ), ) as DateTime Function()); + @override void add(String? deviceId) => super.noSuchMethod( Invocation.method( @@ -420,6 +465,7 @@ class MockDiscoveredDevicesRegistry extends _i1.Mock ), returnValueForMissingStub: null, ); + @override void remove(String? deviceId) => super.noSuchMethod( Invocation.method( @@ -428,6 +474,7 @@ class MockDiscoveredDevicesRegistry extends _i1.Mock ), returnValueForMissingStub: null, ); + @override bool isEmpty() => (super.noSuchMethod( Invocation.method( @@ -436,6 +483,7 @@ class MockDiscoveredDevicesRegistry extends _i1.Mock ), returnValue: false, ) as bool); + @override bool deviceIsDiscoveredRecently({ required String? deviceId, diff --git a/packages/flutter_reactive_ble/test/device_scanner_test.mocks.dart b/packages/flutter_reactive_ble/test/device_scanner_test.mocks.dart index 11e8e1a2..b71afbfd 100644 --- a/packages/flutter_reactive_ble/test/device_scanner_test.mocks.dart +++ b/packages/flutter_reactive_ble/test/device_scanner_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in flutter_reactive_ble/test/device_scanner_test.dart. // Do not manually edit this file. @@ -14,6 +14,8 @@ import 'package:reactive_ble_platform_interface/src/reactive_ble_platform_interf // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -68,23 +70,27 @@ class MockReactiveBlePlatform extends _i1.Mock Invocation.getter(#scanStream), returnValue: _i4.Stream<_i2.ScanResult>.empty(), ) as _i4.Stream<_i2.ScanResult>); + @override _i4.Stream<_i2.BleStatus> get bleStatusStream => (super.noSuchMethod( Invocation.getter(#bleStatusStream), returnValue: _i4.Stream<_i2.BleStatus>.empty(), ) as _i4.Stream<_i2.BleStatus>); + @override _i4.Stream<_i2.ConnectionStateUpdate> get connectionUpdateStream => (super.noSuchMethod( Invocation.getter(#connectionUpdateStream), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Stream<_i2.CharacteristicValue> get charValueUpdateStream => (super.noSuchMethod( Invocation.getter(#charValueUpdateStream), returnValue: _i4.Stream<_i2.CharacteristicValue>.empty(), ) as _i4.Stream<_i2.CharacteristicValue>); + @override _i4.Future initialize() => (super.noSuchMethod( Invocation.method( @@ -94,6 +100,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future deinitialize() => (super.noSuchMethod( Invocation.method( @@ -103,6 +110,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future<_i2.DeviceAssociationInfo?> launchCompanionWorkflow({ required String? pattern, @@ -121,6 +129,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream scanForDevices({ required List<_i2.Uuid>? withServices, @@ -139,6 +148,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>> clearGattCache(String? deviceId) => (super.noSuchMethod( @@ -158,8 +168,9 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future< - _i2.Result<_i2.Unit, - _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + _i2 + .Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + @override _i4.Future<_i2.BondingStatus> establishBonding(String? deviceId) => (super.noSuchMethod( @@ -170,6 +181,16 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future<_i2.BondingStatus>.value(_i2.BondingStatus.none), ) as _i4.Future<_i2.BondingStatus>); + + @override + _i4.Future readRssi(String? deviceId) => (super.noSuchMethod( + Invocation.method( + #readRssi, + [deviceId], + ), + returnValue: _i4.Future.value(0), + ) as _i4.Future); + @override _i4.Stream connectToDevice( String? id, @@ -187,6 +208,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future retrieveDeviceName(String? id) => (super.noSuchMethod( Invocation.method( @@ -195,6 +217,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future disconnectDevice(String? deviceId) => (super.noSuchMethod( Invocation.method( @@ -204,6 +227,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future> discoverServices(String? deviceId) => (super.noSuchMethod( @@ -214,9 +238,22 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future>.value( <_i2.DiscoveredService>[]), ) as _i4.Future>); + + @override + _i4.Future> getDiscoverServices( + String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #getDiscoverServices, + [deviceId], + ), + returnValue: _i4.Future>.value( + <_i2.DiscoveredService>[]), + ) as _i4.Future>); + @override _i4.Stream readCharacteristic( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #readCharacteristic, @@ -224,9 +261,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -249,9 +287,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithoutResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -274,9 +313,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Stream subscribeToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #subscribeToNotifications, @@ -284,9 +324,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future stopSubscribingToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #stopSubscribingToNotifications, @@ -295,6 +336,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future requestMtuSize( String? deviceId, @@ -310,6 +352,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future<_i2.ConnectionPriorityInfo> requestConnectionPriority( String? deviceId, diff --git a/packages/flutter_reactive_ble/test/reactive_ble_test.dart b/packages/flutter_reactive_ble/test/reactive_ble_test.dart index a791a118..1f65fee5 100644 --- a/packages/flutter_reactive_ble/test/reactive_ble_test.dart +++ b/packages/flutter_reactive_ble/test/reactive_ble_test.dart @@ -8,6 +8,7 @@ import 'package:flutter_reactive_ble/src/device_scanner.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:reactive_ble_platform_interface/reactive_ble_platform_interface.dart'; import 'reactive_ble_test.mocks.dart'; @@ -47,8 +48,8 @@ void main() { (_) => Future.value(), ); - when(_blePlatform.bleStatusStream).thenAnswer( - (realInvocation) => _bleStatusController.stream.asBroadcastStream()); + when(_blePlatform.bleStatusStream) + .thenAnswer((realInvocation) => _bleStatusController.stream.asBroadcastStream()); _sut = FlutterReactiveBle.witDependencies( reactiveBlePlatform: _blePlatform, @@ -97,17 +98,21 @@ void main() { }); group('CharacteristicValueStream', () { - const characteristic = Result, - GenericFailure>.success( + const characteristic = Result, GenericFailure>.success( [1], ); - final charValue = CharacteristicValue( - characteristic: _createChar(), result: characteristic); + final characteristicInstance = CharacteristicInstance( + deviceId: "1", + characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", + serviceId: Uuid.parse('F0FF'), + serviceInstanceId: "101", + ); + final charValue = CharacteristicValue(characteristic: characteristicInstance, result: characteristic); Stream? charValueStream; setUp(() { - when(_deviceOperation.characteristicValueStream) - .thenAnswer((_) => Stream.fromIterable([charValue])); + when(_deviceOperation.characteristicValueStream).thenAnswer((_) => Stream.fromIterable([charValue])); charValueStream = _sut.characteristicValueStream; }); @@ -124,26 +129,65 @@ void main() { group('Deinitialize', () { setUp(() async { when(_blePlatform.deinitialize()).thenAnswer((_) async => 1); - await _sut.deinitialize(); }); - test('It executes deinitialize succesfull', () { - expect(true, true); + test('It executes deinitialize successful', () async { + await _sut.deinitialize(); }); }); group('Read characteristic', () { - QualifiedCharacteristic characteristic; + late QualifiedCharacteristic characteristic; List? result; setUp(() async { characteristic = _createChar(); - when(_deviceOperation.readCharacteristic(any)) - .thenAnswer((_) async => [1]); + when(_deviceOperation.getDiscoverServices(characteristic.deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + characteristicIds: [characteristic.characteristicId], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("1234"), + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + DiscoveredCharacteristic( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ) + ]); + when(_deviceOperation.readCharacteristic(any)).thenAnswer((_) async => [1]); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => const Stream.empty()); result = await _sut.readCharacteristic(characteristic); }); + test("It reads the correct characteristic", () { + verify(_deviceOperation.readCharacteristic(CharacteristicInstance( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + deviceId: characteristic.deviceId, + ))).called(1); + }); + test('It returns correct value', () { expect(result, [1]); }); @@ -151,7 +195,7 @@ void main() { group('Write characteristic with response', () { const value = [2]; - QualifiedCharacteristic characteristic; + late QualifiedCharacteristic characteristic; setUp(() async { characteristic = _createChar(); @@ -160,19 +204,58 @@ void main() { any, value: anyNamed('value'), )).thenAnswer((_) async => [0]); - - await _sut.writeCharacteristicWithResponse(characteristic, - value: value); + when(_deviceOperation.getDiscoverServices(characteristic.deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + characteristicIds: [characteristic.characteristicId], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("1234"), + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + DiscoveredCharacteristic( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ) + ]); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => const Stream.empty()); + + await _sut.writeCharacteristicWithResponse(characteristic, value: value); }); - test('It completes operation without errors', () { - expect(true, true); + test("It write to the correct characteristic", () { + verify(_deviceOperation.writeCharacteristicWithResponse( + CharacteristicInstance( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + deviceId: characteristic.deviceId, + ), + value: [2], + )).called(1); }); }); group('Write characteristic without response', () { const value = [2]; - QualifiedCharacteristic characteristic; + late QualifiedCharacteristic characteristic; setUp(() async { characteristic = _createChar(); @@ -181,6 +264,37 @@ void main() { any, value: anyNamed('value'), )).thenAnswer((_) async => [0]); + when(_deviceOperation.getDiscoverServices(characteristic.deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + characteristicIds: [characteristic.characteristicId], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("1234"), + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + DiscoveredCharacteristic( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ) + ]); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => const Stream.empty()); await _sut.writeCharacteristicWithoutResponse( characteristic, @@ -188,8 +302,17 @@ void main() { ); }); - test('It completes operation without errors', () { - expect(true, true); + test("It write to the correct characteristic", () { + verify(_deviceOperation.writeCharacteristicWithoutResponse( + CharacteristicInstance( + characteristicId: characteristic.characteristicId, + characteristicInstanceId: "101", + serviceId: characteristic.serviceId, + serviceInstanceId: "11", + deviceId: characteristic.deviceId, + ), + value: [2], + )).called(1); }); }); @@ -199,8 +322,7 @@ void main() { int? result; setUp(() async { - when(_deviceOperation.requestMtu(any, any)) - .thenAnswer((_) async => mtu); + when(_deviceOperation.requestMtu(any, any)).thenAnswer((_) async => mtu); result = await _sut.requestMtu(deviceId: deviceId, mtu: mtu); }); @@ -215,10 +337,8 @@ void main() { const priority = ConnectionPriority.highPerformance; setUp(() async { - when(_deviceOperation.requestConnectionPriority(any, any)) - .thenAnswer((_) async => 0); - await _sut.requestConnectionPriority( - deviceId: deviceId, priority: priority); + when(_deviceOperation.requestConnectionPriority(any, any)).thenAnswer((_) async => 0); + await _sut.requestConnectionPriority(deviceId: deviceId, priority: priority); }); test('It completes operation without errors', () { @@ -246,8 +366,7 @@ void main() { when(_deviceScanner.scanForDevices( withServices: anyNamed('withServices'), scanMode: anyNamed('scanMode'), - requireLocationServicesEnabled: - anyNamed('requireLocationServicesEnabled'), + requireLocationServicesEnabled: anyNamed('requireLocationServicesEnabled'), )).thenAnswer((_) => Stream.fromIterable([device])); deviceStream = _sut.scanForDevices( @@ -284,8 +403,7 @@ void main() { setUp(() { when(_deviceConnector.connect( id: anyNamed('id'), - servicesWithCharacteristicsToDiscover: - anyNamed('servicesWithCharacteristicsToDiscover'), + servicesWithCharacteristicsToDiscover: anyNamed('servicesWithCharacteristicsToDiscover'), connectionTimeout: anyNamed('connectionTimeout'))) .thenAnswer((realInvocation) => Stream.fromIterable([update])); @@ -325,8 +443,7 @@ void main() { setUp(() { when(_deviceConnector.connectToAdvertisingDevice( id: anyNamed('id'), - servicesWithCharacteristicsToDiscover: - anyNamed('servicesWithCharacteristicsToDiscover'), + servicesWithCharacteristicsToDiscover: anyNamed('servicesWithCharacteristicsToDiscover'), connectionTimeout: anyNamed('connectionTimeout'), prescanDuration: anyNamed('prescanDuration'), withServices: anyNamed('withServices'), @@ -359,8 +476,7 @@ void main() { ); setUp(() async { - when(_blePlatform.clearGattCache('123')) - .thenAnswer((_) async => result); + when(_blePlatform.clearGattCache('123')).thenAnswer((_) async => result); await _sut.clearGattCache(deviceId); }); @@ -370,6 +486,14 @@ void main() { }); }); + test('Read RSSI', () async { + const deviceId = '123'; + + when(_blePlatform.readRssi(deviceId)).thenAnswer((_) async => -42); + + expect(await _sut.readRssi(deviceId), -42); + }); + group('ConnecteddeviceStream stream', () { const update = ConnectionStateUpdate( deviceId: '123', @@ -410,16 +534,44 @@ void main() { setUp(() { char = _createChar(); - when(_deviceConnector.deviceConnectionStateUpdateStream) - .thenAnswer((_) => Stream.fromIterable([update])); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => Stream.fromIterable([update])); + when(_deviceOperation.getDiscoverServices(char.deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: char.serviceId, + serviceInstanceId: "11", + characteristicIds: [char.characteristicId], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("1234"), + characteristicInstanceId: "101", + serviceId: char.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + DiscoveredCharacteristic( + characteristicId: char.characteristicId, + characteristicInstanceId: "101", + serviceId: char.serviceId, + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ) + ]); valueStream = Stream.fromIterable([ [1], [2] ]); - when(_deviceOperation.subscribeToCharacteristic(any, any)) - .thenAnswer((_) => valueStream); + when(_deviceOperation.subscribeToCharacteristic(any, any)).thenAnswer((_) => valueStream); resultStream = _sut.subscribeToCharacteristic(char); }); @@ -444,15 +596,174 @@ void main() { const result = []; setUp(() { - when(_deviceOperation.discoverServices(any)) - .thenAnswer((_) async => result); + when(_deviceOperation.discoverServices(any)).thenAnswer((_) async => result); }); test('It returns result', () async { + // ignore: deprecated_member_use_from_same_package expect(await _sut.discoverServices(deviceId), []); }); }); }); + + group('Discover all services', () { + const deviceId = '123'; + + group('When operation is successful', () { + const result = []; + + setUp(() { + when(_deviceOperation.discoverServices(any)).thenAnswer((_) async => result); + }); + + test('It succeeds', () async { + await _sut.discoverAllServices(deviceId); + verify(_deviceOperation.discoverServices(deviceId)).called(1); + }); + }); + }); + + group("getDiscoveredServices", () { + const deviceId = "123"; + + group("multiple characteristics with same id in single service", () { + setUp(() { + when(_deviceOperation.getDiscoverServices(deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "11", + characteristicIds: [Uuid.parse("aa01")], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + DiscoveredCharacteristic( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "102", + serviceId: Uuid.parse("ff01"), + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ) + ]); + when(_deviceOperation.readCharacteristic(any)).thenAnswer((_) async => [42]); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => const Stream.empty()); + }); + + test("reading first instance of characteristic", () async { + final services = await _sut.getDiscoveredServices("123"); + + expect(await services.single.characteristics.first.read(), [42]); + + verify(_deviceOperation.readCharacteristic(CharacteristicInstance( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "11", + deviceId: "123", + ))); + }); + + test("reading second instance of characteristic", () async { + final services = await _sut.getDiscoveredServices("123"); + + expect(await services.single.characteristics[1].read(), [42]); + + verify(_deviceOperation.readCharacteristic(CharacteristicInstance( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "102", + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "11", + deviceId: "123", + ))); + }); + }); + + group("multiple characteristics with same id in different service", () { + setUp(() { + when(_deviceOperation.getDiscoverServices(deviceId)).thenAnswer((_) async => [ + DiscoveredService( + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "11", + characteristicIds: [Uuid.parse("aa01")], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ), + DiscoveredService( + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "12", + characteristicIds: [Uuid.parse("aa01")], + includedServices: [], + characteristics: [ + DiscoveredCharacteristic( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + isReadable: true, + isWritableWithResponse: true, + isWritableWithoutResponse: true, + isNotifiable: true, + isIndicatable: true, + ), + ], + ), + ]); + when(_deviceConnector.deviceConnectionStateUpdateStream).thenAnswer((_) => const Stream.empty()); + when(_deviceOperation.readCharacteristic(any)).thenAnswer((_) async => [42]); + }); + + test("reading first instance of characteristic", () async { + final services = await _sut.getDiscoveredServices("123"); + + expect(await services.first.characteristics.single.read(), [42]); + + verify(_deviceOperation.readCharacteristic(CharacteristicInstance( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "11", + deviceId: "123", + ))); + }); + + test("reading second instance of characteristic", () async { + final services = await _sut.getDiscoveredServices("123"); + + expect(await services[1].characteristics.single.read(), [42]); + + verify(_deviceOperation.readCharacteristic(CharacteristicInstance( + characteristicId: Uuid.parse("aa01"), + characteristicInstanceId: "101", + serviceId: Uuid.parse("ff01"), + serviceInstanceId: "12", + deviceId: "123", + ))); + }); + }); + }); }); } diff --git a/packages/flutter_reactive_ble/test/reactive_ble_test.mocks.dart b/packages/flutter_reactive_ble/test/reactive_ble_test.mocks.dart index 2db8c78a..b864842d 100644 --- a/packages/flutter_reactive_ble/test/reactive_ble_test.mocks.dart +++ b/packages/flutter_reactive_ble/test/reactive_ble_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in flutter_reactive_ble/test/reactive_ble_test.dart. // Do not manually edit this file. @@ -17,6 +17,8 @@ import 'package:reactive_ble_platform_interface/src/models.dart' as _i2; // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -71,23 +73,27 @@ class MockReactiveBlePlatform extends _i1.Mock Invocation.getter(#scanStream), returnValue: _i4.Stream<_i2.ScanResult>.empty(), ) as _i4.Stream<_i2.ScanResult>); + @override _i4.Stream<_i2.BleStatus> get bleStatusStream => (super.noSuchMethod( Invocation.getter(#bleStatusStream), returnValue: _i4.Stream<_i2.BleStatus>.empty(), ) as _i4.Stream<_i2.BleStatus>); + @override _i4.Stream<_i2.ConnectionStateUpdate> get connectionUpdateStream => (super.noSuchMethod( Invocation.getter(#connectionUpdateStream), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Stream<_i2.CharacteristicValue> get charValueUpdateStream => (super.noSuchMethod( Invocation.getter(#charValueUpdateStream), returnValue: _i4.Stream<_i2.CharacteristicValue>.empty(), ) as _i4.Stream<_i2.CharacteristicValue>); + @override _i4.Future initialize() => (super.noSuchMethod( Invocation.method( @@ -97,6 +103,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future deinitialize() => (super.noSuchMethod( Invocation.method( @@ -106,6 +113,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future<_i2.DeviceAssociationInfo?> launchCompanionWorkflow({ required String? pattern, @@ -124,6 +132,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream scanForDevices({ required List<_i2.Uuid>? withServices, @@ -142,6 +151,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>> clearGattCache(String? deviceId) => (super.noSuchMethod( @@ -161,8 +171,9 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future< - _i2.Result<_i2.Unit, - _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + _i2 + .Result<_i2.Unit, _i2.GenericFailure<_i2.ClearGattCacheError>?>>); + @override _i4.Future<_i2.BondingStatus> establishBonding(String? deviceId) => (super.noSuchMethod( @@ -173,6 +184,16 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future<_i2.BondingStatus>.value(_i2.BondingStatus.none), ) as _i4.Future<_i2.BondingStatus>); + + @override + _i4.Future readRssi(String? deviceId) => (super.noSuchMethod( + Invocation.method( + #readRssi, + [deviceId], + ), + returnValue: _i4.Future.value(0), + ) as _i4.Future); + @override _i4.Stream connectToDevice( String? id, @@ -190,6 +211,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future retrieveDeviceName(String? id) => (super.noSuchMethod( Invocation.method( @@ -198,6 +220,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future disconnectDevice(String? deviceId) => (super.noSuchMethod( Invocation.method( @@ -207,6 +230,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future> discoverServices(String? deviceId) => (super.noSuchMethod( @@ -217,9 +241,22 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future>.value( <_i2.DiscoveredService>[]), ) as _i4.Future>); + + @override + _i4.Future> getDiscoverServices( + String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #getDiscoverServices, + [deviceId], + ), + returnValue: _i4.Future>.value( + <_i2.DiscoveredService>[]), + ) as _i4.Future>); + @override _i4.Stream readCharacteristic( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #readCharacteristic, @@ -227,9 +264,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -252,9 +290,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Future<_i2.WriteCharacteristicInfo> writeCharacteristicWithoutResponse( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -277,9 +316,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), )), ) as _i4.Future<_i2.WriteCharacteristicInfo>); + @override _i4.Stream subscribeToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #subscribeToNotifications, @@ -287,9 +327,10 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Stream.empty(), ) as _i4.Stream); + @override _i4.Future stopSubscribingToNotifications( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #stopSubscribingToNotifications, @@ -298,6 +339,7 @@ class MockReactiveBlePlatform extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future requestMtuSize( String? deviceId, @@ -313,6 +355,7 @@ class MockReactiveBlePlatform extends _i1.Mock ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future<_i2.ConnectionPriorityInfo> requestConnectionPriority( String? deviceId, @@ -356,11 +399,13 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override _i2.LogLevel get logLevel => (super.noSuchMethod( Invocation.getter(#logLevel), returnValue: _i2.LogLevel.none, ) as _i2.LogLevel); + @override void log(Object? message) => super.noSuchMethod( Invocation.method( @@ -386,9 +431,10 @@ class MockConnectedDeviceOperation extends _i1.Mock Invocation.getter(#characteristicValueStream), returnValue: _i4.Stream<_i2.CharacteristicValue>.empty(), ) as _i4.Stream<_i2.CharacteristicValue>); + @override _i4.Future> readCharacteristic( - _i2.QualifiedCharacteristic? characteristic) => + _i2.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #readCharacteristic, @@ -396,9 +442,10 @@ class MockConnectedDeviceOperation extends _i1.Mock ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); + @override _i4.Future writeCharacteristicWithResponse( - _i2.QualifiedCharacteristic? characteristic, { + _i2.CharacteristicInstance? characteristic, { required List? value, }) => (super.noSuchMethod( @@ -410,9 +457,10 @@ class MockConnectedDeviceOperation extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future writeCharacteristicWithoutResponse( - _i2.QualifiedCharacteristic? characteristic, { + _i2.CharacteristicInstance? characteristic, { required List? value, }) => (super.noSuchMethod( @@ -424,9 +472,10 @@ class MockConnectedDeviceOperation extends _i1.Mock returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Stream> subscribeToCharacteristic( - _i2.QualifiedCharacteristic? characteristic, + _i2.CharacteristicInstance? characteristic, _i4.Future? isDisconnected, ) => (super.noSuchMethod( @@ -439,6 +488,7 @@ class MockConnectedDeviceOperation extends _i1.Mock ), returnValue: _i4.Stream>.empty(), ) as _i4.Stream>); + @override _i4.Future requestMtu( String? deviceId, @@ -454,6 +504,7 @@ class MockConnectedDeviceOperation extends _i1.Mock ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future> discoverServices(String? deviceId) => (super.noSuchMethod( @@ -464,6 +515,19 @@ class MockConnectedDeviceOperation extends _i1.Mock returnValue: _i4.Future>.value( <_i2.DiscoveredService>[]), ) as _i4.Future>); + + @override + _i4.Future> getDiscoverServices( + String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #getDiscoverServices, + [deviceId], + ), + returnValue: _i4.Future>.value( + <_i2.DiscoveredService>[]), + ) as _i4.Future>); + @override _i4.Future requestConnectionPriority( String? deviceId, @@ -496,6 +560,7 @@ class MockDeviceConnector extends _i1.Mock implements _i6.DeviceConnector { Invocation.getter(#deviceConnectionStateUpdateStream), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Future<_i2.BondingStatus> establishBonding({required String? deviceId}) => (super.noSuchMethod( @@ -507,6 +572,7 @@ class MockDeviceConnector extends _i1.Mock implements _i6.DeviceConnector { returnValue: _i4.Future<_i2.BondingStatus>.value(_i2.BondingStatus.none), ) as _i4.Future<_i2.BondingStatus>); + @override _i4.Stream<_i2.ConnectionStateUpdate> connect({ required String? id, @@ -526,6 +592,7 @@ class MockDeviceConnector extends _i1.Mock implements _i6.DeviceConnector { ), returnValue: _i4.Stream<_i2.ConnectionStateUpdate>.empty(), ) as _i4.Stream<_i2.ConnectionStateUpdate>); + @override _i4.Future retrieveDeviceName(String? id) => (super.noSuchMethod( Invocation.method( @@ -534,6 +601,7 @@ class MockDeviceConnector extends _i1.Mock implements _i6.DeviceConnector { ), returnValue: _i4.Future.value(), ) as _i4.Future); + @override _i4.Stream<_i2.ConnectionStateUpdate> connectToAdvertisingDevice({ required String? id, @@ -585,6 +653,7 @@ class MockDeviceScanner extends _i1.Mock implements _i7.DeviceScanner { ), returnValue: _i4.Future<_i2.DeviceAssociationInfo?>.value(), ) as _i4.Future<_i2.DeviceAssociationInfo?>); + @override _i4.Stream<_i2.DiscoveredDevice> scanForDevices({ required List<_i2.Uuid>? withServices, diff --git a/packages/reactive_ble_mobile/CHANGELOG.md b/packages/reactive_ble_mobile/CHANGELOG.md index 5e37d6f1..a7cb4efa 100644 --- a/packages/reactive_ble_mobile/CHANGELOG.md +++ b/packages/reactive_ble_mobile/CHANGELOG.md @@ -1,3 +1,27 @@ +## 5.3.1 + +* Use proper platform_interface dependency version #837 + +## 5.3.0 + +* Readd accidentally removed version constraint #789 +* Add a placeholder implementation for non-mobile platforms #688 +* Add Github actions and Migrate to latest Android SDK, AGP and protobuf plugin #830 +* Include packages lock-files #797 +* Update Kotlin version in README #831 +* Migrate away from deprecated strong mode analysis options #832 +* Read RSSI #796 + +## 5.2.0 + +* Bump the minimum requirement to Dart 2.17 and upgrade melos to 3.1.0 in #762 +* swiftlint config and inital formatting pass in #765 +* Cancel subscription when a disconnect event has been thrown in #769 +* Fix typos in #778 +* Update CI config to use Xcode 14 in #786 +* Support multiple services or characteristics with the same id in #776 +* Breaking change: If a device has multiple characteristics with the same ID, `readCharacteristic`, `writeCharacteristic` and `subscribeToCharacteristic` used to select the first of those characteristics. Now they will fail in this case. Use `resolve` or `getDiscoveredServices` instead. + ## 5.1.1 * Make Connectable backwards compatible #757, #750 diff --git a/packages/reactive_ble_mobile/android/build.gradle b/packages/reactive_ble_mobile/android/build.gradle index 73e5036c..e503373b 100644 --- a/packages/reactive_ble_mobile/android/build.gradle +++ b/packages/reactive_ble_mobile/android/build.gradle @@ -3,7 +3,7 @@ version '1.0-SNAPSHOT' buildscript { ext.detekt_version = '1.17.1' - ext.kotlin_version = '1.5.31' + ext.kotlin_version = '1.8.21' repositories { google() mavenCentral() @@ -13,8 +13,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.17' + classpath 'com.android.tools.build:gradle:8.0.2' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$detekt_version" classpath "de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1" @@ -51,11 +51,13 @@ android { defaultConfig { minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 33 consumerProguardFiles 'proguard-rules.txt' } - lintOptions { + namespace 'com.signify.hue.flutterreactiveble' + + lint { disable 'InvalidPackage' } @@ -79,7 +81,7 @@ detekt { protobuf { protoc { - artifact = 'com.google.protobuf:protoc:3.18.1' + artifact = 'com.google.protobuf:protoc:3.23.0' } generateProtoTasks { @@ -96,7 +98,7 @@ protobuf { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.polidea.rxandroidble2:rxandroidble:1.16.0' - implementation 'com.google.protobuf:protobuf-javalite:3.18.1' + implementation 'com.google.protobuf:protobuf-javalite:3.23.0' implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' diff --git a/packages/reactive_ble_mobile/android/gradle.properties b/packages/reactive_ble_mobile/android/gradle.properties deleted file mode 100644 index 7d27a569..00000000 --- a/packages/reactive_ble_mobile/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx3072m -org.gradle.caching=true -org.gradle.parallel=true -android.useAndroidX=true diff --git a/packages/reactive_ble_mobile/android/gradle/wrapper/gradle-wrapper.properties b/packages/reactive_ble_mobile/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 40f6db41..00000000 --- a/packages/reactive_ble_mobile/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Wed Sep 29 14:33:41 CEST 2021 -distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME diff --git a/packages/reactive_ble_mobile/android/src/main/AndroidManifest.xml b/packages/reactive_ble_mobile/android/src/main/AndroidManifest.xml index c18bc1ae..0ceba194 100644 --- a/packages/reactive_ble_mobile/android/src/main/AndroidManifest.xml +++ b/packages/reactive_ble_mobile/android/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + Unit>( + "initialize" to this::initializeClient, + "deinitialize" to this::deinitializeClient, + "launchCompanionWorkflow" to this::launchCompanionFlow, + "scanForDevices" to this::scanForDevices, + "establishBonding" to this::establishBonding, + "connectToDevice" to this::connectToDevice, + "clearGattCache" to this::clearGattCache, + "disconnectFromDevice" to this::disconnectFromDevice, + "readCharacteristic" to this::readCharacteristic, + "writeCharacteristicWithResponse" to this::writeCharacteristicWithResponse, + "writeCharacteristicWithoutResponse" to this::writeCharacteristicWithoutResponse, + "readNotifications" to this::readNotifications, + "stopNotifications" to this::stopNotifications, + "negotiateMtuSize" to this::negotiateMtuSize, + "requestConnectionPriority" to this::requestConnectionPriority, + "discoverServices" to this::discoverServices, + "getDiscoveredServices" to this::discoverServices, + "readRssi" to this::readRssi, + ) + + private lateinit var bleClient: com.signify.hue.flutterreactiveble.ble.BleClient + + private lateinit var scanchannel: EventChannel + private lateinit var deviceConnectionChannel: EventChannel + private lateinit var charNotificationChannel: EventChannel - private val pluginMethods = mapOf Unit>( - "initialize" to this::initializeClient, - "deinitialize" to this::deinitializeClient, - "launchCompanionWorkflow" to this::launchCompanionFlow, - "scanForDevices" to this::scanForDevices, - "establishBonding" to this::establishBonding, - "connectToDevice" to this::connectToDevice, - "clearGattCache" to this::clearGattCache, - "disconnectFromDevice" to this::disconnectFromDevice, - "readCharacteristic" to this::readCharacteristic, - "writeCharacteristicWithResponse" to this::writeCharacteristicWithResponse, - "writeCharacteristicWithoutResponse" to this::writeCharacteristicWithoutResponse, - "readNotifications" to this::readNotifications, - "stopNotifications" to this::stopNotifications, - "negotiateMtuSize" to this::negotiateMtuSize, - "requestConnectionPriority" to this::requestConnectionPriority, - "discoverServices" to this::discoverServices - ) - - lateinit var bleClient: com.signify.hue.flutterreactiveble.ble.BleClient - - lateinit var scanchannel: EventChannel - lateinit var deviceConnectionChannel: EventChannel - lateinit var charNotificationChannel: EventChannel - - lateinit var companionHandler: CompanionHandler - lateinit var scandevicesHandler: ScanDevicesHandler - lateinit var deviceConnectionHandler: DeviceConnectionHandler - lateinit var charNotificationHandler: CharNotificationHandler + private lateinit var companionHandler: CompanionHandler + private lateinit var scanDevicesHandler: ScanDevicesHandler + private lateinit var deviceConnectionHandler: DeviceConnectionHandler + private lateinit var charNotificationHandler: CharNotificationHandler private val uuidConverter = UuidConverter() private val protoConverter = ProtobufMessageConverter() - internal fun initialize(messenger: BinaryMessenger, context: Context) { + internal fun initialize( + messenger: BinaryMessenger, + context: Context, + ) { bleClient = com.signify.hue.flutterreactiveble.ble.ReactiveBleClient(context) scanchannel = EventChannel(messenger, "flutter_reactive_ble_scan") @@ -73,57 +74,67 @@ class PluginController : PluginRegistry.ActivityResultListener { val bleStatusChannel = EventChannel(messenger, "flutter_reactive_ble_status") companionHandler = CompanionHandler() - scandevicesHandler = ScanDevicesHandler(bleClient) + scanDevicesHandler = ScanDevicesHandler(bleClient) deviceConnectionHandler = DeviceConnectionHandler(bleClient) charNotificationHandler = CharNotificationHandler(bleClient) val bleStatusHandler = BleStatusHandler(bleClient) - scanchannel.setStreamHandler(scandevicesHandler) + scanchannel.setStreamHandler(scanDevicesHandler) deviceConnectionChannel.setStreamHandler(deviceConnectionHandler) charNotificationChannel.setStreamHandler(charNotificationHandler) bleStatusChannel.setStreamHandler(bleStatusHandler) } internal fun deinitialize() { - scandevicesHandler.stopDeviceScan() + scanDevicesHandler.stopDeviceScan() deviceConnectionHandler.disconnectAll() } - internal fun execute(call: MethodCall, result: Result) { + internal fun execute( + call: MethodCall, + result: Result, + ) { pluginMethods[call.method]?.invoke(call, result) ?: result.notImplemented() } - private fun initializeClient(call: MethodCall, result: Result) { + private fun initializeClient( + call: MethodCall, + result: Result, + ) { bleClient.initializeClient() result.success(null) } - private fun deinitializeClient(call: MethodCall, result: Result) { + private fun deinitializeClient( + call: MethodCall, + result: Result, + ) { deinitialize() result.success(null) } - private fun launchCompanionFlow(call: MethodCall, result: Result) { + private fun launchCompanionFlow( + call: MethodCall, + result: Result, + ) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { companionHandler.launchCompanionFlow( pb.LaunchCompanionRequest.parseFrom(call.arguments as ByteArray), - result + result, ) } else { result.error( "NOT_SUPPORTED", "Companion flow is only supported on Android Oreo and above", - null + null, ) } } - private fun scanForDevices(call: MethodCall, result: Result) { - scandevicesHandler.prepareScan(pb.ScanForDevicesRequest.parseFrom(call.arguments as ByteArray)) - result.success(null) - } - - private fun establishBonding(call: MethodCall, result: Result) { + private fun establishBonding( + call: MethodCall, + result: Result, + ) { val establishBondingMessage = pb.EstablishBondingRequest.parseFrom(call.arguments as ByteArray) deviceConnectionHandler.establishBonding(establishBondingMessage).subscribe({ result.success(protoConverter.convertBondingInfo(it).toByteArray()) @@ -132,14 +143,28 @@ class PluginController : PluginRegistry.ActivityResultListener { }).discard() } - private fun connectToDevice(call: MethodCall, result: Result) { + private fun scanForDevices( + call: MethodCall, + result: Result, + ) { + scanDevicesHandler.prepareScan(pb.ScanForDevicesRequest.parseFrom(call.arguments as ByteArray)) + result.success(null) + } + + private fun connectToDevice( + call: MethodCall, + result: Result, + ) { result.success(null) val connectDeviceMessage = pb.ConnectToDeviceRequest.parseFrom(call.arguments as ByteArray) deviceConnectionHandler.connectToDevice(connectDeviceMessage) } - private fun clearGattCache(call: MethodCall, result: Result) { + private fun clearGattCache( + call: MethodCall, + result: Result, + ) { val args = pb.ClearGattCacheRequest.parseFrom(call.arguments as ByteArray) bleClient.clearGattCache(args.deviceId) .observeOn(AndroidSchedulers.mainThread()) @@ -149,54 +174,64 @@ class PluginController : PluginRegistry.ActivityResultListener { result.success(info.toByteArray()) }, { - val info = protoConverter.convertClearGattCacheError( - ClearGattCacheErrorType.UNKNOWN, - it.message - ) + val info = + protoConverter.convertClearGattCacheError( + ClearGattCacheErrorType.UNKNOWN, + it.message, + ) result.success(info.toByteArray()) - } + }, ) .discard() } - private fun disconnectFromDevice(call: MethodCall, result: Result) { + private fun disconnectFromDevice( + call: MethodCall, + result: Result, + ) { result.success(null) val connectDeviceMessage = pb.DisconnectFromDeviceRequest.parseFrom(call.arguments as ByteArray) deviceConnectionHandler.disconnectDevice(connectDeviceMessage.deviceId) } - private fun readCharacteristic(call: MethodCall, result: Result) { + private fun readCharacteristic( + call: MethodCall, + result: Result, + ) { result.success(null) val readCharMessage = pb.ReadCharacteristicRequest.parseFrom(call.arguments as ByteArray) val deviceId = readCharMessage.characteristic.deviceId - val characteristic = - uuidConverter.uuidFromByteArray(readCharMessage.characteristic.characteristicUuid.data.toByteArray()) + val characteristic = uuidConverter.uuidFromByteArray(readCharMessage.characteristic.characteristicUuid.data.toByteArray()) + val characteristicInstance = readCharMessage.characteristic.characteristicInstanceId.toInt() bleClient.readCharacteristic( - readCharMessage.characteristic.deviceId, characteristic + deviceId, + characteristic, + characteristicInstance, ) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { charResult -> when (charResult) { is com.signify.hue.flutterreactiveble.ble.CharOperationSuccessful -> { - val charInfo = protoConverter.convertCharacteristicInfo( - readCharMessage.characteristic, - charResult.value.toByteArray() - ) + val charInfo = + protoConverter.convertCharacteristicInfo( + readCharMessage.characteristic, + charResult.value.toByteArray(), + ) charNotificationHandler.addSingleReadToStream(charInfo) } is com.signify.hue.flutterreactiveble.ble.CharOperationFailed -> { protoConverter.convertCharacteristicError( readCharMessage.characteristic, - "Failed to connect" + "Failed to connect", ) charNotificationHandler.addSingleErrorToStream( readCharMessage.characteristic, - charResult.errorMessage + charResult.errorMessage, ) } } @@ -204,30 +239,36 @@ class PluginController : PluginRegistry.ActivityResultListener { { throwable -> protoConverter.convertCharacteristicError( readCharMessage.characteristic, - throwable.message + throwable.message, ) charNotificationHandler.addSingleErrorToStream( readCharMessage.characteristic, - throwable?.message ?: "Failure" + throwable?.message ?: "Failure", ) - } + }, ) .discard() } - private fun writeCharacteristicWithResponse(call: MethodCall, result: Result) { + private fun writeCharacteristicWithResponse( + call: MethodCall, + result: Result, + ) { executeWriteAndPropagateResultToChannel( call, result, - com.signify.hue.flutterreactiveble.ble.BleClient::writeCharacteristicWithResponse + com.signify.hue.flutterreactiveble.ble.BleClient::writeCharacteristicWithResponse, ) } - private fun writeCharacteristicWithoutResponse(call: MethodCall, result: Result) { + private fun writeCharacteristicWithoutResponse( + call: MethodCall, + result: Result, + ) { executeWriteAndPropagateResultToChannel( call, result, - com.signify.hue.flutterreactiveble.ble.BleClient::writeCharacteristicWithoutResponse + com.signify.hue.flutterreactiveble.ble.BleClient::writeCharacteristicWithoutResponse, ) } @@ -237,122 +278,137 @@ class PluginController : PluginRegistry.ActivityResultListener { writeOperation: com.signify.hue.flutterreactiveble.ble.BleClient.( deviceId: String, characteristic: UUID, - value: ByteArray - ) -> Single + characteristicInstanceId: Int, + value: ByteArray, + ) -> Single, ) { val writeCharMessage = pb.WriteCharacteristicRequest.parseFrom(call.arguments as ByteArray) bleClient.writeOperation( writeCharMessage.characteristic.deviceId, uuidConverter.uuidFromByteArray(writeCharMessage.characteristic.characteristicUuid.data.toByteArray()), - writeCharMessage.value.toByteArray() + writeCharMessage.characteristic.characteristicInstanceId.toInt(), + writeCharMessage.value.toByteArray(), ) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ operationResult -> - when (operationResult) { - is com.signify.hue.flutterreactiveble.ble.CharOperationSuccessful -> { - result.success( - protoConverter.convertWriteCharacteristicInfo( - writeCharMessage, - null - ).toByteArray() - ) - } - - is com.signify.hue.flutterreactiveble.ble.CharOperationFailed -> { - result.success( - protoConverter.convertWriteCharacteristicInfo( - writeCharMessage, - operationResult.errorMessage - ).toByteArray() - ) + .subscribe( + { operationResult -> + when (operationResult) { + is com.signify.hue.flutterreactiveble.ble.CharOperationSuccessful -> { + result.success( + protoConverter.convertWriteCharacteristicInfo( + writeCharMessage, + null, + ).toByteArray(), + ) + } + is com.signify.hue.flutterreactiveble.ble.CharOperationFailed -> { + result.success( + protoConverter.convertWriteCharacteristicInfo( + writeCharMessage, + operationResult.errorMessage, + ).toByteArray(), + ) + } } - } - }, + }, { throwable -> result.success( protoConverter.convertWriteCharacteristicInfo( writeCharMessage, - throwable.message - ).toByteArray() + throwable.message, + ).toByteArray(), ) - } + }, ) .discard() } - private fun readNotifications(call: MethodCall, result: Result) { + private fun readNotifications( + call: MethodCall, + result: Result, + ) { val request = pb.NotifyCharacteristicRequest.parseFrom(call.arguments as ByteArray) charNotificationHandler.subscribeToNotifications(request) result.success(null) } - private fun stopNotifications(call: MethodCall, result: Result) { + private fun stopNotifications( + call: MethodCall, + result: Result, + ) { val request = pb.NotifyNoMoreCharacteristicRequest.parseFrom(call.arguments as ByteArray) charNotificationHandler.unsubscribeFromNotifications(request) result.success(null) } - private fun negotiateMtuSize(call: MethodCall, result: Result) { + private fun negotiateMtuSize( + call: MethodCall, + result: Result, + ) { val request = pb.NegotiateMtuRequest.parseFrom(call.arguments as ByteArray) bleClient.negotiateMtuSize(request.deviceId, request.mtuSize) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ mtuResult -> - result.success(protoConverter.convertNegotiateMtuInfo(mtuResult).toByteArray()) - }, { throwable -> - result.success( - protoConverter.convertNegotiateMtuInfo( - com.signify.hue.flutterreactiveble.ble.MtuNegotiateFailed( - request.deviceId, - throwable.message ?: "" - ) - ).toByteArray() - ) - } + .subscribe( + { mtuResult -> + result.success(protoConverter.convertNegotiateMtuInfo(mtuResult).toByteArray()) + }, + { throwable -> + result.success( + protoConverter.convertNegotiateMtuInfo( + com.signify.hue.flutterreactiveble.ble.MtuNegotiateFailed( + request.deviceId, + throwable.message ?: "", + ), + ).toByteArray(), + ) + }, ) .discard() } - private fun requestConnectionPriority(call: MethodCall, result: Result) { + private fun requestConnectionPriority( + call: MethodCall, + result: Result, + ) { val request = pb.ChangeConnectionPriorityRequest.parseFrom(call.arguments as ByteArray) - bleClient.requestConnectionPriority( - request.deviceId, - request.priority.toConnectionPriority() - ) + bleClient.requestConnectionPriority(request.deviceId, request.priority.toConnectionPriority()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ requestResult -> - result.success( - protoConverter - .convertRequestConnectionPriorityInfo(requestResult).toByteArray() - ) - }, + .subscribe( + { requestResult -> + result.success( + protoConverter + .convertRequestConnectionPriorityInfo(requestResult).toByteArray(), + ) + }, { throwable -> result.success( protoConverter.convertRequestConnectionPriorityInfo( RequestConnectionPriorityFailed( - request.deviceId, throwable?.message - ?: "Unknown error" - ) - ).toByteArray() + request.deviceId, + throwable?.message + ?: "Unknown error", + ), + ).toByteArray(), ) - }) + }, + ) .discard() } - private fun discoverServices(call: MethodCall, result: Result) { + private fun discoverServices( + call: MethodCall, + result: Result, + ) { val request = pb.DiscoverServicesRequest.parseFrom(call.arguments as ByteArray) bleClient.discoverServices(request.deviceId) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ discoverResult -> - result.success( - protoConverter.convertDiscoverServicesInfo( - request.deviceId, - discoverResult - ).toByteArray() - ) - }, { throwable -> - result.error("service_discovery_failure", throwable.message, null) + result.success(protoConverter.convertDiscoverServicesInfo(request.deviceId, discoverResult).toByteArray()) + }, { + throwable -> + result.error("service_discovery_failure", throwable.toString(), throwable.stackTrace.toList().toString()) }) .discard() } @@ -361,10 +417,14 @@ class PluginController : PluginRegistry.ActivityResultListener { companionHandler.setActivity(activity) } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { + override fun onActivityResult( + requestCode: Int, + resultCode: Int, + data: Intent?, + ): Boolean { if (requestCode == CompanionHandler.SELECT_DEVICE_REQUEST_CODE && resultCode == Activity.RESULT_OK) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - return false; + return false } // When @@ -375,4 +435,21 @@ class PluginController : PluginRegistry.ActivityResultListener { return false } + + private fun readRssi( + call: MethodCall, + result: Result, + ) { + val args = pb.ReadRssiRequest.parseFrom(call.arguments as ByteArray) + + bleClient.readRssi(args.deviceId) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ rssi -> + val info = protoConverter.convertReadRssiResult(rssi) + result.success(info.toByteArray()) + }, { error -> + result.error("read_rssi_error", error.message, null) + }) + .discard() + } } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ReactiveBlePlugin.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ReactiveBlePlugin.kt index 92ae6eaa..32c1758c 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ReactiveBlePlugin.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ReactiveBlePlugin.kt @@ -25,7 +25,7 @@ class ReactiveBlePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, Activi private fun initializePlugin( messenger: BinaryMessenger, context: Context, - plugin: ReactiveBlePlugin + plugin: ReactiveBlePlugin, ) { val channel = MethodChannel(messenger, "flutter_reactive_ble_method") channel.setMethodCallHandler(plugin) @@ -39,7 +39,10 @@ class ReactiveBlePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, Activi } } - override fun onMethodCall(call: MethodCall, result: Result) { + override fun onMethodCall( + call: MethodCall, + result: Result, + ) { pluginController.execute(call, result) } @@ -60,6 +63,4 @@ class ReactiveBlePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, Activi override fun onDetachedFromActivity() { pluginController.setActivity(null) } - - } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleClient.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleClient.kt index 6b0848c7..8287e11e 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleClient.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleClient.kt @@ -12,11 +12,9 @@ import java.util.UUID @Suppress("TooManyFunctions") interface BleClient { - - val connectionUpdateSubject: BehaviorSubject + val connectionUpdateSubject: BehaviorSubject fun initializeClient() - fun scanForDevices(services: List, scanMode: ScanMode, requireLocationServicesEnabled: Boolean): Observable /** * Establishes a bond with the device. @@ -28,25 +26,63 @@ interface BleClient { * - [android.bluetooth.BluetoothDevice.BOND_BONDED] */ fun establishBond(deviceId: String): Single - fun connectToDevice(deviceId: String, timeout: Duration) + + fun scanForDevices( + services: List, + scanMode: ScanMode, + requireLocationServicesEnabled: Boolean, + ): Observable + + fun connectToDevice( + deviceId: String, + timeout: Duration, + ) + fun disconnectDevice(deviceId: String) + fun disconnectAllDevices() + fun discoverServices(deviceId: String): Single + fun clearGattCache(deviceId: String): Completable - fun readCharacteristic(deviceId: String, characteristic: UUID): Single - fun setupNotification(deviceId: String, characteristic: UUID): Observable + + fun readCharacteristic( + deviceId: String, + characteristicId: UUID, + characteristicInstanceId: Int, + ): Single + + fun setupNotification( + deviceId: String, + characteristicId: UUID, + characteristicInstanceId: Int, + ): Observable + fun writeCharacteristicWithResponse( deviceId: String, - characteristic: UUID, - value: ByteArray + characteristicId: UUID, + characteristicInstanceId: Int, + value: ByteArray, ): Single + fun writeCharacteristicWithoutResponse( deviceId: String, - characteristic: UUID, - value: ByteArray + characteristicId: UUID, + characteristicInstanceId: Int, + value: ByteArray, ): Single - fun negotiateMtuSize(deviceId: String, size: Int): Single + + fun negotiateMtuSize( + deviceId: String, + size: Int, + ): Single + fun observeBleStatus(): Observable - fun requestConnectionPriority(deviceId: String, priority: ConnectionPriority): - Single + + fun requestConnectionPriority( + deviceId: String, + priority: ConnectionPriority, + ): Single + + fun readRssi(deviceId: String): Single } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleWrapper.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleWrapper.kt index 08737a09..d15f2eb4 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleWrapper.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BleWrapper.kt @@ -34,23 +34,33 @@ data class ScanInfo(val deviceId: String, val name: String, val rssi: Int, val c } sealed class ConnectionUpdate + data class ConnectionUpdateSuccess(val deviceId: String, val connectionState: Int) : ConnectionUpdate() + data class ConnectionUpdateError(val deviceId: String, val errorMessage: String) : ConnectionUpdate() sealed class EstablishConnectionResult + data class EstablishedConnection(val deviceId: String, val rxConnection: RxBleConnection) : EstablishConnectionResult() + data class EstablishConnectionFailure(val deviceId: String, val errorMessage: String) : EstablishConnectionResult() sealed class MtuNegotiateResult -data class MtuNegotiateSuccesful(val deviceId: String, val size: Int) : MtuNegotiateResult() + +data class MtuNegotiateSuccessful(val deviceId: String, val size: Int) : MtuNegotiateResult() + data class MtuNegotiateFailed(val deviceId: String, val errorMessage: String) : MtuNegotiateResult() sealed class CharOperationResult + data class CharOperationSuccessful(val deviceId: String, val value: List) : CharOperationResult() + data class CharOperationFailed(val deviceId: String, val errorMessage: String) : CharOperationResult() sealed class RequestConnectionPriorityResult + data class RequestConnectionPrioritySuccess(val deviceId: String) : RequestConnectionPriorityResult() + data class RequestConnectionPriorityFailed(val deviceId: String, val errorMessage: String) : RequestConnectionPriorityResult() enum class BleStatus(val code: Int) { @@ -59,17 +69,17 @@ enum class BleStatus(val code: Int) { UNAUTHORIZED(code = 2), POWERED_OFF(code = 3), LOCATION_SERVICES_DISABLED(code = 4), - READY(code = 5) + READY(code = 5), } enum class ConnectionPriority(val code: Int) { BALANCED(code = 0), HIGH_PERFORMACE(code = 1), - LOW_POWER(code = 2) + LOW_POWER(code = 2), } enum class Connectable(val code: Int) { UNKNOWN(code = 0), NOT_CONNECTABLE(code = 1), - CONNECTABLE(code = 2) + CONNECTABLE(code = 2), } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManager.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManager.kt index e2d77004..035a33a2 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManager.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManager.kt @@ -19,9 +19,9 @@ class BondingFailedException : RuntimeException() class BondingManager(private val context: Context) { /** + * TODO: try to understand why the popup is being displayed in the notification center (sometimes) ???!!! * @throws BondingFailedException */ - // TODO: try to understand why the popup is being displayed in the notification center (sometimes) ???!!! @SuppressLint("MissingPermission") fun bondWithDevice(rxBleDevice: RxBleDevice): Single { return Single.create { completion -> @@ -30,43 +30,50 @@ class BondingManager(private val context: Context) { return@create } - val receiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val deviceBeingPaired: BluetoothDevice? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent.getParcelableExtra( - BluetoothDevice.EXTRA_DEVICE, - BluetoothDevice::class.java - ) - } else { - @Suppress("DEPRECATION") - intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) - } + val receiver = + object : BroadcastReceiver() { + override fun onReceive( + context: Context, + intent: Intent, + ) { + val deviceBeingPaired: BluetoothDevice? = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, + BluetoothDevice::class.java, + ) + } else { + @Suppress("DEPRECATION") + intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) + } - if (deviceBeingPaired?.address == rxBleDevice.bluetoothDevice.address) { - val state = intent.getIntExtra( - BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.BOND_NONE - ) + if (deviceBeingPaired?.address == rxBleDevice.bluetoothDevice.address) { + val state = + intent.getIntExtra( + BluetoothDevice.EXTRA_BOND_STATE, + BluetoothDevice.BOND_NONE, + ) - when (state) { - BluetoothDevice.BOND_BONDED -> completion.onSuccess(state) - BluetoothDevice.BOND_NONE -> completion.onSuccess(state) - // BOND_BONDING is a intermediate state - do not send this back. + when (state) { + BluetoothDevice.BOND_BONDED -> completion.onSuccess(state) + BluetoothDevice.BOND_NONE -> completion.onSuccess(state) + // BOND_BONDING is a intermediate state - do not send this back. + } } } } - } - completion.setDisposable(Disposables.fromAction { - context.unregisterReceiver( - receiver - ) - }) + completion.setDisposable( + Disposables.fromAction { + context.unregisterReceiver( + receiver, + ) + }, + ) context.registerReceiver( receiver, - IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED) + IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED), ) val createBondResult = rxBleDevice.bluetoothDevice.createBond() diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ConnectionQueue.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ConnectionQueue.kt index 80287378..6c0343fe 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ConnectionQueue.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ConnectionQueue.kt @@ -4,7 +4,6 @@ import androidx.annotation.VisibleForTesting import io.reactivex.subjects.BehaviorSubject internal class ConnectionQueue { - private val queueSubject = BehaviorSubject.createDefault(listOf()) fun observeQueue() = queueSubject diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnector.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnector.kt index b64bac8c..8a53cf7b 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnector.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnector.kt @@ -21,7 +21,6 @@ internal class DeviceConnector( private val updateListeners: (update: ConnectionUpdate) -> Unit, private val connectionQueue: ConnectionQueue, ) { - companion object { private const val minTimeMsBeforeDisconnectingIsAllowed = 200L private const val delayMsAfterClearingCache = 300L @@ -34,10 +33,11 @@ internal class DeviceConnector( @VisibleForTesting internal var connectionDisposable: Disposable? = null - private val lazyConnection = lazy { - connectionDisposable = establishConnection(device) - connectDeviceSubject - } + private val lazyConnection = + lazy { + connectionDisposable = establishConnection(device) + connectDeviceSubject + } private val currentConnection: EstablishConnectionResult? get() = if (lazyConnection.isInitialized()) connection.value else null @@ -47,16 +47,12 @@ internal class DeviceConnector( private val connectionStatusUpdates by lazy { device.observeConnectionStateChanges() .startWith(device.connectionState) - .map { - ConnectionUpdateSuccess( - device.macAddress, - it.toConnectionState().code - ) - } + .map { ConnectionUpdateSuccess(device.macAddress, it.toConnectionState().code) } .onErrorReturn { ConnectionUpdateError( - device.macAddress, it.message - ?: "Unknown error" + device.macAddress, + it.message + ?: "Unknown error", ) } .subscribe { @@ -72,10 +68,7 @@ internal class DeviceConnector( disconnect to quickly after establishing connection. https://issuetracker.google.com/issues/37121223 */ if (diff < DeviceConnector.Companion.minTimeMsBeforeDisconnectingIsAllowed) { - Single.timer( - DeviceConnector.Companion.minTimeMsBeforeDisconnectingIsAllowed - diff, - TimeUnit.MILLISECONDS - ) + Single.timer(DeviceConnector.Companion.minTimeMsBeforeDisconnectingIsAllowed - diff, TimeUnit.MILLISECONDS) .doFinally { sendDisconnectedUpdate(deviceId) disposeSubscriptions() @@ -109,23 +102,18 @@ internal class DeviceConnector( Observable.just( EstablishConnectionFailure( deviceId, - "Device is not in queue" - ) + "Device is not in queue", + ), ) } else { connectDevice(rxBleDevice, shouldNotTimeout) - .map { - EstablishedConnection( - rxBleDevice.macAddress, - it - ) - } + .map { EstablishedConnection(rxBleDevice.macAddress, it) } } } .onErrorReturn { error -> EstablishConnectionFailure( rxBleDevice.macAddress, - error.message ?: "Unknown error" + error.message ?: "Unknown error", ) } .doOnNext { @@ -142,13 +130,16 @@ internal class DeviceConnector( connectionQueue.removeFromQueue(deviceId) updateListeners.invoke( ConnectionUpdateError( - deviceId, it.message - ?: "Unknown error" - ) + deviceId, + it.message + ?: "Unknown error", + ), ) } - .subscribe({ connectDeviceSubject.onNext(it) }, - { throwable -> connectDeviceSubject.onError(throwable) }) + .subscribe( + { connectDeviceSubject.onNext(it) }, + { throwable -> connectDeviceSubject.onError(throwable) }, + ) } private fun connectDevice( @@ -156,7 +147,6 @@ internal class DeviceConnector( shouldNotTimeout: Boolean, ): Observable = rxBleDevice.establishConnection(shouldNotTimeout) - .compose { if (shouldNotTimeout) { it @@ -165,17 +155,18 @@ internal class DeviceConnector( Observable.timer(connectionTimeout.value, connectionTimeout.unit), Function> { Observable.never() - } + }, ) } } - internal fun clearGattCache(): Completable = currentConnection?.let { connection -> - when (connection) { - is EstablishedConnection -> clearGattCache(connection.rxConnection) - is EstablishConnectionFailure -> Completable.error(Throwable(connection.errorMessage)) - } - } ?: Completable.error(IllegalStateException("Connection is not established")) + internal fun clearGattCache(): Completable = + currentConnection?.let { connection -> + when (connection) { + is EstablishedConnection -> clearGattCache(connection.rxConnection) + is EstablishConnectionFailure -> Completable.error(Throwable(connection.errorMessage)) + } + } ?: Completable.error(IllegalStateException("Connection is not established")) /** * Clear GATT attribute cache using an undocumented method `BluetoothGatt.refresh()`. @@ -189,24 +180,22 @@ internal class DeviceConnector( * Known to work up to Android Q beta 2. */ private fun clearGattCache(connection: RxBleConnection): Completable { - val operation = RxBleCustomOperation { bluetoothGatt, _, _ -> - try { - val refreshMethod = bluetoothGatt.javaClass.getMethod("refresh") - val success = refreshMethod.invoke(bluetoothGatt) as Boolean - if (success) { - Observable.empty() - .delay( - DeviceConnector.Companion.delayMsAfterClearingCache, - TimeUnit.MILLISECONDS - ) - } else { - val reason = "BluetoothGatt.refresh() returned false" - Observable.error(RuntimeException(reason)) + val operation = + RxBleCustomOperation { bluetoothGatt, _, _ -> + try { + val refreshMethod = bluetoothGatt.javaClass.getMethod("refresh") + val success = refreshMethod.invoke(bluetoothGatt) as Boolean + if (success) { + Observable.empty() + .delay(DeviceConnector.Companion.delayMsAfterClearingCache, TimeUnit.MILLISECONDS) + } else { + val reason = "BluetoothGatt.refresh() returned false" + Observable.error(RuntimeException(reason)) + } + } catch (e: ReflectiveOperationException) { + Observable.error(e) } - } catch (e: ReflectiveOperationException) { - Observable.error(e) } - } return connection.queue(operation).ignoreElements() } @@ -216,4 +205,15 @@ internal class DeviceConnector( queue.firstOrNull() == deviceId || !queue.contains(deviceId) } .takeUntil { it.isEmpty() || it.first() == deviceId } + + /** + * Reads the current RSSI value of the device + */ + internal fun readRssi(): Single = + currentConnection?.let { connection -> + when (connection) { + is EstablishedConnection -> connection.rxConnection.readRssi() + is EstablishConnectionFailure -> Single.error(Throwable(connection.errorMessage)) + } + } ?: Single.error(IllegalStateException("Connection is not established")) } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClient.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClient.kt index a0a75ee5..0f726d0f 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClient.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClient.kt @@ -16,6 +16,7 @@ import com.polidea.rxandroidble2.RxBleDeviceServices import com.polidea.rxandroidble2.scan.IsConnectable import com.polidea.rxandroidble2.scan.ScanFilter import com.polidea.rxandroidble2.scan.ScanSettings +import com.signify.hue.flutterreactiveble.ble.extensions.resolveCharacteristic import com.signify.hue.flutterreactiveble.ble.extensions.writeCharWithResponse import com.signify.hue.flutterreactiveble.ble.extensions.writeCharWithoutResponse import com.signify.hue.flutterreactiveble.converters.extractManufacturerData @@ -39,7 +40,7 @@ open class ReactiveBleClient(private val context: Context) : BleClient { private val allConnections = CompositeDisposable() companion object { - // this needs to be in companion update since backgroundisolates respawn the eventchannels + // this needs to be in companion update since background isolates respawn the event channels // Fix for https://github.com/PhilipsHue/flutter_reactive_ble/issues/277 private val connectionUpdateBehaviorSubject: BehaviorSubject = BehaviorSubject.create() @@ -59,19 +60,19 @@ open class ReactiveBleClient(private val context: Context) : BleClient { /*yes spread operator is not performant but after kotlin v1.60 it is less bad and it is also the recommended way to call varargs in java https://kotlinlang.org/docs/reference/java-interop.html#java-varargs - */ + */ @Suppress("SpreadOperator") override fun scanForDevices( services: List, scanMode: ScanMode, - requireLocationServicesEnabled: Boolean + requireLocationServicesEnabled: Boolean, ): Observable { - - val filters = services.map { service -> - ScanFilter.Builder() - .setServiceUuid(service) - .build() - }.toTypedArray() + val filters = + services.map { service -> + ScanFilter.Builder() + .setServiceUuid(service) + .build() + }.toTypedArray() return rxBleClient.scanBleDevices( ScanSettings.Builder() @@ -80,20 +81,24 @@ open class ReactiveBleClient(private val context: Context) : BleClient { .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .setShouldCheckLocationServicesState(requireLocationServicesEnabled) .build(), - *filters + *filters, ) .map { result -> - ScanInfo(result.bleDevice.macAddress, result.scanRecord.deviceName - ?: result.bleDevice.name ?: "", + ScanInfo( + result.bleDevice.macAddress, + result.scanRecord.deviceName + ?: result.bleDevice.name ?: "", result.rssi, when (result.isConnectable) { + null -> Connectable.UNKNOWN IsConnectable.LEGACY_UNKNOWN -> Connectable.UNKNOWN IsConnectable.NOT_CONNECTABLE -> Connectable.NOT_CONNECTABLE IsConnectable.CONNECTABLE -> Connectable.CONNECTABLE }, result.scanRecord.serviceData?.mapKeys { it.key.uuid } ?: emptyMap(), result.scanRecord.serviceUuids?.map { it.uuid } ?: emptyList(), - extractManufacturerData(result.scanRecord.manufacturerSpecificData)) + extractManufacturerData(result.scanRecord.manufacturerSpecificData), + ) } } @@ -102,29 +107,34 @@ open class ReactiveBleClient(private val context: Context) : BleClient { return BondingManager(context).bondWithDevice(device) } - override fun connectToDevice(deviceId: String, timeout: Duration) { - allConnections.add(getConnection(deviceId, timeout) - .subscribe({ result -> - when (result) { - is EstablishedConnection -> { - } - is EstablishConnectionFailure -> { - connectionUpdateBehaviorSubject.onNext( - ConnectionUpdateError( - deviceId, - result.errorMessage + override fun connectToDevice( + deviceId: String, + timeout: Duration, + ) { + allConnections.add( + getConnection(deviceId, timeout) + .subscribe({ result -> + when (result) { + is EstablishedConnection -> { + } + is EstablishConnectionFailure -> { + connectionUpdateBehaviorSubject.onNext( + ConnectionUpdateError( + deviceId, + result.errorMessage, + ), ) - ) + } } - } - }, { error -> - connectionUpdateBehaviorSubject.onNext( - ConnectionUpdateError( - deviceId, error?.message - ?: "unknown error" + }, { error -> + connectionUpdateBehaviorSubject.onNext( + ConnectionUpdateError( + deviceId, + error?.message + ?: "unknown error", + ), ) - ) - }) + }), ) } @@ -143,12 +153,15 @@ open class ReactiveBleClient(private val context: Context) : BleClient { ?: Completable.error(IllegalStateException("Device is not connected")) override fun discoverServices(deviceId: String): Single { - return getConnection(deviceId).flatMapSingle { connectionResult -> when (connectionResult) { is EstablishedConnection -> if (rxBleClient.getBleDevice(connectionResult.deviceId).bluetoothDevice.bondState == BOND_BONDING) { - Single.error(Exception("Bonding is in progress wait for bonding to be finished before executing more operations on the device")) + Single.error( + Exception( + "Bonding is in progress wait for bonding to be finished before executing more operations on the device", + ), + ) } else { connectionResult.rxConnection.discoverServices() } @@ -159,63 +172,78 @@ open class ReactiveBleClient(private val context: Context) : BleClient { override fun readCharacteristic( deviceId: String, - characteristic: UUID + characteristicId: UUID, + characteristicInstanceId: Int, ): Single = - getConnection(deviceId).flatMapSingle { connectionResult -> + getConnection(deviceId).flatMapSingle { connectionResult -> when (connectionResult) { - is EstablishedConnection -> - connectionResult.rxConnection.readCharacteristic(characteristic) - /* - On Android7 the ble stack frequently gives incorrectly - the error GAT_AUTH_FAIL(137) when reading char that will establish - the bonding with the peripheral. By retrying the operation once we - deviate between this flaky one time error and real auth failed cases - */ - .retry(1) { Build.VERSION.SDK_INT < Build.VERSION_CODES.O } - .map { value -> - CharOperationSuccessful(deviceId, value.asList()) - } + is EstablishedConnection -> { + connectionResult.rxConnection.resolveCharacteristic( + characteristicId, + characteristicInstanceId, + ).flatMap { c: BluetoothGattCharacteristic -> + connectionResult.rxConnection.readCharacteristic(c) + /* + On Android7 the ble stack frequently gives incorrectly + the error GAT_AUTH_FAIL(137) when reading char that will establish + the bonding with the peripheral. By retrying the operation once we + deviate between this flaky one time error and real auth failed cases + */ + .retry(1) { Build.VERSION.SDK_INT < Build.VERSION_CODES.O } + .map { value -> + CharOperationSuccessful(deviceId, value.asList()) + } + } + } is EstablishConnectionFailure -> Single.just( CharOperationFailed( deviceId, - "failed to connect ${connectionResult.errorMessage}" - ) + "failed to connect ${connectionResult.errorMessage}", + ), ) } }.first(CharOperationFailed(deviceId, "read char failed")) override fun writeCharacteristicWithResponse( deviceId: String, - characteristic: UUID, - value: ByteArray + characteristicId: UUID, + characteristicInstanceId: Int, + value: ByteArray, ): Single = executeWriteOperation( deviceId, - characteristic, + characteristicId, + characteristicInstanceId, value, - RxBleConnection::writeCharWithResponse + RxBleConnection::writeCharWithResponse, ) override fun writeCharacteristicWithoutResponse( deviceId: String, - characteristic: UUID, - value: ByteArray + characteristicId: UUID, + characteristicInstanceId: Int, + value: ByteArray, ): Single = - executeWriteOperation( deviceId, - characteristic, + characteristicId, + characteristicInstanceId, value, - RxBleConnection::writeCharWithoutResponse + RxBleConnection::writeCharWithoutResponse, ) - override fun setupNotification(deviceId: String, characteristic: UUID): Observable { + override fun setupNotification( + deviceId: String, + characteristicId: UUID, + characteristicInstanceId: Int, + ): Observable { return getConnection(deviceId) .flatMap { deviceConnection -> setupNotificationOrIndication( deviceConnection, - characteristic + characteristicId, + characteristicInstanceId, ) } // now we have setup the subscription and we want the actual value @@ -224,29 +252,36 @@ open class ReactiveBleClient(private val context: Context) : BleClient { } } - override fun negotiateMtuSize(deviceId: String, size: Int): Single = + override fun negotiateMtuSize( + deviceId: String, + size: Int, + ): Single = getConnection(deviceId).flatMapSingle { connectionResult -> when (connectionResult) { - is EstablishedConnection -> connectionResult.rxConnection.requestMtu(size) - .map { value -> MtuNegotiateSuccesful(deviceId, value) } + is EstablishedConnection -> + connectionResult.rxConnection.requestMtu(size) + .map { value -> MtuNegotiateSuccessful(deviceId, value) } is EstablishConnectionFailure -> Single.just( MtuNegotiateFailed( deviceId, - "failed to connect ${connectionResult.errorMessage}" - ) + "failed to connect ${connectionResult.errorMessage}", + ), ) } }.first(MtuNegotiateFailed(deviceId, "negotiate mtu timed out")) - override fun observeBleStatus(): Observable = rxBleClient.observeStateChanges() - .startWith(rxBleClient.state) - .map { it.toBleState() } + override fun observeBleStatus(): Observable = + rxBleClient.observeStateChanges() + .startWith(rxBleClient.state) + .map { it.toBleState() } @VisibleForTesting - internal open fun createDeviceConnector(device: RxBleDevice, timeout: Duration) = - DeviceConnector(device, timeout, connectionUpdateBehaviorSubject::onNext, connectionQueue) + internal open fun createDeviceConnector( + device: RxBleDevice, + timeout: Duration, + ) = DeviceConnector(device, timeout, connectionUpdateBehaviorSubject::onNext, connectionQueue) private fun getConnection( deviceId: String, @@ -261,23 +296,27 @@ open class ReactiveBleClient(private val context: Context) : BleClient { private fun executeWriteOperation( deviceId: String, - characteristic: UUID, + characteristicId: UUID, + characteristicInstanceId: Int, value: ByteArray, - bleOperation: RxBleConnection.(characteristic: UUID, value: ByteArray) -> Single + bleOperation: RxBleConnection.(characteristic: BluetoothGattCharacteristic, value: ByteArray) -> Single, ): Single { return getConnection(deviceId) - .flatMapSingle { connectionResult -> + .flatMapSingle { connectionResult -> when (connectionResult) { is EstablishedConnection -> { - connectionResult.rxConnection.bleOperation(characteristic, value) - .map { value -> CharOperationSuccessful(deviceId, value.asList()) } + connectionResult.rxConnection.resolveCharacteristic(characteristicId, characteristicInstanceId) + .flatMap { characteristic -> + connectionResult.rxConnection.bleOperation(characteristic, value) + .map { value -> CharOperationSuccessful(deviceId, value.asList()) } + } } is EstablishConnectionFailure -> { Single.just( CharOperationFailed( deviceId, - "failed to connect ${connectionResult.errorMessage}" - ) + "failed to connect ${connectionResult.errorMessage}", + ), ) } } @@ -286,33 +325,36 @@ open class ReactiveBleClient(private val context: Context) : BleClient { private fun setupNotificationOrIndication( deviceConnection: EstablishConnectionResult, - characteristic: UUID + characteristicId: UUID, + characteristicInstanceId: Int, ): Observable> = - when (deviceConnection) { is EstablishedConnection -> { - if (rxBleClient.getBleDevice(deviceConnection.deviceId).bluetoothDevice.bondState == BOND_BONDING) { - Observable.error(Exception("Bonding is in progress wait for bonding to be finished before executing more operations on the device")) + Observable.error( + Exception("Bonding is in progress wait for bonding to be finished before executing more operations on the device"), + ) } else { - deviceConnection.rxConnection.discoverServices() - .flatMap { deviceServices -> deviceServices.getCharacteristic(characteristic) } - .flatMapObservable { char -> - val mode = if (char.descriptors.isEmpty()) { + deviceConnection.rxConnection.resolveCharacteristic( + characteristicId, + characteristicInstanceId, + ).flatMapObservable { characteristic -> + val mode = + if (characteristic.descriptors.isEmpty()) { NotificationSetupMode.COMPAT } else { NotificationSetupMode.DEFAULT } - if ((char.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { - deviceConnection.rxConnection.setupNotification( - characteristic, - mode - ) - } else { - deviceConnection.rxConnection.setupIndication(characteristic, mode) - } + if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { + deviceConnection.rxConnection.setupNotification( + characteristic, + mode, + ) + } else { + deviceConnection.rxConnection.setupIndication(characteristic, mode) } + } } } is EstablishConnectionFailure -> { @@ -322,32 +364,49 @@ open class ReactiveBleClient(private val context: Context) : BleClient { override fun requestConnectionPriority( deviceId: String, - priority: ConnectionPriority + priority: ConnectionPriority, ): Single = - getConnection(deviceId).switchMapSingle { connectionResult -> + getConnection(deviceId).switchMapSingle { connectionResult -> when (connectionResult) { is EstablishedConnection -> connectionResult.rxConnection.requestConnectionPriority( priority.code, 2, - TimeUnit.SECONDS + TimeUnit.SECONDS, ) .toSingle { RequestConnectionPrioritySuccess(deviceId) } - is EstablishConnectionFailure -> Single.fromCallable { - RequestConnectionPriorityFailed(deviceId, connectionResult.errorMessage) - } + is EstablishConnectionFailure -> + Single.fromCallable { + RequestConnectionPriorityFailed(deviceId, connectionResult.errorMessage) + } } }.first(RequestConnectionPriorityFailed(deviceId, "Unknown failure")) + override fun readRssi(deviceId: String): Single = + getConnection(deviceId).flatMapSingle { connectionResult -> + when (connectionResult) { + is EstablishedConnection -> { + connectionResult.rxConnection.readRssi() + } + is EstablishConnectionFailure -> + Single.error( + java.lang.IllegalStateException( + "Reading RSSI failed. Device is not connected", + ), + ) + } + }.firstOrError() + // enable this for extra debug output on the android stack - private fun enableDebugLogging() = RxBleClient - .updateLogOptions( - LogOptions.Builder().setLogLevel(LogConstants.VERBOSE) - .setMacAddressLogSetting(LogConstants.MAC_ADDRESS_FULL) - .setUuidsLogSetting(LogConstants.UUIDS_FULL) - .setShouldLogAttributeValues(true) - .build() - ) + private fun enableDebugLogging() = + RxBleClient + .updateLogOptions( + LogOptions.Builder().setLogLevel(LogConstants.VERBOSE) + .setMacAddressLogSetting(LogConstants.MAC_ADDRESS_FULL) + .setUuidsLogSetting(LogConstants.UUIDS_FULL) + .setShouldLogAttributeValues(true) + .build(), + ) } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/extensions/RxBleConnectionExtension.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/extensions/RxBleConnectionExtension.kt index ab3678b6..ac094f66 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/extensions/RxBleConnectionExtension.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/extensions/RxBleConnectionExtension.kt @@ -5,16 +5,32 @@ import com.polidea.rxandroidble2.RxBleConnection import io.reactivex.Single import java.util.UUID -fun RxBleConnection.writeCharWithResponse(uuid: UUID, value: ByteArray): Single = - executeWrite(uuid, value, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) +fun RxBleConnection.resolveCharacteristic( + uuid: UUID, + instanceId: Int, +): Single = + discoverServices().flatMap { services -> + Single.just( + services.bluetoothGattServices.flatMap { service -> + service.characteristics.filter { + it.uuid == uuid && it.instanceId == instanceId + } + }.single(), + ) + } -fun RxBleConnection.writeCharWithoutResponse(uuid: UUID, value: ByteArray): Single = - executeWrite(uuid, value, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) +fun RxBleConnection.writeCharWithResponse( + characteristic: BluetoothGattCharacteristic, + value: ByteArray, +): Single { + characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT + return writeCharacteristic(characteristic, value) +} -private fun RxBleConnection.executeWrite(uuid: UUID, value: ByteArray, writeType: Int) = - this.discoverServices().flatMap { services -> - services.getCharacteristic(uuid).flatMap { char -> - char.writeType = writeType - this.writeCharacteristic(char, value) - } - } +fun RxBleConnection.writeCharWithoutResponse( + characteristic: BluetoothGattCharacteristic, + value: ByteArray, +): Single { + characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE + return writeCharacteristic(characteristic, value) +} diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/BleStatusHandler.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/BleStatusHandler.kt index 2b942097..035071eb 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/BleStatusHandler.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/BleStatusHandler.kt @@ -10,14 +10,16 @@ import java.util.concurrent.TimeUnit import com.signify.hue.flutterreactiveble.ProtobufModel as pb class BleStatusHandler(private val bleClient: BleClient) : EventChannel.StreamHandler { - companion object { private const val delayListenBleStatus = 500L } private val subscriptionDisposable = SerialDisposable() - override fun onListen(arg: Any?, eventSink: EventChannel.EventSink?) { + override fun onListen( + arg: Any?, + eventSink: EventChannel.EventSink?, + ) { subscriptionDisposable.set(eventSink?.let(::listenToBleStatus)) } @@ -26,15 +28,16 @@ class BleStatusHandler(private val bleClient: BleClient) : EventChannel.StreamHa } private fun listenToBleStatus(eventSink: EventChannel.EventSink): Disposable = - Observable.timer(delayListenBleStatus, TimeUnit.MILLISECONDS) - .switchMap { bleClient.observeBleStatus() } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ bleStatus -> - val message = pb.BleStatusInfo.newBuilder() - .setStatus(bleStatus.code) - .build() - eventSink.success(message.toByteArray()) - }, { throwable -> - eventSink.error("ObserveBleStatusFailure", throwable.message, null) - }) + Observable.timer(delayListenBleStatus, TimeUnit.MILLISECONDS) + .switchMap { bleClient.observeBleStatus() } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ bleStatus -> + val message = + pb.BleStatusInfo.newBuilder() + .setStatus(bleStatus.code) + .build() + eventSink.success(message.toByteArray()) + }, { throwable -> + eventSink.error("ObserveBleStatusFailure", throwable.message, null) + }) } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CharNotificationHandler.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CharNotificationHandler.kt index c2cefe8c..a699eb58 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CharNotificationHandler.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CharNotificationHandler.kt @@ -1,11 +1,12 @@ package com.signify.hue.flutterreactiveble.channelhandlers -import com.signify.hue.flutterreactiveble.ProtobufModel as pb +import com.polidea.rxandroidble2.exceptions.BleDisconnectedException import com.signify.hue.flutterreactiveble.converters.ProtobufMessageConverter import com.signify.hue.flutterreactiveble.converters.UuidConverter import io.flutter.plugin.common.EventChannel import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable +import com.signify.hue.flutterreactiveble.ProtobufModel as pb class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreactiveble.ble.BleClient) : EventChannel.StreamHandler { @@ -18,7 +19,10 @@ class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreac private val subscriptionMap = mutableMapOf() } - override fun onListen(objectSink: Any?, eventSink: EventChannel.EventSink?) { + override fun onListen( + objectSink: Any?, + eventSink: EventChannel.EventSink?, + ) { eventSink?.let { charNotificationSink = eventSink } @@ -29,15 +33,28 @@ class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreac } fun subscribeToNotifications(request: pb.NotifyCharacteristicRequest) { - val charUuid = uuidConverter - .uuidFromByteArray(request.characteristic.characteristicUuid.data.toByteArray()) - val subscription = bleClient.setupNotification(request.characteristic.deviceId, charUuid) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ value -> - handleNotificationValue(request.characteristic, value) - }, { - handleNotificationError(request.characteristic, it) - }) + val charUuid = + uuidConverter + .uuidFromByteArray(request.characteristic.characteristicUuid.data.toByteArray()) + val subscription = + bleClient.setupNotification( + request.characteristic.deviceId, + charUuid, + request.characteristic.characteristicInstanceId.toInt(), + ) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ value -> + handleNotificationValue(request.characteristic, value) + }, { + when (it) { + is BleDisconnectedException -> { + subscriptionMap.remove(request.characteristic)?.dispose() + } + else -> { + handleNotificationError(request.characteristic, it) + } + } + }) subscriptionMap[request.characteristic] = subscription } @@ -49,7 +66,10 @@ class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreac handleNotificationValue(charInfo.characteristic, charInfo.value.toByteArray()) } - fun addSingleErrorToStream(subscriptionRequest: pb.CharacteristicAddress, error: String) { + fun addSingleErrorToStream( + subscriptionRequest: pb.CharacteristicAddress, + error: String, + ) { val convertedMsg = protobufConverter.convertCharacteristicError(subscriptionRequest, error) charNotificationSink?.success(convertedMsg.toByteArray()) } @@ -61,7 +81,7 @@ class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreac private fun handleNotificationValue( subscriptionRequest: pb.CharacteristicAddress, - value: ByteArray + value: ByteArray, ) { val convertedMsg = protobufConverter.convertCharacteristicInfo(subscriptionRequest, value) charNotificationSink?.success(convertedMsg.toByteArray()) @@ -69,7 +89,7 @@ class CharNotificationHandler(private val bleClient: com.signify.hue.flutterreac private fun handleNotificationError( subscriptionRequest: pb.CharacteristicAddress, - error: Throwable + error: Throwable, ) { val convertedMsg = protobufConverter.convertCharacteristicError(subscriptionRequest, error.message ?: "") diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CompanionHandler.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CompanionHandler.kt index c775c380..9d47daa5 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CompanionHandler.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/CompanionHandler.kt @@ -31,25 +31,28 @@ class CompanionHandler { @RequiresApi(Build.VERSION_CODES.O) fun launchCompanionFlow( parseFrom: ProtobufModel.LaunchCompanionRequest, - result: MethodChannel.Result + result: MethodChannel.Result, ) { - val deviceFilter: BluetoothLeDeviceFilter = BluetoothLeDeviceFilter.Builder() - .setNamePattern(Pattern.compile(parseFrom.deviceNamePattern)) - .build() + val deviceFilter: BluetoothLeDeviceFilter = + BluetoothLeDeviceFilter.Builder() + .setNamePattern(Pattern.compile(parseFrom.deviceNamePattern)) + .build() - val pairingRequestBuilder = AssociationRequest.Builder() - .addDeviceFilter(deviceFilter) - .setSingleDevice(parseFrom.singleDeviceScan) + val pairingRequestBuilder = + AssociationRequest.Builder() + .addDeviceFilter(deviceFilter) + .setSingleDevice(parseFrom.singleDeviceScan) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { pairingRequestBuilder.setForceConfirmation(parseFrom.forceConfirmation) } - val activity = activity.get() ?: return result.error( - "CompanionHandler", - "Activity is null", - null - ) + val activity = + activity.get() ?: return result.error( + "CompanionHandler", + "Activity is null", + null, + ) val deviceManager = activity.getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager @@ -57,7 +60,8 @@ class CompanionHandler { val executor = Executor { it.run() } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - deviceManager.associate(pairingRequestBuilder.build(), + deviceManager.associate( + pairingRequestBuilder.build(), executor, object : CompanionDeviceManager.Callback() { override fun onAssociationPending(intentSender: IntentSender) { @@ -67,7 +71,7 @@ class CompanionHandler { null, 0, 0, - 0 + 0, ) } @@ -75,10 +79,10 @@ class CompanionHandler { result.success( ProtobufModel.DeviceAssociationInfo.newBuilder() .setMacAddress( - associationInfo.deviceMacAddress!!.toString().uppercase() + associationInfo.deviceMacAddress!!.toString().uppercase(), ) .build() - .toByteArray() + .toByteArray(), ) } @@ -86,7 +90,8 @@ class CompanionHandler { Log.e(TAG, "onFailure: $errorMessage") result.error("CompanionHandler", errorMessage.toString(), null) } - }) + }, + ) } else { deviceManager.associate( pairingRequestBuilder.build(), @@ -96,7 +101,11 @@ class CompanionHandler { tmpResult = result activity.startIntentSenderForResult( chooserLauncher, - SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0 + SELECT_DEVICE_REQUEST_CODE, + null, + 0, + 0, + 0, ) } @@ -104,22 +113,24 @@ class CompanionHandler { Log.e(TAG, "onFailure: $error") result.error("CompanionHandler", error.toString(), null) } - }, null + }, + null, ) } } fun setActivity(activity: Activity?) { - this.activity = WeakReference(activity); + this.activity = WeakReference(activity) } @RequiresApi(Build.VERSION_CODES.O) fun onActivityResult(data: Intent?): ScanResult? { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - val associationInfo = data?.getParcelableExtra( - CompanionDeviceManager.EXTRA_ASSOCIATION, - AssociationInfo::class.java - ) + val associationInfo = + data?.getParcelableExtra( + CompanionDeviceManager.EXTRA_ASSOCIATION, + AssociationInfo::class.java, + ) Log.d(TAG, "onActivityResult: ${associationInfo?.id}") Log.d(TAG, "onActivityResult: ${associationInfo?.displayName}") @@ -132,13 +143,12 @@ class CompanionHandler { val scanResult: ScanResult? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) - if (scanResult != null) { tmpResult?.success( ProtobufModel.DeviceAssociationInfo.newBuilder() .setMacAddress(scanResult.device.address.uppercase()) .build() - .toByteArray() + .toByteArray(), ) tmpResult = null @@ -147,4 +157,4 @@ class CompanionHandler { null } } -} \ No newline at end of file +} diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/DeviceConnectionHandler.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/DeviceConnectionHandler.kt index 3aacb021..9675e14d 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/DeviceConnectionHandler.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/DeviceConnectionHandler.kt @@ -1,6 +1,5 @@ package com.signify.hue.flutterreactiveble.channelhandlers -import com.signify.hue.flutterreactiveble.ProtobufModel as pb import com.signify.hue.flutterreactiveble.converters.ProtobufMessageConverter import com.signify.hue.flutterreactiveble.utils.Duration import io.flutter.plugin.common.EventChannel @@ -8,6 +7,7 @@ import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import java.util.concurrent.TimeUnit +import com.signify.hue.flutterreactiveble.ProtobufModel as pb class DeviceConnectionHandler(private val bleClient: com.signify.hue.flutterreactiveble.ble.BleClient) : EventChannel.StreamHandler { private var connectDeviceSink: EventChannel.EventSink? = null @@ -15,7 +15,10 @@ class DeviceConnectionHandler(private val bleClient: com.signify.hue.flutterreac private lateinit var connectionUpdatesDisposable: Disposable - override fun onListen(objectSink: Any?, eventSink: EventChannel.EventSink?) { + override fun onListen( + objectSink: Any?, + eventSink: EventChannel.EventSink?, + ) { eventSink?.let { connectDeviceSink = eventSink connectionUpdatesDisposable = listenToConnectionChanges() @@ -33,8 +36,8 @@ class DeviceConnectionHandler(private val bleClient: com.signify.hue.flutterreac fun connectToDevice(connectToDeviceMessage: pb.ConnectToDeviceRequest) { bleClient.connectToDevice( - connectToDeviceMessage.deviceId, - Duration(connectToDeviceMessage.timeoutInMs.toLong(), TimeUnit.MILLISECONDS) + connectToDeviceMessage.deviceId, + Duration(connectToDeviceMessage.timeoutInMs.toLong(), TimeUnit.MILLISECONDS), ) } @@ -47,7 +50,8 @@ class DeviceConnectionHandler(private val bleClient: com.signify.hue.flutterreac bleClient.disconnectAllDevices() } - private fun listenToConnectionChanges() = bleClient.connectionUpdateSubject + private fun listenToConnectionChanges() = + bleClient.connectionUpdateSubject .observeOn(AndroidSchedulers.mainThread()) .subscribe { update -> when (update) { @@ -56,7 +60,7 @@ class DeviceConnectionHandler(private val bleClient: com.signify.hue.flutterreac } is com.signify.hue.flutterreactiveble.ble.ConnectionUpdateError -> { handleDeviceConnectionUpdateResult( - converter.convertConnectionErrorToDeviceInfo(update.deviceId, update.errorMessage) + converter.convertConnectionErrorToDeviceInfo(update.deviceId, update.errorMessage), ) } } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ScanDevicesHandler.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ScanDevicesHandler.kt index cc820422..270ab0e8 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ScanDevicesHandler.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ScanDevicesHandler.kt @@ -1,7 +1,6 @@ package com.signify.hue.flutterreactiveble.channelhandlers import android.os.ParcelUuid -import com.signify.hue.flutterreactiveble.ProtobufModel as pb import com.signify.hue.flutterreactiveble.converters.ProtobufMessageConverter import com.signify.hue.flutterreactiveble.converters.UuidConverter import com.signify.hue.flutterreactiveble.model.ScanMode @@ -9,9 +8,9 @@ import com.signify.hue.flutterreactiveble.model.createScanMode import io.flutter.plugin.common.EventChannel import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable +import com.signify.hue.flutterreactiveble.ProtobufModel as pb class ScanDevicesHandler(private val bleClient: com.signify.hue.flutterreactiveble.ble.BleClient) : EventChannel.StreamHandler { - private var scanDevicesSink: EventChannel.EventSink? = null private lateinit var scanForDevicesDisposable: Disposable private val converter = ProtobufMessageConverter() @@ -20,7 +19,10 @@ class ScanDevicesHandler(private val bleClient: com.signify.hue.flutterreactiveb private var scanParameters: ScanParameters? = null } - override fun onListen(objectSink: Any?, eventSink: EventChannel.EventSink?) { + override fun onListen( + objectSink: Any?, + eventSink: EventChannel.EventSink?, + ) { eventSink?.let { scanDevicesSink = eventSink startDeviceScan() @@ -34,32 +36,36 @@ class ScanDevicesHandler(private val bleClient: com.signify.hue.flutterreactiveb private fun startDeviceScan() { scanParameters?.let { params -> - scanForDevicesDisposable = bleClient.scanForDevices(params.filter, params.mode, params.locationServiceIsMandatory) + scanForDevicesDisposable = + bleClient.scanForDevices(params.filter, params.mode, params.locationServiceIsMandatory) .observeOn(AndroidSchedulers.mainThread()) .subscribe( - { scanResult -> - handleDeviceScanResult(converter.convertScanInfo(scanResult)) - }, - { throwable -> - handleDeviceScanResult(converter.convertScanErrorInfo(throwable.message)) - } + { scanResult -> + handleDeviceScanResult(converter.convertScanInfo(scanResult)) + }, + { throwable -> + handleDeviceScanResult(converter.convertScanErrorInfo(throwable.message)) + }, ) } - ?: handleDeviceScanResult(converter.convertScanErrorInfo("Scanning parameters are not set")) + ?: handleDeviceScanResult(converter.convertScanErrorInfo("Scanning parameters are not set")) } fun stopDeviceScan() { - if (this::scanForDevicesDisposable.isInitialized) scanForDevicesDisposable.let { - if (!it.isDisposed) { - it.dispose() - scanParameters = null + if (this::scanForDevicesDisposable.isInitialized) { + scanForDevicesDisposable.let { + if (!it.isDisposed) { + it.dispose() + scanParameters = null + } } } } fun prepareScan(scanMessage: pb.ScanForDevicesRequest) { stopDeviceScan() - val filter = scanMessage.serviceUuidsList + val filter = + scanMessage.serviceUuidsList .map { ParcelUuid(UuidConverter().uuidFromByteArray(it.data.toByteArray())) } val scanMode = createScanMode(scanMessage.scanMode) scanParameters = ScanParameters(filter, scanMode, scanMessage.requireLocationServicesEnabled) diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverter.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverter.kt index d7c8bc64..164a6c31 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverter.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverter.kt @@ -9,7 +9,7 @@ import com.signify.hue.flutterreactiveble.ProtobufModel.EstablishBondingInfo.Bon import com.signify.hue.flutterreactiveble.ble.ConnectionUpdateSuccess import com.signify.hue.flutterreactiveble.ble.MtuNegotiateFailed import com.signify.hue.flutterreactiveble.ble.MtuNegotiateResult -import com.signify.hue.flutterreactiveble.ble.MtuNegotiateSuccesful +import com.signify.hue.flutterreactiveble.ble.MtuNegotiateSuccessful import com.signify.hue.flutterreactiveble.ble.RequestConnectionPriorityFailed import com.signify.hue.flutterreactiveble.ble.RequestConnectionPriorityResult import com.signify.hue.flutterreactiveble.ble.RequestConnectionPrioritySuccess @@ -25,7 +25,6 @@ import com.signify.hue.flutterreactiveble.ProtobufModel as pb @Suppress("TooManyFunctions") class ProtobufMessageConverter { - companion object { private const val positionMostSignificantBit = 2 private const val positionLeastSignificantBit = 3 @@ -41,7 +40,7 @@ class ProtobufMessageConverter { .setIsConnectable( pb.IsConnectable.newBuilder() .setCode(scanInfo.connectable.code) - .build() + .build(), ) .addAllServiceData(createServiceDataEntry(scanInfo.serviceData)) .addAllServiceUuids(createServiceUuids(scanInfo.serviceUuids)) @@ -54,7 +53,7 @@ class ProtobufMessageConverter { pb.GenericFailure.newBuilder() .setCode(ScanErrorType.UNKNOWN.code) .setMessage(errorMessage ?: "") - .build() + .build(), ) .build() @@ -66,9 +65,8 @@ class ProtobufMessageConverter { fun convertConnectionErrorToDeviceInfo( deviceId: String, - errorMessage: String? + errorMessage: String?, ): pb.DeviceInfo { - return pb.DeviceInfo.newBuilder() .setId(deviceId) .setConnectionState(ConnectionState.DISCONNECTED.code) @@ -76,14 +74,14 @@ class ProtobufMessageConverter { pb.GenericFailure.newBuilder() .setCode(ConnectionErrorType.FAILEDTOCONNECT.code) .setMessage(errorMessage ?: "") - .build() + .build(), ) .build() } fun convertClearGattCacheError( code: ClearGattCacheErrorType, - message: String? + message: String?, ): pb.ClearGattCacheInfo { val failure = pb.GenericFailure.newBuilder().setCode(code.code) message?.let(failure::setMessage) @@ -92,9 +90,8 @@ class ProtobufMessageConverter { fun convertCharacteristicInfo( request: pb.CharacteristicAddress, - value: ByteArray + value: ByteArray, ): pb.CharacteristicValueInfo { - val characteristicAddress = createCharacteristicAddress(request) return pb.CharacteristicValueInfo.newBuilder() @@ -105,30 +102,33 @@ class ProtobufMessageConverter { fun convertCharacteristicError( request: pb.CharacteristicAddress, - error: String? + error: String?, ): pb.CharacteristicValueInfo { - val characteristicAdress = createCharacteristicAddress(request) - val failure = pb.GenericFailure.newBuilder() - .setCode(CharacteristicErrorType.UNKNOWN.code) - .setMessage(error ?: "Unknown error") + val characteristicAddress = createCharacteristicAddress(request) + val failure = + pb.GenericFailure.newBuilder() + .setCode(CharacteristicErrorType.UNKNOWN.code) + .setMessage(error ?: "Unknown error") return pb.CharacteristicValueInfo.newBuilder() - .setCharacteristic(characteristicAdress) + .setCharacteristic(characteristicAddress) .setFailure(failure) .build() } fun convertWriteCharacteristicInfo( request: pb.WriteCharacteristicRequest, - error: String? + error: String?, ): pb.WriteCharacteristicInfo { - val builder = pb.WriteCharacteristicInfo.newBuilder() - .setCharacteristic(request.characteristic) + val builder = + pb.WriteCharacteristicInfo.newBuilder() + .setCharacteristic(request.characteristic) error?.let { - val failure = pb.GenericFailure.newBuilder() - .setCode(CharacteristicErrorType.UNKNOWN.code) - .setMessage(error) + val failure = + pb.GenericFailure.newBuilder() + .setCode(CharacteristicErrorType.UNKNOWN.code) + .setMessage(error) builder.setFailure(failure) } @@ -138,17 +138,17 @@ class ProtobufMessageConverter { fun convertNegotiateMtuInfo(result: MtuNegotiateResult): pb.NegotiateMtuInfo = when (result) { - is MtuNegotiateSuccesful -> pb.NegotiateMtuInfo.newBuilder() - .setDeviceId(result.deviceId) - .setMtuSize(result.size) - .build() - - is MtuNegotiateFailed -> { - - val failure = pb.GenericFailure.newBuilder() - .setCode(NegotiateMtuErrorType.UNKNOWN.code) - .setMessage(result.errorMessage) + is MtuNegotiateSuccessful -> + pb.NegotiateMtuInfo.newBuilder() + .setDeviceId(result.deviceId) + .setMtuSize(result.size) .build() + is MtuNegotiateFailed -> { + val failure = + pb.GenericFailure.newBuilder() + .setCode(NegotiateMtuErrorType.UNKNOWN.code) + .setMessage(result.errorMessage) + .build() pb.NegotiateMtuInfo.newBuilder() .setDeviceId(result.deviceId) @@ -157,19 +157,18 @@ class ProtobufMessageConverter { } } - fun convertRequestConnectionPriorityInfo( - result: RequestConnectionPriorityResult - ): pb.ChangeConnectionPriorityInfo { + fun convertRequestConnectionPriorityInfo(result: RequestConnectionPriorityResult): pb.ChangeConnectionPriorityInfo { return when (result) { - is RequestConnectionPrioritySuccess -> pb.ChangeConnectionPriorityInfo.newBuilder() - .setDeviceId(result.deviceId) - .build() - - is RequestConnectionPriorityFailed -> { - val failure = pb.GenericFailure.newBuilder() - .setCode(0) - .setMessage(result.errorMessage) + is RequestConnectionPrioritySuccess -> + pb.ChangeConnectionPriorityInfo.newBuilder() + .setDeviceId(result.deviceId) .build() + is RequestConnectionPriorityFailed -> { + val failure = + pb.GenericFailure.newBuilder() + .setCode(0) + .setMessage(result.errorMessage) + .build() pb.ChangeConnectionPriorityInfo.newBuilder() .setDeviceId(result.deviceId) @@ -181,7 +180,7 @@ class ProtobufMessageConverter { fun convertDiscoverServicesInfo( deviceId: String, - services: RxBleDeviceServices + services: RxBleDeviceServices, ): pb.DiscoverServicesInfo { return pb.DiscoverServicesInfo.newBuilder() .setDeviceId(deviceId) @@ -189,54 +188,65 @@ class ProtobufMessageConverter { .build() } + fun convertReadRssiResult(rssi: Int): pb.ReadRssiResult { + return pb.ReadRssiResult.newBuilder() + .setRssi(rssi) + .build() + } + private fun fromBluetoothGattService(gattService: BluetoothGattService): pb.DiscoveredService { return pb.DiscoveredService.newBuilder() .setServiceUuid(createUuidFromParcelUuid(gattService.uuid)) + .setServiceInstanceId(gattService.instanceId.toString()) .addAllCharacteristicUuids(gattService.characteristics.map { createUuidFromParcelUuid(it.uuid) }) - .addAllCharacteristics(gattService.characteristics.map { - val prop = it.properties - val readable = (prop and BluetoothGattCharacteristic.PROPERTY_READ) > 0 - val write = (prop and BluetoothGattCharacteristic.PROPERTY_WRITE) > 0 - val writeNoResp = - (prop and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0 - val notify = (prop and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0 - val indicate = (prop and BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0 - - pb.DiscoveredCharacteristic.newBuilder() - .setCharacteristicId(createUuidFromParcelUuid(it.uuid)) - .setServiceId(createUuidFromParcelUuid(it.service.uuid)) - .setIsReadable(readable) - .setIsWritableWithResponse(write) - .setIsWritableWithoutResponse(writeNoResp) - .setIsNotifiable(notify) - .setIsIndicatable(indicate) - .build() - }) + .addAllCharacteristics( + gattService.characteristics.map { + val prop = it.properties + val readable = (prop and BluetoothGattCharacteristic.PROPERTY_READ) > 0 + val write = (prop and BluetoothGattCharacteristic.PROPERTY_WRITE) > 0 + val writeNoResp = (prop and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0 + val notify = (prop and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0 + val indicate = (prop and BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0 + + pb.DiscoveredCharacteristic.newBuilder() + .setCharacteristicId(createUuidFromParcelUuid(it.uuid)) + .setCharacteristicInstanceId(it.instanceId.toString()) + .setServiceId(createUuidFromParcelUuid(it.service.uuid)) + .setIsReadable(readable) + .setIsWritableWithResponse(write) + .setIsWritableWithoutResponse(writeNoResp) + .setIsNotifiable(notify) + .setIsIndicatable(indicate) + .build() + }, + ) .addAllIncludedServices(gattService.includedServices.map { convertInternalService(it) }) .build() } private fun convertInternalService(gattService: BluetoothGattService): pb.DiscoveredService { - val root = pb.DiscoveredService.newBuilder() - .setServiceUuid(createUuidFromParcelUuid(gattService.uuid)) - .addAllCharacteristicUuids(gattService.characteristics.map { createUuidFromParcelUuid(it.uuid) }) - - val children = gattService.includedServices.map { - convertInternalService(it) - } + val root = + pb.DiscoveredService.newBuilder() + .setServiceUuid(createUuidFromParcelUuid(gattService.uuid)) + .addAllCharacteristicUuids(gattService.characteristics.map { createUuidFromParcelUuid(it.uuid) }) + + val children = + gattService.includedServices.map { + convertInternalService(it) + } return root.addAllIncludedServices(children).build() } - private fun createCharacteristicAddress(request: pb.CharacteristicAddress): - pb.CharacteristicAddress.Builder? { + private fun createCharacteristicAddress(request: pb.CharacteristicAddress): pb.CharacteristicAddress.Builder? { return pb.CharacteristicAddress.newBuilder() .setDeviceId(request.deviceId) .setServiceUuid(request.serviceUuid) + .setServiceInstanceId(request.serviceInstanceId) + .setCharacteristicInstanceId(request.characteristicInstanceId) .setCharacteristicUuid(request.characteristicUuid) } private fun createServiceDataEntry(serviceData: Map): List { - val serviceDataEntries = mutableListOf() // Needed ugly for-loop because we support API23 that does not support kotlin foreach @@ -245,7 +255,7 @@ class ProtobufMessageConverter { pb.ServiceDataEntry.newBuilder() .setServiceUuid(createUuidFromParcelUuid(entry.key)) .setData(ByteString.copyFrom(entry.value)) - .build() + .build(), ) } @@ -263,12 +273,13 @@ class ProtobufMessageConverter { } fun convertBondingInfo(status: Int): pb.EstablishBondingInfo { - val bondState = when (status) { - BluetoothDevice.BOND_BONDED -> BondState.BONDED - BluetoothDevice.BOND_BONDING -> BondState.BONDING - BluetoothDevice.BOND_NONE -> BondState.NONE - else -> BondState.NONE - } + val bondState = + when (status) { + BluetoothDevice.BOND_BONDED -> BondState.BONDED + BluetoothDevice.BOND_BONDING -> BondState.BONDING + BluetoothDevice.BOND_NONE -> BondState.NONE + else -> BondState.NONE + } return pb.EstablishBondingInfo.newBuilder().setStatus(bondState).build() } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverter.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverter.kt index 89a74570..a0f7cf59 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverter.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverter.kt @@ -11,7 +11,6 @@ class UuidConverter { } fun uuidFromByteArray(bytes: ByteArray): UUID { - return when (bytes.size) { byteSize16Bit -> convert16BitToUuid(bytes) byteSize32Bit -> convert32BitToUuid(bytes) @@ -22,16 +21,50 @@ class UuidConverter { @Suppress("Detekt.MagicNumber") private fun convert16BitToUuid(bytes: ByteArray): UUID { // UUID construction is retrieved from BLE corespec v5.0 page 1917 - val uuidConstruct = byteArrayOf(0x00, 0x00, bytes[0], bytes[1], 0x00, 0x00, 0x10, 0x00, - 0x80.toByte(), 0x00, 0x00, 0x80.toByte(), 0x5F, 0x9B.toByte(), 0x34, 0xFB.toByte()) + val uuidConstruct = + byteArrayOf( + 0x00, + 0x00, + bytes[0], + bytes[1], + 0x00, + 0x00, + 0x10, + 0x00, + 0x80.toByte(), + 0x00, + 0x00, + 0x80.toByte(), + 0x5F, + 0x9B.toByte(), + 0x34, + 0xFB.toByte(), + ) return convert128BitNotationToUuid(uuidConstruct) } @Suppress("Detekt.MagicNumber") private fun convert32BitToUuid(bytes: ByteArray): UUID { - val uuidConstruct = byteArrayOf(bytes[0], bytes[1], bytes[2], bytes[3], 0x00, 0x00, 0x10, 0x00, - 0x80.toByte(), 0x00, 0x00, 0x80.toByte(), 0x5F, 0x9B.toByte(), 0x34, 0xFB.toByte()) + val uuidConstruct = + byteArrayOf( + bytes[0], + bytes[1], + bytes[2], + bytes[3], + 0x00, + 0x00, + 0x10, + 0x00, + 0x80.toByte(), + 0x00, + 0x00, + 0x80.toByte(), + 0x5F, + 0x9B.toByte(), + 0x34, + 0xFB.toByte(), + ) return convert128BitNotationToUuid(uuidConstruct) } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/debugutils/PerformanceAnalyzer.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/debugutils/PerformanceAnalyzer.kt index 14bf87ae..8c105593 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/debugutils/PerformanceAnalyzer.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/debugutils/PerformanceAnalyzer.kt @@ -1,7 +1,6 @@ package com.signify.hue.flutterreactiveble.debugutils object PerformanceAnalyzer { - var timer = Pair(0, 0) fun start(startTime: Long) { diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ConnectionState.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ConnectionState.kt index b6a88a45..9be3be13 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ConnectionState.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ConnectionState.kt @@ -8,7 +8,7 @@ enum class ConnectionState(val code: Int) { CONNECTED(1), DISCONNECTING(2), DISCONNECTED(3), - UNKNOWN(4) + UNKNOWN(4), } fun RxBleConnection.RxBleConnectionState.toConnectionState(): ConnectionState = @@ -18,4 +18,4 @@ fun RxBleConnection.RxBleConnectionState.toConnectionState(): ConnectionState = "CONNECTED" -> ConnectionState.CONNECTED "DISCONNECTING" -> ConnectionState.DISCONNECTING else -> ConnectionState.UNKNOWN -} + } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ErrorType.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ErrorType.kt index 46e71118..456db908 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ErrorType.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ErrorType.kt @@ -2,21 +2,21 @@ package com.signify.hue.flutterreactiveble.model enum class ConnectionErrorType(val code: Int) { UNKNOWN(0), - FAILEDTOCONNECT(1) + FAILEDTOCONNECT(1), } enum class ClearGattCacheErrorType(val code: Int) { - UNKNOWN(0) + UNKNOWN(0), } enum class CharacteristicErrorType(val code: Int) { - UNKNOWN(0) + UNKNOWN(0), } enum class NegotiateMtuErrorType(val code: Int) { - UNKNOWN(0) + UNKNOWN(0), } enum class ScanErrorType(val code: Int) { - UNKNOWN(0) + UNKNOWN(0), } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ScanMode.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ScanMode.kt index 31ec3198..9614612f 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ScanMode.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/model/ScanMode.kt @@ -6,7 +6,7 @@ enum class ScanMode(val code: Int) { OPPORTUNISTIC(-1), LOW_POWER(0), BALANCED(1), - LOW_LATENCY(2) + LOW_LATENCY(2), } internal fun ScanMode.toScanSettings(): Int = @@ -18,10 +18,10 @@ internal fun ScanMode.toScanSettings(): Int = } internal fun createScanMode(mode: Int): ScanMode = - when (mode) { - -1 -> ScanMode.OPPORTUNISTIC - 0 -> ScanMode.LOW_POWER - 1 -> ScanMode.BALANCED - 2 -> ScanMode.LOW_LATENCY - else -> ScanMode.LOW_POWER - } + when (mode) { + -1 -> ScanMode.OPPORTUNISTIC + 0 -> ScanMode.LOW_POWER + 1 -> ScanMode.BALANCED + 2 -> ScanMode.LOW_LATENCY + else -> ScanMode.LOW_POWER + } diff --git a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/utils/BleWrapperExtensions.kt b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/utils/BleWrapperExtensions.kt index c4a120dd..13b0b9dd 100644 --- a/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/utils/BleWrapperExtensions.kt +++ b/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/utils/BleWrapperExtensions.kt @@ -10,18 +10,18 @@ import com.signify.hue.flutterreactiveble.ble.BleStatus import com.signify.hue.flutterreactiveble.ble.ConnectionPriority fun RxBleClient.State.toBleState(): BleStatus = - when (this) { - BLUETOOTH_NOT_AVAILABLE -> BleStatus.UNSUPPORTED - LOCATION_PERMISSION_NOT_GRANTED -> BleStatus.UNAUTHORIZED - BLUETOOTH_NOT_ENABLED -> BleStatus.POWERED_OFF - LOCATION_SERVICES_NOT_ENABLED -> BleStatus.LOCATION_SERVICES_DISABLED - READY -> BleStatus.READY - } + when (this) { + BLUETOOTH_NOT_AVAILABLE -> BleStatus.UNSUPPORTED + LOCATION_PERMISSION_NOT_GRANTED -> BleStatus.UNAUTHORIZED + BLUETOOTH_NOT_ENABLED -> BleStatus.POWERED_OFF + LOCATION_SERVICES_NOT_ENABLED -> BleStatus.LOCATION_SERVICES_DISABLED + READY -> BleStatus.READY + } fun Int.toConnectionPriority() = - when (this) { - 0 -> ConnectionPriority.BALANCED - 1 -> ConnectionPriority.HIGH_PERFORMACE - 2 -> ConnectionPriority.LOW_POWER - else -> ConnectionPriority.BALANCED - } + when (this) { + 0 -> ConnectionPriority.BALANCED + 1 -> ConnectionPriority.HIGH_PERFORMACE + 2 -> ConnectionPriority.LOW_POWER + else -> ConnectionPriority.BALANCED + } diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManagerTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManagerTest.kt index 564a9e0e..caca61d3 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManagerTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/BondingManagerTest.kt @@ -42,7 +42,6 @@ class BondingManagerTest { @Nested @DisplayName("Bonding => to success") inner class BondingSuccessTest { - private var receiver: CapturingSlot = CapturingSlot() @BeforeEach @@ -63,18 +62,18 @@ class BondingManagerTest { @ValueSource( ints = [ BluetoothDevice.BOND_BONDED, - BluetoothDevice.BOND_NONE - ] + BluetoothDevice.BOND_NONE, + ], ) fun createBond(bondState: Int) { val result = sut.bondWithDevice(device).test() every { deviceIntent.action }.returns(BluetoothDevice.ACTION_BOND_STATE_CHANGED) every { deviceIntent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, any()) }.returns( - bondState + bondState, ) every { deviceIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) }.returns( - bluetoothDevice + bluetoothDevice, ) receiver.captured.onReceive(context, deviceIntent) @@ -87,7 +86,6 @@ class BondingManagerTest { @Nested @DisplayName("Already bonded") inner class AlreadyBonded { - @BeforeEach fun setup() { every { bluetoothDevice.bondState }.returns(BluetoothDevice.BOND_BONDED) @@ -105,7 +103,6 @@ class BondingManagerTest { @Nested @DisplayName("Bonding Failed") inner class FailedBondingTest { - @BeforeEach fun setup() { every { bluetoothDevice.bondState }.returns(BluetoothDevice.BOND_NONE) @@ -121,4 +118,4 @@ class BondingManagerTest { assert(result.errors().first() is BondingFailedException) } } -} \ No newline at end of file +} diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnectorTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnectorTest.kt index 91a4f498..31b0e83f 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnectorTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/DeviceConnectorTest.kt @@ -20,10 +20,7 @@ import java.lang.Exception import java.util.concurrent.TimeUnit @DisplayName("DeviceConnector unit tests") - - class DeviceConnectorTest { - @MockK private lateinit var connection: RxBleConnection @@ -34,7 +31,7 @@ class DeviceConnectorTest { private lateinit var connectionQueue: ConnectionQueue @MockK - private lateinit var updateListener: (update: ConnectionUpdate) -> Unit + private lateinit var updateListener: (update: ConnectionUpdate) -> Unit private lateinit var sut: DeviceConnector private lateinit var subject: BehaviorSubject> @@ -45,28 +42,26 @@ class DeviceConnectorTest { MockKAnnotations.init(this) subject = BehaviorSubject.create() every { device.connectionState }.returns(RxBleConnection.RxBleConnectionState.DISCONNECTED) - every { device.observeConnectionStateChanges()}.returns(Observable.just(RxBleConnection.RxBleConnectionState.CONNECTED)) + every { device.observeConnectionStateChanges() }.returns(Observable.just(RxBleConnection.RxBleConnectionState.CONNECTED)) every { device.macAddress }.returns(deviceId) every { updateListener.invoke(allAny()) }.returns(Unit) - every {connectionQueue.addToQueue(any())}.returns(Unit) - every {connectionQueue.observeQueue()}.returns(subject) - every {connectionQueue.removeFromQueue(any())}.returns(Unit) + every { connectionQueue.addToQueue(any()) }.returns(Unit) + every { connectionQueue.observeQueue() }.returns(subject) + every { connectionQueue.removeFromQueue(any()) }.returns(Unit) subject.onNext(listOf(device.macAddress)) sut = DeviceConnector(device, Duration(0L, TimeUnit.MILLISECONDS), updateListener, connectionQueue) - } @AfterEach - fun teardown(){ + fun teardown() { sut.disconnectDevice(deviceId) } @Nested - @DisplayName ("Successfull connection") + @DisplayName("Successfull connection") inner class SuccesfullConnectionTest { - @BeforeEach fun setup() { every { device.establishConnection(any()) }.returns(Observable.just(connection)) @@ -74,12 +69,11 @@ class DeviceConnectorTest { @Test @DisplayName("Add device to queue") - fun addDeviceToQueue(){ + fun addDeviceToQueue() { sut.connection.test() verify(exactly = 1) { connectionQueue.addToQueue(deviceId) } } - @Test @DisplayName("Connects to device only once") fun connectOnlyOnce() { @@ -103,7 +97,6 @@ class DeviceConnectorTest { sut.connection.test() verify(exactly = 1) { updateListener.invoke(ConnectionUpdateSuccess(deviceId, ConnectionState.CONNECTED.code)) } - } @Test @@ -119,15 +112,14 @@ class DeviceConnectorTest { @Test @DisplayName("Remove device from queue") - fun removeDeviceFromQueue(){ + fun removeDeviceFromQueue() { sut.connection.test() verify(exactly = 1) { connectionQueue.removeFromQueue(deviceId) } } } - @Nested - @DisplayName ("Failed connection") + @DisplayName("Failed connection") inner class NotSuccesfullConnectionTest { private val errorMessage = "aaa" @@ -154,7 +146,7 @@ class DeviceConnectorTest { @Test @DisplayName("Remove device from queue") - fun removeDeviceFromQueue(){ + fun removeDeviceFromQueue() { sut.connection.test() verify(exactly = 1) { connectionQueue.removeFromQueue(deviceId) } } @@ -174,4 +166,3 @@ class DeviceConnectorTest { verify(exactly = 1) { updateListener.invoke(ConnectionUpdateSuccess(deviceId, ConnectionState.DISCONNECTED.code)) } } } - diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClientTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClientTest.kt index 9c0a8c0c..a3fee977 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClientTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClientTest.kt @@ -2,12 +2,14 @@ package com.signify.hue.flutterreactiveble.ble import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice.BOND_BONDED +import android.bluetooth.BluetoothGattCharacteristic import android.content.Context import com.google.common.truth.Truth.assertThat import com.polidea.rxandroidble2.RxBleClient import com.polidea.rxandroidble2.RxBleConnection import com.polidea.rxandroidble2.RxBleDevice import com.polidea.rxandroidble2.RxBleDeviceServices +import com.signify.hue.flutterreactiveble.ble.extensions.resolveCharacteristic import com.signify.hue.flutterreactiveble.ble.extensions.writeCharWithResponse import com.signify.hue.flutterreactiveble.ble.extensions.writeCharWithoutResponse import com.signify.hue.flutterreactiveble.utils.Duration @@ -32,19 +34,22 @@ import org.junit.jupiter.api.Test import java.util.UUID import java.util.concurrent.TimeUnit -private class BleClientForTesting(val bleClient: RxBleClient, appContext: Context, val deviceConnector: DeviceConnector) : ReactiveBleClient(appContext) { - +private class BleClientForTesting(val bleClient: RxBleClient, appContext: Context, val deviceConnector: DeviceConnector) : ReactiveBleClient( + appContext, +) { override fun initializeClient() { rxBleClient = bleClient activeConnections = mutableMapOf() } - override fun createDeviceConnector(device: RxBleDevice, timeout: Duration): DeviceConnector = deviceConnector + override fun createDeviceConnector( + device: RxBleDevice, + timeout: Duration, + ): DeviceConnector = deviceConnector } @DisplayName("BleClient unit tests") class ReactiveBleClientTest { - @MockK private lateinit var context: Context @@ -104,11 +109,9 @@ class ReactiveBleClientTest { subject.onComplete() } - @DisplayName("Establishing a connection") @Nested inner class EstablishConnectionTest { - @Test fun `should use deviceconnector when connecting to a device`() { sut.connectToDevice("test", testTimeout) @@ -122,36 +125,55 @@ class ReactiveBleClientTest { inner class BleOperationsTest { @Test fun `should call readcharacteristic in case the connection is established`() { - sut.readCharacteristic("test", UUID.randomUUID()).test() + every { + rxConnection.resolveCharacteristic( + any(), + any(), + ) + }.returns(Single.just(BluetoothGattCharacteristic(UUID.randomUUID(), 0, 0))) + + sut.readCharacteristic("test", UUID.randomUUID(), 11).test() - verify(exactly = 1) { rxConnection.readCharacteristic(any()) } + verify(exactly = 1) { rxConnection.readCharacteristic(any()) } } @Test fun `should not call readcharacteristic in case the connection is not established`() { subject.onNext(EstablishConnectionFailure("test", "error")) - sut.readCharacteristic("test", UUID.randomUUID()).test() + val result = sut.readCharacteristic("test", UUID.randomUUID(), 11).test() - verify(exactly = 0) { rxConnection.readCharacteristic(any()) } + assertThat(result.values().first()).isInstanceOf(CharOperationFailed::class.java) + verify(exactly = 0) { rxConnection.readCharacteristic(any()) } } @Test fun `should report failure in case reading characteristic fails`() { subject.onNext(EstablishConnectionFailure("test", "error")) - val observable = sut.readCharacteristic("test", UUID.randomUUID()).test() + val observable = sut.readCharacteristic("test", UUID.randomUUID(), 11).test() assertThat(observable.values().first()).isInstanceOf(CharOperationFailed::class.java) } @Test - fun `should incorporate the value in case readcharacteristics succeeds`() { + fun `should incorporate the value in case readcharacteristic succeeds`() { val byteMin = Byte.MIN_VALUE val byteMax = Byte.MAX_VALUE - every { rxConnection.readCharacteristic(any()) }.returns(Single.just(byteArrayOf(byteMin, byteMax))) - val observable = sut.readCharacteristic("test", UUID.randomUUID()) + every { + rxConnection.readCharacteristic( + any(), + ) + }.returns(Single.just(byteArrayOf(byteMin, byteMax))) + every { + rxConnection.resolveCharacteristic( + any(), + any(), + ) + }.returns(Single.just(BluetoothGattCharacteristic(UUID.randomUUID(), 0, 0))) + val observable = + sut.readCharacteristic("test", UUID.randomUUID(), 11) .map { result -> result as CharOperationSuccessful }.test() assertThat(observable.values().first().value).isEqualTo(listOf(byteMin, byteMax)) @@ -163,9 +185,15 @@ class ReactiveBleClientTest { val byteMax = Byte.MAX_VALUE val bytes = byteArrayOf(byteMin, byteMax) - sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), bytes).test() + every { + rxConnection.resolveCharacteristic( + any(), + any(), + ) + }.returns(Single.just(BluetoothGattCharacteristic(UUID.randomUUID(), 0, 0))) + sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), 11, bytes).test() - verify(exactly = 1) { rxConnection.writeCharWithResponse(any(), any()) } + verify(exactly = 1) { rxConnection.writeCharWithResponse(any(), any()) } } @Test @@ -174,9 +202,9 @@ class ReactiveBleClientTest { val byteMax = Byte.MAX_VALUE val bytes = byteArrayOf(byteMin, byteMax) - sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), bytes).test() + sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), 11, bytes).test() - verify(exactly = 0) { rxConnection.writeCharWithoutResponse(any(), any()) } + verify(exactly = 0) { rxConnection.writeCharWithoutResponse(any(), any()) } } @Test @@ -186,9 +214,10 @@ class ReactiveBleClientTest { val bytes = byteArrayOf(byteMin, byteMax) subject.onNext(EstablishConnectionFailure("test", "error")) - sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), bytes).test() + val result = sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), 11, bytes).test() + assertThat(result.values().first()).isInstanceOf(CharOperationFailed::class.java) - verify(exactly = 0) { rxConnection.writeCharWithResponse(any(), any()) } + verify(exactly = 0) { rxConnection.writeCharWithResponse(any(), any()) } } @Test @@ -197,9 +226,15 @@ class ReactiveBleClientTest { val byteMax = Byte.MAX_VALUE val bytes = byteArrayOf(byteMin, byteMax) - sut.writeCharacteristicWithoutResponse("test", UUID.randomUUID(), bytes).test() + every { + rxConnection.resolveCharacteristic( + any(), + any(), + ) + }.returns(Single.just(BluetoothGattCharacteristic(UUID.randomUUID(), 0, 0))) + sut.writeCharacteristicWithoutResponse("test", UUID.randomUUID(), 11, bytes).test() - verify(exactly = 1) { rxConnection.writeCharWithoutResponse(any(), any()) } + verify(exactly = 1) { rxConnection.writeCharWithoutResponse(any(), any()) } } @Test @@ -209,10 +244,10 @@ class ReactiveBleClientTest { val bytes = byteArrayOf(byteMin, byteMax) subject.onNext(EstablishConnectionFailure("test", "error")) + val result = sut.writeCharacteristicWithoutResponse("test", UUID.randomUUID(), 11, bytes).test() - sut.writeCharacteristicWithoutResponse("test", UUID.randomUUID(), bytes).test() - - verify(exactly = 0) { rxConnection.writeCharWithoutResponse(any(), any()) } + assertThat(result.values().first()).isInstanceOf(CharOperationFailed::class.java) + verify(exactly = 0) { rxConnection.writeCharWithoutResponse(any(), any()) } } @Test @@ -223,7 +258,7 @@ class ReactiveBleClientTest { subject.onNext(EstablishConnectionFailure("test", "error")) - val observable = sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), bytes).test() + val observable = sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), 11, bytes).test() assertThat(observable.values().first()).isInstanceOf(CharOperationFailed::class.java) } @@ -235,7 +270,14 @@ class ReactiveBleClientTest { val bytes = byteArrayOf(byteMin, byteMax) every { rxConnection.writeCharWithResponse(any(), any()) }.returns(Single.just(byteArrayOf(byteMin, byteMax))) - val observable = sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), bytes) + every { + rxConnection.resolveCharacteristic( + any(), + any(), + ) + }.returns(Single.just(BluetoothGattCharacteristic(UUID.randomUUID(), 0, 0))) + val observable = + sut.writeCharacteristicWithResponse("test", UUID.randomUUID(), 11, bytes) .map { result -> result as CharOperationSuccessful }.test() assertThat(observable.values().first().value).isEqualTo(bytes.toList()) @@ -245,7 +287,6 @@ class ReactiveBleClientTest { @Nested @DisplayName("Negotiate mtu") inner class NegotiateMtuTest { - @Test fun `should return mtunegotiatesuccesful in case it succeeds`() { val mtuSize = 19 @@ -253,7 +294,7 @@ class ReactiveBleClientTest { val result = sut.negotiateMtuSize("", mtuSize).test() - assertThat(result.values().first()).isInstanceOf(MtuNegotiateSuccesful::class.java) + assertThat(result.values().first()).isInstanceOf(MtuNegotiateSuccessful::class.java) } @Test @@ -267,6 +308,29 @@ class ReactiveBleClientTest { } } + @Nested + @DisplayName("Read RSSI") + inner class ReadRssiTest { + @Test + fun `should return RSSI in case it succeeds`() { + val rssi = -42 + every { rxConnection.readRssi() }.returns(Single.just(rssi)) + + val result = sut.readRssi("").test() + + assertThat(result.values().first()).isEqualTo(rssi) + } + + @Test + fun `should return error in case it fails`() { + every { rxConnection.readRssi() }.returns(Single.error(IllegalStateException("boom"))) + + val result = sut.readRssi("").test() + + assertThat(result.errors().first()).isInstanceOf(IllegalStateException::class.java) + } + } + @Nested @DisplayName("Observe status") inner class ObserveBleStatusTest { @@ -289,7 +353,6 @@ class ReactiveBleClientTest { @Test fun `starts with current state`() { - val result = sut.observeBleStatus().test() assertThat(result.values().count()).isEqualTo(2) assertThat(result.values().first()).isEqualTo(BleStatus.POWERED_OFF) @@ -299,9 +362,8 @@ class ReactiveBleClientTest { @Nested @DisplayName("Change priority") inner class ChangePriorityTest { - @Test - fun `returns prioritysuccess when completed`() { + fun `returns prioritysuccess when completed`() { val completer = Completable.fromCallable { true } every { rxConnection.requestConnectionPriority(any(), any(), any()) }.returns(completer) @@ -320,11 +382,10 @@ class ReactiveBleClientTest { @Nested @DisplayName("Discover services") inner class DiscoverServicesTest { - @BeforeEach fun setup() { every { bleDevice.bluetoothDevice }.returns(bluetoothDevice) - every {bluetoothDevice.bondState}.returns(BOND_BONDED) + every { bluetoothDevice.bondState }.returns(BOND_BONDED) } @Test diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ConnectionQueueTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ConnectionQueueTest.kt index 1ee09253..f0c8fe75 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ConnectionQueueTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/channelhandlers/ConnectionQueueTest.kt @@ -1,11 +1,10 @@ package com.signify.hue.flutterreactiveble.channelhandlers import com.google.common.truth.Truth.assertThat import io.reactivex.subjects.BehaviorSubject -import org.junit.jupiter.api.Test import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class ConnectionQueueTest { - private lateinit var sut: com.signify.hue.flutterreactiveble.ble.ConnectionQueue @BeforeEach diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverterTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverterTest.kt index 3fce209b..d7a5e5c2 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverterTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ProtobufMessageConverterTest.kt @@ -7,7 +7,7 @@ import com.signify.hue.flutterreactiveble.ProtobufModel.EstablishBondingInfo.Bon import com.signify.hue.flutterreactiveble.ble.Connectable import com.signify.hue.flutterreactiveble.ble.ConnectionUpdateSuccess import com.signify.hue.flutterreactiveble.ble.MtuNegotiateFailed -import com.signify.hue.flutterreactiveble.ble.MtuNegotiateSuccesful +import com.signify.hue.flutterreactiveble.ble.MtuNegotiateSuccessful import com.signify.hue.flutterreactiveble.ble.ScanInfo import com.signify.hue.flutterreactiveble.model.NegotiateMtuErrorType import org.junit.jupiter.api.DisplayName @@ -19,14 +19,12 @@ import java.util.UUID import java.util.stream.Stream import com.signify.hue.flutterreactiveble.ProtobufModel as pb - class ProtobufMessageConverterTest { val protobufConverter = ProtobufMessageConverter() @Nested @DisplayName("Convert to scaninfo") inner class ScanInfoTest { - @Test fun `converts scan result to DeviceDiscoveryMessage`() { val scanInfo = createScanInfo() @@ -113,7 +111,6 @@ class ProtobufMessageConverterTest { @Nested @DisplayName("Convert to deviceinfo") inner class DeviceInfoTest { - @Test fun `converts device id as parameter in device connection message`() { val deviceId = "2" @@ -126,7 +123,7 @@ class ProtobufMessageConverterTest { val result = 0 val connection = ConnectionUpdateSuccess("", result) assertThat(protobufConverter.convertToDeviceInfo(connection).connectionState).isEqualTo( - result + result, ) } } @@ -134,23 +131,17 @@ class ProtobufMessageConverterTest { @Nested @DisplayName("Convert to charinfo") inner class ConvertCharInfoTest { - @Test fun `converts to a characteristicvalueInfo object `() { val request = createCharacteristicRequest("a", UUID.randomUUID()) - assertThat( - protobufConverter.convertCharacteristicInfo( - request.characteristic, - byteArrayOf(1) - ) - ) + assertThat(protobufConverter.convertCharacteristicInfo(request.characteristic, byteArrayOf(1))) .isInstanceOf(pb.CharacteristicValueInfo::class.java) } @Test fun `converts a char value and request into a characteristic info value `() { - val request = createCharacteristicRequest("a", UUID.randomUUID()) + val request = createCharacteristicRequest("b", UUID.randomUUID()) val expectedValue = byteArrayOf(1) val valueInfo = protobufConverter.convertCharacteristicInfo(request.characteristic, expectedValue) @@ -162,32 +153,29 @@ class ProtobufMessageConverterTest { @Nested @DisplayName("Convert to negotiatemtuinfo") inner class NegotiateMtuInfoTest { - @Test fun `converts to negotiatemtuinfo object`() { - val result = MtuNegotiateSuccesful("", 3) + val result = MtuNegotiateSuccessful("", 3) assertThat(protobufConverter.convertNegotiateMtuInfo(result)).isInstanceOf(pb.NegotiateMtuInfo::class.java) } @Test fun `converts deviceId`() { - val result = MtuNegotiateSuccesful("id", 3) + val result = MtuNegotiateSuccessful("id", 3) assertThat(protobufConverter.convertNegotiateMtuInfo(result).deviceId).isEqualTo(result.deviceId) } @Test fun `converts mtusize`() { - val result = MtuNegotiateSuccesful("id", 3) + val result = MtuNegotiateSuccessful("id", 3) assertThat(protobufConverter.convertNegotiateMtuInfo(result).mtuSize).isEqualTo(result.size) } @Test fun `sets default value for error in case no error occurred`() { - val result = MtuNegotiateSuccesful("id", 3) - assertThat(protobufConverter.convertNegotiateMtuInfo(result).failure.message).isEqualTo( - "" - ) + val result = MtuNegotiateSuccessful("id", 3) + assertThat(protobufConverter.convertNegotiateMtuInfo(result).failure.message).isEqualTo("") } @Test @@ -210,7 +198,10 @@ class ProtobufMessageConverterTest { inner class BondInfoTest { @Test @MethodSource("provideParameters") - fun `converts bonded`(bondState: BondState, androidConstant: Int) { + fun `converts bonded`( + bondState: BondState, + androidConstant: Int, + ) { assertThat(protobufConverter.convertBondingInfo(androidConstant)).isEqualTo(bondState) } @@ -218,7 +209,7 @@ class ProtobufMessageConverterTest { return Stream.of( Arguments.of(BondState.BONDED, BluetoothDevice.BOND_BONDED), Arguments.of(BondState.BONDING, BluetoothDevice.BOND_BONDING), - Arguments.of(BondState.NONE, BluetoothDevice.BOND_NONE) + Arguments.of(BondState.NONE, BluetoothDevice.BOND_NONE), ) } @@ -231,7 +222,7 @@ class ProtobufMessageConverterTest { } private fun createScanInfo(): ScanInfo { - val macAdress = "123" + val macAddress = "123" val deviceName = "Testdevice" val rssi = 200 val uuid = UUID.randomUUID() @@ -244,7 +235,7 @@ class ProtobufMessageConverterTest { val manufacturerData = "123".toByteArray() return ScanInfo( - deviceId = macAdress, + deviceId = macAddress, name = deviceName, rssi = rssi, connectable = Connectable.UNKNOWN, @@ -256,20 +247,21 @@ class ProtobufMessageConverterTest { private fun createCharacteristicRequest( deviceId: String, - serviceUuid: UUID + serviceUuid: UUID, ): pb.ReadCharacteristicRequest { val uuidConverter = UuidConverter() - val uuid = pb.Uuid.newBuilder() - .setData(ByteString.copyFrom(uuidConverter.byteArrayFromUuid(serviceUuid))) + val uuid = + pb.Uuid.newBuilder() + .setData(ByteString.copyFrom(uuidConverter.byteArrayFromUuid(serviceUuid))) - val characteristicAddress = pb.CharacteristicAddress.newBuilder() - .setDeviceId(deviceId) - .setServiceUuid(uuid) - .setCharacteristicUuid(uuid) + val characteristicAddress = + pb.CharacteristicAddress.newBuilder() + .setDeviceId(deviceId) + .setServiceUuid(uuid) + .setCharacteristicUuid(uuid) return pb.ReadCharacteristicRequest.newBuilder() .setCharacteristic(characteristicAddress) .build() } } - diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ServicesWithCharacteristicsConverterTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ServicesWithCharacteristicsConverterTest.kt index 2d509a7e..34ee6f59 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ServicesWithCharacteristicsConverterTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/ServicesWithCharacteristicsConverterTest.kt @@ -12,9 +12,7 @@ import org.junit.Test import java.util.UUID import com.signify.hue.flutterreactiveble.ProtobufModel as pb - class ServicesWithCharacteristicsConverterTest { - private val serviceUuid = UUID.randomUUID() private val characteristicUuid = UUID.randomUUID() private val internalCharacteristicUuid = UUID.randomUUID() @@ -42,7 +40,6 @@ class ServicesWithCharacteristicsConverterTest { @MockK lateinit var internalCharacteristicLevel2: BluetoothGattCharacteristic - @Before fun setUp() { MockKAnnotations.init(this) @@ -61,8 +58,11 @@ class ServicesWithCharacteristicsConverterTest { every { internalServiceLevel2.includedServices }.returns(listOf()) every { internalServiceLevel2.characteristics }.returns(listOf(internalCharacteristicLevel2)) - conversionResult = sut.convertDiscoverServicesInfo("test", - RxBleDeviceServices(listOf(service))) + conversionResult = + sut.convertDiscoverServicesInfo( + "test", + RxBleDeviceServices(listOf(service)), + ) } @Test @@ -75,11 +75,11 @@ class ServicesWithCharacteristicsConverterTest { assertThat(conversionResult.getServices(0).characteristicUuidsCount).isEqualTo(1) } - @Test fun `It converts nested internal services correctly`() { - assertThat(conversionResult.getServices(0).getIncludedServices(0) - .includedServicesCount).isEqualTo(2) + assertThat( + conversionResult.getServices(0).getIncludedServices(0) + .includedServicesCount, + ).isEqualTo(2) } } - diff --git a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverterTest.kt b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverterTest.kt index a3cf42ec..52e47d2e 100644 --- a/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverterTest.kt +++ b/packages/reactive_ble_mobile/android/src/test/kotlin/com/signify/hue/flutterreactiveble/converters/UuidConverterTest.kt @@ -2,11 +2,9 @@ package com.signify.hue.flutterreactiveble.converters import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.Test -import java.util.* - +import java.util.UUID class UuidConverterTest { - val converter = UuidConverter() @Test @@ -20,7 +18,6 @@ class UuidConverterTest { @Test fun `should be able to convert 16bit uuid`() { - val array = byteArrayOf(0xFE.toByte(), 0x0F.toByte()) val uuid = converter.uuidFromByteArray(array) assertThat(uuid.toString().toUpperCase()).isEqualTo("0000FE0F-0000-1000-8000-00805F9B34FB") @@ -28,7 +25,6 @@ class UuidConverterTest { @Test fun `should be able to convert 32bit uuid`() { - val array = byteArrayOf(0xFE.toByte(), 0x0F.toByte(), 0x0F.toByte(), 0xFE.toByte()) val uuid = converter.uuidFromByteArray(array) assertThat(uuid.toString().toUpperCase()).isEqualTo("FE0F0FFE-0000-1000-8000-00805F9B34FB") diff --git a/packages/reactive_ble_mobile/ios/Classes/BleData extras/CharacteristicInstance.swift b/packages/reactive_ble_mobile/ios/Classes/BleData extras/CharacteristicInstance.swift new file mode 100644 index 00000000..2e27e788 --- /dev/null +++ b/packages/reactive_ble_mobile/ios/Classes/BleData extras/CharacteristicInstance.swift @@ -0,0 +1,105 @@ +import class CoreBluetooth.CBUUID +import class CoreBluetooth.CBCharacteristic +import class CoreBluetooth.CBService + +struct CharacteristicInstance: Equatable { + + let id: CharacteristicID + let instanceID: CharacteristicInstanceID + let serviceID: ServiceID + let serviceInstanceID: ServiceInstanceID + let peripheralID: PeripheralID +} + +extension CharacteristicInstance { + + init(_ characteristic: CBCharacteristic) throws { + guard let service = characteristic.service + else { + throw Failure.serviceNotFound + } + + guard let peripheral = service.peripheral + else { + throw Failure.peripheralNotFound + } + + guard + // Since CBCharacteristic has no field that identifies a specific instance of a characteristic (among those with the same id), + // the index among the characteristics with the same uuid within a service is used as identification. This assumes characteristics + // aren't reordered when new charcteristics are discovered later. + let characteristicIndex = service.characteristics?.filter({ c in c.uuid == characteristic.uuid }).index(of: characteristic) + else { + throw Failure.characteristicNotFound + } + + guard + // Since CBService has no field that identifies a specific instance of a service (among those with the same id), + // the index among the services with the same uuid is used as identification. This assumes services are not reordered when + // new services are discovered later. + let serviceIndex = peripheral.services?.filter({ s in s.uuid == service.uuid }).index(of: service) + else { + throw Failure.serviceNotFound + } + + self.init( + id: characteristic.uuid, + instanceID: "\(characteristicIndex)", + serviceID: service.uuid, + serviceInstanceID: "\(serviceIndex)", + peripheralID: peripheral.identifier + ) + } + + private enum Failure: Error, CustomStringConvertible { + + case serviceNotFound + case peripheralNotFound + case characteristicNotFound + + var description: String { + switch self { + case .serviceNotFound: + return "Service not found" + case .peripheralNotFound: + return "Peripheral not found" + case .characteristicNotFound: + return "Characteristic not found" + } + } + } +} + +struct CharacteristicInstanceIDFactory { + + func make(from message: CharacteristicAddress) -> CharacteristicInstance? { + guard + message.hasCharacteristicUuid, + message.hasServiceUuid, + let peripheralID = UUID(uuidString: message.deviceID) + else { return nil } + + let characteristicID = CBUUID(data: message.characteristicUuid.data) + let serviceID = CBUUID(data: message.serviceUuid.data) + + return CharacteristicInstance( + id: characteristicID, + instanceID: message.characteristicInstanceID, + serviceID: serviceID, + serviceInstanceID: message.serviceInstanceID, + peripheralID: peripheralID + ) + } +} + +public extension CBCharacteristic { + var instanceId: Int? { + return service?.characteristics?.filter({ c in c.uuid == uuid }).index(of: self) + } +} + +public extension CBService { + var instanceId: Int? { + return peripheral?.services?.filter({ s in s.uuid == uuid }).index(of: self) + } +} diff --git a/packages/reactive_ble_mobile/ios/Classes/BleData extras/QualifiedCharacteristic.swift b/packages/reactive_ble_mobile/ios/Classes/BleData extras/QualifiedCharacteristic.swift deleted file mode 100644 index 033a047c..00000000 --- a/packages/reactive_ble_mobile/ios/Classes/BleData extras/QualifiedCharacteristic.swift +++ /dev/null @@ -1,40 +0,0 @@ -import class CoreBluetooth.CBUUID -import class CoreBluetooth.CBCharacteristic - -struct QualifiedCharacteristic: Equatable { - - let id: CharacteristicID - let serviceID: ServiceID - let peripheralID: PeripheralID -} - -extension QualifiedCharacteristic { - - init(_ characteristic: CBCharacteristic) { - self.init( - id: characteristic.uuid, - serviceID: characteristic.service?.uuid ?? ServiceID(), - peripheralID: characteristic.service?.peripheral?.identifier ?? PeripheralID(uuid: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - ) - } -} - -struct QualifiedCharacteristicIDFactory { - - func make(from message: CharacteristicAddress) -> QualifiedCharacteristic? { - guard - message.hasCharacteristicUuid, - message.hasServiceUuid, - let peripheralID = UUID(uuidString: message.deviceID) - else { return nil } - - let characteristicID = CBUUID(data: message.characteristicUuid.data) - let serviceID = CBUUID(data: message.serviceUuid.data) - - return QualifiedCharacteristic( - id: characteristicID, - serviceID: serviceID, - peripheralID: peripheralID - ) - } -} diff --git a/packages/reactive_ble_mobile/ios/Classes/BleData/bledata.pb.swift b/packages/reactive_ble_mobile/ios/Classes/BleData/bledata.pb.swift index 4b5539c7..c288516b 100644 --- a/packages/reactive_ble_mobile/ios/Classes/BleData/bledata.pb.swift +++ b/packages/reactive_ble_mobile/ios/Classes/BleData/bledata.pb.swift @@ -559,6 +559,10 @@ struct CharacteristicAddress { /// Clears the value of `characteristicUuid`. Subsequent reads from it will return its default value. mutating func clearCharacteristicUuid() {self._characteristicUuid = nil} + var serviceInstanceID: String = String() + + var characteristicInstanceID: String = String() + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -671,6 +675,8 @@ struct DiscoveredService { var characteristics: [DiscoveredCharacteristic] = [] + var serviceInstanceID: String = String() + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -711,6 +717,8 @@ struct DiscoveredCharacteristic { var isIndicatable: Bool = false + var characteristicInstanceID: String = String() + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -719,6 +727,30 @@ struct DiscoveredCharacteristic { fileprivate var _serviceID: Uuid? = nil } +struct ReadRssiRequest { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var deviceID: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ReadRssiResult { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var rssi: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + struct Uuid { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for @@ -791,6 +823,8 @@ extension DiscoverServicesRequest: @unchecked Sendable {} extension DiscoverServicesInfo: @unchecked Sendable {} extension DiscoveredService: @unchecked Sendable {} extension DiscoveredCharacteristic: @unchecked Sendable {} +extension ReadRssiRequest: @unchecked Sendable {} +extension ReadRssiResult: @unchecked Sendable {} extension Uuid: @unchecked Sendable {} extension GenericFailure: @unchecked Sendable {} extension IsConnectable: @unchecked Sendable {} @@ -1778,6 +1812,8 @@ extension CharacteristicAddress: SwiftProtobuf.Message, SwiftProtobuf._MessageIm 1: .same(proto: "deviceId"), 2: .same(proto: "serviceUuid"), 3: .same(proto: "characteristicUuid"), + 4: .same(proto: "serviceInstanceId"), + 5: .same(proto: "characteristicInstanceId"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -1789,6 +1825,8 @@ extension CharacteristicAddress: SwiftProtobuf.Message, SwiftProtobuf._MessageIm case 1: try { try decoder.decodeSingularStringField(value: &self.deviceID) }() case 2: try { try decoder.decodeSingularMessageField(value: &self._serviceUuid) }() case 3: try { try decoder.decodeSingularMessageField(value: &self._characteristicUuid) }() + case 4: try { try decoder.decodeSingularStringField(value: &self.serviceInstanceID) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.characteristicInstanceID) }() default: break } } @@ -1808,6 +1846,12 @@ extension CharacteristicAddress: SwiftProtobuf.Message, SwiftProtobuf._MessageIm try { if let v = self._characteristicUuid { try visitor.visitSingularMessageField(value: v, fieldNumber: 3) } }() + if !self.serviceInstanceID.isEmpty { + try visitor.visitSingularStringField(value: self.serviceInstanceID, fieldNumber: 4) + } + if !self.characteristicInstanceID.isEmpty { + try visitor.visitSingularStringField(value: self.characteristicInstanceID, fieldNumber: 5) + } try unknownFields.traverse(visitor: &visitor) } @@ -1815,6 +1859,8 @@ extension CharacteristicAddress: SwiftProtobuf.Message, SwiftProtobuf._MessageIm if lhs.deviceID != rhs.deviceID {return false} if lhs._serviceUuid != rhs._serviceUuid {return false} if lhs._characteristicUuid != rhs._characteristicUuid {return false} + if lhs.serviceInstanceID != rhs.serviceInstanceID {return false} + if lhs.characteristicInstanceID != rhs.characteristicInstanceID {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -2013,6 +2059,7 @@ extension DiscoveredService: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem 2: .same(proto: "characteristicUuids"), 3: .same(proto: "includedServices"), 4: .same(proto: "characteristics"), + 5: .same(proto: "serviceInstanceId"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -2025,6 +2072,7 @@ extension DiscoveredService: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem case 2: try { try decoder.decodeRepeatedMessageField(value: &self.characteristicUuids) }() case 3: try { try decoder.decodeRepeatedMessageField(value: &self.includedServices) }() case 4: try { try decoder.decodeRepeatedMessageField(value: &self.characteristics) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.serviceInstanceID) }() default: break } } @@ -2047,6 +2095,9 @@ extension DiscoveredService: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if !self.characteristics.isEmpty { try visitor.visitRepeatedMessageField(value: self.characteristics, fieldNumber: 4) } + if !self.serviceInstanceID.isEmpty { + try visitor.visitSingularStringField(value: self.serviceInstanceID, fieldNumber: 5) + } try unknownFields.traverse(visitor: &visitor) } @@ -2055,6 +2106,7 @@ extension DiscoveredService: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if lhs.characteristicUuids != rhs.characteristicUuids {return false} if lhs.includedServices != rhs.includedServices {return false} if lhs.characteristics != rhs.characteristics {return false} + if lhs.serviceInstanceID != rhs.serviceInstanceID {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -2070,6 +2122,7 @@ extension DiscoveredCharacteristic: SwiftProtobuf.Message, SwiftProtobuf._Messag 5: .same(proto: "isWritableWithoutResponse"), 6: .same(proto: "isNotifiable"), 7: .same(proto: "isIndicatable"), + 8: .same(proto: "characteristicInstanceId"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -2085,6 +2138,7 @@ extension DiscoveredCharacteristic: SwiftProtobuf.Message, SwiftProtobuf._Messag case 5: try { try decoder.decodeSingularBoolField(value: &self.isWritableWithoutResponse) }() case 6: try { try decoder.decodeSingularBoolField(value: &self.isNotifiable) }() case 7: try { try decoder.decodeSingularBoolField(value: &self.isIndicatable) }() + case 8: try { try decoder.decodeSingularStringField(value: &self.characteristicInstanceID) }() default: break } } @@ -2116,6 +2170,9 @@ extension DiscoveredCharacteristic: SwiftProtobuf.Message, SwiftProtobuf._Messag if self.isIndicatable != false { try visitor.visitSingularBoolField(value: self.isIndicatable, fieldNumber: 7) } + if !self.characteristicInstanceID.isEmpty { + try visitor.visitSingularStringField(value: self.characteristicInstanceID, fieldNumber: 8) + } try unknownFields.traverse(visitor: &visitor) } @@ -2127,6 +2184,71 @@ extension DiscoveredCharacteristic: SwiftProtobuf.Message, SwiftProtobuf._Messag if lhs.isWritableWithoutResponse != rhs.isWritableWithoutResponse {return false} if lhs.isNotifiable != rhs.isNotifiable {return false} if lhs.isIndicatable != rhs.isIndicatable {return false} + if lhs.characteristicInstanceID != rhs.characteristicInstanceID {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ReadRssiRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ReadRssiRequest" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "deviceId"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.deviceID) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.deviceID.isEmpty { + try visitor.visitSingularStringField(value: self.deviceID, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ReadRssiRequest, rhs: ReadRssiRequest) -> Bool { + if lhs.deviceID != rhs.deviceID {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ReadRssiResult: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ReadRssiResult" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "rssi"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.rssi) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.rssi != 0 { + try visitor.visitSingularInt32Field(value: self.rssi, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ReadRssiResult, rhs: ReadRssiResult) -> Bool { + if lhs.rssi != rhs.rssi {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/packages/reactive_ble_mobile/ios/Classes/Plugin/PluginController.swift b/packages/reactive_ble_mobile/ios/Classes/Plugin/PluginController.swift index fcf11263..ca4151f5 100644 --- a/packages/reactive_ble_mobile/ios/Classes/Plugin/PluginController.swift +++ b/packages/reactive_ble_mobile/ios/Classes/Plugin/PluginController.swift @@ -114,7 +114,9 @@ final class PluginController { let message = CharacteristicValueInfo.with { $0.characteristic = CharacteristicAddress.with { $0.characteristicUuid = Uuid.with { $0.data = characteristic.id.data } + $0.characteristicInstanceID = characteristic.instanceID $0.serviceUuid = Uuid.with { $0.data = characteristic.serviceID.data } + $0.serviceInstanceID = characteristic.serviceInstanceID $0.deviceID = characteristic.peripheralID.uuidString } if let value = value { @@ -134,7 +136,6 @@ final class PluginController { // In case message arrives before sink is created context.messageQueue.append(message) } - } ) @@ -316,12 +317,14 @@ final class PluginController { func makeDiscoveredService(service: CBService) -> DiscoveredService { DiscoveredService.with { $0.serviceUuid = Uuid.with { $0.data = service.uuid.data } + $0.serviceInstanceID = service.instanceId?.description ?? "" $0.characteristicUuids = (service.characteristics ?? []).map { characteristic in Uuid.with { $0.data = characteristic.uuid.data } } $0.characteristics = (service.characteristics ?? []).map { characteristic in DiscoveredCharacteristic.with { $0.characteristicID = Uuid.with {$0.data = characteristic.uuid.data} + $0.characteristicInstanceID = characteristic.instanceId?.description ?? "" if characteristic.service?.uuid.data != nil { $0.serviceID = Uuid.with {$0.data = characteristic.service!.uuid.data} } @@ -353,6 +356,57 @@ final class PluginController { } } + func getDiscoveredServices(name: String, args: DiscoverServicesRequest, completion: @escaping PlatformMethodCompletionHandler) { + guard let central = central + else { + completion(.failure(PluginError.notInitialized.asFlutterError)) + return + } + + guard let deviceID = UUID(uuidString: args.deviceID) + else { + completion(.failure(PluginError.invalidMethodCall(method: name, details: "\"deviceID\" is invalid").asFlutterError)) + return + } + + func makeDiscoveredService(service: CBService) -> DiscoveredService { + DiscoveredService.with { + $0.serviceUuid = Uuid.with { $0.data = service.uuid.data } + $0.serviceInstanceID = service.instanceId?.description ?? "" + $0.characteristicUuids = (service.characteristics ?? []).map { characteristic in + Uuid.with { $0.data = characteristic.uuid.data } + } + $0.characteristics = (service.characteristics ?? []).map { characteristic in + DiscoveredCharacteristic.with { + $0.characteristicID = Uuid.with {$0.data = characteristic.uuid.data} + $0.characteristicInstanceID = characteristic.instanceId?.description ?? "" + if characteristic.service?.uuid.data != nil { + $0.serviceID = Uuid.with {$0.data = characteristic.service!.uuid.data} + } + $0.isReadable = characteristic.properties.contains(.read) + $0.isWritableWithResponse = characteristic.properties.contains(.write) + $0.isWritableWithoutResponse = characteristic.properties.contains(.writeWithoutResponse) + $0.isNotifiable = characteristic.properties.contains(.notify) + $0.isIndicatable = characteristic.properties.contains(.indicate) + } + } + + $0.includedServices = (service.includedServices ?? []).map(makeDiscoveredService) + } + } + + do { + let peripheral = try central.peripheral(for: deviceID) + completion(.success(DiscoverServicesInfo.with { + $0.deviceID = deviceID.uuidString + $0.services = (peripheral.services ?? []).map(makeDiscoveredService) + })) + + } catch { + completion(.failure(PluginError.unknown(error).asFlutterError)) + } + } + func enableCharacteristicNotifications(name: String, args: NotifyCharacteristicRequest, completion: @escaping PlatformMethodCompletionHandler) { guard let central = central else { @@ -360,7 +414,7 @@ final class PluginController { return } - guard let characteristic = QualifiedCharacteristicIDFactory().make(from: args.characteristic) + guard let characteristic = CharacteristicInstanceIDFactory().make(from: args.characteristic) else { completion(.failure(PluginError.invalidMethodCall(method: name, details: "characteristic, service, and peripheral IDs are required").asFlutterError)) return @@ -386,7 +440,7 @@ final class PluginController { return } - guard let characteristic = QualifiedCharacteristicIDFactory().make(from: args.characteristic) + guard let characteristic = CharacteristicInstanceIDFactory().make(from: args.characteristic) else { completion(.failure(PluginError.invalidMethodCall(method: name, details: "characteristic, service, and peripheral IDs are required").asFlutterError)) return @@ -412,7 +466,7 @@ final class PluginController { return } - guard let characteristic = QualifiedCharacteristicIDFactory().make(from: args.characteristic) + guard let characteristic = CharacteristicInstanceIDFactory().make(from: args.characteristic) else { completion(.failure(PluginError.invalidMethodCall(method: name, details: "characteristic, service, and peripheral IDs are required").asFlutterError)) return @@ -447,7 +501,7 @@ final class PluginController { return } - guard let characteristic = QualifiedCharacteristicIDFactory().make(from: args.characteristic) + guard let characteristic = CharacteristicInstanceIDFactory().make(from: args.characteristic) else { completion(.failure(PluginError.invalidMethodCall(method: name, details: "characteristic, service, and peripheral IDs are required").asFlutterError)) return @@ -456,14 +510,10 @@ final class PluginController { do { try central.writeWithResponse( value: args.value, - characteristic: QualifiedCharacteristic(id: characteristic.id, serviceID: characteristic.serviceID, peripheralID: characteristic.peripheralID), + characteristic: characteristic, completion: { _, characteristic, error in let result = WriteCharacteristicInfo.with { - $0.characteristic = CharacteristicAddress.with { - $0.characteristicUuid = Uuid.with { $0.data = characteristic.id.data } - $0.serviceUuid = Uuid.with { $0.data = characteristic.serviceID.data } - $0.deviceID = characteristic.peripheralID.uuidString - } + $0.characteristic = args.characteristic if let error = error { $0.failure = GenericFailure.with { $0.code = Int32(WriteCharacteristicFailure.unknown.rawValue) @@ -495,7 +545,7 @@ final class PluginController { return } - guard let characteristic = QualifiedCharacteristicIDFactory().make(from: args.characteristic) + guard let characteristic = CharacteristicInstanceIDFactory().make(from: args.characteristic) else { completion(.failure(PluginError.invalidMethodCall(method: name, details: "characteristic, service, and peripheral IDs are required").asFlutterError)) return @@ -505,7 +555,7 @@ final class PluginController { do { try central.writeWithoutResponse( value: args.value, - characteristic: QualifiedCharacteristic(id: characteristic.id, serviceID: characteristic.serviceID, peripheralID: characteristic.peripheralID) + characteristic: characteristic ) result = WriteCharacteristicInfo.with { $0.characteristic = args.characteristic @@ -555,6 +605,50 @@ final class PluginController { completion(.success(result)) } + + func readRssi(name: String, args: ReadRssiRequest, completion: @escaping PlatformMethodCompletionHandler) { + guard let central = central + else { + completion(.failure(PluginError.notInitialized.asFlutterError)) + return + } + + guard let peripheralID = UUID(uuidString: args.deviceID) + else { + completion(.failure(PluginError.invalidMethodCall(method: name, details: "peripheral ID is required").asFlutterError)) + return + } + + do { + try central.readRssi( + for: peripheralID, + completion: papply(weak: self) { context, result in + result.iif( + success: { rssi in + let result: ReadRssiResult = ReadRssiResult.with { + $0.rssi = Int32(rssi) + } + completion(.success(result)) + }, + failure: { error in + completion(.failure(context.makeFlutterError(error: error))) + } + ) + } + ) + } catch let error { + completion(.failure(makeFlutterError(error: error))) + } + } + + // takes an error and converts it into a Flutter error + private func makeFlutterError(error: Error) -> FlutterError { + if let error = error as? PluginError { + return error.asFlutterError + } else { + return PluginError.unknown(error).asFlutterError + } + } private func reportState(_ knownState: CBManagerState? = nil) { guard let sink = stateSink diff --git a/packages/reactive_ble_mobile/ios/Classes/Plugin/SwiftReactiveBlePlugin.swift b/packages/reactive_ble_mobile/ios/Classes/Plugin/SwiftReactiveBlePlugin.swift index c08dfa51..bdf5b881 100644 --- a/packages/reactive_ble_mobile/ios/Classes/Plugin/SwiftReactiveBlePlugin.swift +++ b/packages/reactive_ble_mobile/ios/Classes/Plugin/SwiftReactiveBlePlugin.swift @@ -123,6 +123,9 @@ public class SwiftReactiveBlePlugin: NSObject, FlutterPlugin { AnyPlatformMethod(UnaryPlatformMethod(name: "discoverServices") { (name, context, args: DiscoverServicesRequest, completion) in context.discoverServices(name: name, args: args, completion: completion) }), + AnyPlatformMethod(UnaryPlatformMethod(name: "getDiscoveredServices") { (name, context, args: DiscoverServicesRequest, completion) in + context.getDiscoveredServices(name: name, args: args, completion: completion) + }), AnyPlatformMethod(UnaryPlatformMethod(name: "readNotifications") { (name, context, args: NotifyCharacteristicRequest, completion) in context.enableCharacteristicNotifications(name: name, args: args, completion: completion) }), @@ -140,6 +143,9 @@ public class SwiftReactiveBlePlugin: NSObject, FlutterPlugin { }), AnyPlatformMethod(UnaryPlatformMethod(name: "negotiateMtuSize") { (name, context, args: NegotiateMtuRequest, completion) in context.reportMaximumWriteValueLength(name: name, args: args, completion: completion) + }), + AnyPlatformMethod(UnaryPlatformMethod(name: "readRssi") { (name, context, args: ReadRssiRequest, completion) in + context.readRssi(name: name, args: args, completion: completion) }) ]) diff --git a/packages/reactive_ble_mobile/ios/Classes/Prelude/CoreBluetooth+Extensions.swift b/packages/reactive_ble_mobile/ios/Classes/Prelude/CoreBluetooth+Extensions.swift index a4c7c790..e66458fc 100644 --- a/packages/reactive_ble_mobile/ios/Classes/Prelude/CoreBluetooth+Extensions.swift +++ b/packages/reactive_ble_mobile/ios/Classes/Prelude/CoreBluetooth+Extensions.swift @@ -13,7 +13,7 @@ import class CoreBluetooth.CBPeripheral // // Thus this code shadows original property declarations in CoreBluetooth // and changes their semantics from `unsafe non-optional` to `weak optional` -// to mimic Xcode 13 behaviour. +// to mimic Xcode 13 behavior. // // - Note: This code compiles only when using Xcode 12 and below. // - SeeAlso: https://forums.swift.org/t/is-unowned-unsafe-t-weak-t-a-breaking-change/49917 diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Central.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Central.swift index d0f10683..da31d6b5 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Central.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Central.swift @@ -4,7 +4,9 @@ typealias RSSI = Int typealias PeripheralID = UUID typealias ServiceID = CBUUID +typealias ServiceInstanceID = String typealias CharacteristicID = CBUUID +typealias CharacteristicInstanceID = String typealias ServiceData = [ServiceID: Data] typealias AdvertisementData = [String: Any] @@ -16,8 +18,8 @@ final class Central { typealias ConnectionChangeHandler = (Central, CBPeripheral, ConnectionChange) -> Void typealias ServicesWithCharacteristicsDiscoveryHandler = (Central, CBPeripheral, [Error]) -> Void typealias CharacteristicNotifyCompletionHandler = (Central, Error?) -> Void - typealias CharacteristicValueUpdateHandler = (Central, QualifiedCharacteristic, Data?, Error?) -> Void - typealias CharacteristicWriteCompletionHandler = (Central, QualifiedCharacteristic, Error?) -> Void + typealias CharacteristicValueUpdateHandler = (Central, CharacteristicInstance, Data?, Error?) -> Void + typealias CharacteristicWriteCompletionHandler = (Central, CharacteristicInstance, Error?) -> Void private let onServicesWithCharacteristicsInitialDiscovery: ServicesWithCharacteristicsDiscoveryHandler @@ -31,6 +33,7 @@ final class Central { private let servicesWithCharacteristicsDiscoveryRegistry = PeripheralTaskRegistry() private let characteristicNotifyRegistry = PeripheralTaskRegistry() private let characteristicWriteRegistry = PeripheralTaskRegistry() + private let readRssiRegistry = PeripheralTaskRegistry() init( onStateChange: @escaping StateChangeHandler, @@ -82,19 +85,40 @@ final class Central { ) }, onCharacteristicNotificationStateUpdate: papply(weak: self) { central, characteristic, error in + guard let q = try? CharacteristicInstance(characteristic) + else { + return + } + central.characteristicNotifyRegistry.updateTask( - key: QualifiedCharacteristic(characteristic), + key: q, action: { $0.complete(error: error) } ) }, onCharacteristicValueUpdate: papply(weak: self) { central, characteristic, error in - onCharacteristicValueUpdate(central, QualifiedCharacteristic(characteristic), characteristic.value, error) + guard let q = try? CharacteristicInstance(characteristic) + else { + return + } + + onCharacteristicValueUpdate(central, q, characteristic.value, error) }, onCharacteristicValueWrite: papply(weak: self) { central, characteristic, error in + guard let q = try? CharacteristicInstance(characteristic) + else { + return + } + central.characteristicWriteRegistry.updateTask( - key: QualifiedCharacteristic(characteristic), + key: q, action: { $0.handleWrite(error: error) } ) + }, + onReadRssi: papply(weak: self) { central, peripheral, rssi, error in + central.readRssiRegistry.updateTask( + key: peripheral.identifier, + action: { $0.handleReadRssi(rssi: rssi, error: error) } + ) } ) self.centralManager = CBCentralManager( @@ -188,6 +212,10 @@ final class Central { ) } + func peripheral(for peripheralID: PeripheralID) throws -> CBPeripheral { + return try resolve(connected: peripheralID) + } + private func discoverServicesWithCharacteristics( for peripheral: CBPeripheral, discover servicesWithCharacteristicsToDiscover: ServicesWithCharacteristicsToDiscover, @@ -206,15 +234,15 @@ final class Central { ) } - func turnNotifications(_ state: OnOff, for qualifiedCharacteristic: QualifiedCharacteristic, completion: @escaping CharacteristicNotifyCompletionHandler) throws { - let characteristic = try resolve(characteristic: qualifiedCharacteristic) + func turnNotifications(_ state: OnOff, for characteristicInstance: CharacteristicInstance, completion: @escaping CharacteristicNotifyCompletionHandler) throws { + let characteristic = try resolve(characteristic: characteristicInstance) guard [CBCharacteristicProperties.notify, .notifyEncryptionRequired, .indicate, .indicateEncryptionRequired] .contains(where: characteristic.properties.contains) - else { throw Failure.notificationsNotSupported(qualifiedCharacteristic) } + else { throw Failure.notificationsNotSupported(characteristicInstance) } characteristicNotifyRegistry.registerTask( - key: qualifiedCharacteristic, + key: characteristicInstance, params: .init(state: state), completion: papply(weak: self) { central, result in completion(central, result) @@ -222,62 +250,63 @@ final class Central { ) characteristicNotifyRegistry.updateTask( - key: qualifiedCharacteristic, + key: characteristicInstance, action: { $0.start(characteristic: characteristic) } ) } - func read(characteristic qualifiedCharacteristic: QualifiedCharacteristic) throws { - let characteristic = try resolve(characteristic: qualifiedCharacteristic) + func read(characteristic characteristicInstance: CharacteristicInstance) throws { + let characteristic = try resolve(characteristic: characteristicInstance) guard characteristic.properties.contains(.read) - else { throw Failure.notReadable(qualifiedCharacteristic) } + else { throw Failure.notReadable(characteristicInstance) } guard let peripheral = characteristic.service?.peripheral - else { throw Failure.peripheralIsUnknown(qualifiedCharacteristic.peripheralID) } + else { throw Failure.peripheralIsUnknown(characteristicInstance.peripheralID) } peripheral.readValue(for: characteristic) - } func writeWithResponse( value: Data, - characteristic qualifiedCharacteristic: QualifiedCharacteristic, + characteristic characteristicInstance: CharacteristicInstance, completion: @escaping CharacteristicWriteCompletionHandler ) throws { - let characteristic = try resolve(characteristic: qualifiedCharacteristic) + let characteristic = try resolve(characteristic: characteristicInstance) guard characteristic.properties.contains(.write) - else { throw Failure.notWritable(qualifiedCharacteristic) } + else { throw Failure.notWritable(characteristicInstance) } + + let qualifiedChar = try CharacteristicInstance(characteristic) characteristicWriteRegistry.registerTask( - key: qualifiedCharacteristic, + key: qualifiedChar, params: .init(value: value), completion: papply(weak: self) { central, error in - completion(central, qualifiedCharacteristic, error) + completion(central, qualifiedChar, error) } ) guard let peripheral = characteristic.service?.peripheral - else { throw Failure.peripheralIsUnknown(qualifiedCharacteristic.peripheralID) } + else { throw Failure.peripheralIsUnknown(qualifiedChar.peripheralID) } characteristicWriteRegistry.updateTask( - key: qualifiedCharacteristic, + key: qualifiedChar, action: { $0.start(peripheral: peripheral) } ) } func writeWithoutResponse( value: Data, - characteristic qualifiedCharacteristic: QualifiedCharacteristic + characteristic characteristicInstance: CharacteristicInstance ) throws { - let characteristic = try resolve(characteristic: qualifiedCharacteristic) + let characteristic = try resolve(characteristic: characteristicInstance) guard characteristic.properties.contains(.writeWithoutResponse) - else { throw Failure.notWritable(qualifiedCharacteristic) } + else { throw Failure.notWritable(characteristicInstance) } guard let response = characteristic.service?.peripheral?.writeValue(value, for: characteristic, type: .withoutResponse) - else { throw Failure.characteristicNotFound(qualifiedCharacteristic) } + else { throw Failure.characteristicNotFound(characteristicInstance) } return response } @@ -287,6 +316,24 @@ final class Central { return peripheral.maximumWriteValueLength(for: type) } + + func readRssi(for peripheralId: PeripheralID, completion: @escaping (Failable) -> Void) throws { + let peripheral = try resolve(connected: peripheralId) + + readRssiRegistry.registerTask( + key: peripheralId, + params: .init(), + completion: completion + ) + + readRssiRegistry.updateTask( + key: peripheralId, + action: { + $0.start(peripheral: peripheral) + } + ) + } + private func eject(_ peripheral: CBPeripheral, error: Error) { peripheral.delegate = nil activePeripherals[peripheral.identifier] = nil @@ -322,14 +369,14 @@ final class Central { return peripheral } - private func resolve(characteristic qualifiedCharacteristic: QualifiedCharacteristic) throws -> CBCharacteristic { - let peripheral = try resolve(connected: qualifiedCharacteristic.peripheralID) + private func resolve(characteristic characteristicInstance: CharacteristicInstance) throws -> CBCharacteristic { + let peripheral = try resolve(connected: characteristicInstance.peripheralID) - guard let service = peripheral.services?.first(where: { $0.uuid == qualifiedCharacteristic.serviceID }) - else { throw Failure.serviceNotFound(qualifiedCharacteristic.serviceID, qualifiedCharacteristic.peripheralID) } + guard let service = peripheral.services?.filter({ $0.uuid == characteristicInstance.serviceID })[Int(characteristicInstance.serviceInstanceID) ?? 0] + else { throw Failure.serviceNotFound(characteristicInstance.serviceID, characteristicInstance.peripheralID) } - guard let characteristic = service.characteristics?.first(where: { $0.uuid == qualifiedCharacteristic.id }) - else { throw Failure.characteristicNotFound(qualifiedCharacteristic) } + guard let characteristic = service.characteristics?.filter({ $0.uuid == characteristicInstance.id })[Int(characteristicInstance.instanceID) ?? 0] + else { throw Failure.characteristicNotFound(characteristicInstance) } return characteristic } @@ -340,10 +387,10 @@ final class Central { case peripheralIsUnknown(PeripheralID) case peripheralIsNotConnected(PeripheralID) case serviceNotFound(ServiceID, PeripheralID) - case characteristicNotFound(QualifiedCharacteristic) - case notificationsNotSupported(QualifiedCharacteristic) - case notReadable(QualifiedCharacteristic) - case notWritable(QualifiedCharacteristic) + case characteristicNotFound(CharacteristicInstance) + case notificationsNotSupported(CharacteristicInstance) + case notReadable(CharacteristicInstance) + case notWritable(CharacteristicInstance) var description: String { switch self { @@ -355,14 +402,14 @@ final class Central { return "The peripheral \(peripheralID.uuidString) is not connected" case .serviceNotFound(let serviceID, let peripheralID): return "A service \(serviceID) is not found in the peripheral \(peripheralID) (make sure it has been discovered)" - case .characteristicNotFound(let qualifiedCharacteristic): - return "A characteristic \(qualifiedCharacteristic.id) is not found in the service \(qualifiedCharacteristic.serviceID) of the peripheral \(qualifiedCharacteristic.peripheralID) (make sure it has been discovered)" - case .notificationsNotSupported(let qualifiedCharacteristic): - return "The characteristic \(qualifiedCharacteristic.id) of the service \(qualifiedCharacteristic.serviceID) of the peripheral \(qualifiedCharacteristic.peripheralID) does not support either notifications or indications" - case .notReadable(let qualifiedCharacteristic): - return "The characteristic \(qualifiedCharacteristic.id) of the service \(qualifiedCharacteristic.serviceID) of the peripheral \(qualifiedCharacteristic.peripheralID) is not readable" - case .notWritable(let qualifiedCharacteristic): - return "The characteristic \(qualifiedCharacteristic.id) of the service \(qualifiedCharacteristic.serviceID) of the peripheral \(qualifiedCharacteristic.peripheralID) is not writable" + case .characteristicNotFound(let characteristicInstance): + return "A characteristic \(characteristicInstance.id) is not found in the service \(characteristicInstance.serviceID) of the peripheral \(characteristicInstance.peripheralID) (make sure it has been discovered)" + case .notificationsNotSupported(let characteristicInstance): + return "The characteristic \(characteristicInstance.id) of the service \(characteristicInstance.serviceID) of the peripheral \(characteristicInstance.peripheralID) does not support either notifications or indications" + case .notReadable(let characteristicInstance): + return "The characteristic \(characteristicInstance.id) of the service \(characteristicInstance.serviceID) of the peripheral \(characteristicInstance.peripheralID) is not readable" + case .notWritable(let characteristicInstance): + return "The characteristic \(characteristicInstance.id) of the service \(characteristicInstance.serviceID) of the peripheral \(characteristicInstance.peripheralID) is not writable" } } } diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/PeripheralDelegate.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/PeripheralDelegate.swift index 0c50851b..3b30f57f 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/PeripheralDelegate.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/PeripheralDelegate.swift @@ -7,25 +7,29 @@ final class PeripheralDelegate: NSObject, CBPeripheralDelegate { typealias CharacteristicNotificationStateUpdateHandler = (CBCharacteristic, Error?) -> Void typealias CharacteristicValueUpdateHandler = (CBCharacteristic, Error?) -> Void typealias CharacteristicValueWriteHandler = (CBCharacteristic, Error?) -> Void + typealias ReadRssiHandler = (CBPeripheral, Int, Error?) -> Void private let onServicesDiscovery: ServicesDiscoveryHandler private let onCharacteristicsDiscovery: CharacteristicsDiscoverHandler private let onCharacteristicNotificationStateUpdate: CharacteristicNotificationStateUpdateHandler private let onCharacteristicValueUpdate: CharacteristicValueUpdateHandler private let onCharacteristicValueWrite: CharacteristicValueWriteHandler + private let onReadRssi: ReadRssiHandler init( onServicesDiscovery: @escaping ServicesDiscoveryHandler, onCharacteristicsDiscovery: @escaping CharacteristicsDiscoverHandler, onCharacteristicNotificationStateUpdate: @escaping CharacteristicNotificationStateUpdateHandler, onCharacteristicValueUpdate: @escaping CharacteristicValueUpdateHandler, - onCharacteristicValueWrite: @escaping CharacteristicValueWriteHandler + onCharacteristicValueWrite: @escaping CharacteristicValueWriteHandler, + onReadRssi: @escaping ReadRssiHandler ) { self.onServicesDiscovery = onServicesDiscovery self.onCharacteristicsDiscovery = onCharacteristicsDiscovery self.onCharacteristicNotificationStateUpdate = onCharacteristicNotificationStateUpdate self.onCharacteristicValueUpdate = onCharacteristicValueUpdate self.onCharacteristicValueWrite = onCharacteristicValueWrite + self.onReadRssi = onReadRssi } func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { @@ -47,4 +51,8 @@ final class PeripheralDelegate: NSObject, CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { onCharacteristicValueWrite(characteristic, error) } + + func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) { + onReadRssi(peripheral, RSSI.intValue, error) + } } diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicNotify/CharacteristicNotifyTaskSpec.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicNotify/CharacteristicNotifyTaskSpec.swift index dcfbfbe0..8c9ecb16 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicNotify/CharacteristicNotifyTaskSpec.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicNotify/CharacteristicNotifyTaskSpec.swift @@ -1,6 +1,6 @@ struct CharacteristicNotifyTaskSpec: PeripheralTaskSpec { - typealias Key = QualifiedCharacteristic + typealias Key = CharacteristicInstance struct Params { diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskController.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskController.swift index f4ea621e..e689e6c2 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskController.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskController.swift @@ -13,8 +13,8 @@ struct CharacteristicWriteTaskController: PeripheralTaskController { func start(peripheral: CBPeripheral) -> SubjectTask { guard peripheral.state == .connected, - let service = peripheral.services?.first(where: { $0.uuid == task.key.serviceID }), - let characteristic = service.characteristics?.first(where: { $0.uuid == task.key.id }), + let service = peripheral.services?.filter({ $0.uuid == task.key.serviceID })[Int(task.key.serviceInstanceID) ?? 0], + let characteristic = service.characteristics?.filter({ $0.uuid == task.key.id })[Int(task.key.instanceID) ?? 0], characteristic.properties.contains(.write) else { return task.with(state: task.state.finished(PluginError.internalInconcictency(details: nil))) diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskSpec.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskSpec.swift index 55c247ce..a5d0d4d5 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskSpec.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/CharacteristicWrite/CharacteristicWriteTaskSpec.swift @@ -1,6 +1,6 @@ struct CharacteristicWriteTaskSpec: PeripheralTaskSpec { - typealias Key = QualifiedCharacteristic + typealias Key = CharacteristicInstance struct Params { diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskController.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskController.swift new file mode 100644 index 00000000..efb7a0fa --- /dev/null +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskController.swift @@ -0,0 +1,42 @@ +import CoreBluetooth + +struct ReadRssiTaskController: PeripheralTaskController { + typealias TaskSpec = ReadRssiTaskSpec + + private let task: SubjectTask + + init(_ task: SubjectTask) { + self.task = task + } + + func start(peripheral: CBPeripheral) -> SubjectTask { + // error if not connected + guard peripheral.state == .connected + else { + return task.with( + state: task.state.finished( + .failure(PluginError.internalInconcictency(details: nil)) + ) + ) + } + + peripheral.readRSSI() + + return task.with(state: task.state.processing(.readingRssi)) + } + + func cancel(error: Error) -> SubjectTask { + return task + .with(state: task.state.finished(.failure(error))) + } + + func handleReadRssi(rssi: Int, error: Error?) -> SubjectTask { + if let error = error { + return task + .with(state: task.state.finished(.failure(error))) + } else { + return task + .with(state: task.state.finished(.success(rssi))) + } + } +} diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskSpec.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskSpec.swift new file mode 100644 index 00000000..54d545cf --- /dev/null +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ReadRssi/ReadRssiTaskSpec.swift @@ -0,0 +1,17 @@ +struct ReadRssiTaskSpec: PeripheralTaskSpec { + typealias Key = PeripheralID + + struct Params {} + + enum Stage { + case readingRssi + } + + typealias Result = Failable + + static let tag = "READ RSSI" + + static func isMember(_ key: Key, of group: PeripheralID) -> Bool { + return key == group + } +} diff --git a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ServicesWithCharacteristicsDiscovery/ServicesWithCharacteristicsDiscoveryTaskController.swift b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ServicesWithCharacteristicsDiscovery/ServicesWithCharacteristicsDiscoveryTaskController.swift index b3158b24..dd37a4c9 100644 --- a/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ServicesWithCharacteristicsDiscovery/ServicesWithCharacteristicsDiscoveryTaskController.swift +++ b/packages/reactive_ble_mobile/ios/Classes/ReactiveBle/Tasks/ServicesWithCharacteristicsDiscovery/ServicesWithCharacteristicsDiscoveryTaskController.swift @@ -101,9 +101,9 @@ struct ServicesWithCharacteristicsDiscoveryTaskController: PeripheralTaskControl items = servicesWithCharacteristicsToDiscover .compactMap { item in knownServices? - .first(where: { $0.uuid == item.key }) - .flatMap { service in (service, item.value) } - } + .filter({ $0.uuid == item.key }) + .map { service in (service, item.value) } + }.flatMap { $0 } } items?.forEach(body) diff --git a/packages/reactive_ble_mobile/lib/src/converter/args_to_protubuf_converter.dart b/packages/reactive_ble_mobile/lib/src/converter/args_to_protubuf_converter.dart index 75360301..b36589cc 100644 --- a/packages/reactive_ble_mobile/lib/src/converter/args_to_protubuf_converter.dart +++ b/packages/reactive_ble_mobile/lib/src/converter/args_to_protubuf_converter.dart @@ -16,20 +16,20 @@ abstract class ArgsToProtobufConverter { pb.DisconnectFromDeviceRequest createDisconnectDeviceArgs(String deviceId); pb.ReadCharacteristicRequest createReadCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ); pb.WriteCharacteristicRequest createWriteCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ); pb.NotifyCharacteristicRequest createNotifyCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ); pb.NotifyNoMoreCharacteristicRequest createNotifyNoMoreCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ); pb.NegotiateMtuRequest createNegotiateMtuRequest( @@ -57,6 +57,8 @@ abstract class ArgsToProtobufConverter { pb.ClearGattCacheRequest createClearGattCacheRequest(String deviceId); pb.DiscoverServicesRequest createDiscoverServicesRequest(String deviceId); + + pb.ReadRssiRequest createReadRssiRequest(String deviceId); } class ArgsToProtobufConverterImpl implements ArgsToProtobufConverter { @@ -107,29 +109,33 @@ class ArgsToProtobufConverterImpl implements ArgsToProtobufConverter { @override pb.ReadCharacteristicRequest createReadCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { final args = pb.ReadCharacteristicRequest() ..characteristic = (pb.CharacteristicAddress() ..deviceId = characteristic.deviceId ..serviceUuid = (pb.Uuid()..data = characteristic.serviceId.data) + ..serviceInstanceId = characteristic.serviceInstanceId ..characteristicUuid = - (pb.Uuid()..data = characteristic.characteristicId.data)); + (pb.Uuid()..data = characteristic.characteristicId.data) + ..characteristicInstanceId = characteristic.characteristicInstanceId); return args; } @override pb.WriteCharacteristicRequest createWriteCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ) { final args = pb.WriteCharacteristicRequest() ..characteristic = (pb.CharacteristicAddress() ..deviceId = characteristic.deviceId ..serviceUuid = (pb.Uuid()..data = characteristic.serviceId.data) + ..serviceInstanceId = characteristic.serviceInstanceId ..characteristicUuid = - (pb.Uuid()..data = characteristic.characteristicId.data)) + (pb.Uuid()..data = characteristic.characteristicId.data) + ..characteristicInstanceId = characteristic.characteristicInstanceId) ..value = value; return args; @@ -137,28 +143,32 @@ class ArgsToProtobufConverterImpl implements ArgsToProtobufConverter { @override pb.NotifyCharacteristicRequest createNotifyCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { final args = pb.NotifyCharacteristicRequest() ..characteristic = (pb.CharacteristicAddress() ..deviceId = characteristic.deviceId ..serviceUuid = (pb.Uuid()..data = characteristic.serviceId.data) + ..serviceInstanceId = characteristic.serviceInstanceId ..characteristicUuid = - (pb.Uuid()..data = characteristic.characteristicId.data)); + (pb.Uuid()..data = characteristic.characteristicId.data) + ..characteristicInstanceId = characteristic.characteristicInstanceId); return args; } @override pb.NotifyNoMoreCharacteristicRequest createNotifyNoMoreCharacteristicRequest( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { final args = pb.NotifyNoMoreCharacteristicRequest() ..characteristic = (pb.CharacteristicAddress() ..deviceId = characteristic.deviceId ..serviceUuid = (pb.Uuid()..data = characteristic.serviceId.data) + ..serviceInstanceId = characteristic.serviceInstanceId ..characteristicUuid = - (pb.Uuid()..data = characteristic.characteristicId.data)); + (pb.Uuid()..data = characteristic.characteristicId.data) + ..characteristicInstanceId = characteristic.characteristicInstanceId); return args; } @@ -228,4 +238,10 @@ class ArgsToProtobufConverterImpl implements ArgsToProtobufConverter { final args = pb.DiscoverServicesRequest()..deviceId = deviceId; return args; } + + @override + pb.ReadRssiRequest createReadRssiRequest(String deviceId) { + final args = pb.ReadRssiRequest()..deviceId = deviceId; + return args; + } } diff --git a/packages/reactive_ble_mobile/lib/src/converter/protobuf_converter.dart b/packages/reactive_ble_mobile/lib/src/converter/protobuf_converter.dart index 2317371c..a5d7d4be 100644 --- a/packages/reactive_ble_mobile/lib/src/converter/protobuf_converter.dart +++ b/packages/reactive_ble_mobile/lib/src/converter/protobuf_converter.dart @@ -31,6 +31,8 @@ abstract class ProtobufConverter { pb.NegotiateMtuInfo.fromBuffer(data).mtuSize; List discoveredServicesFrom(List data); + + int readRssiResultFrom(List data); } class ProtobufConverterImpl implements ProtobufConverter { @@ -201,10 +203,12 @@ class ProtobufConverterImpl implements ProtobufConverter { int mtuSizeFrom(List data) => pb.NegotiateMtuInfo.fromBuffer(data).mtuSize; - QualifiedCharacteristic qualifiedCharacteristicFrom( + CharacteristicInstance qualifiedCharacteristicFrom( pb.CharacteristicAddress message) => - QualifiedCharacteristic( + CharacteristicInstance( + characteristicInstanceId: message.characteristicInstanceId, characteristicId: Uuid(message.characteristicUuid.data), + serviceInstanceId: message.serviceInstanceId, serviceId: Uuid(message.serviceUuid.data), deviceId: message.deviceId, ); @@ -234,9 +238,14 @@ class ProtobufConverterImpl implements ProtobufConverter { return message.services.map(_convertService).toList(growable: false); } + @override + int readRssiResultFrom(List data) => + pb.ReadRssiResult.fromBuffer(data).rssi; + DiscoveredService _convertService(pb.DiscoveredService service) => DiscoveredService( serviceId: Uuid(service.serviceUuid.data), + serviceInstanceId: service.serviceInstanceId, characteristicIds: service.characteristicUuids .map((c) => Uuid(c.data)) .toList(growable: false), @@ -244,6 +253,7 @@ class ProtobufConverterImpl implements ProtobufConverter { .map((c) => DiscoveredCharacteristic( characteristicId: Uuid(c.characteristicId.data), serviceId: Uuid(c.serviceId.data), + characteristicInstanceId: c.characteristicInstanceId, isReadable: c.isReadable, isWritableWithResponse: c.isWritableWithResponse, isWritableWithoutResponse: c.isWritableWithoutResponse, diff --git a/packages/reactive_ble_mobile/lib/src/generated/bledata.pb.dart b/packages/reactive_ble_mobile/lib/src/generated/bledata.pb.dart index 51b67ff7..9094419e 100644 --- a/packages/reactive_ble_mobile/lib/src/generated/bledata.pb.dart +++ b/packages/reactive_ble_mobile/lib/src/generated/bledata.pb.dart @@ -1,13 +1,9 @@ -// +/// // Generated code. Do not modify. // source: bledata.proto // // @dart = 2.12 - -// ignore_for_file: annotate_overrides, camel_case_types -// ignore_for_file: constant_identifier_names, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_final_fields -// ignore_for_file: unnecessary_import, unnecessary_this, unused_import +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core; @@ -122,18 +118,33 @@ class DeviceAssociationInfo extends $pb.GeneratedMessage { } class ScanForDevicesRequest extends $pb.GeneratedMessage { - factory ScanForDevicesRequest() => create(); - ScanForDevicesRequest._() : super(); - factory ScanForDevicesRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ScanForDevicesRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ScanForDevicesRequest', createEmptyInstance: create) - ..pc(1, _omitFieldNames ? '' : 'serviceUuids', $pb.PbFieldType.PM, protoName: 'serviceUuids', subBuilder: Uuid.create) - ..a<$core.int>(2, _omitFieldNames ? '' : 'scanMode', $pb.PbFieldType.O3, protoName: 'scanMode') - ..aOB(3, _omitFieldNames ? '' : 'requireLocationServicesEnabled', protoName: 'requireLocationServicesEnabled') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ScanForDevicesRequest', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceUuids', $pb.PbFieldType.PM, protoName: 'serviceUuids', subBuilder: Uuid.create) + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scanMode', $pb.PbFieldType.O3, protoName: 'scanMode') + ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'requireLocationServicesEnabled', protoName: 'requireLocationServicesEnabled') ..hasRequiredFields = false ; + ScanForDevicesRequest._() : super(); + factory ScanForDevicesRequest({ + $core.Iterable? serviceUuids, + $core.int? scanMode, + $core.bool? requireLocationServicesEnabled, + }) { + final _result = create(); + if (serviceUuids != null) { + _result.serviceUuids.addAll(serviceUuids); + } + if (scanMode != null) { + _result.scanMode = scanMode; + } + if (requireLocationServicesEnabled != null) { + _result.requireLocationServicesEnabled = requireLocationServicesEnabled; + } + return _result; + } + factory ScanForDevicesRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ScanForDevicesRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -143,10 +154,8 @@ class ScanForDevicesRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ScanForDevicesRequest copyWith(void Function(ScanForDevicesRequest) updates) => super.copyWith((message) => updates(message as ScanForDevicesRequest)) as ScanForDevicesRequest; - + ScanForDevicesRequest copyWith(void Function(ScanForDevicesRequest) updates) => super.copyWith((message) => updates(message as ScanForDevicesRequest)) as ScanForDevicesRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ScanForDevicesRequest create() => ScanForDevicesRequest._(); ScanForDevicesRequest createEmptyInstance() => create(); @@ -178,23 +187,58 @@ class ScanForDevicesRequest extends $pb.GeneratedMessage { } class DeviceScanInfo extends $pb.GeneratedMessage { - factory DeviceScanInfo() => create(); - DeviceScanInfo._() : super(); - factory DeviceScanInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DeviceScanInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DeviceScanInfo', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'id') - ..aOS(2, _omitFieldNames ? '' : 'name') - ..aOM(3, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) - ..pc(4, _omitFieldNames ? '' : 'serviceData', $pb.PbFieldType.PM, protoName: 'serviceData', subBuilder: ServiceDataEntry.create) - ..a<$core.int>(5, _omitFieldNames ? '' : 'rssi', $pb.PbFieldType.O3) - ..a<$core.List<$core.int>>(6, _omitFieldNames ? '' : 'manufacturerData', $pb.PbFieldType.OY, protoName: 'manufacturerData') - ..pc(7, _omitFieldNames ? '' : 'serviceUuids', $pb.PbFieldType.PM, protoName: 'serviceUuids', subBuilder: Uuid.create) - ..aOM(8, _omitFieldNames ? '' : 'isConnectable', protoName: 'isConnectable', subBuilder: IsConnectable.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeviceScanInfo', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) + ..pc(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceData', $pb.PbFieldType.PM, protoName: 'serviceData', subBuilder: ServiceDataEntry.create) + ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rssi', $pb.PbFieldType.O3) + ..a<$core.List<$core.int>>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'manufacturerData', $pb.PbFieldType.OY, protoName: 'manufacturerData') + ..pc(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceUuids', $pb.PbFieldType.PM, protoName: 'serviceUuids', subBuilder: Uuid.create) + ..aOM(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isConnectable', protoName: 'isConnectable', subBuilder: IsConnectable.create) ..hasRequiredFields = false ; + DeviceScanInfo._() : super(); + factory DeviceScanInfo({ + $core.String? id, + $core.String? name, + GenericFailure? failure, + $core.Iterable? serviceData, + $core.int? rssi, + $core.List<$core.int>? manufacturerData, + $core.Iterable? serviceUuids, + IsConnectable? isConnectable, + }) { + final _result = create(); + if (id != null) { + _result.id = id; + } + if (name != null) { + _result.name = name; + } + if (failure != null) { + _result.failure = failure; + } + if (serviceData != null) { + _result.serviceData.addAll(serviceData); + } + if (rssi != null) { + _result.rssi = rssi; + } + if (manufacturerData != null) { + _result.manufacturerData = manufacturerData; + } + if (serviceUuids != null) { + _result.serviceUuids.addAll(serviceUuids); + } + if (isConnectable != null) { + _result.isConnectable = isConnectable; + } + return _result; + } + factory DeviceScanInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DeviceScanInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -204,10 +248,8 @@ class DeviceScanInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DeviceScanInfo copyWith(void Function(DeviceScanInfo) updates) => super.copyWith((message) => updates(message as DeviceScanInfo)) as DeviceScanInfo; - + DeviceScanInfo copyWith(void Function(DeviceScanInfo) updates) => super.copyWith((message) => updates(message as DeviceScanInfo)) as DeviceScanInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DeviceScanInfo create() => DeviceScanInfo._(); DeviceScanInfo createEmptyInstance() => create(); @@ -366,18 +408,33 @@ class EstablishBondingInfo extends $pb.GeneratedMessage { } class ConnectToDeviceRequest extends $pb.GeneratedMessage { - factory ConnectToDeviceRequest() => create(); - ConnectToDeviceRequest._() : super(); - factory ConnectToDeviceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ConnectToDeviceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ConnectToDeviceRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..aOM(2, _omitFieldNames ? '' : 'servicesWithCharacteristicsToDiscover', protoName: 'servicesWithCharacteristicsToDiscover', subBuilder: ServicesWithCharacteristics.create) - ..a<$core.int>(3, _omitFieldNames ? '' : 'timeoutInMs', $pb.PbFieldType.O3, protoName: 'timeoutInMs') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ConnectToDeviceRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'servicesWithCharacteristicsToDiscover', protoName: 'servicesWithCharacteristicsToDiscover', subBuilder: ServicesWithCharacteristics.create) + ..a<$core.int>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeoutInMs', $pb.PbFieldType.O3, protoName: 'timeoutInMs') ..hasRequiredFields = false ; + ConnectToDeviceRequest._() : super(); + factory ConnectToDeviceRequest({ + $core.String? deviceId, + ServicesWithCharacteristics? servicesWithCharacteristicsToDiscover, + $core.int? timeoutInMs, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (servicesWithCharacteristicsToDiscover != null) { + _result.servicesWithCharacteristicsToDiscover = servicesWithCharacteristicsToDiscover; + } + if (timeoutInMs != null) { + _result.timeoutInMs = timeoutInMs; + } + return _result; + } + factory ConnectToDeviceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ConnectToDeviceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -387,10 +444,8 @@ class ConnectToDeviceRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ConnectToDeviceRequest copyWith(void Function(ConnectToDeviceRequest) updates) => super.copyWith((message) => updates(message as ConnectToDeviceRequest)) as ConnectToDeviceRequest; - + ConnectToDeviceRequest copyWith(void Function(ConnectToDeviceRequest) updates) => super.copyWith((message) => updates(message as ConnectToDeviceRequest)) as ConnectToDeviceRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ConnectToDeviceRequest create() => ConnectToDeviceRequest._(); ConnectToDeviceRequest createEmptyInstance() => create(); @@ -430,18 +485,33 @@ class ConnectToDeviceRequest extends $pb.GeneratedMessage { } class DeviceInfo extends $pb.GeneratedMessage { - factory DeviceInfo() => create(); - DeviceInfo._() : super(); - factory DeviceInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DeviceInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DeviceInfo', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'id') - ..a<$core.int>(2, _omitFieldNames ? '' : 'connectionState', $pb.PbFieldType.O3, protoName: 'connectionState') - ..aOM(3, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeviceInfo', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'connectionState', $pb.PbFieldType.O3, protoName: 'connectionState') + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + DeviceInfo._() : super(); + factory DeviceInfo({ + $core.String? id, + $core.int? connectionState, + GenericFailure? failure, + }) { + final _result = create(); + if (id != null) { + _result.id = id; + } + if (connectionState != null) { + _result.connectionState = connectionState; + } + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory DeviceInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DeviceInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -451,10 +521,8 @@ class DeviceInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DeviceInfo copyWith(void Function(DeviceInfo) updates) => super.copyWith((message) => updates(message as DeviceInfo)) as DeviceInfo; - + DeviceInfo copyWith(void Function(DeviceInfo) updates) => super.copyWith((message) => updates(message as DeviceInfo)) as DeviceInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DeviceInfo create() => DeviceInfo._(); DeviceInfo createEmptyInstance() => create(); @@ -588,16 +656,23 @@ class DeviceNameInfo extends $pb.GeneratedMessage { } class DisconnectFromDeviceRequest extends $pb.GeneratedMessage { - factory DisconnectFromDeviceRequest() => create(); - DisconnectFromDeviceRequest._() : super(); - factory DisconnectFromDeviceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DisconnectFromDeviceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DisconnectFromDeviceRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DisconnectFromDeviceRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') ..hasRequiredFields = false ; + DisconnectFromDeviceRequest._() : super(); + factory DisconnectFromDeviceRequest({ + $core.String? deviceId, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + return _result; + } + factory DisconnectFromDeviceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DisconnectFromDeviceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -607,10 +682,8 @@ class DisconnectFromDeviceRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DisconnectFromDeviceRequest copyWith(void Function(DisconnectFromDeviceRequest) updates) => super.copyWith((message) => updates(message as DisconnectFromDeviceRequest)) as DisconnectFromDeviceRequest; - + DisconnectFromDeviceRequest copyWith(void Function(DisconnectFromDeviceRequest) updates) => super.copyWith((message) => updates(message as DisconnectFromDeviceRequest)) as DisconnectFromDeviceRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DisconnectFromDeviceRequest create() => DisconnectFromDeviceRequest._(); DisconnectFromDeviceRequest createEmptyInstance() => create(); @@ -630,16 +703,23 @@ class DisconnectFromDeviceRequest extends $pb.GeneratedMessage { } class ClearGattCacheRequest extends $pb.GeneratedMessage { - factory ClearGattCacheRequest() => create(); - ClearGattCacheRequest._() : super(); - factory ClearGattCacheRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ClearGattCacheRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ClearGattCacheRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ClearGattCacheRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') ..hasRequiredFields = false ; + ClearGattCacheRequest._() : super(); + factory ClearGattCacheRequest({ + $core.String? deviceId, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + return _result; + } + factory ClearGattCacheRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ClearGattCacheRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -649,10 +729,8 @@ class ClearGattCacheRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ClearGattCacheRequest copyWith(void Function(ClearGattCacheRequest) updates) => super.copyWith((message) => updates(message as ClearGattCacheRequest)) as ClearGattCacheRequest; - + ClearGattCacheRequest copyWith(void Function(ClearGattCacheRequest) updates) => super.copyWith((message) => updates(message as ClearGattCacheRequest)) as ClearGattCacheRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ClearGattCacheRequest create() => ClearGattCacheRequest._(); ClearGattCacheRequest createEmptyInstance() => create(); @@ -672,16 +750,23 @@ class ClearGattCacheRequest extends $pb.GeneratedMessage { } class ClearGattCacheInfo extends $pb.GeneratedMessage { - factory ClearGattCacheInfo() => create(); - ClearGattCacheInfo._() : super(); - factory ClearGattCacheInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ClearGattCacheInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ClearGattCacheInfo', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ClearGattCacheInfo', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + ClearGattCacheInfo._() : super(); + factory ClearGattCacheInfo({ + GenericFailure? failure, + }) { + final _result = create(); + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory ClearGattCacheInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ClearGattCacheInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -691,10 +776,8 @@ class ClearGattCacheInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ClearGattCacheInfo copyWith(void Function(ClearGattCacheInfo) updates) => super.copyWith((message) => updates(message as ClearGattCacheInfo)) as ClearGattCacheInfo; - + ClearGattCacheInfo copyWith(void Function(ClearGattCacheInfo) updates) => super.copyWith((message) => updates(message as ClearGattCacheInfo)) as ClearGattCacheInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ClearGattCacheInfo create() => ClearGattCacheInfo._(); ClearGattCacheInfo createEmptyInstance() => create(); @@ -716,16 +799,23 @@ class ClearGattCacheInfo extends $pb.GeneratedMessage { } class NotifyCharacteristicRequest extends $pb.GeneratedMessage { - factory NotifyCharacteristicRequest() => create(); - NotifyCharacteristicRequest._() : super(); - factory NotifyCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NotifyCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NotifyCharacteristicRequest', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NotifyCharacteristicRequest', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) ..hasRequiredFields = false ; + NotifyCharacteristicRequest._() : super(); + factory NotifyCharacteristicRequest({ + CharacteristicAddress? characteristic, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + return _result; + } + factory NotifyCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NotifyCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -735,10 +825,8 @@ class NotifyCharacteristicRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - NotifyCharacteristicRequest copyWith(void Function(NotifyCharacteristicRequest) updates) => super.copyWith((message) => updates(message as NotifyCharacteristicRequest)) as NotifyCharacteristicRequest; - + NotifyCharacteristicRequest copyWith(void Function(NotifyCharacteristicRequest) updates) => super.copyWith((message) => updates(message as NotifyCharacteristicRequest)) as NotifyCharacteristicRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static NotifyCharacteristicRequest create() => NotifyCharacteristicRequest._(); NotifyCharacteristicRequest createEmptyInstance() => create(); @@ -760,16 +848,23 @@ class NotifyCharacteristicRequest extends $pb.GeneratedMessage { } class NotifyNoMoreCharacteristicRequest extends $pb.GeneratedMessage { - factory NotifyNoMoreCharacteristicRequest() => create(); - NotifyNoMoreCharacteristicRequest._() : super(); - factory NotifyNoMoreCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NotifyNoMoreCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NotifyNoMoreCharacteristicRequest', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NotifyNoMoreCharacteristicRequest', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) ..hasRequiredFields = false ; + NotifyNoMoreCharacteristicRequest._() : super(); + factory NotifyNoMoreCharacteristicRequest({ + CharacteristicAddress? characteristic, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + return _result; + } + factory NotifyNoMoreCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NotifyNoMoreCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -779,10 +874,8 @@ class NotifyNoMoreCharacteristicRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - NotifyNoMoreCharacteristicRequest copyWith(void Function(NotifyNoMoreCharacteristicRequest) updates) => super.copyWith((message) => updates(message as NotifyNoMoreCharacteristicRequest)) as NotifyNoMoreCharacteristicRequest; - + NotifyNoMoreCharacteristicRequest copyWith(void Function(NotifyNoMoreCharacteristicRequest) updates) => super.copyWith((message) => updates(message as NotifyNoMoreCharacteristicRequest)) as NotifyNoMoreCharacteristicRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static NotifyNoMoreCharacteristicRequest create() => NotifyNoMoreCharacteristicRequest._(); NotifyNoMoreCharacteristicRequest createEmptyInstance() => create(); @@ -804,16 +897,23 @@ class NotifyNoMoreCharacteristicRequest extends $pb.GeneratedMessage { } class ReadCharacteristicRequest extends $pb.GeneratedMessage { - factory ReadCharacteristicRequest() => create(); - ReadCharacteristicRequest._() : super(); - factory ReadCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ReadCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ReadCharacteristicRequest', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ReadCharacteristicRequest', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) ..hasRequiredFields = false ; + ReadCharacteristicRequest._() : super(); + factory ReadCharacteristicRequest({ + CharacteristicAddress? characteristic, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + return _result; + } + factory ReadCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ReadCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -823,10 +923,8 @@ class ReadCharacteristicRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ReadCharacteristicRequest copyWith(void Function(ReadCharacteristicRequest) updates) => super.copyWith((message) => updates(message as ReadCharacteristicRequest)) as ReadCharacteristicRequest; - + ReadCharacteristicRequest copyWith(void Function(ReadCharacteristicRequest) updates) => super.copyWith((message) => updates(message as ReadCharacteristicRequest)) as ReadCharacteristicRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ReadCharacteristicRequest create() => ReadCharacteristicRequest._(); ReadCharacteristicRequest createEmptyInstance() => create(); @@ -848,18 +946,33 @@ class ReadCharacteristicRequest extends $pb.GeneratedMessage { } class CharacteristicValueInfo extends $pb.GeneratedMessage { - factory CharacteristicValueInfo() => create(); - CharacteristicValueInfo._() : super(); - factory CharacteristicValueInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CharacteristicValueInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CharacteristicValueInfo', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) - ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) - ..aOM(3, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CharacteristicValueInfo', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value', $pb.PbFieldType.OY) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + CharacteristicValueInfo._() : super(); + factory CharacteristicValueInfo({ + CharacteristicAddress? characteristic, + $core.List<$core.int>? value, + GenericFailure? failure, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + if (value != null) { + _result.value = value; + } + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory CharacteristicValueInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CharacteristicValueInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -869,10 +982,8 @@ class CharacteristicValueInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CharacteristicValueInfo copyWith(void Function(CharacteristicValueInfo) updates) => super.copyWith((message) => updates(message as CharacteristicValueInfo)) as CharacteristicValueInfo; - + CharacteristicValueInfo copyWith(void Function(CharacteristicValueInfo) updates) => super.copyWith((message) => updates(message as CharacteristicValueInfo)) as CharacteristicValueInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static CharacteristicValueInfo create() => CharacteristicValueInfo._(); CharacteristicValueInfo createEmptyInstance() => create(); @@ -914,17 +1025,28 @@ class CharacteristicValueInfo extends $pb.GeneratedMessage { } class WriteCharacteristicRequest extends $pb.GeneratedMessage { - factory WriteCharacteristicRequest() => create(); - WriteCharacteristicRequest._() : super(); - factory WriteCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WriteCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'WriteCharacteristicRequest', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) - ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WriteCharacteristicRequest', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value', $pb.PbFieldType.OY) ..hasRequiredFields = false ; + WriteCharacteristicRequest._() : super(); + factory WriteCharacteristicRequest({ + CharacteristicAddress? characteristic, + $core.List<$core.int>? value, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + if (value != null) { + _result.value = value; + } + return _result; + } + factory WriteCharacteristicRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory WriteCharacteristicRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -934,10 +1056,8 @@ class WriteCharacteristicRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WriteCharacteristicRequest copyWith(void Function(WriteCharacteristicRequest) updates) => super.copyWith((message) => updates(message as WriteCharacteristicRequest)) as WriteCharacteristicRequest; - + WriteCharacteristicRequest copyWith(void Function(WriteCharacteristicRequest) updates) => super.copyWith((message) => updates(message as WriteCharacteristicRequest)) as WriteCharacteristicRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static WriteCharacteristicRequest create() => WriteCharacteristicRequest._(); WriteCharacteristicRequest createEmptyInstance() => create(); @@ -968,17 +1088,28 @@ class WriteCharacteristicRequest extends $pb.GeneratedMessage { } class WriteCharacteristicInfo extends $pb.GeneratedMessage { - factory WriteCharacteristicInfo() => create(); - WriteCharacteristicInfo._() : super(); - factory WriteCharacteristicInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WriteCharacteristicInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'WriteCharacteristicInfo', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) - ..aOM(3, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WriteCharacteristicInfo', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristic', subBuilder: CharacteristicAddress.create) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + WriteCharacteristicInfo._() : super(); + factory WriteCharacteristicInfo({ + CharacteristicAddress? characteristic, + GenericFailure? failure, + }) { + final _result = create(); + if (characteristic != null) { + _result.characteristic = characteristic; + } + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory WriteCharacteristicInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory WriteCharacteristicInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -988,10 +1119,8 @@ class WriteCharacteristicInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WriteCharacteristicInfo copyWith(void Function(WriteCharacteristicInfo) updates) => super.copyWith((message) => updates(message as WriteCharacteristicInfo)) as WriteCharacteristicInfo; - + WriteCharacteristicInfo copyWith(void Function(WriteCharacteristicInfo) updates) => super.copyWith((message) => updates(message as WriteCharacteristicInfo)) as WriteCharacteristicInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static WriteCharacteristicInfo create() => WriteCharacteristicInfo._(); WriteCharacteristicInfo createEmptyInstance() => create(); @@ -1024,17 +1153,28 @@ class WriteCharacteristicInfo extends $pb.GeneratedMessage { } class NegotiateMtuRequest extends $pb.GeneratedMessage { - factory NegotiateMtuRequest() => create(); - NegotiateMtuRequest._() : super(); - factory NegotiateMtuRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NegotiateMtuRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NegotiateMtuRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..a<$core.int>(2, _omitFieldNames ? '' : 'mtuSize', $pb.PbFieldType.O3, protoName: 'mtuSize') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NegotiateMtuRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mtuSize', $pb.PbFieldType.O3, protoName: 'mtuSize') ..hasRequiredFields = false ; + NegotiateMtuRequest._() : super(); + factory NegotiateMtuRequest({ + $core.String? deviceId, + $core.int? mtuSize, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (mtuSize != null) { + _result.mtuSize = mtuSize; + } + return _result; + } + factory NegotiateMtuRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NegotiateMtuRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1044,10 +1184,8 @@ class NegotiateMtuRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - NegotiateMtuRequest copyWith(void Function(NegotiateMtuRequest) updates) => super.copyWith((message) => updates(message as NegotiateMtuRequest)) as NegotiateMtuRequest; - + NegotiateMtuRequest copyWith(void Function(NegotiateMtuRequest) updates) => super.copyWith((message) => updates(message as NegotiateMtuRequest)) as NegotiateMtuRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static NegotiateMtuRequest create() => NegotiateMtuRequest._(); NegotiateMtuRequest createEmptyInstance() => create(); @@ -1076,18 +1214,33 @@ class NegotiateMtuRequest extends $pb.GeneratedMessage { } class NegotiateMtuInfo extends $pb.GeneratedMessage { - factory NegotiateMtuInfo() => create(); - NegotiateMtuInfo._() : super(); - factory NegotiateMtuInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NegotiateMtuInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NegotiateMtuInfo', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..a<$core.int>(2, _omitFieldNames ? '' : 'mtuSize', $pb.PbFieldType.O3, protoName: 'mtuSize') - ..aOM(3, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NegotiateMtuInfo', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mtuSize', $pb.PbFieldType.O3, protoName: 'mtuSize') + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + NegotiateMtuInfo._() : super(); + factory NegotiateMtuInfo({ + $core.String? deviceId, + $core.int? mtuSize, + GenericFailure? failure, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (mtuSize != null) { + _result.mtuSize = mtuSize; + } + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory NegotiateMtuInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NegotiateMtuInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1097,10 +1250,8 @@ class NegotiateMtuInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - NegotiateMtuInfo copyWith(void Function(NegotiateMtuInfo) updates) => super.copyWith((message) => updates(message as NegotiateMtuInfo)) as NegotiateMtuInfo; - + NegotiateMtuInfo copyWith(void Function(NegotiateMtuInfo) updates) => super.copyWith((message) => updates(message as NegotiateMtuInfo)) as NegotiateMtuInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static NegotiateMtuInfo create() => NegotiateMtuInfo._(); NegotiateMtuInfo createEmptyInstance() => create(); @@ -1140,16 +1291,23 @@ class NegotiateMtuInfo extends $pb.GeneratedMessage { } class BleStatusInfo extends $pb.GeneratedMessage { - factory BleStatusInfo() => create(); - BleStatusInfo._() : super(); - factory BleStatusInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory BleStatusInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleStatusInfo', createEmptyInstance: create) - ..a<$core.int>(1, _omitFieldNames ? '' : 'status', $pb.PbFieldType.O3) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BleStatusInfo', createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'status', $pb.PbFieldType.O3) ..hasRequiredFields = false ; + BleStatusInfo._() : super(); + factory BleStatusInfo({ + $core.int? status, + }) { + final _result = create(); + if (status != null) { + _result.status = status; + } + return _result; + } + factory BleStatusInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BleStatusInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1159,10 +1317,8 @@ class BleStatusInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - BleStatusInfo copyWith(void Function(BleStatusInfo) updates) => super.copyWith((message) => updates(message as BleStatusInfo)) as BleStatusInfo; - + BleStatusInfo copyWith(void Function(BleStatusInfo) updates) => super.copyWith((message) => updates(message as BleStatusInfo)) as BleStatusInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static BleStatusInfo create() => BleStatusInfo._(); BleStatusInfo createEmptyInstance() => create(); @@ -1182,17 +1338,28 @@ class BleStatusInfo extends $pb.GeneratedMessage { } class ChangeConnectionPriorityRequest extends $pb.GeneratedMessage { - factory ChangeConnectionPriorityRequest() => create(); - ChangeConnectionPriorityRequest._() : super(); - factory ChangeConnectionPriorityRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ChangeConnectionPriorityRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ChangeConnectionPriorityRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..a<$core.int>(2, _omitFieldNames ? '' : 'priority', $pb.PbFieldType.O3) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ChangeConnectionPriorityRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'priority', $pb.PbFieldType.O3) ..hasRequiredFields = false ; + ChangeConnectionPriorityRequest._() : super(); + factory ChangeConnectionPriorityRequest({ + $core.String? deviceId, + $core.int? priority, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (priority != null) { + _result.priority = priority; + } + return _result; + } + factory ChangeConnectionPriorityRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChangeConnectionPriorityRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1202,10 +1369,8 @@ class ChangeConnectionPriorityRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ChangeConnectionPriorityRequest copyWith(void Function(ChangeConnectionPriorityRequest) updates) => super.copyWith((message) => updates(message as ChangeConnectionPriorityRequest)) as ChangeConnectionPriorityRequest; - + ChangeConnectionPriorityRequest copyWith(void Function(ChangeConnectionPriorityRequest) updates) => super.copyWith((message) => updates(message as ChangeConnectionPriorityRequest)) as ChangeConnectionPriorityRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ChangeConnectionPriorityRequest create() => ChangeConnectionPriorityRequest._(); ChangeConnectionPriorityRequest createEmptyInstance() => create(); @@ -1234,17 +1399,28 @@ class ChangeConnectionPriorityRequest extends $pb.GeneratedMessage { } class ChangeConnectionPriorityInfo extends $pb.GeneratedMessage { - factory ChangeConnectionPriorityInfo() => create(); - ChangeConnectionPriorityInfo._() : super(); - factory ChangeConnectionPriorityInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ChangeConnectionPriorityInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ChangeConnectionPriorityInfo', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..aOM(2, _omitFieldNames ? '' : 'failure', subBuilder: GenericFailure.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ChangeConnectionPriorityInfo', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'failure', subBuilder: GenericFailure.create) ..hasRequiredFields = false ; + ChangeConnectionPriorityInfo._() : super(); + factory ChangeConnectionPriorityInfo({ + $core.String? deviceId, + GenericFailure? failure, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (failure != null) { + _result.failure = failure; + } + return _result; + } + factory ChangeConnectionPriorityInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChangeConnectionPriorityInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1254,10 +1430,8 @@ class ChangeConnectionPriorityInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ChangeConnectionPriorityInfo copyWith(void Function(ChangeConnectionPriorityInfo) updates) => super.copyWith((message) => updates(message as ChangeConnectionPriorityInfo)) as ChangeConnectionPriorityInfo; - + ChangeConnectionPriorityInfo copyWith(void Function(ChangeConnectionPriorityInfo) updates) => super.copyWith((message) => updates(message as ChangeConnectionPriorityInfo)) as ChangeConnectionPriorityInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ChangeConnectionPriorityInfo create() => ChangeConnectionPriorityInfo._(); ChangeConnectionPriorityInfo createEmptyInstance() => create(); @@ -1288,18 +1462,43 @@ class ChangeConnectionPriorityInfo extends $pb.GeneratedMessage { } class CharacteristicAddress extends $pb.GeneratedMessage { - factory CharacteristicAddress() => create(); - CharacteristicAddress._() : super(); - factory CharacteristicAddress.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CharacteristicAddress.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CharacteristicAddress', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..aOM(2, _omitFieldNames ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) - ..aOM(3, _omitFieldNames ? '' : 'characteristicUuid', protoName: 'characteristicUuid', subBuilder: Uuid.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CharacteristicAddress', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristicUuid', protoName: 'characteristicUuid', subBuilder: Uuid.create) + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceInstanceId', protoName: 'serviceInstanceId') + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristicInstanceId', protoName: 'characteristicInstanceId') ..hasRequiredFields = false ; + CharacteristicAddress._() : super(); + factory CharacteristicAddress({ + $core.String? deviceId, + Uuid? serviceUuid, + Uuid? characteristicUuid, + $core.String? serviceInstanceId, + $core.String? characteristicInstanceId, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (serviceUuid != null) { + _result.serviceUuid = serviceUuid; + } + if (characteristicUuid != null) { + _result.characteristicUuid = characteristicUuid; + } + if (serviceInstanceId != null) { + _result.serviceInstanceId = serviceInstanceId; + } + if (characteristicInstanceId != null) { + _result.characteristicInstanceId = characteristicInstanceId; + } + return _result; + } + factory CharacteristicAddress.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CharacteristicAddress.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1309,10 +1508,8 @@ class CharacteristicAddress extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CharacteristicAddress copyWith(void Function(CharacteristicAddress) updates) => super.copyWith((message) => updates(message as CharacteristicAddress)) as CharacteristicAddress; - + CharacteristicAddress copyWith(void Function(CharacteristicAddress) updates) => super.copyWith((message) => updates(message as CharacteristicAddress)) as CharacteristicAddress; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static CharacteristicAddress create() => CharacteristicAddress._(); CharacteristicAddress createEmptyInstance() => create(); @@ -1351,20 +1548,49 @@ class CharacteristicAddress extends $pb.GeneratedMessage { void clearCharacteristicUuid() => clearField(3); @$pb.TagNumber(3) Uuid ensureCharacteristicUuid() => $_ensure(2); + + @$pb.TagNumber(4) + $core.String get serviceInstanceId => $_getSZ(3); + @$pb.TagNumber(4) + set serviceInstanceId($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasServiceInstanceId() => $_has(3); + @$pb.TagNumber(4) + void clearServiceInstanceId() => clearField(4); + + @$pb.TagNumber(5) + $core.String get characteristicInstanceId => $_getSZ(4); + @$pb.TagNumber(5) + set characteristicInstanceId($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasCharacteristicInstanceId() => $_has(4); + @$pb.TagNumber(5) + void clearCharacteristicInstanceId() => clearField(5); } class ServiceDataEntry extends $pb.GeneratedMessage { - factory ServiceDataEntry() => create(); - ServiceDataEntry._() : super(); - factory ServiceDataEntry.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ServiceDataEntry.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ServiceDataEntry', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) - ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'data', $pb.PbFieldType.OY) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ServiceDataEntry', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) + ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) ..hasRequiredFields = false ; + ServiceDataEntry._() : super(); + factory ServiceDataEntry({ + Uuid? serviceUuid, + $core.List<$core.int>? data, + }) { + final _result = create(); + if (serviceUuid != null) { + _result.serviceUuid = serviceUuid; + } + if (data != null) { + _result.data = data; + } + return _result; + } + factory ServiceDataEntry.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ServiceDataEntry.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1374,10 +1600,8 @@ class ServiceDataEntry extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ServiceDataEntry copyWith(void Function(ServiceDataEntry) updates) => super.copyWith((message) => updates(message as ServiceDataEntry)) as ServiceDataEntry; - + ServiceDataEntry copyWith(void Function(ServiceDataEntry) updates) => super.copyWith((message) => updates(message as ServiceDataEntry)) as ServiceDataEntry; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ServiceDataEntry create() => ServiceDataEntry._(); ServiceDataEntry createEmptyInstance() => create(); @@ -1408,16 +1632,23 @@ class ServiceDataEntry extends $pb.GeneratedMessage { } class ServicesWithCharacteristics extends $pb.GeneratedMessage { - factory ServicesWithCharacteristics() => create(); - ServicesWithCharacteristics._() : super(); - factory ServicesWithCharacteristics.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ServicesWithCharacteristics.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ServicesWithCharacteristics', createEmptyInstance: create) - ..pc(1, _omitFieldNames ? '' : 'items', $pb.PbFieldType.PM, subBuilder: ServiceWithCharacteristics.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ServicesWithCharacteristics', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: ServiceWithCharacteristics.create) ..hasRequiredFields = false ; + ServicesWithCharacteristics._() : super(); + factory ServicesWithCharacteristics({ + $core.Iterable? items, + }) { + final _result = create(); + if (items != null) { + _result.items.addAll(items); + } + return _result; + } + factory ServicesWithCharacteristics.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ServicesWithCharacteristics.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1427,10 +1658,8 @@ class ServicesWithCharacteristics extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ServicesWithCharacteristics copyWith(void Function(ServicesWithCharacteristics) updates) => super.copyWith((message) => updates(message as ServicesWithCharacteristics)) as ServicesWithCharacteristics; - + ServicesWithCharacteristics copyWith(void Function(ServicesWithCharacteristics) updates) => super.copyWith((message) => updates(message as ServicesWithCharacteristics)) as ServicesWithCharacteristics; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ServicesWithCharacteristics create() => ServicesWithCharacteristics._(); ServicesWithCharacteristics createEmptyInstance() => create(); @@ -1444,17 +1673,28 @@ class ServicesWithCharacteristics extends $pb.GeneratedMessage { } class ServiceWithCharacteristics extends $pb.GeneratedMessage { - factory ServiceWithCharacteristics() => create(); - ServiceWithCharacteristics._() : super(); - factory ServiceWithCharacteristics.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory ServiceWithCharacteristics.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ServiceWithCharacteristics', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'serviceId', protoName: 'serviceId', subBuilder: Uuid.create) - ..pc(2, _omitFieldNames ? '' : 'characteristics', $pb.PbFieldType.PM, subBuilder: Uuid.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ServiceWithCharacteristics', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceId', protoName: 'serviceId', subBuilder: Uuid.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristics', $pb.PbFieldType.PM, subBuilder: Uuid.create) ..hasRequiredFields = false ; + ServiceWithCharacteristics._() : super(); + factory ServiceWithCharacteristics({ + Uuid? serviceId, + $core.Iterable? characteristics, + }) { + final _result = create(); + if (serviceId != null) { + _result.serviceId = serviceId; + } + if (characteristics != null) { + _result.characteristics.addAll(characteristics); + } + return _result; + } + factory ServiceWithCharacteristics.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ServiceWithCharacteristics.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1464,10 +1704,8 @@ class ServiceWithCharacteristics extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - ServiceWithCharacteristics copyWith(void Function(ServiceWithCharacteristics) updates) => super.copyWith((message) => updates(message as ServiceWithCharacteristics)) as ServiceWithCharacteristics; - + ServiceWithCharacteristics copyWith(void Function(ServiceWithCharacteristics) updates) => super.copyWith((message) => updates(message as ServiceWithCharacteristics)) as ServiceWithCharacteristics; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static ServiceWithCharacteristics create() => ServiceWithCharacteristics._(); ServiceWithCharacteristics createEmptyInstance() => create(); @@ -1492,16 +1730,23 @@ class ServiceWithCharacteristics extends $pb.GeneratedMessage { } class DiscoverServicesRequest extends $pb.GeneratedMessage { - factory DiscoverServicesRequest() => create(); - DiscoverServicesRequest._() : super(); - factory DiscoverServicesRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DiscoverServicesRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DiscoverServicesRequest', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DiscoverServicesRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') ..hasRequiredFields = false ; + DiscoverServicesRequest._() : super(); + factory DiscoverServicesRequest({ + $core.String? deviceId, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + return _result; + } + factory DiscoverServicesRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DiscoverServicesRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1511,10 +1756,8 @@ class DiscoverServicesRequest extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DiscoverServicesRequest copyWith(void Function(DiscoverServicesRequest) updates) => super.copyWith((message) => updates(message as DiscoverServicesRequest)) as DiscoverServicesRequest; - + DiscoverServicesRequest copyWith(void Function(DiscoverServicesRequest) updates) => super.copyWith((message) => updates(message as DiscoverServicesRequest)) as DiscoverServicesRequest; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DiscoverServicesRequest create() => DiscoverServicesRequest._(); DiscoverServicesRequest createEmptyInstance() => create(); @@ -1534,17 +1777,28 @@ class DiscoverServicesRequest extends $pb.GeneratedMessage { } class DiscoverServicesInfo extends $pb.GeneratedMessage { - factory DiscoverServicesInfo() => create(); - DiscoverServicesInfo._() : super(); - factory DiscoverServicesInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DiscoverServicesInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DiscoverServicesInfo', createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'deviceId', protoName: 'deviceId') - ..pc(2, _omitFieldNames ? '' : 'services', $pb.PbFieldType.PM, subBuilder: DiscoveredService.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DiscoverServicesInfo', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'services', $pb.PbFieldType.PM, subBuilder: DiscoveredService.create) ..hasRequiredFields = false ; + DiscoverServicesInfo._() : super(); + factory DiscoverServicesInfo({ + $core.String? deviceId, + $core.Iterable? services, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (services != null) { + _result.services.addAll(services); + } + return _result; + } + factory DiscoverServicesInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DiscoverServicesInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1554,10 +1808,8 @@ class DiscoverServicesInfo extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DiscoverServicesInfo copyWith(void Function(DiscoverServicesInfo) updates) => super.copyWith((message) => updates(message as DiscoverServicesInfo)) as DiscoverServicesInfo; - + DiscoverServicesInfo copyWith(void Function(DiscoverServicesInfo) updates) => super.copyWith((message) => updates(message as DiscoverServicesInfo)) as DiscoverServicesInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DiscoverServicesInfo create() => DiscoverServicesInfo._(); DiscoverServicesInfo createEmptyInstance() => create(); @@ -1580,19 +1832,43 @@ class DiscoverServicesInfo extends $pb.GeneratedMessage { } class DiscoveredService extends $pb.GeneratedMessage { - factory DiscoveredService() => create(); - DiscoveredService._() : super(); - factory DiscoveredService.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DiscoveredService.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DiscoveredService', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) - ..pc(2, _omitFieldNames ? '' : 'characteristicUuids', $pb.PbFieldType.PM, protoName: 'characteristicUuids', subBuilder: Uuid.create) - ..pc(3, _omitFieldNames ? '' : 'includedServices', $pb.PbFieldType.PM, protoName: 'includedServices', subBuilder: DiscoveredService.create) - ..pc(4, _omitFieldNames ? '' : 'characteristics', $pb.PbFieldType.PM, subBuilder: DiscoveredCharacteristic.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DiscoveredService', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceUuid', protoName: 'serviceUuid', subBuilder: Uuid.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristicUuids', $pb.PbFieldType.PM, protoName: 'characteristicUuids', subBuilder: Uuid.create) + ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'includedServices', $pb.PbFieldType.PM, protoName: 'includedServices', subBuilder: DiscoveredService.create) + ..pc(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristics', $pb.PbFieldType.PM, subBuilder: DiscoveredCharacteristic.create) + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceInstanceId', protoName: 'serviceInstanceId') ..hasRequiredFields = false ; + DiscoveredService._() : super(); + factory DiscoveredService({ + Uuid? serviceUuid, + $core.Iterable? characteristicUuids, + $core.Iterable? includedServices, + $core.Iterable? characteristics, + $core.String? serviceInstanceId, + }) { + final _result = create(); + if (serviceUuid != null) { + _result.serviceUuid = serviceUuid; + } + if (characteristicUuids != null) { + _result.characteristicUuids.addAll(characteristicUuids); + } + if (includedServices != null) { + _result.includedServices.addAll(includedServices); + } + if (characteristics != null) { + _result.characteristics.addAll(characteristics); + } + if (serviceInstanceId != null) { + _result.serviceInstanceId = serviceInstanceId; + } + return _result; + } + factory DiscoveredService.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DiscoveredService.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1602,10 +1878,8 @@ class DiscoveredService extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DiscoveredService copyWith(void Function(DiscoveredService) updates) => super.copyWith((message) => updates(message as DiscoveredService)) as DiscoveredService; - + DiscoveredService copyWith(void Function(DiscoveredService) updates) => super.copyWith((message) => updates(message as DiscoveredService)) as DiscoveredService; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DiscoveredService create() => DiscoveredService._(); DiscoveredService createEmptyInstance() => create(); @@ -1633,25 +1907,70 @@ class DiscoveredService extends $pb.GeneratedMessage { @$pb.TagNumber(4) $core.List get characteristics => $_getList(3); + + @$pb.TagNumber(5) + $core.String get serviceInstanceId => $_getSZ(4); + @$pb.TagNumber(5) + set serviceInstanceId($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasServiceInstanceId() => $_has(4); + @$pb.TagNumber(5) + void clearServiceInstanceId() => clearField(5); } class DiscoveredCharacteristic extends $pb.GeneratedMessage { - factory DiscoveredCharacteristic() => create(); - DiscoveredCharacteristic._() : super(); - factory DiscoveredCharacteristic.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DiscoveredCharacteristic.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'DiscoveredCharacteristic', createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'characteristicId', protoName: 'characteristicId', subBuilder: Uuid.create) - ..aOM(2, _omitFieldNames ? '' : 'serviceId', protoName: 'serviceId', subBuilder: Uuid.create) - ..aOB(3, _omitFieldNames ? '' : 'isReadable', protoName: 'isReadable') - ..aOB(4, _omitFieldNames ? '' : 'isWritableWithResponse', protoName: 'isWritableWithResponse') - ..aOB(5, _omitFieldNames ? '' : 'isWritableWithoutResponse', protoName: 'isWritableWithoutResponse') - ..aOB(6, _omitFieldNames ? '' : 'isNotifiable', protoName: 'isNotifiable') - ..aOB(7, _omitFieldNames ? '' : 'isIndicatable', protoName: 'isIndicatable') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DiscoveredCharacteristic', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristicId', protoName: 'characteristicId', subBuilder: Uuid.create) + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'serviceId', protoName: 'serviceId', subBuilder: Uuid.create) + ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isReadable', protoName: 'isReadable') + ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isWritableWithResponse', protoName: 'isWritableWithResponse') + ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isWritableWithoutResponse', protoName: 'isWritableWithoutResponse') + ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isNotifiable', protoName: 'isNotifiable') + ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isIndicatable', protoName: 'isIndicatable') + ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'characteristicInstanceId', protoName: 'characteristicInstanceId') ..hasRequiredFields = false ; + DiscoveredCharacteristic._() : super(); + factory DiscoveredCharacteristic({ + Uuid? characteristicId, + Uuid? serviceId, + $core.bool? isReadable, + $core.bool? isWritableWithResponse, + $core.bool? isWritableWithoutResponse, + $core.bool? isNotifiable, + $core.bool? isIndicatable, + $core.String? characteristicInstanceId, + }) { + final _result = create(); + if (characteristicId != null) { + _result.characteristicId = characteristicId; + } + if (serviceId != null) { + _result.serviceId = serviceId; + } + if (isReadable != null) { + _result.isReadable = isReadable; + } + if (isWritableWithResponse != null) { + _result.isWritableWithResponse = isWritableWithResponse; + } + if (isWritableWithoutResponse != null) { + _result.isWritableWithoutResponse = isWritableWithoutResponse; + } + if (isNotifiable != null) { + _result.isNotifiable = isNotifiable; + } + if (isIndicatable != null) { + _result.isIndicatable = isIndicatable; + } + if (characteristicInstanceId != null) { + _result.characteristicInstanceId = characteristicInstanceId; + } + return _result; + } + factory DiscoveredCharacteristic.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DiscoveredCharacteristic.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1661,10 +1980,8 @@ class DiscoveredCharacteristic extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DiscoveredCharacteristic copyWith(void Function(DiscoveredCharacteristic) updates) => super.copyWith((message) => updates(message as DiscoveredCharacteristic)) as DiscoveredCharacteristic; - + DiscoveredCharacteristic copyWith(void Function(DiscoveredCharacteristic) updates) => super.copyWith((message) => updates(message as DiscoveredCharacteristic)) as DiscoveredCharacteristic; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static DiscoveredCharacteristic create() => DiscoveredCharacteristic._(); DiscoveredCharacteristic createEmptyInstance() => create(); @@ -1739,32 +2056,140 @@ class DiscoveredCharacteristic extends $pb.GeneratedMessage { $core.bool hasIsIndicatable() => $_has(6); @$pb.TagNumber(7) void clearIsIndicatable() => clearField(7); -} -class Uuid extends $pb.GeneratedMessage { - factory Uuid() => create(); - Uuid._() : super(); - factory Uuid.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory Uuid.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$pb.TagNumber(8) + $core.String get characteristicInstanceId => $_getSZ(7); + @$pb.TagNumber(8) + set characteristicInstanceId($core.String v) { $_setString(7, v); } + @$pb.TagNumber(8) + $core.bool hasCharacteristicInstanceId() => $_has(7); + @$pb.TagNumber(8) + void clearCharacteristicInstanceId() => clearField(8); +} - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Uuid', createEmptyInstance: create) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'data', $pb.PbFieldType.OY) +class ReadRssiRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ReadRssiRequest', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId', protoName: 'deviceId') ..hasRequiredFields = false ; + ReadRssiRequest._() : super(); + factory ReadRssiRequest({ + $core.String? deviceId, + }) { + final _result = create(); + if (deviceId != null) { + _result.deviceId = deviceId; + } + return _result; + } + factory ReadRssiRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ReadRssiRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - Uuid clone() => Uuid()..mergeFromMessage(this); + ReadRssiRequest clone() => ReadRssiRequest()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - Uuid copyWith(void Function(Uuid) updates) => super.copyWith((message) => updates(message as Uuid)) as Uuid; + ReadRssiRequest copyWith(void Function(ReadRssiRequest) updates) => super.copyWith((message) => updates(message as ReadRssiRequest)) as ReadRssiRequest; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ReadRssiRequest create() => ReadRssiRequest._(); + ReadRssiRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ReadRssiRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ReadRssiRequest? _defaultInstance; + @$pb.TagNumber(1) + $core.String get deviceId => $_getSZ(0); + @$pb.TagNumber(1) + set deviceId($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasDeviceId() => $_has(0); + @$pb.TagNumber(1) + void clearDeviceId() => clearField(1); +} + +class ReadRssiResult extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ReadRssiResult', createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rssi', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + ReadRssiResult._() : super(); + factory ReadRssiResult({ + $core.int? rssi, + }) { + final _result = create(); + if (rssi != null) { + _result.rssi = rssi; + } + return _result; + } + factory ReadRssiResult.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ReadRssiResult.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ReadRssiResult clone() => ReadRssiResult()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ReadRssiResult copyWith(void Function(ReadRssiResult) updates) => super.copyWith((message) => updates(message as ReadRssiResult)) as ReadRssiResult; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ReadRssiResult create() => ReadRssiResult._(); + ReadRssiResult createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ReadRssiResult getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ReadRssiResult? _defaultInstance; + @$pb.TagNumber(1) + $core.int get rssi => $_getIZ(0); + @$pb.TagNumber(1) + set rssi($core.int v) { $_setSignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasRssi() => $_has(0); + @$pb.TagNumber(1) + void clearRssi() => clearField(1); +} + +class Uuid extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Uuid', createEmptyInstance: create) + ..a<$core.List<$core.int>>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + Uuid._() : super(); + factory Uuid({ + $core.List<$core.int>? data, + }) { + final _result = create(); + if (data != null) { + _result.data = data; + } + return _result; + } + factory Uuid.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Uuid.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Uuid clone() => Uuid()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Uuid copyWith(void Function(Uuid) updates) => super.copyWith((message) => updates(message as Uuid)) as Uuid; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') static Uuid create() => Uuid._(); Uuid createEmptyInstance() => create(); @@ -1784,17 +2209,28 @@ class Uuid extends $pb.GeneratedMessage { } class GenericFailure extends $pb.GeneratedMessage { - factory GenericFailure() => create(); - GenericFailure._() : super(); - factory GenericFailure.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory GenericFailure.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GenericFailure', createEmptyInstance: create) - ..a<$core.int>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.O3) - ..aOS(2, _omitFieldNames ? '' : 'message') + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GenericFailure', createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message') ..hasRequiredFields = false ; + GenericFailure._() : super(); + factory GenericFailure({ + $core.int? code, + $core.String? message, + }) { + final _result = create(); + if (code != null) { + _result.code = code; + } + if (message != null) { + _result.message = message; + } + return _result; + } + factory GenericFailure.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GenericFailure.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1804,10 +2240,8 @@ class GenericFailure extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - GenericFailure copyWith(void Function(GenericFailure) updates) => super.copyWith((message) => updates(message as GenericFailure)) as GenericFailure; - + GenericFailure copyWith(void Function(GenericFailure) updates) => super.copyWith((message) => updates(message as GenericFailure)) as GenericFailure; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static GenericFailure create() => GenericFailure._(); GenericFailure createEmptyInstance() => create(); @@ -1836,16 +2270,23 @@ class GenericFailure extends $pb.GeneratedMessage { } class IsConnectable extends $pb.GeneratedMessage { - factory IsConnectable() => create(); - IsConnectable._() : super(); - factory IsConnectable.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory IsConnectable.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'IsConnectable', createEmptyInstance: create) - ..a<$core.int>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.O3) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IsConnectable', createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) ..hasRequiredFields = false ; + IsConnectable._() : super(); + factory IsConnectable({ + $core.int? code, + }) { + final _result = create(); + if (code != null) { + _result.code = code; + } + return _result; + } + factory IsConnectable.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory IsConnectable.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' @@ -1855,10 +2296,8 @@ class IsConnectable extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - IsConnectable copyWith(void Function(IsConnectable) updates) => super.copyWith((message) => updates(message as IsConnectable)) as IsConnectable; - + IsConnectable copyWith(void Function(IsConnectable) updates) => super.copyWith((message) => updates(message as IsConnectable)) as IsConnectable; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') static IsConnectable create() => IsConnectable._(); IsConnectable createEmptyInstance() => create(); @@ -1877,6 +2316,3 @@ class IsConnectable extends $pb.GeneratedMessage { void clearCode() => clearField(1); } - -const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); -const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbenum.dart b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbenum.dart index c8a652ee..02610f8b 100644 --- a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbenum.dart +++ b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbenum.dart @@ -1,13 +1,9 @@ -// +/// // Generated code. Do not modify. // source: bledata.proto // // @dart = 2.12 - -// ignore_for_file: annotate_overrides, camel_case_types -// ignore_for_file: constant_identifier_names, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_final_fields -// ignore_for_file: unnecessary_import, unnecessary_this, unused_import +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core; diff --git a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbjson.dart b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbjson.dart index 89f0d5c6..36fe24f6 100644 --- a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbjson.dart +++ b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbjson.dart @@ -1,539 +1,679 @@ -// +/// // Generated code. Do not modify. // source: bledata.proto // // @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name -// ignore_for_file: annotate_overrides, camel_case_types -// ignore_for_file: constant_identifier_names, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_final_fields -// ignore_for_file: unnecessary_import, unnecessary_this, unused_import - -import 'dart:convert' as $convert; import 'dart:core' as $core; +import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use launchCompanionRequestDescriptor instead') -const LaunchCompanionRequest$json = { - '1': 'LaunchCompanionRequest', - '2': [ - {'1': 'deviceNamePattern', '3': 1, '4': 1, '5': 9, '10': 'deviceNamePattern'}, - {'1': 'singleDeviceScan', '3': 2, '4': 1, '5': 8, '10': 'singleDeviceScan'}, - {'1': 'forceConfirmation', '3': 3, '4': 1, '5': 8, '10': 'forceConfirmation'}, - ], -}; - -/// Descriptor for `LaunchCompanionRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List launchCompanionRequestDescriptor = $convert.base64Decode( - 'ChZMYXVuY2hDb21wYW5pb25SZXF1ZXN0EiwKEWRldmljZU5hbWVQYXR0ZXJuGAEgASgJUhFkZX' - 'ZpY2VOYW1lUGF0dGVybhIqChBzaW5nbGVEZXZpY2VTY2FuGAIgASgIUhBzaW5nbGVEZXZpY2VT' - 'Y2FuEiwKEWZvcmNlQ29uZmlybWF0aW9uGAMgASgIUhFmb3JjZUNvbmZpcm1hdGlvbg=='); - -@$core.Deprecated('Use deviceAssociationInfoDescriptor instead') -const DeviceAssociationInfo$json = { - '1': 'DeviceAssociationInfo', - '2': [ - {'1': 'macAddress', '3': 1, '4': 1, '5': 9, '10': 'macAddress'}, - ], -}; - -/// Descriptor for `DeviceAssociationInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List deviceAssociationInfoDescriptor = $convert.base64Decode( - 'ChVEZXZpY2VBc3NvY2lhdGlvbkluZm8SHgoKbWFjQWRkcmVzcxgBIAEoCVIKbWFjQWRkcmVzcw' - '=='); - @$core.Deprecated('Use scanForDevicesRequestDescriptor instead') -const ScanForDevicesRequest$json = { +const ScanForDevicesRequest$json = const { '1': 'ScanForDevicesRequest', - '2': [ - {'1': 'serviceUuids', '3': 1, '4': 3, '5': 11, '6': '.Uuid', '10': 'serviceUuids'}, - {'1': 'scanMode', '3': 2, '4': 1, '5': 5, '10': 'scanMode'}, - {'1': 'requireLocationServicesEnabled', '3': 3, '4': 1, '5': 8, '10': 'requireLocationServicesEnabled'}, + '2': const [ + const { + '1': 'serviceUuids', + '3': 1, + '4': 3, + '5': 11, + '6': '.Uuid', + '10': 'serviceUuids' + }, + const {'1': 'scanMode', '3': 2, '4': 1, '5': 5, '10': 'scanMode'}, + const { + '1': 'requireLocationServicesEnabled', + '3': 3, + '4': 1, + '5': 8, + '10': 'requireLocationServicesEnabled' + }, ], }; /// Descriptor for `ScanForDevicesRequest`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List scanForDevicesRequestDescriptor = $convert.base64Decode( - 'ChVTY2FuRm9yRGV2aWNlc1JlcXVlc3QSKQoMc2VydmljZVV1aWRzGAEgAygLMgUuVXVpZFIMc2' - 'VydmljZVV1aWRzEhoKCHNjYW5Nb2RlGAIgASgFUghzY2FuTW9kZRJGCh5yZXF1aXJlTG9jYXRp' - 'b25TZXJ2aWNlc0VuYWJsZWQYAyABKAhSHnJlcXVpcmVMb2NhdGlvblNlcnZpY2VzRW5hYmxlZA' - '=='); - + 'ChVTY2FuRm9yRGV2aWNlc1JlcXVlc3QSKQoMc2VydmljZVV1aWRzGAEgAygLMgUuVXVpZFIMc2VydmljZVV1aWRzEhoKCHNjYW5Nb2RlGAIgASgFUghzY2FuTW9kZRJGCh5yZXF1aXJlTG9jYXRpb25TZXJ2aWNlc0VuYWJsZWQYAyABKAhSHnJlcXVpcmVMb2NhdGlvblNlcnZpY2VzRW5hYmxlZA=='); @$core.Deprecated('Use deviceScanInfoDescriptor instead') -const DeviceScanInfo$json = { +const DeviceScanInfo$json = const { '1': 'DeviceScanInfo', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, - {'1': 'failure', '3': 3, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, - {'1': 'serviceData', '3': 4, '4': 3, '5': 11, '6': '.ServiceDataEntry', '10': 'serviceData'}, - {'1': 'manufacturerData', '3': 6, '4': 1, '5': 12, '10': 'manufacturerData'}, - {'1': 'serviceUuids', '3': 7, '4': 3, '5': 11, '6': '.Uuid', '10': 'serviceUuids'}, - {'1': 'rssi', '3': 5, '4': 1, '5': 5, '10': 'rssi'}, - {'1': 'isConnectable', '3': 8, '4': 1, '5': 11, '6': '.IsConnectable', '10': 'isConnectable'}, + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, + const { + '1': 'failure', + '3': 3, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, + const { + '1': 'serviceData', + '3': 4, + '4': 3, + '5': 11, + '6': '.ServiceDataEntry', + '10': 'serviceData' + }, + const { + '1': 'manufacturerData', + '3': 6, + '4': 1, + '5': 12, + '10': 'manufacturerData' + }, + const { + '1': 'serviceUuids', + '3': 7, + '4': 3, + '5': 11, + '6': '.Uuid', + '10': 'serviceUuids' + }, + const {'1': 'rssi', '3': 5, '4': 1, '5': 5, '10': 'rssi'}, + const { + '1': 'isConnectable', + '3': 8, + '4': 1, + '5': 11, + '6': '.IsConnectable', + '10': 'isConnectable' + }, ], }; /// Descriptor for `DeviceScanInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List deviceScanInfoDescriptor = $convert.base64Decode( - 'Cg5EZXZpY2VTY2FuSW5mbxIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRIpCg' - 'dmYWlsdXJlGAMgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1cmUSMwoLc2VydmljZURhdGEY' - 'BCADKAsyES5TZXJ2aWNlRGF0YUVudHJ5UgtzZXJ2aWNlRGF0YRIqChBtYW51ZmFjdHVyZXJEYX' - 'RhGAYgASgMUhBtYW51ZmFjdHVyZXJEYXRhEikKDHNlcnZpY2VVdWlkcxgHIAMoCzIFLlV1aWRS' - 'DHNlcnZpY2VVdWlkcxISCgRyc3NpGAUgASgFUgRyc3NpEjQKDWlzQ29ubmVjdGFibGUYCCABKA' - 'syDi5Jc0Nvbm5lY3RhYmxlUg1pc0Nvbm5lY3RhYmxl'); - -@$core.Deprecated('Use establishBondingRequestDescriptor instead') -const EstablishBondingRequest$json = { - '1': 'EstablishBondingRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - ], -}; - -/// Descriptor for `EstablishBondingRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List establishBondingRequestDescriptor = $convert.base64Decode( - 'ChdFc3RhYmxpc2hCb25kaW5nUmVxdWVzdBIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQ='); - -@$core.Deprecated('Use establishBondingInfoDescriptor instead') -const EstablishBondingInfo$json = { - '1': 'EstablishBondingInfo', - '2': [ - {'1': 'status', '3': 1, '4': 1, '5': 14, '6': '.EstablishBondingInfo.BondState', '10': 'status'}, - ], - '4': [EstablishBondingInfo_BondState$json], -}; - -@$core.Deprecated('Use establishBondingInfoDescriptor instead') -const EstablishBondingInfo_BondState$json = { - '1': 'BondState', - '2': [ - {'1': 'NONE', '2': 0}, - {'1': 'BONDING', '2': 1}, - {'1': 'BONDED', '2': 2}, - ], -}; - -/// Descriptor for `EstablishBondingInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List establishBondingInfoDescriptor = $convert.base64Decode( - 'ChRFc3RhYmxpc2hCb25kaW5nSW5mbxI3CgZzdGF0dXMYASABKA4yHy5Fc3RhYmxpc2hCb25kaW' - '5nSW5mby5Cb25kU3RhdGVSBnN0YXR1cyIuCglCb25kU3RhdGUSCAoETk9ORRAAEgsKB0JPTkRJ' - 'TkcQARIKCgZCT05ERUQQAg=='); - + 'Cg5EZXZpY2VTY2FuSW5mbxIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRIpCgdmYWlsdXJlGAMgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1cmUSMwoLc2VydmljZURhdGEYBCADKAsyES5TZXJ2aWNlRGF0YUVudHJ5UgtzZXJ2aWNlRGF0YRIqChBtYW51ZmFjdHVyZXJEYXRhGAYgASgMUhBtYW51ZmFjdHVyZXJEYXRhEikKDHNlcnZpY2VVdWlkcxgHIAMoCzIFLlV1aWRSDHNlcnZpY2VVdWlkcxISCgRyc3NpGAUgASgFUgRyc3NpEjQKDWlzQ29ubmVjdGFibGUYCCABKAsyDi5Jc0Nvbm5lY3RhYmxlUg1pc0Nvbm5lY3RhYmxl'); @$core.Deprecated('Use connectToDeviceRequestDescriptor instead') -const ConnectToDeviceRequest$json = { +const ConnectToDeviceRequest$json = const { '1': 'ConnectToDeviceRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'servicesWithCharacteristicsToDiscover', '3': 2, '4': 1, '5': 11, '6': '.ServicesWithCharacteristics', '10': 'servicesWithCharacteristicsToDiscover'}, - {'1': 'timeoutInMs', '3': 3, '4': 1, '5': 5, '10': 'timeoutInMs'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const { + '1': 'servicesWithCharacteristicsToDiscover', + '3': 2, + '4': 1, + '5': 11, + '6': '.ServicesWithCharacteristics', + '10': 'servicesWithCharacteristicsToDiscover' + }, + const {'1': 'timeoutInMs', '3': 3, '4': 1, '5': 5, '10': 'timeoutInMs'}, ], }; /// Descriptor for `ConnectToDeviceRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List connectToDeviceRequestDescriptor = $convert.base64Decode( - 'ChZDb25uZWN0VG9EZXZpY2VSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBJyCi' - 'VzZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3NUb0Rpc2NvdmVyGAIgASgLMhwuU2VydmljZXNX' - 'aXRoQ2hhcmFjdGVyaXN0aWNzUiVzZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3NUb0Rpc2Nvdm' - 'VyEiAKC3RpbWVvdXRJbk1zGAMgASgFUgt0aW1lb3V0SW5Ncw=='); - +final $typed_data.Uint8List connectToDeviceRequestDescriptor = + $convert.base64Decode( + 'ChZDb25uZWN0VG9EZXZpY2VSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBJyCiVzZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3NUb0Rpc2NvdmVyGAIgASgLMhwuU2VydmljZXNXaXRoQ2hhcmFjdGVyaXN0aWNzUiVzZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3NUb0Rpc2NvdmVyEiAKC3RpbWVvdXRJbk1zGAMgASgFUgt0aW1lb3V0SW5Ncw=='); @$core.Deprecated('Use deviceInfoDescriptor instead') -const DeviceInfo$json = { +const DeviceInfo$json = const { '1': 'DeviceInfo', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - {'1': 'connectionState', '3': 2, '4': 1, '5': 5, '10': 'connectionState'}, - {'1': 'failure', '3': 3, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const { + '1': 'connectionState', + '3': 2, + '4': 1, + '5': 5, + '10': 'connectionState' + }, + const { + '1': 'failure', + '3': 3, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `DeviceInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List deviceInfoDescriptor = $convert.base64Decode( - 'CgpEZXZpY2VJbmZvEg4KAmlkGAEgASgJUgJpZBIoCg9jb25uZWN0aW9uU3RhdGUYAiABKAVSD2' - 'Nvbm5lY3Rpb25TdGF0ZRIpCgdmYWlsdXJlGAMgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1' - 'cmU='); - -@$core.Deprecated('Use getDeviceNameRequestDescriptor instead') -const GetDeviceNameRequest$json = { - '1': 'GetDeviceNameRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - ], -}; - -/// Descriptor for `GetDeviceNameRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List getDeviceNameRequestDescriptor = $convert.base64Decode( - 'ChRHZXREZXZpY2VOYW1lUmVxdWVzdBIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQ='); - -@$core.Deprecated('Use deviceNameInfoDescriptor instead') -const DeviceNameInfo$json = { - '1': 'DeviceNameInfo', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - {'1': 'deviceName', '3': 2, '4': 1, '5': 9, '10': 'deviceName'}, - ], -}; - -/// Descriptor for `DeviceNameInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List deviceNameInfoDescriptor = $convert.base64Decode( - 'Cg5EZXZpY2VOYW1lSW5mbxIOCgJpZBgBIAEoCVICaWQSHgoKZGV2aWNlTmFtZRgCIAEoCVIKZG' - 'V2aWNlTmFtZQ=='); - + 'CgpEZXZpY2VJbmZvEg4KAmlkGAEgASgJUgJpZBIoCg9jb25uZWN0aW9uU3RhdGUYAiABKAVSD2Nvbm5lY3Rpb25TdGF0ZRIpCgdmYWlsdXJlGAMgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1cmU='); @$core.Deprecated('Use disconnectFromDeviceRequestDescriptor instead') -const DisconnectFromDeviceRequest$json = { +const DisconnectFromDeviceRequest$json = const { '1': 'DisconnectFromDeviceRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, ], }; /// Descriptor for `DisconnectFromDeviceRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List disconnectFromDeviceRequestDescriptor = $convert.base64Decode( - 'ChtEaXNjb25uZWN0RnJvbURldmljZVJlcXVlc3QSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZU' - 'lk'); - +final $typed_data.Uint8List disconnectFromDeviceRequestDescriptor = + $convert.base64Decode( + 'ChtEaXNjb25uZWN0RnJvbURldmljZVJlcXVlc3QSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlk'); @$core.Deprecated('Use clearGattCacheRequestDescriptor instead') -const ClearGattCacheRequest$json = { +const ClearGattCacheRequest$json = const { '1': 'ClearGattCacheRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, ], }; /// Descriptor for `ClearGattCacheRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List clearGattCacheRequestDescriptor = $convert.base64Decode( - 'ChVDbGVhckdhdHRDYWNoZVJlcXVlc3QSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlk'); - +final $typed_data.Uint8List clearGattCacheRequestDescriptor = + $convert.base64Decode( + 'ChVDbGVhckdhdHRDYWNoZVJlcXVlc3QSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlk'); @$core.Deprecated('Use clearGattCacheInfoDescriptor instead') -const ClearGattCacheInfo$json = { +const ClearGattCacheInfo$json = const { '1': 'ClearGattCacheInfo', - '2': [ - {'1': 'failure', '3': 1, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const { + '1': 'failure', + '3': 1, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `ClearGattCacheInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List clearGattCacheInfoDescriptor = $convert.base64Decode( - 'ChJDbGVhckdhdHRDYWNoZUluZm8SKQoHZmFpbHVyZRgBIAEoCzIPLkdlbmVyaWNGYWlsdXJlUg' - 'dmYWlsdXJl'); - + 'ChJDbGVhckdhdHRDYWNoZUluZm8SKQoHZmFpbHVyZRgBIAEoCzIPLkdlbmVyaWNGYWlsdXJlUgdmYWlsdXJl'); @$core.Deprecated('Use notifyCharacteristicRequestDescriptor instead') -const NotifyCharacteristicRequest$json = { +const NotifyCharacteristicRequest$json = const { '1': 'NotifyCharacteristicRequest', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, ], }; /// Descriptor for `NotifyCharacteristicRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List notifyCharacteristicRequestDescriptor = $convert.base64Decode( - 'ChtOb3RpZnlDaGFyYWN0ZXJpc3RpY1JlcXVlc3QSPgoOY2hhcmFjdGVyaXN0aWMYASABKAsyFi' - '5DaGFyYWN0ZXJpc3RpY0FkZHJlc3NSDmNoYXJhY3RlcmlzdGlj'); - +final $typed_data.Uint8List notifyCharacteristicRequestDescriptor = + $convert.base64Decode( + 'ChtOb3RpZnlDaGFyYWN0ZXJpc3RpY1JlcXVlc3QSPgoOY2hhcmFjdGVyaXN0aWMYASABKAsyFi5DaGFyYWN0ZXJpc3RpY0FkZHJlc3NSDmNoYXJhY3RlcmlzdGlj'); @$core.Deprecated('Use notifyNoMoreCharacteristicRequestDescriptor instead') -const NotifyNoMoreCharacteristicRequest$json = { +const NotifyNoMoreCharacteristicRequest$json = const { '1': 'NotifyNoMoreCharacteristicRequest', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, ], }; /// Descriptor for `NotifyNoMoreCharacteristicRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List notifyNoMoreCharacteristicRequestDescriptor = $convert.base64Decode( - 'CiFOb3RpZnlOb01vcmVDaGFyYWN0ZXJpc3RpY1JlcXVlc3QSPgoOY2hhcmFjdGVyaXN0aWMYAS' - 'ABKAsyFi5DaGFyYWN0ZXJpc3RpY0FkZHJlc3NSDmNoYXJhY3RlcmlzdGlj'); - +final $typed_data.Uint8List notifyNoMoreCharacteristicRequestDescriptor = + $convert.base64Decode( + 'CiFOb3RpZnlOb01vcmVDaGFyYWN0ZXJpc3RpY1JlcXVlc3QSPgoOY2hhcmFjdGVyaXN0aWMYASABKAsyFi5DaGFyYWN0ZXJpc3RpY0FkZHJlc3NSDmNoYXJhY3RlcmlzdGlj'); @$core.Deprecated('Use readCharacteristicRequestDescriptor instead') -const ReadCharacteristicRequest$json = { +const ReadCharacteristicRequest$json = const { '1': 'ReadCharacteristicRequest', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, ], }; /// Descriptor for `ReadCharacteristicRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List readCharacteristicRequestDescriptor = $convert.base64Decode( - 'ChlSZWFkQ2hhcmFjdGVyaXN0aWNSZXF1ZXN0Ej4KDmNoYXJhY3RlcmlzdGljGAEgASgLMhYuQ2' - 'hhcmFjdGVyaXN0aWNBZGRyZXNzUg5jaGFyYWN0ZXJpc3RpYw=='); - +final $typed_data.Uint8List readCharacteristicRequestDescriptor = + $convert.base64Decode( + 'ChlSZWFkQ2hhcmFjdGVyaXN0aWNSZXF1ZXN0Ej4KDmNoYXJhY3RlcmlzdGljGAEgASgLMhYuQ2hhcmFjdGVyaXN0aWNBZGRyZXNzUg5jaGFyYWN0ZXJpc3RpYw=='); @$core.Deprecated('Use characteristicValueInfoDescriptor instead') -const CharacteristicValueInfo$json = { +const CharacteristicValueInfo$json = const { '1': 'CharacteristicValueInfo', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, - {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, - {'1': 'failure', '3': 3, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, + const {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, + const { + '1': 'failure', + '3': 3, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `CharacteristicValueInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List characteristicValueInfoDescriptor = $convert.base64Decode( - 'ChdDaGFyYWN0ZXJpc3RpY1ZhbHVlSW5mbxI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLkNoYX' - 'JhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSFAoFdmFsdWUYAiABKAxSBXZhbHVl' - 'EikKB2ZhaWx1cmUYAyABKAsyDy5HZW5lcmljRmFpbHVyZVIHZmFpbHVyZQ=='); - +final $typed_data.Uint8List characteristicValueInfoDescriptor = + $convert.base64Decode( + 'ChdDaGFyYWN0ZXJpc3RpY1ZhbHVlSW5mbxI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLkNoYXJhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSFAoFdmFsdWUYAiABKAxSBXZhbHVlEikKB2ZhaWx1cmUYAyABKAsyDy5HZW5lcmljRmFpbHVyZVIHZmFpbHVyZQ=='); @$core.Deprecated('Use writeCharacteristicRequestDescriptor instead') -const WriteCharacteristicRequest$json = { +const WriteCharacteristicRequest$json = const { '1': 'WriteCharacteristicRequest', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, - {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, + const {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, ], }; /// Descriptor for `WriteCharacteristicRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List writeCharacteristicRequestDescriptor = $convert.base64Decode( - 'ChpXcml0ZUNoYXJhY3RlcmlzdGljUmVxdWVzdBI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLk' - 'NoYXJhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSFAoFdmFsdWUYAiABKAxSBXZh' - 'bHVl'); - +final $typed_data.Uint8List writeCharacteristicRequestDescriptor = + $convert.base64Decode( + 'ChpXcml0ZUNoYXJhY3RlcmlzdGljUmVxdWVzdBI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLkNoYXJhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSFAoFdmFsdWUYAiABKAxSBXZhbHVl'); @$core.Deprecated('Use writeCharacteristicInfoDescriptor instead') -const WriteCharacteristicInfo$json = { +const WriteCharacteristicInfo$json = const { '1': 'WriteCharacteristicInfo', - '2': [ - {'1': 'characteristic', '3': 1, '4': 1, '5': 11, '6': '.CharacteristicAddress', '10': 'characteristic'}, - {'1': 'failure', '3': 3, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const { + '1': 'characteristic', + '3': 1, + '4': 1, + '5': 11, + '6': '.CharacteristicAddress', + '10': 'characteristic' + }, + const { + '1': 'failure', + '3': 3, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `WriteCharacteristicInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List writeCharacteristicInfoDescriptor = $convert.base64Decode( - 'ChdXcml0ZUNoYXJhY3RlcmlzdGljSW5mbxI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLkNoYX' - 'JhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSKQoHZmFpbHVyZRgDIAEoCzIPLkdl' - 'bmVyaWNGYWlsdXJlUgdmYWlsdXJl'); - +final $typed_data.Uint8List writeCharacteristicInfoDescriptor = + $convert.base64Decode( + 'ChdXcml0ZUNoYXJhY3RlcmlzdGljSW5mbxI+Cg5jaGFyYWN0ZXJpc3RpYxgBIAEoCzIWLkNoYXJhY3RlcmlzdGljQWRkcmVzc1IOY2hhcmFjdGVyaXN0aWMSKQoHZmFpbHVyZRgDIAEoCzIPLkdlbmVyaWNGYWlsdXJlUgdmYWlsdXJl'); @$core.Deprecated('Use negotiateMtuRequestDescriptor instead') -const NegotiateMtuRequest$json = { +const NegotiateMtuRequest$json = const { '1': 'NegotiateMtuRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'mtuSize', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const {'1': 'mtuSize', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'}, ], }; /// Descriptor for `NegotiateMtuRequest`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List negotiateMtuRequestDescriptor = $convert.base64Decode( - 'ChNOZWdvdGlhdGVNdHVSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIYCgdtdH' - 'VTaXplGAIgASgFUgdtdHVTaXpl'); - + 'ChNOZWdvdGlhdGVNdHVSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIYCgdtdHVTaXplGAIgASgFUgdtdHVTaXpl'); @$core.Deprecated('Use negotiateMtuInfoDescriptor instead') -const NegotiateMtuInfo$json = { +const NegotiateMtuInfo$json = const { '1': 'NegotiateMtuInfo', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'mtuSize', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'}, - {'1': 'failure', '3': 3, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const {'1': 'mtuSize', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'}, + const { + '1': 'failure', + '3': 3, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `NegotiateMtuInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List negotiateMtuInfoDescriptor = $convert.base64Decode( - 'ChBOZWdvdGlhdGVNdHVJbmZvEhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIYCgdtdHVTaX' - 'plGAIgASgFUgdtdHVTaXplEikKB2ZhaWx1cmUYAyABKAsyDy5HZW5lcmljRmFpbHVyZVIHZmFp' - 'bHVyZQ=='); - + 'ChBOZWdvdGlhdGVNdHVJbmZvEhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIYCgdtdHVTaXplGAIgASgFUgdtdHVTaXplEikKB2ZhaWx1cmUYAyABKAsyDy5HZW5lcmljRmFpbHVyZVIHZmFpbHVyZQ=='); @$core.Deprecated('Use bleStatusInfoDescriptor instead') -const BleStatusInfo$json = { +const BleStatusInfo$json = const { '1': 'BleStatusInfo', - '2': [ - {'1': 'status', '3': 1, '4': 1, '5': 5, '10': 'status'}, + '2': const [ + const {'1': 'status', '3': 1, '4': 1, '5': 5, '10': 'status'}, ], }; /// Descriptor for `BleStatusInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List bleStatusInfoDescriptor = $convert.base64Decode( - 'Cg1CbGVTdGF0dXNJbmZvEhYKBnN0YXR1cxgBIAEoBVIGc3RhdHVz'); - +final $typed_data.Uint8List bleStatusInfoDescriptor = $convert + .base64Decode('Cg1CbGVTdGF0dXNJbmZvEhYKBnN0YXR1cxgBIAEoBVIGc3RhdHVz'); @$core.Deprecated('Use changeConnectionPriorityRequestDescriptor instead') -const ChangeConnectionPriorityRequest$json = { +const ChangeConnectionPriorityRequest$json = const { '1': 'ChangeConnectionPriorityRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'priority', '3': 2, '4': 1, '5': 5, '10': 'priority'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const {'1': 'priority', '3': 2, '4': 1, '5': 5, '10': 'priority'}, ], }; /// Descriptor for `ChangeConnectionPriorityRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List changeConnectionPriorityRequestDescriptor = $convert.base64Decode( - 'Ch9DaGFuZ2VDb25uZWN0aW9uUHJpb3JpdHlSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZX' - 'ZpY2VJZBIaCghwcmlvcml0eRgCIAEoBVIIcHJpb3JpdHk='); - +final $typed_data.Uint8List changeConnectionPriorityRequestDescriptor = + $convert.base64Decode( + 'Ch9DaGFuZ2VDb25uZWN0aW9uUHJpb3JpdHlSZXF1ZXN0EhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIaCghwcmlvcml0eRgCIAEoBVIIcHJpb3JpdHk='); @$core.Deprecated('Use changeConnectionPriorityInfoDescriptor instead') -const ChangeConnectionPriorityInfo$json = { +const ChangeConnectionPriorityInfo$json = const { '1': 'ChangeConnectionPriorityInfo', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'failure', '3': 2, '4': 1, '5': 11, '6': '.GenericFailure', '10': 'failure'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const { + '1': 'failure', + '3': 2, + '4': 1, + '5': 11, + '6': '.GenericFailure', + '10': 'failure' + }, ], }; /// Descriptor for `ChangeConnectionPriorityInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List changeConnectionPriorityInfoDescriptor = $convert.base64Decode( - 'ChxDaGFuZ2VDb25uZWN0aW9uUHJpb3JpdHlJbmZvEhoKCGRldmljZUlkGAEgASgJUghkZXZpY2' - 'VJZBIpCgdmYWlsdXJlGAIgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1cmU='); - +final $typed_data.Uint8List changeConnectionPriorityInfoDescriptor = + $convert.base64Decode( + 'ChxDaGFuZ2VDb25uZWN0aW9uUHJpb3JpdHlJbmZvEhoKCGRldmljZUlkGAEgASgJUghkZXZpY2VJZBIpCgdmYWlsdXJlGAIgASgLMg8uR2VuZXJpY0ZhaWx1cmVSB2ZhaWx1cmU='); @$core.Deprecated('Use characteristicAddressDescriptor instead') -const CharacteristicAddress$json = { +const CharacteristicAddress$json = const { '1': 'CharacteristicAddress', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'serviceUuid', '3': 2, '4': 1, '5': 11, '6': '.Uuid', '10': 'serviceUuid'}, - {'1': 'characteristicUuid', '3': 3, '4': 1, '5': 11, '6': '.Uuid', '10': 'characteristicUuid'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const { + '1': 'serviceUuid', + '3': 2, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'serviceUuid' + }, + const { + '1': 'characteristicUuid', + '3': 3, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'characteristicUuid' + }, + const { + '1': 'serviceInstanceId', + '3': 4, + '4': 1, + '5': 9, + '10': 'serviceInstanceId' + }, + const { + '1': 'characteristicInstanceId', + '3': 5, + '4': 1, + '5': 9, + '10': 'characteristicInstanceId' + }, ], }; /// Descriptor for `CharacteristicAddress`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List characteristicAddressDescriptor = $convert.base64Decode( - 'ChVDaGFyYWN0ZXJpc3RpY0FkZHJlc3MSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlkEicKC3' - 'NlcnZpY2VVdWlkGAIgASgLMgUuVXVpZFILc2VydmljZVV1aWQSNQoSY2hhcmFjdGVyaXN0aWNV' - 'dWlkGAMgASgLMgUuVXVpZFISY2hhcmFjdGVyaXN0aWNVdWlk'); - + 'ChVDaGFyYWN0ZXJpc3RpY0FkZHJlc3MSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlkEicKC3NlcnZpY2VVdWlkGAIgASgLMgUuVXVpZFILc2VydmljZVV1aWQSNQoSY2hhcmFjdGVyaXN0aWNVdWlkGAMgASgLMgUuVXVpZFISY2hhcmFjdGVyaXN0aWNVdWlkEiwKEXNlcnZpY2VJbnN0YW5jZUlkGAQgASgJUhFzZXJ2aWNlSW5zdGFuY2VJZBI6ChhjaGFyYWN0ZXJpc3RpY0luc3RhbmNlSWQYBSABKAlSGGNoYXJhY3RlcmlzdGljSW5zdGFuY2VJZA=='); @$core.Deprecated('Use serviceDataEntryDescriptor instead') -const ServiceDataEntry$json = { +const ServiceDataEntry$json = const { '1': 'ServiceDataEntry', - '2': [ - {'1': 'serviceUuid', '3': 1, '4': 1, '5': 11, '6': '.Uuid', '10': 'serviceUuid'}, - {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'}, + '2': const [ + const { + '1': 'serviceUuid', + '3': 1, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'serviceUuid' + }, + const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'}, ], }; /// Descriptor for `ServiceDataEntry`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List serviceDataEntryDescriptor = $convert.base64Decode( - 'ChBTZXJ2aWNlRGF0YUVudHJ5EicKC3NlcnZpY2VVdWlkGAEgASgLMgUuVXVpZFILc2VydmljZV' - 'V1aWQSEgoEZGF0YRgCIAEoDFIEZGF0YQ=='); - + 'ChBTZXJ2aWNlRGF0YUVudHJ5EicKC3NlcnZpY2VVdWlkGAEgASgLMgUuVXVpZFILc2VydmljZVV1aWQSEgoEZGF0YRgCIAEoDFIEZGF0YQ=='); @$core.Deprecated('Use servicesWithCharacteristicsDescriptor instead') -const ServicesWithCharacteristics$json = { +const ServicesWithCharacteristics$json = const { '1': 'ServicesWithCharacteristics', - '2': [ - {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.ServiceWithCharacteristics', '10': 'items'}, + '2': const [ + const { + '1': 'items', + '3': 1, + '4': 3, + '5': 11, + '6': '.ServiceWithCharacteristics', + '10': 'items' + }, ], }; /// Descriptor for `ServicesWithCharacteristics`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List servicesWithCharacteristicsDescriptor = $convert.base64Decode( - 'ChtTZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3MSMQoFaXRlbXMYASADKAsyGy5TZXJ2aWNlV2' - 'l0aENoYXJhY3RlcmlzdGljc1IFaXRlbXM='); - +final $typed_data.Uint8List servicesWithCharacteristicsDescriptor = + $convert.base64Decode( + 'ChtTZXJ2aWNlc1dpdGhDaGFyYWN0ZXJpc3RpY3MSMQoFaXRlbXMYASADKAsyGy5TZXJ2aWNlV2l0aENoYXJhY3RlcmlzdGljc1IFaXRlbXM='); @$core.Deprecated('Use serviceWithCharacteristicsDescriptor instead') -const ServiceWithCharacteristics$json = { +const ServiceWithCharacteristics$json = const { '1': 'ServiceWithCharacteristics', - '2': [ - {'1': 'serviceId', '3': 1, '4': 1, '5': 11, '6': '.Uuid', '10': 'serviceId'}, - {'1': 'characteristics', '3': 2, '4': 3, '5': 11, '6': '.Uuid', '10': 'characteristics'}, + '2': const [ + const { + '1': 'serviceId', + '3': 1, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'serviceId' + }, + const { + '1': 'characteristics', + '3': 2, + '4': 3, + '5': 11, + '6': '.Uuid', + '10': 'characteristics' + }, ], }; /// Descriptor for `ServiceWithCharacteristics`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List serviceWithCharacteristicsDescriptor = $convert.base64Decode( - 'ChpTZXJ2aWNlV2l0aENoYXJhY3RlcmlzdGljcxIjCglzZXJ2aWNlSWQYASABKAsyBS5VdWlkUg' - 'lzZXJ2aWNlSWQSLwoPY2hhcmFjdGVyaXN0aWNzGAIgAygLMgUuVXVpZFIPY2hhcmFjdGVyaXN0' - 'aWNz'); - +final $typed_data.Uint8List serviceWithCharacteristicsDescriptor = + $convert.base64Decode( + 'ChpTZXJ2aWNlV2l0aENoYXJhY3RlcmlzdGljcxIjCglzZXJ2aWNlSWQYASABKAsyBS5VdWlkUglzZXJ2aWNlSWQSLwoPY2hhcmFjdGVyaXN0aWNzGAIgAygLMgUuVXVpZFIPY2hhcmFjdGVyaXN0aWNz'); @$core.Deprecated('Use discoverServicesRequestDescriptor instead') -const DiscoverServicesRequest$json = { +const DiscoverServicesRequest$json = const { '1': 'DiscoverServicesRequest', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, ], }; /// Descriptor for `DiscoverServicesRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List discoverServicesRequestDescriptor = $convert.base64Decode( - 'ChdEaXNjb3ZlclNlcnZpY2VzUmVxdWVzdBIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQ='); - +final $typed_data.Uint8List discoverServicesRequestDescriptor = + $convert.base64Decode( + 'ChdEaXNjb3ZlclNlcnZpY2VzUmVxdWVzdBIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQ='); @$core.Deprecated('Use discoverServicesInfoDescriptor instead') -const DiscoverServicesInfo$json = { +const DiscoverServicesInfo$json = const { '1': 'DiscoverServicesInfo', - '2': [ - {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, - {'1': 'services', '3': 2, '4': 3, '5': 11, '6': '.DiscoveredService', '10': 'services'}, + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + const { + '1': 'services', + '3': 2, + '4': 3, + '5': 11, + '6': '.DiscoveredService', + '10': 'services' + }, ], }; /// Descriptor for `DiscoverServicesInfo`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List discoverServicesInfoDescriptor = $convert.base64Decode( - 'ChREaXNjb3ZlclNlcnZpY2VzSW5mbxIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQSLgoIc2' - 'VydmljZXMYAiADKAsyEi5EaXNjb3ZlcmVkU2VydmljZVIIc2VydmljZXM='); - + 'ChREaXNjb3ZlclNlcnZpY2VzSW5mbxIaCghkZXZpY2VJZBgBIAEoCVIIZGV2aWNlSWQSLgoIc2VydmljZXMYAiADKAsyEi5EaXNjb3ZlcmVkU2VydmljZVIIc2VydmljZXM='); @$core.Deprecated('Use discoveredServiceDescriptor instead') -const DiscoveredService$json = { +const DiscoveredService$json = const { '1': 'DiscoveredService', - '2': [ - {'1': 'serviceUuid', '3': 1, '4': 1, '5': 11, '6': '.Uuid', '10': 'serviceUuid'}, - {'1': 'characteristicUuids', '3': 2, '4': 3, '5': 11, '6': '.Uuid', '10': 'characteristicUuids'}, - {'1': 'includedServices', '3': 3, '4': 3, '5': 11, '6': '.DiscoveredService', '10': 'includedServices'}, - {'1': 'characteristics', '3': 4, '4': 3, '5': 11, '6': '.DiscoveredCharacteristic', '10': 'characteristics'}, + '2': const [ + const { + '1': 'serviceUuid', + '3': 1, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'serviceUuid' + }, + const { + '1': 'characteristicUuids', + '3': 2, + '4': 3, + '5': 11, + '6': '.Uuid', + '10': 'characteristicUuids' + }, + const { + '1': 'includedServices', + '3': 3, + '4': 3, + '5': 11, + '6': '.DiscoveredService', + '10': 'includedServices' + }, + const { + '1': 'characteristics', + '3': 4, + '4': 3, + '5': 11, + '6': '.DiscoveredCharacteristic', + '10': 'characteristics' + }, + const { + '1': 'serviceInstanceId', + '3': 5, + '4': 1, + '5': 9, + '10': 'serviceInstanceId' + }, ], }; /// Descriptor for `DiscoveredService`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List discoveredServiceDescriptor = $convert.base64Decode( - 'ChFEaXNjb3ZlcmVkU2VydmljZRInCgtzZXJ2aWNlVXVpZBgBIAEoCzIFLlV1aWRSC3NlcnZpY2' - 'VVdWlkEjcKE2NoYXJhY3RlcmlzdGljVXVpZHMYAiADKAsyBS5VdWlkUhNjaGFyYWN0ZXJpc3Rp' - 'Y1V1aWRzEj4KEGluY2x1ZGVkU2VydmljZXMYAyADKAsyEi5EaXNjb3ZlcmVkU2VydmljZVIQaW' - '5jbHVkZWRTZXJ2aWNlcxJDCg9jaGFyYWN0ZXJpc3RpY3MYBCADKAsyGS5EaXNjb3ZlcmVkQ2hh' - 'cmFjdGVyaXN0aWNSD2NoYXJhY3RlcmlzdGljcw=='); - + 'ChFEaXNjb3ZlcmVkU2VydmljZRInCgtzZXJ2aWNlVXVpZBgBIAEoCzIFLlV1aWRSC3NlcnZpY2VVdWlkEjcKE2NoYXJhY3RlcmlzdGljVXVpZHMYAiADKAsyBS5VdWlkUhNjaGFyYWN0ZXJpc3RpY1V1aWRzEj4KEGluY2x1ZGVkU2VydmljZXMYAyADKAsyEi5EaXNjb3ZlcmVkU2VydmljZVIQaW5jbHVkZWRTZXJ2aWNlcxJDCg9jaGFyYWN0ZXJpc3RpY3MYBCADKAsyGS5EaXNjb3ZlcmVkQ2hhcmFjdGVyaXN0aWNSD2NoYXJhY3RlcmlzdGljcxIsChFzZXJ2aWNlSW5zdGFuY2VJZBgFIAEoCVIRc2VydmljZUluc3RhbmNlSWQ='); @$core.Deprecated('Use discoveredCharacteristicDescriptor instead') -const DiscoveredCharacteristic$json = { +const DiscoveredCharacteristic$json = const { '1': 'DiscoveredCharacteristic', - '2': [ - {'1': 'characteristicId', '3': 1, '4': 1, '5': 11, '6': '.Uuid', '10': 'characteristicId'}, - {'1': 'serviceId', '3': 2, '4': 1, '5': 11, '6': '.Uuid', '10': 'serviceId'}, - {'1': 'isReadable', '3': 3, '4': 1, '5': 8, '10': 'isReadable'}, - {'1': 'isWritableWithResponse', '3': 4, '4': 1, '5': 8, '10': 'isWritableWithResponse'}, - {'1': 'isWritableWithoutResponse', '3': 5, '4': 1, '5': 8, '10': 'isWritableWithoutResponse'}, - {'1': 'isNotifiable', '3': 6, '4': 1, '5': 8, '10': 'isNotifiable'}, - {'1': 'isIndicatable', '3': 7, '4': 1, '5': 8, '10': 'isIndicatable'}, + '2': const [ + const { + '1': 'characteristicId', + '3': 1, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'characteristicId' + }, + const { + '1': 'serviceId', + '3': 2, + '4': 1, + '5': 11, + '6': '.Uuid', + '10': 'serviceId' + }, + const {'1': 'isReadable', '3': 3, '4': 1, '5': 8, '10': 'isReadable'}, + const { + '1': 'isWritableWithResponse', + '3': 4, + '4': 1, + '5': 8, + '10': 'isWritableWithResponse' + }, + const { + '1': 'isWritableWithoutResponse', + '3': 5, + '4': 1, + '5': 8, + '10': 'isWritableWithoutResponse' + }, + const {'1': 'isNotifiable', '3': 6, '4': 1, '5': 8, '10': 'isNotifiable'}, + const {'1': 'isIndicatable', '3': 7, '4': 1, '5': 8, '10': 'isIndicatable'}, + const { + '1': 'characteristicInstanceId', + '3': 8, + '4': 1, + '5': 9, + '10': 'characteristicInstanceId' + }, ], }; /// Descriptor for `DiscoveredCharacteristic`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List discoveredCharacteristicDescriptor = $convert.base64Decode( - 'ChhEaXNjb3ZlcmVkQ2hhcmFjdGVyaXN0aWMSMQoQY2hhcmFjdGVyaXN0aWNJZBgBIAEoCzIFLl' - 'V1aWRSEGNoYXJhY3RlcmlzdGljSWQSIwoJc2VydmljZUlkGAIgASgLMgUuVXVpZFIJc2Vydmlj' - 'ZUlkEh4KCmlzUmVhZGFibGUYAyABKAhSCmlzUmVhZGFibGUSNgoWaXNXcml0YWJsZVdpdGhSZX' - 'Nwb25zZRgEIAEoCFIWaXNXcml0YWJsZVdpdGhSZXNwb25zZRI8Chlpc1dyaXRhYmxlV2l0aG91' - 'dFJlc3BvbnNlGAUgASgIUhlpc1dyaXRhYmxlV2l0aG91dFJlc3BvbnNlEiIKDGlzTm90aWZpYW' - 'JsZRgGIAEoCFIMaXNOb3RpZmlhYmxlEiQKDWlzSW5kaWNhdGFibGUYByABKAhSDWlzSW5kaWNh' - 'dGFibGU='); +final $typed_data.Uint8List discoveredCharacteristicDescriptor = + $convert.base64Decode( + 'ChhEaXNjb3ZlcmVkQ2hhcmFjdGVyaXN0aWMSMQoQY2hhcmFjdGVyaXN0aWNJZBgBIAEoCzIFLlV1aWRSEGNoYXJhY3RlcmlzdGljSWQSIwoJc2VydmljZUlkGAIgASgLMgUuVXVpZFIJc2VydmljZUlkEh4KCmlzUmVhZGFibGUYAyABKAhSCmlzUmVhZGFibGUSNgoWaXNXcml0YWJsZVdpdGhSZXNwb25zZRgEIAEoCFIWaXNXcml0YWJsZVdpdGhSZXNwb25zZRI8Chlpc1dyaXRhYmxlV2l0aG91dFJlc3BvbnNlGAUgASgIUhlpc1dyaXRhYmxlV2l0aG91dFJlc3BvbnNlEiIKDGlzTm90aWZpYWJsZRgGIAEoCFIMaXNOb3RpZmlhYmxlEiQKDWlzSW5kaWNhdGFibGUYByABKAhSDWlzSW5kaWNhdGFibGUSOgoYY2hhcmFjdGVyaXN0aWNJbnN0YW5jZUlkGAggASgJUhhjaGFyYWN0ZXJpc3RpY0luc3RhbmNlSWQ='); +@$core.Deprecated('Use readRssiRequestDescriptor instead') +const ReadRssiRequest$json = const { + '1': 'ReadRssiRequest', + '2': const [ + const {'1': 'deviceId', '3': 1, '4': 1, '5': 9, '10': 'deviceId'}, + ], +}; + +/// Descriptor for `ReadRssiRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List readRssiRequestDescriptor = $convert.base64Decode( + 'Cg9SZWFkUnNzaVJlcXVlc3QSGgoIZGV2aWNlSWQYASABKAlSCGRldmljZUlk'); +@$core.Deprecated('Use readRssiResultDescriptor instead') +const ReadRssiResult$json = const { + '1': 'ReadRssiResult', + '2': const [ + const {'1': 'rssi', '3': 1, '4': 1, '5': 5, '10': 'rssi'}, + ], +}; +/// Descriptor for `ReadRssiResult`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List readRssiResultDescriptor = + $convert.base64Decode('Cg5SZWFkUnNzaVJlc3VsdBISCgRyc3NpGAEgASgFUgRyc3Np'); @$core.Deprecated('Use uuidDescriptor instead') -const Uuid$json = { +const Uuid$json = const { '1': 'Uuid', - '2': [ - {'1': 'data', '3': 1, '4': 1, '5': 12, '10': 'data'}, + '2': const [ + const {'1': 'data', '3': 1, '4': 1, '5': 12, '10': 'data'}, ], }; /// Descriptor for `Uuid`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List uuidDescriptor = $convert.base64Decode( - 'CgRVdWlkEhIKBGRhdGEYASABKAxSBGRhdGE='); - +final $typed_data.Uint8List uuidDescriptor = + $convert.base64Decode('CgRVdWlkEhIKBGRhdGEYASABKAxSBGRhdGE='); @$core.Deprecated('Use genericFailureDescriptor instead') -const GenericFailure$json = { +const GenericFailure$json = const { '1': 'GenericFailure', - '2': [ - {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, - {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, + '2': const [ + const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, + const {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, ], }; /// Descriptor for `GenericFailure`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List genericFailureDescriptor = $convert.base64Decode( - 'Cg5HZW5lcmljRmFpbHVyZRISCgRjb2RlGAEgASgFUgRjb2RlEhgKB21lc3NhZ2UYAiABKAlSB2' - '1lc3NhZ2U='); - + 'Cg5HZW5lcmljRmFpbHVyZRISCgRjb2RlGAEgASgFUgRjb2RlEhgKB21lc3NhZ2UYAiABKAlSB21lc3NhZ2U='); @$core.Deprecated('Use isConnectableDescriptor instead') -const IsConnectable$json = { +const IsConnectable$json = const { '1': 'IsConnectable', - '2': [ - {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, + '2': const [ + const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, ], }; /// Descriptor for `IsConnectable`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List isConnectableDescriptor = $convert.base64Decode( - 'Cg1Jc0Nvbm5lY3RhYmxlEhIKBGNvZGUYASABKAVSBGNvZGU='); - +final $typed_data.Uint8List isConnectableDescriptor = + $convert.base64Decode('Cg1Jc0Nvbm5lY3RhYmxlEhIKBGNvZGUYASABKAVSBGNvZGU='); diff --git a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbserver.dart b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbserver.dart index 9765515c..d859c88b 100644 --- a/packages/reactive_ble_mobile/lib/src/generated/bledata.pbserver.dart +++ b/packages/reactive_ble_mobile/lib/src/generated/bledata.pbserver.dart @@ -1,14 +1,9 @@ -// +/// // Generated code. Do not modify. // source: bledata.proto // // @dart = 2.12 - -// ignore_for_file: annotate_overrides, camel_case_types -// ignore_for_file: constant_identifier_names -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_final_fields -// ignore_for_file: unnecessary_import, unnecessary_this, unused_import +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name export 'bledata.pb.dart'; diff --git a/packages/reactive_ble_mobile/lib/src/reactive_ble_mobile_platform.dart b/packages/reactive_ble_mobile/lib/src/reactive_ble_mobile_platform.dart index 98baae5a..d21980f9 100644 --- a/packages/reactive_ble_mobile/lib/src/reactive_ble_mobile_platform.dart +++ b/packages/reactive_ble_mobile/lib/src/reactive_ble_mobile_platform.dart @@ -206,7 +206,7 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { } @override - Stream readCharacteristic(QualifiedCharacteristic characteristic) { + Stream readCharacteristic(CharacteristicInstance characteristic) { _logger?.log( 'Read characteristic: $characteristic', ); @@ -222,7 +222,7 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { @override Future writeCharacteristicWithResponse( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ) async { _logger?.log('Write with response to $characteristic, value: $value'); @@ -237,7 +237,7 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { @override Future writeCharacteristicWithoutResponse( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ) async { _logger?.log( @@ -255,7 +255,7 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { @override Stream subscribeToNotifications( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { _logger?.log('Start subscribing to notifications for $characteristic'); return _bleMethodChannel @@ -270,7 +270,7 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { @override Future stopSubscribingToNotifications( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { _logger?.log('Stop subscribing to notifications for $characteristic'); return _bleMethodChannel @@ -340,6 +340,29 @@ class ReactiveBleMobilePlatform extends ReactiveBlePlatform { ) .then((data) => _protobufConverter.discoveredServicesFrom(data!)); } + + @override + Future> getDiscoverServices(String deviceId) async { + _logger?.log('Get discovered services for device: $deviceId'); + return _bleMethodChannel + .invokeMethod>( + 'getDiscoveredServices', + _argsToProtobufConverter + .createDiscoverServicesRequest(deviceId) + .writeToBuffer(), + ) + .then((data) => _protobufConverter.discoveredServicesFrom(data!)); + } + + @override + Future readRssi(String deviceId) async => _bleMethodChannel + .invokeMethod>( + "readRssi", + _argsToProtobufConverter + .createReadRssiRequest(deviceId) + .writeToBuffer(), + ) + .then((data) => _protobufConverter.readRssiResultFrom(data!)); } class ReactiveBleMobilePlatformFactory { diff --git a/packages/reactive_ble_mobile/protos/README.md b/packages/reactive_ble_mobile/protos/README.md index 38ac7b35..c6e76b15 100644 --- a/packages/reactive_ble_mobile/protos/README.md +++ b/packages/reactive_ble_mobile/protos/README.md @@ -18,7 +18,7 @@ brew install swift-protobuf brew install dart ``` -4. Run `pub global activate protoc_plugin` +4. Run `dart pub global activate protoc_plugin` 5. OPTIONAL Add plugin path to `PATH` environment variable 6. Run the following command from the "protos" directory diff --git a/packages/reactive_ble_mobile/protos/bledata.proto b/packages/reactive_ble_mobile/protos/bledata.proto index b6f8a20b..30962542 100644 --- a/packages/reactive_ble_mobile/protos/bledata.proto +++ b/packages/reactive_ble_mobile/protos/bledata.proto @@ -133,6 +133,8 @@ message CharacteristicAddress { string deviceId = 1; Uuid serviceUuid = 2; Uuid characteristicUuid = 3; + string serviceInstanceId = 4; + string characteristicInstanceId = 5; } message ServiceDataEntry { @@ -163,6 +165,7 @@ message DiscoveredService { repeated Uuid characteristicUuids = 2; repeated DiscoveredService includedServices = 3; repeated DiscoveredCharacteristic characteristics = 4; + string serviceInstanceId = 5; } message DiscoveredCharacteristic { @@ -173,6 +176,15 @@ message DiscoveredCharacteristic { bool isWritableWithoutResponse = 5; bool isNotifiable = 6; bool isIndicatable = 7; + string characteristicInstanceId = 8; +} + +message ReadRssiRequest { + string deviceId = 1; +} + +message ReadRssiResult { + int32 rssi = 1; } message Uuid { diff --git a/packages/reactive_ble_mobile/pubspec.lock b/packages/reactive_ble_mobile/pubspec.lock index bb22d54c..b5e65eae 100644 --- a/packages/reactive_ble_mobile/pubspec.lock +++ b/packages/reactive_ble_mobile/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "61.0.0" + version: "67.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "5.13.0" + version: "6.4.1" args: dependency: transitive description: @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -61,34 +61,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.10" + version: "7.3.0" built_collection: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.9.2" characters: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.10.0" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.6" fake_async: dependency: transitive description: @@ -198,6 +198,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" flutter_test: dependency: "direct dev" description: flutter @@ -207,10 +215,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" functional_data: dependency: transitive description: @@ -263,10 +271,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -275,6 +283,38 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + 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: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" logging: dependency: transitive description: @@ -287,42 +327,42 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" mockito: dependency: "direct dev" description: name: mockito - sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" url: "https://pub.dev" source: hosted - version: "5.4.2" + version: "5.4.4" package_config: dependency: transitive description: @@ -335,18 +375,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pool: dependency: transitive description: @@ -385,7 +425,7 @@ packages: path: "../reactive_ble_platform_interface" relative: true source: path - version: "5.1.1" + version: "5.3.1" shelf: dependency: transitive description: @@ -411,34 +451,34 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.5.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -467,10 +507,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" timing: dependency: transitive description: @@ -495,6 +535,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -503,14 +551,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" yaml: dependency: transitive description: @@ -520,5 +576,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=2.0.0" diff --git a/packages/reactive_ble_mobile/pubspec.yaml b/packages/reactive_ble_mobile/pubspec.yaml index 494a8ff1..070e1f13 100644 --- a/packages/reactive_ble_mobile/pubspec.yaml +++ b/packages/reactive_ble_mobile/pubspec.yaml @@ -1,6 +1,6 @@ name: reactive_ble_mobile description: Official Android and iOS implementation for the flutter_reactive_ble plugin. -version: 5.1.1 +version: 5.3.1 homepage: https://github.com/PhilipsHue/flutter_reactive_ble environment: @@ -11,13 +11,19 @@ dependencies: flutter: sdk: flutter protobuf: ^2.0.0 - reactive_ble_platform_interface: ^5.1.1 + reactive_ble_platform_interface: ^5.3.1 + dev_dependencies: build_runner: ^2.3.3 + flutter_lints: ^1.0.4 flutter_test: sdk: flutter mockito: ^5.0.14 +dependency_overrides: + reactive_ble_platform_interface: + path: ../reactive_ble_platform_interface + flutter: plugin: platforms: diff --git a/packages/reactive_ble_mobile/test/converter/args_to_protobuf_converter_test.dart b/packages/reactive_ble_mobile/test/converter/args_to_protobuf_converter_test.dart index 4e6a874b..758ba04c 100644 --- a/packages/reactive_ble_mobile/test/converter/args_to_protobuf_converter_test.dart +++ b/packages/reactive_ble_mobile/test/converter/args_to_protobuf_converter_test.dart @@ -115,28 +115,26 @@ void main() { const deviceId = '123'; final serviceUuid = Uuid.parse('FEFF'); final charUuid = Uuid.parse('FEEF'); - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; setUp(() { - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: charUuid, + characteristicInstanceId: "101", serviceId: serviceUuid, + serviceInstanceId: "11", deviceId: deviceId, ); result = _sut.createReadCharacteristicRequest(characteristic); }); - test('It converts device Id ', () { + test('It converts the ids', () { expect(result.characteristic.deviceId, deviceId); - }); - - test('It converts service Uuid', () { expect(result.characteristic.serviceUuid.data, [254, 255]); - }); - - test('It converts char Uuid', () { + expect(result.characteristic.serviceInstanceId, "11"); expect(result.characteristic.characteristicUuid.data, [254, 239]); + expect(result.characteristic.characteristicInstanceId, "101"); }); }); @@ -145,30 +143,28 @@ void main() { const deviceId = '123'; final serviceUuid = Uuid.parse('FEFF'); final charUuid = Uuid.parse('FEEF'); - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; const value = [0, 1]; setUp(() { - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: charUuid, + characteristicInstanceId: "101", serviceId: serviceUuid, + serviceInstanceId: "11", deviceId: deviceId, ); result = _sut.createWriteCharacteristicRequest(characteristic, value); }); - test('It converts device Id ', () { + test('It converts the ids', () { expect(result.characteristic.deviceId, deviceId); - }); - - test('It converts service Uuid', () { expect(result.characteristic.serviceUuid.data, [254, 255]); - }); - - test('It converts char Uuid', () { + expect(result.characteristic.serviceInstanceId, "11"); expect(result.characteristic.characteristicUuid.data, [254, 239]); + expect(result.characteristic.characteristicInstanceId, "101"); }); test('It converts value', () { @@ -181,28 +177,26 @@ void main() { const deviceId = '123'; final serviceUuid = Uuid.parse('FEFF'); final charUuid = Uuid.parse('FEEF'); - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; setUp(() { - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: charUuid, + characteristicInstanceId: "101", serviceId: serviceUuid, + serviceInstanceId: "11", deviceId: deviceId, ); result = _sut.createNotifyCharacteristicRequest(characteristic); }); - test('It converts device Id ', () { + test('It converts device ids', () { expect(result.characteristic.deviceId, deviceId); - }); - - test('It converts service Uuid', () { expect(result.characteristic.serviceUuid.data, [254, 255]); - }); - - test('It converts char Uuid', () { + expect(result.characteristic.serviceInstanceId, "11"); expect(result.characteristic.characteristicUuid.data, [254, 239]); + expect(result.characteristic.characteristicInstanceId, "101"); }); }); @@ -365,28 +359,26 @@ void main() { const deviceId = '123'; final serviceUuid = Uuid.parse('FEFF'); final charUuid = Uuid.parse('FEEF'); - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; late pb.NotifyNoMoreCharacteristicRequest result; setUp(() { - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: charUuid, + characteristicInstanceId: "101", serviceId: serviceUuid, + serviceInstanceId: "11", deviceId: deviceId, ); result = _sut.createNotifyNoMoreCharacteristicRequest(characteristic); }); - test('It converts deviceId', () { + test('It converts the ids', () { expect(result.characteristic.deviceId, deviceId); - }); - - test('It converts serviceUuid', () { expect(result.characteristic.serviceUuid.data, [254, 255]); - }); - - test('It converts characteristicUuid', () { + expect(result.characteristic.serviceInstanceId, "11"); expect(result.characteristic.characteristicUuid.data, [254, 239]); + expect(result.characteristic.characteristicInstanceId, "101"); }); }); diff --git a/packages/reactive_ble_mobile/test/converter/protobuf_converter_test.dart b/packages/reactive_ble_mobile/test/converter/protobuf_converter_test.dart index 99420675..ec3e9830 100644 --- a/packages/reactive_ble_mobile/test/converter/protobuf_converter_test.dart +++ b/packages/reactive_ble_mobile/test/converter/protobuf_converter_test.dart @@ -514,9 +514,11 @@ void main() { final discoveredInternalServices = pb.DiscoveredService() ..serviceUuid = internalServiceUuid + ..serviceInstanceId = '11' ..characteristics.add( pb.DiscoveredCharacteristic() ..characteristicId = internalCharUuid + ..characteristicInstanceId = '102' ..serviceId = internalServiceUuid ..isReadable = true, ) @@ -524,10 +526,12 @@ void main() { final discoveredService = pb.DiscoveredService() ..serviceUuid = serviceUuid + ..serviceInstanceId = '10' ..characteristicUuids.add(charUuid) ..characteristics.add( pb.DiscoveredCharacteristic() ..characteristicId = charUuid + ..characteristicInstanceId = '101' ..serviceId = serviceUuid ..isWritableWithResponse = true, ) @@ -546,12 +550,14 @@ void main() { [ DiscoveredService( serviceId: Uuid([0]), + serviceInstanceId: '10', characteristicIds: [ Uuid([0, 1, 1]) ], characteristics: [ DiscoveredCharacteristic( characteristicId: Uuid([0, 1, 1]), + characteristicInstanceId: '101', serviceId: Uuid([0]), isReadable: false, isWritableWithResponse: true, @@ -562,12 +568,14 @@ void main() { ], includedServices: [ DiscoveredService( + serviceInstanceId: '11', serviceId: Uuid([1]), characteristicIds: [ Uuid([1, 1]) ], characteristics: [ DiscoveredCharacteristic( + characteristicInstanceId: '102', characteristicId: Uuid([1, 1]), serviceId: Uuid([1]), isReadable: true, diff --git a/packages/reactive_ble_mobile/test/reactive_ble_platform_test.dart b/packages/reactive_ble_mobile/test/reactive_ble_platform_test.dart index d9a20f98..ea60c6a4 100644 --- a/packages/reactive_ble_mobile/test/reactive_ble_platform_test.dart +++ b/packages/reactive_ble_mobile/test/reactive_ble_platform_test.dart @@ -11,6 +11,7 @@ import 'package:reactive_ble_mobile/src/reactive_ble_mobile_platform.dart'; import 'package:reactive_ble_platform_interface/reactive_ble_platform_interface.dart'; import 'reactive_ble_platform_test.mocks.dart'; + // ignore_for_file: avoid_implementing_value_types @GenerateMocks([ @@ -140,9 +141,11 @@ void main() { setUp(() { valueUpdate = CharacteristicValue( - characteristic: QualifiedCharacteristic( + characteristic: CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ), result: const Result.success([1]), @@ -166,14 +169,16 @@ void main() { }); group('Read characteristic', () { - late QualifiedCharacteristic characteristic; + late CharacteristicInstance characteristic; late pb.ReadCharacteristicRequest request; setUp(() { request = pb.ReadCharacteristicRequest(); - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); when(_argsConverter.createReadCharacteristicRequest(characteristic)) @@ -197,7 +202,7 @@ void main() { }); group('Write characteristic with response', () { - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; const value = [0, 1]; late pb.WriteCharacteristicRequest request; late WriteCharacteristicInfo expectedResult; @@ -206,9 +211,11 @@ void main() { setUp(() async { request = pb.WriteCharacteristicRequest(); - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "11", deviceId: '123', ); @@ -248,7 +255,7 @@ void main() { }); group('Write characteristic without response', () { - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; const value = [0, 1]; late pb.WriteCharacteristicRequest request; late WriteCharacteristicInfo expectedResult; @@ -256,17 +263,18 @@ void main() { setUp(() async { request = pb.WriteCharacteristicRequest(); - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); expectedResult = WriteCharacteristicInfo( - // ignore: void_checks characteristic: characteristic, - // ignore: void_checks - result: const Result.success(Unit())); + result: const Result.success(Unit()), + ); when(_methodChannel.invokeMethod?>(any, any)).thenAnswer( (_) async => value, @@ -300,14 +308,16 @@ void main() { }); group('Subscribe to notifications', () { - late QualifiedCharacteristic characteristic; + late CharacteristicInstance characteristic; late pb.NotifyCharacteristicRequest request; setUp(() { request = pb.NotifyCharacteristicRequest(); - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); @@ -337,14 +347,16 @@ void main() { }); group('Stop subscribe to notifications', () { - QualifiedCharacteristic characteristic; + CharacteristicInstance characteristic; late pb.NotifyNoMoreCharacteristicRequest request; setUp(() async { request = pb.NotifyNoMoreCharacteristicRequest(); - characteristic = QualifiedCharacteristic( + characteristic = CharacteristicInstance( characteristicId: Uuid.parse('FEFF'), + characteristicInstanceId: "11", serviceId: Uuid.parse('FEFF'), + serviceInstanceId: "101", deviceId: '123', ); @@ -600,6 +612,7 @@ void main() { final services = [ DiscoveredService( serviceId: Uuid([0x01, 0x02]), + serviceInstanceId: "101", characteristicIds: const [], characteristics: const [], includedServices: const [], diff --git a/packages/reactive_ble_mobile/test/reactive_ble_platform_test.mocks.dart b/packages/reactive_ble_mobile/test/reactive_ble_platform_test.mocks.dart index 447cf90f..702916cd 100644 --- a/packages/reactive_ble_mobile/test/reactive_ble_platform_test.mocks.dart +++ b/packages/reactive_ble_mobile/test/reactive_ble_platform_test.mocks.dart @@ -1,14 +1,15 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in reactive_ble_mobile/test/reactive_ble_platform_test.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i9; +import 'dart:async' as _i10; import 'package:flutter/src/services/binary_messenger.dart' as _i5; import 'package:flutter/src/services/message_codec.dart' as _i4; -import 'package:flutter/src/services/platform_channel.dart' as _i8; +import 'package:flutter/src/services/platform_channel.dart' as _i9; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i8; import 'package:reactive_ble_mobile/src/converter/args_to_protubuf_converter.dart' as _i6; import 'package:reactive_ble_mobile/src/converter/protobuf_converter.dart' @@ -21,6 +22,8 @@ import 'package:reactive_ble_platform_interface/reactive_ble_platform_interface. // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -182,9 +185,20 @@ class _FakeDiscoverServicesRequest_13 extends _i1.SmartFake ); } -class _FakeDeviceAssociationInfo_14 extends _i1.SmartFake +class _FakeReadRssiRequest_14 extends _i1.SmartFake + implements _i2.ReadRssiRequest { + _FakeReadRssiRequest_14( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDeviceAssociationInfo_15 extends _i1.SmartFake implements _i3.DeviceAssociationInfo { - _FakeDeviceAssociationInfo_14( + _FakeDeviceAssociationInfo_15( Object parent, Invocation parentInvocation, ) : super( @@ -193,8 +207,8 @@ class _FakeDeviceAssociationInfo_14 extends _i1.SmartFake ); } -class _FakeScanResult_15 extends _i1.SmartFake implements _i3.ScanResult { - _FakeScanResult_15( +class _FakeScanResult_16 extends _i1.SmartFake implements _i3.ScanResult { + _FakeScanResult_16( Object parent, Invocation parentInvocation, ) : super( @@ -203,9 +217,9 @@ class _FakeScanResult_15 extends _i1.SmartFake implements _i3.ScanResult { ); } -class _FakeConnectionStateUpdate_16 extends _i1.SmartFake +class _FakeConnectionStateUpdate_17 extends _i1.SmartFake implements _i3.ConnectionStateUpdate { - _FakeConnectionStateUpdate_16( + _FakeConnectionStateUpdate_17( Object parent, Invocation parentInvocation, ) : super( @@ -214,9 +228,9 @@ class _FakeConnectionStateUpdate_16 extends _i1.SmartFake ); } -class _FakeResult_17 extends _i1.SmartFake +class _FakeResult_18 extends _i1.SmartFake implements _i3.Result { - _FakeResult_17( + _FakeResult_18( Object parent, Invocation parentInvocation, ) : super( @@ -225,9 +239,9 @@ class _FakeResult_17 extends _i1.SmartFake ); } -class _FakeCharacteristicValue_18 extends _i1.SmartFake +class _FakeCharacteristicValue_19 extends _i1.SmartFake implements _i3.CharacteristicValue { - _FakeCharacteristicValue_18( + _FakeCharacteristicValue_19( Object parent, Invocation parentInvocation, ) : super( @@ -236,9 +250,9 @@ class _FakeCharacteristicValue_18 extends _i1.SmartFake ); } -class _FakeWriteCharacteristicInfo_19 extends _i1.SmartFake +class _FakeWriteCharacteristicInfo_20 extends _i1.SmartFake implements _i3.WriteCharacteristicInfo { - _FakeWriteCharacteristicInfo_19( + _FakeWriteCharacteristicInfo_20( Object parent, Invocation parentInvocation, ) : super( @@ -247,9 +261,9 @@ class _FakeWriteCharacteristicInfo_19 extends _i1.SmartFake ); } -class _FakeConnectionPriorityInfo_20 extends _i1.SmartFake +class _FakeConnectionPriorityInfo_21 extends _i1.SmartFake implements _i3.ConnectionPriorityInfo { - _FakeConnectionPriorityInfo_20( + _FakeConnectionPriorityInfo_21( Object parent, Invocation parentInvocation, ) : super( @@ -258,8 +272,8 @@ class _FakeConnectionPriorityInfo_20 extends _i1.SmartFake ); } -class _FakeMethodCodec_21 extends _i1.SmartFake implements _i4.MethodCodec { - _FakeMethodCodec_21( +class _FakeMethodCodec_22 extends _i1.SmartFake implements _i4.MethodCodec { + _FakeMethodCodec_22( Object parent, Invocation parentInvocation, ) : super( @@ -268,9 +282,9 @@ class _FakeMethodCodec_21 extends _i1.SmartFake implements _i4.MethodCodec { ); } -class _FakeBinaryMessenger_22 extends _i1.SmartFake +class _FakeBinaryMessenger_23 extends _i1.SmartFake implements _i5.BinaryMessenger { - _FakeBinaryMessenger_22( + _FakeBinaryMessenger_23( Object parent, Invocation parentInvocation, ) : super( @@ -303,6 +317,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.EstablishBondingRequest); + @override _i2.ConnectToDeviceRequest createConnectToDeviceArgs( String? id, @@ -330,6 +345,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.ConnectToDeviceRequest); + @override _i2.GetDeviceNameRequest createGetDeviceNameArgs(String? id) => (super.noSuchMethod( @@ -345,6 +361,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.GetDeviceNameRequest); + @override _i2.DisconnectFromDeviceRequest createDisconnectDeviceArgs( String? deviceId) => @@ -361,9 +378,10 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.DisconnectFromDeviceRequest); + @override _i2.ReadCharacteristicRequest createReadCharacteristicRequest( - _i3.QualifiedCharacteristic? characteristic) => + _i3.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #createReadCharacteristicRequest, @@ -377,9 +395,10 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.ReadCharacteristicRequest); + @override _i2.WriteCharacteristicRequest createWriteCharacteristicRequest( - _i3.QualifiedCharacteristic? characteristic, + _i3.CharacteristicInstance? characteristic, List? value, ) => (super.noSuchMethod( @@ -401,9 +420,10 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.WriteCharacteristicRequest); + @override _i2.NotifyCharacteristicRequest createNotifyCharacteristicRequest( - _i3.QualifiedCharacteristic? characteristic) => + _i3.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #createNotifyCharacteristicRequest, @@ -417,9 +437,10 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.NotifyCharacteristicRequest); + @override _i2.NotifyNoMoreCharacteristicRequest createNotifyNoMoreCharacteristicRequest( - _i3.QualifiedCharacteristic? characteristic) => + _i3.CharacteristicInstance? characteristic) => (super.noSuchMethod( Invocation.method( #createNotifyNoMoreCharacteristicRequest, @@ -433,6 +454,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.NotifyNoMoreCharacteristicRequest); + @override _i2.NegotiateMtuRequest createNegotiateMtuRequest( String? deviceId, @@ -457,6 +479,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.NegotiateMtuRequest); + @override _i2.ChangeConnectionPriorityRequest createChangeConnectionPrioRequest( String? deviceId, @@ -481,6 +504,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.ChangeConnectionPriorityRequest); + @override _i2.LaunchCompanionRequest createLaunchCompanionWorkflowRequest({ required String? deviceNamePattern, @@ -510,6 +534,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.LaunchCompanionRequest); + @override _i2.ScanForDevicesRequest createScanForDevicesRequest({ required List<_i3.Uuid>? withServices, @@ -539,6 +564,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.ScanForDevicesRequest); + @override _i2.ClearGattCacheRequest createClearGattCacheRequest(String? deviceId) => (super.noSuchMethod( @@ -554,6 +580,7 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.ClearGattCacheRequest); + @override _i2.DiscoverServicesRequest createDiscoverServicesRequest(String? deviceId) => (super.noSuchMethod( @@ -569,6 +596,22 @@ class MockArgsToProtobufConverter extends _i1.Mock ), ), ) as _i2.DiscoverServicesRequest); + + @override + _i2.ReadRssiRequest createReadRssiRequest(String? deviceId) => + (super.noSuchMethod( + Invocation.method( + #createReadRssiRequest, + [deviceId], + ), + returnValue: _FakeReadRssiRequest_14( + this, + Invocation.method( + #createReadRssiRequest, + [deviceId], + ), + ), + ) as _i2.ReadRssiRequest); } /// A class which mocks [ProtobufConverter]. @@ -587,6 +630,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), returnValue: _i3.BondingStatus.none, ) as _i3.BondingStatus); + @override _i3.BleStatus bleStatusFrom(List? data) => (super.noSuchMethod( Invocation.method( @@ -595,6 +639,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), returnValue: _i3.BleStatus.unknown, ) as _i3.BleStatus); + @override _i3.DeviceAssociationInfo associationInfoFrom(List? data) => (super.noSuchMethod( @@ -602,7 +647,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #associationInfoFrom, [data], ), - returnValue: _FakeDeviceAssociationInfo_14( + returnValue: _FakeDeviceAssociationInfo_15( this, Invocation.method( #associationInfoFrom, @@ -610,13 +655,14 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.DeviceAssociationInfo); + @override _i3.ScanResult scanResultFrom(List? data) => (super.noSuchMethod( Invocation.method( #scanResultFrom, [data], ), - returnValue: _FakeScanResult_15( + returnValue: _FakeScanResult_16( this, Invocation.method( #scanResultFrom, @@ -624,14 +670,22 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.ScanResult); + @override String deviceNameFrom(List? data) => (super.noSuchMethod( Invocation.method( #deviceNameFrom, [data], ), - returnValue: '', + returnValue: _i8.dummyValue( + this, + Invocation.method( + #deviceNameFrom, + [data], + ), + ), ) as String); + @override _i3.ConnectionStateUpdate connectionStateUpdateFrom(List? data) => (super.noSuchMethod( @@ -639,7 +693,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #connectionStateUpdateFrom, [data], ), - returnValue: _FakeConnectionStateUpdate_16( + returnValue: _FakeConnectionStateUpdate_17( this, Invocation.method( #connectionStateUpdateFrom, @@ -647,6 +701,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.ConnectionStateUpdate); + @override _i3.Result<_i3.Unit, _i3.GenericFailure<_i3.ClearGattCacheError>?> clearGattCacheResultFrom(List? data) => (super.noSuchMethod( @@ -654,7 +709,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #clearGattCacheResultFrom, [data], ), - returnValue: _FakeResult_17<_i3.Unit, + returnValue: _FakeResult_18<_i3.Unit, _i3.GenericFailure<_i3.ClearGattCacheError>?>( this, Invocation.method( @@ -664,6 +719,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ) as _i3 .Result<_i3.Unit, _i3.GenericFailure<_i3.ClearGattCacheError>?>); + @override _i3.CharacteristicValue characteristicValueFrom(List? data) => (super.noSuchMethod( @@ -671,7 +727,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #characteristicValueFrom, [data], ), - returnValue: _FakeCharacteristicValue_18( + returnValue: _FakeCharacteristicValue_19( this, Invocation.method( #characteristicValueFrom, @@ -679,6 +735,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.CharacteristicValue); + @override _i3.WriteCharacteristicInfo writeCharacteristicInfoFrom(List? data) => (super.noSuchMethod( @@ -686,7 +743,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #writeCharacteristicInfoFrom, [data], ), - returnValue: _FakeWriteCharacteristicInfo_19( + returnValue: _FakeWriteCharacteristicInfo_20( this, Invocation.method( #writeCharacteristicInfoFrom, @@ -694,6 +751,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.WriteCharacteristicInfo); + @override _i3.ConnectionPriorityInfo connectionPriorityInfoFrom(List? data) => (super.noSuchMethod( @@ -701,7 +759,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { #connectionPriorityInfoFrom, [data], ), - returnValue: _FakeConnectionPriorityInfo_20( + returnValue: _FakeConnectionPriorityInfo_21( this, Invocation.method( #connectionPriorityInfoFrom, @@ -709,6 +767,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), ), ) as _i3.ConnectionPriorityInfo); + @override int mtuSizeFrom(List? data) => (super.noSuchMethod( Invocation.method( @@ -717,6 +776,7 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), returnValue: 0, ) as int); + @override List<_i3.DiscoveredService> discoveredServicesFrom(List? data) => (super.noSuchMethod( @@ -726,12 +786,21 @@ class MockProtobufConverter extends _i1.Mock implements _i7.ProtobufConverter { ), returnValue: <_i3.DiscoveredService>[], ) as List<_i3.DiscoveredService>); + + @override + int readRssiResultFrom(List? data) => (super.noSuchMethod( + Invocation.method( + #readRssiResultFrom, + [data], + ), + returnValue: 0, + ) as int); } /// A class which mocks [MethodChannel]. /// /// See the documentation for Mockito's code generation for more information. -class MockMethodChannel extends _i1.Mock implements _i8.MethodChannel { +class MockMethodChannel extends _i1.Mock implements _i9.MethodChannel { MockMethodChannel() { _i1.throwOnMissingStub(this); } @@ -739,26 +808,32 @@ class MockMethodChannel extends _i1.Mock implements _i8.MethodChannel { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i8.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); + @override _i4.MethodCodec get codec => (super.noSuchMethod( Invocation.getter(#codec), - returnValue: _FakeMethodCodec_21( + returnValue: _FakeMethodCodec_22( this, Invocation.getter(#codec), ), ) as _i4.MethodCodec); + @override _i5.BinaryMessenger get binaryMessenger => (super.noSuchMethod( Invocation.getter(#binaryMessenger), - returnValue: _FakeBinaryMessenger_22( + returnValue: _FakeBinaryMessenger_23( this, Invocation.getter(#binaryMessenger), ), ) as _i5.BinaryMessenger); + @override - _i9.Future invokeMethod( + _i10.Future invokeMethod( String? method, [ dynamic arguments, ]) => @@ -770,10 +845,11 @@ class MockMethodChannel extends _i1.Mock implements _i8.MethodChannel { arguments, ], ), - returnValue: _i9.Future.value(), - ) as _i9.Future); + returnValue: _i10.Future.value(), + ) as _i10.Future); + @override - _i9.Future?> invokeListMethod( + _i10.Future?> invokeListMethod( String? method, [ dynamic arguments, ]) => @@ -785,10 +861,11 @@ class MockMethodChannel extends _i1.Mock implements _i8.MethodChannel { arguments, ], ), - returnValue: _i9.Future?>.value(), - ) as _i9.Future?>); + returnValue: _i10.Future?>.value(), + ) as _i10.Future?>); + @override - _i9.Future?> invokeMapMethod( + _i10.Future?> invokeMapMethod( String? method, [ dynamic arguments, ]) => @@ -800,11 +877,12 @@ class MockMethodChannel extends _i1.Mock implements _i8.MethodChannel { arguments, ], ), - returnValue: _i9.Future?>.value(), - ) as _i9.Future?>); + returnValue: _i10.Future?>.value(), + ) as _i10.Future?>); + @override void setMethodCallHandler( - _i9.Future Function(_i4.MethodCall)? handler) => + _i10.Future Function(_i4.MethodCall)? handler) => super.noSuchMethod( Invocation.method( #setMethodCallHandler, diff --git a/packages/reactive_ble_platform_interface/CHANGELOG.md b/packages/reactive_ble_platform_interface/CHANGELOG.md index 66f76324..08a7e299 100644 --- a/packages/reactive_ble_platform_interface/CHANGELOG.md +++ b/packages/reactive_ble_platform_interface/CHANGELOG.md @@ -1,3 +1,27 @@ +## 5.3.1 + +* Use proper platform_interface dependency version #837 + +## 5.3.0 + +* Readd accidentally removed version constraint #789 +* Add a placeholder implementation for non-mobile platforms #688 +* Add Github actions and Migrate to latest Android SDK, AGP and protobuf plugin #830 +* Include packages lock-files #797 +* Update Kotlin version in README #831 +* Migrate away from deprecated strong mode analysis options #832 +* Read RSSI #796 + +## 5.2.0 + +* Bump the minimum requirement to Dart 2.17 and upgrade melos to 3.1.0 in #762 +* swiftlint config and inital formatting pass in #765 +* Cancel subscription when a disconnect event has been thrown in #769 +* Fix typos in #778 +* Update CI config to use Xcode 14 in #786 +* Support multiple services or characteristics with the same id in #776 +* Breaking change: If a device has multiple characteristics with the same ID, `readCharacteristic`, `writeCharacteristic` and `subscribeToCharacteristic` used to select the first of those characteristics. Now they will fail in this case. Use `resolve` or `getDiscoveredServices` instead. + ## 5.1.1 * Make Connectable backwards compatible #757, #750 diff --git a/packages/reactive_ble_platform_interface/lib/src/model/characteristic_instance.dart b/packages/reactive_ble_platform_interface/lib/src/model/characteristic_instance.dart new file mode 100644 index 00000000..8b478353 --- /dev/null +++ b/packages/reactive_ble_platform_interface/lib/src/model/characteristic_instance.dart @@ -0,0 +1,56 @@ +import 'package:meta/meta.dart'; + +import 'uuid.dart'; + +@immutable +class CharacteristicInstance { + /// Unique uuid of the specific characteristic + final Uuid characteristicId; + + /// The id that identifies the specific instance of all characteristics with [characteristicId] in a given service. + /// This should no be exposed to user of the plugin as it may be different each time a device is connected to, so it + /// should not be used to identify characteristics across sessions. + final String characteristicInstanceId; + + /// Service uuid of the characteristic + final Uuid serviceId; + + /// The id that identifies the specific instance of all services with [serviceId] in a given device. + /// This should no be exposed to user of the plugin as it may be different each time a device is connected to, so it + /// should not be used to identify characteristics across sessions. + final String serviceInstanceId; + + /// Device id of the BLE device + final String deviceId; + + const CharacteristicInstance({ + required this.characteristicId, + required this.characteristicInstanceId, + required this.serviceId, + required this.serviceInstanceId, + required this.deviceId, + }); + + @override + String toString() => "$runtimeType(characteristicId: $characteristicId($characteristicInstanceId), " + "serviceId: $serviceId($serviceInstanceId), deviceId: $deviceId)"; + + @override + int get hashCode => Object.hash( + characteristicId.expanded, + characteristicInstanceId, + serviceId.expanded, + serviceInstanceId, + deviceId, + ); + + @override + bool operator ==(Object other) => + other is CharacteristicInstance && + runtimeType == other.runtimeType && + characteristicId.expanded == other.characteristicId.expanded && + characteristicInstanceId == other.characteristicInstanceId && + serviceId.expanded == other.serviceId.expanded && + serviceInstanceId == other.serviceInstanceId && + deviceId == other.deviceId; +} diff --git a/packages/reactive_ble_platform_interface/lib/src/model/characteristic_value.dart b/packages/reactive_ble_platform_interface/lib/src/model/characteristic_value.dart index a7f3da52..4a1aceec 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/characteristic_value.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/characteristic_value.dart @@ -1,10 +1,10 @@ +import 'characteristic_instance.dart'; import 'generic_failure.dart'; -import 'qualified_characteristic.dart'; import 'result.dart'; -/// Value update for specific [QualifiedCharacteristic]. +/// Value update for specific [CharacteristicInstance]. class CharacteristicValue { - final QualifiedCharacteristic characteristic; + final CharacteristicInstance characteristic; final Result, GenericFailure?> result; diff --git a/packages/reactive_ble_platform_interface/lib/src/model/connection_priority.dart b/packages/reactive_ble_platform_interface/lib/src/model/connection_priority.dart index 2ad3951f..c16d8b24 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/connection_priority.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/connection_priority.dart @@ -9,7 +9,7 @@ enum ConnectionPriority { /// high priority, low latency connection. highPerformance, - // reduced power, low data rate connennection. + // reduced power, low data rate connection. lowPower, } diff --git a/packages/reactive_ble_platform_interface/lib/src/model/discovered_characteristic.dart b/packages/reactive_ble_platform_interface/lib/src/model/discovered_characteristic.dart index 3e0a721f..dd341788 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/discovered_characteristic.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/discovered_characteristic.dart @@ -2,13 +2,15 @@ import 'package:meta/meta.dart'; import 'uuid.dart'; -/// Specific BLE characteristic for a BLE device characterised by [deviceId], [serviceId] and +/// Specific BLE characteristic for a BLE device characterized by [deviceId], [serviceId] and /// [characteristicId]. @immutable class DiscoveredCharacteristic { /// Unique uuid of the specific characteristic final Uuid characteristicId; + final String characteristicInstanceId; + /// Service uuid of the characteristic final Uuid serviceId; @@ -21,6 +23,7 @@ class DiscoveredCharacteristic { const DiscoveredCharacteristic({ required this.characteristicId, + required this.characteristicInstanceId, required this.serviceId, required this.isReadable, required this.isWritableWithResponse, diff --git a/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.dart b/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.dart index 90f10b01..468eda60 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.dart @@ -5,12 +5,14 @@ import 'package:reactive_ble_platform_interface/src/model/discovered_characteris import 'uuid.dart'; part 'discovered_service.g.dart'; + //ignore_for_file: annotate_overrides @FunctionalData() class DiscoveredService extends $DiscoveredService { const DiscoveredService({ required this.serviceId, + required this.serviceInstanceId, required this.characteristicIds, required this.characteristics, this.includedServices = const [], @@ -18,6 +20,8 @@ class DiscoveredService extends $DiscoveredService { final Uuid serviceId; + final String serviceInstanceId; + @CustomEquality(DeepCollectionEquality()) final List characteristicIds; diff --git a/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.g.dart b/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.g.dart index 01a3aec7..fe6fdbd4 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.g.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/discovered_service.g.dart @@ -10,18 +10,21 @@ abstract class $DiscoveredService { const $DiscoveredService(); Uuid get serviceId; + String get serviceInstanceId; List get characteristicIds; List get characteristics; List get includedServices; DiscoveredService copyWith({ Uuid? serviceId, + String? serviceInstanceId, List? characteristicIds, List? characteristics, List? includedServices, }) => DiscoveredService( serviceId: serviceId ?? this.serviceId, + serviceInstanceId: serviceInstanceId ?? this.serviceInstanceId, characteristicIds: characteristicIds ?? this.characteristicIds, characteristics: characteristics ?? this.characteristics, includedServices: includedServices ?? this.includedServices, @@ -31,6 +34,7 @@ abstract class $DiscoveredService { void Function(DiscoveredService$Change change) mutator) { final change = DiscoveredService$Change._( this.serviceId, + this.serviceInstanceId, this.characteristicIds, this.characteristics, this.includedServices, @@ -38,6 +42,7 @@ abstract class $DiscoveredService { mutator(change); return DiscoveredService( serviceId: change.serviceId, + serviceInstanceId: change.serviceInstanceId, characteristicIds: change.characteristicIds, characteristics: change.characteristics, includedServices: change.includedServices, @@ -46,7 +51,7 @@ abstract class $DiscoveredService { @override String toString() => - "DiscoveredService(serviceId: $serviceId, characteristicIds: $characteristicIds, characteristics: $characteristics, includedServices: $includedServices)"; + "DiscoveredService(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, characteristicIds: $characteristicIds, characteristics: $characteristics, includedServices: $includedServices)"; @override // ignore: avoid_equals_and_hash_code_on_mutable_classes @@ -54,6 +59,7 @@ abstract class $DiscoveredService { other is DiscoveredService && other.runtimeType == runtimeType && serviceId == other.serviceId && + serviceInstanceId == other.serviceInstanceId && const DeepCollectionEquality() .equals(characteristicIds, other.characteristicIds) && const DeepCollectionEquality() @@ -66,6 +72,7 @@ abstract class $DiscoveredService { int get hashCode { var result = 17; result = 37 * result + serviceId.hashCode; + result = 37 * result + serviceInstanceId.hashCode; result = 37 * result + const DeepCollectionEquality().hash(characteristicIds); result = 37 * result + const DeepCollectionEquality().hash(characteristics); @@ -78,12 +85,14 @@ abstract class $DiscoveredService { class DiscoveredService$Change { DiscoveredService$Change._( this.serviceId, + this.serviceInstanceId, this.characteristicIds, this.characteristics, this.includedServices, ); Uuid serviceId; + String serviceInstanceId; List characteristicIds; List characteristics; List includedServices; @@ -97,6 +106,14 @@ class DiscoveredService$ { serviceIdContainer.copyWith(serviceId: serviceId), ); + static final serviceInstanceId = Lens( + (serviceInstanceIdContainer) => + serviceInstanceIdContainer.serviceInstanceId, + (serviceInstanceIdContainer, serviceInstanceId) => + serviceInstanceIdContainer.copyWith( + serviceInstanceId: serviceInstanceId), + ); + static final characteristicIds = Lens>( (characteristicIdsContainer) => characteristicIdsContainer.characteristicIds, diff --git a/packages/reactive_ble_platform_interface/lib/src/model/log_level.dart b/packages/reactive_ble_platform_interface/lib/src/model/log_level.dart index a04deb14..5cd999a6 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/log_level.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/log_level.dart @@ -1,4 +1,4 @@ -/// States the level of debuglogging within this library +/// States the level of debug logging within this library enum LogLevel { /// No debugLogging at all. This is the default level within the library. none, diff --git a/packages/reactive_ble_platform_interface/lib/src/model/qualified_characteristic.dart b/packages/reactive_ble_platform_interface/lib/src/model/qualified_characteristic.dart index b04bf73e..e1486ea2 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/qualified_characteristic.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/qualified_characteristic.dart @@ -2,7 +2,7 @@ import 'package:meta/meta.dart'; import 'uuid.dart'; -/// Specific BLE characteristic for a BLE device characterised by [deviceId], [serviceId] and +/// Specific BLE characteristic for a BLE device characterized by [deviceId], [serviceId] and /// [characteristicId]. @immutable class QualifiedCharacteristic { diff --git a/packages/reactive_ble_platform_interface/lib/src/model/result.dart b/packages/reactive_ble_platform_interface/lib/src/model/result.dart index 03f1ead4..1aa41932 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/result.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/result.dart @@ -2,7 +2,7 @@ import 'package:meta/meta.dart'; ///Result of a ble operation. /// -/// In case the result is succesfull [Failure] is null. +/// In case the result is successful [Failure] is null. @immutable class Result { const Result.success(this._value) diff --git a/packages/reactive_ble_platform_interface/lib/src/model/scan_mode.dart b/packages/reactive_ble_platform_interface/lib/src/model/scan_mode.dart index ed32889b..63d5d1a5 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/scan_mode.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/scan_mode.dart @@ -1,16 +1,16 @@ -///Android only: mode in which BLE discovery is executed. +/// Android only: mode in which BLE discovery is executed. enum ScanMode { /// passively listen for other scan results without starting BLE scan itself. opportunistic, - /// scanmode which has the lowest battery consumption. + /// Scan mode which has the lowest battery consumption. lowPower, - /// scanmode that is a good compromise between battery consumption and latency. + /// Scan mode that is a good compromise between battery consumption and latency. balanced, - ///Scanmode with highest battery consumption and lowest latency. - ///Should not be used when scanning for a long time. + /// Scan mode with highest battery consumption and lowest latency. + /// Should not be used when scanning for a long time. lowLatency, } diff --git a/packages/reactive_ble_platform_interface/lib/src/model/uuid.dart b/packages/reactive_ble_platform_interface/lib/src/model/uuid.dart index c93c7202..ad78aa7d 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/uuid.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/uuid.dart @@ -41,6 +41,15 @@ class Uuid { } } + /// Expands a 16 bit uuid to a 128 bit one + Uuid get expanded { + if (data.length == 2) { + return Uuid.parse("0000$this-0000-1000-8000-00805f9b34fb"); + } else { + return this; + } + } + @override String toString() { String paddedHex(int num) { diff --git a/packages/reactive_ble_platform_interface/lib/src/model/write_characteristic_info.dart b/packages/reactive_ble_platform_interface/lib/src/model/write_characteristic_info.dart index 5f619a93..1cf19977 100644 --- a/packages/reactive_ble_platform_interface/lib/src/model/write_characteristic_info.dart +++ b/packages/reactive_ble_platform_interface/lib/src/model/write_characteristic_info.dart @@ -1,13 +1,13 @@ import 'package:meta/meta.dart'; +import 'characteristic_instance.dart'; import 'generic_failure.dart'; -import 'qualified_characteristic.dart'; import 'result.dart'; import 'unit.dart'; @immutable class WriteCharacteristicInfo { - final QualifiedCharacteristic characteristic; + final CharacteristicInstance characteristic; final Result?> result; const WriteCharacteristicInfo({ diff --git a/packages/reactive_ble_platform_interface/lib/src/models.dart b/packages/reactive_ble_platform_interface/lib/src/models.dart index 9dcf0375..faef0524 100644 --- a/packages/reactive_ble_platform_interface/lib/src/models.dart +++ b/packages/reactive_ble_platform_interface/lib/src/models.dart @@ -1,5 +1,6 @@ export './model/ble_status.dart'; export './model/bonding_status.dart'; +export './model/characteristic_instance.dart'; export './model/characteristic_value.dart'; export './model/clear_gatt_cache_error.dart'; export './model/connection_priority.dart'; diff --git a/packages/reactive_ble_platform_interface/lib/src/reactive_ble_platform_interface.dart b/packages/reactive_ble_platform_interface/lib/src/reactive_ble_platform_interface.dart index a7acb7cf..252f218e 100644 --- a/packages/reactive_ble_platform_interface/lib/src/reactive_ble_platform_interface.dart +++ b/packages/reactive_ble_platform_interface/lib/src/reactive_ble_platform_interface.dart @@ -13,7 +13,7 @@ abstract class ReactiveBlePlatform extends PlatformInterface { ReactiveBlePlatform() : super(token: _token); static final Object _token = Object(); - static late ReactiveBlePlatform _instance; + static ReactiveBlePlatform _instance = _PlaceholderImplementation(); static ReactiveBlePlatform get instance => _instance; @@ -123,6 +123,11 @@ abstract class ReactiveBlePlatform extends PlatformInterface { throw UnimplementedError('establishBonding() has not been implemented.'); } + Future readRssi(String deviceId) async { + throw UnimplementedError( + 'readRssi(String deviceId) has not been implemented.'); + } + /// Connects to a specific device and the connection remains `established` until /// the stream is `cancelled` or the connection is closed by the peripheral. /// @@ -153,13 +158,17 @@ abstract class ReactiveBlePlatform extends PlatformInterface { throw UnimplementedError('discoverServices has not been implemented.'); } + Future> getDiscoverServices(String deviceId) { + throw UnimplementedError('getDiscoverServices has not been implemented.'); + } + /// Performs service discovery on the peripheral and returns the discovered /// services. /// /// This operation can only succeed when the host is `connected` with the /// peripheral. Only the success or failure of this operation should be propagated /// to this stream. The read value is distributed to [charValueUpdateStream]. - Stream readCharacteristic(QualifiedCharacteristic characteristic) { + Stream readCharacteristic(CharacteristicInstance characteristic) { throw UnimplementedError('readCharacteristic has not been implemented.'); } @@ -169,7 +178,7 @@ abstract class ReactiveBlePlatform extends PlatformInterface { /// When implement this operation on the platform make sure that you return a /// response only when the peripheral `acknowledged` the write operation Future writeCharacteristicWithResponse( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ) { throw UnimplementedError( @@ -182,30 +191,30 @@ abstract class ReactiveBlePlatform extends PlatformInterface { /// When implementing this operation on the platform make sure that it directly /// returns a response to the dart layer when the command arrived. Future writeCharacteristicWithoutResponse( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, List value, ) { throw UnimplementedError( 'writeCharacteristicWithoutResponse has not been implemented.'); } - /// Starts subscribing to notifications for a specificied characteristic. + /// Starts subscribing to notifications for a specified characteristic. /// /// This stream only returns the result of the operation. Value updates should /// be propagated to [charValueUpdateStream]. Stream subscribeToNotifications( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { throw UnimplementedError( 'subscribeToNotifications has not been implemented.'); } - /// Stops subscribing to notifications for a specificied characteristic. + /// Stops subscribing to notifications for a specified characteristic. Future stopSubscribingToNotifications( - QualifiedCharacteristic characteristic, + CharacteristicInstance characteristic, ) { throw UnimplementedError( - 'stopSubscribingToNotifiations has not been implemented.'); + 'stopSubscribingToNotifications has not been implemented.'); } /// Requests a specific MTU for a connected device. @@ -220,6 +229,8 @@ abstract class ReactiveBlePlatform extends PlatformInterface { Future requestConnectionPriority( String deviceId, ConnectionPriority priority) { throw UnimplementedError( - 'requesConnectionPriority has not been implemented.'); + 'requestConnectionPriority has not been implemented.'); } } + +class _PlaceholderImplementation extends ReactiveBlePlatform {} diff --git a/packages/reactive_ble_platform_interface/pubspec.lock b/packages/reactive_ble_platform_interface/pubspec.lock index 1969af6b..971ee206 100644 --- a/packages/reactive_ble_platform_interface/pubspec.lock +++ b/packages/reactive_ble_platform_interface/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -61,34 +61,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.10" + version: "7.3.0" built_collection: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.9.2" characters: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.10.0" collection: dependency: "direct main" description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" fake_async: dependency: transitive description: @@ -215,10 +215,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" functional_data: dependency: "direct main" description: @@ -279,10 +279,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -291,6 +291,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + 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: @@ -311,42 +335,42 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" mockito: dependency: "direct dev" description: name: mockito - sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" url: "https://pub.dev" source: hosted - version: "5.4.2" + version: "5.4.4" package_config: dependency: transitive description: @@ -359,18 +383,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" plugin_platform_interface: dependency: "direct main" description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pool: dependency: transitive description: @@ -420,34 +444,34 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.5.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -476,10 +500,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" timing: dependency: transitive description: @@ -504,6 +528,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -512,14 +544,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" yaml: dependency: transitive description: @@ -529,5 +569,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=2.0.0" diff --git a/packages/reactive_ble_platform_interface/pubspec.yaml b/packages/reactive_ble_platform_interface/pubspec.yaml index 7456f59d..62edc19b 100644 --- a/packages/reactive_ble_platform_interface/pubspec.yaml +++ b/packages/reactive_ble_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: reactive_ble_platform_interface description: Platform interface for the flutter_reactive_ble_project -version: 5.1.1 +version: 5.3.1 homepage: https://github.com/PhilipsHue/flutter_reactive_ble environment: