From e5c4803395666c8e022eb0a226992679358cd218 Mon Sep 17 00:00:00 2001 From: Rohit Sangwan Date: Sun, 19 Jun 2022 16:59:20 +0530 Subject: [PATCH 1/4] Add OnWriteHandler and Errors --- .../quick_blue/example/lib/peripheral_detail_page.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/quick_blue/example/lib/peripheral_detail_page.dart b/packages/quick_blue/example/lib/peripheral_detail_page.dart index 091c441..6825adc 100644 --- a/packages/quick_blue/example/lib/peripheral_detail_page.dart +++ b/packages/quick_blue/example/lib/peripheral_detail_page.dart @@ -40,6 +40,7 @@ class _PeripheralDetailPageState extends State { QuickBlue.setConnectionHandler(_handleConnectionChange); QuickBlue.setServiceHandler(_handleServiceDiscovery); QuickBlue.setValueHandler(_handleValueChange); + QuickBlue.setWriteValueHandler(_handlerWriteValue); } @override @@ -48,10 +49,15 @@ class _PeripheralDetailPageState extends State { QuickBlue.setValueHandler(null); QuickBlue.setServiceHandler(null); QuickBlue.setConnectionHandler(null); + QuickBlue.setWriteValueHandler(null); } - void _handleConnectionChange(String deviceId, BlueConnectionState state) { - debugPrint('_handleConnectionChange $deviceId, $state'); + void _handlerWriteValue(String deviceId, String characteristicId, String? error) { + debugPrint('_handlerWriteValue $deviceId, State : $characteristicId ,Error : $error'); + } + + void _handleConnectionChange(String deviceId, BlueConnectionState state,String? error) { + debugPrint('_handleConnectionChange $deviceId,State : ${state.value} , Error : $error'); } void _handleServiceDiscovery(String deviceId, String serviceId, List characteristicIds) { From 163e99b3addb65975acb1c046424e895f2e3e034 Mon Sep 17 00:00:00 2001 From: Rohit Sangwan Date: Sun, 19 Jun 2022 17:00:30 +0530 Subject: [PATCH 2/4] Add onWriteHandler and Errors --- .../quick_blue/darwin/QuickBlueDarwin.swift | 20 ++++++++++++++++++- packages/quick_blue/lib/quick_blue.dart | 4 ++++ .../lib/src/method_channel_quick_blue.dart | 17 +++++++++------- .../quick_blue/lib/src/quick_blue_linux.dart | 6 +++--- .../src/quick_blue_platform_interface.dart | 8 ++++++-- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/quick_blue/darwin/QuickBlueDarwin.swift b/packages/quick_blue/darwin/QuickBlueDarwin.swift index d8ff321..1c46d00 100644 --- a/packages/quick_blue/darwin/QuickBlueDarwin.swift +++ b/packages/quick_blue/darwin/QuickBlueDarwin.swift @@ -79,7 +79,7 @@ public class QuickBlueDarwin: NSObject, FlutterPlugin { case "stopScan": manager.stopScan() result(nil) - case "connect": + case "connect": let arguments = call.arguments as! Dictionary let deviceId = arguments["deviceId"] as! String guard let peripheral = discoveredPeripherals[deviceId] else { @@ -200,12 +200,22 @@ extension QuickBlueDarwin: CBCentralManagerDelegate { "ConnectionState": "connected", ]) } + + public func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral,error: Error?) { + print("centralManager:didFailToConnect \(peripheral.uuid.uuidString) error: \(String(describing: error))") + messageConnector.sendMessage([ + "deviceId": peripheral.uuid.uuidString, + "ConnectionState": "disconnected", + "error": String(describing: error) + ]) + } public func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { print("centralManager:didDisconnectPeripheral: \(peripheral.uuid.uuidString) error: \(String(describing: error))") messageConnector.sendMessage([ "deviceId": peripheral.uuid.uuidString, "ConnectionState": "disconnected", + "error": String(describing: error) ]) } } @@ -248,6 +258,7 @@ extension QuickBlueDarwin: CBPeripheralDelegate { } self.messageConnector.sendMessage([ "deviceId": peripheral.uuid.uuidString, + "error": String(describing: error), "ServiceState": "discovered", "service": service.uuid.uuidStr, "characteristics": service.characteristics!.map { $0.uuid.uuidStr } @@ -257,6 +268,12 @@ extension QuickBlueDarwin: CBPeripheralDelegate { public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { let data = characteristic.value as NSData? print("peripheral:didWriteValueForCharacteristic \(characteristic.uuid.uuidStr) \(String(describing: data)) error: \(String(describing: error))") + self.messageConnector.sendMessage([ + "deviceId": peripheral.uuid.uuidString, + "write": "Success", + "characteristic": characteristic.uuid.uuidStr, + "error": String(describing: error) + ]) } public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { @@ -264,6 +281,7 @@ extension QuickBlueDarwin: CBPeripheralDelegate { print("peripheral:didUpdateValueForCharacteristic \(characteristic.uuid) \(String(describing: data)) error: \(String(describing: error))") self.messageConnector.sendMessage([ "deviceId": peripheral.uuid.uuidString, + "error": String(describing: error), "characteristicValue": [ "characteristic": characteristic.uuid.uuidStr, "value": FlutterStandardTypedData(bytes: characteristic.value!) diff --git a/packages/quick_blue/lib/quick_blue.dart b/packages/quick_blue/lib/quick_blue.dart index 4bb5139..f29f312 100644 --- a/packages/quick_blue/lib/quick_blue.dart +++ b/packages/quick_blue/lib/quick_blue.dart @@ -39,6 +39,10 @@ class QuickBlue { _platform.onConnectionChanged = onConnectionChanged; } + static void setWriteValueHandler(OnWrite? onWrite) { + _platform.onWrite = onWrite; + } + static void discoverServices(String deviceId) => _platform.discoverServices(deviceId); static void setServiceHandler(OnServiceDiscovered? onServiceDiscovered) { diff --git a/packages/quick_blue/lib/src/method_channel_quick_blue.dart b/packages/quick_blue/lib/src/method_channel_quick_blue.dart index 87d3ef1..54341e3 100644 --- a/packages/quick_blue/lib/src/method_channel_quick_blue.dart +++ b/packages/quick_blue/lib/src/method_channel_quick_blue.dart @@ -64,18 +64,19 @@ class MethodChannelQuickBlue extends QuickBluePlatform { } @override - void discoverServices(String deviceId) { - _method.invokeMethod('discoverServices', { + Future discoverServices(String deviceId) async{ + await _method.invokeMethod('discoverServices', { 'deviceId': deviceId, }).then((_) => _log('discoverServices invokeMethod success')); } Future _handleConnectorMessage(dynamic message) async { _log('_handleConnectorMessage $message', logLevel: Level.ALL); + String? error = (message['error'] == null || message['error'] == 'nil') ? null : message['error']; if (message['ConnectionState'] != null) { String deviceId = message['deviceId']; BlueConnectionState connectionState = BlueConnectionState.parse(message['ConnectionState']); - onConnectionChanged?.call(deviceId, connectionState); + onConnectionChanged?.call(deviceId, connectionState,error); } else if (message['ServiceState'] != null) { if (message['ServiceState'] == 'discovered') { String deviceId = message['deviceId']; @@ -91,12 +92,14 @@ class MethodChannelQuickBlue extends QuickBluePlatform { onValueChanged?.call(deviceId, characteristic, value); } else if (message['mtuConfig'] != null) { _mtuConfigController.add(message['mtuConfig']); + }else if (message['write'] != null) { + onWrite?.call(message['deviceId'],message['characteristic'],error); } } @override Future setNotifiable(String deviceId, String service, String characteristic, BleInputProperty bleInputProperty) async { - _method.invokeMethod('setNotifiable', { + await _method.invokeMethod('setNotifiable', { 'deviceId': deviceId, 'service': service, 'characteristic': characteristic, @@ -106,7 +109,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform { @override Future readValue(String deviceId, String service, String characteristic) async { - _method.invokeMethod('readValue', { + await _method.invokeMethod('readValue', { 'deviceId': deviceId, 'service': service, 'characteristic': characteristic, @@ -115,7 +118,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform { @override Future writeValue(String deviceId, String service, String characteristic, Uint8List value, BleOutputProperty bleOutputProperty) async { - _method.invokeMethod('writeValue', { + await _method.invokeMethod('writeValue', { 'deviceId': deviceId, 'service': service, 'characteristic': characteristic, @@ -134,7 +137,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform { @override Future requestMtu(String deviceId, int expectedMtu) async { - _method.invokeMethod('requestMtu', { + await _method.invokeMethod('requestMtu', { 'deviceId': deviceId, 'expectedMtu': expectedMtu, }).then((_) => _log('requestMtu invokeMethod success')); diff --git a/packages/quick_blue/lib/src/quick_blue_linux.dart b/packages/quick_blue/lib/src/quick_blue_linux.dart index 3cf1211..3c73be8 100644 --- a/packages/quick_blue/lib/src/quick_blue_linux.dart +++ b/packages/quick_blue/lib/src/quick_blue_linux.dart @@ -103,19 +103,19 @@ class QuickBlueLinux extends QuickBluePlatform { @override void connect(String deviceId) { _findDeviceById(deviceId).connect().then((_) { - onConnectionChanged?.call(deviceId, BlueConnectionState.connected); + onConnectionChanged?.call(deviceId, BlueConnectionState.connected,null); }); } @override void disconnect(String deviceId) { _findDeviceById(deviceId).disconnect().then((_) { - onConnectionChanged?.call(deviceId, BlueConnectionState.disconnected); + onConnectionChanged?.call(deviceId, BlueConnectionState.disconnected,null); }); } @override - void discoverServices(String deviceId) { + Future discoverServices(String deviceId) async{ var device = _findDeviceById(deviceId); for (var service in device.gattServices) { diff --git a/packages/quick_blue/lib/src/quick_blue_platform_interface.dart b/packages/quick_blue/lib/src/quick_blue_platform_interface.dart index 7f1f5a3..1874fb7 100644 --- a/packages/quick_blue/lib/src/quick_blue_platform_interface.dart +++ b/packages/quick_blue/lib/src/quick_blue_platform_interface.dart @@ -11,12 +11,14 @@ export 'models.dart'; typedef QuickLogger = Logger; -typedef OnConnectionChanged = void Function(String deviceId, BlueConnectionState state); +typedef OnConnectionChanged = void Function(String deviceId, BlueConnectionState state,String? error); typedef OnServiceDiscovered = void Function(String deviceId, String serviceId, List characteristicIds); typedef OnValueChanged = void Function(String deviceId, String characteristicId, Uint8List value); +typedef OnWrite = void Function(String deviceId, String characteristicId, String? error); + abstract class QuickBluePlatform extends PlatformInterface { QuickBluePlatform() : super(token: _token); @@ -47,7 +49,7 @@ abstract class QuickBluePlatform extends PlatformInterface { OnConnectionChanged? onConnectionChanged; - void discoverServices(String deviceId); + Future discoverServices(String deviceId); OnServiceDiscovered? onServiceDiscovered; @@ -55,6 +57,8 @@ abstract class QuickBluePlatform extends PlatformInterface { OnValueChanged? onValueChanged; + OnWrite? onWrite; + Future readValue(String deviceId, String service, String characteristic); Future writeValue(String deviceId, String service, String characteristic, Uint8List value, BleOutputProperty bleOutputProperty); From 28f386bdd63bc21ad469939d0f3f8e835ce1e841 Mon Sep 17 00:00:00 2001 From: Rohit Sangwan Date: Sun, 19 Jun 2022 17:40:44 +0530 Subject: [PATCH 3/4] Add Android WriteError --- .../kotlin/com/example/quick_blue/QuickBluePlugin.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/quick_blue/android/src/main/kotlin/com/example/quick_blue/QuickBluePlugin.kt b/packages/quick_blue/android/src/main/kotlin/com/example/quick_blue/QuickBluePlugin.kt index db2f868..36b5d8d 100644 --- a/packages/quick_blue/android/src/main/kotlin/com/example/quick_blue/QuickBluePlugin.kt +++ b/packages/quick_blue/android/src/main/kotlin/com/example/quick_blue/QuickBluePlugin.kt @@ -209,10 +209,12 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand "ConnectionState" to "connected" )) } else { + // TODO Parse status code and send correct error messages cleanConnection(gatt) sendMessage(messageConnector, mapOf( "deviceId" to gatt.device.address, - "ConnectionState" to "disconnected" + "ConnectionState" to "disconnected", + "error" to "Disconnection Reason : Status $status" )) } } @@ -260,6 +262,13 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic, status: Int) { Log.v(TAG, "onCharacteristicWrite ${characteristic.uuid}, ${characteristic.value.contentToString()} $status") + val deviceID = gatt?.device?.address ?: "" + // TODO Parse status code and send correct error messages + sendMessage(messageConnector, mapOf( + "deviceId" to deviceID, + "characteristic" to characteristic.uuid.toString(), + "error" to "Write Command Status : $status" + )) } override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { From 042fda9607d6adbe28f241bf74081f0be297d6d1 Mon Sep 17 00:00:00 2001 From: Rohit Sangwan Date: Sun, 19 Jun 2022 17:51:05 +0530 Subject: [PATCH 4/4] Add Linux WriteError --- .../quick_blue/lib/src/quick_blue_linux.dart | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/quick_blue/lib/src/quick_blue_linux.dart b/packages/quick_blue/lib/src/quick_blue_linux.dart index 3c73be8..2b81196 100644 --- a/packages/quick_blue/lib/src/quick_blue_linux.dart +++ b/packages/quick_blue/lib/src/quick_blue_linux.dart @@ -105,6 +105,11 @@ class QuickBlueLinux extends QuickBluePlatform { _findDeviceById(deviceId).connect().then((_) { onConnectionChanged?.call(deviceId, BlueConnectionState.connected,null); }); + //TODO : Listen for PropertisChanged event , to update Connection Status on Disconnection from BleDevice , + + // _findDeviceById(deviceId).propertiesChanged.listen((event) { + // print(event); + // }); } @override @@ -173,13 +178,17 @@ class QuickBlueLinux extends QuickBluePlatform { @override Future writeValue(String deviceId, String service, String characteristic, Uint8List value, BleOutputProperty bleOutputProperty) async { var c = _getCharacteristic(deviceId, service, characteristic); - - if (bleOutputProperty == BleOutputProperty.withResponse) { - await c.writeValue(value, type: BlueZGattCharacteristicWriteType.request); - } else { - await c.writeValue(value, type: BlueZGattCharacteristicWriteType.command); + try{ + if (bleOutputProperty == BleOutputProperty.withResponse) { + await c.writeValue(value, type: BlueZGattCharacteristicWriteType.request); + } else { + await c.writeValue(value, type: BlueZGattCharacteristicWriteType.command); + } + _log('writeValue $characteristic, ${hex.encode(value)}'); + onWrite?.call(deviceId,characteristic,null); + }catch(e){ + onWrite?.call(deviceId,characteristic,e.toString()); } - _log('writeValue $characteristic, ${hex.encode(value)}'); } @override