diff --git a/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt b/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt index f9ad05e..68e4321 100644 --- a/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt +++ b/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt @@ -106,6 +106,33 @@ fun Int.parseBluetoothStatusCodeError(): String? { } } +fun Int.parseGattErrorCode(): String? { + return when (this) { + BluetoothGatt.GATT_SUCCESS -> null + BluetoothGatt.GATT_READ_NOT_PERMITTED -> "GATT_READ_NOT_PERMITTED" + BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "GATT_WRITE_NOT_PERMITTED" + BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION -> "GATT_INSUFFICIENT_AUTHENTICATION" + BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED -> "GATT_REQUEST_NOT_SUPPORTED" + BluetoothGatt.GATT_INVALID_OFFSET -> "GATT_INVALID_OFFSET" + BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION -> "GATT_INSUFFICIENT_AUTHORIZATION" + BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH -> "GATT_INVALID_ATTRIBUTE_LENGTH" + BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION -> "GATT_INSUFFICIENT_ENCRYPTION" + BluetoothGatt.GATT_CONNECTION_CONGESTED -> "GATT_CONNECTION_CONGESTED" + BluetoothGatt.GATT_FAILURE -> "GATT_FAILURE" + 0x01 -> "GATT_INVALID_HANDLE" + 0x04 -> "GATT_INVALID_PDU" + 0x09 -> "GATT_PREPARE_QUEUE_FULL" + 0x0a -> "GATT_ATTR_NOT_FOUND" + 0x0b -> "GATT_ATTR_NOT_LONG" + 0x0c -> "GATT_INSUFFICIENT_KEY_SIZE" + 0x0e -> "GATT_UNLIKELY" + 0x10 -> "GATT_UNSUPPORTED_GROUP" + 0x11 -> "GATT_INSUFFICIENT_RESOURCES" + else -> "Unknown Error: $this" + } +} + + val ScanResult.manufacturerDataHead: ByteArray? get() { val sparseArray = scanRecord?.manufacturerSpecificData ?: return null diff --git a/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt b/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt index 5bc7b42..0b07960 100644 --- a/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt +++ b/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt @@ -267,7 +267,20 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(), it.serviceId == characteristic.service.uuid.toString() }.forEach { bleCharacteristicFutureList.remove(it) - it.result(Result.success(value)) + if (status == BluetoothGatt.GATT_SUCCESS) { + it.result(Result.success(value)) + } else { + it.result( + Result.failure( + FlutterError( + status.toString(), + "Failed to read: (${status.parseGattErrorCode()})", + null, + ) + ) + ) + } + } } @@ -374,9 +387,9 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(), it.result( Result.failure( FlutterError( - "Failed", - "Failed to write ($status)", - "status $status" + status.toString(), + "Failed to write: (${status.parseGattErrorCode()})", + null, ) ) ) diff --git a/darwin/Classes/UniversalBleHelper.swift b/darwin/Classes/UniversalBleHelper.swift index a834751..92ee390 100644 --- a/darwin/Classes/UniversalBleHelper.swift +++ b/darwin/Classes/UniversalBleHelper.swift @@ -101,6 +101,15 @@ extension CBManagerState { } } +extension Error { + func toFlutterError() -> FlutterError { + let nsError = self as NSError + let errorCode: String = .init(nsError.code) + let errorDescription: String = nsError.localizedDescription + return FlutterError(code: errorCode, message: errorDescription, details: nil) + } +} + public extension CBUUID { var uuidStr: String { uuidString.lowercased() diff --git a/darwin/Classes/UniversalBlePlugin.swift b/darwin/Classes/UniversalBlePlugin.swift index bd9d5b0..034ee0a 100644 --- a/darwin/Classes/UniversalBlePlugin.swift +++ b/darwin/Classes/UniversalBlePlugin.swift @@ -36,7 +36,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral oldValue?(Result.success(AvailabilityState.unknown.rawValue)) } } - + init(callbackChannel: UniversalBleCallbackChannel) { self.callbackChannel = callbackChannel super.init() @@ -44,14 +44,14 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral func getBluetoothAvailabilityState(completion: @escaping (Result) -> Void) { let managerState = manager.state - + if managerState == .unknown { bluetoothAvailabilityStateCallback = completion } else { completion(.success(managerState.toAvailabilityState().rawValue)) } } - + func enableBluetooth(completion: @escaping (Result) -> Void) { completion(Result.failure(FlutterError(code: "NotSupported", message: nil, details: nil))) } @@ -280,8 +280,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral // Update futures for writeValue characteristicWriteFutures.removeAll { future in if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr { - if error != nil { - future.result(Result.failure(FlutterError(code: "WriteFailed", message: String(describing: error), details: nil))) + if let flutterError = error?.toFlutterError() { + future.result(Result.failure(flutterError)) } else { future.result(Result.success({}())) } @@ -306,8 +306,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral // Update futures for readValue characteristicReadFutures.removeAll { future in if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr { - if error != nil { - future.result(Result.failure(FlutterError(code: "ReadFailed", message: String(describing: error), details: nil))) + if let flutterError = error?.toFlutterError() { + future.result(Result.failure(flutterError)) } else { if let characteristicValue = characteristic.value { future.result(Result.success(FlutterStandardTypedData(bytes: characteristicValue))) diff --git a/example/pubspec.lock b/example/pubspec.lock index e9cbfb9..580ae8c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -386,7 +386,7 @@ packages: path: ".." relative: true source: path - version: "0.9.0" + version: "0.9.1" vector_math: dependency: transitive description: