From 47d12e17442e4c399114aa18be234cf6d8e4e1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kojdecki?= Date: Tue, 10 Mar 2020 18:05:49 +0100 Subject: [PATCH] Release 2.2.3 (#445) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix capitalization style for UUID and constant names (#437) * Fix capitalization of UUID in Service * Fix capitalization of UUID in ScanResult * Fix capitalization of UUID in Peripheral * Rename bytes to value * Fix capitalization of UUID in metadata strings in ScanResult * Fix constants capitalization in BleError * Revert "Fix capitalization of UUID in metadata strings in ScanResult" This reverts commit 08516ec65b7a5874331fff3813f97d4b2e511dcb. * Fix capitalization of UUID in managers for classes * Fix capitalization of UUID for InternalBleManager * Fix capitalization of UUID in CharacteristicsMixin * Fix capitalization of UUID in DevicesMixin * Rename bytes to value in internal classes * Add unit tests for Service (#439) * unit test for BleManager * [descriptor] override equals & hashcode functions * [tests] add: mock classes for managers * [service] add: service tests * [tests] create characteristics and descriptors using separate generators * [service][tests] cover generating transactionId when it's not specified * [service][tests] clear mocks interactions after each test * [service][tests] add missing test for getting all descriptors for specified characteristic Co-authored-by: Paweł Byszewski <4048063+pawelByszewski@users.noreply.github.com> * Bump MBA and lib version Co-authored-by: Łukasz Rejman Co-authored-by: Bartosz Wilk Co-authored-by: Paweł Byszewski <4048063+pawelByszewski@users.noreply.github.com> --- CHANGELOG.md | 4 + android/build.gradle | 4 +- example/ios/Podfile.lock | 10 +- ios/flutter_ble_lib.podspec | 4 +- lib/ble_manager.dart | 2 +- lib/characteristic.dart | 5 +- lib/descriptor.dart | 15 + lib/error/ble_error.dart | 126 ++++---- lib/peripheral.dart | 34 +-- lib/scan_result.dart | 13 +- lib/service.dart | 18 +- lib/src/_managers_for_classes.dart | 28 +- lib/src/bridge/characteristics_mixin.dart | 44 +-- lib/src/bridge/devices_mixin.dart | 4 +- lib/src/internal_ble_manager.dart | 48 +-- pubspec.yaml | 2 +- test/ble_manager_test.dart | 16 + test/mock/manager_mock.dart | 8 + test/service_test.dart | 298 +++++++++++++++++++ test/test_util/characteristic_generator.dart | 28 ++ test/test_util/descriptor_generator.dart | 23 ++ 21 files changed, 564 insertions(+), 170 deletions(-) create mode 100644 test/ble_manager_test.dart create mode 100644 test/mock/manager_mock.dart create mode 100644 test/service_test.dart create mode 100644 test/test_util/characteristic_generator.dart create mode 100644 test/test_util/descriptor_generator.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index a334fb59..3d1ea6d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.3 + +* Fix issue with duplicated or malformed notification values + ## 2.2.2 * Fix issue with invalid characteristic value base64 coding when performing characteristic operations on iOS diff --git a/android/build.gradle b/android/build.gradle index 67811ed2..51faa26d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ group 'com.polidea.flutter_ble_lib' -version '2.2.0' +version '2.2.3' buildscript { repositories { @@ -36,5 +36,5 @@ android { dependencies { implementation 'androidx.annotation:annotation:1.1.0' - implementation 'com.github.Polidea:MultiPlatformBleAdapter:0.1.4' + implementation 'com.github.Polidea:MultiPlatformBleAdapter:0.1.5' } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 619a9229..a6a5adb4 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - Flutter (1.0.0) - - flutter_ble_lib (2.1.0): + - flutter_ble_lib (2.2.3): - Flutter - - MultiplatformBleAdapter (= 0.1.4) - - MultiplatformBleAdapter (0.1.4) + - MultiplatformBleAdapter (= 0.1.5) + - MultiplatformBleAdapter (0.1.5) - "permission_handler (4.2.0+hotfix.3)": - Flutter @@ -26,8 +26,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: 0e3d915762c693b495b44d77113d4970485de6ec - flutter_ble_lib: b2cf6d76a88368075db66966d782630318c6e67d - MultiplatformBleAdapter: 1ef6e0c8d11f753c56cbad1654b36c8e24142648 + flutter_ble_lib: 20e79f0b1d78d921d9ed68ab4451e190029bc3d9 + MultiplatformBleAdapter: 3c4391d428382738a47662ae1f665a29ce78ff39 permission_handler: 40520ab8ad1bb78a282b832464e995ec87f77ec6 PODFILE CHECKSUM: 1b66dae606f75376c5f2135a8290850eeb09ae83 diff --git a/ios/flutter_ble_lib.podspec b/ios/flutter_ble_lib.podspec index 76b0dc4e..7176e923 100644 --- a/ios/flutter_ble_lib.podspec +++ b/ios/flutter_ble_lib.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'flutter_ble_lib' - s.version = '2.2.0' + s.version = '2.2.3' s.summary = 'A new flutter plugin project.' s.description = <<-DESC A new flutter plugin project. @@ -16,7 +16,7 @@ A new flutter plugin project. s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' s.swift_versions = ['4.0', '4.2', '5.0'] - s.dependency 'MultiplatformBleAdapter', '0.1.4' + s.dependency 'MultiplatformBleAdapter', '0.1.5' s.ios.deployment_target = '8.0' end diff --git a/lib/ble_manager.dart b/lib/ble_manager.dart index d3595ec2..34fb4734 100644 --- a/lib/ble_manager.dart +++ b/lib/ble_manager.dart @@ -42,7 +42,7 @@ abstract class BleManager { } /// Cancels transaction's return, resulting in [BleError] with - /// [BleError.errorCode] set to [BleErrorCode.OperationCancelled] being returned + /// [BleError.errorCode] set to [BleErrorCode.operationCancelled] being returned /// from transaction's Future. /// /// The operation might be cancelled if it hadn't yet started or be run diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 9bb3a9e8..070de610 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -36,6 +36,7 @@ class Characteristic extends InternalCharacteristic { /// True if this characteristic can be monitored via notifications. bool isNotifiable; + /// True if this characteristic can be monitored via indications. bool isIndicatable; @@ -70,14 +71,14 @@ class Characteristic extends InternalCharacteristic { /// [isWritableWithoutResponse] is `true` and argument [withResponse] is /// set accordingly. Future write( - Uint8List bytes, + Uint8List value, bool withResponse, { String transactionId, }) => _manager.writeCharacteristicForIdentifier( service.peripheral, this, - bytes, + value, withResponse, transactionId ?? TransactionIdGenerator.getNextId(), ); diff --git a/lib/descriptor.dart b/lib/descriptor.dart index 9b938721..5e2e265a 100644 --- a/lib/descriptor.dart +++ b/lib/descriptor.dart @@ -33,6 +33,21 @@ class Descriptor extends InternalDescriptor { value, transactionId ?? TransactionIdGenerator.getNextId(), ); + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Descriptor && + runtimeType == other.runtimeType && + _manager == other._manager && + characteristic == other.characteristic && + uuid == other.uuid; + + @override + int get hashCode => + _manager.hashCode ^ + characteristic.hashCode ^ + uuid.hashCode; } class DescriptorWithValue extends Descriptor with WithValue { diff --git a/lib/error/ble_error.dart b/lib/error/ble_error.dart index 1b1ddbd9..dde9b639 100644 --- a/lib/error/ble_error.dart +++ b/lib/error/ble_error.dart @@ -1,15 +1,15 @@ part of flutter_ble_lib; abstract class _BleErrorMetadata { - static const String ERROR_CODE = "errorCode"; - static const String ATT_ERROR_CODE = "attErrorCode"; - static const String ANDROID_ERROR_CODE = "androidErrorCode"; - static const String REASON = "reason"; - static const String DEVICE_ID = "deviceID"; - static const String SERVICE_UUID = "serviceUUID"; - static const String CHARACTERISTIC_UUID = "characteristicUUID"; - static const String DESCRIPTOR_UUID = "descriptorUUID"; - static const String INTERNAL_MESSAGE = "internalMessage"; + static const String errorCode = "errorCode"; + static const String attErrorCode = "attErrorCode"; + static const String androidErrorCode = "androidErrorCode"; + static const String reason = "reason"; + static const String deviceId = "deviceID"; + static const String serviceUuid = "serviceUUID"; + static const String characteristicUuid = "characteristicUUID"; + static const String descriptorUuid = "descriptorUUID"; + static const String internalMessage = "internalMessage"; } class BleError { @@ -20,21 +20,21 @@ class BleError { String reason; String deviceID; - String serviceUUID; - String characteristicUUID; - String descriptorUUID; + String serviceUuid; + String characteristicUuid; + String descriptorUuid; String internalMessage; BleError.fromJson(Map json) - : errorCode = BleErrorCode(json[_BleErrorMetadata.ERROR_CODE]), - attErrorCode = json[_BleErrorMetadata.ATT_ERROR_CODE], - androidErrorCode = json[_BleErrorMetadata.ANDROID_ERROR_CODE], - reason = json[_BleErrorMetadata.REASON], - deviceID = json[_BleErrorMetadata.DEVICE_ID], - serviceUUID = json[_BleErrorMetadata.SERVICE_UUID], - characteristicUUID = json[_BleErrorMetadata.CHARACTERISTIC_UUID], - descriptorUUID = json[_BleErrorMetadata.DESCRIPTOR_UUID], - internalMessage = json[_BleErrorMetadata.INTERNAL_MESSAGE]; + : errorCode = BleErrorCode(json[_BleErrorMetadata.errorCode]), + attErrorCode = json[_BleErrorMetadata.attErrorCode], + androidErrorCode = json[_BleErrorMetadata.androidErrorCode], + reason = json[_BleErrorMetadata.reason], + deviceID = json[_BleErrorMetadata.deviceId], + serviceUuid = json[_BleErrorMetadata.serviceUuid], + characteristicUuid = json[_BleErrorMetadata.characteristicUuid], + descriptorUuid = json[_BleErrorMetadata.descriptorUuid], + internalMessage = json[_BleErrorMetadata.internalMessage]; @override String toString() => "BleError (" @@ -45,57 +45,57 @@ class BleError { "reason: $reason, " "internal message: $internalMessage, " "device ID: $deviceID, " - "service UUID: $serviceUUID, " - "characteristic UUID: $characteristicUUID, " - "descriptor UUID: $descriptorUUID)"; + "service UUID: $serviceUuid, " + "characteristic UUID: $characteristicUuid, " + "descriptor UUID: $descriptorUuid)"; } class BleErrorCode { - static const int UnknownError = 0; - static const int BluetoothManagerDestroyed = 1; - static const int OperationCancelled = 2; - static const int OperationTimedOut = 3; - static const int OperationStartFailed = 4; - static const int InvalidIdentifiers = 5; + static const int unknownError = 0; + static const int bluetoothManagerDestroyed = 1; + static const int operationCancelled = 2; + static const int operationTimedOut = 3; + static const int operationStartFailed = 4; + static const int invalidIdentifiers = 5; - static const int BluetoothUnsupported = 100; - static const int BluetoothUnauthorized = 101; - static const int BluetoothPoweredOff = 102; - static const int BluetoothInUnknownState = 103; - static const int BluetoothResetting = 104; - static const int BluetoothStateChangeFailed = 105; + static const int bluetoothUnsupported = 100; + static const int bluetoothUnauthorized = 101; + static const int bluetoothPoweredOff = 102; + static const int bluetoothInUnknownState = 103; + static const int bluetoothResetting = 104; + static const int bluetoothStateChangeFailed = 105; - static const int DeviceConnectionFailed = 200; - static const int DeviceDisconnected = 201; - static const int DeviceRSSIReadFailed = 202; - static const int DeviceAlreadyConnected = 203; - static const int DeviceNotFound = 204; - static const int DeviceNotConnected = 205; - static const int DeviceMTUChangeFailed = 206; + static const int deviceConnectionFailed = 200; + static const int deviceDisconnected = 201; + static const int deviceRSSIReadFailed = 202; + static const int deviceAlreadyConnected = 203; + static const int deviceNotFound = 204; + static const int deviceNotConnected = 205; + static const int deviceMTUChangeFailed = 206; - static const int ServicesDiscoveryFailed = 300; - static const int IncludedServicesDiscoveryFailed = 301; - static const int ServiceNotFound = 302; - static const int ServicesNotDiscovered = 303; + static const int servicesDiscoveryFailed = 300; + static const int includedServicesDiscoveryFailed = 301; + static const int serviceNotFound = 302; + static const int servicesNotDiscovered = 303; - static const int CharacteristicsDiscoveryFailed = 400; - static const int CharacteristicWriteFailed = 401; - static const int CharacteristicReadFailed = 402; - static const int CharacteristicNotifyChangeFailed = 403; - static const int CharacteristicNotFound = 404; - static const int CharacteristicsNotDiscovered = 405; - static const int CharacteristicInvalidDataFormat = 406; + static const int characteristicsDiscoveryFailed = 400; + static const int characteristicWriteFailed = 401; + static const int characteristicReadFailed = 402; + static const int characteristicNotifyChangeFailed = 403; + static const int characteristicNotFound = 404; + static const int characteristicsNotDiscovered = 405; + static const int characteristicInvalidDataFormat = 406; - static const int DescriptorsDiscoveryFailed = 500; - static const int DescriptorWriteFailed = 501; - static const int DescriptorReadFailed = 502; - static const int DescriptorNotFound = 503; - static const int DescriptorsNotDiscovered = 504; - static const int DescriptorInvalidDataFormat = 505; - static const int DescriptorWriteNotAllowed = 506; + static const int descriptorsDiscoveryFailed = 500; + static const int descriptorWriteFailed = 501; + static const int descriptorReadFailed = 502; + static const int descriptorNotFound = 503; + static const int descriptorsNotDiscovered = 504; + static const int descriptorInvalidDataFormat = 505; + static const int descriptorWriteNotAllowed = 506; - static const int ScanStartFailed = 600; - static const int LocationServicesDisabled = 601; + static const int scanStartFailed = 600; + static const int locationServicesDisabled = 601; int value; diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 5a24b364..c8298878 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -122,39 +122,39 @@ class Peripheral { /// Reads value of [Characteristic] matching specified UUIDs. /// - /// Returns value of characteristic with [characteristicUUID] for service with - /// [serviceUUID]. Optional [transactionId] could be used to cancel operation. + /// Returns value of characteristic with [characteristicUuid] for service with + /// [serviceUuid]. Optional [transactionId] could be used to cancel operation. /// /// Will result in error if discovery was not done during this connection. Future readCharacteristic( - String serviceUUID, - String characteristicUUID, { + String serviceUuid, + String characteristicUuid, { String transactionId, }) => _manager.readCharacteristicForDevice( this, - serviceUUID, - characteristicUUID, + serviceUuid, + characteristicUuid, transactionId ?? TransactionIdGenerator.getNextId(), ); /// Writes value of [Characteristic] matching specified UUIDs. /// - /// Writes [value] to characteristic with [characteristicUUID] for service with - /// [serviceUUID]. Optional [transactionId] could be used to cancel operation. + /// Writes [value] to characteristic with [characteristicUuid] for service with + /// [serviceUuid]. Optional [transactionId] could be used to cancel operation. /// /// Will result in error if discovery was not done during this connection. Future writeCharacteristic( - String serviceUUID, - String characteristicUUID, + String serviceUuid, + String characteristicUuid, Uint8List value, bool withResponse, { String transactionId, }) => _manager.writeCharacteristicForDevice( this, - serviceUUID, - characteristicUUID, + serviceUuid, + characteristicUuid, value, withResponse, transactionId ?? TransactionIdGenerator.getNextId(), @@ -221,21 +221,21 @@ class Peripheral { /// matching specified UUIDs. /// /// Emits [CharacteristicWithValue] for every observed change of the - /// characteristic specified by [serviceUUID] and [characteristicUUID] + /// characteristic specified by [serviceUuid] and [characteristicUuid] /// If notifications are enabled they will be used in favour of indications. /// Optional [transactionId] could be used to cancel operation. Unsubscribing /// from the stream cancels monitoring. /// /// Will result in error if discovery was not done during this connection. Stream monitorCharacteristic( - String serviceUUID, - String characteristicUUID, { + String serviceUuid, + String characteristicUuid, { String transactionId, }) => _manager.monitorCharacteristicForDevice( this, - serviceUUID, - characteristicUUID, + serviceUuid, + characteristicUuid, transactionId ?? TransactionIdGenerator.getNextId(), ); diff --git a/lib/scan_result.dart b/lib/scan_result.dart index 04921ce4..112b3c65 100644 --- a/lib/scan_result.dart +++ b/lib/scan_result.dart @@ -20,11 +20,12 @@ class ScanResult { /// Signal strength of the peripheral in dBm. int rssi; + /// An indicator whether the peripheral is connectable (iOS only). bool isConnectable; /// A list of UUIDs found in the overflow area of the advertisement data (iOS only). - List overflowServiceUUIDs; + List overflowServiceUuids; /// A packet of data advertised by the peripheral. AdvertisementData advertisementData; @@ -33,7 +34,7 @@ class ScanResult { : peripheral = Peripheral.fromJson(json, manager), rssi = json[_ScanResultMetadata.rssi], isConnectable = json[_ScanResultMetadata.isConnectable], - overflowServiceUUIDs = json[_ScanResultMetadata.overflowServiceUuids], + overflowServiceUuids = json[_ScanResultMetadata.overflowServiceUuids], advertisementData = AdvertisementData._fromJson(json); } @@ -47,7 +48,7 @@ class AdvertisementData { Map serviceData; /// A list of service UUIDs. - List serviceUUIDs; + List serviceUuids; /// The local name of the [Peripheral]. Might be different than /// [Peripheral.name]. @@ -57,18 +58,18 @@ class AdvertisementData { int txPowerLevel; /// A list of solicited service UUIDs. - List solicitedServiceUUIDs; + List solicitedServiceUuids; AdvertisementData._fromJson(Map json) : manufacturerData = _decodeBase64OrNull(json[_ScanResultMetadata.manufacturerData]), serviceData = _getServiceDataOrNull(json[_ScanResultMetadata.serviceData]), - serviceUUIDs = + serviceUuids = _mapToListOfStringsOrNull(json[_ScanResultMetadata.serviceUuids]), localName = json[_ScanResultMetadata.localName], txPowerLevel = json[_ScanResultMetadata.txPowerLevel], - solicitedServiceUUIDs = _mapToListOfStringsOrNull( + solicitedServiceUuids = _mapToListOfStringsOrNull( json[_ScanResultMetadata.solicitedServiceUuids]); static Map _getServiceDataOrNull( diff --git a/lib/service.dart b/lib/service.dart index 90742dcd..2b00d663 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -30,7 +30,7 @@ class Service extends InternalService { _manager.characteristicsForService(this); /// Writes the [value] to the [Characteristic] identified by - /// [characteristicUUID]. + /// [characteristicUuid]. /// /// It returns a [Future] that completes with the [Characteristic] for the /// convenience of chaining operations. @@ -40,7 +40,7 @@ class Service extends InternalService { /// [Characteristic.isWritableWithoutResponse] is `true` and /// [withResponse] is specified accordingly can be written to. Future writeCharacteristic( - String characteristicUUID, + String characteristicUuid, Uint8List value, bool withResponse, { String transactionId, @@ -48,30 +48,30 @@ class Service extends InternalService { _manager.writeCharacteristicForService( peripheral, this, - characteristicUUID, + characteristicUuid, value, withResponse, transactionId ?? TransactionIdGenerator.getNextId()); - /// Reads the value of a [Characteristic] identified by [characteristicUUID]. + /// Reads the value of a [Characteristic] identified by [characteristicUuid]. /// /// It returns a [Future] that completes with [CharacteristicWithValue], /// which is just a [Characteristic] but with an additonal `value` /// property of type [Uint8List]. Only [Characteristic] where /// [Characteristic.isReadable] is `true` can be read. Future readCharacteristic( - String characteristicUUID, { + String characteristicUuid, { String transactionId, }) => _manager.readCharacteristicForService( peripheral, this, - characteristicUUID, + characteristicUuid, transactionId ?? TransactionIdGenerator.getNextId(), ); /// Returns a [Stream] of values emitted by a [Characteristic] identified by - /// [characteristicUUID]. + /// [characteristicUuid]. /// /// Just like [readCharacteristic()] method, values are emitted as /// [CharacteristicWithValue] objects, which are the same as [Characteristic] @@ -79,13 +79,13 @@ class Service extends InternalService { /// [Characteristic] where [Characteristic.isNotifiable] is `true` can be /// monitored. Stream monitorCharacteristic( - String characteristicUUID, { + String characteristicUuid, { String transactionId, }) => _manager.monitorCharacteristicForService( peripheral, this, - characteristicUUID, + characteristicUuid, transactionId ?? TransactionIdGenerator.getNextId(), ); diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 2459814d..69a92814 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -48,22 +48,22 @@ abstract class ManagerForPeripheral { Future readCharacteristicForDevice( Peripheral peripheral, String serviceUuid, - String characteristicUUID, + String characteristicUuid, String transactionId, ); Future writeCharacteristicForDevice( Peripheral peripheral, - String serviceUUID, - String characteristicUUID, - Uint8List bytes, + String serviceUuid, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId); Stream monitorCharacteristicForDevice( Peripheral peripheral, - String serviceUUID, - String characteristicUUID, + String serviceUuid, + String characteristicUuid, String transactionId, ); @@ -86,7 +86,7 @@ abstract class ManagerForPeripheral { String serviceUuid, String characteristicUuid, String descriptorUuid, - Uint8List bytes, + Uint8List value, String transactionId, ); } @@ -97,15 +97,15 @@ abstract class ManagerForService { Future readCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, + String characteristicUuid, String transactionId, ); Future writeCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, - Uint8List bytes, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId, ); @@ -113,7 +113,7 @@ abstract class ManagerForService { Stream monitorCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, + String characteristicUuid, String transactionId, ); @@ -133,7 +133,7 @@ abstract class ManagerForService { Service service, String characteristicUuid, String descriptorUuid, - Uint8List bytes, + Uint8List value, String transactionId, ); } @@ -148,7 +148,7 @@ abstract class ManagerForCharacteristic { Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, - Uint8List bytes, + Uint8List value, bool withResponse, String transactionId, ); @@ -185,7 +185,7 @@ abstract class ManagerForDescriptor { Future writeDescriptorForIdentifier( Descriptor descriptor, - Uint8List bytes, + Uint8List value, String transactionId, ); } diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index 535ef0da..1f1bfcd5 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -28,7 +28,7 @@ mixin CharacteristicsMixin on FlutterBLE { Future readCharacteristicForDevice( Peripheral peripheral, String serviceUuid, - String characteristicUUID, + String characteristicUuid, String transactionId, ) => _methodChannel @@ -37,7 +37,7 @@ mixin CharacteristicsMixin on FlutterBLE { { ArgumentName.deviceIdentifier: peripheral.identifier, ArgumentName.serviceUuid: serviceUuid, - ArgumentName.characteristicUuid: characteristicUUID, + ArgumentName.characteristicUuid: characteristicUuid, ArgumentName.transactionId: transactionId }, ) @@ -52,7 +52,7 @@ mixin CharacteristicsMixin on FlutterBLE { Future readCharacteristicForService( Peripheral peripheral, int serviceIdentifier, - String characteristicUUID, + String characteristicUuid, String transactionId, ) => _methodChannel @@ -60,7 +60,7 @@ mixin CharacteristicsMixin on FlutterBLE { MethodName.readCharacteristicForService, { ArgumentName.serviceIdentifier: serviceIdentifier, - ArgumentName.characteristicUuid: characteristicUUID, + ArgumentName.characteristicUuid: characteristicUuid, ArgumentName.transactionId: transactionId }, ) @@ -75,7 +75,7 @@ mixin CharacteristicsMixin on FlutterBLE { Future writeCharacteristicForIdentifier( Peripheral peripheral, int characteristicIdentifier, - Uint8List bytes, + Uint8List value, bool withResponse, String transactionId, ) => @@ -83,7 +83,7 @@ mixin CharacteristicsMixin on FlutterBLE { MethodName.writeCharacteristicForIdentifier, { ArgumentName.characteristicIdentifier: characteristicIdentifier, - ArgumentName.value: bytes, + ArgumentName.value: value, ArgumentName.withResponse: withResponse, ArgumentName.transactionId: transactionId, }, @@ -92,9 +92,9 @@ mixin CharacteristicsMixin on FlutterBLE { Future writeCharacteristicForDevice( Peripheral peripheral, - String serviceUUID, - String characteristicUUID, - Uint8List bytes, + String serviceUuid, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId) => _methodChannel @@ -102,9 +102,9 @@ mixin CharacteristicsMixin on FlutterBLE { MethodName.writeCharacteristicForDevice, { ArgumentName.deviceIdentifier: peripheral.identifier, - ArgumentName.serviceUuid: serviceUUID, - ArgumentName.characteristicUuid: characteristicUUID, - ArgumentName.value: bytes, + ArgumentName.serviceUuid: serviceUuid, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, ArgumentName.withResponse: withResponse, ArgumentName.transactionId: transactionId, }, @@ -119,8 +119,8 @@ mixin CharacteristicsMixin on FlutterBLE { Future writeCharacteristicForService( Peripheral peripheral, int serviceIdentifier, - String characteristicUUID, - Uint8List bytes, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId, ) => @@ -129,8 +129,8 @@ mixin CharacteristicsMixin on FlutterBLE { MethodName.writeCharacteristicForService, { ArgumentName.serviceIdentifier: serviceIdentifier, - ArgumentName.characteristicUuid: characteristicUUID, - ArgumentName.value: bytes, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, ArgumentName.withResponse: withResponse, ArgumentName.transactionId: transactionId, }, @@ -172,7 +172,7 @@ mixin CharacteristicsMixin on FlutterBLE { Stream monitorCharacteristicForDevice( Peripheral peripheral, String serviceUuid, - String characteristicUUID, + String characteristicUuid, String transactionId, ) { void Function() startMonitoring = () => _methodChannel.invokeMethod( @@ -180,14 +180,14 @@ mixin CharacteristicsMixin on FlutterBLE { { ArgumentName.deviceIdentifier: peripheral.identifier, ArgumentName.serviceUuid: serviceUuid, - ArgumentName.characteristicUuid: characteristicUUID, + ArgumentName.characteristicUuid: characteristicUuid, ArgumentName.transactionId: transactionId, }, ); bool Function(CharacteristicWithValueAndTransactionId) characteristicsFilter = (characteristic) => - equalsIgnoreAsciiCase(characteristicUUID, characteristic.uuid) && + equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && equalsIgnoreAsciiCase(serviceUuid, characteristic.service.uuid) && equalsIgnoreAsciiCase( transactionId ?? "", characteristic.transactionId ?? ""); @@ -203,21 +203,21 @@ mixin CharacteristicsMixin on FlutterBLE { Stream monitorCharacteristicForService( Peripheral peripheral, int serviceIdentifier, - String characteristicUUID, + String characteristicUuid, String transactionId, ) { void Function() startMonitoring = () => _methodChannel.invokeMethod( MethodName.monitorCharacteristicForService, { ArgumentName.serviceIdentifier: serviceIdentifier, - ArgumentName.characteristicUuid: characteristicUUID, + ArgumentName.characteristicUuid: characteristicUuid, ArgumentName.transactionId: transactionId, }, ); bool Function(CharacteristicWithValueAndTransactionId) characteristicFilter = (characteristic) => - equalsIgnoreAsciiCase(characteristicUUID, characteristic.uuid) && + equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && serviceIdentifier == characteristic.service._id && equalsIgnoreAsciiCase( transactionId ?? "", characteristic.transactionId ?? ""); diff --git a/lib/src/bridge/devices_mixin.dart b/lib/src/bridge/devices_mixin.dart index ca2895e8..872e145e 100644 --- a/lib/src/bridge/devices_mixin.dart +++ b/lib/src/bridge/devices_mixin.dart @@ -12,10 +12,10 @@ mixin DevicesMixin on FlutterBLE { }); } - Future> connectedDevices(List serviceUUIDs) async { + Future> connectedDevices(List serviceUuids) async { return _methodChannel .invokeMethod(MethodName.connectedDevices, { - ArgumentName.uuids: serviceUUIDs, + ArgumentName.uuids: serviceUuids, }).then((peripheralsJson) { print("connected devices json: $peripheralsJson"); return _parsePeripheralsJson(peripheralsJson); diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 42814da6..5234e89c 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -184,8 +184,8 @@ class InternalBleManager } @override - Future> connectedPeripherals(List serviceUUIDs) { - return _bleLib.connectedDevices(serviceUUIDs ?? []); + Future> connectedPeripherals(List serviceUuids) { + return _bleLib.connectedDevices(serviceUuids ?? []); } @override @@ -201,12 +201,12 @@ class InternalBleManager Future readCharacteristicForDevice( Peripheral peripheral, String serviceUuid, - String characteristicUUID, + String characteristicUuid, String transactionId) => _bleLib.readCharacteristicForDevice( peripheral, serviceUuid, - characteristicUUID, + characteristicUuid, transactionId, ); @@ -214,12 +214,12 @@ class InternalBleManager Future readCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, + String characteristicUuid, String transactionId) => _bleLib.readCharacteristicForService( peripheral, service._id, - characteristicUUID, + characteristicUuid, transactionId, ); @@ -227,13 +227,13 @@ class InternalBleManager Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, - Uint8List bytes, + Uint8List value, bool withResponse, String transactionId) => _bleLib.writeCharacteristicForIdentifier( peripheral, characteristic._id, - bytes, + value, withResponse, transactionId, ); @@ -241,16 +241,16 @@ class InternalBleManager @override Future writeCharacteristicForDevice( Peripheral peripheral, - String serviceUUID, - String characteristicUUID, - Uint8List bytes, + String serviceUuid, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId) => _bleLib.writeCharacteristicForDevice( peripheral, - serviceUUID, - characteristicUUID, - bytes, + serviceUuid, + characteristicUuid, + value, withResponse, transactionId, ); @@ -259,15 +259,15 @@ class InternalBleManager Future writeCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, - Uint8List bytes, + String characteristicUuid, + Uint8List value, bool withResponse, String transactionId) => _bleLib.writeCharacteristicForService( peripheral, service._id, - characteristicUUID, - bytes, + characteristicUuid, + value, withResponse, transactionId, ); @@ -275,14 +275,14 @@ class InternalBleManager @override Stream monitorCharacteristicForDevice( Peripheral peripheral, - String serviceUUID, - String characteristicUUID, + String serviceUuid, + String characteristicUuid, String transactionId, ) => _bleLib.monitorCharacteristicForDevice( peripheral, - serviceUUID, - characteristicUUID, + serviceUuid, + characteristicUuid, transactionId, ); @@ -290,13 +290,13 @@ class InternalBleManager Stream monitorCharacteristicForService( Peripheral peripheral, InternalService service, - String characteristicUUID, + String characteristicUuid, String transactionId, ) => _bleLib.monitorCharacteristicForService( peripheral, service._id, - characteristicUUID, + characteristicUuid, transactionId, ); diff --git a/pubspec.yaml b/pubspec.yaml index 2794288d..7a4c0e3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_ble_lib description: FlutterBle Library is a flutter library that supports BLE operations. It uses MultiPlatformBleAdapter as a native backend.. -version: 2.2.2 +version: 2.2.3 author: "Polidea " homepage: https://github.com/Polidea/FlutterBleLib diff --git a/test/ble_manager_test.dart b/test/ble_manager_test.dart new file mode 100644 index 00000000..267d54a6 --- /dev/null +++ b/test/ble_manager_test.dart @@ -0,0 +1,16 @@ + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:test/test.dart'; + +void main() { + test('Ble manager must be singleton', () { + //given + final firstInstanceOfBlemanager = BleManager(); + + //when + final secondInstanceOfBleManager = BleManager(); + + //then + expect(secondInstanceOfBleManager, firstInstanceOfBlemanager); + }); +} \ No newline at end of file diff --git a/test/mock/manager_mock.dart b/test/mock/manager_mock.dart new file mode 100644 index 00000000..3c9721b5 --- /dev/null +++ b/test/mock/manager_mock.dart @@ -0,0 +1,8 @@ +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import 'package:mockito/mockito.dart'; + +class ManagerForServiceMock extends Mock implements ManagerForService {} + +class ManagerForCharacteristicMock extends Mock implements ManagerForCharacteristic {} + +class ManagerForDescriptorMock extends Mock implements ManagerForDescriptor {} diff --git a/test/service_test.dart b/test/service_test.dart new file mode 100644 index 00000000..01b9319a --- /dev/null +++ b/test/service_test.dart @@ -0,0 +1,298 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; + +import 'mock/manager_mock.dart'; +import 'mock/mock_peripheral.dart'; +import 'test_util/characteristic_generator.dart'; +import 'test_util/descriptor_generator.dart'; + +void main() { + Peripheral peripheral = PeripheralMock(); + ManagerForService managerForService = ManagerForServiceMock(); + ManagerForCharacteristic managerForCharacteristic = + ManagerForCharacteristicMock(); + ManagerForDescriptor managerForDescriptor = ManagerForDescriptorMock(); + CharacteristicGenerator characteristicGenerator = + CharacteristicGenerator(managerForCharacteristic); + DescriptorGenerator descriptorGenerator = + DescriptorGenerator(managerForDescriptor); + + Service service = Service.fromJson({ + "serviceId": 1, + "serviceUuid": "testUuid", + }, peripheral, managerForService); + + CharacteristicWithValue createCharacteristic(int seed) => + characteristicGenerator.create(seed, service); + + DescriptorWithValue createDescriptor(int seed) => + descriptorGenerator.create(seed, createCharacteristic(seed)); + + tearDown(() { + [ + peripheral, + managerForService, + managerForCharacteristic, + managerForDescriptor, + ].forEach(clearInteractions); + }); + + test("characteristics returns characteristics provided by manager", () async { + //given + when(managerForService.characteristicsForService(service)) + .thenAnswer((_) => Future.value([ + createCharacteristic(0), + createCharacteristic(1), + createCharacteristic(2), + ])); + + //when + var characteristics = await service.characteristics(); + + //then + expect( + characteristics, + equals([ + createCharacteristic(0), + createCharacteristic(1), + createCharacteristic(2), + ])); + }); + + test("descriptorsForCharacteristic returns characteristics provided by manager", () async { + //given + when(managerForService.descriptorsForService(service, "123")) + .thenAnswer((_) => Future.value([ + createDescriptor(0), + createDescriptor(1), + createDescriptor(2), + ])); + + //when + var descriptors = await service.descriptorsForCharacteristic("123"); + + //then + expect( + descriptors, + equals([ + createDescriptor(0), + createDescriptor(1), + createDescriptor(2), + ])); + }); + + test("readCharacteristic returns expected characteristic", () async { + //given + when(managerForService.readCharacteristicForService( + peripheral, service, "123", "456")) + .thenAnswer((_) => Future.value(createCharacteristic(0))); + + //when + var characteristic = + await service.readCharacteristic("123", transactionId: "456"); + + //then + expect(characteristic, equals(createCharacteristic(0))); + }); + + test("readCharacteristic reads characteristic using manager", () { + //when + service.readCharacteristic("123", transactionId: "456"); + + //then + verify( + managerForService.readCharacteristicForService( + peripheral, service, "123", "456"), + ); + }); + + test( + "readCharacteristic reads characteristic with generated transactionId using manager", + () { + //when + service.readCharacteristic("123", transactionId: null); + + //then + verify( + managerForService.readCharacteristicForService( + peripheral, service, "123", argThat(isNotNull)), + ); + }); + + test("readDescriptor returns expected descriptor", () async { + //given + when(managerForService.readDescriptorForService( + service, "123", "456", "789")) + .thenAnswer((_) => Future.value(createDescriptor(0))); + + //when + var characteristic = + await service.readDescriptor("123", "456", transactionId: "789"); + + //then + expect(characteristic, equals(createDescriptor(0))); + }); + + test("readDescriptor reads characteristic using manager", () { + //when + service.readDescriptor("123", "456", transactionId: "789"); + + //then + verify( + managerForService.readDescriptorForService(service, "123", "456", "789"), + ); + }); + + test( + "readDescriptor reads descriptor with generated transactionId using manager", + () { + //when + service.readDescriptor("123", "456", transactionId: null); + + //then + verify( + managerForService.readDescriptorForService( + service, "123", "456", argThat(isNotNull)), + ); + }); + + test("writeCharacteristic returns expected characteristic", () async { + //given + when(managerForService.writeCharacteristicForService(peripheral, service, + "123", Uint8List.fromList([1, 2, 3, 4]), false, "456")) + .thenAnswer((_) => Future.value(createCharacteristic(0))); + + //when + var characteristic = await service.writeCharacteristic( + "123", + Uint8List.fromList([1, 2, 3, 4]), + false, + transactionId: "456", + ); + + //then + expect(characteristic, equals(createCharacteristic(0))); + }); + + test("writeCharacteristic writes characteristic using manager", () { + //when + service.writeCharacteristic("123", Uint8List.fromList([1, 2, 3, 4]), false, + transactionId: "456"); + + //then + verify( + managerForService.writeCharacteristicForService(peripheral, service, + "123", Uint8List.fromList([1, 2, 3, 4]), false, "456"), + ); + }); + + test( + "writeCharacteristic writes characteristic with generated transactionId using manager", + () { + //when + service.writeCharacteristic("123", Uint8List.fromList([1, 2, 3, 4]), false, + transactionId: null); + + //then + verify( + managerForService.writeCharacteristicForService(peripheral, service, + "123", Uint8List.fromList([1, 2, 3, 4]), false, argThat(isNotNull)), + ); + }); + + test("writeDescriptor returns expected descriptor", () async { + //given + when(managerForService.writeDescriptorForService( + service, "123", "456", Uint8List.fromList([1, 2, 3, 4]), "789")) + .thenAnswer((_) => Future.value(createDescriptor(0))); + + //when + var characteristic = await service.writeDescriptor( + "123", "456", Uint8List.fromList([1, 2, 3, 4]), + transactionId: "789"); + + //then + expect(characteristic, equals(createDescriptor(0))); + }); + + test("writeDescriptor writes descriptor using manager", () { + //when + service.writeDescriptor("123", "456", Uint8List.fromList([1, 2, 3, 4]), + transactionId: "789"); + + //then + verify( + managerForService.writeDescriptorForService( + service, "123", "456", Uint8List.fromList([1, 2, 3, 4]), "789"), + ); + }); + + test( + "writeDescriptor writes descriptor with generated transactionId using manager", + () { + //when + service.writeDescriptor("123", "456", Uint8List.fromList([1, 2, 3, 4]), + transactionId: null); + + //then + verify( + managerForService.writeDescriptorForService(service, "123", "456", + Uint8List.fromList([1, 2, 3, 4]), argThat(isNotNull)), + ); + }); + + test("monitorCharacteristic streams expected characteristic", () { + //given + var streamController = StreamController(); + when(managerForService.monitorCharacteristicForService( + peripheral, service, "123", "456")) + .thenAnswer((_) => streamController.stream); + + //when + var characteristicNotifications = + service.monitorCharacteristic("123", transactionId: "456"); + streamController.sink.add(createCharacteristic(0)); + streamController.sink.add(createCharacteristic(1)); + streamController.sink.add(createCharacteristic(2)); + streamController.close(); + + //then + expect( + characteristicNotifications, + emitsInOrder([ + emits(equals(createCharacteristic(0))), + emits(equals(createCharacteristic(1))), + emits(equals(createCharacteristic(2))), + emitsDone + ])); + }); + + test("monitorCharacteristic monitors characteristic using manager", () { + //when + service.monitorCharacteristic("123", transactionId: "456"); + + //then + verify( + managerForService.monitorCharacteristicForService( + peripheral, service, "123", "456"), + ); + }); + + test( + "monitorCharacteristic monitors characteristic with generated transactionId using manager", + () { + //when + service.monitorCharacteristic("123", transactionId: null); + + //then + verify( + managerForService.monitorCharacteristicForService( + peripheral, service, "123", argThat(isNotNull)), + ); + }); +} diff --git a/test/test_util/characteristic_generator.dart b/test/test_util/characteristic_generator.dart new file mode 100644 index 00000000..6b979c6b --- /dev/null +++ b/test/test_util/characteristic_generator.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; + +class CharacteristicGenerator { + ManagerForCharacteristic managerForCharacteristic; + + CharacteristicGenerator(this.managerForCharacteristic); + + Map _createRawCharacteristic(int seed) => { + "characteristicUuid": seed.toString(), + "id": seed, + "isReadable": seed % 2 == 0, + "isWritableWithResponse": seed % 2 == 0, + "isWritableWithoutResponse": seed % 2 == 0, + "isNotifiable": seed % 2 == 0, + "isIndicatable": seed % 2 == 0, + "value": base64Encode([seed]) + }; + + CharacteristicWithValue create(int seed, Service service) => + CharacteristicWithValue.fromJson( + _createRawCharacteristic(seed), + service, + managerForCharacteristic, + ); +} diff --git a/test/test_util/descriptor_generator.dart b/test/test_util/descriptor_generator.dart new file mode 100644 index 00000000..f836854c --- /dev/null +++ b/test/test_util/descriptor_generator.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; + +class DescriptorGenerator { + ManagerForDescriptor managerForDescriptor; + + DescriptorGenerator(this.managerForDescriptor); + + Map _createRawDescriptor(int seed) => { + "descriptorId": seed, + "descriptorUuid": seed.toString(), + "value": base64Encode([seed]) + }; + + DescriptorWithValue create(int seed, Characteristic characteristic) => + DescriptorWithValue.fromJson( + _createRawDescriptor(seed), + characteristic, + managerForDescriptor, + ); +}