Implement unified and type safe error messages (#186)
* Implement unified and type safe error messages * Fix Apple error handling * improve linux exception handling * improve web exception handling * fix window imports * update pigeon generated files * Fix compilaton issue * Fix windows error parsing * Fix windows compilation * Improve error handling on dart side * rename _wrapFuture to _executeWithErrorHandling * Add pigeon generation script and format generated dart file * Update changelog * Update readme --------- Co-authored-by: Foti Dim <foti@navideck.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v22.6.1), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.0.5), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
@@ -7,33 +7,67 @@ package com.navideck.universal_ble
|
||||
import android.util.Log
|
||||
import io.flutter.plugin.common.BasicMessageChannel
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import io.flutter.plugin.common.MessageCodec
|
||||
import io.flutter.plugin.common.StandardMethodCodec
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.nio.ByteBuffer
|
||||
private object UniversalBlePigeonUtils {
|
||||
|
||||
private fun wrapResult(result: Any?): List<Any?> {
|
||||
return listOf(result)
|
||||
}
|
||||
fun createConnectionError(channelName: String): FlutterError {
|
||||
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") }
|
||||
|
||||
private fun wrapError(exception: Throwable): List<Any?> {
|
||||
return if (exception is FlutterError) {
|
||||
listOf(
|
||||
exception.code,
|
||||
exception.message,
|
||||
exception.details
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
exception.javaClass.simpleName,
|
||||
exception.toString(),
|
||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
||||
)
|
||||
fun wrapResult(result: Any?): List<Any?> {
|
||||
return listOf(result)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConnectionError(channelName: String): FlutterError {
|
||||
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "")}
|
||||
fun wrapError(exception: Throwable): List<Any?> {
|
||||
return if (exception is FlutterError) {
|
||||
listOf(
|
||||
exception.code,
|
||||
exception.message,
|
||||
exception.details
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
exception.javaClass.simpleName,
|
||||
exception.toString(),
|
||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
||||
)
|
||||
}
|
||||
}
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
return a.size == b.size && a.all {
|
||||
(b as Map<Any?, Any?>).contains(it.key) &&
|
||||
deepEquals(it.value, b[it.key])
|
||||
}
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
||||
@@ -47,6 +81,77 @@ class FlutterError (
|
||||
val details: Any? = null
|
||||
) : Throwable()
|
||||
|
||||
/** Unified error codes for all platforms */
|
||||
enum class UniversalBleErrorCode(val raw: Int) {
|
||||
UNKNOWN_ERROR(0),
|
||||
FAILED(1),
|
||||
NOT_SUPPORTED(2),
|
||||
NOT_IMPLEMENTED(3),
|
||||
CHANNEL_ERROR(4),
|
||||
BLUETOOTH_NOT_AVAILABLE(5),
|
||||
BLUETOOTH_NOT_ENABLED(6),
|
||||
BLUETOOTH_NOT_ALLOWED(7),
|
||||
BLUETOOTH_UNAUTHORIZED(8),
|
||||
DEVICE_DISCONNECTED(9),
|
||||
CONNECTION_TIMEOUT(10),
|
||||
CONNECTION_FAILED(11),
|
||||
CONNECTION_REJECTED(12),
|
||||
CONNECTION_LIMIT_EXCEEDED(13),
|
||||
CONNECTION_ALREADY_EXISTS(14),
|
||||
CONNECTION_TERMINATED(15),
|
||||
CONNECTION_IN_PROGRESS(16),
|
||||
ILLEGAL_ARGUMENT(17),
|
||||
DEVICE_NOT_FOUND(18),
|
||||
SERVICE_NOT_FOUND(19),
|
||||
CHARACTERISTIC_NOT_FOUND(20),
|
||||
INVALID_SERVICE_UUID(21),
|
||||
INVALID_CHARACTERISTIC_UUID(22),
|
||||
INVALID_OFFSET(23),
|
||||
INVALID_ATTRIBUTE_LENGTH(24),
|
||||
INVALID_PDU(25),
|
||||
INVALID_HANDLE(26),
|
||||
READ_FAILED(27),
|
||||
READ_NOT_PERMITTED(28),
|
||||
WRITE_FAILED(29),
|
||||
WRITE_NOT_PERMITTED(30),
|
||||
WRITE_REQUEST_BUSY(31),
|
||||
INVALID_ACTION(32),
|
||||
OPERATION_NOT_SUPPORTED(33),
|
||||
OPERATION_TIMEOUT(34),
|
||||
OPERATION_CANCELLED(35),
|
||||
OPERATION_IN_PROGRESS(36),
|
||||
CHARACTERISTIC_DOES_NOT_SUPPORT_READ(37),
|
||||
CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE(38),
|
||||
CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE_WITHOUT_RESPONSE(39),
|
||||
CHARACTERISTIC_DOES_NOT_SUPPORT_NOTIFY(40),
|
||||
CHARACTERISTIC_DOES_NOT_SUPPORT_INDICATE(41),
|
||||
NOT_PAIRED(42),
|
||||
NOT_PAIRABLE(43),
|
||||
ALREADY_PAIRED(44),
|
||||
PAIRING_FAILED(45),
|
||||
PAIRING_CANCELLED(46),
|
||||
PAIRING_TIMEOUT(47),
|
||||
PAIRING_NOT_ALLOWED(48),
|
||||
AUTHENTICATION_FAILURE(49),
|
||||
INSUFFICIENT_AUTHENTICATION(50),
|
||||
INSUFFICIENT_AUTHORIZATION(51),
|
||||
INSUFFICIENT_ENCRYPTION(52),
|
||||
INSUFFICIENT_KEY_SIZE(53),
|
||||
PROTECTION_LEVEL_NOT_MET(54),
|
||||
ACCESS_DENIED(55),
|
||||
UNPAIRING_FAILED(56),
|
||||
ALREADY_UNPAIRED(57),
|
||||
SCAN_FAILED(58),
|
||||
STOPPING_SCAN_IN_PROGRESS(59),
|
||||
WEB_BLUETOOTH_GLOBALLY_DISABLED(60);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): UniversalBleErrorCode? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBleScanResult (
|
||||
val deviceId: String,
|
||||
@@ -78,6 +183,16 @@ data class UniversalBleScanResult (
|
||||
services,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleScanResult) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -99,6 +214,16 @@ data class UniversalBleService (
|
||||
characteristics,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleService) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -120,6 +245,16 @@ data class UniversalBleCharacteristic (
|
||||
properties,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleCharacteristic) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +283,16 @@ data class UniversalScanFilter (
|
||||
withManufacturerData,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalScanFilter) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -172,6 +317,16 @@ data class UniversalManufacturerDataFilter (
|
||||
mask,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerDataFilter) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -193,36 +348,51 @@ data class UniversalManufacturerData (
|
||||
data,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerData) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
}
|
||||
private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalBleScanResult.fromList(it)
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
UniversalBleErrorCode.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
130.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalBleService.fromList(it)
|
||||
UniversalBleScanResult.fromList(it)
|
||||
}
|
||||
}
|
||||
131.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalBleCharacteristic.fromList(it)
|
||||
UniversalBleService.fromList(it)
|
||||
}
|
||||
}
|
||||
132.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanFilter.fromList(it)
|
||||
UniversalBleCharacteristic.fromList(it)
|
||||
}
|
||||
}
|
||||
133.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
UniversalScanFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
134.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
135.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerData.fromList(it)
|
||||
}
|
||||
@@ -232,30 +402,34 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is UniversalBleScanResult -> {
|
||||
is UniversalBleErrorCode -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.toList())
|
||||
writeValue(stream, value.raw.toLong())
|
||||
}
|
||||
is UniversalBleService -> {
|
||||
is UniversalBleScanResult -> {
|
||||
stream.write(130)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalBleCharacteristic -> {
|
||||
is UniversalBleService -> {
|
||||
stream.write(131)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanFilter -> {
|
||||
is UniversalBleCharacteristic -> {
|
||||
stream.write(132)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
is UniversalScanFilter -> {
|
||||
stream.write(133)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
stream.write(134)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
stream.write(135)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
@@ -302,10 +476,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.getBluetoothAvailabilityState{ result: Result<Long> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,10 +494,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.enableBluetooth{ result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,10 +512,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.disableBluetooth{ result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,7 +533,7 @@ interface UniversalBlePlatformChannel {
|
||||
api.startScan(filterArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -375,7 +549,7 @@ interface UniversalBlePlatformChannel {
|
||||
api.stopScan()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -393,7 +567,7 @@ interface UniversalBlePlatformChannel {
|
||||
api.connect(deviceIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -411,7 +585,7 @@ interface UniversalBlePlatformChannel {
|
||||
api.disconnect(deviceIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -431,9 +605,9 @@ interface UniversalBlePlatformChannel {
|
||||
api.setNotifiable(deviceIdArg, serviceArg, characteristicArg, bleInputPropertyArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(wrapResult(null))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -450,10 +624,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.discoverServices(deviceIdArg) { result: Result<List<UniversalBleService>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -472,10 +646,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.readValue(deviceIdArg, serviceArg, characteristicArg) { result: Result<ByteArray> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,10 +667,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.requestMtu(deviceIdArg, expectedMtuArg) { result: Result<Long> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,9 +691,9 @@ interface UniversalBlePlatformChannel {
|
||||
api.writeValue(deviceIdArg, serviceArg, characteristicArg, valueArg, bleOutputPropertyArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(wrapResult(null))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -536,10 +710,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.isPaired(deviceIdArg) { result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,10 +730,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.pair(deviceIdArg) { result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,7 +751,7 @@ interface UniversalBlePlatformChannel {
|
||||
api.unPair(deviceIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -594,10 +768,10 @@ interface UniversalBlePlatformChannel {
|
||||
api.getSystemDevices(withServicesArg) { result: Result<List<UniversalBleScanResult>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(wrapResult(data))
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -614,7 +788,7 @@ interface UniversalBlePlatformChannel {
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getConnectionState(deviceIdArg))
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
@@ -650,7 +824,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(createConnectionError(channelName)))
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -667,7 +841,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(createConnectionError(channelName)))
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -684,7 +858,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(createConnectionError(channelName)))
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -701,7 +875,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(createConnectionError(channelName)))
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -718,7 +892,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(createConnectionError(channelName)))
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,8 @@ package com.navideck.universal_ble
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.os.ParcelUuid
|
||||
import android.util.Log
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.util.UUID
|
||||
import kotlin.experimental.and
|
||||
|
||||
@@ -46,7 +43,7 @@ class UniversalBleFilterUtil {
|
||||
}
|
||||
|
||||
private fun isNameMatchingFilters(scanFilter: UniversalScanFilter, name: String?): Boolean {
|
||||
val namePrefixFilter = scanFilter.withNamePrefix.filterNotNull()
|
||||
val namePrefixFilter = scanFilter.withNamePrefix
|
||||
if (namePrefixFilter.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
@@ -74,7 +71,7 @@ class UniversalBleFilterUtil {
|
||||
scanFilter: UniversalScanFilter,
|
||||
manufacturerDataList: List<UniversalManufacturerData>,
|
||||
): Boolean {
|
||||
val filters = scanFilter.withManufacturerData.filterNotNull()
|
||||
val filters = scanFilter.withManufacturerData
|
||||
if (filters.isEmpty()) return true
|
||||
if (manufacturerDataList.isEmpty()) return false
|
||||
return manufacturerDataList.any { msd ->
|
||||
@@ -122,8 +119,8 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.toString())
|
||||
throw FlutterError(
|
||||
"illegalIllegalArgument",
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.INVALID_SERVICE_UUID,
|
||||
"Invalid serviceId: $service",
|
||||
e.toString()
|
||||
)
|
||||
@@ -133,7 +130,7 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
||||
// Add ManufacturerData Filter
|
||||
for (manufacturerData in this.withManufacturerData) {
|
||||
try {
|
||||
manufacturerData?.companyIdentifier?.let {
|
||||
manufacturerData.companyIdentifier.let {
|
||||
val data: ByteArray = manufacturerData.data ?: ByteArray(0)
|
||||
val mask: ByteArray? = manufacturerData.mask
|
||||
if (mask == null) {
|
||||
@@ -152,9 +149,9 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.toString())
|
||||
throw FlutterError(
|
||||
"illegalIllegalArgument",
|
||||
"Invalid manufacturerData: ${manufacturerData?.companyIdentifier} ${manufacturerData?.data} ${manufacturerData?.mask}",
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Invalid manufacturerData: ${manufacturerData.companyIdentifier} ${manufacturerData.data} ${manufacturerData.mask}",
|
||||
e.toString()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import android.util.SparseArray
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.util.UUID
|
||||
import androidx.core.util.size
|
||||
|
||||
private const val TAG = "UniversalBlePlugin"
|
||||
|
||||
@@ -46,8 +47,8 @@ enum class BleInputProperty(val value: Long) {
|
||||
}
|
||||
|
||||
enum class BleOutputProperty(val value: Long) {
|
||||
withResponse(0),
|
||||
withoutResponse(1);
|
||||
WithResponse(0),
|
||||
WithoutResponse(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +81,10 @@ fun List<String>.toUUIDList(): List<UUID> {
|
||||
|
||||
fun String.toBluetoothGatt(): BluetoothGatt {
|
||||
return this.findGatt()
|
||||
?: throw FlutterError("IllegalArgument", "Unknown deviceId: $this", null)
|
||||
?: throw createFlutterError(
|
||||
UniversalBleErrorCode.DEVICE_NOT_FOUND,
|
||||
"Unknown deviceId: $this",
|
||||
)
|
||||
}
|
||||
|
||||
fun String.isKnownGatt(): Boolean {
|
||||
@@ -122,53 +126,6 @@ fun Int.parseScanErrorMessage(): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.parseBluetoothStatusCodeError(): String? {
|
||||
if (this == BluetoothStatusCodes.SUCCESS) return null
|
||||
return when (this) {
|
||||
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED -> "ERROR_BLUETOOTH_NOT_ENABLED"
|
||||
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED -> "ERROR_BLUETOOTH_NOT_ALLOWED"
|
||||
BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED -> "ERROR_DEVICE_NOT_BONDED"
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED -> "ERROR_GATT_WRITE_NOT_ALLOWED"
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY -> "ERROR_GATT_WRITE_REQUEST_BUSY"
|
||||
BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION -> "ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION"
|
||||
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND -> "ERROR_PROFILE_SERVICE_NOT_BOUND"
|
||||
BluetoothStatusCodes.ERROR_UNKNOWN -> "ERROR_UNKNOWN"
|
||||
BluetoothStatusCodes.FEATURE_NOT_CONFIGURED -> "FEATURE_NOT_CONFIGURED"
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED -> "FEATURE_NOT_SUPPORTED"
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED -> "FEATURE_SUPPORTED"
|
||||
else -> "ErrorCode: $this"
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED -> "ERROR_GATT_WRITE_NOT_ALLOWED"
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY -> "ERROR_GATT_WRITE_REQUEST_BUSY"
|
||||
BluetoothStatusCodes.FEATURE_NOT_CONFIGURED -> "FEATURE_NOT_CONFIGURED"
|
||||
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.manufacturerDataList: List<UniversalManufacturerData>
|
||||
get() {
|
||||
return scanRecord?.manufacturerSpecificData?.toList()?.map { (key, value) ->
|
||||
@@ -177,7 +134,7 @@ val ScanResult.manufacturerDataList: List<UniversalManufacturerData>
|
||||
}
|
||||
|
||||
fun <T> SparseArray<T>.toList(): List<Pair<Int, T>> {
|
||||
return (0 until size()).map { index ->
|
||||
return (0 until size).map { index ->
|
||||
keyAt(index) to valueAt(index)
|
||||
}
|
||||
}
|
||||
@@ -189,16 +146,6 @@ fun BluetoothGatt.getCharacteristic(
|
||||
return getService(UUID.fromString(service))?.getCharacteristic(UUID.fromString(characteristic))
|
||||
}
|
||||
|
||||
fun subscriptionFailedError(error: String? = null): Result<Unit> {
|
||||
return Result.failure(
|
||||
FlutterError(
|
||||
"Failed",
|
||||
"Failed to update subscription state",
|
||||
error
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun BluetoothDevice.removeBond() {
|
||||
try {
|
||||
javaClass.getMethod("removeBond").invoke(this)
|
||||
@@ -207,7 +154,6 @@ fun BluetoothDevice.removeBond() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun BluetoothGattCharacteristic.getPropertiesList(): ArrayList<Long> {
|
||||
val propertiesList = arrayListOf<Long>()
|
||||
if (properties and BluetoothGattCharacteristic.PROPERTY_BROADCAST > 0) {
|
||||
@@ -241,16 +187,54 @@ fun BluetoothGattCharacteristic.getPropertiesList(): ArrayList<Long> {
|
||||
fun Short.toByteArray(byteOrder: ByteOrder = ByteOrder.LITTLE_ENDIAN): ByteArray =
|
||||
ByteBuffer.allocate(2 /*Short.SIZE_BYTES*/).order(byteOrder).putShort(this).array()
|
||||
|
||||
// Errors
|
||||
fun unknownCharacteristicError(char: String) =
|
||||
FlutterError("IllegalArgument", "Unknown error", null)
|
||||
|
||||
fun createFlutterError(
|
||||
code: UniversalBleErrorCode,
|
||||
message: String? = null,
|
||||
details: String? = null,
|
||||
) = FlutterError(code.raw.toString(), message, details ?: code.toString())
|
||||
|
||||
val DeviceDisconnectedError: FlutterError = FlutterError(
|
||||
"DeviceDisconnected",
|
||||
"Device Disconnected",
|
||||
null
|
||||
)
|
||||
fun gattStatusToUniversalBleErrorCode(code: Int): UniversalBleErrorCode {
|
||||
return when (code) {
|
||||
BluetoothGatt.GATT_READ_NOT_PERMITTED -> UniversalBleErrorCode.READ_NOT_PERMITTED
|
||||
BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> UniversalBleErrorCode.WRITE_NOT_PERMITTED
|
||||
BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION -> UniversalBleErrorCode.INSUFFICIENT_AUTHENTICATION
|
||||
BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION -> UniversalBleErrorCode.INSUFFICIENT_AUTHORIZATION
|
||||
BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION -> UniversalBleErrorCode.INSUFFICIENT_ENCRYPTION
|
||||
BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED -> UniversalBleErrorCode.OPERATION_NOT_SUPPORTED
|
||||
BluetoothGatt.GATT_INVALID_OFFSET -> UniversalBleErrorCode.INVALID_OFFSET
|
||||
BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH -> UniversalBleErrorCode.INVALID_ATTRIBUTE_LENGTH
|
||||
BluetoothGatt.GATT_CONNECTION_CONGESTED -> UniversalBleErrorCode.CONNECTION_FAILED
|
||||
BluetoothGatt.GATT_FAILURE -> UniversalBleErrorCode.FAILED
|
||||
0x01 -> UniversalBleErrorCode.INVALID_HANDLE
|
||||
0x04 -> UniversalBleErrorCode.INVALID_PDU
|
||||
0x09 -> UniversalBleErrorCode.OPERATION_IN_PROGRESS
|
||||
0x0a -> UniversalBleErrorCode.SERVICE_NOT_FOUND
|
||||
0x0b -> UniversalBleErrorCode.INVALID_ATTRIBUTE_LENGTH
|
||||
0x0c -> UniversalBleErrorCode.INSUFFICIENT_KEY_SIZE
|
||||
0x0e -> UniversalBleErrorCode.FAILED
|
||||
0x10 -> UniversalBleErrorCode.OPERATION_NOT_SUPPORTED
|
||||
0x11 -> UniversalBleErrorCode.FAILED
|
||||
else -> UniversalBleErrorCode.UNKNOWN_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.parseBluetoothStatusCodeError(): UniversalBleErrorCode? {
|
||||
if (this == BluetoothStatusCodes.SUCCESS) return null
|
||||
return when (this) {
|
||||
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED -> UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED
|
||||
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED -> UniversalBleErrorCode.BLUETOOTH_NOT_ALLOWED
|
||||
BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED -> UniversalBleErrorCode.NOT_PAIRED
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED -> UniversalBleErrorCode.WRITE_NOT_PERMITTED
|
||||
BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY -> UniversalBleErrorCode.WRITE_REQUEST_BUSY
|
||||
BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION -> UniversalBleErrorCode.CONNECTION_FAILED
|
||||
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND -> UniversalBleErrorCode.SERVICE_NOT_FOUND
|
||||
BluetoothStatusCodes.ERROR_UNKNOWN -> UniversalBleErrorCode.UNKNOWN_ERROR
|
||||
BluetoothStatusCodes.FEATURE_NOT_CONFIGURED -> UniversalBleErrorCode.NOT_IMPLEMENTED
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED -> UniversalBleErrorCode.NOT_SUPPORTED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.parseHciErrorCode(): String? {
|
||||
return when (this) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import io.flutter.plugin.common.PluginRegistry
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import androidx.core.content.edit
|
||||
|
||||
|
||||
private const val TAG = "UniversalBlePlugin"
|
||||
@@ -102,7 +103,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (bluetoothEnableRequestFuture != null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError("Failed", "Bluetooth enable request in progress", null)
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||
"Bluetooth enable request in progress"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
@@ -120,7 +124,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (bluetoothDisableRequestFuture != null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError("Failed", "Bluetooth disable request in progress", null)
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||
"Bluetooth disable request in progress"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
@@ -131,9 +138,9 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
|
||||
override fun startScan(filter: UniversalScanFilter?) {
|
||||
if (!isBluetoothAvailable()) throw FlutterError(
|
||||
"BluetoothNotEnabled",
|
||||
"Bluetooth not enabled",
|
||||
if (!isBluetoothAvailable()) throw createFlutterError(
|
||||
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||
"Bluetooth not enabled"
|
||||
)
|
||||
|
||||
val builder = ScanSettings.Builder()
|
||||
@@ -143,10 +150,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
val settings = builder.build()
|
||||
|
||||
val usesCustomFilters = filter?.usesCustomFilters() ?: false;
|
||||
val usesCustomFilters = filter?.usesCustomFilters() ?: false
|
||||
|
||||
try {
|
||||
val filterServices = filter?.withServices?.filterNotNull()?.toUUIDList() ?: emptyList()
|
||||
val filterServices = filter?.withServices?.toUUIDList() ?: emptyList()
|
||||
var scanFilters = emptyList<ScanFilter>()
|
||||
|
||||
// Set custom scan filter only if required
|
||||
@@ -156,25 +163,25 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
universalBleFilterUtil.serviceFilterUUIDS = filterServices
|
||||
} else {
|
||||
universalBleFilterUtil.scanFilter = null
|
||||
scanFilters = filter?.toScanFilters(filterServices) ?: emptyList<ScanFilter>()
|
||||
scanFilters = filter?.toScanFilters(filterServices) ?: emptyList()
|
||||
}
|
||||
|
||||
safeScanner.startScan(
|
||||
scanFilters, settings, scanCallback
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
throw FlutterError(
|
||||
"illegalIllegalArgument",
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to start Scan",
|
||||
e.toString()
|
||||
details = e.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun stopScan() {
|
||||
if (!isBluetoothAvailable()) throw FlutterError(
|
||||
"BluetoothNotEnabled",
|
||||
"Bluetooth not enabled",
|
||||
if (!isBluetoothAvailable()) throw createFlutterError(
|
||||
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||
"Bluetooth not enabled"
|
||||
)
|
||||
// check if already scanning
|
||||
safeScanner.stopScan(scanCallback)
|
||||
@@ -192,7 +199,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
return
|
||||
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
||||
throw FlutterError("Connecting", "Connection already in progress", null)
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.CONNECTION_IN_PROGRESS,
|
||||
"Connection already in progress"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +250,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
discoverServicesFutureList.add(DiscoverServicesFuture(deviceId, callback))
|
||||
} else {
|
||||
callback(
|
||||
Result.failure(FlutterError("Failed", "Failed to discover services", null))
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to discover services"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: FlutterError) {
|
||||
@@ -253,7 +268,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
discoverServicesFutureList.filter { it.deviceId == gatt.device.address }.forEach {
|
||||
discoverServicesFutureList.remove(it)
|
||||
it.result(
|
||||
Result.failure(FlutterError("Failed", "Failed to discover services", null))
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to discover services"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
return
|
||||
@@ -290,7 +310,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
gatt.getCharacteristic(service, characteristic)
|
||||
|
||||
if (gattCharacteristic == null) {
|
||||
callback(subscriptionFailedError("characteristic not found"))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"characteristic not found"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -298,7 +325,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
gattCharacteristic.getDescriptor(ccdCharacteristic)
|
||||
|
||||
val bleInputPropertyEnum: BleInputProperty =
|
||||
BleInputProperty.values().first { it.value == bleInputProperty }
|
||||
BleInputProperty.entries.first { it.value == bleInputProperty }
|
||||
|
||||
val (value, enable) = when (bleInputPropertyEnum) {
|
||||
BleInputProperty.Notification -> BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE to true
|
||||
@@ -310,14 +337,30 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
// Some devices do not need CCCD to update
|
||||
@Suppress("DEPRECATION")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val status = gatt.writeDescriptor(descriptor, value)
|
||||
if (gatt.writeDescriptor(descriptor, value) != BluetoothStatusCodes.SUCCESS) {
|
||||
callback(subscriptionFailedError("Failed to update descriptor"))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
status.parseBluetoothStatusCodeError()
|
||||
?: UniversalBleErrorCode.FAILED,
|
||||
"Failed to update descriptor"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
descriptor.value = value
|
||||
if (!gatt.writeDescriptor(descriptor)) {
|
||||
callback(subscriptionFailedError("Failed to update descriptor"))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to update descriptor"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -339,12 +382,27 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(subscriptionFailedError())
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to update subscription state"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: FlutterError) {
|
||||
callback(Result.failure(e))
|
||||
} catch (e: Exception) {
|
||||
callback(subscriptionFailedError(e.toString()))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to update subscription state",
|
||||
e.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,13 +417,23 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
val gattCharacteristic = gatt.getCharacteristic(service, characteristic)
|
||||
if (gattCharacteristic == null) {
|
||||
callback(
|
||||
Result.failure(FlutterError("IllegalArgument", "Unknown characteristic", null))
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"Unknown characteristic"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!gatt.readCharacteristic(gattCharacteristic)) {
|
||||
callback(
|
||||
Result.failure(unknownCharacteristicError(characteristic))
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"$characteristic not found",
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -383,8 +451,8 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
} catch (e: Exception) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
"Failed",
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.READ_FAILED,
|
||||
"Failed to read value",
|
||||
e.toString()
|
||||
)
|
||||
@@ -410,10 +478,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
} else {
|
||||
it.result(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
status.toString(),
|
||||
"Failed to read: (${status.parseGattErrorCode()})",
|
||||
null,
|
||||
createFlutterError(
|
||||
gattStatusToUniversalBleErrorCode(status),
|
||||
"Failed to read",
|
||||
status.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -434,33 +502,38 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
val gatt = deviceId.toBluetoothGatt()
|
||||
val gattCharacteristic = gatt.getCharacteristic(service, characteristic)
|
||||
if (gattCharacteristic == null) {
|
||||
callback(Result.failure(unknownCharacteristicError(characteristic)))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"$characteristic not found",
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
if (bleOutputProperty == BleOutputProperty.withResponse.value) {
|
||||
if (bleOutputProperty == BleOutputProperty.WithResponse.value) {
|
||||
if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE == 0) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
"IllegalArgument",
|
||||
"Characteristic does not support write withResponse",
|
||||
null
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE,
|
||||
"Characteristic does not support write withResponse"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
} else if (bleOutputProperty == BleOutputProperty.withoutResponse.value) {
|
||||
} else if (bleOutputProperty == BleOutputProperty.WithoutResponse.value) {
|
||||
if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE == 0) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
"IllegalArgument",
|
||||
"Characteristic does not support write withoutResponse",
|
||||
null
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE_WITHOUT_RESPONSE,
|
||||
"Characteristic does not support write withoutResponse"
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -495,10 +568,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
writeResultFutureList.remove(writeFuture)
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
"WriteError",
|
||||
"Failed to write: ${result.parseGattErrorCode()}",
|
||||
null
|
||||
createFlutterError(
|
||||
gattStatusToUniversalBleErrorCode(result),
|
||||
"Failed to write",
|
||||
result.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -524,10 +597,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
} else {
|
||||
it.result(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
status.toString(),
|
||||
"Failed to write: (${status.parseGattErrorCode()})",
|
||||
null,
|
||||
createFlutterError(
|
||||
gattStatusToUniversalBleErrorCode(status),
|
||||
"Failed to write",
|
||||
status.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -553,7 +626,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
it.result(Result.success(mtu.toLong()))
|
||||
} else {
|
||||
it.result(Result.failure(FlutterError("Failed to change MTU", null, null)))
|
||||
it.result(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to change MTU"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -580,10 +660,9 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (pendingFuture != null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
"InProgress",
|
||||
"Pairing already in progress",
|
||||
null
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||
"Pairing already in progress"
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -594,12 +673,19 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (remoteDevice.createBond()) {
|
||||
pairResultFutures[deviceId] = callback
|
||||
} else {
|
||||
callback(Result.failure(FlutterError("Failed", "Failed to pair", null)))
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.PAIRING_FAILED,
|
||||
"Failed to pair"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
callback(
|
||||
Result.failure(
|
||||
FlutterError("Failed", e.toString(), null)
|
||||
createFlutterError(UniversalBleErrorCode.FAILED, e.toString())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -664,7 +750,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
try {
|
||||
val timeout = (devices.size * 2).toLong()
|
||||
latch.await(timeout, TimeUnit.SECONDS)
|
||||
} catch (e: InterruptedException) {
|
||||
} catch (_: InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
|
||||
@@ -749,10 +835,13 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
private fun cleanConnection(gatt: BluetoothGatt) {
|
||||
gatt.removeCache()
|
||||
gatt.disconnect()
|
||||
|
||||
val deviceDisconnectedError: FlutterError = createFlutterError(
|
||||
UniversalBleErrorCode.DEVICE_DISCONNECTED,
|
||||
"Device Disconnected",
|
||||
)
|
||||
readResultFutureList.removeAll {
|
||||
if (it.deviceId == gatt.device.address) {
|
||||
it.result(Result.failure(DeviceDisconnectedError))
|
||||
it.result(Result.failure(deviceDisconnectedError))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -760,7 +849,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
writeResultFutureList.removeAll {
|
||||
if (it.deviceId == gatt.device.address) {
|
||||
it.result(Result.failure(DeviceDisconnectedError))
|
||||
it.result(Result.failure(deviceDisconnectedError))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -768,7 +857,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
subscriptionResultFutureList.removeAll {
|
||||
if (it.deviceId == gatt.device.address) {
|
||||
it.result(Result.failure(DeviceDisconnectedError))
|
||||
it.result(Result.failure(deviceDisconnectedError))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -776,7 +865,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
mtuResultFutureList.removeAll {
|
||||
if (it.deviceId == gatt.device.address) {
|
||||
it.result(Result.failure(DeviceDisconnectedError))
|
||||
it.result(Result.failure(deviceDisconnectedError))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -784,7 +873,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
discoverServicesFutureList.removeAll {
|
||||
if (it.deviceId == gatt.device.address) {
|
||||
it.result(Result.failure(DeviceDisconnectedError))
|
||||
it.result(Result.failure(deviceDisconnectedError))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -830,7 +919,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
Log.v(TAG, "${device.address} BOND_BONDING")
|
||||
}
|
||||
|
||||
BluetoothDevice.BOND_BONDED -> {
|
||||
BOND_BONDED -> {
|
||||
onBondStateUpdate(device.address, true)
|
||||
}
|
||||
|
||||
@@ -944,7 +1033,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (descriptor?.uuid.toString() == ccdCharacteristic.toString()) {
|
||||
val char: String? = descriptor?.characteristic?.uuid?.toString()
|
||||
val service: String? = descriptor?.characteristic?.service?.uuid?.toString()
|
||||
val deviceId: String? = gatt?.device?.address;
|
||||
val deviceId: String? = gatt?.device?.address
|
||||
if (deviceId != null && char != null && service != null) {
|
||||
updateSubscriptionState(deviceId, char, service, status)
|
||||
}
|
||||
@@ -963,14 +1052,13 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
it.serviceId == service
|
||||
}.forEach {
|
||||
subscriptionResultFutureList.remove(it)
|
||||
val error: String? = status.parseGattErrorCode()
|
||||
if (error != null) {
|
||||
if (status != BluetoothGatt.GATT_SUCCESS) {
|
||||
it.result(
|
||||
Result.failure(
|
||||
FlutterError(
|
||||
status.toString(),
|
||||
"Failed to update subscription state: $error",
|
||||
null,
|
||||
createFlutterError(
|
||||
gattStatusToUniversalBleErrorCode(status),
|
||||
"Failed to update subscription state",
|
||||
status.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -989,7 +1077,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
"com.navideck.universal_ble.services",
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
cachedServicesSharedPref.edit().putStringSet(deviceId, services.toSet()).apply()
|
||||
cachedServicesSharedPref.edit { putStringSet(deviceId, services.toSet()) }
|
||||
cachedServicesMap[deviceId] = services
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user