From a64021cfc54485e393fbf7944f562e88d3ad194c Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Fri, 26 Mar 2021 16:10:39 +0100 Subject: [PATCH 01/33] Work in progress --- example/pubspec.yaml | 2 +- lib/ble_manager.dart | 16 +++++--- lib/characteristic.dart | 44 ++++++++++----------- lib/descriptor.dart | 28 ++++++------- lib/error/ble_error.dart | 2 + lib/peripheral.dart | 18 ++++----- lib/scan_result.dart | 18 ++++----- lib/service.dart | 19 +++++---- lib/src/_managers_for_classes.dart | 10 ++--- lib/src/base_entities.dart | 10 ++--- lib/src/bridge/characteristics_mixin.dart | 16 ++++---- lib/src/bridge/device_connection_mixin.dart | 9 ++++- lib/src/bridge/lib_core.dart | 35 +++++++++------- lib/src/bridge/scanning_mixin.dart | 18 +++++---- lib/src/internal_ble_manager.dart | 31 +++++++-------- pubspec.yaml | 13 +++--- 16 files changed, 150 insertions(+), 139 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index d10740c4..19913f60 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1+1 publish_to: "none" environment: - sdk: ">=2.6.0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dependencies: flutter: diff --git a/lib/ble_manager.dart b/lib/ble_manager.dart index 5a353eb4..4b847caa 100644 --- a/lib/ble_manager.dart +++ b/lib/ble_manager.dart @@ -31,12 +31,16 @@ enum LogLevel { none, verbose, debug, info, warning, error } ///}); ///``` abstract class BleManager { - static BleManager _instance; + static BleManager? _instance; factory BleManager() { - _instance ??= InternalBleManager(); + var instance = _instance; + if (instance == null) { + instance = InternalBleManager(); + _instance = instance; + } - return _instance; + return instance; } /// Cancels transaction's return, resulting in [BleError] with @@ -59,8 +63,8 @@ abstract class BleManager { /// await BleManager().createClient(); /// ``` Future createClient({ - String restoreStateIdentifier, - RestoreStateAction restoreStateAction, + String? restoreStateIdentifier, + RestoreStateAction? restoreStateAction, }); /// Frees native resources. @@ -147,7 +151,7 @@ abstract class BleManager { /// On Android [peripheralId] scanned on one device may or may not be /// recognized on a different Android device depending on peripheral’s /// implementation and changes in future OS releases. - Peripheral createUnsafePeripheral(String peripheralId, {String name}); + Peripheral createUnsafePeripheral(String peripheralId, {String? name}); } /// State of the Bluetooth Adapter. diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 070de610..88450d12 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -42,23 +42,22 @@ class Characteristic extends InternalCharacteristic { Characteristic.fromJson(Map jsonObject, Service service, ManagerForCharacteristic manager) - : super(jsonObject[_CharacteristicMetadata.id]) { - _manager = manager; - this.service = service; - uuid = jsonObject[_CharacteristicMetadata.uuid]; - isReadable = jsonObject[_CharacteristicMetadata.isReadable]; - isWritableWithResponse = - jsonObject[_CharacteristicMetadata.isWritableWithResponse]; - isWritableWithoutResponse = - jsonObject[_CharacteristicMetadata.isWritableWithoutResponse]; - isNotifiable = jsonObject[_CharacteristicMetadata.isNotifiable]; - isIndicatable = jsonObject[_CharacteristicMetadata.isIndicatable]; - } + : _manager = manager, + service = service, + uuid = jsonObject[_CharacteristicMetadata.uuid], + isReadable = jsonObject[_CharacteristicMetadata.isReadable], + isWritableWithResponse = + jsonObject[_CharacteristicMetadata.isWritableWithResponse], + isWritableWithoutResponse = + jsonObject[_CharacteristicMetadata.isWritableWithoutResponse], + isNotifiable = jsonObject[_CharacteristicMetadata.isNotifiable], + isIndicatable = jsonObject[_CharacteristicMetadata.isIndicatable], + super(jsonObject[_CharacteristicMetadata.id]); /// Reads the value of this characteristic. /// /// The value can be read only if [isReadable] is `true`. - Future read({String transactionId}) => + Future read({String? transactionId}) => _manager.readCharacteristicForIdentifier( service.peripheral, this, @@ -73,7 +72,7 @@ class Characteristic extends InternalCharacteristic { Future write( Uint8List value, bool withResponse, { - String transactionId, + String? transactionId, }) => _manager.writeCharacteristicForIdentifier( service.peripheral, @@ -91,7 +90,7 @@ class Characteristic extends InternalCharacteristic { /// Subscribing to the returned object enables the notifications/indications /// on the peripheral. Cancelling the last subscription disables the /// notifications/indications on this characteristic. - Stream monitor({String transactionId}) => + Stream monitor({String? transactionId}) => _manager.monitorCharacteristicForIdentifier( service.peripheral, this, @@ -105,7 +104,7 @@ class Characteristic extends InternalCharacteristic { /// Reads the value of a [Descriptor] identified by [descriptorUuid]. Future readDescriptor( String descriptorUuid, { - String transactionId, + String? transactionId, }) => _manager.readDescriptorForCharacteristic( this, @@ -117,7 +116,7 @@ class Characteristic extends InternalCharacteristic { Future writeDescriptor( String descriptorUuid, Uint8List value, { - String transactionId, + String? transactionId, }) => _manager.writeDescriptorForCharacteristic( this, @@ -170,21 +169,22 @@ class Characteristic extends InternalCharacteristic { /// /// This type is created to support chaining of operations on the characteristic /// when it was first read from [Peripheral] or [Service]. -class CharacteristicWithValue extends Characteristic with WithValue { +class CharacteristicWithValue extends Characteristic { + Uint8List value; + CharacteristicWithValue.fromJson( Map jsonObject, Service service, ManagerForCharacteristic manager, - ) : super.fromJson(jsonObject, service, manager) { - value = base64Decode(jsonObject[_CharacteristicMetadata.value]); - } + ) : value = base64Decode(jsonObject[_CharacteristicMetadata.value]), + super.fromJson(jsonObject, service, manager); @override bool operator ==(Object other) { return identical(this, other) || super == other && other is CharacteristicWithValue && - value?.toString() == other.value?.toString() && + value.toString() == other.value.toString() && runtimeType == other.runtimeType; } diff --git a/lib/descriptor.dart b/lib/descriptor.dart index 6e43cee5..b1e4f0ad 100644 --- a/lib/descriptor.dart +++ b/lib/descriptor.dart @@ -7,27 +7,26 @@ abstract class _DescriptorMetadata { } class Descriptor extends InternalDescriptor { - ManagerForDescriptor _manager; - Characteristic characteristic; - String uuid; + final ManagerForDescriptor _manager; + final Characteristic characteristic; + final String uuid; Descriptor.fromJson( Map jsonObject, Characteristic characteristic, ManagerForDescriptor manager, - ) : super(jsonObject[_DescriptorMetadata.id]) { - _manager = manager; - this.characteristic = characteristic; - uuid = jsonObject[_DescriptorMetadata.uuid]; - } + ) : _manager = manager, + characteristic = characteristic, + uuid = jsonObject[_DescriptorMetadata.uuid], + super(jsonObject[_DescriptorMetadata.id]); - Future read({String transactionId}) => + Future read({String? transactionId}) => _manager.readDescriptorForIdentifier( this, transactionId ?? TransactionIdGenerator.getNextId(), ); - Future write(Uint8List value, {String transactionId}) => + Future write(Uint8List value, {String? transactionId}) => _manager.writeDescriptorForIdentifier( this, value, @@ -48,12 +47,13 @@ class Descriptor extends InternalDescriptor { _manager.hashCode ^ characteristic.hashCode ^ uuid.hashCode; } -class DescriptorWithValue extends Descriptor with WithValue { +class DescriptorWithValue extends Descriptor { + Uint8List value; + DescriptorWithValue.fromJson( Map jsonObject, Characteristic characteristic, ManagerForDescriptor manager, - ) : super.fromJson(jsonObject, characteristic, manager) { - value = base64Decode(jsonObject[_DescriptorMetadata.value]); - } + ) : value = base64Decode(jsonObject[_DescriptorMetadata.value]), + super.fromJson(jsonObject, characteristic, manager); } diff --git a/lib/error/ble_error.dart b/lib/error/ble_error.dart index dde9b639..1124ce40 100644 --- a/lib/error/ble_error.dart +++ b/lib/error/ble_error.dart @@ -3,6 +3,7 @@ part of flutter_ble_lib; abstract class _BleErrorMetadata { static const String errorCode = "errorCode"; static const String attErrorCode = "attErrorCode"; + static const String iosErrorCode = "iosErrorCode"; static const String androidErrorCode = "androidErrorCode"; static const String reason = "reason"; static const String deviceId = "deviceID"; @@ -28,6 +29,7 @@ class BleError { BleError.fromJson(Map json) : errorCode = BleErrorCode(json[_BleErrorMetadata.errorCode]), attErrorCode = json[_BleErrorMetadata.attErrorCode], + iosErrorCode = json[_BleErrorMetadata.iosErrorCode], androidErrorCode = json[_BleErrorMetadata.androidErrorCode], reason = json[_BleErrorMetadata.reason], deviceID = json[_BleErrorMetadata.deviceId], diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 61863b05..49c249ee 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -51,7 +51,7 @@ class Peripheral { {bool isAutoConnect = false, int requestMtu = NO_MTU_NEGOTIATION, bool refreshGatt = false, - Duration timeout}) => + Duration? timeout}) => _manager.connectToPeripheral(identifier, isAutoConnect: isAutoConnect, requestMtu: requestMtu, @@ -79,7 +79,7 @@ class Peripheral { /// Must be done prior to any other operation concerning those. /// /// Optional [transactionId] could be used to cancel operation. - Future discoverAllServicesAndCharacteristics({String transactionId}) => + Future discoverAllServicesAndCharacteristics({String? transactionId}) => _manager.discoverAllServicesAndCharacteristics( this, transactionId ?? TransactionIdGenerator.getNextId()); @@ -101,7 +101,7 @@ class Peripheral { /// Reads RSSI for the peripheral. /// /// Optional [transactionId] could be used to cancel operation. - Future rssi({String transactionId}) => + Future rssi({String? transactionId}) => _manager.rssi(this, transactionId ?? TransactionIdGenerator.getNextId()); /// Requests new MTU value for current connection and return the negotiation @@ -115,7 +115,7 @@ class Peripheral { /// Optional [transactionId] could be used to cancel operation. /// /// If MTU has been requested in [connect()] this method will end with [BleError]. - Future requestMtu(int mtu, {String transactionId}) => + Future requestMtu(int mtu, {String? transactionId}) => _manager.requestMtu( this, mtu, transactionId ?? TransactionIdGenerator.getNextId()); @@ -128,7 +128,7 @@ class Peripheral { Future readCharacteristic( String serviceUuid, String characteristicUuid, { - String transactionId, + String? transactionId, }) => _manager.readCharacteristicForDevice( this, @@ -148,7 +148,7 @@ class Peripheral { String characteristicUuid, Uint8List value, bool withResponse, { - String transactionId, + String? transactionId, }) => _manager.writeCharacteristicForDevice( this, @@ -183,7 +183,7 @@ class Peripheral { String serviceUuid, String characteristicUuid, String descriptorUuid, { - String transactionId, + String? transactionId, }) => _manager.readDescriptorForPeripheral( this, @@ -205,7 +205,7 @@ class Peripheral { String characteristicUuid, String descriptorUuid, Uint8List value, { - String transactionId, + String? transactionId, }) => _manager.writeDescriptorForPeripheral( this, @@ -229,7 +229,7 @@ class Peripheral { Stream monitorCharacteristic( String serviceUuid, String characteristicUuid, { - String transactionId, + String? transactionId, }) => _manager.monitorCharacteristicForDevice( this, diff --git a/lib/scan_result.dart b/lib/scan_result.dart index 3ae7ce6d..6bd37605 100644 --- a/lib/scan_result.dart +++ b/lib/scan_result.dart @@ -40,13 +40,13 @@ class ScanResult { /// manufacturer's data, advertised [Service]s class AdvertisementData { /// The manufacturer data of the peripheral. - Uint8List manufacturerData; + Uint8List? manufacturerData; /// A dictionary that contains service-specific advertisement data. - Map serviceData; + Map? serviceData; /// A list of service UUIDs. - List serviceUuids; + List? serviceUuids; /// The local name of the [Peripheral]. Might be different than /// [Peripheral.name]. @@ -56,7 +56,7 @@ class AdvertisementData { int txPowerLevel; /// A list of solicited service UUIDs. - List solicitedServiceUuids; + List? solicitedServiceUuids; AdvertisementData._fromJson(Map json) : manufacturerData = @@ -70,20 +70,20 @@ class AdvertisementData { solicitedServiceUuids = _mapToListOfStringsOrNull( json[_ScanResultMetadata.solicitedServiceUuids]); - static Map _getServiceDataOrNull( - Map serviceData) { + static Map? _getServiceDataOrNull( + Map? serviceData) { return serviceData?.map( (key, value) => MapEntry(key, base64Decode(value)), ); } - static Uint8List _decodeBase64OrNull(String base64Value) { + static Uint8List? _decodeBase64OrNull(String? base64Value) { if (base64Value != null) return base64.decode(base64Value); else return null; } - static List _mapToListOfStringsOrNull(List values) => - values?.cast(); + static List? _mapToListOfStringsOrNull(List? values) => + values?.cast(); } diff --git a/lib/service.dart b/lib/service.dart index 2b00d663..a7989b20 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -19,11 +19,10 @@ class Service extends InternalService { Map jsonObject, Peripheral peripheral, ManagerForService managerForService, - ) : super(jsonObject[_ServiceMetadata.id]) { - this.peripheral = peripheral; - uuid = jsonObject[_ServiceMetadata.uuid]; - _manager = managerForService; - } + ) : peripheral = peripheral, + uuid = jsonObject[_ServiceMetadata.uuid], + _manager = managerForService, + super(jsonObject[_ServiceMetadata.id]); /// Returns a list of [Characteristic]s of this service. Future> characteristics() => @@ -43,7 +42,7 @@ class Service extends InternalService { String characteristicUuid, Uint8List value, bool withResponse, { - String transactionId, + String? transactionId, }) => _manager.writeCharacteristicForService( peripheral, @@ -61,7 +60,7 @@ class Service extends InternalService { /// [Characteristic.isReadable] is `true` can be read. Future readCharacteristic( String characteristicUuid, { - String transactionId, + String? transactionId, }) => _manager.readCharacteristicForService( peripheral, @@ -80,7 +79,7 @@ class Service extends InternalService { /// monitored. Stream monitorCharacteristic( String characteristicUuid, { - String transactionId, + String? transactionId, }) => _manager.monitorCharacteristicForService( peripheral, @@ -108,7 +107,7 @@ class Service extends InternalService { Future readDescriptor( String characteristicUuid, String descriptorUuid, { - String transactionId, + String? transactionId, }) => _manager.readDescriptorForService( this, @@ -125,7 +124,7 @@ class Service extends InternalService { String characteristicUuid, String descriptorUuid, Uint8List value, { - String transactionId, + String? transactionId, }) => _manager.writeDescriptorForService( this, diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 69a92814..9f951a27 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -7,10 +7,10 @@ import '_internal.dart'; abstract class ManagerForPeripheral { Future connectToPeripheral( String peripheralIdentifier, { - bool isAutoConnect, - int requestMtu, - bool refreshGatt, - Duration timeout, + required bool isAutoConnect, + required int requestMtu, + required bool refreshGatt, + Duration? timeout, }); Future isPeripheralConnected(String peripheralIdentifier); @@ -39,7 +39,7 @@ abstract class ManagerForPeripheral { String transactionId, ); - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId, diff --git a/lib/src/base_entities.dart b/lib/src/base_entities.dart index 15a30288..f332e3a0 100644 --- a/lib/src/base_entities.dart +++ b/lib/src/base_entities.dart @@ -1,24 +1,20 @@ part of _internal; class InternalService { - int _id; + final int _id; InternalService(this._id); } class InternalCharacteristic { - int _id; + final int _id; InternalCharacteristic(this._id); } class InternalDescriptor { - int _id; + final int _id; InternalDescriptor(this._id); } -mixin WithValue { - /// The value of this object. - Uint8List value; -} diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index 1f1bfcd5..1298d5e6 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -159,7 +159,7 @@ mixin CharacteristicsMixin on FlutterBLE { characteristicFilter = (characteristic) => characteristic._id == characteristicIdentifier && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic.transactionId ?? ""); + transactionId ?? "", characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -190,7 +190,7 @@ mixin CharacteristicsMixin on FlutterBLE { equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && equalsIgnoreAsciiCase(serviceUuid, characteristic.service.uuid) && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic.transactionId ?? ""); + transactionId ?? "", characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -220,7 +220,7 @@ mixin CharacteristicsMixin on FlutterBLE { equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && serviceIdentifier == characteristic.service._id && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic.transactionId ?? ""); + transactionId ?? "", characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -291,7 +291,7 @@ mixin CharacteristicsMixin on FlutterBLE { } class CharacteristicWithValueAndTransactionId extends CharacteristicWithValue { - String transactionId; + String? _transactionId; CharacteristicWithValueAndTransactionId.fromJson( Map jsonObject, @@ -301,7 +301,7 @@ class CharacteristicWithValueAndTransactionId extends CharacteristicWithValue { CharacteristicWithValueAndTransactionId setTransactionId( String transactionId) { - this.transactionId = transactionId; + _transactionId = transactionId; return this; } @@ -311,13 +311,13 @@ class CharacteristicWithValueAndTransactionId extends CharacteristicWithValue { super == other && other is CharacteristicWithValueAndTransactionId && runtimeType == other.runtimeType && - transactionId == other.transactionId; + _transactionId == other._transactionId; @override - int get hashCode => super.hashCode ^ transactionId.hashCode; + int get hashCode => super.hashCode ^ _transactionId.hashCode; @override String toString() => super.toString() + - ' CharacteristicWithValueAndTransactionId{transactionId: $transactionId}'; + ' CharacteristicWithValueAndTransactionId{transactionId: $_transactionId}'; } diff --git a/lib/src/bridge/device_connection_mixin.dart b/lib/src/bridge/device_connection_mixin.dart index c15ef44f..ed22d7bf 100644 --- a/lib/src/bridge/device_connection_mixin.dart +++ b/lib/src/bridge/device_connection_mixin.dart @@ -5,8 +5,13 @@ mixin DeviceConnectionMixin on FlutterBLE { const EventChannel(ChannelName.connectionStateChangeEvents) .receiveBroadcastStream(); - Future connectToPeripheral(String deviceIdentifier, bool isAutoConnect, - int requestMtu, bool refreshGatt, Duration timeout) async { + Future connectToPeripheral( + String deviceIdentifier, + bool isAutoConnect, + int requestMtu, + bool refreshGatt, + Duration? timeout + ) async { return await _methodChannel.invokeMethod( MethodName.connectToDevice, { diff --git a/lib/src/bridge/lib_core.dart b/lib/src/bridge/lib_core.dart index 8589f1de..b3f7ed80 100644 --- a/lib/src/bridge/lib_core.dart +++ b/lib/src/bridge/lib_core.dart @@ -1,7 +1,9 @@ part of _internal; abstract class FlutterBLE { - InternalBleManager _manager; + final InternalBleManager _manager; + + FlutterBLE._(this._manager); final MethodChannel _methodChannel = const MethodChannel(ChannelName.flutterBleLib); @@ -29,30 +31,33 @@ class FlutterBleLib extends FlutterBLE const EventChannel(ChannelName.stateRestoreEvents) .receiveBroadcastStream(); - void registerManager(InternalBleManager manager) { - _manager = manager; - } + FlutterBleLib(InternalBleManager manager) : super._(manager); - Future> restoredState() => _restoreStateEvents + Future> restoredState() async { + final peripherals = await _restoreStateEvents .map( (jsonString) { - if (jsonString == null) + if (jsonString == null || + jsonString is String == false) { return null; - else { - List> restoredPeripheralsJson = - (jsonDecode(jsonString) as List).cast(); - return restoredPeripheralsJson - .map((peripheralJson) => - Peripheral.fromJson(peripheralJson, _manager)) - .toList(); } + final restoredPeripheralsJson = + (jsonDecode(jsonString) as List) + .cast>(); + return restoredPeripheralsJson + .map((peripheralJson) => + Peripheral.fromJson(peripheralJson, _manager)) + .toList(); + }, ) .take(1) .single; + return peripherals ?? []; + } - Future createClient(String restoreStateIdentifier) async { - await _methodChannel.invokeMethod(MethodName.createClient, { + Future createClient(String? restoreStateIdentifier) async { + await _methodChannel.invokeMethod(MethodName.createClient, { ArgumentName.restoreStateIdentifier: restoreStateIdentifier }); return; diff --git a/lib/src/bridge/scanning_mixin.dart b/lib/src/bridge/scanning_mixin.dart index d05a9809..1d2eba56 100644 --- a/lib/src/bridge/scanning_mixin.dart +++ b/lib/src/bridge/scanning_mixin.dart @@ -1,10 +1,10 @@ part of _internal; mixin ScanningMixin on FlutterBLE { - Stream _scanEvents; + Stream? _scanEvents; - void _prepareScanEventsStream() { - _scanEvents = const EventChannel(ChannelName.scanningEvents) + Stream _prepareScanEventsStream() { + return const EventChannel(ChannelName.scanningEvents) .receiveBroadcastStream() .handleError( (errorJson) => throw BleError.fromJson(jsonDecode(errorJson.details)), @@ -22,11 +22,13 @@ mixin ScanningMixin on FlutterBLE { List uuids, bool allowDuplicates, ) { - if (_scanEvents == null) { - _prepareScanEventsStream(); + var scanEvents = _scanEvents; + if (scanEvents == null) { + scanEvents = _prepareScanEventsStream(); + _scanEvents = scanEvents; } - StreamController streamController = StreamController.broadcast( + final streamController = StreamController.broadcast( onListen: () => _methodChannel.invokeMethod( MethodName.startDeviceScan, { @@ -40,8 +42,8 @@ mixin ScanningMixin on FlutterBLE { ); streamController - .addStream(_scanEvents, cancelOnError: true) - .then((_) => streamController?.close()); + .addStream(scanEvents, cancelOnError: true) + .then((_) => streamController.close()); return streamController.stream; } diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 888d1a8e..53211c16 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -7,17 +7,16 @@ class InternalBleManager ManagerForService, ManagerForCharacteristic, ManagerForDescriptor { - FlutterBleLib _bleLib; - + late FlutterBleLib _bleLib; + InternalBleManager() { - _bleLib = FlutterBleLib(); - _bleLib.registerManager(this); + _bleLib = FlutterBleLib(this); } @override Future createClient({ - String restoreStateIdentifier, - RestoreStateAction restoreStateAction, + String? restoreStateIdentifier, + RestoreStateAction? restoreStateAction, }) { if (restoreStateAction != null) { _bleLib.restoredState().then((devices) { @@ -35,11 +34,11 @@ class InternalBleManager _bleLib.cancelTransaction(transactionId); @override - Future enableRadio({String transactionId}) => + Future enableRadio({String? transactionId}) => _bleLib.enableRadio(transactionId ?? TransactionIdGenerator.getNextId()); @override - Future disableRadio({String transactionId}) => + Future disableRadio({String? transactionId}) => _bleLib.disableRadio(transactionId ?? TransactionIdGenerator.getNextId()); @override @@ -63,7 +62,7 @@ class InternalBleManager Future stopPeripheralScan() => _bleLib.stopDeviceScan(); @override - Peripheral createUnsafePeripheral(String peripheralId, {String name}) { + Peripheral createUnsafePeripheral(String peripheralId, {String? name}) { const nameField = 'name'; const identifierField = 'id'; return Peripheral.fromJson({ @@ -75,10 +74,10 @@ class InternalBleManager @override Future connectToPeripheral( String identifier, { - bool isAutoConnect, - int requestMtu, - bool refreshGatt, - Duration timeout, + required bool isAutoConnect, + required int requestMtu, + required bool refreshGatt, + Duration? timeout, }) async => _bleLib.connectToPeripheral( identifier, isAutoConnect, requestMtu, refreshGatt, timeout); @@ -182,7 +181,7 @@ class InternalBleManager } @override - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId) { return _bleLib.requestMtu(peripheral, mtu, transactionId); } @@ -190,12 +189,12 @@ class InternalBleManager @override Future> knownPeripherals( List peripheralIdentifiers) { - return _bleLib.knownDevices(peripheralIdentifiers ?? []); + return _bleLib.knownDevices(peripheralIdentifiers); } @override Future> connectedPeripherals(List serviceUuids) { - return _bleLib.connectedDevices(serviceUuids ?? []); + return _bleLib.connectedDevices(serviceUuids); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 1b9363ad..790ca061 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,23 +1,22 @@ name: flutter_ble_lib description: FlutterBle Library is a flutter library that supports BLE operations. It uses MultiPlatformBleAdapter as a native backend.. -version: 2.3.2 +version: 2.4.0 homepage: https://github.com/Polidea/FlutterBleLib environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" # Flutter versions prior to 1.10 did not support the flutter.plugin.platforms map. flutter: ">=1.10.0 <2.0.0" dependencies: - collection: ^1.14.11 - async: ^2.2.0 + collection: ^1.15.0 + async: ^2.5.0 flutter: sdk: flutter dev_dependencies: - test: ^1.5.3 - mockito: ^4.0.0 - pedantic: ^1.9.0 + mockito: ^5.0.3 + pedantic: ^1.11.0 flutter_test: sdk: flutter From cd829b2b9f593e66af4150ab341f2b5238a7fa33 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 29 Mar 2021 16:00:05 +0200 Subject: [PATCH 02/33] lib/** nullability compliant; added linter exceptions for string single quotes and pedantic local variable type rule --- analysis_options.yaml | 7 ++++++- lib/characteristic.dart | 2 +- lib/scan_result.dart | 5 +++-- lib/service.dart | 2 +- lib/src/bridge/characteristics_mixin.dart | 13 +++++++------ lib/src/bridge/device_connection_mixin.dart | 6 +++--- test/characteristic_test.dart | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index d4fcc1ad..46596843 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,6 @@ -include: package:pedantic/analysis_options.yaml \ No newline at end of file +include: package:pedantic/analysis_options.yaml + +linter: + rules: + prefer_single_quotes: false + omit_local_variable_types: false diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 88450d12..c2369c17 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -20,7 +20,7 @@ class Characteristic extends InternalCharacteristic { /// The [Service] containing this characteristic. Service service; - ManagerForCharacteristic _manager; + final ManagerForCharacteristic _manager; /// The UUID of this characteristic. String uuid; diff --git a/lib/scan_result.dart b/lib/scan_result.dart index 6bd37605..9d175d1b 100644 --- a/lib/scan_result.dart +++ b/lib/scan_result.dart @@ -78,10 +78,11 @@ class AdvertisementData { } static Uint8List? _decodeBase64OrNull(String? base64Value) { - if (base64Value != null) + if (base64Value != null) { return base64.decode(base64Value); - else + } else { return null; + } } static List? _mapToListOfStringsOrNull(List? values) => diff --git a/lib/service.dart b/lib/service.dart index a7989b20..9a54a663 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -10,7 +10,7 @@ class Service extends InternalService { /// [Peripheral] containing this service. Peripheral peripheral; - ManagerForService _manager; + final ManagerForService _manager; /// The UUID of this service. String uuid; diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index 1298d5e6..ff1e9528 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -159,7 +159,7 @@ mixin CharacteristicsMixin on FlutterBLE { characteristicFilter = (characteristic) => characteristic._id == characteristicIdentifier && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic._transactionId ?? ""); + transactionId, characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -190,7 +190,7 @@ mixin CharacteristicsMixin on FlutterBLE { equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && equalsIgnoreAsciiCase(serviceUuid, characteristic.service.uuid) && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic._transactionId ?? ""); + transactionId, characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -220,7 +220,7 @@ mixin CharacteristicsMixin on FlutterBLE { equalsIgnoreAsciiCase(characteristicUuid, characteristic.uuid) && serviceIdentifier == characteristic.service._id && equalsIgnoreAsciiCase( - transactionId ?? "", characteristic._transactionId ?? ""); + transactionId, characteristic._transactionId ?? ""); return _createMonitoringStream( startMonitoring, @@ -255,7 +255,7 @@ mixin CharacteristicsMixin on FlutterBLE { streamController .addStream(stream, cancelOnError: true) - .then((_) => streamController?.close()); + .then((_) => streamController.close()); return streamController.stream; } @@ -283,10 +283,11 @@ mixin CharacteristicsMixin on FlutterBLE { void _throwErrorIfMatchesWithTransactionId(errorJson, transactionId) { var errorDetails = jsonDecode(errorJson.details); - if (transactionId == errorDetails["transactionId"]) + if (transactionId == errorDetails["transactionId"]) { throw BleError.fromJson(errorDetails); - else + } else { return; + } } } diff --git a/lib/src/bridge/device_connection_mixin.dart b/lib/src/bridge/device_connection_mixin.dart index ed22d7bf..b2629c79 100644 --- a/lib/src/bridge/device_connection_mixin.dart +++ b/lib/src/bridge/device_connection_mixin.dart @@ -30,7 +30,7 @@ mixin DeviceConnectionMixin on FlutterBLE { Stream observePeripheralConnectionState( String identifier, bool emitCurrentValue) { - var controller = StreamController( + final controller = StreamController( onListen: () => _methodChannel.invokeMethod( MethodName.observeConnectionState, { @@ -42,7 +42,7 @@ mixin DeviceConnectionMixin on FlutterBLE { ), ); - var sourceStream = _peripheralConnectionStateChanges + final sourceStream = _peripheralConnectionStateChanges .map((jsonString) => ConnectionStateContainer.fromJson(jsonDecode(jsonString))) .where((connectionStateContainer) => @@ -71,7 +71,7 @@ mixin DeviceConnectionMixin on FlutterBLE { sourceStream, cancelOnError: true, ) - .then((value) => controller?.close()); + .then((value) => controller.close()); return controller.stream; } diff --git a/test/characteristic_test.dart b/test/characteristic_test.dart index 543e0a13..0f0ed1ac 100644 --- a/test/characteristic_test.dart +++ b/test/characteristic_test.dart @@ -5,7 +5,7 @@ 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 'package:flutter_test'; import 'mock/mocks.dart'; import 'test_util/characteristic_generator.dart'; From 44cf93f3a9244cfdc2c7091c9bdbd56cc57fcf47 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 29 Mar 2021 17:22:37 +0200 Subject: [PATCH 03/33] Example:: updated to nullsafe-ready dependencies --- example/lib/device_details/device_details_bloc.dart | 6 +++--- .../lib/device_details/view/logs_container_view.dart | 2 +- example/lib/devices_list/devices_bloc.dart | 10 ++-------- example/lib/devices_list/devices_list_view.dart | 2 +- example/lib/repository/device_repository.dart | 2 +- example/pubspec.yaml | 12 ++++++------ 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/example/lib/device_details/device_details_bloc.dart b/example/lib/device_details/device_details_bloc.dart index 693de732..b1d23043 100644 --- a/example/lib/device_details/device_details_bloc.dart +++ b/example/lib/device_details/device_details_bloc.dart @@ -13,16 +13,16 @@ class DeviceDetailsBloc { BehaviorSubject _deviceController; - ValueObservable get device => _deviceController.stream; + ValueStream get device => _deviceController.stream; BehaviorSubject _connectionStateController; - ValueObservable get connectionState => + ValueStream get connectionState => _connectionStateController.stream; Subject> _logsController; - Observable> get logs => _logsController.stream; + Stream> get logs => _logsController.stream; Stream get disconnectedDevice => _deviceRepository.pickedDevice .skipWhile((bleDevice) => bleDevice != null); diff --git a/example/lib/device_details/view/logs_container_view.dart b/example/lib/device_details/view/logs_container_view.dart index 37398d9f..925cff7d 100644 --- a/example/lib/device_details/view/logs_container_view.dart +++ b/example/lib/device_details/view/logs_container_view.dart @@ -3,7 +3,7 @@ import 'package:flutter_ble_lib_example/device_details/device_details_bloc.dart' import 'package:rxdart/rxdart.dart'; class LogsContainerView extends StatelessWidget { - final Observable> _logs; + final Stream> _logs; LogsContainerView(this._logs); diff --git a/example/lib/devices_list/devices_bloc.dart b/example/lib/devices_list/devices_bloc.dart index 4c57c66b..9503ed46 100644 --- a/example/lib/devices_list/devices_bloc.dart +++ b/example/lib/devices_list/devices_bloc.dart @@ -18,13 +18,12 @@ class DevicesBloc { StreamSubscription _scanSubscription; StreamSubscription _devicePickerSubscription; - ValueObservable> get visibleDevices => _visibleDevicesController.stream; + ValueStream> get visibleDevices => _visibleDevicesController.stream; Sink get devicePicker => _devicePickerController.sink; DeviceRepository _deviceRepository; BleManager _bleManager; - PermissionStatus _locationPermissionStatus = PermissionStatus.unknown; Stream get pickedDevice => _deviceRepository.pickedDevice .skipWhile((bleDevice) => bleDevice == null); @@ -97,12 +96,7 @@ class DevicesBloc { Future _checkPermissions() async { if (Platform.isAndroid) { - var permissionStatus = await PermissionHandler() - .requestPermissions([PermissionGroup.location]); - - _locationPermissionStatus = permissionStatus[PermissionGroup.location]; - - if (_locationPermissionStatus != PermissionStatus.granted) { + if (await Permission.location.isGranted) { return Future.error(Exception("Location permission not granted")); } } diff --git a/example/lib/devices_list/devices_list_view.dart b/example/lib/devices_list/devices_list_view.dart index e5ebadc1..61cef3d0 100644 --- a/example/lib/devices_list/devices_list_view.dart +++ b/example/lib/devices_list/devices_list_view.dart @@ -72,7 +72,7 @@ class DeviceListScreenState extends State { title: Text('Bluetooth devices'), ), body: StreamBuilder>( - initialData: _devicesBloc.visibleDevices.value, + initialData: _devicesBloc.visibleDevices.valueWrapper?.value ?? [], stream: _devicesBloc.visibleDevices, builder: (context, snapshot) => RefreshIndicator( onRefresh: _devicesBloc.refresh, diff --git a/example/lib/repository/device_repository.dart b/example/lib/repository/device_repository.dart index b9fa1978..904610b8 100644 --- a/example/lib/repository/device_repository.dart +++ b/example/lib/repository/device_repository.dart @@ -23,7 +23,7 @@ class DeviceRepository { _deviceController.add(_bleDevice); } - ValueObservable get pickedDevice => + ValueStream get pickedDevice => _deviceController.stream.shareValueSeeded(_bleDevice); bool get hasPickedDevice => _bleDevice != null; diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 19913f60..7b975071 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,10 +1,10 @@ name: flutter_ble_lib_example description: Demonstrates how to use the flutter_ble_lib plugin. -version: 0.0.1+1 +version: 0.1.0+2 publish_to: "none" environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.11.0-0 <3.0.0" dependencies: flutter: @@ -12,12 +12,12 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 + cupertino_icons: ^1.0.2 - rxdart: ^0.22.0 - fimber: ^0.1.10 + rxdart: ^0.26.0 + fimber: ^0.6.1 - permission_handler: ^4.2.0+hotfix.3 + permission_handler: ^6.1.1 dev_dependencies: flutter_test: From 7cff4d42cb31cde551c2e8b4d144a40857078532 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 30 Mar 2021 08:37:09 +0200 Subject: [PATCH 04/33] Example:: nullsafety + refactor WIP --- .../device_details/device_detail_view.dart | 24 ++- .../device_details/device_details_bloc.dart | 158 +++++++++--------- .../devices_details_bloc_provider.dart | 6 +- .../lib/device_details/view/button_view.dart | 2 +- .../view/logs_container_view.dart | 16 +- .../devices_list/devices_bloc_provider.dart | 6 +- example/lib/repository/device_repository.dart | 14 +- example/pubspec.yaml | 2 +- 8 files changed, 119 insertions(+), 109 deletions(-) diff --git a/example/lib/device_details/device_detail_view.dart b/example/lib/device_details/device_detail_view.dart index dc8948a7..529314ca 100644 --- a/example/lib/device_details/device_detail_view.dart +++ b/example/lib/device_details/device_detail_view.dart @@ -13,8 +13,8 @@ class DeviceDetailsView extends StatefulWidget { } class DeviceDetailsViewState extends State { - DeviceDetailsBloc _deviceDetailsBloc; - StreamSubscription _appStateSubscription; + DeviceDetailsBloc? _deviceDetailsBloc; + StreamSubscription? _appStateSubscription; bool _shouldRunOnResume = true; @@ -33,9 +33,9 @@ class DeviceDetailsViewState extends State { void _onResume() { Fimber.d("onResume"); - _deviceDetailsBloc.init(); + _deviceDetailsBloc?.init(); _appStateSubscription = - _deviceDetailsBloc.disconnectedDevice.listen((bleDevice) async { + _deviceDetailsBloc?.disconnectedDevice.listen((bleDevice) async { Fimber.d("navigate to details"); _onPause(); Navigator.pop(context); @@ -46,8 +46,8 @@ class DeviceDetailsViewState extends State { void _onPause() { Fimber.d("onPause"); - _appStateSubscription.cancel(); - _deviceDetailsBloc.dispose(); + _appStateSubscription?.cancel(); + _deviceDetailsBloc?.dispose(); } @override @@ -59,9 +59,13 @@ class DeviceDetailsViewState extends State { @override Widget build(BuildContext context) { + final deviceDetailsBloc = _deviceDetailsBloc; return WillPopScope( onWillPop: () { - return _deviceDetailsBloc.disconnect().then((_) { + if (deviceDetailsBloc == null) { + return Future.value(true); + } + return deviceDetailsBloc.disconnect().then((_) { return false; }); }, @@ -86,8 +90,10 @@ class DeviceDetailsViewState extends State { ), body: TabBarView( children: [ - AutoTestView(_deviceDetailsBloc), - ManualTestView(_deviceDetailsBloc), + if (deviceDetailsBloc != null) + AutoTestView(deviceDetailsBloc), + if (deviceDetailsBloc != null) + ManualTestView(deviceDetailsBloc), ], )), ), diff --git a/example/lib/device_details/device_details_bloc.dart b/example/lib/device_details/device_details_bloc.dart index b1d23043..266e95e3 100644 --- a/example/lib/device_details/device_details_bloc.dart +++ b/example/lib/device_details/device_details_bloc.dart @@ -11,9 +11,7 @@ class DeviceDetailsBloc { final BleManager _bleManager; final DeviceRepository _deviceRepository; - BehaviorSubject _deviceController; - - ValueStream get device => _deviceController.stream; + final BleDevice _bleDevice; BehaviorSubject _connectionStateController; @@ -24,22 +22,22 @@ class DeviceDetailsBloc { Stream> get logs => _logsController.stream; - Stream get disconnectedDevice => _deviceRepository.pickedDevice - .skipWhile((bleDevice) => bleDevice != null); + Stream get disconnectedDevice => _deviceRepository.pickedDevice + .skipWhile((bleDevice) => bleDevice != null).cast(); List _logs = []; - Logger log; - Logger logError; - - DeviceDetailsBloc(this._deviceRepository, this._bleManager) { - var device = _deviceRepository.pickedDevice.value; - _deviceController = BehaviorSubject.seeded(device); - - _connectionStateController = - BehaviorSubject.seeded( - PeripheralConnectionState.disconnected); - - _logsController = PublishSubject>(); + late Logger log; + late Logger logError; + + DeviceDetailsBloc( + this._deviceRepository, + this._bleManager + ) + : _connectionStateController = + BehaviorSubject.seeded( + PeripheralConnectionState.disconnected + ), + _logsController = PublishSubject>() { log = (text) { var now = DateTime.now(); @@ -73,146 +71,150 @@ class DeviceDetailsBloc { Future disconnectManual() async { _clearLogs(); - if (await _deviceController.stream.value.peripheral.isConnected()) { + final bleDevice = _bleDevice; + // if (bleDevice == null) { + // log("No device to Disconnect!"); + // return; + // } + if (await bleDevice.peripheral.isConnected()) { log("DISCONNECTING..."); - await _deviceController.stream.value.peripheral - .disconnectOrCancelConnection(); + await bleDevice.peripheral.disconnectOrCancelConnection(); } log("Disconnected!"); } void readRssi() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .testReadingRssi(); - }); + // }); } void discovery() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .discovery(); - }); + // }); } void fetchConnectedDevices() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .fetchConnectedDevice(); - }); + // }); } void fetchKnownDevices() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .fetchKnownDevice(); - }); + // }); } void readCharacteristicForPeripheral() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .readCharacteristicForPeripheral(); - }); + // }); } void readCharacteristicForService() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .readCharacteristicForService(); - }); + // }); } void readCharacteristicDirectly() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .readCharacteristic(); - }); + // }); } void writeCharacteristicForPeripheral() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .writeCharacteristicForPeripheral(); - }); + // }); } void writeCharacteristicForService() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .writeCharacteristicForService(); - }); + // }); } void writeCharacteristicDirectly() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .writeCharacteristic(); - }); + // }); } void monitorCharacteristicForPeripheral() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .monitorCharacteristicForPeripheral(); - }); + // }); } void monitorCharacteristicForService() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .monitorCharacteristicForService(); - }); + // }); } void monitorCharacteristicDirectly() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .monitorCharacteristic(); - }); + // }); } void disableBluetooth() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .disableBluetooth(); - }); + // }); } void enableBluetooth() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .enableBluetooth(); - }); + // }); } void fetchBluetoothState() { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, bleDevice.peripheral, log, logError) + // _bleDevice.stream.listen((bleDevice) async { + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .fetchBluetoothState(); - }); + // }); } Future connect() async { _clearLogs(); - _deviceController.stream.listen((bleDevice) async { - var peripheral = bleDevice.peripheral; + // _bleDevice.stream.listen((bleDevice) async { + var peripheral = _bleDevice.peripheral; peripheral .observeConnectionState( @@ -229,12 +231,12 @@ class DeviceDetailsBloc { } on BleError catch (e) { logError(e.toString()); } - }); + // }); } void dispose() async { - await _deviceController.drain(); - _deviceController.close(); + // await _bleDevice.drain(); + // _bleDevice.close(); await _connectionStateController.drain(); _connectionStateController.close(); @@ -268,17 +270,17 @@ class DeviceDetailsBloc { void startAutoTest() { _clearLogs(); - _deviceController.stream.listen((bleDevice) { - Fimber.d("got bleDevice: $bleDevice"); - bleDevice.peripheral.isConnected().then((isConnected) { + // _bleDevice.stream.listen((bleDevice) { + Fimber.d("got bleDevice: $_bleDevice"); + _bleDevice.peripheral.isConnected().then((isConnected) { Fimber.d('The device is connected: $isConnected'); if (!isConnected) { - _connectTo(bleDevice); + _connectTo(_bleDevice); } }).catchError((error) { logError('Connection problem: ${error.toString()}'); }); - }); + // }); } void _clearLogs() { diff --git a/example/lib/device_details/devices_details_bloc_provider.dart b/example/lib/device_details/devices_details_bloc_provider.dart index 72952eaa..d6dcb229 100644 --- a/example/lib/device_details/devices_details_bloc_provider.dart +++ b/example/lib/device_details/devices_details_bloc_provider.dart @@ -8,9 +8,9 @@ class DeviceDetailsBlocProvider extends InheritedWidget { final DeviceDetailsBloc deviceDetailsBloc; DeviceDetailsBlocProvider({ - Key key, - DeviceDetailsBloc deviceDetailsBloc, - Widget child, + Key? key, + DeviceDetailsBloc? deviceDetailsBloc, + required Widget child, }) : deviceDetailsBloc = deviceDetailsBloc ?? DeviceDetailsBloc(DeviceRepository(), BleManager()), super(key: key, child: child); diff --git a/example/lib/device_details/view/button_view.dart b/example/lib/device_details/view/button_view.dart index f9789f61..a5457fda 100644 --- a/example/lib/device_details/view/button_view.dart +++ b/example/lib/device_details/view/button_view.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class ButtonView extends StatelessWidget { final String _text; - final Function action; + final void Function()? action; ButtonView(this._text, {this.action}); diff --git a/example/lib/device_details/view/logs_container_view.dart b/example/lib/device_details/view/logs_container_view.dart index 925cff7d..81d78ff7 100644 --- a/example/lib/device_details/view/logs_container_view.dart +++ b/example/lib/device_details/view/logs_container_view.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_ble_lib_example/device_details/device_details_bloc.dart'; -import 'package:rxdart/rxdart.dart'; class LogsContainerView extends StatelessWidget { final Stream> _logs; @@ -31,8 +30,9 @@ class LogsContainerView extends StatelessWidget { } Widget _buildLogs(BuildContext context, AsyncSnapshot> logs) { + final data = logs.data; return ListView.builder( - itemCount: logs.data.length, + itemCount: data?.length, shrinkWrap: true, itemBuilder: (buildContext, index) => Container( decoration: BoxDecoration( @@ -55,15 +55,17 @@ class LogsContainerView extends StatelessWidget { Padding( padding: const EdgeInsets.only(right: 8.0), child: Text( - logs.data[index].time, + data?[index].time ?? "", style: TextStyle(fontSize: 9), ), ), Flexible( - child: Text(logs.data[index].content, - overflow: TextOverflow.ellipsis, - softWrap: true, - style: TextStyle(fontSize: 13)), + child: Text( + data?[index].content ?? "", + overflow: TextOverflow.ellipsis, + softWrap: true, + style: TextStyle(fontSize: 13) + ), ), ], ), diff --git a/example/lib/devices_list/devices_bloc_provider.dart b/example/lib/devices_list/devices_bloc_provider.dart index 61156c86..495fcb63 100644 --- a/example/lib/devices_list/devices_bloc_provider.dart +++ b/example/lib/devices_list/devices_bloc_provider.dart @@ -7,9 +7,9 @@ class DevicesBlocProvider extends InheritedWidget { final DevicesBloc devicesBloc; DevicesBlocProvider({ - Key key, - DevicesBloc devicesBloc, - Widget child, + Key? key, + DevicesBloc devicesBloc = DevicesBloc(), + required Widget child, }) : devicesBloc = devicesBloc ?? DevicesBloc(DeviceRepository(), BleManager()), super(key: key, child: child); diff --git a/example/lib/repository/device_repository.dart b/example/lib/repository/device_repository.dart index 904610b8..f8f0fe7b 100644 --- a/example/lib/repository/device_repository.dart +++ b/example/lib/repository/device_repository.dart @@ -4,8 +4,8 @@ import 'package:rxdart/rxdart.dart'; class MissingPickedDeviceException implements Exception {} class DeviceRepository { - static BleDevice _bleDevice; - BehaviorSubject _deviceController; + static BleDevice? _bleDevice; + BehaviorSubject _deviceController; static final DeviceRepository _deviceRepository = DeviceRepository._internal(); @@ -14,16 +14,16 @@ class DeviceRepository { return _deviceRepository; } - DeviceRepository._internal() { - _deviceController = BehaviorSubject.seeded(_bleDevice); - } + DeviceRepository._internal() + : _deviceController = BehaviorSubject.seeded(_bleDevice); + - void pickDevice(BleDevice bleDevice) { + void pickDevice(BleDevice? bleDevice) { _bleDevice = bleDevice; _deviceController.add(_bleDevice); } - ValueStream get pickedDevice => + ValueStream get pickedDevice => _deviceController.stream.shareValueSeeded(_bleDevice); bool get hasPickedDevice => _bleDevice != null; diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 7b975071..72b65611 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.1.0+2 publish_to: "none" environment: - sdk: ">=2.11.0-0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dependencies: flutter: From 991473f1b4288838545efa562158abfb8746a977 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 30 Mar 2021 19:15:28 +0200 Subject: [PATCH 05/33] Example:: nullsafe ready --- .../device_details/device_details_bloc.dart | 18 ++++++---- .../devices_details_bloc_provider.dart | 12 +++---- example/lib/devices_list/devices_bloc.dart | 33 ++++++++++------- .../devices_list/devices_bloc_provider.dart | 11 +++--- .../lib/devices_list/devices_list_view.dart | 35 ++++++++++++------- example/lib/devices_list/hex_painter.dart | 4 +-- example/lib/repository/device_repository.dart | 2 +- .../bluetooth_state_toggle_scenario.dart | 4 +-- .../peripheral_test_operations.dart | 10 +++--- .../sensor_tag_test_scenario.dart | 5 ++- 10 files changed, 75 insertions(+), 59 deletions(-) diff --git a/example/lib/device_details/device_details_bloc.dart b/example/lib/device_details/device_details_bloc.dart index 266e95e3..280fb4d4 100644 --- a/example/lib/device_details/device_details_bloc.dart +++ b/example/lib/device_details/device_details_bloc.dart @@ -7,11 +7,14 @@ import 'package:flutter_ble_lib_example/repository/device_repository.dart'; import 'package:flutter_ble_lib_example/test_scenarios/test_scenarios.dart'; import 'package:rxdart/rxdart.dart'; +import '../model/ble_device.dart'; +import '../repository/device_repository.dart'; + class DeviceDetailsBloc { final BleManager _bleManager; final DeviceRepository _deviceRepository; - final BleDevice _bleDevice; + late final BleDevice _bleDevice; BehaviorSubject _connectionStateController; @@ -29,15 +32,18 @@ class DeviceDetailsBloc { late Logger log; late Logger logError; - DeviceDetailsBloc( - this._deviceRepository, - this._bleManager - ) - : _connectionStateController = + DeviceDetailsBloc({ + DeviceRepository? deviceRepository, + BleManager? bleManager + }) + : _deviceRepository = deviceRepository ?? DeviceRepository(), + _bleManager = bleManager ?? BleManager(), + _connectionStateController = BehaviorSubject.seeded( PeripheralConnectionState.disconnected ), _logsController = PublishSubject>() { + _bleDevice = _deviceRepository.pickedDevice.value!; log = (text) { var now = DateTime.now(); diff --git a/example/lib/device_details/devices_details_bloc_provider.dart b/example/lib/device_details/devices_details_bloc_provider.dart index d6dcb229..26930f91 100644 --- a/example/lib/device_details/devices_details_bloc_provider.dart +++ b/example/lib/device_details/devices_details_bloc_provider.dart @@ -1,24 +1,22 @@ import 'package:flutter/widgets.dart'; -import 'package:flutter_ble_lib_example/repository/device_repository.dart'; -import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'device_details_bloc.dart'; class DeviceDetailsBlocProvider extends InheritedWidget { - final DeviceDetailsBloc deviceDetailsBloc; + final DeviceDetailsBloc _deviceDetailsBloc; DeviceDetailsBlocProvider({ Key? key, DeviceDetailsBloc? deviceDetailsBloc, required Widget child, - }) : deviceDetailsBloc = deviceDetailsBloc ?? - DeviceDetailsBloc(DeviceRepository(), BleManager()), - super(key: key, child: child); + }) + : _deviceDetailsBloc = deviceDetailsBloc ?? DeviceDetailsBloc(), + super(key: key, child: child); @override bool updateShouldNotify(InheritedWidget oldWidget) => true; static DeviceDetailsBloc of(BuildContext context) => context .dependOnInheritedWidgetOfExactType() - .deviceDetailsBloc; + !._deviceDetailsBloc; } diff --git a/example/lib/devices_list/devices_bloc.dart b/example/lib/devices_list/devices_bloc.dart index 9503ed46..aab41edf 100644 --- a/example/lib/devices_list/devices_bloc.dart +++ b/example/lib/devices_list/devices_bloc.dart @@ -15,20 +15,27 @@ class DevicesBloc { StreamController _devicePickerController = StreamController(); - StreamSubscription _scanSubscription; - StreamSubscription _devicePickerSubscription; + StreamSubscription? _scanSubscription; + StreamSubscription? _devicePickerSubscription; ValueStream> get visibleDevices => _visibleDevicesController.stream; Sink get devicePicker => _devicePickerController.sink; - DeviceRepository _deviceRepository; - BleManager _bleManager; + final DeviceRepository _deviceRepository; + final BleManager _bleManager; Stream get pickedDevice => _deviceRepository.pickedDevice - .skipWhile((bleDevice) => bleDevice == null); + .skipWhile((bleDevice) => bleDevice == null).cast(); - DevicesBloc(this._deviceRepository, this._bleManager); + DevicesBloc({ + DeviceRepository? deviceRepository, + BleManager? bleManager + }) + : _deviceRepository = deviceRepository ?? DeviceRepository(), + _bleManager = bleManager ?? BleManager() { + + } bool clientCreated = false; @@ -38,7 +45,7 @@ class DevicesBloc { void dispose() { Fimber.d("cancel _devicePickerSubscription"); - _devicePickerSubscription.cancel(); + _devicePickerSubscription?.cancel(); _visibleDevicesController.close(); _devicePickerController.close(); _scanSubscription?.cancel(); @@ -83,7 +90,7 @@ class DevicesBloc { .createClient( restoreStateIdentifier: "example-restore-state-identifier", restoreStateAction: (peripherals) { - peripherals?.forEach((peripheral) { + peripherals.forEach((peripheral) { Fimber.d("Restored peripheral: ${peripheral.name}"); }); } @@ -104,12 +111,12 @@ class DevicesBloc { Future _waitForBluetoothPoweredOn() async { Completer completer = Completer(); - StreamSubscription subscription; + StreamSubscription? subscription; subscription = _bleManager .observeBluetoothState(emitCurrentValue: true) .listen((bluetoothState) async { if (bluetoothState == BluetoothState.POWERED_ON && !completer.isCompleted) { - await subscription.cancel(); + await subscription?.cancel(); completer.complete(); } }); @@ -120,9 +127,9 @@ class DevicesBloc { void _startScan() { Fimber.d("Ble start scan"); _scanSubscription = _bleManager.startPeripheralScan() - .listen((ScanResult scanResult) { + .listen((scanResult) { var bleDevice = BleDevice(scanResult); - if (scanResult.advertisementData.localName != null && !bleDevices.contains(bleDevice)) { + if (!bleDevices.contains(bleDevice)) { Fimber.d('found new device ${scanResult.advertisementData.localName} ${scanResult.peripheral.identifier}'); bleDevices.add(bleDevice); _visibleDevicesController.add(bleDevices.sublist(0)); @@ -132,7 +139,7 @@ class DevicesBloc { Future refresh() async { await _bleManager.stopPeripheralScan(); - await _scanSubscription.cancel(); + await _scanSubscription?.cancel(); bleDevices.clear(); _visibleDevicesController.add(bleDevices.sublist(0)); diff --git a/example/lib/devices_list/devices_bloc_provider.dart b/example/lib/devices_list/devices_bloc_provider.dart index 495fcb63..bc37ae17 100644 --- a/example/lib/devices_list/devices_bloc_provider.dart +++ b/example/lib/devices_list/devices_bloc_provider.dart @@ -1,17 +1,14 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_ble_lib_example/devices_list/devices_bloc.dart'; -import 'package:flutter_ble_lib_example/repository/device_repository.dart'; -import 'package:flutter_ble_lib/flutter_ble_lib.dart'; class DevicesBlocProvider extends InheritedWidget { - final DevicesBloc devicesBloc; + final DevicesBloc _devicesBloc; DevicesBlocProvider({ Key? key, - DevicesBloc devicesBloc = DevicesBloc(), + DevicesBloc? devicesBloc, required Widget child, - }) : devicesBloc = - devicesBloc ?? DevicesBloc(DeviceRepository(), BleManager()), + }) : _devicesBloc = devicesBloc ?? DevicesBloc(), super(key: key, child: child); @override @@ -19,5 +16,5 @@ class DevicesBlocProvider extends InheritedWidget { static DevicesBloc of(BuildContext context) => context .dependOnInheritedWidgetOfExactType() - .devicesBloc; + !._devicesBloc; } diff --git a/example/lib/devices_list/devices_list_view.dart b/example/lib/devices_list/devices_list_view.dart index 61cef3d0..a73a90ce 100644 --- a/example/lib/devices_list/devices_list_view.dart +++ b/example/lib/devices_list/devices_list_view.dart @@ -17,8 +17,8 @@ class DevicesListScreen extends StatefulWidget { } class DeviceListScreenState extends State { - DevicesBloc _devicesBloc; - StreamSubscription _appStateSubscription; + DevicesBloc? _devicesBloc; + StreamSubscription? _appStateSubscription; bool _shouldRunOnResume = true; @override @@ -29,14 +29,19 @@ class DeviceListScreenState extends State { void _onPause() { Fimber.d("onPause"); - _appStateSubscription.cancel(); - _devicesBloc.dispose(); + _appStateSubscription?.cancel(); + _devicesBloc?.dispose(); } void _onResume() { Fimber.d("onResume"); - _devicesBloc.init(); - _appStateSubscription = _devicesBloc.pickedDevice.listen((bleDevice) async { + final devicesBloc = _devicesBloc; + if (devicesBloc == null) { + Fimber.d("onResume:: no devicesBloc present"); + return; + } + devicesBloc.init(); + _appStateSubscription = devicesBloc.pickedDevice.listen((bleDevice) async { Fimber.d("navigate to details"); _onPause(); await Navigator.pushNamed(context, "/details"); @@ -67,16 +72,20 @@ class DeviceListScreenState extends State { _shouldRunOnResume = false; _onResume(); } + final devicesBloc = _devicesBloc; + if (devicesBloc == null) { + throw Exception(); + } return Scaffold( appBar: AppBar( title: Text('Bluetooth devices'), ), body: StreamBuilder>( - initialData: _devicesBloc.visibleDevices.valueWrapper?.value ?? [], - stream: _devicesBloc.visibleDevices, + initialData: devicesBloc.visibleDevices.valueWrapper?.value ?? [], + stream: devicesBloc.visibleDevices, builder: (context, snapshot) => RefreshIndicator( - onRefresh: _devicesBloc.refresh, - child: DevicesList(_devicesBloc, snapshot.data), + onRefresh: devicesBloc.refresh , + child: DevicesList(devicesBloc, snapshot.data), ), ), ); @@ -103,17 +112,17 @@ class DeviceListScreenState extends State { } class DevicesList extends ListView { - DevicesList(DevicesBloc devicesBloc, List devices) + DevicesList(DevicesBloc devicesBloc, List? devices) : super.separated( separatorBuilder: (context, index) => Divider( color: Colors.grey[300], height: 0, indent: 0, ), - itemCount: devices.length, + itemCount: devices?.length ?? 0, itemBuilder: (context, i) { Fimber.d("Build row for $i"); - return _buildRow(context, devices[i], + return _buildRow(context, devices![i], _createTapListener(devicesBloc, devices[i])); }); diff --git a/example/lib/devices_list/hex_painter.dart b/example/lib/devices_list/hex_painter.dart index b2416c73..d8ea409d 100644 --- a/example/lib/devices_list/hex_painter.dart +++ b/example/lib/devices_list/hex_painter.dart @@ -5,8 +5,8 @@ class HexPainter extends CustomPainter { final Color _backgroundColor; HexPainter({ - Color backgroundColor, - Color foregroundColor, + Color? backgroundColor, + Color? foregroundColor, }) : _backgroundColor = backgroundColor ?? Colors.white, _foregroundColor = foregroundColor ?? Colors.black, super(); diff --git a/example/lib/repository/device_repository.dart b/example/lib/repository/device_repository.dart index f8f0fe7b..e06dca12 100644 --- a/example/lib/repository/device_repository.dart +++ b/example/lib/repository/device_repository.dart @@ -10,7 +10,7 @@ class DeviceRepository { static final DeviceRepository _deviceRepository = DeviceRepository._internal(); - factory DeviceRepository() { + factory DeviceRepository() { return _deviceRepository; } diff --git a/example/lib/test_scenarios/bluetooth_state_toggle_scenario.dart b/example/lib/test_scenarios/bluetooth_state_toggle_scenario.dart index 043582c8..c6310e4c 100644 --- a/example/lib/test_scenarios/bluetooth_state_toggle_scenario.dart +++ b/example/lib/test_scenarios/bluetooth_state_toggle_scenario.dart @@ -1,7 +1,7 @@ part of test_scenarios; class BluetoothStateTestScenario implements TestScenario { - StreamSubscription _radioStateSubscription; + StreamSubscription? _radioStateSubscription; @override Future runTestScenario(Logger log, Logger errorLogger) async { @@ -24,7 +24,7 @@ class BluetoothStateTestScenario implements TestScenario { try { await bleManager.enableRadio(); } catch (e) { - errorLogger(e); + errorLogger(e.toString()); } log("Enabled radio!"); diff --git a/example/lib/test_scenarios/peripheral_test_operations.dart b/example/lib/test_scenarios/peripheral_test_operations.dart index dffe5d65..295f6292 100644 --- a/example/lib/test_scenarios/peripheral_test_operations.dart +++ b/example/lib/test_scenarios/peripheral_test_operations.dart @@ -6,7 +6,7 @@ class PeripheralTestOperations { final Peripheral peripheral; final Logger log; final Logger logError; - StreamSubscription monitoringStreamSubscription; + StreamSubscription? _monitoringStreamSubscription; final BleManager bleManager; PeripheralTestOperations( @@ -60,9 +60,9 @@ class PeripheralTestOperations { log("Found characteristic \n ${characteristic.uuid}")); //------------ descriptors - List descriptors; + List? descriptors; - var printDescriptors = () => descriptors.forEach((descriptor) { + var printDescriptors = () => descriptors?.forEach((descriptor) { log("Descriptor: ${descriptor.uuid}"); }); @@ -711,8 +711,8 @@ class PeripheralTestOperations { void _startMonitoringTemperature( Stream characteristicUpdates, Function log) async { - await monitoringStreamSubscription?.cancel(); - monitoringStreamSubscription = + await _monitoringStreamSubscription?.cancel(); + _monitoringStreamSubscription = characteristicUpdates.map(_convertToTemperature).listen( (temperature) { log("Temperature updated: ${temperature}C"); diff --git a/example/lib/test_scenarios/sensor_tag_test_scenario.dart b/example/lib/test_scenarios/sensor_tag_test_scenario.dart index 9ce95c4b..b9bde9a2 100644 --- a/example/lib/test_scenarios/sensor_tag_test_scenario.dart +++ b/example/lib/test_scenarios/sensor_tag_test_scenario.dart @@ -4,10 +4,9 @@ class SensorTagTestScenario { PeripheralTestOperations _peripheralTestOperations; SensorTagTestScenario(BleManager bleManager, Peripheral peripheral, - Logger log, Logger logError) { - _peripheralTestOperations = + Logger log, Logger logError) + : _peripheralTestOperations = PeripheralTestOperations(bleManager, peripheral, log, logError); - } Future runTestScenario() async { _peripheralTestOperations From fdac5688e66598ac410b1a36be46dfb6137b4b88 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 30 Mar 2021 19:17:58 +0200 Subject: [PATCH 06/33] Example/test:: nullsafe ready --- example/test/widget_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index def6a68d..86f64e65 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -19,7 +19,7 @@ void main() { expect( find.byWidgetPredicate( (Widget widget) => - widget is Text && widget.data.startsWith('Running on:'), + widget is Text && widget.data != null && widget.data!.startsWith('Running on:'), ), findsOneWidget, ); From 5ba26680915ecba01e103b15b456de035bb6070c Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 31 Mar 2021 12:36:56 +0200 Subject: [PATCH 07/33] test:: using new mocking mechanism additional fixes --- .vscode/settings.json | 5 + analysis_options.yaml | 1 + lib/service.dart | 3 +- pubspec.yaml | 1 + test/analysis_options.yaml | 5 + test/ble_manager_test.dart | 2 +- test/characteristic_test.dart | 19 +- test/characteristic_test.mocks.dart | 383 +++++++++++++++++++ test/descriptor_test.dart | 9 +- test/descriptor_test.mocks.dart | 168 ++++++++ test/mock/mocks.dart | 1 - test/service_test.dart | 14 +- test/service_test.mocks.dart | 376 ++++++++++++++++++ test/src/bridge/lib_core_test.dart | 94 +++-- test/src/bridge/lib_core_test.mocks.dart | 349 +++++++++++++++++ test/test_util/characteristic_generator.dart | 2 +- test/test_util/descriptor_generator.dart | 2 +- 17 files changed, 1371 insertions(+), 63 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 test/analysis_options.yaml create mode 100644 test/characteristic_test.mocks.dart create mode 100644 test/descriptor_test.mocks.dart create mode 100644 test/service_test.mocks.dart create mode 100644 test/src/bridge/lib_core_test.mocks.dart diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..305ccba7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.rulers": [ + 80 + ] +} \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index 46596843..bcdf3e0c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -4,3 +4,4 @@ linter: rules: prefer_single_quotes: false omit_local_variable_types: false + unawaited_futures: false diff --git a/lib/service.dart b/lib/service.dart index 9a54a663..409ded39 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -18,10 +18,9 @@ class Service extends InternalService { Service.fromJson( Map jsonObject, Peripheral peripheral, - ManagerForService managerForService, + this._manager, ) : peripheral = peripheral, uuid = jsonObject[_ServiceMetadata.uuid], - _manager = managerForService, super(jsonObject[_ServiceMetadata.id]); /// Returns a list of [Characteristic]s of this service. diff --git a/pubspec.yaml b/pubspec.yaml index 790ca061..08664996 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: dev_dependencies: mockito: ^5.0.3 + build_runner: ^1.12.2 pedantic: ^1.11.0 flutter_test: diff --git a/test/analysis_options.yaml b/test/analysis_options.yaml new file mode 100644 index 00000000..94594611 --- /dev/null +++ b/test/analysis_options.yaml @@ -0,0 +1,5 @@ +include: ../analysis_options.yaml + +linter: + rules: + unawaited_futures: false diff --git a/test/ble_manager_test.dart b/test/ble_manager_test.dart index f4c2c86a..7967dec2 100644 --- a/test/ble_manager_test.dart +++ b/test/ble_manager_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_ble_lib/flutter_ble_lib.dart'; -import 'package:test/test.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { test('Ble manager must be singleton', () { diff --git a/test/characteristic_test.dart b/test/characteristic_test.dart index 0f0ed1ac..5efcacf8 100644 --- a/test/characteristic_test.dart +++ b/test/characteristic_test.dart @@ -5,25 +5,26 @@ 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:flutter_test'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:mockito/annotations.dart'; +import './characteristic_test.mocks.dart'; -import 'mock/mocks.dart'; import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; -class ServiceMock extends Mock implements Service {} - +@GenerateMocks([Peripheral, ManagerForCharacteristic, ManagerForDescriptor, Service]) void main() { - Peripheral peripheral = PeripheralMock(); + Peripheral peripheral = MockPeripheral(); ManagerForCharacteristic managerForCharacteristic = - ManagerForCharacteristicMock(); + MockManagerForCharacteristic(); CharacteristicGenerator characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); DescriptorGenerator descriptorGenerator = - DescriptorGenerator(ManagerForDescriptorMock()); + DescriptorGenerator(MockManagerForDescriptor()); Characteristic characteristic = - characteristicGenerator.create(123, ServiceMock()); + characteristicGenerator.create(123, MockService()); DescriptorWithValue createDescriptor(int seed) => descriptorGenerator.create(seed, characteristic); @@ -92,7 +93,7 @@ void main() { //then verify( managerForCharacteristic.readCharacteristicForIdentifier( - any, characteristic, argThat(isNotNull)), + MockPeripheral(), characteristic, argThat(isNotNull)), ); }); diff --git a/test/characteristic_test.mocks.dart b/test/characteristic_test.mocks.dart new file mode 100644 index 00000000..2d1fc9f8 --- /dev/null +++ b/test/characteristic_test.mocks.dart @@ -0,0 +1,383 @@ +// Mocks generated by Mockito 5.0.3 from annotations +// in flutter_ble_lib/test/characteristic_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i4; +import 'dart:typed_data' as _i3; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i2; +import 'package:flutter_ble_lib/src/_internal.dart' as _i6; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i5; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeCharacteristicWithValue extends _i1.Fake + implements _i2.CharacteristicWithValue {} + +class _FakeCharacteristic extends _i1.Fake implements _i2.Characteristic {} + +class _FakeDescriptorWithValue extends _i1.Fake + implements _i2.DescriptorWithValue {} + +class _FakeDescriptor extends _i1.Fake implements _i2.Descriptor {} + +class _FakeUint8List extends _i1.Fake implements _i3.Uint8List {} + +class _FakePeripheral extends _i1.Fake implements _i2.Peripheral {} + +/// A class which mocks [Peripheral]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPeripheral extends _i1.Mock implements _i2.Peripheral { + MockPeripheral() { + _i1.throwOnMissingStub(this); + } + + @override + String get name => + (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); + @override + set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), + returnValueForMissingStub: null); + @override + String get identifier => + (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') + as String); + @override + set identifier(String? _identifier) => + super.noSuchMethod(Invocation.setter(#identifier, _identifier), + returnValueForMissingStub: null); + @override + _i4.Future connect( + {bool? isAutoConnect = false, + int? requestMtu = 0, + bool? refreshGatt = false, + Duration? timeout}) => + (super.noSuchMethod( + Invocation.method(#connect, [], { + #isAutoConnect: isAutoConnect, + #requestMtu: requestMtu, + #refreshGatt: refreshGatt, + #timeout: timeout + }), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i2.PeripheralConnectionState> observeConnectionState( + {bool? emitCurrentValue = false, + bool? completeOnDisconnect = false}) => + (super.noSuchMethod( + Invocation.method(#observeConnectionState, [], { + #emitCurrentValue: emitCurrentValue, + #completeOnDisconnect: completeOnDisconnect + }), + returnValue: Stream<_i2.PeripheralConnectionState>.empty()) + as _i4.Stream<_i2.PeripheralConnectionState>); + @override + _i4.Future isConnected() => + (super.noSuchMethod(Invocation.method(#isConnected, []), + returnValue: Future.value(false)) as _i4.Future); + @override + _i4.Future disconnectOrCancelConnection() => + (super.noSuchMethod(Invocation.method(#disconnectOrCancelConnection, []), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future discoverAllServicesAndCharacteristics( + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#discoverAllServicesAndCharacteristics, [], + {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future> services() => + (super.noSuchMethod(Invocation.method(#services, []), + returnValue: Future.value(<_i2.Service>[])) + as _i4.Future>); + @override + _i4.Future> characteristics(String? servicedUuid) => + (super.noSuchMethod(Invocation.method(#characteristics, [servicedUuid]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future rssi({String? transactionId}) => (super.noSuchMethod( + Invocation.method(#rssi, [], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future requestMtu(int? mtu, {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #requestMtu, [mtu], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeCharacteristic, + [serviceUuid, characteristicUuid, value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Future> descriptorsForCharacteristic( + String? serviceUuid, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, + [serviceUuid, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptor(String? serviceUuid, + String? characteristicUuid, String? descriptorUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptor( + String? serviceUuid, + String? characteristicUuid, + String? descriptorUuid, + _i3.Uint8List? value, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid, value], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #monitorCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); +} + +/// A class which mocks [ManagerForCharacteristic]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForCharacteristic extends _i1.Mock + implements _i5.ManagerForCharacteristic { + MockManagerForCharacteristic() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future writeCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Stream<_i3.Uint8List>.empty()) + as _i4.Stream<_i3.Uint8List>); + @override + _i4.Future> descriptorsForCharacteristic( + _i2.Characteristic? characteristic) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, [characteristic]), + returnValue: + Future.value(<_i2.Descriptor>[])) as _i4 + .Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForCharacteristic, + [characteristic, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + _i3.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForCharacteristic, + [characteristic, descriptorUuid, value, transactionId]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); +} + +/// A class which mocks [ManagerForDescriptor]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForDescriptor extends _i1.Mock + implements _i5.ManagerForDescriptor { + MockManagerForDescriptor() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( + _i2.Descriptor? descriptor, String? transactionId) => + (super.noSuchMethod( + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, + _i3.Uint8List? value, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); +} + +/// A class which mocks [Service]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockService extends _i1.Mock implements _i2.Service { + MockService() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Peripheral get peripheral => + (super.noSuchMethod(Invocation.getter(#peripheral), + returnValue: _FakePeripheral()) as _i2.Peripheral); + @override + set peripheral(_i2.Peripheral? _peripheral) => + super.noSuchMethod(Invocation.setter(#peripheral, _peripheral), + returnValueForMissingStub: null); + @override + String get uuid => + (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); + @override + set uuid(String? _uuid) => super.noSuchMethod(Invocation.setter(#uuid, _uuid), + returnValueForMissingStub: null); + @override + int get hashCode => + (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); + @override + _i4.Future> characteristics() => + (super.noSuchMethod(Invocation.method(#characteristics, []), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristic( + String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeCharacteristic, + [characteristicUuid, value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( + String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#readCharacteristic, [characteristicUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristic( + String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristic, [characteristicUuid], + {#transactionId: transactionId}), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + _i4.Future> descriptorsForCharacteristic( + String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method( + #descriptorsForCharacteristic, [characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptor( + String? characteristicUuid, String? descriptorUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readDescriptor, + [characteristicUuid, descriptorUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptor(String? characteristicUuid, + String? descriptorUuid, _i3.Uint8List? value, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeDescriptor, + [characteristicUuid, descriptorUuid, value], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); + @override + bool operator ==(Object? other) => + (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) + as bool); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); +} diff --git a/test/descriptor_test.dart b/test/descriptor_test.dart index a38de706..20352802 100644 --- a/test/descriptor_test.dart +++ b/test/descriptor_test.dart @@ -4,18 +4,19 @@ 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 'package:mockito/annotations.dart'; +import 'package:flutter_test/flutter_test.dart'; -import 'mock/mocks.dart'; import 'test_util/descriptor_generator.dart'; +@GenerateMocks([ManagerForDescriptor, Characteristic]) void main() { - ManagerForDescriptor managerForDescriptor = ManagerForDescriptorMock(); + ManagerForDescriptor managerForDescriptor = MockManagerForDescriptor(); DescriptorGenerator descriptorGenerator = DescriptorGenerator(managerForDescriptor); DescriptorWithValue createDescriptor(int seed) => - descriptorGenerator.create(seed, CharacteristicMock()); + descriptorGenerator.create(seed, MockCharacteristic()); Descriptor descriptor = createDescriptor(123); diff --git a/test/descriptor_test.mocks.dart b/test/descriptor_test.mocks.dart new file mode 100644 index 00000000..9809d530 --- /dev/null +++ b/test/descriptor_test.mocks.dart @@ -0,0 +1,168 @@ +// Mocks generated by Mockito 5.0.3 from annotations +// in flutter_ble_lib/test/descriptor_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i5; +import 'dart:typed_data' as _i2; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i3; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} + +class _FakeService extends _i1.Fake implements _i3.Service {} + +class _FakeDescriptorWithValue extends _i1.Fake + implements _i3.DescriptorWithValue {} + +class _FakeDescriptor extends _i1.Fake implements _i3.Descriptor {} + +/// A class which mocks [ManagerForDescriptor]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForDescriptor extends _i1.Mock + implements _i4.ManagerForDescriptor { + MockManagerForDescriptor() { + _i1.throwOnMissingStub(this); + } + + @override + _i5.Future<_i2.Uint8List> readDescriptorForIdentifier( + _i3.Descriptor? descriptor, String? transactionId) => + (super.noSuchMethod( + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i5.Future<_i2.Uint8List>); + @override + _i5.Future writeDescriptorForIdentifier(_i3.Descriptor? descriptor, + _i2.Uint8List? value, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i5.Future); +} + +/// A class which mocks [Characteristic]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCharacteristic extends _i1.Mock implements _i3.Characteristic { + MockCharacteristic() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Service get service => (super.noSuchMethod(Invocation.getter(#service), + returnValue: _FakeService()) as _i3.Service); + @override + set service(_i3.Service? _service) => + super.noSuchMethod(Invocation.setter(#service, _service), + returnValueForMissingStub: null); + @override + String get uuid => + (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); + @override + set uuid(String? _uuid) => super.noSuchMethod(Invocation.setter(#uuid, _uuid), + returnValueForMissingStub: null); + @override + bool get isReadable => + (super.noSuchMethod(Invocation.getter(#isReadable), returnValue: false) + as bool); + @override + set isReadable(bool? _isReadable) => + super.noSuchMethod(Invocation.setter(#isReadable, _isReadable), + returnValueForMissingStub: null); + @override + bool get isWritableWithResponse => + (super.noSuchMethod(Invocation.getter(#isWritableWithResponse), + returnValue: false) as bool); + @override + set isWritableWithResponse(bool? _isWritableWithResponse) => + super.noSuchMethod( + Invocation.setter(#isWritableWithResponse, _isWritableWithResponse), + returnValueForMissingStub: null); + @override + bool get isWritableWithoutResponse => + (super.noSuchMethod(Invocation.getter(#isWritableWithoutResponse), + returnValue: false) as bool); + @override + set isWritableWithoutResponse(bool? _isWritableWithoutResponse) => + super.noSuchMethod( + Invocation.setter( + #isWritableWithoutResponse, _isWritableWithoutResponse), + returnValueForMissingStub: null); + @override + bool get isNotifiable => + (super.noSuchMethod(Invocation.getter(#isNotifiable), returnValue: false) + as bool); + @override + set isNotifiable(bool? _isNotifiable) => + super.noSuchMethod(Invocation.setter(#isNotifiable, _isNotifiable), + returnValueForMissingStub: null); + @override + bool get isIndicatable => + (super.noSuchMethod(Invocation.getter(#isIndicatable), returnValue: false) + as bool); + @override + set isIndicatable(bool? _isIndicatable) => + super.noSuchMethod(Invocation.setter(#isIndicatable, _isIndicatable), + returnValueForMissingStub: null); + @override + int get hashCode => + (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); + @override + _i5.Future<_i2.Uint8List> read({String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#read, [], {#transactionId: transactionId}), + returnValue: Future.value(_FakeUint8List())) + as _i5.Future<_i2.Uint8List>); + @override + _i5.Future write(_i2.Uint8List? value, bool? withResponse, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #write, [value, withResponse], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i5.Future); + @override + _i5.Stream<_i2.Uint8List> monitor({String? transactionId}) => (super + .noSuchMethod( + Invocation.method(#monitor, [], {#transactionId: transactionId}), + returnValue: Stream<_i2.Uint8List>.empty()) + as _i5.Stream<_i2.Uint8List>); + @override + _i5.Future> descriptors() => + (super.noSuchMethod(Invocation.method(#descriptors, []), + returnValue: Future.value(<_i3.Descriptor>[])) + as _i5.Future>); + @override + _i5.Future<_i3.DescriptorWithValue> readDescriptor(String? descriptorUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#readDescriptor, [descriptorUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i5.Future<_i3.DescriptorWithValue>); + @override + _i5.Future<_i3.Descriptor> writeDescriptor( + String? descriptorUuid, _i2.Uint8List? value, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#writeDescriptor, [descriptorUuid, value], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptor())) + as _i5.Future<_i3.Descriptor>); + @override + bool operator ==(Object? other) => + (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) + as bool); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); +} diff --git a/test/mock/mocks.dart b/test/mock/mocks.dart index 0bfb4388..d985738b 100644 --- a/test/mock/mocks.dart +++ b/test/mock/mocks.dart @@ -2,7 +2,6 @@ import 'package:flutter_ble_lib/flutter_ble_lib.dart'; 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 {} diff --git a/test/service_test.dart b/test/service_test.dart index 4bbf0fa7..a54d3ff2 100644 --- a/test/service_test.dart +++ b/test/service_test.dart @@ -4,18 +4,20 @@ 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 'package:mockito/annotations.dart'; +import 'package:flutter_test/flutter_test.dart'; -import 'mock/mocks.dart'; +import './service_test.mocks.dart'; import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; +@GenerateMocks([Peripheral, ManagerForService, ManagerForCharacteristic, ManagerForDescriptor]) void main() { - Peripheral peripheral = PeripheralMock(); - ManagerForService managerForService = ManagerForServiceMock(); + Peripheral peripheral = MockPeripheral(); + ManagerForService managerForService = MockManagerForService(); ManagerForCharacteristic managerForCharacteristic = - ManagerForCharacteristicMock(); - ManagerForDescriptor managerForDescriptor = ManagerForDescriptorMock(); + MockManagerForCharacteristic(); + ManagerForDescriptor managerForDescriptor = MockManagerForDescriptor(); CharacteristicGenerator characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); DescriptorGenerator descriptorGenerator = diff --git a/test/service_test.mocks.dart b/test/service_test.mocks.dart new file mode 100644 index 00000000..04a47141 --- /dev/null +++ b/test/service_test.mocks.dart @@ -0,0 +1,376 @@ +// Mocks generated by Mockito 5.0.3 from annotations +// in flutter_ble_lib/test/service_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i4; +import 'dart:typed_data' as _i3; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i2; +import 'package:flutter_ble_lib/src/_internal.dart' as _i6; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i5; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeCharacteristicWithValue extends _i1.Fake + implements _i2.CharacteristicWithValue {} + +class _FakeCharacteristic extends _i1.Fake implements _i2.Characteristic {} + +class _FakeDescriptorWithValue extends _i1.Fake + implements _i2.DescriptorWithValue {} + +class _FakeDescriptor extends _i1.Fake implements _i2.Descriptor {} + +class _FakeUint8List extends _i1.Fake implements _i3.Uint8List {} + +/// A class which mocks [Peripheral]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPeripheral extends _i1.Mock implements _i2.Peripheral { + MockPeripheral() { + _i1.throwOnMissingStub(this); + } + + @override + String get name => + (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); + @override + set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), + returnValueForMissingStub: null); + @override + String get identifier => + (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') + as String); + @override + set identifier(String? _identifier) => + super.noSuchMethod(Invocation.setter(#identifier, _identifier), + returnValueForMissingStub: null); + @override + _i4.Future connect( + {bool? isAutoConnect = false, + int? requestMtu = 0, + bool? refreshGatt = false, + Duration? timeout}) => + (super.noSuchMethod( + Invocation.method(#connect, [], { + #isAutoConnect: isAutoConnect, + #requestMtu: requestMtu, + #refreshGatt: refreshGatt, + #timeout: timeout + }), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i2.PeripheralConnectionState> observeConnectionState( + {bool? emitCurrentValue = false, + bool? completeOnDisconnect = false}) => + (super.noSuchMethod( + Invocation.method(#observeConnectionState, [], { + #emitCurrentValue: emitCurrentValue, + #completeOnDisconnect: completeOnDisconnect + }), + returnValue: Stream<_i2.PeripheralConnectionState>.empty()) + as _i4.Stream<_i2.PeripheralConnectionState>); + @override + _i4.Future isConnected() => + (super.noSuchMethod(Invocation.method(#isConnected, []), + returnValue: Future.value(false)) as _i4.Future); + @override + _i4.Future disconnectOrCancelConnection() => + (super.noSuchMethod(Invocation.method(#disconnectOrCancelConnection, []), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future discoverAllServicesAndCharacteristics( + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#discoverAllServicesAndCharacteristics, [], + {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future> services() => + (super.noSuchMethod(Invocation.method(#services, []), + returnValue: Future.value(<_i2.Service>[])) + as _i4.Future>); + @override + _i4.Future> characteristics(String? servicedUuid) => + (super.noSuchMethod(Invocation.method(#characteristics, [servicedUuid]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future rssi({String? transactionId}) => (super.noSuchMethod( + Invocation.method(#rssi, [], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future requestMtu(int? mtu, {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #requestMtu, [mtu], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeCharacteristic, + [serviceUuid, characteristicUuid, value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Future> descriptorsForCharacteristic( + String? serviceUuid, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, + [serviceUuid, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptor(String? serviceUuid, + String? characteristicUuid, String? descriptorUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptor( + String? serviceUuid, + String? characteristicUuid, + String? descriptorUuid, + _i3.Uint8List? value, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid, value], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #monitorCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); +} + +/// A class which mocks [ManagerForService]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { + MockManagerForService() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future> characteristicsForService( + _i2.Service? service) => + (super.noSuchMethod( + Invocation.method(#characteristicsForService, [service]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForService, + [peripheral, service, characteristicUuid, transactionId]), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForService, [ + peripheral, + service, + characteristicUuid, + value, + withResponse, + transactionId + ]), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForService, + [peripheral, service, characteristicUuid, transactionId]), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + _i4.Future> descriptorsForService( + _i2.Service? service, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method( + #descriptorsForService, [service, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForService( + _i2.Service? service, + String? characteristicUuid, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForService, + [service, characteristicUuid, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForService( + _i2.Service? service, + String? characteristicUuid, + String? descriptorUuid, + _i3.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForService, [ + service, + characteristicUuid, + descriptorUuid, + value, + transactionId + ]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); +} + +/// A class which mocks [ManagerForCharacteristic]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForCharacteristic extends _i1.Mock + implements _i5.ManagerForCharacteristic { + MockManagerForCharacteristic() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future writeCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Stream<_i3.Uint8List>.empty()) + as _i4.Stream<_i3.Uint8List>); + @override + _i4.Future> descriptorsForCharacteristic( + _i2.Characteristic? characteristic) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, [characteristic]), + returnValue: + Future.value(<_i2.Descriptor>[])) as _i4 + .Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForCharacteristic, + [characteristic, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + _i3.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForCharacteristic, + [characteristic, descriptorUuid, value, transactionId]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); +} + +/// A class which mocks [ManagerForDescriptor]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForDescriptor extends _i1.Mock + implements _i5.ManagerForDescriptor { + MockManagerForDescriptor() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( + _i2.Descriptor? descriptor, String? transactionId) => + (super.noSuchMethod( + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, + _i3.Uint8List? value, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); +} diff --git a/test/src/bridge/lib_core_test.dart b/test/src/bridge/lib_core_test.dart index 15e9bd93..de089225 100644 --- a/test/src/bridge/lib_core_test.dart +++ b/test/src/bridge/lib_core_test.dart @@ -7,69 +7,72 @@ import 'package:flutter/services.dart'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'package:flutter_ble_lib/src/_internal.dart'; import 'package:flutter_ble_lib/src/_constants.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; +import './lib_core_test.mocks.dart'; import '../../json/ble_error_jsons.dart'; -import '../../mock/mocks.dart'; const flutterBleLibMethodChannelName = 'flutter_ble_lib'; const monitorCharacteristicEventChannelName = flutterBleLibMethodChannelName + '/monitorCharacteristic'; +@GenerateMocks([Peripheral, ManagerForService, ManagerForCharacteristic]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); - FlutterBleLib bleLib; - Peripheral peripheral = PeripheralMock(); + late FlutterBleLib bleLib; + Peripheral peripheral = MockPeripheral(); MethodChannel methodChannel = MethodChannel(flutterBleLibMethodChannelName); MethodChannel eventMethodChannel = MethodChannel(monitorCharacteristicEventChannelName); setUp(() { - bleLib = FlutterBleLib(); + bleLib = FlutterBleLib(InternalBleManager()); when(peripheral.identifier).thenReturn("4B:99:4C:34:DE:77"); methodChannel.setMockMethodCallHandler((call) => Future.value("")); eventMethodChannel.setMockMethodCallHandler((call) => Future.value("")); }); Future emitPlatformError(String errorJson) => - ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( monitorCharacteristicEventChannelName, const StandardMethodCodec() .encodeErrorEnvelope(code: "irrelevant", details: errorJson), - (ByteData data) {}); + (data) {}); Future emitMonitoringEvent(String eventJson) => - ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( monitorCharacteristicEventChannelName, const StandardMethodCodec().encodeSuccessEnvelope(eventJson), - (ByteData data) {}); + (data) {}); Future emitStreamCompletion() => - ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( monitorCharacteristicEventChannelName, null, - (ByteData data) {}, + (data) {}, ); CharacteristicWithValueAndTransactionId createCharacteristicFromDecodedJson( - Map decodedRoot) { - Map decodedCharacteristic = decodedRoot["characteristic"]; + Map decodedRoot) { + Map decodedCharacteristic = decodedRoot["characteristic"]; String transactionId = decodedRoot["transactionId"]; return CharacteristicWithValueAndTransactionId.fromJson( decodedCharacteristic, - Service.fromJson(decodedRoot, peripheral, null), - null, + Service.fromJson(decodedRoot, peripheral, MockManagerForService()), + MockManagerForCharacteristic(), ).setTransactionId(transactionId); } - Map createRawCharacteristic( - {int id, - int serviceId, - String serviceUuid, - String characteristicUuid, - String transactionId, - String base64value}) => + Map createRawCharacteristic( + {int? id, + int? serviceId, + String? serviceUuid, + String? characteristicUuid, + String? transactionId, + String? base64value}) => { "serviceUuid": serviceUuid, "serviceId": serviceId, @@ -87,19 +90,22 @@ void main() { }; test('monitorCharacteristicForIdentifier cancels on stream error', () async { - expectLater( - bleLib.monitorCharacteristicForIdentifier(peripheral, 123, null), - emitsInOrder([ - emitsError(isInstanceOf()), - emitsDone, - ])); + final fut = expectLater( + bleLib.monitorCharacteristicForIdentifier(peripheral, 123, "asdasd"), + emitsInOrder([ + emitsError(isInstanceOf()), + emitsDone, + ]) + ); await emitPlatformError(cancellationErrorJson); + await fut; }); test('monitorCharacteristicForDevice cancels on stream error', () async { + String nullStr = ""; expectLater( bleLib.monitorCharacteristicForDevice( - peripheral, "serviceUuid", "characteristicUuid", null), + peripheral, "serviceUuid", "characteristicUuid", nullStr), emitsInOrder([ emitsError(isInstanceOf()), emitsDone, @@ -108,9 +114,10 @@ void main() { }); test('monitorCharacteristicForService cancels on stream error', () async { + String nullStr = ""; expectLater( bleLib.monitorCharacteristicForService( - peripheral, 123, "characteristicUuid", null), + peripheral, 123, "characteristicUuid", nullStr), emitsInOrder([ emitsError(isInstanceOf()), emitsDone, @@ -143,16 +150,27 @@ void main() { 'monitorCharacteristicForDevice streams events with matching characteristic uuid, service uuid and transaction id', () async { expectLater( - bleLib.monitorCharacteristicForDevice( - peripheral, "serviceUuid", "characteristicUuid", "1"), - emitsInOrder([ - emits(equals(createCharacteristicFromDecodedJson( + bleLib.monitorCharacteristicForDevice( + peripheral, + "serviceUuid", + "characteristicUuid", + "1" + ), + emitsInOrder([ + emits( + equals( + createCharacteristicFromDecodedJson( createRawCharacteristic( - serviceUuid: "serviceUuid", - characteristicUuid: "characteristicUuid", - transactionId: "1")))), - emitsDone - ])); + serviceUuid: "serviceUuid", + characteristicUuid: "characteristicUuid", + transactionId: "1" + ) + ) + ) + ), + emitsDone + ]) + ); await emitMonitoringEvent(jsonEncode(createRawCharacteristic( serviceUuid: "serviceUuid", diff --git a/test/src/bridge/lib_core_test.mocks.dart b/test/src/bridge/lib_core_test.mocks.dart new file mode 100644 index 00000000..12eedc66 --- /dev/null +++ b/test/src/bridge/lib_core_test.mocks.dart @@ -0,0 +1,349 @@ +// Mocks generated by Mockito 5.0.3 from annotations +// in flutter_ble_lib/test/src/bridge/lib_core_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i4; +import 'dart:typed_data' as _i3; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i2; +import 'package:flutter_ble_lib/src/_internal.dart' as _i6; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i5; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeCharacteristicWithValue extends _i1.Fake + implements _i2.CharacteristicWithValue {} + +class _FakeCharacteristic extends _i1.Fake implements _i2.Characteristic {} + +class _FakeDescriptorWithValue extends _i1.Fake + implements _i2.DescriptorWithValue {} + +class _FakeDescriptor extends _i1.Fake implements _i2.Descriptor {} + +class _FakeUint8List extends _i1.Fake implements _i3.Uint8List {} + +/// A class which mocks [Peripheral]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPeripheral extends _i1.Mock implements _i2.Peripheral { + MockPeripheral() { + _i1.throwOnMissingStub(this); + } + + @override + String get name => + (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); + @override + set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), + returnValueForMissingStub: null); + @override + String get identifier => + (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') + as String); + @override + set identifier(String? _identifier) => + super.noSuchMethod(Invocation.setter(#identifier, _identifier), + returnValueForMissingStub: null); + @override + _i4.Future connect( + {bool? isAutoConnect = false, + int? requestMtu = 0, + bool? refreshGatt = false, + Duration? timeout}) => + (super.noSuchMethod( + Invocation.method(#connect, [], { + #isAutoConnect: isAutoConnect, + #requestMtu: requestMtu, + #refreshGatt: refreshGatt, + #timeout: timeout + }), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i2.PeripheralConnectionState> observeConnectionState( + {bool? emitCurrentValue = false, + bool? completeOnDisconnect = false}) => + (super.noSuchMethod( + Invocation.method(#observeConnectionState, [], { + #emitCurrentValue: emitCurrentValue, + #completeOnDisconnect: completeOnDisconnect + }), + returnValue: Stream<_i2.PeripheralConnectionState>.empty()) + as _i4.Stream<_i2.PeripheralConnectionState>); + @override + _i4.Future isConnected() => + (super.noSuchMethod(Invocation.method(#isConnected, []), + returnValue: Future.value(false)) as _i4.Future); + @override + _i4.Future disconnectOrCancelConnection() => + (super.noSuchMethod(Invocation.method(#disconnectOrCancelConnection, []), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future discoverAllServicesAndCharacteristics( + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method(#discoverAllServicesAndCharacteristics, [], + {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future> services() => + (super.noSuchMethod(Invocation.method(#services, []), + returnValue: Future.value(<_i2.Service>[])) + as _i4.Future>); + @override + _i4.Future> characteristics(String? servicedUuid) => + (super.noSuchMethod(Invocation.method(#characteristics, [servicedUuid]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future rssi({String? transactionId}) => (super.noSuchMethod( + Invocation.method(#rssi, [], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future requestMtu(int? mtu, {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #requestMtu, [mtu], {#transactionId: transactionId}), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeCharacteristic, + [serviceUuid, characteristicUuid, value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Future> descriptorsForCharacteristic( + String? serviceUuid, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, + [serviceUuid, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptor(String? serviceUuid, + String? characteristicUuid, String? descriptorUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #readDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptor( + String? serviceUuid, + String? characteristicUuid, + String? descriptorUuid, + _i3.Uint8List? value, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #writeDescriptor, + [serviceUuid, characteristicUuid, descriptorUuid, value], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristic( + String? serviceUuid, String? characteristicUuid, + {String? transactionId}) => + (super.noSuchMethod( + Invocation.method( + #monitorCharacteristic, + [serviceUuid, characteristicUuid], + {#transactionId: transactionId}), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); +} + +/// A class which mocks [ManagerForService]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { + MockManagerForService() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future> characteristicsForService( + _i2.Service? service) => + (super.noSuchMethod( + Invocation.method(#characteristicsForService, [service]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForService, + [peripheral, service, characteristicUuid, transactionId]), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override + _i4.Future<_i2.Characteristic> writeCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForService, [ + peripheral, + service, + characteristicUuid, + value, + withResponse, + transactionId + ]), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForService( + _i2.Peripheral? peripheral, + _i6.InternalService? service, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForService, + [peripheral, service, characteristicUuid, transactionId]), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override + _i4.Future> descriptorsForService( + _i2.Service? service, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method( + #descriptorsForService, [service, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForService( + _i2.Service? service, + String? characteristicUuid, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForService, + [service, characteristicUuid, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForService( + _i2.Service? service, + String? characteristicUuid, + String? descriptorUuid, + _i3.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForService, [ + service, + characteristicUuid, + descriptorUuid, + value, + transactionId + ]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); +} + +/// A class which mocks [ManagerForCharacteristic]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForCharacteristic extends _i1.Mock + implements _i5.ManagerForCharacteristic { + MockManagerForCharacteristic() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future writeCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Stream<_i3.Uint8List>.empty()) + as _i4.Stream<_i3.Uint8List>); + @override + _i4.Future> descriptorsForCharacteristic( + _i2.Characteristic? characteristic) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, [characteristic]), + returnValue: + Future.value(<_i2.Descriptor>[])) as _i4 + .Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForCharacteristic, + [characteristic, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( + _i2.Characteristic? characteristic, + String? descriptorUuid, + _i3.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForCharacteristic, + [characteristic, descriptorUuid, value, transactionId]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); +} diff --git a/test/test_util/characteristic_generator.dart b/test/test_util/characteristic_generator.dart index 6b979c6b..c505884f 100644 --- a/test/test_util/characteristic_generator.dart +++ b/test/test_util/characteristic_generator.dart @@ -8,7 +8,7 @@ class CharacteristicGenerator { CharacteristicGenerator(this.managerForCharacteristic); - Map _createRawCharacteristic(int seed) => { + Map _createRawCharacteristic(int seed) => { "characteristicUuid": seed.toString(), "id": seed, "isReadable": seed % 2 == 0, diff --git a/test/test_util/descriptor_generator.dart b/test/test_util/descriptor_generator.dart index f836854c..6616fdb6 100644 --- a/test/test_util/descriptor_generator.dart +++ b/test/test_util/descriptor_generator.dart @@ -8,7 +8,7 @@ class DescriptorGenerator { DescriptorGenerator(this.managerForDescriptor); - Map _createRawDescriptor(int seed) => { + Map _createRawDescriptor(int seed) => { "descriptorId": seed, "descriptorUuid": seed.toString(), "value": base64Encode([seed]) From 44cb104dabae0104aed9ec6efdf466a4ce32842c Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 1 Apr 2021 09:47:11 +0200 Subject: [PATCH 08/33] Java: added some null checks to make the calls to stop and destroy reentrant --- .../polidea/flutter_ble_lib/FlutterBleLibPlugin.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/polidea/flutter_ble_lib/FlutterBleLibPlugin.java b/android/src/main/java/com/polidea/flutter_ble_lib/FlutterBleLibPlugin.java index e2007224..f23de145 100644 --- a/android/src/main/java/com/polidea/flutter_ble_lib/FlutterBleLibPlugin.java +++ b/android/src/main/java/com/polidea/flutter_ble_lib/FlutterBleLibPlugin.java @@ -139,7 +139,9 @@ public void onEvent(Integer restoreStateIdentifier) { } private void destroyClient(Result result) { - bleAdapter.destroyClient(); + if (bleAdapter != null) { + bleAdapter.destroyClient(); + } scanningStreamHandler.onComplete(); connectionStateStreamHandler.onComplete(); bleAdapter = null; @@ -167,13 +169,17 @@ public void onError(BleError error) { } private void stopDeviceScan(Result result) { - bleAdapter.stopDeviceScan(); + if (bleAdapter != null) { + bleAdapter.stopDeviceScan(); + } scanningStreamHandler.onComplete(); result.success(null); } private void cancelTransaction(MethodCall call, Result result) { - bleAdapter.cancelTransaction(call.argument(ArgumentKey.TRANSACTION_ID)); + if (bleAdapter != null) { + bleAdapter.cancelTransaction(call.argument(ArgumentKey.TRANSACTION_ID)); + } result.success(null); } } From 67f1b5a6d4a9a1416b1780de02dd495ea2514ba1 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 1 Apr 2021 09:54:43 +0200 Subject: [PATCH 09/33] Example:: additional cleanup and refactor Lib:: enchanced error handling, refined nullability on certain types --- .../device_details/device_details_bloc.dart | 151 +++++++----------- example/lib/devices_list/devices_bloc.dart | 12 +- example/lib/model/ble_device.dart | 4 +- lib/peripheral.dart | 2 +- lib/scan_result.dart | 51 ++++-- lib/src/bridge/device_connection_mixin.dart | 11 +- 6 files changed, 108 insertions(+), 123 deletions(-) diff --git a/example/lib/device_details/device_details_bloc.dart b/example/lib/device_details/device_details_bloc.dart index 280fb4d4..d4a363c9 100644 --- a/example/lib/device_details/device_details_bloc.dart +++ b/example/lib/device_details/device_details_bloc.dart @@ -91,159 +91,122 @@ class DeviceDetailsBloc { void readRssi() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .testReadingRssi(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .testReadingRssi(); } void discovery() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .discovery(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .discovery(); } void fetchConnectedDevices() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .fetchConnectedDevice(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .fetchConnectedDevice(); } void fetchKnownDevices() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .fetchKnownDevice(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .fetchKnownDevice(); } void readCharacteristicForPeripheral() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .readCharacteristicForPeripheral(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .readCharacteristicForPeripheral(); } void readCharacteristicForService() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .readCharacteristicForService(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .readCharacteristicForService(); } void readCharacteristicDirectly() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .readCharacteristic(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .readCharacteristic(); } void writeCharacteristicForPeripheral() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .writeCharacteristicForPeripheral(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .writeCharacteristicForPeripheral(); } void writeCharacteristicForService() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .writeCharacteristicForService(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .writeCharacteristicForService(); } void writeCharacteristicDirectly() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .writeCharacteristic(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .writeCharacteristic(); } void monitorCharacteristicForPeripheral() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) .monitorCharacteristicForPeripheral(); - // }); } void monitorCharacteristicForService() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .monitorCharacteristicForService(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .monitorCharacteristicForService(); } void monitorCharacteristicDirectly() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .monitorCharacteristic(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .monitorCharacteristic(); } void disableBluetooth() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .disableBluetooth(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .disableBluetooth(); } void enableBluetooth() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .enableBluetooth(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .enableBluetooth(); } void fetchBluetoothState() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) - .fetchBluetoothState(); - // }); + PeripheralTestOperations(_bleManager, _bleDevice.peripheral, log, logError) + .fetchBluetoothState(); } Future connect() async { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) async { - var peripheral = _bleDevice.peripheral; - - peripheral - .observeConnectionState( - emitCurrentValue: true, completeOnDisconnect: true) - .listen((connectionState) { - log('Observed new connection state: \n$connectionState'); - _connectionStateController.add(connectionState); - }); - - try { - log("Connecting to ${peripheral.name}"); - await peripheral.connect(); - log("Connected!"); - } on BleError catch (e) { - logError(e.toString()); - } - // }); + var peripheral = _bleDevice.peripheral; + + peripheral + .observeConnectionState( + emitCurrentValue: true, completeOnDisconnect: true) + .listen((connectionState) { + log('Observed new connection state: \n$connectionState'); + _connectionStateController.add(connectionState); + }); + + try { + log("Connecting to ${peripheral.name}"); + await peripheral.connect(); + log("Connected!"); + } on BleError catch (e) { + logError(e.toString()); + } } void dispose() async { - // await _bleDevice.drain(); - // _bleDevice.close(); - await _connectionStateController.drain(); _connectionStateController.close(); } @@ -276,17 +239,15 @@ class DeviceDetailsBloc { void startAutoTest() { _clearLogs(); - // _bleDevice.stream.listen((bleDevice) { - Fimber.d("got bleDevice: $_bleDevice"); - _bleDevice.peripheral.isConnected().then((isConnected) { - Fimber.d('The device is connected: $isConnected'); - if (!isConnected) { - _connectTo(_bleDevice); - } - }).catchError((error) { - logError('Connection problem: ${error.toString()}'); - }); - // }); + Fimber.d("got bleDevice: $_bleDevice"); + _bleDevice.peripheral.isConnected().then((isConnected) { + Fimber.d('The device is connected: $isConnected'); + if (!isConnected) { + _connectTo(_bleDevice); + } + }).catchError((error) { + logError('Connection problem: ${error.toString()}'); + }); } void _clearLogs() { diff --git a/example/lib/devices_list/devices_bloc.dart b/example/lib/devices_list/devices_bloc.dart index aab41edf..89ca2d04 100644 --- a/example/lib/devices_list/devices_bloc.dart +++ b/example/lib/devices_list/devices_bloc.dart @@ -33,9 +33,7 @@ class DevicesBloc { BleManager? bleManager }) : _deviceRepository = deviceRepository ?? DeviceRepository(), - _bleManager = bleManager ?? BleManager() { - - } + _bleManager = bleManager ?? BleManager(); bool clientCreated = false; @@ -49,7 +47,7 @@ class DevicesBloc { _visibleDevicesController.close(); _devicePickerController.close(); _scanSubscription?.cancel(); - _bleManager.destroyClient(); + // _bleManager.destroyClient(); } void init() { @@ -103,7 +101,11 @@ class DevicesBloc { Future _checkPermissions() async { if (Platform.isAndroid) { - if (await Permission.location.isGranted) { + var locGranted = await Permission.location.isGranted; + if (locGranted == false) { + locGranted = (await Permission.location.request()).isGranted; + } + if (locGranted == false) { return Future.error(Exception("Location permission not granted")); } } diff --git a/example/lib/model/ble_device.dart b/example/lib/model/ble_device.dart index eb8c1d7a..c97e068b 100644 --- a/example/lib/model/ble_device.dart +++ b/example/lib/model/ble_device.dart @@ -19,8 +19,6 @@ class BleDevice { @override bool operator ==(other) => other is BleDevice && - this.name != null && - other.name != null && compareAsciiLowerCase(this.name, other.name) == 0 && this.id == other.id; @@ -39,7 +37,7 @@ extension on ScanResult { DeviceCategory get category { if (name == "SensorTag") { return DeviceCategory.sensorTag; - } else if (name != null && name.startsWith("Hex")) { + } else if (name.startsWith("Hex")) { return DeviceCategory.hex; } else { return DeviceCategory.other; diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 49c249ee..0d1134e0 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -17,7 +17,7 @@ class Peripheral { static const int NO_MTU_NEGOTIATION = 0; final ManagerForPeripheral _manager; - String name; + String? name; String identifier; Peripheral.fromJson(Map json, ManagerForPeripheral manager) diff --git a/lib/scan_result.dart b/lib/scan_result.dart index 9d175d1b..1840974f 100644 --- a/lib/scan_result.dart +++ b/lib/scan_result.dart @@ -14,26 +14,43 @@ abstract class _ScanResultMetadata { /// A scan result emitted by the scanning operation, containing [Peripheral] and [AdvertisementData]. class ScanResult { - Peripheral peripheral; + final Peripheral peripheral; /// Signal strength of the peripheral in dBm. - int rssi; + final int rssi; /// An indicator whether the peripheral is connectable (iOS only). - bool isConnectable; + late final bool isConnectable; /// A list of UUIDs found in the overflow area of the advertisement data (iOS only). - List overflowServiceUuids; + late final List overflowServiceUuids; /// A packet of data advertised by the peripheral. - AdvertisementData advertisementData; - - ScanResult.fromJson(Map json, ManagerForPeripheral manager) - : peripheral = Peripheral.fromJson(json, manager), - rssi = json[_ScanResultMetadata.rssi], - isConnectable = json[_ScanResultMetadata.isConnectable], - overflowServiceUuids = json[_ScanResultMetadata.overflowServiceUuids], - advertisementData = AdvertisementData._fromJson(json); + final AdvertisementData advertisementData; + + ScanResult._( + this.peripheral, + this.rssi, + this.advertisementData, + {bool? isConnectable, + List? overflowServiceUuids, + }) : isConnectable = isConnectable ?? false, + overflowServiceUuids = overflowServiceUuids ?? []; + + + factory ScanResult.fromJson( + Map json, + ManagerForPeripheral manager + ) { + assert(json[_ScanResultMetadata.rssi] is int); + return ScanResult._( + Peripheral.fromJson(json, manager), + json[_ScanResultMetadata.rssi], + AdvertisementData._fromJson(json), + isConnectable: json[_ScanResultMetadata.isConnectable], + overflowServiceUuids: json[_ScanResultMetadata.overflowServiceUuids] + ); + } } /// Data advertised by the [Peripheral]: power level, local name, @@ -50,10 +67,10 @@ class AdvertisementData { /// The local name of the [Peripheral]. Might be different than /// [Peripheral.name]. - String localName; + String? localName; /// The transmit power of the peripheral. - int txPowerLevel; + int? txPowerLevel; /// A list of solicited service UUIDs. List? solicitedServiceUuids; @@ -67,8 +84,10 @@ class AdvertisementData { _mapToListOfStringsOrNull(json[_ScanResultMetadata.serviceUuids]), localName = json[_ScanResultMetadata.localName], txPowerLevel = json[_ScanResultMetadata.txPowerLevel], - solicitedServiceUuids = _mapToListOfStringsOrNull( - json[_ScanResultMetadata.solicitedServiceUuids]); + solicitedServiceUuids = + _mapToListOfStringsOrNull( + json[_ScanResultMetadata.solicitedServiceUuids] + ); static Map? _getServiceDataOrNull( Map? serviceData) { diff --git a/lib/src/bridge/device_connection_mixin.dart b/lib/src/bridge/device_connection_mixin.dart index b2629c79..b1eadd99 100644 --- a/lib/src/bridge/device_connection_mixin.dart +++ b/lib/src/bridge/device_connection_mixin.dart @@ -81,9 +81,14 @@ mixin DeviceConnectionMixin on FlutterBLE { .invokeMethod(MethodName.isDeviceConnected, { ArgumentName.deviceIdentifier: peripheralIdentifier, }).catchError( - (errorJson) => Future.error( - BleError.fromJson(jsonDecode(errorJson.details)), - ), + (errorJson) { + if (errorJson is MissingPluginException) { + return Future.error(errorJson); + } + return Future.error( + BleError.fromJson(jsonDecode(errorJson.details)) + ); + } ); } From a3277e75b49f3818e3639d71d5c5fb9120c0ad0b Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 5 Apr 2021 14:12:01 +0200 Subject: [PATCH 10/33] TestFix:: the injected manager instance is not part of the Characteristic POD so should be ignored when checking for equallity --- lib/characteristic.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/characteristic.dart b/lib/characteristic.dart index c2369c17..4740cd22 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -131,7 +131,6 @@ class Characteristic extends InternalCharacteristic { other is Characteristic && runtimeType == other.runtimeType && service == other.service && - _manager == other._manager && uuid == other.uuid && isReadable == other.isReadable && isWritableWithResponse == other.isWritableWithResponse && From ae7d4dcf2a529985c6afffdce967cb0ea330f929 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 5 Apr 2021 14:13:12 +0200 Subject: [PATCH 11/33] ble_error seem to have rather nullable fields --- lib/error/ble_error.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/error/ble_error.dart b/lib/error/ble_error.dart index 1124ce40..0556dede 100644 --- a/lib/error/ble_error.dart +++ b/lib/error/ble_error.dart @@ -15,16 +15,16 @@ abstract class _BleErrorMetadata { class BleError { BleErrorCode errorCode; - int attErrorCode; - int iosErrorCode; - int androidErrorCode; + int? attErrorCode; + int? iosErrorCode; + int? androidErrorCode; String reason; - String deviceID; - String serviceUuid; - String characteristicUuid; - String descriptorUuid; - String internalMessage; + String? deviceID; + String? serviceUuid; + String? characteristicUuid; + String? descriptorUuid; + String? internalMessage; BleError.fromJson(Map json) : errorCode = BleErrorCode(json[_BleErrorMetadata.errorCode]), From 8b1175be27220d01ed83cb2a95cdf7d57149a15a Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 5 Apr 2021 14:14:52 +0200 Subject: [PATCH 12/33] TestFix: little refactor on characteristic_mixin regarding clearity and type annotations --- lib/src/bridge/characteristics_mixin.dart | 49 +++++++++++++++-------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index ff1e9528..df9cdd2f 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -155,11 +155,17 @@ mixin CharacteristicsMixin on FlutterBLE { }, ); - bool Function(CharacteristicWithValueAndTransactionId) - characteristicFilter = (characteristic) => - characteristic._id == characteristicIdentifier && - equalsIgnoreAsciiCase( - transactionId, characteristic._transactionId ?? ""); + bool characteristicFilter( + CharacteristicWithValueAndTransactionId characteristic, + ) { + if (characteristic._id != characteristicIdentifier) { + return false; + } + return equalsIgnoreAsciiCase( + transactionId, + characteristic._transactionId ?? "", + ); + }; return _createMonitoringStream( startMonitoring, @@ -169,7 +175,7 @@ mixin CharacteristicsMixin on FlutterBLE { ).map((characteristicWithValue) => characteristicWithValue.value); } - Stream monitorCharacteristicForDevice( + Stream monitorCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -230,13 +236,14 @@ mixin CharacteristicsMixin on FlutterBLE { ); } - Stream _createMonitoringStream( + Stream _createMonitoringStream( void Function() onListen, bool Function(CharacteristicWithValueAndTransactionId) filter, Peripheral peripheral, String transactionId, ) { - Stream stream = _characteristicsMonitoringEvents + Stream stream = + _characteristicsMonitoringEvents .map( (rawJsonValue) => _parseCharacteristicWithValueWithTransactionIdResponse( @@ -245,9 +252,11 @@ mixin CharacteristicsMixin on FlutterBLE { .where(filter) .handleError((errorJson) => _throwErrorIfMatchesWithTransactionId(errorJson, transactionId)) - .transform(CancelOnErrorStreamTransformer()); + .transform( + CancelOnErrorStreamTransformer() + ); - StreamController streamController = + StreamController streamController = StreamController.broadcast( onListen: onListen, onCancel: () => cancelTransaction(transactionId), @@ -262,8 +271,12 @@ mixin CharacteristicsMixin on FlutterBLE { CharacteristicWithValueAndTransactionId _parseCharacteristicWithValueWithTransactionIdResponse( - Peripheral peripheral, rawJsonValue) { - Map rootObject = jsonDecode(rawJsonValue); + Peripheral peripheral, dynamic? rawJsonValue) { + var jsonString = ""; + if (rawJsonValue is String) { + jsonString = rawJsonValue; + } + Map rootObject = jsonDecode(jsonString); Service service = Service.fromJson(rootObject, peripheral, _manager); var transactionId = rootObject["transactionId"]; @@ -281,13 +294,15 @@ mixin CharacteristicsMixin on FlutterBLE { rootObject["characteristic"], service, _manager); } - void _throwErrorIfMatchesWithTransactionId(errorJson, transactionId) { - var errorDetails = jsonDecode(errorJson.details); - if (transactionId == errorDetails["transactionId"]) { - throw BleError.fromJson(errorDetails); - } else { + void _throwErrorIfMatchesWithTransactionId(PlatformException errorJson, String transactionId) { + if (errorJson is PlatformException == false) { + return; + } + final errorDetails = jsonDecode(errorJson.details); + if (transactionId != errorDetails["transactionId"]) { return; } + throw BleError.fromJson(errorDetails); } } From b58f8a0ae13d53be29d0155966fefec5810037f5 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 5 Apr 2021 14:16:01 +0200 Subject: [PATCH 13/33] TestFix:: lib_core_test:: tests now passing --- test/characteristic_test.mocks.dart | 6 - test/json/ble_error_jsons.dart | 5 +- test/service_test.mocks.dart | 6 - test/src/bridge/lib_core_test.dart | 325 ++++++++++++------ test/src/bridge/lib_core_test.mocks.dart | 411 ++++++++++++++++++----- 5 files changed, 564 insertions(+), 189 deletions(-) diff --git a/test/characteristic_test.mocks.dart b/test/characteristic_test.mocks.dart index 2d1fc9f8..f747299c 100644 --- a/test/characteristic_test.mocks.dart +++ b/test/characteristic_test.mocks.dart @@ -35,12 +35,6 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { _i1.throwOnMissingStub(this); } - @override - String get name => - (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); - @override - set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), - returnValueForMissingStub: null); @override String get identifier => (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') diff --git a/test/json/ble_error_jsons.dart b/test/json/ble_error_jsons.dart index ca3cf6df..6a46ebc0 100644 --- a/test/json/ble_error_jsons.dart +++ b/test/json/ble_error_jsons.dart @@ -1,6 +1,7 @@ -String cancellationErrorJson = """ +String cancellationErrorJson(String transactionId) => """ { "errorCode": 2, - "reason": "Operation cancelled" + "reason": "Operation cancelled", + "transactionId": "$transactionId" } """; diff --git a/test/service_test.mocks.dart b/test/service_test.mocks.dart index 04a47141..a049e039 100644 --- a/test/service_test.mocks.dart +++ b/test/service_test.mocks.dart @@ -33,12 +33,6 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { _i1.throwOnMissingStub(this); } - @override - String get name => - (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); - @override - set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), - returnValueForMissingStub: null); @override String get identifier => (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') diff --git a/test/src/bridge/lib_core_test.dart b/test/src/bridge/lib_core_test.dart index de089225..b550e536 100644 --- a/test/src/bridge/lib_core_test.dart +++ b/test/src/bridge/lib_core_test.dart @@ -18,8 +18,14 @@ import '../../json/ble_error_jsons.dart'; const flutterBleLibMethodChannelName = 'flutter_ble_lib'; const monitorCharacteristicEventChannelName = flutterBleLibMethodChannelName + '/monitorCharacteristic'; - -@GenerateMocks([Peripheral, ManagerForService, ManagerForCharacteristic]) +const mockServiceUuid = "A0C8AAC8-2C37-4CE4-9110-EA7E09704D54"; +const mockCharacteristicUuid = "A56CCE6A-2178-4710-81CA-7895309A1350"; +const mockCharacteristicId = 44; +const mockServiceId = 42; +const mockId = 43; +const mockTransactionId = "asdasd123asd"; + +@GenerateMocks([Peripheral, InternalBleManager]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); late FlutterBleLib bleLib; @@ -29,127 +35,231 @@ void main() { MethodChannel(monitorCharacteristicEventChannelName); setUp(() { - bleLib = FlutterBleLib(InternalBleManager()); + bleLib = FlutterBleLib(MockInternalBleManager()); when(peripheral.identifier).thenReturn("4B:99:4C:34:DE:77"); - methodChannel.setMockMethodCallHandler((call) => Future.value("")); - eventMethodChannel.setMockMethodCallHandler((call) => Future.value("")); + methodChannel.setMockMethodCallHandler((call) { + return Future.value(""); + }); + eventMethodChannel.setMockMethodCallHandler((call) { + return Future.value(""); + }); }); - Future emitPlatformError(String errorJson) => - ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( - monitorCharacteristicEventChannelName, - const StandardMethodCodec() - .encodeErrorEnvelope(code: "irrelevant", details: errorJson), - (data) {}); - - Future emitMonitoringEvent(String eventJson) => - ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( - monitorCharacteristicEventChannelName, - const StandardMethodCodec().encodeSuccessEnvelope(eventJson), - (data) {}); - - Future emitStreamCompletion() => - ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( - monitorCharacteristicEventChannelName, - null, - (data) {}, - ); + Future _emitPlatformError(String errorJson) async { + final serBinding = ServicesBinding.instance; + if (serBinding == null) { + return; + } + await serBinding.defaultBinaryMessenger.handlePlatformMessage( + monitorCharacteristicEventChannelName, + const StandardMethodCodec().encodeErrorEnvelope( + code: "irrelevant", + details: errorJson + ), + (data) { + print(data); + } + ); + } + + Future _emitMonitoringEvent(String eventJson) async { + final serBinding = ServicesBinding.instance; + if (serBinding == null) { + return; + } + await serBinding.defaultBinaryMessenger.handlePlatformMessage( + monitorCharacteristicEventChannelName, + const StandardMethodCodec().encodeSuccessEnvelope(eventJson), + (data) {} + ); + } + + Future _emitStreamCompletion() async { + final serBinding = ServicesBinding.instance; + if (serBinding == null) { + return; + } + await serBinding.defaultBinaryMessenger.handlePlatformMessage( + monitorCharacteristicEventChannelName, + null, + (data) {}, + ); + } CharacteristicWithValueAndTransactionId createCharacteristicFromDecodedJson( - Map decodedRoot) { + Map decodedRoot + ) { Map decodedCharacteristic = decodedRoot["characteristic"]; String transactionId = decodedRoot["transactionId"]; return CharacteristicWithValueAndTransactionId.fromJson( decodedCharacteristic, - Service.fromJson(decodedRoot, peripheral, MockManagerForService()), - MockManagerForCharacteristic(), + Service.fromJson(decodedRoot, peripheral, MockInternalBleManager()), + MockInternalBleManager(), ).setTransactionId(transactionId); } Map createRawCharacteristic( - {int? id, - int? serviceId, - String? serviceUuid, - String? characteristicUuid, - String? transactionId, - String? base64value}) => - { - "serviceUuid": serviceUuid, - "serviceId": serviceId, - "transactionId": transactionId, - "characteristic": { - "characteristicUuid": characteristicUuid, - "id": id, - "isReadable": true, - "isWritableWithResponse": false, - "isWritableWithoutResponse": false, - "isNotifiable": true, - "isIndicatable": false, - "value": base64value ?? "" - } - }; + { + bool mockIds = false, + int? id, + int? serviceId, + String? serviceUuid, + String? characteristicUuid, + String? transactionId, + String base64value = "" + }) { + if (mockIds) { + serviceUuid ??= mockServiceUuid; + serviceId ??= mockServiceId; + characteristicUuid ??= mockCharacteristicUuid; + id ??= mockCharacteristicId; + } + + return { + "serviceUuid": serviceUuid, + "serviceId": serviceId, + "transactionId": transactionId, + "characteristic": { + "characteristicUuid": characteristicUuid, + "id": id, + "isReadable": true, + "isWritableWithResponse": false, + "isWritableWithoutResponse": false, + "isNotifiable": true, + "isIndicatable": false, + "value": base64value, + } + }; + } test('monitorCharacteristicForIdentifier cancels on stream error', () async { + final mockTransId = "asdasd"; + final fut = expectLater( - bleLib.monitorCharacteristicForIdentifier(peripheral, 123, "asdasd"), + bleLib.monitorCharacteristicForIdentifier(peripheral, 123, mockTransId), emitsInOrder([ emitsError(isInstanceOf()), emitsDone, ]) ); - await emitPlatformError(cancellationErrorJson); + await _emitPlatformError(cancellationErrorJson(mockTransId)); + + // await fut; + print("anyad"); await fut; }); test('monitorCharacteristicForDevice cancels on stream error', () async { - String nullStr = ""; - expectLater( + String mockTransId = ""; + final fut = expectLater( bleLib.monitorCharacteristicForDevice( - peripheral, "serviceUuid", "characteristicUuid", nullStr), + peripheral, + "serviceUuid", + "characteristicUuid", + mockTransId + ), emitsInOrder([ emitsError(isInstanceOf()), emitsDone, ])); - await emitPlatformError(cancellationErrorJson); + await _emitPlatformError(cancellationErrorJson(mockTransId)); + await fut; }); test('monitorCharacteristicForService cancels on stream error', () async { - String nullStr = ""; - expectLater( + String mockTransId = ""; + final fut = expectLater( bleLib.monitorCharacteristicForService( - peripheral, 123, "characteristicUuid", nullStr), + peripheral, 123, "characteristicUuid", mockTransId), emitsInOrder([ emitsError(isInstanceOf()), emitsDone, ])); - await emitPlatformError(cancellationErrorJson); + await _emitPlatformError(cancellationErrorJson(mockTransId)); + await fut; }); test( 'monitorCharacteristicForIdentifier streams events with matching characteristic id and transaction id', () async { - expectLater( - bleLib.monitorCharacteristicForIdentifier(peripheral, 1, "1"), - emitsInOrder([ - emits(equals(Uint8List.fromList([1, 0, 0, 0]))), - emitsDone - ])); + final fut = expectLater( + bleLib.monitorCharacteristicForIdentifier(peripheral, 1, "1"), + emitsInOrder([ + emits( + equals( + Uint8List.fromList([1, 0, 0, 0]) + ) + ), + emitsDone + ]) + ); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( - id: 1, transactionId: "1", base64value: "AQAAAA=="))); //[1,0,0,0] - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( - id: 1, transactionId: "2", base64value: "AAEAAA=="))); //[0,1,0,0] - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( - id: 2, transactionId: "1", base64value: "AAABAA=="))); //[0,0,1,0] - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( - id: 2, transactionId: "2", base64value: "AAAAAQ=="))); //[0,0,0,1] - await emitStreamCompletion(); + await _emitMonitoringEvent( + jsonEncode( + createRawCharacteristic( + mockIds: true, + id: 1, + transactionId: "1", + base64value: "AQAAAA==" + ) + ) + ); //[1,0,0,0] + await _emitMonitoringEvent( + jsonEncode( + createRawCharacteristic( + mockIds: true, + id: 1, + transactionId: "2", + base64value: "AAEAAA==" + ) + ) + ); //[0,1,0,0] + await _emitMonitoringEvent( + jsonEncode( + createRawCharacteristic( + mockIds: true, + id: 2, + transactionId: "1", + base64value: "AAABAA==" + ) + ) + ); //[0,0,1,0] + await _emitMonitoringEvent( + jsonEncode( + createRawCharacteristic( + mockIds: true, + id: 2, + transactionId: "2", + base64value: "AAAAAQ==" + ) + ) + ); //[0,0,0,1] + await _emitStreamCompletion(); + await fut; }); test( 'monitorCharacteristicForDevice streams events with matching characteristic uuid, service uuid and transaction id', () async { - expectLater( + final expected = + createRawCharacteristic( + mockIds: true, + serviceUuid: "serviceUuid", + characteristicUuid: "characteristicUuid", + transactionId: "1" + ); + // final a = bleLib.monitorCharacteristicForDevice( + // peripheral, + // "serviceUuid", + // "characteristicUuid", + // "1" + // ).listen((event) { + // final expEvent = createCharacteristicFromDecodedJson(expected); + // print(event == expEvent); + // }, onDone: () { + // print("done"); + // }); + final fut = expectLater( bleLib.monitorCharacteristicForDevice( peripheral, "serviceUuid", @@ -159,47 +269,63 @@ void main() { emitsInOrder([ emits( equals( - createCharacteristicFromDecodedJson( - createRawCharacteristic( - serviceUuid: "serviceUuid", - characteristicUuid: "characteristicUuid", - transactionId: "1" - ) - ) + createCharacteristicFromDecodedJson(expected) ) ), emitsDone ]) ); - - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + final valid = + createRawCharacteristic( + mockIds: true, serviceUuid: "serviceUuid", characteristicUuid: "characteristicUuid", - transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + transactionId: "1" + ); + final invalid1 = + createRawCharacteristic( + mockIds: true, serviceUuid: "serviceUuid", characteristicUuid: "fakeUuid", - transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + transactionId: "1" + ); + final invalid2 = + createRawCharacteristic( + mockIds: true, serviceUuid: "fakeUuid", characteristicUuid: "characteristicUuid", - transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + transactionId: "1" + ); + final invalid3 = + createRawCharacteristic( + mockIds: true, serviceUuid: "serviceUuid", characteristicUuid: "characteristicUuid", - transactionId: "2"))); - await emitStreamCompletion(); + transactionId: "2" + ); + expect(expected, equals(valid)); + expect(expected, isNot(equals(invalid1))); + expect(expected, isNot(equals(invalid2))); + expect(expected, isNot(equals(invalid3))); + + await _emitMonitoringEvent(jsonEncode(valid)); + await _emitMonitoringEvent(jsonEncode(invalid1)); + await _emitMonitoringEvent(jsonEncode(invalid2)); + await _emitMonitoringEvent(jsonEncode(invalid3)); + await _emitStreamCompletion(); + await fut; }); test( 'monitorCharacteristicForService streams events with matching service id, characteristic uuid and transaction id', () async { - expectLater( + final fut = expectLater( bleLib.monitorCharacteristicForService( peripheral, 1, "characteristicUuid", "1"), emitsInOrder([ emits(equals( createCharacteristicFromDecodedJson(createRawCharacteristic( + mockIds: true, serviceId: 1, characteristicUuid: "characteristicUuid", transactionId: "1", @@ -207,21 +333,26 @@ void main() { emitsDone ])); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + await _emitMonitoringEvent(jsonEncode(createRawCharacteristic( + mockIds: true, serviceId: 1, characteristicUuid: "characteristicUuid", transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + await _emitMonitoringEvent(jsonEncode(createRawCharacteristic( + mockIds: true, serviceId: 1, characteristicUuid: "fakeUuid", transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + await _emitMonitoringEvent(jsonEncode(createRawCharacteristic( + mockIds: true, serviceId: 2, characteristicUuid: "characteristicUuid", transactionId: "1"))); - await emitMonitoringEvent(jsonEncode(createRawCharacteristic( + await _emitMonitoringEvent(jsonEncode(createRawCharacteristic( + mockIds: true, serviceId: 1, characteristicUuid: "characteristicUuid", transactionId: "2"))); - await emitStreamCompletion(); + await _emitStreamCompletion(); + await fut; }); test( diff --git a/test/src/bridge/lib_core_test.mocks.dart b/test/src/bridge/lib_core_test.mocks.dart index 12eedc66..4cf52bfd 100644 --- a/test/src/bridge/lib_core_test.mocks.dart +++ b/test/src/bridge/lib_core_test.mocks.dart @@ -6,8 +6,7 @@ import 'dart:async' as _i4; import 'dart:typed_data' as _i3; import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i2; -import 'package:flutter_ble_lib/src/_internal.dart' as _i6; -import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i5; +import 'package:flutter_ble_lib/src/_internal.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: comment_references @@ -23,6 +22,8 @@ class _FakeDescriptorWithValue extends _i1.Fake class _FakeDescriptor extends _i1.Fake implements _i2.Descriptor {} +class _FakePeripheral extends _i1.Fake implements _i2.Peripheral {} + class _FakeUint8List extends _i1.Fake implements _i3.Uint8List {} /// A class which mocks [Peripheral]. @@ -33,12 +34,6 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { _i1.throwOnMissingStub(this); } - @override - String get name => - (super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String); - @override - set name(String? _name) => super.noSuchMethod(Invocation.setter(#name, _name), - returnValueForMissingStub: null); @override String get identifier => (super.noSuchMethod(Invocation.getter(#identifier), returnValue: '') @@ -182,14 +177,184 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { as String); } -/// A class which mocks [ManagerForService]. +/// A class which mocks [InternalBleManager]. /// /// See the documentation for Mockito's code generation for more information. -class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { - MockManagerForService() { +class MockInternalBleManager extends _i1.Mock + implements _i5.InternalBleManager { + MockInternalBleManager() { _i1.throwOnMissingStub(this); } + @override + _i4.Future createClient( + {String? restoreStateIdentifier, + _i2.RestoreStateAction? restoreStateAction}) => + (super.noSuchMethod( + Invocation.method(#createClient, [], { + #restoreStateIdentifier: restoreStateIdentifier, + #restoreStateAction: restoreStateAction + }), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future destroyClient() => + (super.noSuchMethod(Invocation.method(#destroyClient, []), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future cancelTransaction(String? transactionId) => (super + .noSuchMethod(Invocation.method(#cancelTransaction, [transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future enableRadio({String? transactionId}) => (super.noSuchMethod( + Invocation.method(#enableRadio, [], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future disableRadio({String? transactionId}) => (super.noSuchMethod( + Invocation.method(#disableRadio, [], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future<_i2.BluetoothState> bluetoothState() => + (super.noSuchMethod(Invocation.method(#bluetoothState, []), + returnValue: Future.value(_i2.BluetoothState.UNKNOWN)) + as _i4.Future<_i2.BluetoothState>); + @override + _i4.Stream<_i2.BluetoothState> observeBluetoothState( + {bool? emitCurrentValue = true}) => + (super.noSuchMethod( + Invocation.method(#observeBluetoothState, [], + {#emitCurrentValue: emitCurrentValue}), + returnValue: Stream<_i2.BluetoothState>.empty()) + as _i4.Stream<_i2.BluetoothState>); + @override + _i4.Stream<_i2.ScanResult> startPeripheralScan( + {int? scanMode = 0, + int? callbackType = 1, + List? uuids = const [], + bool? allowDuplicates = false}) => + (super.noSuchMethod( + Invocation.method(#startPeripheralScan, [], { + #scanMode: scanMode, + #callbackType: callbackType, + #uuids: uuids, + #allowDuplicates: allowDuplicates + }), + returnValue: Stream<_i2.ScanResult>.empty()) + as _i4.Stream<_i2.ScanResult>); + @override + _i4.Future stopPeripheralScan() => + (super.noSuchMethod(Invocation.method(#stopPeripheralScan, []), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i2.Peripheral createUnsafePeripheral(String? peripheralId, {String? name}) => + (super.noSuchMethod( + Invocation.method( + #createUnsafePeripheral, [peripheralId], {#name: name}), + returnValue: _FakePeripheral()) as _i2.Peripheral); + @override + _i4.Future connectToPeripheral(String? identifier, + {bool? isAutoConnect, + int? requestMtu, + bool? refreshGatt, + Duration? timeout}) => + (super.noSuchMethod( + Invocation.method(#connectToPeripheral, [ + identifier + ], { + #isAutoConnect: isAutoConnect, + #requestMtu: requestMtu, + #refreshGatt: refreshGatt, + #timeout: timeout + }), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Stream<_i2.PeripheralConnectionState> observePeripheralConnectionState( + String? peripheralIdentifier, + bool? emitCurrentValue, + bool? completeOnDisconnect) => + (super.noSuchMethod( + Invocation.method(#observePeripheralConnectionState, [ + peripheralIdentifier, + emitCurrentValue, + completeOnDisconnect + ]), + returnValue: Stream<_i2.PeripheralConnectionState>.empty()) + as _i4.Stream<_i2.PeripheralConnectionState>); + @override + _i4.Future disconnectOrCancelPeripheralConnection( + String? peripheralIdentifier) => + (super.noSuchMethod( + Invocation.method( + #disconnectOrCancelPeripheralConnection, [peripheralIdentifier]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future isPeripheralConnected(String? peripheralIdentifier) => + (super.noSuchMethod( + Invocation.method(#isPeripheralConnected, [peripheralIdentifier]), + returnValue: Future.value(false)) as _i4.Future); + @override + _i4.Future<_i2.LogLevel> logLevel() => + (super.noSuchMethod(Invocation.method(#logLevel, []), + returnValue: Future.value(_i2.LogLevel.none)) + as _i4.Future<_i2.LogLevel>); + @override + _i4.Future setLogLevel(_i2.LogLevel? logLevel) => + (super.noSuchMethod(Invocation.method(#setLogLevel, [logLevel]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future> characteristics( + _i2.Peripheral? peripheral, String? serviceUuid) => + (super.noSuchMethod( + Invocation.method(#characteristics, [peripheral, serviceUuid]), + returnValue: Future.value(<_i2.Characteristic>[])) + as _i4.Future>); + @override + _i4.Future> services(_i2.Peripheral? peripheral) => + (super.noSuchMethod(Invocation.method(#services, [peripheral]), + returnValue: Future.value(<_i2.Service>[])) + as _i4.Future>); + @override + _i4.Future> descriptorsForPeripheral( + _i2.Peripheral? peripheral, + String? serviceUuid, + String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method(#descriptorsForPeripheral, + [peripheral, serviceUuid, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future> descriptorsForService( + _i2.Service? service, String? characteristicUuid) => + (super.noSuchMethod( + Invocation.method( + #descriptorsForService, [service, characteristicUuid]), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future> descriptorsForCharacteristic( + _i2.Characteristic? characteristic) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, [characteristic]), + returnValue: + Future.value(<_i2.Descriptor>[])) as _i4 + .Future>); + @override + _i4.Future discoverAllServicesAndCharacteristics( + _i2.Peripheral? peripheral, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#discoverAllServicesAndCharacteristics, + [peripheral, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); @override _i4.Future> characteristicsForService( _i2.Service? service) => @@ -198,9 +363,54 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Future.value(<_i2.Characteristic>[])) as _i4.Future>); @override + _i4.Future rssi(_i2.Peripheral? peripheral, String? transactionId) => + (super.noSuchMethod(Invocation.method(#rssi, [peripheral, transactionId]), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future requestMtu( + _i2.Peripheral? peripheral, int? mtu, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#requestMtu, [peripheral, mtu, transactionId]), + returnValue: Future.value(0)) as _i4.Future); + @override + _i4.Future> knownPeripherals( + List? peripheralIdentifiers) => + (super.noSuchMethod( + Invocation.method(#knownPeripherals, [peripheralIdentifiers]), + returnValue: Future.value(<_i2.Peripheral>[])) + as _i4.Future>); + @override + _i4.Future> connectedPeripherals( + List? serviceUuids) => + (super.noSuchMethod( + Invocation.method(#connectedPeripherals, [serviceUuids]), + returnValue: Future.value(<_i2.Peripheral>[])) + as _i4.Future>); + @override + _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i5.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); + @override + _i4.Future<_i2.CharacteristicWithValue> readCharacteristicForDevice( + _i2.Peripheral? peripheral, + String? serviceUuid, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForDevice, + [peripheral, serviceUuid, characteristicUuid, transactionId]), + returnValue: Future.value(_FakeCharacteristicWithValue())) + as _i4.Future<_i2.CharacteristicWithValue>); + @override _i4.Future<_i2.CharacteristicWithValue> readCharacteristicForService( _i2.Peripheral? peripheral, - _i6.InternalService? service, + _i5.InternalService? service, String? characteristicUuid, String? transactionId) => (super.noSuchMethod( @@ -209,9 +419,40 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override + _i4.Future writeCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i5.InternalCharacteristic? characteristic, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future<_i2.Characteristic> writeCharacteristicForDevice( + _i2.Peripheral? peripheral, + String? serviceUuid, + String? characteristicUuid, + _i3.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForDevice, [ + peripheral, + serviceUuid, + characteristicUuid, + value, + withResponse, + transactionId + ]), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic>); + @override _i4.Future<_i2.Characteristic> writeCharacteristicForService( _i2.Peripheral? peripheral, - _i6.InternalService? service, + _i5.InternalService? service, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, @@ -228,9 +469,20 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Future.value(_FakeCharacteristic())) as _i4.Future<_i2.Characteristic>); @override + _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForDevice( + _i2.Peripheral? peripheral, + String? serviceUuid, + String? characteristicUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForDevice, + [peripheral, serviceUuid, characteristicUuid, transactionId]), + returnValue: Stream<_i2.CharacteristicWithValue>.empty()) + as _i4.Stream<_i2.CharacteristicWithValue>); + @override _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForService( _i2.Peripheral? peripheral, - _i6.InternalService? service, + _i5.InternalService? service, String? characteristicUuid, String? transactionId) => (super.noSuchMethod( @@ -239,24 +491,34 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Stream<_i2.CharacteristicWithValue>.empty()) as _i4.Stream<_i2.CharacteristicWithValue>); @override - _i4.Future> descriptorsForService( - _i2.Service? service, String? characteristicUuid) => + _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( + _i2.Peripheral? peripheral, + _i5.InternalCharacteristic? characteristic, + String? transactionId) => (super.noSuchMethod( - Invocation.method( - #descriptorsForService, [service, characteristicUuid]), - returnValue: Future.value(<_i2.Descriptor>[])) - as _i4.Future>); + Invocation.method(#monitorCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Stream<_i3.Uint8List>.empty()) + as _i4.Stream<_i3.Uint8List>); @override - _i4.Future<_i2.DescriptorWithValue> readDescriptorForService( - _i2.Service? service, - String? characteristicUuid, + _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, + _i3.Uint8List? value, String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); + @override + _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( + _i2.Characteristic? characteristic, String? descriptorUuid, + _i3.Uint8List? value, String? transactionId) => (super.noSuchMethod( - Invocation.method(#readDescriptorForService, - [service, characteristicUuid, descriptorUuid, transactionId]), - returnValue: Future.value(_FakeDescriptorWithValue())) - as _i4.Future<_i2.DescriptorWithValue>); + Invocation.method(#writeDescriptorForCharacteristic, + [characteristic, descriptorUuid, value, transactionId]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); @override _i4.Future<_i2.Descriptor> writeDescriptorForService( _i2.Service? service, @@ -274,57 +536,33 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { ]), returnValue: Future.value(_FakeDescriptor())) as _i4.Future<_i2.Descriptor>); -} - -/// A class which mocks [ManagerForCharacteristic]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockManagerForCharacteristic extends _i1.Mock - implements _i5.ManagerForCharacteristic { - MockManagerForCharacteristic() { - _i1.throwOnMissingStub(this); - } - @override - _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( + _i4.Future<_i2.Descriptor> writeDescriptorForPeripheral( _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - String? transactionId) => - (super.noSuchMethod( - Invocation.method(#readCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), - returnValue: Future.value(_FakeUint8List())) - as _i4.Future<_i3.Uint8List>); - @override - _i4.Future writeCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, + String? serviceUuid, + String? characteristicUuid, + String? descriptorUuid, _i3.Uint8List? value, - bool? withResponse, - String? transactionId) => - (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, - [peripheral, characteristic, value, withResponse, transactionId]), - returnValue: Future.value(null), - returnValueForMissingStub: Future.value()) as _i4.Future); - @override - _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, String? transactionId) => (super.noSuchMethod( - Invocation.method(#monitorCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), - returnValue: Stream<_i3.Uint8List>.empty()) - as _i4.Stream<_i3.Uint8List>); + Invocation.method(#writeDescriptorForPeripheral, [ + peripheral, + serviceUuid, + characteristicUuid, + descriptorUuid, + value, + transactionId + ]), + returnValue: Future.value(_FakeDescriptor())) + as _i4.Future<_i2.Descriptor>); @override - _i4.Future> descriptorsForCharacteristic( - _i2.Characteristic? characteristic) => + _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( + _i2.Descriptor? descriptor, String? transactionId) => (super.noSuchMethod( - Invocation.method(#descriptorsForCharacteristic, [characteristic]), - returnValue: - Future.value(<_i2.Descriptor>[])) as _i4 - .Future>); + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); @override _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( _i2.Characteristic? characteristic, @@ -336,14 +574,31 @@ class MockManagerForCharacteristic extends _i1.Mock returnValue: Future.value(_FakeDescriptorWithValue())) as _i4.Future<_i2.DescriptorWithValue>); @override - _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( - _i2.Characteristic? characteristic, + _i4.Future<_i2.DescriptorWithValue> readDescriptorForService( + _i2.Service? service, + String? characteristicUuid, String? descriptorUuid, - _i3.Uint8List? value, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeDescriptorForCharacteristic, - [characteristic, descriptorUuid, value, transactionId]), - returnValue: Future.value(_FakeDescriptor())) - as _i4.Future<_i2.Descriptor>); + Invocation.method(#readDescriptorForService, + [service, characteristicUuid, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptorForPeripheral( + _i2.Peripheral? peripheral, + String? serviceUuid, + String? characteristicUuid, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForPeripheral, [ + peripheral, + serviceUuid, + characteristicUuid, + descriptorUuid, + transactionId + ]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i4.Future<_i2.DescriptorWithValue>); } From 682260b4e51be2086ddfd5516af03890c8312756 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 6 Apr 2021 21:20:31 +0200 Subject: [PATCH 14/33] Example:: removed comment-disabled code --- example/lib/device_details/device_details_bloc.dart | 4 ---- example/lib/devices_list/devices_bloc.dart | 1 - 2 files changed, 5 deletions(-) diff --git a/example/lib/device_details/device_details_bloc.dart b/example/lib/device_details/device_details_bloc.dart index d4a363c9..b237dc43 100644 --- a/example/lib/device_details/device_details_bloc.dart +++ b/example/lib/device_details/device_details_bloc.dart @@ -78,10 +78,6 @@ class DeviceDetailsBloc { Future disconnectManual() async { _clearLogs(); final bleDevice = _bleDevice; - // if (bleDevice == null) { - // log("No device to Disconnect!"); - // return; - // } if (await bleDevice.peripheral.isConnected()) { log("DISCONNECTING..."); await bleDevice.peripheral.disconnectOrCancelConnection(); diff --git a/example/lib/devices_list/devices_bloc.dart b/example/lib/devices_list/devices_bloc.dart index 89ca2d04..5816a6dd 100644 --- a/example/lib/devices_list/devices_bloc.dart +++ b/example/lib/devices_list/devices_bloc.dart @@ -47,7 +47,6 @@ class DevicesBloc { _visibleDevicesController.close(); _devicePickerController.close(); _scanSubscription?.cancel(); - // _bleManager.destroyClient(); } void init() { From 2292ffcc492ac3b2f3f1f0097293e20b7180ce23 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 6 Apr 2021 22:02:36 +0200 Subject: [PATCH 15/33] =?UTF-8?q?Test::=20all=20tests=20Passing=20now!=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/test/widget_test.dart | 2 +- lib/flutter_ble_lib.dart | 1 + lib/src/util/_transaction_id_generator.dart | 5 + test/characteristic_test.dart | 47 +++- test/characteristic_test.mocks.dart | 115 ++++------ test/descriptor_test.dart | 9 +- test/service_test.dart | 47 +++- test/service_test.mocks.dart | 215 +++++++++++++----- test/src/bridge/lib_core_test.dart | 14 +- test/test_util/characteristic_generator.dart | 11 +- .../characteristic_generator.mocks.dart | 89 ++++++++ 11 files changed, 392 insertions(+), 163 deletions(-) create mode 100644 test/test_util/characteristic_generator.mocks.dart diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 86f64e65..bb48b547 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -19,7 +19,7 @@ void main() { expect( find.byWidgetPredicate( (Widget widget) => - widget is Text && widget.data != null && widget.data!.startsWith('Running on:'), + widget is Text, ), findsOneWidget, ); diff --git a/lib/flutter_ble_lib.dart b/lib/flutter_ble_lib.dart index a330fe19..5bef34b0 100644 --- a/lib/flutter_ble_lib.dart +++ b/lib/flutter_ble_lib.dart @@ -37,6 +37,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter_ble_lib/src/_internal.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; diff --git a/lib/src/util/_transaction_id_generator.dart b/lib/src/util/_transaction_id_generator.dart index b5270479..df261165 100644 --- a/lib/src/util/_transaction_id_generator.dart +++ b/lib/src/util/_transaction_id_generator.dart @@ -1,6 +1,11 @@ +import 'package:meta/meta.dart'; + abstract class TransactionIdGenerator { static int _id = 0; + @visibleForTesting + static int get id => _id; + static String getNextId() { _id++; return _id.toString(); diff --git a/test/characteristic_test.dart b/test/characteristic_test.dart index 5efcacf8..882dc2a7 100644 --- a/test/characteristic_test.dart +++ b/test/characteristic_test.dart @@ -13,18 +13,47 @@ import './characteristic_test.mocks.dart'; import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; -@GenerateMocks([Peripheral, ManagerForCharacteristic, ManagerForDescriptor, Service]) +@GenerateMocks( + [Peripheral, ManagerForDescriptor, DescriptorWithValue], + customMocks: [ + MockSpec(returnNullOnMissingStub: true), + ] +) void main() { - Peripheral peripheral = MockPeripheral(); - ManagerForCharacteristic managerForCharacteristic = + final peripheral = MockPeripheral(); + when(peripheral.toString()).thenReturn("mocked peripheral toString()"); + final managerForCharacteristic = MockManagerForCharacteristic(); - CharacteristicGenerator characteristicGenerator = + when( + managerForCharacteristic.readCharacteristicForIdentifier(any, any, any) + ).thenAnswer( + (_) async => Uint8List.fromList([]) + ); + when( + managerForCharacteristic.monitorCharacteristicForIdentifier(any, any, any) + ).thenAnswer( + (_) => Stream.value(Uint8List.fromList([])) + ); + when( + managerForCharacteristic.readDescriptorForCharacteristic(any, any, any) + ).thenAnswer( + (_) async => MockDescriptorWithValue() + ); + when( + managerForCharacteristic.writeDescriptorForCharacteristic(any, any, any, any) + ).thenAnswer( + (_) async => MockDescriptorWithValue() + ); + final characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); - DescriptorGenerator descriptorGenerator = + final descriptorGenerator = DescriptorGenerator(MockManagerForDescriptor()); + final service = MockService(); + when(service.peripheral).thenReturn(peripheral); + when(service.toString()).thenReturn("mocked service toString()"); - Characteristic characteristic = - characteristicGenerator.create(123, MockService()); + final characteristic = + characteristicGenerator.create(123, service); DescriptorWithValue createDescriptor(int seed) => descriptorGenerator.create(seed, characteristic); @@ -93,7 +122,7 @@ void main() { //then verify( managerForCharacteristic.readCharacteristicForIdentifier( - MockPeripheral(), characteristic, argThat(isNotNull)), + any, characteristic, argThat(isNotNull)), ); }); @@ -105,7 +134,7 @@ void main() { characteristic.read(); //then - var transactionIds = verify( + final transactionIds = verify( managerForCharacteristic.readCharacteristicForIdentifier( any, characteristic, captureThat(isNotNull)), ).captured; diff --git a/test/characteristic_test.mocks.dart b/test/characteristic_test.mocks.dart index f747299c..ee004248 100644 --- a/test/characteristic_test.mocks.dart +++ b/test/characteristic_test.mocks.dart @@ -6,7 +6,6 @@ import 'dart:async' as _i4; import 'dart:typed_data' as _i3; import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i2; -import 'package:flutter_ble_lib/src/_internal.dart' as _i6; import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; @@ -178,113 +177,81 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { as String); } -/// A class which mocks [ManagerForCharacteristic]. +/// A class which mocks [ManagerForDescriptor]. /// /// See the documentation for Mockito's code generation for more information. -class MockManagerForCharacteristic extends _i1.Mock - implements _i5.ManagerForCharacteristic { - MockManagerForCharacteristic() { +class MockManagerForDescriptor extends _i1.Mock + implements _i5.ManagerForDescriptor { + MockManagerForDescriptor() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - String? transactionId) => + _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( + _i2.Descriptor? descriptor, String? transactionId) => (super.noSuchMethod( - Invocation.method(#readCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future writeCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - _i3.Uint8List? value, - bool? withResponse, - String? transactionId) => + _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, + _i3.Uint8List? value, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, - [peripheral, characteristic, value, withResponse, transactionId]), + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), returnValue: Future.value(null), returnValueForMissingStub: Future.value()) as _i4.Future); - @override - _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - String? transactionId) => - (super.noSuchMethod( - Invocation.method(#monitorCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), - returnValue: Stream<_i3.Uint8List>.empty()) - as _i4.Stream<_i3.Uint8List>); - @override - _i4.Future> descriptorsForCharacteristic( - _i2.Characteristic? characteristic) => - (super.noSuchMethod( - Invocation.method(#descriptorsForCharacteristic, [characteristic]), - returnValue: - Future.value(<_i2.Descriptor>[])) as _i4 - .Future>); - @override - _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( - _i2.Characteristic? characteristic, - String? descriptorUuid, - String? transactionId) => - (super.noSuchMethod( - Invocation.method(#readDescriptorForCharacteristic, - [characteristic, descriptorUuid, transactionId]), - returnValue: Future.value(_FakeDescriptorWithValue())) - as _i4.Future<_i2.DescriptorWithValue>); - @override - _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( - _i2.Characteristic? characteristic, - String? descriptorUuid, - _i3.Uint8List? value, - String? transactionId) => - (super.noSuchMethod( - Invocation.method(#writeDescriptorForCharacteristic, - [characteristic, descriptorUuid, value, transactionId]), - returnValue: Future.value(_FakeDescriptor())) - as _i4.Future<_i2.Descriptor>); } -/// A class which mocks [ManagerForDescriptor]. +/// A class which mocks [DescriptorWithValue]. /// /// See the documentation for Mockito's code generation for more information. -class MockManagerForDescriptor extends _i1.Mock - implements _i5.ManagerForDescriptor { - MockManagerForDescriptor() { +class MockDescriptorWithValue extends _i1.Mock + implements _i2.DescriptorWithValue { + MockDescriptorWithValue() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( - _i2.Descriptor? descriptor, String? transactionId) => + _i3.Uint8List get value => (super.noSuchMethod(Invocation.getter(#value), + returnValue: _FakeUint8List()) as _i3.Uint8List); + @override + set value(_i3.Uint8List? _value) => + super.noSuchMethod(Invocation.setter(#value, _value), + returnValueForMissingStub: null); + @override + _i2.Characteristic get characteristic => + (super.noSuchMethod(Invocation.getter(#characteristic), + returnValue: _FakeCharacteristic()) as _i2.Characteristic); + @override + String get uuid => + (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); + @override + int get hashCode => + (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); + @override + _i4.Future<_i3.Uint8List> read({String? transactionId}) => (super.noSuchMethod( - Invocation.method( - #readDescriptorForIdentifier, [descriptor, transactionId]), + Invocation.method(#read, [], {#transactionId: transactionId}), returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, - _i3.Uint8List? value, String? transactionId) => + _i4.Future write(_i3.Uint8List? value, {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#writeDescriptorForIdentifier, - [descriptor, value, transactionId]), + Invocation.method(#write, [value], {#transactionId: transactionId}), returnValue: Future.value(null), returnValueForMissingStub: Future.value()) as _i4.Future); + @override + bool operator ==(Object? other) => + (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) + as bool); } /// A class which mocks [Service]. /// /// See the documentation for Mockito's code generation for more information. class MockService extends _i1.Mock implements _i2.Service { - MockService() { - _i1.throwOnMissingStub(this); - } - @override _i2.Peripheral get peripheral => (super.noSuchMethod(Invocation.getter(#peripheral), diff --git a/test/descriptor_test.dart b/test/descriptor_test.dart index 20352802..fa42207a 100644 --- a/test/descriptor_test.dart +++ b/test/descriptor_test.dart @@ -9,9 +9,16 @@ import 'package:flutter_test/flutter_test.dart'; import 'test_util/descriptor_generator.dart'; +import './descriptor_test.mocks.dart'; + @GenerateMocks([ManagerForDescriptor, Characteristic]) void main() { - ManagerForDescriptor managerForDescriptor = MockManagerForDescriptor(); + final managerForDescriptor = MockManagerForDescriptor(); + when( + managerForDescriptor.readDescriptorForIdentifier(any, any) + ).thenAnswer( + (_) async => Uint8List.fromList([]) + ); DescriptorGenerator descriptorGenerator = DescriptorGenerator(managerForDescriptor); diff --git a/test/service_test.dart b/test/service_test.dart index a54d3ff2..1842b983 100644 --- a/test/service_test.dart +++ b/test/service_test.dart @@ -11,16 +11,49 @@ import './service_test.mocks.dart'; import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; -@GenerateMocks([Peripheral, ManagerForService, ManagerForCharacteristic, ManagerForDescriptor]) +@GenerateMocks([ + Peripheral, + ManagerForService, + ManagerForDescriptor, + CharacteristicWithValue, + DescriptorWithValue +]) void main() { - Peripheral peripheral = MockPeripheral(); - ManagerForService managerForService = MockManagerForService(); - ManagerForCharacteristic managerForCharacteristic = + final peripheral = MockPeripheral(); + when(peripheral.toString()).thenReturn("mocked peripheral toString()"); + when(peripheral.identifier).thenReturn("mocked peripheral id"); + final managerForService = MockManagerForService(); + when( + managerForService.readCharacteristicForService(any, any, any, any) + ).thenAnswer( + (_) async => MockCharacteristicWithValue() + ); + when( + managerForService.readDescriptorForService(any, any, any, any) + ).thenAnswer( + (_) async => MockDescriptorWithValue() + ); + when( + managerForService.writeCharacteristicForService(any, any, any, any, any, any) + ).thenAnswer( + (_) async => MockCharacteristicWithValue() + ); + when( + managerForService.writeDescriptorForService(any, any, any, any, any) + ).thenAnswer( + (_) async => MockDescriptorWithValue() + ); + when( + managerForService.monitorCharacteristicForService(any, any, any, any) + ).thenAnswer( + (_) => Stream.value(MockCharacteristicWithValue()) + ); + final managerForCharacteristic = MockManagerForCharacteristic(); - ManagerForDescriptor managerForDescriptor = MockManagerForDescriptor(); - CharacteristicGenerator characteristicGenerator = + final managerForDescriptor = MockManagerForDescriptor(); + final characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); - DescriptorGenerator descriptorGenerator = + final descriptorGenerator = DescriptorGenerator(managerForDescriptor); Service service = Service.fromJson({ diff --git a/test/service_test.mocks.dart b/test/service_test.mocks.dart index a049e039..90516a8a 100644 --- a/test/service_test.mocks.dart +++ b/test/service_test.mocks.dart @@ -25,6 +25,8 @@ class _FakeDescriptor extends _i1.Fake implements _i2.Descriptor {} class _FakeUint8List extends _i1.Fake implements _i3.Uint8List {} +class _FakeService extends _i1.Fake implements _i2.Service {} + /// A class which mocks [Peripheral]. /// /// See the documentation for Mockito's code generation for more information. @@ -270,101 +272,200 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { as _i4.Future<_i2.Descriptor>); } -/// A class which mocks [ManagerForCharacteristic]. +/// A class which mocks [ManagerForDescriptor]. /// /// See the documentation for Mockito's code generation for more information. -class MockManagerForCharacteristic extends _i1.Mock - implements _i5.ManagerForCharacteristic { - MockManagerForCharacteristic() { +class MockManagerForDescriptor extends _i1.Mock + implements _i5.ManagerForDescriptor { + MockManagerForDescriptor() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i3.Uint8List> readCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - String? transactionId) => + _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( + _i2.Descriptor? descriptor, String? transactionId) => (super.noSuchMethod( - Invocation.method(#readCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), + Invocation.method( + #readDescriptorForIdentifier, [descriptor, transactionId]), returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future writeCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - _i3.Uint8List? value, - bool? withResponse, - String? transactionId) => + _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, + _i3.Uint8List? value, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, - [peripheral, characteristic, value, withResponse, transactionId]), + Invocation.method(#writeDescriptorForIdentifier, + [descriptor, value, transactionId]), returnValue: Future.value(null), returnValueForMissingStub: Future.value()) as _i4.Future); +} + +/// A class which mocks [CharacteristicWithValue]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCharacteristicWithValue extends _i1.Mock + implements _i2.CharacteristicWithValue { + MockCharacteristicWithValue() { + _i1.throwOnMissingStub(this); + } + @override - _i4.Stream<_i3.Uint8List> monitorCharacteristicForIdentifier( - _i2.Peripheral? peripheral, - _i6.InternalCharacteristic? characteristic, - String? transactionId) => + _i3.Uint8List get value => (super.noSuchMethod(Invocation.getter(#value), + returnValue: _FakeUint8List()) as _i3.Uint8List); + @override + set value(_i3.Uint8List? _value) => + super.noSuchMethod(Invocation.setter(#value, _value), + returnValueForMissingStub: null); + @override + int get hashCode => + (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); + @override + _i2.Service get service => (super.noSuchMethod(Invocation.getter(#service), + returnValue: _FakeService()) as _i2.Service); + @override + set service(_i2.Service? _service) => + super.noSuchMethod(Invocation.setter(#service, _service), + returnValueForMissingStub: null); + @override + String get uuid => + (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); + @override + set uuid(String? _uuid) => super.noSuchMethod(Invocation.setter(#uuid, _uuid), + returnValueForMissingStub: null); + @override + bool get isReadable => + (super.noSuchMethod(Invocation.getter(#isReadable), returnValue: false) + as bool); + @override + set isReadable(bool? _isReadable) => + super.noSuchMethod(Invocation.setter(#isReadable, _isReadable), + returnValueForMissingStub: null); + @override + bool get isWritableWithResponse => + (super.noSuchMethod(Invocation.getter(#isWritableWithResponse), + returnValue: false) as bool); + @override + set isWritableWithResponse(bool? _isWritableWithResponse) => + super.noSuchMethod( + Invocation.setter(#isWritableWithResponse, _isWritableWithResponse), + returnValueForMissingStub: null); + @override + bool get isWritableWithoutResponse => + (super.noSuchMethod(Invocation.getter(#isWritableWithoutResponse), + returnValue: false) as bool); + @override + set isWritableWithoutResponse(bool? _isWritableWithoutResponse) => + super.noSuchMethod( + Invocation.setter( + #isWritableWithoutResponse, _isWritableWithoutResponse), + returnValueForMissingStub: null); + @override + bool get isNotifiable => + (super.noSuchMethod(Invocation.getter(#isNotifiable), returnValue: false) + as bool); + @override + set isNotifiable(bool? _isNotifiable) => + super.noSuchMethod(Invocation.setter(#isNotifiable, _isNotifiable), + returnValueForMissingStub: null); + @override + bool get isIndicatable => + (super.noSuchMethod(Invocation.getter(#isIndicatable), returnValue: false) + as bool); + @override + set isIndicatable(bool? _isIndicatable) => + super.noSuchMethod(Invocation.setter(#isIndicatable, _isIndicatable), + returnValueForMissingStub: null); + @override + bool operator ==(Object? other) => + (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) + as bool); + @override + String toString() => + (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') + as String); + @override + _i4.Future<_i3.Uint8List> read({String? transactionId}) => (super.noSuchMethod( - Invocation.method(#monitorCharacteristicForIdentifier, - [peripheral, characteristic, transactionId]), - returnValue: Stream<_i3.Uint8List>.empty()) - as _i4.Stream<_i3.Uint8List>); + Invocation.method(#read, [], {#transactionId: transactionId}), + returnValue: Future.value(_FakeUint8List())) + as _i4.Future<_i3.Uint8List>); @override - _i4.Future> descriptorsForCharacteristic( - _i2.Characteristic? characteristic) => + _i4.Future write(_i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#descriptorsForCharacteristic, [characteristic]), - returnValue: - Future.value(<_i2.Descriptor>[])) as _i4 - .Future>); + Invocation.method( + #write, [value, withResponse], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); @override - _i4.Future<_i2.DescriptorWithValue> readDescriptorForCharacteristic( - _i2.Characteristic? characteristic, - String? descriptorUuid, - String? transactionId) => + _i4.Stream<_i3.Uint8List> monitor({String? transactionId}) => (super + .noSuchMethod( + Invocation.method(#monitor, [], {#transactionId: transactionId}), + returnValue: Stream<_i3.Uint8List>.empty()) + as _i4.Stream<_i3.Uint8List>); + @override + _i4.Future> descriptors() => + (super.noSuchMethod(Invocation.method(#descriptors, []), + returnValue: Future.value(<_i2.Descriptor>[])) + as _i4.Future>); + @override + _i4.Future<_i2.DescriptorWithValue> readDescriptor(String? descriptorUuid, + {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#readDescriptorForCharacteristic, - [characteristic, descriptorUuid, transactionId]), + Invocation.method(#readDescriptor, [descriptorUuid], + {#transactionId: transactionId}), returnValue: Future.value(_FakeDescriptorWithValue())) as _i4.Future<_i2.DescriptorWithValue>); @override - _i4.Future<_i2.Descriptor> writeDescriptorForCharacteristic( - _i2.Characteristic? characteristic, - String? descriptorUuid, - _i3.Uint8List? value, - String? transactionId) => + _i4.Future<_i2.Descriptor> writeDescriptor( + String? descriptorUuid, _i3.Uint8List? value, + {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#writeDescriptorForCharacteristic, - [characteristic, descriptorUuid, value, transactionId]), + Invocation.method(#writeDescriptor, [descriptorUuid, value], + {#transactionId: transactionId}), returnValue: Future.value(_FakeDescriptor())) as _i4.Future<_i2.Descriptor>); } -/// A class which mocks [ManagerForDescriptor]. +/// A class which mocks [DescriptorWithValue]. /// /// See the documentation for Mockito's code generation for more information. -class MockManagerForDescriptor extends _i1.Mock - implements _i5.ManagerForDescriptor { - MockManagerForDescriptor() { +class MockDescriptorWithValue extends _i1.Mock + implements _i2.DescriptorWithValue { + MockDescriptorWithValue() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i3.Uint8List> readDescriptorForIdentifier( - _i2.Descriptor? descriptor, String? transactionId) => + _i3.Uint8List get value => (super.noSuchMethod(Invocation.getter(#value), + returnValue: _FakeUint8List()) as _i3.Uint8List); + @override + set value(_i3.Uint8List? _value) => + super.noSuchMethod(Invocation.setter(#value, _value), + returnValueForMissingStub: null); + @override + _i2.Characteristic get characteristic => + (super.noSuchMethod(Invocation.getter(#characteristic), + returnValue: _FakeCharacteristic()) as _i2.Characteristic); + @override + String get uuid => + (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); + @override + int get hashCode => + (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); + @override + _i4.Future<_i3.Uint8List> read({String? transactionId}) => (super.noSuchMethod( - Invocation.method( - #readDescriptorForIdentifier, [descriptor, transactionId]), + Invocation.method(#read, [], {#transactionId: transactionId}), returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future writeDescriptorForIdentifier(_i2.Descriptor? descriptor, - _i3.Uint8List? value, String? transactionId) => + _i4.Future write(_i3.Uint8List? value, {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#writeDescriptorForIdentifier, - [descriptor, value, transactionId]), + Invocation.method(#write, [value], {#transactionId: transactionId}), returnValue: Future.value(null), returnValueForMissingStub: Future.value()) as _i4.Future); + @override + bool operator ==(Object? other) => + (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) + as bool); } diff --git a/test/src/bridge/lib_core_test.dart b/test/src/bridge/lib_core_test.dart index b550e536..3f4726e7 100644 --- a/test/src/bridge/lib_core_test.dart +++ b/test/src/bridge/lib_core_test.dart @@ -7,7 +7,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'package:flutter_ble_lib/src/_internal.dart'; import 'package:flutter_ble_lib/src/_constants.dart'; -import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:mockito/annotations.dart'; @@ -29,7 +28,7 @@ const mockTransactionId = "asdasd123asd"; void main() { TestWidgetsFlutterBinding.ensureInitialized(); late FlutterBleLib bleLib; - Peripheral peripheral = MockPeripheral(); + final peripheral = MockPeripheral(); MethodChannel methodChannel = MethodChannel(flutterBleLibMethodChannelName); MethodChannel eventMethodChannel = MethodChannel(monitorCharacteristicEventChannelName); @@ -248,17 +247,6 @@ void main() { characteristicUuid: "characteristicUuid", transactionId: "1" ); - // final a = bleLib.monitorCharacteristicForDevice( - // peripheral, - // "serviceUuid", - // "characteristicUuid", - // "1" - // ).listen((event) { - // final expEvent = createCharacteristicFromDecodedJson(expected); - // print(event == expEvent); - // }, onDone: () { - // print("done"); - // }); final fut = expectLater( bleLib.monitorCharacteristicForDevice( peripheral, diff --git a/test/test_util/characteristic_generator.dart b/test/test_util/characteristic_generator.dart index c505884f..0bb0bf7d 100644 --- a/test/test_util/characteristic_generator.dart +++ b/test/test_util/characteristic_generator.dart @@ -1,10 +1,19 @@ import 'dart:convert'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:mockito/annotations.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import './characteristic_generator.mocks.dart'; +export './characteristic_generator.mocks.dart'; + +@GenerateMocks( + [], + customMocks:[ + MockSpec(returnNullOnMissingStub: true), +]) class CharacteristicGenerator { - ManagerForCharacteristic managerForCharacteristic; + MockManagerForCharacteristic managerForCharacteristic; CharacteristicGenerator(this.managerForCharacteristic); diff --git a/test/test_util/characteristic_generator.mocks.dart b/test/test_util/characteristic_generator.mocks.dart new file mode 100644 index 00000000..6e19f689 --- /dev/null +++ b/test/test_util/characteristic_generator.mocks.dart @@ -0,0 +1,89 @@ +// Mocks generated by Mockito 5.0.3 from annotations +// in flutter_ble_lib/test/test_util/characteristic_generator.dart. +// Do not manually edit this file. + +import 'dart:async' as _i5; +import 'dart:typed_data' as _i2; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart' as _i3; +import 'package:flutter_ble_lib/src/_internal.dart' as _i6; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} + +class _FakeDescriptorWithValue extends _i1.Fake + implements _i3.DescriptorWithValue {} + +class _FakeDescriptor extends _i1.Fake implements _i3.Descriptor {} + +/// A class which mocks [ManagerForCharacteristic]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockManagerForCharacteristic extends _i1.Mock + implements _i4.ManagerForCharacteristic { + @override + _i5.Future<_i2.Uint8List> readCharacteristicForIdentifier( + _i3.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Future.value(_FakeUint8List())) + as _i5.Future<_i2.Uint8List>); + @override + _i5.Future writeCharacteristicForIdentifier( + _i3.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + _i2.Uint8List? value, + bool? withResponse, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i5.Future); + @override + _i5.Stream<_i2.Uint8List> monitorCharacteristicForIdentifier( + _i3.Peripheral? peripheral, + _i6.InternalCharacteristic? characteristic, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#monitorCharacteristicForIdentifier, + [peripheral, characteristic, transactionId]), + returnValue: Stream<_i2.Uint8List>.empty()) + as _i5.Stream<_i2.Uint8List>); + @override + _i5.Future> descriptorsForCharacteristic( + _i3.Characteristic? characteristic) => + (super.noSuchMethod( + Invocation.method(#descriptorsForCharacteristic, [characteristic]), + returnValue: + Future.value(<_i3.Descriptor>[])) as _i5 + .Future>); + @override + _i5.Future<_i3.DescriptorWithValue> readDescriptorForCharacteristic( + _i3.Characteristic? characteristic, + String? descriptorUuid, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#readDescriptorForCharacteristic, + [characteristic, descriptorUuid, transactionId]), + returnValue: Future.value(_FakeDescriptorWithValue())) + as _i5.Future<_i3.DescriptorWithValue>); + @override + _i5.Future<_i3.Descriptor> writeDescriptorForCharacteristic( + _i3.Characteristic? characteristic, + String? descriptorUuid, + _i2.Uint8List? value, + String? transactionId) => + (super.noSuchMethod( + Invocation.method(#writeDescriptorForCharacteristic, + [characteristic, descriptorUuid, value, transactionId]), + returnValue: Future.value(_FakeDescriptor())) + as _i5.Future<_i3.Descriptor>); +} From ca0cd3cf71b3f5e1892878780cfc071886e40907 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 6 Apr 2021 22:50:30 +0200 Subject: [PATCH 16/33] Enhanced BleError nullability, so that reason always has a default value; made fields final --- lib/error/ble_error.dart | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/error/ble_error.dart b/lib/error/ble_error.dart index 0556dede..b21683ff 100644 --- a/lib/error/ble_error.dart +++ b/lib/error/ble_error.dart @@ -14,24 +14,24 @@ abstract class _BleErrorMetadata { } class BleError { - BleErrorCode errorCode; - int? attErrorCode; - int? iosErrorCode; - int? androidErrorCode; - String reason; + final BleErrorCode errorCode; + final int? attErrorCode; + final int? iosErrorCode; + final int? androidErrorCode; + final String reason; - String? deviceID; - String? serviceUuid; - String? characteristicUuid; - String? descriptorUuid; - String? internalMessage; + final String? deviceID; + final String? serviceUuid; + final String? characteristicUuid; + final String? descriptorUuid; + final String? internalMessage; BleError.fromJson(Map json) - : errorCode = BleErrorCode(json[_BleErrorMetadata.errorCode]), + : errorCode = BleErrorCode(json[_BleErrorMetadata.errorCode] ?? 0), attErrorCode = json[_BleErrorMetadata.attErrorCode], iosErrorCode = json[_BleErrorMetadata.iosErrorCode], androidErrorCode = json[_BleErrorMetadata.androidErrorCode], - reason = json[_BleErrorMetadata.reason], + reason = json[_BleErrorMetadata.reason] ?? "", deviceID = json[_BleErrorMetadata.deviceId], serviceUuid = json[_BleErrorMetadata.serviceUuid], characteristicUuid = json[_BleErrorMetadata.characteristicUuid], From 46aa6bfd347c5db763e6796109b6742a43f81379 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 10:50:23 +0200 Subject: [PATCH 17/33] Travis fix --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 25478c46..238c9f1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,9 @@ _ios_job_template: &ios_job_template - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH script: - cd example + - cd ios + - pod update + - cd .. - flutter build ios --no-codesign matrix: From 50cb72767f1c123ba7a825391c0dbce2b3adf701 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 11:14:53 +0200 Subject: [PATCH 18/33] disabled analysis for tests --- .travis.yml | 1 + analysis_options.yaml | 3 +++ lib/flutter_ble_lib.dart | 1 - test/analysis_options.yaml | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 238c9f1f..27d306a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,7 @@ _ios_job_template: &ios_job_template - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH script: - cd example + - flutter pub get - cd ios - pod update - cd .. diff --git a/analysis_options.yaml b/analysis_options.yaml index bcdf3e0c..7ddec7bd 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,5 +1,8 @@ include: package:pedantic/analysis_options.yaml +analyzer: + exclude: [test/**] + linter: rules: prefer_single_quotes: false diff --git a/lib/flutter_ble_lib.dart b/lib/flutter_ble_lib.dart index 5bef34b0..a330fe19 100644 --- a/lib/flutter_ble_lib.dart +++ b/lib/flutter_ble_lib.dart @@ -37,7 +37,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; -import 'package:flutter/foundation.dart'; import 'package:flutter_ble_lib/src/_internal.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; diff --git a/test/analysis_options.yaml b/test/analysis_options.yaml index 94594611..6b24a314 100644 --- a/test/analysis_options.yaml +++ b/test/analysis_options.yaml @@ -1,5 +1,8 @@ include: ../analysis_options.yaml +analyzer: + exclude: [./**] + linter: rules: unawaited_futures: false From 2b7979be92b5e16d59c4ec78cc6a725759aff4a3 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 11:25:50 +0200 Subject: [PATCH 19/33] Travis:: still fixing ios build --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27d306a9..34f79ee3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,8 @@ _ios_job_template: &ios_job_template - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH script: - cd example - - flutter pub get + - flutter pub upgrade + - flutter build ios --config-only - cd ios - pod update - cd .. From 72f30f29b8af99a155f69a03876979484520ac77 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 21:15:13 +0200 Subject: [PATCH 20/33] vscode:: stopped tracking settings file --- .gitignore | 3 ++- .vscode/settings.json | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index a8aec041..72fac9e5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ lib/generated/ example/lib/generated/ example/.flutter-plugins-dependencies .dart_tool/ -example/ios/Podfile.lock \ No newline at end of file +example/ios/Podfile.lock +.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 305ccba7..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "editor.rulers": [ - 80 - ] -} \ No newline at end of file From b4867899c8b7b6441c90b134cb0e678544e18b48 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 21:15:58 +0200 Subject: [PATCH 21/33] travis:: removed my additions to ios example script --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 34f79ee3..25478c46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,11 +55,6 @@ _ios_job_template: &ios_job_template - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH script: - cd example - - flutter pub upgrade - - flutter build ios --config-only - - cd ios - - pod update - - cd .. - flutter build ios --no-codesign matrix: From 5f5c5769072993da545d042d00f11eb81369d989 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Wed, 7 Apr 2021 21:29:06 +0200 Subject: [PATCH 22/33] Characteristic:: Service field is now final --- lib/characteristic.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 4740cd22..8356f45b 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -18,7 +18,7 @@ abstract class _CharacteristicMetadata { /// a characteristic’s value, and how you access the descriptors. class Characteristic extends InternalCharacteristic { /// The [Service] containing this characteristic. - Service service; + final Service service; final ManagerForCharacteristic _manager; From 5f681245f112d87fe8647cd345e78a234c23ae3b Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 11:05:40 +0200 Subject: [PATCH 23/33] gitignored andoid related staff xcode noise --- .gitignore | 3 +++ example/ios/Runner.xcodeproj/project.pbxproj | 2 -- .../project.xcworkspace/contents.xcworkspacedata | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 72fac9e5..f980fc98 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ example/.flutter-plugins-dependencies .dart_tool/ example/ios/Podfile.lock .vscode/settings.json +org.eclipse.buildship.core.prefs +.project +.classpath diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 671f5ab1..f9dccdcd 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -228,13 +228,11 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../Flutter/Flutter.framework", "${BUILT_PRODUCTS_DIR}/MultiplatformBleAdapter/MultiplatformBleAdapter.framework", "${BUILT_PRODUCTS_DIR}/flutter_ble_lib/flutter_ble_lib.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MultiplatformBleAdapter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_ble_lib.framework", ); diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a16..919434a6 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> From 1da3feb70ed4f853145049fe3c5c4ec16080b287 Mon Sep 17 00:00:00 2001 From: Yauheni Pakala Date: Thu, 8 Apr 2021 15:15:08 +0300 Subject: [PATCH 24/33] Add bluetooth-central key to README.md (#562) * Add bluetooth-central key to README.md Based on #530 * Update README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 84d6651b..b678302d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,19 @@ Add [Privacy - Bluetooth Always Usage Description](https://developer.apple.com/d ... ``` +#### Background mode + +To support background capabilities add [The `bluetooth-central` Background Execution Mode](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html#//apple_ref/doc/uid/TP40013257-CH7-SW6) key to `[project]/ios/Runner/Info.plist` file. + +```xml +... +UIBackgroundModes + + bluetooth-central + +... +``` + ## Usage The library is organised around a few base entities, which are: From 56756e1845d4df49be73fa3b006ffe5403a3af37 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 23:12:21 +0200 Subject: [PATCH 25/33] Travis: updated xcode version to 12.2 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 25478c46..87f9e609 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ _android_job_template: &android_job_template _ios_job_template: &ios_job_template language: objective-c os: osx - osx_image: xcode11.6 + osx_image: xcode12.2 xcode_workspave: example/ios/Runner.xcworkspace xcode_scheme: Runner before_script: From 9bd3e05704d759254ba74cddf1726a23ab7ab7a1 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 23:15:43 +0200 Subject: [PATCH 26/33] BleError:: default reason text added --- lib/error/ble_error.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/error/ble_error.dart b/lib/error/ble_error.dart index b21683ff..2054e5dd 100644 --- a/lib/error/ble_error.dart +++ b/lib/error/ble_error.dart @@ -31,7 +31,7 @@ class BleError { attErrorCode = json[_BleErrorMetadata.attErrorCode], iosErrorCode = json[_BleErrorMetadata.iosErrorCode], androidErrorCode = json[_BleErrorMetadata.androidErrorCode], - reason = json[_BleErrorMetadata.reason] ?? "", + reason = json[_BleErrorMetadata.reason] ?? "Reason not provided", deviceID = json[_BleErrorMetadata.deviceId], serviceUuid = json[_BleErrorMetadata.serviceUuid], characteristicUuid = json[_BleErrorMetadata.characteristicUuid], From 5442bfa83183a91dcaee54c4f70ca9a33514714e Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 23:23:02 +0200 Subject: [PATCH 27/33] ScanResult:: added final qualifiers isConnectable is back to nullable since it's only available on iOS on android it will be null which does not mean false!! --- lib/scan_result.dart | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/scan_result.dart b/lib/scan_result.dart index 1840974f..8f29805c 100644 --- a/lib/scan_result.dart +++ b/lib/scan_result.dart @@ -20,10 +20,10 @@ class ScanResult { final int rssi; /// An indicator whether the peripheral is connectable (iOS only). - late final bool isConnectable; + final bool? isConnectable; /// A list of UUIDs found in the overflow area of the advertisement data (iOS only). - late final List overflowServiceUuids; + final List overflowServiceUuids; /// A packet of data advertised by the peripheral. final AdvertisementData advertisementData; @@ -32,10 +32,9 @@ class ScanResult { this.peripheral, this.rssi, this.advertisementData, - {bool? isConnectable, + {this.isConnectable, List? overflowServiceUuids, - }) : isConnectable = isConnectable ?? false, - overflowServiceUuids = overflowServiceUuids ?? []; + }) : overflowServiceUuids = overflowServiceUuids ?? []; factory ScanResult.fromJson( @@ -57,23 +56,23 @@ class ScanResult { /// manufacturer's data, advertised [Service]s class AdvertisementData { /// The manufacturer data of the peripheral. - Uint8List? manufacturerData; + final Uint8List? manufacturerData; /// A dictionary that contains service-specific advertisement data. - Map? serviceData; + final Map? serviceData; /// A list of service UUIDs. - List? serviceUuids; + final List? serviceUuids; /// The local name of the [Peripheral]. Might be different than /// [Peripheral.name]. - String? localName; + final String? localName; /// The transmit power of the peripheral. - int? txPowerLevel; + final int? txPowerLevel; /// A list of solicited service UUIDs. - List? solicitedServiceUuids; + final List? solicitedServiceUuids; AdvertisementData._fromJson(Map json) : manufacturerData = From fc130ba13029f4651d71e6041e4fc141450d2cc2 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 23:39:13 +0200 Subject: [PATCH 28/33] CharacteristicsMixin:: _parseCharacteristicWithValueWithTransactionIdResponse():: signature is now type safe moved the rawJsonValue String checking to the caller side --- lib/src/bridge/characteristics_mixin.dart | 69 ++++++++++++++--------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index df9cdd2f..12a80d52 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -20,10 +20,16 @@ mixin CharacteristicsMixin on FlutterBLE { ) .catchError((errorJson) => Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then((rawJsonValue) => - _parseCharacteristicWithValueWithTransactionIdResponse( - peripheral, rawJsonValue) - .value); + .then((rawValue) { + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; + } + return _parseCharacteristicWithValueWithTransactionIdResponse( + peripheral, + rawJsonValue + ).value; + }); Future readCharacteristicForDevice( Peripheral peripheral, @@ -43,11 +49,16 @@ mixin CharacteristicsMixin on FlutterBLE { ) .catchError((errorJson) => Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then( - (rawJsonValue) => - _parseCharacteristicWithValueWithTransactionIdResponse( - peripheral, rawJsonValue), - ); + .then((rawValue) { + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; + } + return _parseCharacteristicWithValueWithTransactionIdResponse( + peripheral, + rawJsonValue + ); + }); Future readCharacteristicForService( Peripheral peripheral, @@ -66,11 +77,16 @@ mixin CharacteristicsMixin on FlutterBLE { ) .catchError((errorJson) => Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then( - (rawJsonValue) => - _parseCharacteristicWithValueWithTransactionIdResponse( - peripheral, rawJsonValue), - ); + .then((rawValue) { + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; + } + return _parseCharacteristicWithValueWithTransactionIdResponse( + peripheral, + rawJsonValue + ); + }); Future writeCharacteristicForIdentifier( Peripheral peripheral, @@ -175,7 +191,7 @@ mixin CharacteristicsMixin on FlutterBLE { ).map((characteristicWithValue) => characteristicWithValue.value); } - Stream monitorCharacteristicForDevice( + Stream monitorCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -244,11 +260,16 @@ mixin CharacteristicsMixin on FlutterBLE { ) { Stream stream = _characteristicsMonitoringEvents - .map( - (rawJsonValue) => - _parseCharacteristicWithValueWithTransactionIdResponse( - peripheral, rawJsonValue), - ) + .map((rawValue) { + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; + } + return _parseCharacteristicWithValueWithTransactionIdResponse( + peripheral, + rawJsonValue + ); + }) .where(filter) .handleError((errorJson) => _throwErrorIfMatchesWithTransactionId(errorJson, transactionId)) @@ -271,12 +292,8 @@ mixin CharacteristicsMixin on FlutterBLE { CharacteristicWithValueAndTransactionId _parseCharacteristicWithValueWithTransactionIdResponse( - Peripheral peripheral, dynamic? rawJsonValue) { - var jsonString = ""; - if (rawJsonValue is String) { - jsonString = rawJsonValue; - } - Map rootObject = jsonDecode(jsonString); + Peripheral peripheral, String rawJsonValue) { + Map rootObject = jsonDecode(rawJsonValue); Service service = Service.fromJson(rootObject, peripheral, _manager); var transactionId = rootObject["transactionId"]; From 0d040db5e95aac303e21bac0eb69e8befe1d12e3 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Thu, 8 Apr 2021 23:43:47 +0200 Subject: [PATCH 29/33] Test:: removed dummy print --- test/src/bridge/lib_core_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/src/bridge/lib_core_test.dart b/test/src/bridge/lib_core_test.dart index 3f4726e7..7ed3679f 100644 --- a/test/src/bridge/lib_core_test.dart +++ b/test/src/bridge/lib_core_test.dart @@ -143,8 +143,6 @@ void main() { ); await _emitPlatformError(cancellationErrorJson(mockTransId)); - // await fut; - print("anyad"); await fut; }); From b47cce9540b379bbf52c15e5d5de4f51d840d224 Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Sun, 11 Apr 2021 21:23:55 +0200 Subject: [PATCH 30/33] ScanningMixin:: _prepareScanEventsStream() renamed to just _scanEvents also _resetScanEvents introduced to null the underlying scream out --- lib/src/bridge/scanning_mixin.dart | 38 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/src/bridge/scanning_mixin.dart b/lib/src/bridge/scanning_mixin.dart index 1d2eba56..32d22d78 100644 --- a/lib/src/bridge/scanning_mixin.dart +++ b/lib/src/bridge/scanning_mixin.dart @@ -1,19 +1,29 @@ part of _internal; mixin ScanningMixin on FlutterBLE { - Stream? _scanEvents; - - Stream _prepareScanEventsStream() { - return const EventChannel(ChannelName.scanningEvents) - .receiveBroadcastStream() - .handleError( - (errorJson) => throw BleError.fromJson(jsonDecode(errorJson.details)), + Stream? __scanEvents; + Stream get _scanEvents { + var scanEvents = __scanEvents; + if (scanEvents == null) { + scanEvents = + const EventChannel( + ChannelName.scanningEvents + ).receiveBroadcastStream( + ).handleError( + (errorJson) => throw BleError.fromJson( + jsonDecode(errorJson.details) + ), test: (error) => error is PlatformException, - ) - .map( + ).map( (scanResultJson) => ScanResult.fromJson(jsonDecode(scanResultJson), _manager), ); + __scanEvents = scanEvents; + } + return scanEvents; + } + void _resetScanEvents() { + __scanEvents = null; } Stream startDeviceScan( @@ -22,12 +32,6 @@ mixin ScanningMixin on FlutterBLE { List uuids, bool allowDuplicates, ) { - var scanEvents = _scanEvents; - if (scanEvents == null) { - scanEvents = _prepareScanEventsStream(); - _scanEvents = scanEvents; - } - final streamController = StreamController.broadcast( onListen: () => _methodChannel.invokeMethod( MethodName.startDeviceScan, @@ -42,7 +46,7 @@ mixin ScanningMixin on FlutterBLE { ); streamController - .addStream(scanEvents, cancelOnError: true) + .addStream(_scanEvents, cancelOnError: true) .then((_) => streamController.close()); return streamController.stream; @@ -50,7 +54,7 @@ mixin ScanningMixin on FlutterBLE { Future stopDeviceScan() async { await _methodChannel.invokeMethod(MethodName.stopDeviceScan); - _scanEvents = null; + _resetScanEvents(); return; } } From c9c8d609d53e6ba89dfa4180cc709a29e7c27a3f Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 12 Apr 2021 09:15:29 +0200 Subject: [PATCH 31/33] ScanningMixin:: small refinement on naming stuff --- lib/src/bridge/scanning_mixin.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/src/bridge/scanning_mixin.dart b/lib/src/bridge/scanning_mixin.dart index 32d22d78..84d18410 100644 --- a/lib/src/bridge/scanning_mixin.dart +++ b/lib/src/bridge/scanning_mixin.dart @@ -1,15 +1,14 @@ part of _internal; mixin ScanningMixin on FlutterBLE { - Stream? __scanEvents; + Stream? _activeScanEvents; Stream get _scanEvents { - var scanEvents = __scanEvents; + var scanEvents = _activeScanEvents; if (scanEvents == null) { scanEvents = const EventChannel( ChannelName.scanningEvents - ).receiveBroadcastStream( - ).handleError( + ).receiveBroadcastStream().handleError( (errorJson) => throw BleError.fromJson( jsonDecode(errorJson.details) ), @@ -18,12 +17,12 @@ mixin ScanningMixin on FlutterBLE { (scanResultJson) => ScanResult.fromJson(jsonDecode(scanResultJson), _manager), ); - __scanEvents = scanEvents; + _activeScanEvents = scanEvents; } return scanEvents; } void _resetScanEvents() { - __scanEvents = null; + _activeScanEvents = null; } Stream startDeviceScan( From 86dafd6d0dc4596b03150aeade1a09dfb29596ac Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Mon, 12 Apr 2021 14:44:03 +0200 Subject: [PATCH 32/33] Characteristic:: refactor on Futures to always complete with something even if withResponse is false additional type safety on invokeMethod calls --- lib/characteristic.dart | 2 +- lib/peripheral.dart | 2 +- lib/service.dart | 2 +- lib/src/_managers_for_classes.dart | 6 +- lib/src/bridge/bluetooth_state_mixin.dart | 12 +- lib/src/bridge/characteristics_mixin.dart | 190 +++++++++++------- lib/src/internal_ble_manager.dart | 6 +- test/characteristic_test.dart | 11 +- test/characteristic_test.mocks.dart | 14 +- test/descriptor_test.mocks.dart | 20 +- test/service_test.mocks.dart | 26 +-- test/src/bridge/lib_core_test.mocks.dart | 29 +-- .../characteristic_generator.mocks.dart | 19 +- 13 files changed, 195 insertions(+), 144 deletions(-) diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 8356f45b..6d7e9869 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -69,7 +69,7 @@ class Characteristic extends InternalCharacteristic { /// The value can be written only if [isWritableWithResponse] or /// [isWritableWithoutResponse] is `true` and argument [withResponse] is /// set accordingly. - Future write( + Future write( Uint8List value, bool withResponse, { String? transactionId, diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 0d1134e0..4730daf2 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -143,7 +143,7 @@ class Peripheral { /// [serviceUuid]. Optional [transactionId] could be used to cancel operation. /// /// Will result in error if discovery was not done during this connection. - Future writeCharacteristic( + Future writeCharacteristic( String serviceUuid, String characteristicUuid, Uint8List value, diff --git a/lib/service.dart b/lib/service.dart index 409ded39..54890030 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -37,7 +37,7 @@ class Service extends InternalService { /// [Characteristic.isWritableWithResponse] or /// [Characteristic.isWritableWithoutResponse] is `true` and /// [withResponse] is specified accordingly can be written to. - Future writeCharacteristic( + Future writeCharacteristic( String characteristicUuid, Uint8List value, bool withResponse, { diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 9f951a27..7e6e5d87 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -52,7 +52,7 @@ abstract class ManagerForPeripheral { String transactionId, ); - Future writeCharacteristicForDevice( + Future writeCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -101,7 +101,7 @@ abstract class ManagerForService { String transactionId, ); - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, InternalService service, String characteristicUuid, @@ -145,7 +145,7 @@ abstract class ManagerForCharacteristic { String transactionId, ); - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, Uint8List value, diff --git a/lib/src/bridge/bluetooth_state_mixin.dart b/lib/src/bridge/bluetooth_state_mixin.dart index bc379167..a0f1abaa 100644 --- a/lib/src/bridge/bluetooth_state_mixin.dart +++ b/lib/src/bridge/bluetooth_state_mixin.dart @@ -1,9 +1,11 @@ part of _internal; mixin BluetoothStateMixin on FlutterBLE { - final Stream _adapterStateChanges = - const EventChannel(ChannelName.adapterStateChanges) - .receiveBroadcastStream(); + final Stream _adapterStateChanges = + const EventChannel(ChannelName.adapterStateChanges) + .receiveBroadcastStream() + .where((event) => event is String) + .cast(); Future enableRadio(String transactionId) async { await _methodChannel.invokeMethod( @@ -26,7 +28,7 @@ mixin BluetoothStateMixin on FlutterBLE { } Future state() => _methodChannel - .invokeMethod(MethodName.getState) + .invokeMethod(MethodName.getState) .then(_mapToBluetoothState); Stream observeBluetoothState(bool emitCurrentValue) async* { @@ -37,7 +39,7 @@ mixin BluetoothStateMixin on FlutterBLE { yield* _adapterStateChanges.map(_mapToBluetoothState); } - BluetoothState _mapToBluetoothState(dynamic rawValue) { + BluetoothState _mapToBluetoothState(String? rawValue) { switch (rawValue) { case "Unknown": return BluetoothState.UNKNOWN; diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index 12a80d52..4013dea0 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -11,23 +11,23 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForIdentifier, { ArgumentName.characteristicIdentifier: characteristicIdentifier, ArgumentName.transactionId: transactionId }, ) - .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + .catchError((errorJson) async => + throw BleError.fromJson(jsonDecode(errorJson.details)) + ) .then((rawValue) { - String rawJsonValue = ""; - if (rawValue is String) { - rawJsonValue = rawValue; + if (rawValue == null) { + return Uint8List.fromList([]); } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawJsonValue + rawValue ).value; }); @@ -38,7 +38,7 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForDevice, { ArgumentName.deviceIdentifier: peripheral.identifier, @@ -47,16 +47,16 @@ mixin CharacteristicsMixin on FlutterBLE { ArgumentName.transactionId: transactionId }, ) - .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + .catchError((errorJson) async => + throw BleError.fromJson(jsonDecode(errorJson.details)) + ) .then((rawValue) { - String rawJsonValue = ""; - if (rawValue is String) { - rawJsonValue = rawValue; + if (rawValue == null) { + throw Exception("rawValue cannot be null"); } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawJsonValue + rawValue ); }); @@ -67,7 +67,7 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForService, { ArgumentName.serviceIdentifier: serviceIdentifier, @@ -76,87 +76,123 @@ mixin CharacteristicsMixin on FlutterBLE { }, ) .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + throw BleError.fromJson(jsonDecode(errorJson.details)) + ) .then((rawValue) { - String rawJsonValue = ""; - if (rawValue is String) { - rawJsonValue = rawValue; + if (rawValue == null) { + throw Exception("rawValue cannot be null"); } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawJsonValue + rawValue ); }); - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, int characteristicIdentifier, Uint8List value, bool withResponse, String transactionId, - ) => - _methodChannel.invokeMethod( - MethodName.writeCharacteristicForIdentifier, - { - ArgumentName.characteristicIdentifier: characteristicIdentifier, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ).catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))); - - Future writeCharacteristicForDevice( - Peripheral peripheral, - String serviceUuid, - String characteristicUuid, - Uint8List value, - bool withResponse, - String transactionId) => - _methodChannel - .invokeMethod( - MethodName.writeCharacteristicForDevice, - { - ArgumentName.deviceIdentifier: peripheral.identifier, - ArgumentName.serviceUuid: serviceUuid, - ArgumentName.characteristicUuid: characteristicUuid, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ) - .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then( - (rawJsonValue) => - _parseCharacteristicResponse(peripheral, rawJsonValue), - ); + ) async { + final inv = _methodChannel.invokeMethod( + MethodName.writeCharacteristicForIdentifier, + { + ArgumentName.characteristicIdentifier: characteristicIdentifier, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ).catchError((errorJson) => + throw BleError.fromJson(jsonDecode(errorJson.details)) + ).then((rawJsonValue) { + if (withResponse == false) { + return null; + } + if (rawJsonValue == null) { + return null; + } + return _parseCharacteristicResponse(peripheral, rawJsonValue); + }); + if (withResponse == false) { + return null; + } + return await inv; + } + + + + Future writeCharacteristicForDevice( + Peripheral peripheral, + String serviceUuid, + String characteristicUuid, + Uint8List value, + bool withResponse, + String transactionId + ) async { + final inv = _methodChannel.invokeMethod( + MethodName.writeCharacteristicForDevice, + { + ArgumentName.deviceIdentifier: peripheral.identifier, + ArgumentName.serviceUuid: serviceUuid, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ) + .catchError((errorJson) async => + throw BleError.fromJson(jsonDecode(errorJson.details)) + ) + .then((rawJsonValue) { + if (withResponse == false) { + return null; + } + if (rawJsonValue == null) { + return null; + } + return _parseCharacteristicResponse(peripheral, rawJsonValue); + }); + if (withResponse == false) { + return null; + } + return await inv; + } - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, int serviceIdentifier, String characteristicUuid, Uint8List value, bool withResponse, String transactionId, - ) => - _methodChannel - .invokeMethod( - MethodName.writeCharacteristicForService, - { - ArgumentName.serviceIdentifier: serviceIdentifier, - ArgumentName.characteristicUuid: characteristicUuid, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ) - .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then( - (rawJsonValue) => - _parseCharacteristicResponse(peripheral, rawJsonValue), - ); + ) async { + final inv = _methodChannel.invokeMethod( + MethodName.writeCharacteristicForService, + { + ArgumentName.serviceIdentifier: serviceIdentifier, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ) + .catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + .then((rawJsonValue) { + if (withResponse == false) { + return null; + } + if (rawJsonValue == null) { + return null; + } + return _parseCharacteristicResponse(peripheral, rawJsonValue); + }); + if (withResponse == false) { + return null; + } + return await inv; + } Stream monitorCharacteristicForIdentifier( Peripheral peripheral, diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 53211c16..4ff8e4c9 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -233,7 +233,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, Uint8List value, @@ -248,7 +248,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForDevice( + Future writeCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -265,7 +265,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, InternalService service, String characteristicUuid, diff --git a/test/characteristic_test.dart b/test/characteristic_test.dart index 882dc2a7..89588516 100644 --- a/test/characteristic_test.dart +++ b/test/characteristic_test.dart @@ -14,10 +14,10 @@ import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; @GenerateMocks( - [Peripheral, ManagerForDescriptor, DescriptorWithValue], - customMocks: [ - MockSpec(returnNullOnMissingStub: true), - ] + [Peripheral, ManagerForDescriptor, DescriptorWithValue, Service], + // customMocks: [ + // MockSpec(returnNullOnMissingStub: true), + // ] ) void main() { final peripheral = MockPeripheral(); @@ -44,6 +44,9 @@ void main() { ).thenAnswer( (_) async => MockDescriptorWithValue() ); + when( + managerForCharacteristic.writeCharacteristicForIdentifier(any, any, any, any, any) + ).thenAnswer((_) async => null); final characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); final descriptorGenerator = diff --git a/test/characteristic_test.mocks.dart b/test/characteristic_test.mocks.dart index ee004248..42ce4bc9 100644 --- a/test/characteristic_test.mocks.dart +++ b/test/characteristic_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/test/characteristic_test.dart. +// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/characteristic_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -117,7 +117,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -126,7 +126,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -252,6 +252,10 @@ class MockDescriptorWithValue extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockService extends _i1.Mock implements _i2.Service { + MockService() { + _i1.throwOnMissingStub(this); + } + @override _i2.Peripheral get peripheral => (super.noSuchMethod(Invocation.getter(#peripheral), @@ -275,7 +279,7 @@ class MockService extends _i1.Mock implements _i2.Service { returnValue: Future.value(<_i2.Characteristic>[])) as _i4.Future>); @override - _i4.Future<_i2.Characteristic> writeCharacteristic( + _i4.Future<_i2.Characteristic?> writeCharacteristic( String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -284,7 +288,7 @@ class MockService extends _i1.Mock implements _i2.Service { [characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( String? characteristicUuid, diff --git a/test/descriptor_test.mocks.dart b/test/descriptor_test.mocks.dart index 9809d530..c33117ae 100644 --- a/test/descriptor_test.mocks.dart +++ b/test/descriptor_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/test/descriptor_test.dart. +// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/descriptor_test.dart. // Do not manually edit this file. import 'dart:async' as _i5; @@ -16,6 +16,8 @@ class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} class _FakeService extends _i1.Fake implements _i3.Service {} +class _FakeCharacteristic extends _i1.Fake implements _i3.Characteristic {} + class _FakeDescriptorWithValue extends _i1.Fake implements _i3.DescriptorWithValue {} @@ -60,10 +62,6 @@ class MockCharacteristic extends _i1.Mock implements _i3.Characteristic { _i3.Service get service => (super.noSuchMethod(Invocation.getter(#service), returnValue: _FakeService()) as _i3.Service); @override - set service(_i3.Service? _service) => - super.noSuchMethod(Invocation.setter(#service, _service), - returnValueForMissingStub: null); - @override String get uuid => (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); @override @@ -122,13 +120,13 @@ class MockCharacteristic extends _i1.Mock implements _i3.Characteristic { returnValue: Future.value(_FakeUint8List())) as _i5.Future<_i2.Uint8List>); @override - _i5.Future write(_i2.Uint8List? value, bool? withResponse, - {String? transactionId}) => + _i5.Future<_i3.Characteristic?> write( + _i2.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( - Invocation.method( - #write, [value, withResponse], {#transactionId: transactionId}), - returnValue: Future.value(null), - returnValueForMissingStub: Future.value()) as _i5.Future); + Invocation.method(#write, [value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i5.Future<_i3.Characteristic?>); @override _i5.Stream<_i2.Uint8List> monitor({String? transactionId}) => (super .noSuchMethod( diff --git a/test/service_test.mocks.dart b/test/service_test.mocks.dart index 90516a8a..2cc37799 100644 --- a/test/service_test.mocks.dart +++ b/test/service_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/test/service_test.dart. +// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/service_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -118,7 +118,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -127,7 +127,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -205,7 +205,7 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic> writeCharacteristicForService( + _i4.Future<_i2.Characteristic?> writeCharacteristicForService( _i2.Peripheral? peripheral, _i6.InternalService? service, String? characteristicUuid, @@ -222,7 +222,7 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForService( _i2.Peripheral? peripheral, @@ -322,10 +322,6 @@ class MockCharacteristicWithValue extends _i1.Mock _i2.Service get service => (super.noSuchMethod(Invocation.getter(#service), returnValue: _FakeService()) as _i2.Service); @override - set service(_i2.Service? _service) => - super.noSuchMethod(Invocation.setter(#service, _service), - returnValueForMissingStub: null); - @override String get uuid => (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); @override @@ -389,13 +385,13 @@ class MockCharacteristicWithValue extends _i1.Mock returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future write(_i3.Uint8List? value, bool? withResponse, - {String? transactionId}) => + _i4.Future<_i2.Characteristic?> write( + _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( - Invocation.method( - #write, [value, withResponse], {#transactionId: transactionId}), - returnValue: Future.value(null), - returnValueForMissingStub: Future.value()) as _i4.Future); + Invocation.method(#write, [value, withResponse], + {#transactionId: transactionId}), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic?>); @override _i4.Stream<_i3.Uint8List> monitor({String? transactionId}) => (super .noSuchMethod( diff --git a/test/src/bridge/lib_core_test.mocks.dart b/test/src/bridge/lib_core_test.mocks.dart index 4cf52bfd..689889e7 100644 --- a/test/src/bridge/lib_core_test.mocks.dart +++ b/test/src/bridge/lib_core_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/test/src/bridge/lib_core_test.dart. +// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/src/bridge/lib_core_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -117,7 +117,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -126,7 +126,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -419,19 +419,24 @@ class MockInternalBleManager extends _i1.Mock returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future writeCharacteristicForIdentifier( + _i4.Future<_i2.Characteristic?> writeCharacteristicForIdentifier( _i2.Peripheral? peripheral, _i5.InternalCharacteristic? characteristic, _i3.Uint8List? value, bool? withResponse, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, - [peripheral, characteristic, value, withResponse, transactionId]), - returnValue: Future.value(null), - returnValueForMissingStub: Future.value()) as _i4.Future); + Invocation.method(#writeCharacteristicForIdentifier, [ + peripheral, + characteristic, + value, + withResponse, + transactionId + ]), + returnValue: Future.value(_FakeCharacteristic())) + as _i4.Future<_i2.Characteristic?>); @override - _i4.Future<_i2.Characteristic> writeCharacteristicForDevice( + _i4.Future<_i2.Characteristic?> writeCharacteristicForDevice( _i2.Peripheral? peripheral, String? serviceUuid, String? characteristicUuid, @@ -448,9 +453,9 @@ class MockInternalBleManager extends _i1.Mock transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override - _i4.Future<_i2.Characteristic> writeCharacteristicForService( + _i4.Future<_i2.Characteristic?> writeCharacteristicForService( _i2.Peripheral? peripheral, _i5.InternalService? service, String? characteristicUuid, @@ -467,7 +472,7 @@ class MockInternalBleManager extends _i1.Mock transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic>); + as _i4.Future<_i2.Characteristic?>); @override _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForDevice( _i2.Peripheral? peripheral, diff --git a/test/test_util/characteristic_generator.mocks.dart b/test/test_util/characteristic_generator.mocks.dart index 6e19f689..82e61214 100644 --- a/test/test_util/characteristic_generator.mocks.dart +++ b/test/test_util/characteristic_generator.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/test/test_util/characteristic_generator.dart. +// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/test_util/characteristic_generator.dart. // Do not manually edit this file. import 'dart:async' as _i5; @@ -15,6 +15,8 @@ import 'package:mockito/mockito.dart' as _i1; class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} +class _FakeCharacteristic extends _i1.Fake implements _i3.Characteristic {} + class _FakeDescriptorWithValue extends _i1.Fake implements _i3.DescriptorWithValue {} @@ -36,17 +38,22 @@ class MockManagerForCharacteristic extends _i1.Mock returnValue: Future.value(_FakeUint8List())) as _i5.Future<_i2.Uint8List>); @override - _i5.Future writeCharacteristicForIdentifier( + _i5.Future<_i3.Characteristic?> writeCharacteristicForIdentifier( _i3.Peripheral? peripheral, _i6.InternalCharacteristic? characteristic, _i2.Uint8List? value, bool? withResponse, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, - [peripheral, characteristic, value, withResponse, transactionId]), - returnValue: Future.value(null), - returnValueForMissingStub: Future.value()) as _i5.Future); + Invocation.method(#writeCharacteristicForIdentifier, [ + peripheral, + characteristic, + value, + withResponse, + transactionId + ]), + returnValue: Future.value(_FakeCharacteristic())) + as _i5.Future<_i3.Characteristic?>); @override _i5.Stream<_i2.Uint8List> monitorCharacteristicForIdentifier( _i3.Peripheral? peripheral, From a46482daec875f67388865595a7d08c4a7516fef Mon Sep 17 00:00:00 2001 From: Oliver Kocsis Date: Tue, 13 Apr 2021 08:20:02 +0200 Subject: [PATCH 33/33] Revert "Characteristic:: refactor on Futures to always complete with something even if withResponse is false" This reverts commit 86dafd6d0dc4596b03150aeade1a09dfb29596ac. --- lib/characteristic.dart | 2 +- lib/peripheral.dart | 2 +- lib/service.dart | 2 +- lib/src/_managers_for_classes.dart | 6 +- lib/src/bridge/bluetooth_state_mixin.dart | 12 +- lib/src/bridge/characteristics_mixin.dart | 190 +++++++----------- lib/src/internal_ble_manager.dart | 6 +- test/characteristic_test.dart | 11 +- test/characteristic_test.mocks.dart | 14 +- test/descriptor_test.mocks.dart | 20 +- test/service_test.mocks.dart | 26 ++- test/src/bridge/lib_core_test.mocks.dart | 29 ++- .../characteristic_generator.mocks.dart | 19 +- 13 files changed, 144 insertions(+), 195 deletions(-) diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 6d7e9869..8356f45b 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -69,7 +69,7 @@ class Characteristic extends InternalCharacteristic { /// The value can be written only if [isWritableWithResponse] or /// [isWritableWithoutResponse] is `true` and argument [withResponse] is /// set accordingly. - Future write( + Future write( Uint8List value, bool withResponse, { String? transactionId, diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 4730daf2..0d1134e0 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -143,7 +143,7 @@ class Peripheral { /// [serviceUuid]. Optional [transactionId] could be used to cancel operation. /// /// Will result in error if discovery was not done during this connection. - Future writeCharacteristic( + Future writeCharacteristic( String serviceUuid, String characteristicUuid, Uint8List value, diff --git a/lib/service.dart b/lib/service.dart index 54890030..409ded39 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -37,7 +37,7 @@ class Service extends InternalService { /// [Characteristic.isWritableWithResponse] or /// [Characteristic.isWritableWithoutResponse] is `true` and /// [withResponse] is specified accordingly can be written to. - Future writeCharacteristic( + Future writeCharacteristic( String characteristicUuid, Uint8List value, bool withResponse, { diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 7e6e5d87..9f951a27 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -52,7 +52,7 @@ abstract class ManagerForPeripheral { String transactionId, ); - Future writeCharacteristicForDevice( + Future writeCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -101,7 +101,7 @@ abstract class ManagerForService { String transactionId, ); - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, InternalService service, String characteristicUuid, @@ -145,7 +145,7 @@ abstract class ManagerForCharacteristic { String transactionId, ); - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, Uint8List value, diff --git a/lib/src/bridge/bluetooth_state_mixin.dart b/lib/src/bridge/bluetooth_state_mixin.dart index a0f1abaa..bc379167 100644 --- a/lib/src/bridge/bluetooth_state_mixin.dart +++ b/lib/src/bridge/bluetooth_state_mixin.dart @@ -1,11 +1,9 @@ part of _internal; mixin BluetoothStateMixin on FlutterBLE { - final Stream _adapterStateChanges = - const EventChannel(ChannelName.adapterStateChanges) - .receiveBroadcastStream() - .where((event) => event is String) - .cast(); + final Stream _adapterStateChanges = + const EventChannel(ChannelName.adapterStateChanges) + .receiveBroadcastStream(); Future enableRadio(String transactionId) async { await _methodChannel.invokeMethod( @@ -28,7 +26,7 @@ mixin BluetoothStateMixin on FlutterBLE { } Future state() => _methodChannel - .invokeMethod(MethodName.getState) + .invokeMethod(MethodName.getState) .then(_mapToBluetoothState); Stream observeBluetoothState(bool emitCurrentValue) async* { @@ -39,7 +37,7 @@ mixin BluetoothStateMixin on FlutterBLE { yield* _adapterStateChanges.map(_mapToBluetoothState); } - BluetoothState _mapToBluetoothState(String? rawValue) { + BluetoothState _mapToBluetoothState(dynamic rawValue) { switch (rawValue) { case "Unknown": return BluetoothState.UNKNOWN; diff --git a/lib/src/bridge/characteristics_mixin.dart b/lib/src/bridge/characteristics_mixin.dart index 4013dea0..12a80d52 100644 --- a/lib/src/bridge/characteristics_mixin.dart +++ b/lib/src/bridge/characteristics_mixin.dart @@ -11,23 +11,23 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForIdentifier, { ArgumentName.characteristicIdentifier: characteristicIdentifier, ArgumentName.transactionId: transactionId }, ) - .catchError((errorJson) async => - throw BleError.fromJson(jsonDecode(errorJson.details)) - ) + .catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) .then((rawValue) { - if (rawValue == null) { - return Uint8List.fromList([]); + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawValue + rawJsonValue ).value; }); @@ -38,7 +38,7 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForDevice, { ArgumentName.deviceIdentifier: peripheral.identifier, @@ -47,16 +47,16 @@ mixin CharacteristicsMixin on FlutterBLE { ArgumentName.transactionId: transactionId }, ) - .catchError((errorJson) async => - throw BleError.fromJson(jsonDecode(errorJson.details)) - ) + .catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) .then((rawValue) { - if (rawValue == null) { - throw Exception("rawValue cannot be null"); + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawValue + rawJsonValue ); }); @@ -67,7 +67,7 @@ mixin CharacteristicsMixin on FlutterBLE { String transactionId, ) => _methodChannel - .invokeMethod( + .invokeMethod( MethodName.readCharacteristicForService, { ArgumentName.serviceIdentifier: serviceIdentifier, @@ -76,123 +76,87 @@ mixin CharacteristicsMixin on FlutterBLE { }, ) .catchError((errorJson) => - throw BleError.fromJson(jsonDecode(errorJson.details)) - ) + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) .then((rawValue) { - if (rawValue == null) { - throw Exception("rawValue cannot be null"); + String rawJsonValue = ""; + if (rawValue is String) { + rawJsonValue = rawValue; } return _parseCharacteristicWithValueWithTransactionIdResponse( peripheral, - rawValue + rawJsonValue ); }); - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, int characteristicIdentifier, Uint8List value, bool withResponse, String transactionId, - ) async { - final inv = _methodChannel.invokeMethod( - MethodName.writeCharacteristicForIdentifier, - { - ArgumentName.characteristicIdentifier: characteristicIdentifier, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ).catchError((errorJson) => - throw BleError.fromJson(jsonDecode(errorJson.details)) - ).then((rawJsonValue) { - if (withResponse == false) { - return null; - } - if (rawJsonValue == null) { - return null; - } - return _parseCharacteristicResponse(peripheral, rawJsonValue); - }); - if (withResponse == false) { - return null; - } - return await inv; - } - - - - Future writeCharacteristicForDevice( - Peripheral peripheral, - String serviceUuid, - String characteristicUuid, - Uint8List value, - bool withResponse, - String transactionId - ) async { - final inv = _methodChannel.invokeMethod( - MethodName.writeCharacteristicForDevice, - { - ArgumentName.deviceIdentifier: peripheral.identifier, - ArgumentName.serviceUuid: serviceUuid, - ArgumentName.characteristicUuid: characteristicUuid, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ) - .catchError((errorJson) async => - throw BleError.fromJson(jsonDecode(errorJson.details)) - ) - .then((rawJsonValue) { - if (withResponse == false) { - return null; - } - if (rawJsonValue == null) { - return null; - } - return _parseCharacteristicResponse(peripheral, rawJsonValue); - }); - if (withResponse == false) { - return null; - } - return await inv; - } + ) => + _methodChannel.invokeMethod( + MethodName.writeCharacteristicForIdentifier, + { + ArgumentName.characteristicIdentifier: characteristicIdentifier, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ).catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))); + + Future writeCharacteristicForDevice( + Peripheral peripheral, + String serviceUuid, + String characteristicUuid, + Uint8List value, + bool withResponse, + String transactionId) => + _methodChannel + .invokeMethod( + MethodName.writeCharacteristicForDevice, + { + ArgumentName.deviceIdentifier: peripheral.identifier, + ArgumentName.serviceUuid: serviceUuid, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ) + .catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + .then( + (rawJsonValue) => + _parseCharacteristicResponse(peripheral, rawJsonValue), + ); - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, int serviceIdentifier, String characteristicUuid, Uint8List value, bool withResponse, String transactionId, - ) async { - final inv = _methodChannel.invokeMethod( - MethodName.writeCharacteristicForService, - { - ArgumentName.serviceIdentifier: serviceIdentifier, - ArgumentName.characteristicUuid: characteristicUuid, - ArgumentName.value: value, - ArgumentName.withResponse: withResponse, - ArgumentName.transactionId: transactionId, - }, - ) - .catchError((errorJson) => - Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) - .then((rawJsonValue) { - if (withResponse == false) { - return null; - } - if (rawJsonValue == null) { - return null; - } - return _parseCharacteristicResponse(peripheral, rawJsonValue); - }); - if (withResponse == false) { - return null; - } - return await inv; - } + ) => + _methodChannel + .invokeMethod( + MethodName.writeCharacteristicForService, + { + ArgumentName.serviceIdentifier: serviceIdentifier, + ArgumentName.characteristicUuid: characteristicUuid, + ArgumentName.value: value, + ArgumentName.withResponse: withResponse, + ArgumentName.transactionId: transactionId, + }, + ) + .catchError((errorJson) => + Future.error(BleError.fromJson(jsonDecode(errorJson.details)))) + .then( + (rawJsonValue) => + _parseCharacteristicResponse(peripheral, rawJsonValue), + ); Stream monitorCharacteristicForIdentifier( Peripheral peripheral, diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 4ff8e4c9..53211c16 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -233,7 +233,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForIdentifier( + Future writeCharacteristicForIdentifier( Peripheral peripheral, InternalCharacteristic characteristic, Uint8List value, @@ -248,7 +248,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForDevice( + Future writeCharacteristicForDevice( Peripheral peripheral, String serviceUuid, String characteristicUuid, @@ -265,7 +265,7 @@ class InternalBleManager ); @override - Future writeCharacteristicForService( + Future writeCharacteristicForService( Peripheral peripheral, InternalService service, String characteristicUuid, diff --git a/test/characteristic_test.dart b/test/characteristic_test.dart index 89588516..882dc2a7 100644 --- a/test/characteristic_test.dart +++ b/test/characteristic_test.dart @@ -14,10 +14,10 @@ import 'test_util/characteristic_generator.dart'; import 'test_util/descriptor_generator.dart'; @GenerateMocks( - [Peripheral, ManagerForDescriptor, DescriptorWithValue, Service], - // customMocks: [ - // MockSpec(returnNullOnMissingStub: true), - // ] + [Peripheral, ManagerForDescriptor, DescriptorWithValue], + customMocks: [ + MockSpec(returnNullOnMissingStub: true), + ] ) void main() { final peripheral = MockPeripheral(); @@ -44,9 +44,6 @@ void main() { ).thenAnswer( (_) async => MockDescriptorWithValue() ); - when( - managerForCharacteristic.writeCharacteristicForIdentifier(any, any, any, any, any) - ).thenAnswer((_) async => null); final characteristicGenerator = CharacteristicGenerator(managerForCharacteristic); final descriptorGenerator = diff --git a/test/characteristic_test.mocks.dart b/test/characteristic_test.mocks.dart index 42ce4bc9..ee004248 100644 --- a/test/characteristic_test.mocks.dart +++ b/test/characteristic_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/characteristic_test.dart. +// in flutter_ble_lib/test/characteristic_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -117,7 +117,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -126,7 +126,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -252,10 +252,6 @@ class MockDescriptorWithValue extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockService extends _i1.Mock implements _i2.Service { - MockService() { - _i1.throwOnMissingStub(this); - } - @override _i2.Peripheral get peripheral => (super.noSuchMethod(Invocation.getter(#peripheral), @@ -279,7 +275,7 @@ class MockService extends _i1.Mock implements _i2.Service { returnValue: Future.value(<_i2.Characteristic>[])) as _i4.Future>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristic( + _i4.Future<_i2.Characteristic> writeCharacteristic( String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -288,7 +284,7 @@ class MockService extends _i1.Mock implements _i2.Service { [characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Future<_i2.CharacteristicWithValue> readCharacteristic( String? characteristicUuid, diff --git a/test/descriptor_test.mocks.dart b/test/descriptor_test.mocks.dart index c33117ae..9809d530 100644 --- a/test/descriptor_test.mocks.dart +++ b/test/descriptor_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/descriptor_test.dart. +// in flutter_ble_lib/test/descriptor_test.dart. // Do not manually edit this file. import 'dart:async' as _i5; @@ -16,8 +16,6 @@ class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} class _FakeService extends _i1.Fake implements _i3.Service {} -class _FakeCharacteristic extends _i1.Fake implements _i3.Characteristic {} - class _FakeDescriptorWithValue extends _i1.Fake implements _i3.DescriptorWithValue {} @@ -62,6 +60,10 @@ class MockCharacteristic extends _i1.Mock implements _i3.Characteristic { _i3.Service get service => (super.noSuchMethod(Invocation.getter(#service), returnValue: _FakeService()) as _i3.Service); @override + set service(_i3.Service? _service) => + super.noSuchMethod(Invocation.setter(#service, _service), + returnValueForMissingStub: null); + @override String get uuid => (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); @override @@ -120,13 +122,13 @@ class MockCharacteristic extends _i1.Mock implements _i3.Characteristic { returnValue: Future.value(_FakeUint8List())) as _i5.Future<_i2.Uint8List>); @override - _i5.Future<_i3.Characteristic?> write( - _i2.Uint8List? value, bool? withResponse, {String? transactionId}) => + _i5.Future write(_i2.Uint8List? value, bool? withResponse, + {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#write, [value, withResponse], - {#transactionId: transactionId}), - returnValue: Future.value(_FakeCharacteristic())) - as _i5.Future<_i3.Characteristic?>); + Invocation.method( + #write, [value, withResponse], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i5.Future); @override _i5.Stream<_i2.Uint8List> monitor({String? transactionId}) => (super .noSuchMethod( diff --git a/test/service_test.mocks.dart b/test/service_test.mocks.dart index 2cc37799..90516a8a 100644 --- a/test/service_test.mocks.dart +++ b/test/service_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/service_test.dart. +// in flutter_ble_lib/test/service_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -118,7 +118,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -127,7 +127,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -205,7 +205,7 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristicForService( + _i4.Future<_i2.Characteristic> writeCharacteristicForService( _i2.Peripheral? peripheral, _i6.InternalService? service, String? characteristicUuid, @@ -222,7 +222,7 @@ class MockManagerForService extends _i1.Mock implements _i5.ManagerForService { transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForService( _i2.Peripheral? peripheral, @@ -322,6 +322,10 @@ class MockCharacteristicWithValue extends _i1.Mock _i2.Service get service => (super.noSuchMethod(Invocation.getter(#service), returnValue: _FakeService()) as _i2.Service); @override + set service(_i2.Service? _service) => + super.noSuchMethod(Invocation.setter(#service, _service), + returnValueForMissingStub: null); + @override String get uuid => (super.noSuchMethod(Invocation.getter(#uuid), returnValue: '') as String); @override @@ -385,13 +389,13 @@ class MockCharacteristicWithValue extends _i1.Mock returnValue: Future.value(_FakeUint8List())) as _i4.Future<_i3.Uint8List>); @override - _i4.Future<_i2.Characteristic?> write( - _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => + _i4.Future write(_i3.Uint8List? value, bool? withResponse, + {String? transactionId}) => (super.noSuchMethod( - Invocation.method(#write, [value, withResponse], - {#transactionId: transactionId}), - returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + Invocation.method( + #write, [value, withResponse], {#transactionId: transactionId}), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); @override _i4.Stream<_i3.Uint8List> monitor({String? transactionId}) => (super .noSuchMethod( diff --git a/test/src/bridge/lib_core_test.mocks.dart b/test/src/bridge/lib_core_test.mocks.dart index 689889e7..4cf52bfd 100644 --- a/test/src/bridge/lib_core_test.mocks.dart +++ b/test/src/bridge/lib_core_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/src/bridge/lib_core_test.dart. +// in flutter_ble_lib/test/src/bridge/lib_core_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -117,7 +117,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristic(String? serviceUuid, + _i4.Future<_i2.Characteristic> writeCharacteristic(String? serviceUuid, String? characteristicUuid, _i3.Uint8List? value, bool? withResponse, {String? transactionId}) => (super.noSuchMethod( @@ -126,7 +126,7 @@ class MockPeripheral extends _i1.Mock implements _i2.Peripheral { [serviceUuid, characteristicUuid, value, withResponse], {#transactionId: transactionId}), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Future> descriptorsForCharacteristic( String? serviceUuid, String? characteristicUuid) => @@ -419,24 +419,19 @@ class MockInternalBleManager extends _i1.Mock returnValue: Future.value(_FakeCharacteristicWithValue())) as _i4.Future<_i2.CharacteristicWithValue>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristicForIdentifier( + _i4.Future writeCharacteristicForIdentifier( _i2.Peripheral? peripheral, _i5.InternalCharacteristic? characteristic, _i3.Uint8List? value, bool? withResponse, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, [ - peripheral, - characteristic, - value, - withResponse, - transactionId - ]), - returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i4.Future); @override - _i4.Future<_i2.Characteristic?> writeCharacteristicForDevice( + _i4.Future<_i2.Characteristic> writeCharacteristicForDevice( _i2.Peripheral? peripheral, String? serviceUuid, String? characteristicUuid, @@ -453,9 +448,9 @@ class MockInternalBleManager extends _i1.Mock transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override - _i4.Future<_i2.Characteristic?> writeCharacteristicForService( + _i4.Future<_i2.Characteristic> writeCharacteristicForService( _i2.Peripheral? peripheral, _i5.InternalService? service, String? characteristicUuid, @@ -472,7 +467,7 @@ class MockInternalBleManager extends _i1.Mock transactionId ]), returnValue: Future.value(_FakeCharacteristic())) - as _i4.Future<_i2.Characteristic?>); + as _i4.Future<_i2.Characteristic>); @override _i4.Stream<_i2.CharacteristicWithValue> monitorCharacteristicForDevice( _i2.Peripheral? peripheral, diff --git a/test/test_util/characteristic_generator.mocks.dart b/test/test_util/characteristic_generator.mocks.dart index 82e61214..6e19f689 100644 --- a/test/test_util/characteristic_generator.mocks.dart +++ b/test/test_util/characteristic_generator.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.0.3 from annotations -// in flutter_ble_lib/example/ios/.symlinks/plugins/flutter_ble_lib/test/test_util/characteristic_generator.dart. +// in flutter_ble_lib/test/test_util/characteristic_generator.dart. // Do not manually edit this file. import 'dart:async' as _i5; @@ -15,8 +15,6 @@ import 'package:mockito/mockito.dart' as _i1; class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} -class _FakeCharacteristic extends _i1.Fake implements _i3.Characteristic {} - class _FakeDescriptorWithValue extends _i1.Fake implements _i3.DescriptorWithValue {} @@ -38,22 +36,17 @@ class MockManagerForCharacteristic extends _i1.Mock returnValue: Future.value(_FakeUint8List())) as _i5.Future<_i2.Uint8List>); @override - _i5.Future<_i3.Characteristic?> writeCharacteristicForIdentifier( + _i5.Future writeCharacteristicForIdentifier( _i3.Peripheral? peripheral, _i6.InternalCharacteristic? characteristic, _i2.Uint8List? value, bool? withResponse, String? transactionId) => (super.noSuchMethod( - Invocation.method(#writeCharacteristicForIdentifier, [ - peripheral, - characteristic, - value, - withResponse, - transactionId - ]), - returnValue: Future.value(_FakeCharacteristic())) - as _i5.Future<_i3.Characteristic?>); + Invocation.method(#writeCharacteristicForIdentifier, + [peripheral, characteristic, value, withResponse, transactionId]), + returnValue: Future.value(null), + returnValueForMissingStub: Future.value()) as _i5.Future); @override _i5.Stream<_i2.Uint8List> monitorCharacteristicForIdentifier( _i3.Peripheral? peripheral,