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,3 +1,6 @@
|
|||||||
|
## 1.0.0
|
||||||
|
* Unified error codes for all platforms
|
||||||
|
|
||||||
## 0.21.1
|
## 0.21.1
|
||||||
* Fix device name resolution on Windows
|
* Fix device name resolution on Windows
|
||||||
* Add `exclusionFilters` to filter out devices from scan results
|
* Add `exclusionFilters` to filter out devices from scan results
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
|
|||||||
- [Requesting MTU](#requesting-mtu)
|
- [Requesting MTU](#requesting-mtu)
|
||||||
- [Command Queue](#command-queue)
|
- [Command Queue](#command-queue)
|
||||||
- [Timeout](#timeout)
|
- [Timeout](#timeout)
|
||||||
|
- [Error Handling](#error-handling)
|
||||||
- [UUID Format Agnostic](#uuid-format-agnostic)
|
- [UUID Format Agnostic](#uuid-format-agnostic)
|
||||||
|
|
||||||
## API Support
|
## API Support
|
||||||
@@ -456,6 +457,56 @@ UniversalBle.timeout = null;
|
|||||||
|
|
||||||
You can also specify the `timeout` parameter when sending a command. This will override the global timeout.
|
You can also specify the `timeout` parameter when sending a command. This will override the global timeout.
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Universal BLE provides a unified and type-safe error handling system across all platforms. All errors are represented using the `UniversalBleException` base class with typed error codes from the `UniversalBleErrorCode` enum.
|
||||||
|
|
||||||
|
### Exception Types
|
||||||
|
|
||||||
|
- **`UniversalBleException`**: Base exception class for all BLE errors
|
||||||
|
- **`ConnectionException`**: Thrown for connection-related errors
|
||||||
|
- **`PairingException`**: Thrown for pairing-related errors
|
||||||
|
- **`WebBluetoothGloballyDisabled`**: Thrown when Web Bluetooth is globally disabled
|
||||||
|
|
||||||
|
### Error Codes
|
||||||
|
|
||||||
|
All errors are categorized using the `UniversalBleErrorCode` enum, which includes codes for:
|
||||||
|
- Connection errors (timeout, failed, rejected, etc.)
|
||||||
|
- Pairing errors (failed, cancelled, not allowed, etc.)
|
||||||
|
- Operation errors (not supported, timeout, cancelled, etc.)
|
||||||
|
- Permission errors (not allowed, unauthorized, access denied, etc.)
|
||||||
|
- Device errors (not found, disconnected, etc.)
|
||||||
|
- Service/Characteristic errors (not found, invalid UUID, etc.)
|
||||||
|
- And many more...
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```dart
|
||||||
|
try {
|
||||||
|
await bleDevice.connect();
|
||||||
|
} on ConnectionException catch (e) {
|
||||||
|
// Handle connection-specific errors
|
||||||
|
switch (e.code) {
|
||||||
|
case UniversalBleErrorCode.connectionTimeout:
|
||||||
|
// Handle timeout
|
||||||
|
break;
|
||||||
|
case UniversalBleErrorCode.connectionFailed:
|
||||||
|
// Handle connection failure
|
||||||
|
break;
|
||||||
|
case UniversalBleErrorCode.deviceDisconnected:
|
||||||
|
// Handle disconnection
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handle other connection errors
|
||||||
|
}
|
||||||
|
} on UniversalBleException catch (e) {
|
||||||
|
// Handle other BLE errors
|
||||||
|
print('Error code: ${e.code}, Message: ${e.message}');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The error parser automatically converts platform-specific error formats (strings, numeric codes, PlatformExceptions) into the unified `UniversalBleErrorCode` enum, ensuring consistent error handling across all platforms.
|
||||||
|
|
||||||
## UUID Format Agnostic
|
## UUID Format Agnostic
|
||||||
|
|
||||||
Universal BLE is agnostic to the UUID format of services and characteristics regardless of the platform the app runs on. When passing a UUID, you can pass it in any format (long/short) or character case (upper/lower case) you want. Universal BLE will take care of necessary conversions, across all platforms, so that you don't need to worry about underlying platform differences.
|
Universal BLE is agnostic to the UUID format of services and characteristics regardless of the platform the app runs on. When passing a UUID, you can pass it in any format (long/short) or character case (upper/lower case) you want. Universal BLE will take care of necessary conversions, across all platforms, so that you don't need to worry about underlying platform differences.
|
||||||
|
|||||||
@@ -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
|
// See also: https://pub.dev/packages/pigeon
|
||||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||||
|
|
||||||
@@ -7,16 +7,22 @@ package com.navideck.universal_ble
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import io.flutter.plugin.common.BasicMessageChannel
|
import io.flutter.plugin.common.BasicMessageChannel
|
||||||
import io.flutter.plugin.common.BinaryMessenger
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import io.flutter.plugin.common.EventChannel
|
||||||
import io.flutter.plugin.common.MessageCodec
|
import io.flutter.plugin.common.MessageCodec
|
||||||
|
import io.flutter.plugin.common.StandardMethodCodec
|
||||||
import io.flutter.plugin.common.StandardMessageCodec
|
import io.flutter.plugin.common.StandardMessageCodec
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
private object UniversalBlePigeonUtils {
|
||||||
|
|
||||||
private fun wrapResult(result: Any?): List<Any?> {
|
fun createConnectionError(channelName: String): FlutterError {
|
||||||
|
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") }
|
||||||
|
|
||||||
|
fun wrapResult(result: Any?): List<Any?> {
|
||||||
return listOf(result)
|
return listOf(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wrapError(exception: Throwable): List<Any?> {
|
fun wrapError(exception: Throwable): List<Any?> {
|
||||||
return if (exception is FlutterError) {
|
return if (exception is FlutterError) {
|
||||||
listOf(
|
listOf(
|
||||||
exception.code,
|
exception.code,
|
||||||
@@ -30,10 +36,38 @@ private fun wrapError(exception: Throwable): List<Any?> {
|
|||||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
private fun createConnectionError(channelName: String): FlutterError {
|
}
|
||||||
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "")}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
||||||
@@ -47,6 +81,77 @@ class FlutterError (
|
|||||||
val details: Any? = null
|
val details: Any? = null
|
||||||
) : Throwable()
|
) : 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. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
data class UniversalBleScanResult (
|
data class UniversalBleScanResult (
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
@@ -78,6 +183,16 @@ data class UniversalBleScanResult (
|
|||||||
services,
|
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. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
@@ -99,6 +214,16 @@ data class UniversalBleService (
|
|||||||
characteristics,
|
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. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
@@ -120,6 +245,16 @@ data class UniversalBleCharacteristic (
|
|||||||
properties,
|
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,
|
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. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
@@ -172,6 +317,16 @@ data class UniversalManufacturerDataFilter (
|
|||||||
mask,
|
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. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
@@ -193,36 +348,51 @@ data class UniversalManufacturerData (
|
|||||||
data,
|
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() {
|
private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
129.toByte() -> {
|
129.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as Long?)?.let {
|
||||||
UniversalBleScanResult.fromList(it)
|
UniversalBleErrorCode.ofRaw(it.toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
130.toByte() -> {
|
130.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
UniversalBleService.fromList(it)
|
UniversalBleScanResult.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
131.toByte() -> {
|
131.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
UniversalBleCharacteristic.fromList(it)
|
UniversalBleService.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
132.toByte() -> {
|
132.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
UniversalScanFilter.fromList(it)
|
UniversalBleCharacteristic.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
133.toByte() -> {
|
133.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
UniversalManufacturerDataFilter.fromList(it)
|
UniversalScanFilter.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
134.toByte() -> {
|
134.toByte() -> {
|
||||||
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
|
UniversalManufacturerDataFilter.fromList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
135.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
UniversalManufacturerData.fromList(it)
|
UniversalManufacturerData.fromList(it)
|
||||||
}
|
}
|
||||||
@@ -232,30 +402,34 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
|||||||
}
|
}
|
||||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||||
when (value) {
|
when (value) {
|
||||||
is UniversalBleScanResult -> {
|
is UniversalBleErrorCode -> {
|
||||||
stream.write(129)
|
stream.write(129)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.raw.toLong())
|
||||||
}
|
}
|
||||||
is UniversalBleService -> {
|
is UniversalBleScanResult -> {
|
||||||
stream.write(130)
|
stream.write(130)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is UniversalBleCharacteristic -> {
|
is UniversalBleService -> {
|
||||||
stream.write(131)
|
stream.write(131)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is UniversalScanFilter -> {
|
is UniversalBleCharacteristic -> {
|
||||||
stream.write(132)
|
stream.write(132)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is UniversalManufacturerDataFilter -> {
|
is UniversalScanFilter -> {
|
||||||
stream.write(133)
|
stream.write(133)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is UniversalManufacturerData -> {
|
is UniversalManufacturerDataFilter -> {
|
||||||
stream.write(134)
|
stream.write(134)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
|
is UniversalManufacturerData -> {
|
||||||
|
stream.write(135)
|
||||||
|
writeValue(stream, value.toList())
|
||||||
|
}
|
||||||
else -> super.writeValue(stream, value)
|
else -> super.writeValue(stream, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,10 +476,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.getBluetoothAvailabilityState{ result: Result<Long> ->
|
api.getBluetoothAvailabilityState{ result: Result<Long> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
val data = result.getOrNull()
|
||||||
reply.reply(wrapResult(data))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,10 +494,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.enableBluetooth{ result: Result<Boolean> ->
|
api.enableBluetooth{ result: Result<Boolean> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
val data = result.getOrNull()
|
||||||
reply.reply(wrapResult(data))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,10 +512,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.disableBluetooth{ result: Result<Boolean> ->
|
api.disableBluetooth{ result: Result<Boolean> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
val data = result.getOrNull()
|
||||||
reply.reply(wrapResult(data))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +533,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.startScan(filterArg)
|
api.startScan(filterArg)
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -375,7 +549,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.stopScan()
|
api.stopScan()
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -393,7 +567,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.connect(deviceIdArg)
|
api.connect(deviceIdArg)
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -411,7 +585,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.disconnect(deviceIdArg)
|
api.disconnect(deviceIdArg)
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -431,9 +605,9 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.setNotifiable(deviceIdArg, serviceArg, characteristicArg, bleInputPropertyArg) { result: Result<Unit> ->
|
api.setNotifiable(deviceIdArg, serviceArg, characteristicArg, bleInputPropertyArg) { result: Result<Unit> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
reply.reply(wrapResult(null))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -450,10 +624,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.discoverServices(deviceIdArg) { result: Result<List<UniversalBleService>> ->
|
api.discoverServices(deviceIdArg) { result: Result<List<UniversalBleService>> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
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> ->
|
api.readValue(deviceIdArg, serviceArg, characteristicArg) { result: Result<ByteArray> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
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> ->
|
api.requestMtu(deviceIdArg, expectedMtuArg) { result: Result<Long> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
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> ->
|
api.writeValue(deviceIdArg, serviceArg, characteristicArg, valueArg, bleOutputPropertyArg) { result: Result<Unit> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
reply.reply(wrapResult(null))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,10 +710,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.isPaired(deviceIdArg) { result: Result<Boolean> ->
|
api.isPaired(deviceIdArg) { result: Result<Boolean> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
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> ->
|
api.pair(deviceIdArg) { result: Result<Boolean> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
val data = result.getOrNull()
|
||||||
reply.reply(wrapResult(data))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,7 +751,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.unPair(deviceIdArg)
|
api.unPair(deviceIdArg)
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -594,10 +768,10 @@ interface UniversalBlePlatformChannel {
|
|||||||
api.getSystemDevices(withServicesArg) { result: Result<List<UniversalBleScanResult>> ->
|
api.getSystemDevices(withServicesArg) { result: Result<List<UniversalBleScanResult>> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(wrapError(error))
|
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||||
} else {
|
} else {
|
||||||
val data = result.getOrNull()
|
val data = result.getOrNull()
|
||||||
reply.reply(wrapResult(data))
|
reply.reply(UniversalBlePigeonUtils.wrapResult(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -614,7 +788,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
val wrapped: List<Any?> = try {
|
val wrapped: List<Any?> = try {
|
||||||
listOf(api.getConnectionState(deviceIdArg))
|
listOf(api.getConnectionState(deviceIdArg))
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
wrapError(exception)
|
UniversalBlePigeonUtils.wrapError(exception)
|
||||||
}
|
}
|
||||||
reply.reply(wrapped)
|
reply.reply(wrapped)
|
||||||
}
|
}
|
||||||
@@ -650,7 +824,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
|||||||
callback(Result.success(Unit))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} 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))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} 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))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} 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))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} 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))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} 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.annotation.SuppressLint
|
||||||
import android.bluetooth.le.ScanFilter
|
import android.bluetooth.le.ScanFilter
|
||||||
import android.bluetooth.le.ScanResult
|
|
||||||
import android.os.ParcelUuid
|
import android.os.ParcelUuid
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.ByteOrder
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
|
||||||
@@ -46,7 +43,7 @@ class UniversalBleFilterUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isNameMatchingFilters(scanFilter: UniversalScanFilter, name: String?): Boolean {
|
private fun isNameMatchingFilters(scanFilter: UniversalScanFilter, name: String?): Boolean {
|
||||||
val namePrefixFilter = scanFilter.withNamePrefix.filterNotNull()
|
val namePrefixFilter = scanFilter.withNamePrefix
|
||||||
if (namePrefixFilter.isEmpty()) {
|
if (namePrefixFilter.isEmpty()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -74,7 +71,7 @@ class UniversalBleFilterUtil {
|
|||||||
scanFilter: UniversalScanFilter,
|
scanFilter: UniversalScanFilter,
|
||||||
manufacturerDataList: List<UniversalManufacturerData>,
|
manufacturerDataList: List<UniversalManufacturerData>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val filters = scanFilter.withManufacturerData.filterNotNull()
|
val filters = scanFilter.withManufacturerData
|
||||||
if (filters.isEmpty()) return true
|
if (filters.isEmpty()) return true
|
||||||
if (manufacturerDataList.isEmpty()) return false
|
if (manufacturerDataList.isEmpty()) return false
|
||||||
return manufacturerDataList.any { msd ->
|
return manufacturerDataList.any { msd ->
|
||||||
@@ -122,8 +119,8 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, e.toString())
|
Log.e(TAG, e.toString())
|
||||||
throw FlutterError(
|
throw createFlutterError(
|
||||||
"illegalIllegalArgument",
|
UniversalBleErrorCode.INVALID_SERVICE_UUID,
|
||||||
"Invalid serviceId: $service",
|
"Invalid serviceId: $service",
|
||||||
e.toString()
|
e.toString()
|
||||||
)
|
)
|
||||||
@@ -133,7 +130,7 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
|||||||
// Add ManufacturerData Filter
|
// Add ManufacturerData Filter
|
||||||
for (manufacturerData in this.withManufacturerData) {
|
for (manufacturerData in this.withManufacturerData) {
|
||||||
try {
|
try {
|
||||||
manufacturerData?.companyIdentifier?.let {
|
manufacturerData.companyIdentifier.let {
|
||||||
val data: ByteArray = manufacturerData.data ?: ByteArray(0)
|
val data: ByteArray = manufacturerData.data ?: ByteArray(0)
|
||||||
val mask: ByteArray? = manufacturerData.mask
|
val mask: ByteArray? = manufacturerData.mask
|
||||||
if (mask == null) {
|
if (mask == null) {
|
||||||
@@ -152,9 +149,9 @@ fun UniversalScanFilter.toScanFilters(serviceUuids: List<UUID>): List<ScanFilter
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, e.toString())
|
Log.e(TAG, e.toString())
|
||||||
throw FlutterError(
|
throw createFlutterError(
|
||||||
"illegalIllegalArgument",
|
UniversalBleErrorCode.FAILED,
|
||||||
"Invalid manufacturerData: ${manufacturerData?.companyIdentifier} ${manufacturerData?.data} ${manufacturerData?.mask}",
|
"Invalid manufacturerData: ${manufacturerData.companyIdentifier} ${manufacturerData.data} ${manufacturerData.mask}",
|
||||||
e.toString()
|
e.toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import android.util.SparseArray
|
|||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.ByteOrder
|
import java.nio.ByteOrder
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import androidx.core.util.size
|
||||||
|
|
||||||
private const val TAG = "UniversalBlePlugin"
|
private const val TAG = "UniversalBlePlugin"
|
||||||
|
|
||||||
@@ -46,8 +47,8 @@ enum class BleInputProperty(val value: Long) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class BleOutputProperty(val value: Long) {
|
enum class BleOutputProperty(val value: Long) {
|
||||||
withResponse(0),
|
WithResponse(0),
|
||||||
withoutResponse(1);
|
WithoutResponse(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +81,10 @@ fun List<String>.toUUIDList(): List<UUID> {
|
|||||||
|
|
||||||
fun String.toBluetoothGatt(): BluetoothGatt {
|
fun String.toBluetoothGatt(): BluetoothGatt {
|
||||||
return this.findGatt()
|
return this.findGatt()
|
||||||
?: throw FlutterError("IllegalArgument", "Unknown deviceId: $this", null)
|
?: throw createFlutterError(
|
||||||
|
UniversalBleErrorCode.DEVICE_NOT_FOUND,
|
||||||
|
"Unknown deviceId: $this",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.isKnownGatt(): Boolean {
|
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>
|
val ScanResult.manufacturerDataList: List<UniversalManufacturerData>
|
||||||
get() {
|
get() {
|
||||||
return scanRecord?.manufacturerSpecificData?.toList()?.map { (key, value) ->
|
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>> {
|
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)
|
keyAt(index) to valueAt(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,16 +146,6 @@ fun BluetoothGatt.getCharacteristic(
|
|||||||
return getService(UUID.fromString(service))?.getCharacteristic(UUID.fromString(characteristic))
|
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() {
|
fun BluetoothDevice.removeBond() {
|
||||||
try {
|
try {
|
||||||
javaClass.getMethod("removeBond").invoke(this)
|
javaClass.getMethod("removeBond").invoke(this)
|
||||||
@@ -207,7 +154,6 @@ fun BluetoothDevice.removeBond() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun BluetoothGattCharacteristic.getPropertiesList(): ArrayList<Long> {
|
fun BluetoothGattCharacteristic.getPropertiesList(): ArrayList<Long> {
|
||||||
val propertiesList = arrayListOf<Long>()
|
val propertiesList = arrayListOf<Long>()
|
||||||
if (properties and BluetoothGattCharacteristic.PROPERTY_BROADCAST > 0) {
|
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 =
|
fun Short.toByteArray(byteOrder: ByteOrder = ByteOrder.LITTLE_ENDIAN): ByteArray =
|
||||||
ByteBuffer.allocate(2 /*Short.SIZE_BYTES*/).order(byteOrder).putShort(this).array()
|
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(
|
fun gattStatusToUniversalBleErrorCode(code: Int): UniversalBleErrorCode {
|
||||||
"DeviceDisconnected",
|
return when (code) {
|
||||||
"Device Disconnected",
|
BluetoothGatt.GATT_READ_NOT_PERMITTED -> UniversalBleErrorCode.READ_NOT_PERMITTED
|
||||||
null
|
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? {
|
fun Int.parseHciErrorCode(): String? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import io.flutter.plugin.common.PluginRegistry
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import androidx.core.content.edit
|
||||||
|
|
||||||
|
|
||||||
private const val TAG = "UniversalBlePlugin"
|
private const val TAG = "UniversalBlePlugin"
|
||||||
@@ -102,7 +103,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (bluetoothEnableRequestFuture != null) {
|
if (bluetoothEnableRequestFuture != null) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError("Failed", "Bluetooth enable request in progress", null)
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||||
|
"Bluetooth enable request in progress"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -120,7 +124,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (bluetoothDisableRequestFuture != null) {
|
if (bluetoothDisableRequestFuture != null) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError("Failed", "Bluetooth disable request in progress", null)
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||||
|
"Bluetooth disable request in progress"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -131,9 +138,9 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun startScan(filter: UniversalScanFilter?) {
|
override fun startScan(filter: UniversalScanFilter?) {
|
||||||
if (!isBluetoothAvailable()) throw FlutterError(
|
if (!isBluetoothAvailable()) throw createFlutterError(
|
||||||
"BluetoothNotEnabled",
|
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||||
"Bluetooth not enabled",
|
"Bluetooth not enabled"
|
||||||
)
|
)
|
||||||
|
|
||||||
val builder = ScanSettings.Builder()
|
val builder = ScanSettings.Builder()
|
||||||
@@ -143,10 +150,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
val settings = builder.build()
|
val settings = builder.build()
|
||||||
|
|
||||||
val usesCustomFilters = filter?.usesCustomFilters() ?: false;
|
val usesCustomFilters = filter?.usesCustomFilters() ?: false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val filterServices = filter?.withServices?.filterNotNull()?.toUUIDList() ?: emptyList()
|
val filterServices = filter?.withServices?.toUUIDList() ?: emptyList()
|
||||||
var scanFilters = emptyList<ScanFilter>()
|
var scanFilters = emptyList<ScanFilter>()
|
||||||
|
|
||||||
// Set custom scan filter only if required
|
// Set custom scan filter only if required
|
||||||
@@ -156,25 +163,25 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
universalBleFilterUtil.serviceFilterUUIDS = filterServices
|
universalBleFilterUtil.serviceFilterUUIDS = filterServices
|
||||||
} else {
|
} else {
|
||||||
universalBleFilterUtil.scanFilter = null
|
universalBleFilterUtil.scanFilter = null
|
||||||
scanFilters = filter?.toScanFilters(filterServices) ?: emptyList<ScanFilter>()
|
scanFilters = filter?.toScanFilters(filterServices) ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
safeScanner.startScan(
|
safeScanner.startScan(
|
||||||
scanFilters, settings, scanCallback
|
scanFilters, settings, scanCallback
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw FlutterError(
|
throw createFlutterError(
|
||||||
"illegalIllegalArgument",
|
UniversalBleErrorCode.FAILED,
|
||||||
"Failed to start Scan",
|
"Failed to start Scan",
|
||||||
e.toString()
|
details = e.toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stopScan() {
|
override fun stopScan() {
|
||||||
if (!isBluetoothAvailable()) throw FlutterError(
|
if (!isBluetoothAvailable()) throw createFlutterError(
|
||||||
"BluetoothNotEnabled",
|
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||||
"Bluetooth not enabled",
|
"Bluetooth not enabled"
|
||||||
)
|
)
|
||||||
// check if already scanning
|
// check if already scanning
|
||||||
safeScanner.stopScan(scanCallback)
|
safeScanner.stopScan(scanCallback)
|
||||||
@@ -192,7 +199,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
} 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))
|
discoverServicesFutureList.add(DiscoverServicesFuture(deviceId, callback))
|
||||||
} else {
|
} else {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(FlutterError("Failed", "Failed to discover services", null))
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.FAILED,
|
||||||
|
"Failed to discover services"
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: FlutterError) {
|
} catch (e: FlutterError) {
|
||||||
@@ -253,7 +268,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
discoverServicesFutureList.filter { it.deviceId == gatt.device.address }.forEach {
|
discoverServicesFutureList.filter { it.deviceId == gatt.device.address }.forEach {
|
||||||
discoverServicesFutureList.remove(it)
|
discoverServicesFutureList.remove(it)
|
||||||
it.result(
|
it.result(
|
||||||
Result.failure(FlutterError("Failed", "Failed to discover services", null))
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.FAILED,
|
||||||
|
"Failed to discover services"
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -290,7 +310,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
gatt.getCharacteristic(service, characteristic)
|
gatt.getCharacteristic(service, characteristic)
|
||||||
|
|
||||||
if (gattCharacteristic == null) {
|
if (gattCharacteristic == null) {
|
||||||
callback(subscriptionFailedError("characteristic not found"))
|
callback(
|
||||||
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||||
|
"characteristic not found"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +325,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
gattCharacteristic.getDescriptor(ccdCharacteristic)
|
gattCharacteristic.getDescriptor(ccdCharacteristic)
|
||||||
|
|
||||||
val bleInputPropertyEnum: BleInputProperty =
|
val bleInputPropertyEnum: BleInputProperty =
|
||||||
BleInputProperty.values().first { it.value == bleInputProperty }
|
BleInputProperty.entries.first { it.value == bleInputProperty }
|
||||||
|
|
||||||
val (value, enable) = when (bleInputPropertyEnum) {
|
val (value, enable) = when (bleInputPropertyEnum) {
|
||||||
BleInputProperty.Notification -> BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE to true
|
BleInputProperty.Notification -> BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE to true
|
||||||
@@ -310,14 +337,30 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
// Some devices do not need CCCD to update
|
// Some devices do not need CCCD to update
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
val status = gatt.writeDescriptor(descriptor, value)
|
||||||
if (gatt.writeDescriptor(descriptor, value) != BluetoothStatusCodes.SUCCESS) {
|
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
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
descriptor.value = value
|
descriptor.value = value
|
||||||
if (!gatt.writeDescriptor(descriptor)) {
|
if (!gatt.writeDescriptor(descriptor)) {
|
||||||
callback(subscriptionFailedError("Failed to update descriptor"))
|
callback(
|
||||||
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.FAILED,
|
||||||
|
"Failed to update descriptor"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,12 +382,27 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
callback(Result.success(Unit))
|
callback(Result.success(Unit))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback(subscriptionFailedError())
|
callback(
|
||||||
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.FAILED,
|
||||||
|
"Failed to update subscription state"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: FlutterError) {
|
} catch (e: FlutterError) {
|
||||||
callback(Result.failure(e))
|
callback(Result.failure(e))
|
||||||
} catch (e: Exception) {
|
} 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)
|
val gattCharacteristic = gatt.getCharacteristic(service, characteristic)
|
||||||
if (gattCharacteristic == null) {
|
if (gattCharacteristic == null) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(FlutterError("IllegalArgument", "Unknown characteristic", null))
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||||
|
"Unknown characteristic"
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!gatt.readCharacteristic(gattCharacteristic)) {
|
if (!gatt.readCharacteristic(gattCharacteristic)) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(unknownCharacteristicError(characteristic))
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||||
|
"$characteristic not found",
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -383,8 +451,8 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
"Failed",
|
UniversalBleErrorCode.READ_FAILED,
|
||||||
"Failed to read value",
|
"Failed to read value",
|
||||||
e.toString()
|
e.toString()
|
||||||
)
|
)
|
||||||
@@ -410,10 +478,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
} else {
|
} else {
|
||||||
it.result(
|
it.result(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
status.toString(),
|
gattStatusToUniversalBleErrorCode(status),
|
||||||
"Failed to read: (${status.parseGattErrorCode()})",
|
"Failed to read",
|
||||||
null,
|
status.toString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -434,33 +502,38 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
val gatt = deviceId.toBluetoothGatt()
|
val gatt = deviceId.toBluetoothGatt()
|
||||||
val gattCharacteristic = gatt.getCharacteristic(service, characteristic)
|
val gattCharacteristic = gatt.getCharacteristic(service, characteristic)
|
||||||
if (gattCharacteristic == null) {
|
if (gattCharacteristic == null) {
|
||||||
callback(Result.failure(unknownCharacteristicError(characteristic)))
|
callback(
|
||||||
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||||
|
"$characteristic not found",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
var writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||||
if (bleOutputProperty == BleOutputProperty.withResponse.value) {
|
if (bleOutputProperty == BleOutputProperty.WithResponse.value) {
|
||||||
if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE == 0) {
|
if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE == 0) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
"IllegalArgument",
|
UniversalBleErrorCode.CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE,
|
||||||
"Characteristic does not support write withResponse",
|
"Characteristic does not support write withResponse"
|
||||||
null
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
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) {
|
if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE == 0) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
"IllegalArgument",
|
UniversalBleErrorCode.CHARACTERISTIC_DOES_NOT_SUPPORT_WRITE_WITHOUT_RESPONSE,
|
||||||
"Characteristic does not support write withoutResponse",
|
"Characteristic does not support write withoutResponse"
|
||||||
null
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -495,10 +568,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
writeResultFutureList.remove(writeFuture)
|
writeResultFutureList.remove(writeFuture)
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
"WriteError",
|
gattStatusToUniversalBleErrorCode(result),
|
||||||
"Failed to write: ${result.parseGattErrorCode()}",
|
"Failed to write",
|
||||||
null
|
result.toString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -524,10 +597,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
} else {
|
} else {
|
||||||
it.result(
|
it.result(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
status.toString(),
|
gattStatusToUniversalBleErrorCode(status),
|
||||||
"Failed to write: (${status.parseGattErrorCode()})",
|
"Failed to write",
|
||||||
null,
|
status.toString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -553,7 +626,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
it.result(Result.success(mtu.toLong()))
|
it.result(Result.success(mtu.toLong()))
|
||||||
} else {
|
} 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) {
|
if (pendingFuture != null) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
"InProgress",
|
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||||
"Pairing already in progress",
|
"Pairing already in progress"
|
||||||
null
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -594,12 +673,19 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (remoteDevice.createBond()) {
|
if (remoteDevice.createBond()) {
|
||||||
pairResultFutures[deviceId] = callback
|
pairResultFutures[deviceId] = callback
|
||||||
} else {
|
} else {
|
||||||
callback(Result.failure(FlutterError("Failed", "Failed to pair", null)))
|
callback(
|
||||||
|
Result.failure(
|
||||||
|
createFlutterError(
|
||||||
|
UniversalBleErrorCode.PAIRING_FAILED,
|
||||||
|
"Failed to pair"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
callback(
|
callback(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError("Failed", e.toString(), null)
|
createFlutterError(UniversalBleErrorCode.FAILED, e.toString())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -664,7 +750,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
try {
|
try {
|
||||||
val timeout = (devices.size * 2).toLong()
|
val timeout = (devices.size * 2).toLong()
|
||||||
latch.await(timeout, TimeUnit.SECONDS)
|
latch.await(timeout, TimeUnit.SECONDS)
|
||||||
} catch (e: InterruptedException) {
|
} catch (_: InterruptedException) {
|
||||||
Thread.currentThread().interrupt()
|
Thread.currentThread().interrupt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,10 +835,13 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
private fun cleanConnection(gatt: BluetoothGatt) {
|
private fun cleanConnection(gatt: BluetoothGatt) {
|
||||||
gatt.removeCache()
|
gatt.removeCache()
|
||||||
gatt.disconnect()
|
gatt.disconnect()
|
||||||
|
val deviceDisconnectedError: FlutterError = createFlutterError(
|
||||||
|
UniversalBleErrorCode.DEVICE_DISCONNECTED,
|
||||||
|
"Device Disconnected",
|
||||||
|
)
|
||||||
readResultFutureList.removeAll {
|
readResultFutureList.removeAll {
|
||||||
if (it.deviceId == gatt.device.address) {
|
if (it.deviceId == gatt.device.address) {
|
||||||
it.result(Result.failure(DeviceDisconnectedError))
|
it.result(Result.failure(deviceDisconnectedError))
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -760,7 +849,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
writeResultFutureList.removeAll {
|
writeResultFutureList.removeAll {
|
||||||
if (it.deviceId == gatt.device.address) {
|
if (it.deviceId == gatt.device.address) {
|
||||||
it.result(Result.failure(DeviceDisconnectedError))
|
it.result(Result.failure(deviceDisconnectedError))
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -768,7 +857,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
subscriptionResultFutureList.removeAll {
|
subscriptionResultFutureList.removeAll {
|
||||||
if (it.deviceId == gatt.device.address) {
|
if (it.deviceId == gatt.device.address) {
|
||||||
it.result(Result.failure(DeviceDisconnectedError))
|
it.result(Result.failure(deviceDisconnectedError))
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -776,7 +865,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
mtuResultFutureList.removeAll {
|
mtuResultFutureList.removeAll {
|
||||||
if (it.deviceId == gatt.device.address) {
|
if (it.deviceId == gatt.device.address) {
|
||||||
it.result(Result.failure(DeviceDisconnectedError))
|
it.result(Result.failure(deviceDisconnectedError))
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -784,7 +873,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
}
|
}
|
||||||
discoverServicesFutureList.removeAll {
|
discoverServicesFutureList.removeAll {
|
||||||
if (it.deviceId == gatt.device.address) {
|
if (it.deviceId == gatt.device.address) {
|
||||||
it.result(Result.failure(DeviceDisconnectedError))
|
it.result(Result.failure(deviceDisconnectedError))
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -830,7 +919,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
Log.v(TAG, "${device.address} BOND_BONDING")
|
Log.v(TAG, "${device.address} BOND_BONDING")
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothDevice.BOND_BONDED -> {
|
BOND_BONDED -> {
|
||||||
onBondStateUpdate(device.address, true)
|
onBondStateUpdate(device.address, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,7 +1033,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (descriptor?.uuid.toString() == ccdCharacteristic.toString()) {
|
if (descriptor?.uuid.toString() == ccdCharacteristic.toString()) {
|
||||||
val char: String? = descriptor?.characteristic?.uuid?.toString()
|
val char: String? = descriptor?.characteristic?.uuid?.toString()
|
||||||
val service: String? = descriptor?.characteristic?.service?.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) {
|
if (deviceId != null && char != null && service != null) {
|
||||||
updateSubscriptionState(deviceId, char, service, status)
|
updateSubscriptionState(deviceId, char, service, status)
|
||||||
}
|
}
|
||||||
@@ -963,14 +1052,13 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
it.serviceId == service
|
it.serviceId == service
|
||||||
}.forEach {
|
}.forEach {
|
||||||
subscriptionResultFutureList.remove(it)
|
subscriptionResultFutureList.remove(it)
|
||||||
val error: String? = status.parseGattErrorCode()
|
if (status != BluetoothGatt.GATT_SUCCESS) {
|
||||||
if (error != null) {
|
|
||||||
it.result(
|
it.result(
|
||||||
Result.failure(
|
Result.failure(
|
||||||
FlutterError(
|
createFlutterError(
|
||||||
status.toString(),
|
gattStatusToUniversalBleErrorCode(status),
|
||||||
"Failed to update subscription state: $error",
|
"Failed to update subscription state",
|
||||||
null,
|
status.toString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -989,7 +1077,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
"com.navideck.universal_ble.services",
|
"com.navideck.universal_ble.services",
|
||||||
Context.MODE_PRIVATE
|
Context.MODE_PRIVATE
|
||||||
)
|
)
|
||||||
cachedServicesSharedPref.edit().putStringSet(deviceId, services.toSet()).apply()
|
cachedServicesSharedPref.edit { putStringSet(deviceId, services.toSet()) }
|
||||||
cachedServicesMap[deviceId] = services
|
cachedServicesMap[deviceId] = services
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Building pigeon..."
|
||||||
|
dart run pigeon --input pigeon/universal_ble.dart
|
||||||
|
echo "Pigeon built successfully"
|
||||||
|
|
||||||
|
echo "Formatting generated files..."
|
||||||
|
dart format lib/src/universal_ble_pigeon/universal_ble.g.dart
|
||||||
|
echo "Generated files formatted successfully"
|
||||||
|
|
||||||
|
echo "Done"
|
||||||
@@ -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
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -15,9 +15,9 @@ import Foundation
|
|||||||
final class PigeonError: Error {
|
final class PigeonError: Error {
|
||||||
let code: String
|
let code: String
|
||||||
let message: String?
|
let message: String?
|
||||||
let details: Any?
|
let details: Sendable?
|
||||||
|
|
||||||
init(code: String, message: String?, details: Any?) {
|
init(code: String, message: String?, details: Sendable?) {
|
||||||
self.code = code
|
self.code = code
|
||||||
self.message = message
|
self.message = message
|
||||||
self.details = details
|
self.details = details
|
||||||
@@ -68,8 +68,137 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
|
|||||||
return value as! T?
|
return value as! T?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deepEqualsUniversalBle(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||||
|
let cleanLhs = nilOrValue(lhs) as Any?
|
||||||
|
let cleanRhs = nilOrValue(rhs) as Any?
|
||||||
|
switch (cleanLhs, cleanRhs) {
|
||||||
|
case (nil, nil):
|
||||||
|
return true
|
||||||
|
|
||||||
|
case (nil, _), (_, nil):
|
||||||
|
return false
|
||||||
|
|
||||||
|
case is (Void, Void):
|
||||||
|
return true
|
||||||
|
|
||||||
|
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
|
||||||
|
return cleanLhsHashable == cleanRhsHashable
|
||||||
|
|
||||||
|
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
|
||||||
|
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
|
||||||
|
for (index, element) in cleanLhsArray.enumerated() {
|
||||||
|
if !deepEqualsUniversalBle(element, cleanRhsArray[index]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||||
|
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
|
||||||
|
for (key, cleanLhsValue) in cleanLhsDictionary {
|
||||||
|
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
|
||||||
|
if !deepEqualsUniversalBle(cleanLhsValue, cleanRhsDictionary[key]!) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deepHashUniversalBle(value: Any?, hasher: inout Hasher) {
|
||||||
|
if let valueList = value as? [AnyHashable] {
|
||||||
|
for item in valueList { deepHashUniversalBle(value: item, hasher: &hasher) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let valueDict = value as? [AnyHashable: AnyHashable] {
|
||||||
|
for key in valueDict.keys {
|
||||||
|
hasher.combine(key)
|
||||||
|
deepHashUniversalBle(value: valueDict[key]!, hasher: &hasher)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let hashableValue = value as? AnyHashable {
|
||||||
|
hasher.combine(hashableValue.hashValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasher.combine(String(describing: value))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Unified error codes for all platforms
|
||||||
|
enum UniversalBleErrorCode: Int {
|
||||||
|
case unknownError = 0
|
||||||
|
case failed = 1
|
||||||
|
case notSupported = 2
|
||||||
|
case notImplemented = 3
|
||||||
|
case channelError = 4
|
||||||
|
case bluetoothNotAvailable = 5
|
||||||
|
case bluetoothNotEnabled = 6
|
||||||
|
case bluetoothNotAllowed = 7
|
||||||
|
case bluetoothUnauthorized = 8
|
||||||
|
case deviceDisconnected = 9
|
||||||
|
case connectionTimeout = 10
|
||||||
|
case connectionFailed = 11
|
||||||
|
case connectionRejected = 12
|
||||||
|
case connectionLimitExceeded = 13
|
||||||
|
case connectionAlreadyExists = 14
|
||||||
|
case connectionTerminated = 15
|
||||||
|
case connectionInProgress = 16
|
||||||
|
case illegalArgument = 17
|
||||||
|
case deviceNotFound = 18
|
||||||
|
case serviceNotFound = 19
|
||||||
|
case characteristicNotFound = 20
|
||||||
|
case invalidServiceUuid = 21
|
||||||
|
case invalidCharacteristicUuid = 22
|
||||||
|
case invalidOffset = 23
|
||||||
|
case invalidAttributeLength = 24
|
||||||
|
case invalidPdu = 25
|
||||||
|
case invalidHandle = 26
|
||||||
|
case readFailed = 27
|
||||||
|
case readNotPermitted = 28
|
||||||
|
case writeFailed = 29
|
||||||
|
case writeNotPermitted = 30
|
||||||
|
case writeRequestBusy = 31
|
||||||
|
case invalidAction = 32
|
||||||
|
case operationNotSupported = 33
|
||||||
|
case operationTimeout = 34
|
||||||
|
case operationCancelled = 35
|
||||||
|
case operationInProgress = 36
|
||||||
|
case characteristicDoesNotSupportRead = 37
|
||||||
|
case characteristicDoesNotSupportWrite = 38
|
||||||
|
case characteristicDoesNotSupportWriteWithoutResponse = 39
|
||||||
|
case characteristicDoesNotSupportNotify = 40
|
||||||
|
case characteristicDoesNotSupportIndicate = 41
|
||||||
|
case notPaired = 42
|
||||||
|
case notPairable = 43
|
||||||
|
case alreadyPaired = 44
|
||||||
|
case pairingFailed = 45
|
||||||
|
case pairingCancelled = 46
|
||||||
|
case pairingTimeout = 47
|
||||||
|
case pairingNotAllowed = 48
|
||||||
|
case authenticationFailure = 49
|
||||||
|
case insufficientAuthentication = 50
|
||||||
|
case insufficientAuthorization = 51
|
||||||
|
case insufficientEncryption = 52
|
||||||
|
case insufficientKeySize = 53
|
||||||
|
case protectionLevelNotMet = 54
|
||||||
|
case accessDenied = 55
|
||||||
|
case unpairingFailed = 56
|
||||||
|
case alreadyUnpaired = 57
|
||||||
|
case scanFailed = 58
|
||||||
|
case stoppingScanInProgress = 59
|
||||||
|
case webBluetoothGloballyDisabled = 60
|
||||||
|
}
|
||||||
|
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalBleScanResult {
|
struct UniversalBleScanResult: Hashable {
|
||||||
var deviceId: String
|
var deviceId: String
|
||||||
var name: String? = nil
|
var name: String? = nil
|
||||||
var isPaired: Bool? = nil
|
var isPaired: Bool? = nil
|
||||||
@@ -78,7 +207,6 @@ struct UniversalBleScanResult {
|
|||||||
var services: [String]? = nil
|
var services: [String]? = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleScanResult? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleScanResult? {
|
||||||
let deviceId = pigeonVar_list[0] as! String
|
let deviceId = pigeonVar_list[0] as! String
|
||||||
@@ -107,15 +235,19 @@ struct UniversalBleScanResult {
|
|||||||
services,
|
services,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalBleScanResult, rhs: UniversalBleScanResult) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalBleService {
|
struct UniversalBleService: Hashable {
|
||||||
var uuid: String
|
var uuid: String
|
||||||
var characteristics: [UniversalBleCharacteristic]? = nil
|
var characteristics: [UniversalBleCharacteristic]? = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleService? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleService? {
|
||||||
let uuid = pigeonVar_list[0] as! String
|
let uuid = pigeonVar_list[0] as! String
|
||||||
@@ -132,15 +264,19 @@ struct UniversalBleService {
|
|||||||
characteristics,
|
characteristics,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalBleService, rhs: UniversalBleService) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalBleCharacteristic {
|
struct UniversalBleCharacteristic: Hashable {
|
||||||
var uuid: String
|
var uuid: String
|
||||||
var properties: [Int64]
|
var properties: [Int64]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleCharacteristic? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleCharacteristic? {
|
||||||
let uuid = pigeonVar_list[0] as! String
|
let uuid = pigeonVar_list[0] as! String
|
||||||
@@ -157,18 +293,22 @@ struct UniversalBleCharacteristic {
|
|||||||
properties,
|
properties,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalBleCharacteristic, rhs: UniversalBleCharacteristic) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan Filters
|
/// Scan Filters
|
||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalScanFilter {
|
struct UniversalScanFilter: Hashable {
|
||||||
var withServices: [String]
|
var withServices: [String]
|
||||||
var withNamePrefix: [String]
|
var withNamePrefix: [String]
|
||||||
var withManufacturerData: [UniversalManufacturerDataFilter]
|
var withManufacturerData: [UniversalManufacturerDataFilter]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanFilter? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanFilter? {
|
||||||
let withServices = pigeonVar_list[0] as! [String]
|
let withServices = pigeonVar_list[0] as! [String]
|
||||||
@@ -188,16 +328,20 @@ struct UniversalScanFilter {
|
|||||||
withManufacturerData,
|
withManufacturerData,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalScanFilter, rhs: UniversalScanFilter) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalManufacturerDataFilter {
|
struct UniversalManufacturerDataFilter: Hashable {
|
||||||
var companyIdentifier: Int64
|
var companyIdentifier: Int64
|
||||||
var data: FlutterStandardTypedData? = nil
|
var data: FlutterStandardTypedData? = nil
|
||||||
var mask: FlutterStandardTypedData? = nil
|
var mask: FlutterStandardTypedData? = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
||||||
let companyIdentifier = pigeonVar_list[0] as! Int64
|
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||||
@@ -217,15 +361,19 @@ struct UniversalManufacturerDataFilter {
|
|||||||
mask,
|
mask,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalManufacturerDataFilter, rhs: UniversalManufacturerDataFilter) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalManufacturerData {
|
struct UniversalManufacturerData: Hashable {
|
||||||
var companyIdentifier: Int64
|
var companyIdentifier: Int64
|
||||||
var data: FlutterStandardTypedData
|
var data: FlutterStandardTypedData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerData? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerData? {
|
||||||
let companyIdentifier = pigeonVar_list[0] as! Int64
|
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||||
@@ -242,22 +390,33 @@ struct UniversalManufacturerData {
|
|||||||
data,
|
data,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
static func == (lhs: UniversalManufacturerData, rhs: UniversalManufacturerData) -> Bool {
|
||||||
|
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UniversalBlePigeonCodecReader: FlutterStandardReader {
|
private class UniversalBlePigeonCodecReader: FlutterStandardReader {
|
||||||
override func readValue(ofType type: UInt8) -> Any? {
|
override func readValue(ofType type: UInt8) -> Any? {
|
||||||
switch type {
|
switch type {
|
||||||
case 129:
|
case 129:
|
||||||
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
|
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
|
||||||
|
if let enumResultAsInt = enumResultAsInt {
|
||||||
|
return UniversalBleErrorCode(rawValue: enumResultAsInt)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
case 130:
|
case 130:
|
||||||
return UniversalBleService.fromList(self.readValue() as! [Any?])
|
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
|
||||||
case 131:
|
case 131:
|
||||||
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
|
return UniversalBleService.fromList(self.readValue() as! [Any?])
|
||||||
case 132:
|
case 132:
|
||||||
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
|
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
|
||||||
case 133:
|
case 133:
|
||||||
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
|
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
|
||||||
case 134:
|
case 134:
|
||||||
|
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
|
||||||
|
case 135:
|
||||||
return UniversalManufacturerData.fromList(self.readValue() as! [Any?])
|
return UniversalManufacturerData.fromList(self.readValue() as! [Any?])
|
||||||
default:
|
default:
|
||||||
return super.readValue(ofType: type)
|
return super.readValue(ofType: type)
|
||||||
@@ -267,24 +426,27 @@ private class UniversalBlePigeonCodecReader: FlutterStandardReader {
|
|||||||
|
|
||||||
private class UniversalBlePigeonCodecWriter: FlutterStandardWriter {
|
private class UniversalBlePigeonCodecWriter: FlutterStandardWriter {
|
||||||
override func writeValue(_ value: Any) {
|
override func writeValue(_ value: Any) {
|
||||||
if let value = value as? UniversalBleScanResult {
|
if let value = value as? UniversalBleErrorCode {
|
||||||
super.writeByte(129)
|
super.writeByte(129)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.rawValue)
|
||||||
} else if let value = value as? UniversalBleService {
|
} else if let value = value as? UniversalBleScanResult {
|
||||||
super.writeByte(130)
|
super.writeByte(130)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
} else if let value = value as? UniversalBleCharacteristic {
|
} else if let value = value as? UniversalBleService {
|
||||||
super.writeByte(131)
|
super.writeByte(131)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
} else if let value = value as? UniversalScanFilter {
|
} else if let value = value as? UniversalBleCharacteristic {
|
||||||
super.writeByte(132)
|
super.writeByte(132)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
} else if let value = value as? UniversalManufacturerDataFilter {
|
} else if let value = value as? UniversalScanFilter {
|
||||||
super.writeByte(133)
|
super.writeByte(133)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
} else if let value = value as? UniversalManufacturerData {
|
} else if let value = value as? UniversalManufacturerDataFilter {
|
||||||
super.writeByte(134)
|
super.writeByte(134)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
|
} else if let value = value as? UniversalManufacturerData {
|
||||||
|
super.writeByte(135)
|
||||||
|
super.writeValue(value.toList())
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(value)
|
super.writeValue(value)
|
||||||
}
|
}
|
||||||
@@ -650,7 +812,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
let details: String? = nilOrValue(listResponse[2])
|
let details: String? = nilOrValue(listResponse[2])
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||||
} else {
|
} else {
|
||||||
completion(.success(Void()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,7 +830,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
let details: String? = nilOrValue(listResponse[2])
|
let details: String? = nilOrValue(listResponse[2])
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||||
} else {
|
} else {
|
||||||
completion(.success(Void()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,7 +848,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
let details: String? = nilOrValue(listResponse[2])
|
let details: String? = nilOrValue(listResponse[2])
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||||
} else {
|
} else {
|
||||||
completion(.success(Void()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -704,7 +866,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
let details: String? = nilOrValue(listResponse[2])
|
let details: String? = nilOrValue(listResponse[2])
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||||
} else {
|
} else {
|
||||||
completion(.success(Void()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -722,7 +884,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
let details: String? = nilOrValue(listResponse[2])
|
let details: String? = nilOrValue(listResponse[2])
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||||
} else {
|
} else {
|
||||||
completion(.success(Void()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,12 +103,69 @@ extension CBManagerState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps string error codes to UniversalBleErrorCode enum
|
||||||
|
func mapErrorCodeToEnum(_ code: String) -> UniversalBleErrorCode {
|
||||||
|
switch code.lowercased() {
|
||||||
|
case "notsupported", "not_supported":
|
||||||
|
return .notSupported
|
||||||
|
case "notimplemented", "not_implemented":
|
||||||
|
return .notImplemented
|
||||||
|
case "channel-error", "channelerror":
|
||||||
|
return .channelError
|
||||||
|
case "failed":
|
||||||
|
return .failed
|
||||||
|
case "devicedisconnected", "device_disconnected":
|
||||||
|
return .deviceDisconnected
|
||||||
|
case "illegalargument", "illegal_argument":
|
||||||
|
return .illegalArgument
|
||||||
|
case "invalidaction", "invalid_action":
|
||||||
|
return .invalidAction
|
||||||
|
case "readfailed", "read_failed":
|
||||||
|
return .readFailed
|
||||||
|
case "devicenotfound", "device_not_found":
|
||||||
|
return .deviceNotFound
|
||||||
|
case "servicenotfound", "service_not_found":
|
||||||
|
return .serviceNotFound
|
||||||
|
case "characteristicnotfound", "characteristic_not_found":
|
||||||
|
return .characteristicNotFound
|
||||||
|
case "invalidserviceuuid", "invalid_service_uuid":
|
||||||
|
return .invalidServiceUuid
|
||||||
|
case "characteristicdoesnotsupportread":
|
||||||
|
return .characteristicDoesNotSupportRead
|
||||||
|
case "characteristicdoesnotsupportwrite":
|
||||||
|
return .characteristicDoesNotSupportWrite
|
||||||
|
case "characteristicdoesnotsupportwritewithoutresponse":
|
||||||
|
return .characteristicDoesNotSupportWriteWithoutResponse
|
||||||
|
case "characteristicdoesnotsupportnotify":
|
||||||
|
return .characteristicDoesNotSupportNotify
|
||||||
|
case "characteristicdoesnotsupportindicate":
|
||||||
|
return .characteristicDoesNotSupportIndicate
|
||||||
|
default:
|
||||||
|
return .unknownError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a PigeonError with the error code enum in details
|
||||||
|
func createFlutterError(
|
||||||
|
code: UniversalBleErrorCode,
|
||||||
|
message: String? = nil,
|
||||||
|
details: String? = nil
|
||||||
|
) -> PigeonError {
|
||||||
|
// Pass the enum's rawValue (Int) in code as string, and enum name in details
|
||||||
|
return PigeonError(
|
||||||
|
code: code.rawValue.description,
|
||||||
|
message: message,
|
||||||
|
details: details ?? code.rawValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
extension Error {
|
extension Error {
|
||||||
func toPigeonError() -> PigeonError {
|
func toFlutterError() -> PigeonError {
|
||||||
let nsError = self as NSError
|
let nsError = self as NSError
|
||||||
let errorCode: String = .init(nsError.code)
|
let errorCode: String = .init(nsError.code)
|
||||||
let errorDescription: String = nsError.localizedDescription
|
let errorDescription: String = nsError.localizedDescription
|
||||||
return PigeonError(code: errorCode, message: errorDescription, details: nil)
|
let mappedCode = mapErrorCodeToEnum(errorCode)
|
||||||
|
return createFlutterError(code: mappedCode, message: errorDescription, details: errorCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
|
|
||||||
func enableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void) {
|
func enableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||||
completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil)))
|
completion(Result.failure(createFlutterError(code: .notSupported)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func disableBluetooth(completion: @escaping (Result<Bool, any Error>) -> Void) {
|
func disableBluetooth(completion: @escaping (Result<Bool, any Error>) -> Void) {
|
||||||
completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil)))
|
completion(Result.failure(createFlutterError(code: .notSupported)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func startScan(filter: UniversalScanFilter?) throws {
|
func startScan(filter: UniversalScanFilter?) throws {
|
||||||
@@ -122,7 +122,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
characteristicReadFutures.removeAll { future in
|
characteristicReadFutures.removeAll { future in
|
||||||
if future.deviceId == deviceId {
|
if future.deviceId == deviceId {
|
||||||
future.result(
|
future.result(
|
||||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(createFlutterError(code: .deviceDisconnected, message: "Device Disconnected"))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
characteristicWriteFutures.removeAll { future in
|
characteristicWriteFutures.removeAll { future in
|
||||||
if future.deviceId == deviceId {
|
if future.deviceId == deviceId {
|
||||||
future.result(
|
future.result(
|
||||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(createFlutterError(code: .deviceDisconnected, message: "Device Disconnected"))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
characteristicNotifyFutures.removeAll { future in
|
characteristicNotifyFutures.removeAll { future in
|
||||||
if future.deviceId == deviceId {
|
if future.deviceId == deviceId {
|
||||||
future.result(
|
future.result(
|
||||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(createFlutterError(code: .deviceDisconnected, message: "Device Disconnected"))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
discoverServicesFutures.removeAll { future in
|
discoverServicesFutures.removeAll { future in
|
||||||
if future.deviceId == deviceId {
|
if future.deviceId == deviceId {
|
||||||
future.result(
|
future.result(
|
||||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(createFlutterError(code: .deviceDisconnected, message: "Device Disconnected"))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) {
|
func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) {
|
||||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||||
completion(
|
completion(
|
||||||
Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
Result.failure(createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(self)"))
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -198,22 +198,22 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
func setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Int64, completion: @escaping (Result<Void, any Error>) -> Void) {
|
func setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Int64, completion: @escaping (Result<Void, any Error>) -> Void) {
|
||||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(deviceId)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicNotFound, message: "Unknown characteristic:\(characteristic)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if bleInputProperty == BleInputProperty.notification.rawValue && !gattCharacteristic.properties.contains(.notify) {
|
if bleInputProperty == BleInputProperty.notification.rawValue && !gattCharacteristic.properties.contains(.notify) {
|
||||||
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support notify", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicDoesNotSupportNotify, message: "Characteristic does not support notify")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if bleInputProperty == BleInputProperty.indication.rawValue && !gattCharacteristic.properties.contains(.indicate) {
|
if bleInputProperty == BleInputProperty.indication.rawValue && !gattCharacteristic.properties.contains(.indicate) {
|
||||||
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support indicate", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicDoesNotSupportIndicate, message: "Characteristic does not support indicate")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,15 +224,15 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
func readValue(deviceId: String, service: String, characteristic: String, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
func readValue(deviceId: String, service: String, characteristic: String, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(self)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicNotFound, message: "Unknown characteristic:\(characteristic)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !gattCharacteristic.properties.contains(.read) {
|
if !gattCharacteristic.properties.contains(.read) {
|
||||||
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support read", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicDoesNotSupportRead, message: "Characteristic does not support read")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
peripheral.readValue(for: gattCharacteristic)
|
peripheral.readValue(for: gattCharacteristic)
|
||||||
@@ -241,11 +241,11 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
func writeValue(deviceId: String, service: String, characteristic: String, value: FlutterStandardTypedData, bleOutputProperty: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
func writeValue(deviceId: String, service: String, characteristic: String, value: FlutterStandardTypedData, bleOutputProperty: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(self)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicNotFound, message: "Unknown characteristic:\(characteristic)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,12 +253,12 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
if type == CBCharacteristicWriteType.withResponse {
|
if type == CBCharacteristicWriteType.withResponse {
|
||||||
if !gattCharacteristic.properties.contains(.write) {
|
if !gattCharacteristic.properties.contains(.write) {
|
||||||
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withResponse", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicDoesNotSupportWrite, message: "Characteristic does not support write withResponse")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if type == CBCharacteristicWriteType.withoutResponse {
|
} else if type == CBCharacteristicWriteType.withoutResponse {
|
||||||
if !gattCharacteristic.properties.contains(.writeWithoutResponse) {
|
if !gattCharacteristic.properties.contains(.writeWithoutResponse) {
|
||||||
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withoutResponse", details: nil)))
|
completion(Result.failure(createFlutterError(code: .characteristicDoesNotSupportWriteWithoutResponse, message: "Characteristic does not support write withoutResponse")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
|
|
||||||
func requestMtu(deviceId: String, expectedMtu _: Int64, completion: @escaping (Result<Int64, Error>) -> Void) {
|
func requestMtu(deviceId: String, expectedMtu _: Int64, completion: @escaping (Result<Int64, Error>) -> Void) {
|
||||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||||
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(self)")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mtu = peripheral.maximumWriteValueLength(for: CBCharacteristicWriteType.withoutResponse)
|
let mtu = peripheral.maximumWriteValueLength(for: CBCharacteristicWriteType.withoutResponse)
|
||||||
@@ -285,15 +285,15 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isPaired(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
func isPaired(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||||
completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil)))
|
completion(Result.failure(createFlutterError(code: .notSupported)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func pair(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
func pair(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||||
completion(Result.failure(PigeonError(code: "Implemented in Dart", message: nil, details: nil)))
|
completion(Result.failure(createFlutterError(code: .notImplemented)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func unPair(deviceId _: String) throws {
|
func unPair(deviceId _: String) throws {
|
||||||
throw PigeonError(code: "NotSupported", message: nil, details: nil)
|
throw createFlutterError(code: .notSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
||||||
@@ -427,8 +427,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||||
characteristicWriteFutures.removeAll { future in
|
characteristicWriteFutures.removeAll { future in
|
||||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||||
if let pigeonError = error?.toPigeonError() {
|
if let flutterError = error?.toFlutterError() {
|
||||||
future.result(Result.failure(pigeonError))
|
future.result(Result.failure(flutterError))
|
||||||
} else {
|
} else {
|
||||||
future.result(Result.success({}()))
|
future.result(Result.success({}()))
|
||||||
}
|
}
|
||||||
@@ -441,8 +441,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
||||||
characteristicNotifyFutures.removeAll { future in
|
characteristicNotifyFutures.removeAll { future in
|
||||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||||
if let pigeonError = error?.toPigeonError() {
|
if let flutterError = error?.toFlutterError() {
|
||||||
future.result(Result.failure(pigeonError))
|
future.result(Result.failure(flutterError))
|
||||||
} else {
|
} else {
|
||||||
future.result(Result.success({}()))
|
future.result(Result.success({}()))
|
||||||
}
|
}
|
||||||
@@ -467,13 +467,13 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
// Update futures for readValue
|
// Update futures for readValue
|
||||||
characteristicReadFutures.removeAll { future in
|
characteristicReadFutures.removeAll { future in
|
||||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||||
if let pigeonError = error?.toPigeonError() {
|
if let flutterError = error?.toFlutterError() {
|
||||||
future.result(Result.failure(pigeonError))
|
future.result(Result.failure(flutterError))
|
||||||
} else {
|
} else {
|
||||||
if let characteristicValue = characteristic.value {
|
if let characteristicValue = characteristic.value {
|
||||||
future.result(Result.success(FlutterStandardTypedData(bytes: characteristicValue)))
|
future.result(Result.success(FlutterStandardTypedData(bytes: characteristicValue)))
|
||||||
} else {
|
} else {
|
||||||
future.result(Result.failure(PigeonError(code: "ReadFailed", message: "No value", details: nil)))
|
future.result(Result.failure(createFlutterError(code: .readFailed, message: "No value")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -484,15 +484,15 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension CBPeripheral {
|
extension CBPeripheral {
|
||||||
func saveCache(){
|
func saveCache() {
|
||||||
discoveredPeripherals[self.uuid.uuidString] = self
|
discoveredPeripherals[uuid.uuidString] = self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
func getPeripheral(manager: CBCentralManager) throws -> CBPeripheral {
|
func getPeripheral(manager: CBCentralManager) throws -> CBPeripheral {
|
||||||
guard let peripheral = findPeripheral(manager: manager) else {
|
guard let peripheral = findPeripheral(manager: manager) else {
|
||||||
throw PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)
|
throw createFlutterError(code: .deviceNotFound, message: "Unknown deviceId:\(self)")
|
||||||
}
|
}
|
||||||
return peripheral
|
return peripheral
|
||||||
}
|
}
|
||||||
@@ -515,7 +515,7 @@ extension [String] {
|
|||||||
func toCBUUID() throws -> [CBUUID] {
|
func toCBUUID() throws -> [CBUUID] {
|
||||||
return try compactMap { serviceUUID in
|
return try compactMap { serviceUUID in
|
||||||
guard UUID(uuidString: serviceUUID) != nil else {
|
guard UUID(uuidString: serviceUUID) != nil else {
|
||||||
throw PigeonError(code: "IllegalArgument", message: "Invalid service UUID:\(serviceUUID)", details: nil)
|
throw createFlutterError(code: .invalidServiceUuid, message: "Invalid service UUID:\(serviceUUID)")
|
||||||
}
|
}
|
||||||
return CBUUID(string: serviceUUID)
|
return CBUUID(string: serviceUUID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
# platform :ios, '12.0'
|
# platform :ios, '13.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
|
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
|
||||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||||
|
|
||||||
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
|
PODFILE CHECKSUM: 4f1c12611da7338d21589c0b2ecd6bd20b109694
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -470,7 +470,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -598,7 +598,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -647,7 +647,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
import 'package:universal_ble/src/utils/cache_handler.dart';
|
import 'package:universal_ble/src/utils/cache_handler.dart';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
|
|
||||||
@@ -105,13 +106,17 @@ extension BleDeviceExtension on BleDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (discoveredServices.isEmpty) {
|
if (discoveredServices.isEmpty) {
|
||||||
throw ServiceNotFoundException('No services found');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.serviceNotFound,
|
||||||
|
message: 'No services found',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return discoveredServices.firstWhere(
|
return discoveredServices.firstWhere(
|
||||||
(s) => BleUuidParser.compareStrings(s.uuid, service),
|
(s) => BleUuidParser.compareStrings(s.uuid, service),
|
||||||
orElse: () => throw ServiceNotFoundException(
|
orElse: () => throw UniversalBleException(
|
||||||
'Service "$service" not available',
|
code: UniversalBleErrorCode.serviceNotFound,
|
||||||
|
message: 'Service "$service" not available',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
|
|
||||||
/// Extension methods for [BleService] objects.
|
/// Extension methods for [BleService] objects.
|
||||||
@@ -8,12 +9,16 @@ extension BleServiceExtension on BleService {
|
|||||||
/// with the given UUID is not available.
|
/// with the given UUID is not available.
|
||||||
BleCharacteristic getCharacteristic(String characteristicId) {
|
BleCharacteristic getCharacteristic(String characteristicId) {
|
||||||
if (characteristics.isEmpty) {
|
if (characteristics.isEmpty) {
|
||||||
throw CharacteristicNotFoundException('No characteristics found');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message: 'No characteristics found',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return characteristics.firstWhere(
|
return characteristics.firstWhere(
|
||||||
(c) => BleUuidParser.compareStrings(c.uuid, characteristicId),
|
(c) => BleUuidParser.compareStrings(c.uuid, characteristicId),
|
||||||
orElse: () => throw CharacteristicNotFoundException(
|
orElse: () => throw UniversalBleException(
|
||||||
'Characteristic "$characteristicId" not available',
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message: 'Characteristic "$characteristicId" not available',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,85 @@
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
|
import 'package:universal_ble/src/utils/universal_ble_error_parser.dart';
|
||||||
|
|
||||||
class ConnectionException implements Exception {
|
/// Base exception class for all BLE errors with typed error codes
|
||||||
late String message;
|
class UniversalBleException implements Exception {
|
||||||
|
final UniversalBleErrorCode code;
|
||||||
|
final String message;
|
||||||
|
final dynamic details;
|
||||||
|
|
||||||
ConnectionException([dynamic error]) {
|
UniversalBleException({
|
||||||
message = _errorParser(error);
|
required this.code,
|
||||||
|
required this.message,
|
||||||
|
this.details,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => message;
|
||||||
|
|
||||||
|
factory UniversalBleException.fromError(dynamic error) {
|
||||||
|
String message = error.toString();
|
||||||
|
dynamic details = error;
|
||||||
|
if (error is PlatformException) {
|
||||||
|
message = error.message ?? error.details?.toString() ?? error.code;
|
||||||
|
details = error.details;
|
||||||
}
|
}
|
||||||
|
return UniversalBleException(
|
||||||
@override
|
code: UniversalBleErrorParser.getCode(error),
|
||||||
String toString() => message;
|
message: message,
|
||||||
}
|
details: details,
|
||||||
|
);
|
||||||
class PairingException implements Exception {
|
|
||||||
late String message;
|
|
||||||
|
|
||||||
PairingException([dynamic error]) {
|
|
||||||
message = _errorParser(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebBluetoothGloballyDisabled implements Exception {
|
/// Exception thrown when connection-related errors occur
|
||||||
String message;
|
class ConnectionException extends UniversalBleException {
|
||||||
WebBluetoothGloballyDisabled(this.message);
|
ConnectionException._({
|
||||||
|
required super.code,
|
||||||
|
required super.message,
|
||||||
|
super.details,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
ConnectionException([dynamic error])
|
||||||
String toString() => message;
|
: this._(
|
||||||
|
code: UniversalBleErrorParser.getCode(error),
|
||||||
|
message: _errorParser(error),
|
||||||
|
details: error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotFoundException implements Exception {}
|
/// Exception thrown when pairing-related errors occur
|
||||||
|
class PairingException extends UniversalBleException {
|
||||||
|
PairingException._({
|
||||||
|
required super.code,
|
||||||
|
required super.message,
|
||||||
|
super.details,
|
||||||
|
});
|
||||||
|
|
||||||
class ServiceNotFoundException implements NotFoundException {
|
/// Legacy constructor for backward compatibility
|
||||||
String message;
|
PairingException([dynamic error])
|
||||||
ServiceNotFoundException(this.message);
|
: this._(
|
||||||
|
code: UniversalBleErrorParser.getCode(error),
|
||||||
@override
|
message: _errorParser(error),
|
||||||
String toString() => message;
|
details: error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CharacteristicNotFoundException implements NotFoundException {
|
/// Exception thrown when Web Bluetooth API is globally disabled
|
||||||
String message;
|
class WebBluetoothGloballyDisabled extends UniversalBleException {
|
||||||
CharacteristicNotFoundException(this.message);
|
WebBluetoothGloballyDisabled({
|
||||||
|
super.code = UniversalBleErrorCode.webBluetoothGloballyDisabled,
|
||||||
@override
|
required super.message,
|
||||||
String toString() => message;
|
super.details,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Legacy error parser for backward compatibility
|
||||||
String _errorParser(dynamic error) {
|
String _errorParser(dynamic error) {
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
return "Failed";
|
return "Failed";
|
||||||
} else if (error is PlatformException) {
|
} else if (error is PlatformException) {
|
||||||
return error.message ?? error.details ?? error.code;
|
return error.message ?? error.details ?? error.code ?? 'Unknown error';
|
||||||
} else if (error is String) {
|
} else if (error is String) {
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ import 'dart:async';
|
|||||||
import 'package:bluez/bluez.dart';
|
import 'package:bluez/bluez.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:universal_ble/src/models/model_exports.dart';
|
import 'package:universal_ble/src/models/model_exports.dart';
|
||||||
|
import 'package:universal_ble/src/utils/universal_ble_error_parser.dart';
|
||||||
import 'package:universal_ble/src/utils/universal_ble_filter_util.dart';
|
import 'package:universal_ble/src/utils/universal_ble_filter_util.dart';
|
||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
||||||
import 'package:universal_ble/src/utils/universal_logger.dart';
|
import 'package:universal_ble/src/utils/universal_logger.dart';
|
||||||
|
import 'package:universal_ble/src/universal_ble_exceptions.dart';
|
||||||
|
|
||||||
class UniversalBleLinux extends UniversalBlePlatform {
|
class UniversalBleLinux extends UniversalBlePlatform {
|
||||||
UniversalBleLinux._();
|
UniversalBleLinux._();
|
||||||
@@ -180,7 +183,10 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
|
||||||
if (device.gattServices.isEmpty && !device.servicesResolved) {
|
if (device.gattServices.isEmpty && !device.servicesResolved) {
|
||||||
throw "Failed to resolve services";
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.failed,
|
||||||
|
message: "Failed to resolve services",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BleService> services = [];
|
List<BleService> services = [];
|
||||||
@@ -217,7 +223,10 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
orElse: () => null);
|
orElse: () => null);
|
||||||
|
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
throw Exception('Unknown characteristic:$characteristic');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message: 'Unknown characteristic:$characteristic',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -279,9 +288,8 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
final data = await c.readValue();
|
final data = await c.readValue();
|
||||||
return Uint8List.fromList(data);
|
return Uint8List.fromList(data);
|
||||||
} on BlueZFailedException catch (e) {
|
} on BlueZFailedException catch (e) {
|
||||||
throw PlatformException(
|
throw e.toUniversalBleException(
|
||||||
code: e.errorCode ?? "ReadFailed",
|
defaultCode: UniversalBleErrorCode.readFailed,
|
||||||
message: e.message,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,9 +315,8 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} on BlueZFailedException catch (e) {
|
} on BlueZFailedException catch (e) {
|
||||||
throw PlatformException(
|
throw e.toUniversalBleException(
|
||||||
code: e.errorCode ?? "WriteFailed",
|
defaultCode: UniversalBleErrorCode.writeFailed,
|
||||||
message: e.message,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,7 +324,12 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
@override
|
@override
|
||||||
Future<int> requestMtu(String deviceId, int expectedMtu) async {
|
Future<int> requestMtu(String deviceId, int expectedMtu) async {
|
||||||
final device = _findDeviceById(deviceId);
|
final device = _findDeviceById(deviceId);
|
||||||
if (!device.connected) throw Exception('Device not connected');
|
if (!device.connected) {
|
||||||
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.deviceDisconnected,
|
||||||
|
message: 'Device not connected',
|
||||||
|
);
|
||||||
|
}
|
||||||
for (BlueZGattService service in device.gattServices) {
|
for (BlueZGattService service in device.gattServices) {
|
||||||
for (BlueZGattCharacteristic characteristic in service.characteristics) {
|
for (BlueZGattCharacteristic characteristic in service.characteristics) {
|
||||||
int? mtu = characteristic.mtu;
|
int? mtu = characteristic.mtu;
|
||||||
@@ -325,7 +337,10 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
if (mtu != null) return mtu - 3;
|
if (mtu != null) return mtu - 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw Exception('MTU not available');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.operationNotSupported,
|
||||||
|
message: 'MTU not available',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -393,7 +408,10 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
(device) => device?.address == deviceId,
|
(device) => device?.address == deviceId,
|
||||||
orElse: () => null);
|
orElse: () => null);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
throw Exception('Unknown deviceId:$deviceId');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.deviceNotFound,
|
||||||
|
message: 'Unknown deviceId:$deviceId',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
@@ -459,7 +477,10 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (client.adapters.isEmpty) {
|
if (client.adapters.isEmpty) {
|
||||||
throw Exception('Bluetooth adapter unavailable');
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.bluetoothNotAvailable,
|
||||||
|
message: 'Bluetooth adapter unavailable',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +605,21 @@ extension on BlueZGattCharacteristicFlag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension on BlueZFailedException {
|
extension on BlueZFailedException {
|
||||||
|
UniversalBleException toUniversalBleException({
|
||||||
|
required UniversalBleErrorCode defaultCode,
|
||||||
|
}) {
|
||||||
|
// Map BlueZ error code to UniversalBleErrorCode
|
||||||
|
UniversalBleErrorCode code = UniversalBleErrorParser.getCode(errorCode);
|
||||||
|
if (code == UniversalBleErrorCode.unknownError) {
|
||||||
|
code = defaultCode;
|
||||||
|
}
|
||||||
|
throw UniversalBleException(
|
||||||
|
code: code,
|
||||||
|
message: message,
|
||||||
|
details: errorCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Extract error code from message and parse into decimal
|
/// Extract error code from message and parse into decimal
|
||||||
/// example: 'Operation failed with ATT error: 0x90' => 144
|
/// example: 'Operation failed with ATT error: 0x90' => 144
|
||||||
String? get errorCode {
|
String? get errorCode {
|
||||||
|
|||||||
@@ -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
|
// See also: https://pub.dev/packages/pigeon
|
||||||
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
@@ -15,7 +15,8 @@ PlatformException _createConnectionError(String channelName) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
|
List<Object?> wrapResponse(
|
||||||
|
{Object? result, PlatformException? error, bool empty = false}) {
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return <Object?>[];
|
return <Object?>[];
|
||||||
}
|
}
|
||||||
@@ -25,6 +26,86 @@ List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty
|
|||||||
return <Object?>[error.code, error.message, error.details];
|
return <Object?>[error.code, error.message, error.details];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _deepEquals(Object? a, Object? b) {
|
||||||
|
if (a is List && b is List) {
|
||||||
|
return a.length == b.length &&
|
||||||
|
a.indexed
|
||||||
|
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
|
||||||
|
}
|
||||||
|
if (a is Map && b is Map) {
|
||||||
|
return a.length == b.length &&
|
||||||
|
a.entries.every((MapEntry<Object?, Object?> entry) =>
|
||||||
|
(b as Map<Object?, Object?>).containsKey(entry.key) &&
|
||||||
|
_deepEquals(entry.value, b[entry.key]));
|
||||||
|
}
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unified error codes for all platforms
|
||||||
|
enum UniversalBleErrorCode {
|
||||||
|
unknownError,
|
||||||
|
failed,
|
||||||
|
notSupported,
|
||||||
|
notImplemented,
|
||||||
|
channelError,
|
||||||
|
bluetoothNotAvailable,
|
||||||
|
bluetoothNotEnabled,
|
||||||
|
bluetoothNotAllowed,
|
||||||
|
bluetoothUnauthorized,
|
||||||
|
deviceDisconnected,
|
||||||
|
connectionTimeout,
|
||||||
|
connectionFailed,
|
||||||
|
connectionRejected,
|
||||||
|
connectionLimitExceeded,
|
||||||
|
connectionAlreadyExists,
|
||||||
|
connectionTerminated,
|
||||||
|
connectionInProgress,
|
||||||
|
illegalArgument,
|
||||||
|
deviceNotFound,
|
||||||
|
serviceNotFound,
|
||||||
|
characteristicNotFound,
|
||||||
|
invalidServiceUuid,
|
||||||
|
invalidCharacteristicUuid,
|
||||||
|
invalidOffset,
|
||||||
|
invalidAttributeLength,
|
||||||
|
invalidPdu,
|
||||||
|
invalidHandle,
|
||||||
|
readFailed,
|
||||||
|
readNotPermitted,
|
||||||
|
writeFailed,
|
||||||
|
writeNotPermitted,
|
||||||
|
writeRequestBusy,
|
||||||
|
invalidAction,
|
||||||
|
operationNotSupported,
|
||||||
|
operationTimeout,
|
||||||
|
operationCancelled,
|
||||||
|
operationInProgress,
|
||||||
|
characteristicDoesNotSupportRead,
|
||||||
|
characteristicDoesNotSupportWrite,
|
||||||
|
characteristicDoesNotSupportWriteWithoutResponse,
|
||||||
|
characteristicDoesNotSupportNotify,
|
||||||
|
characteristicDoesNotSupportIndicate,
|
||||||
|
notPaired,
|
||||||
|
notPairable,
|
||||||
|
alreadyPaired,
|
||||||
|
pairingFailed,
|
||||||
|
pairingCancelled,
|
||||||
|
pairingTimeout,
|
||||||
|
pairingNotAllowed,
|
||||||
|
authenticationFailure,
|
||||||
|
insufficientAuthentication,
|
||||||
|
insufficientAuthorization,
|
||||||
|
insufficientEncryption,
|
||||||
|
insufficientKeySize,
|
||||||
|
protectionLevelNotMet,
|
||||||
|
accessDenied,
|
||||||
|
unpairingFailed,
|
||||||
|
alreadyUnpaired,
|
||||||
|
scanFailed,
|
||||||
|
stoppingScanInProgress,
|
||||||
|
webBluetoothGloballyDisabled,
|
||||||
|
}
|
||||||
|
|
||||||
class UniversalBleScanResult {
|
class UniversalBleScanResult {
|
||||||
UniversalBleScanResult({
|
UniversalBleScanResult({
|
||||||
required this.deviceId,
|
required this.deviceId,
|
||||||
@@ -47,7 +128,7 @@ class UniversalBleScanResult {
|
|||||||
|
|
||||||
List<String>? services;
|
List<String>? services;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
deviceId,
|
deviceId,
|
||||||
name,
|
name,
|
||||||
@@ -58,6 +139,10 @@ class UniversalBleScanResult {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalBleScanResult decode(Object result) {
|
static UniversalBleScanResult decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalBleScanResult(
|
return UniversalBleScanResult(
|
||||||
@@ -65,10 +150,27 @@ class UniversalBleScanResult {
|
|||||||
name: result[1] as String?,
|
name: result[1] as String?,
|
||||||
isPaired: result[2] as bool?,
|
isPaired: result[2] as bool?,
|
||||||
rssi: result[3] as int?,
|
rssi: result[3] as int?,
|
||||||
manufacturerDataList: (result[4] as List<Object?>?)?.cast<UniversalManufacturerData>(),
|
manufacturerDataList:
|
||||||
|
(result[4] as List<Object?>?)?.cast<UniversalManufacturerData>(),
|
||||||
services: (result[5] as List<Object?>?)?.cast<String>(),
|
services: (result[5] as List<Object?>?)?.cast<String>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalBleScanResult || other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalBleService {
|
class UniversalBleService {
|
||||||
@@ -81,20 +183,41 @@ class UniversalBleService {
|
|||||||
|
|
||||||
List<UniversalBleCharacteristic>? characteristics;
|
List<UniversalBleCharacteristic>? characteristics;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
uuid,
|
uuid,
|
||||||
characteristics,
|
characteristics,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalBleService decode(Object result) {
|
static UniversalBleService decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalBleService(
|
return UniversalBleService(
|
||||||
uuid: result[0]! as String,
|
uuid: result[0]! as String,
|
||||||
characteristics: (result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic>(),
|
characteristics:
|
||||||
|
(result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalBleService || other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalBleCharacteristic {
|
class UniversalBleCharacteristic {
|
||||||
@@ -107,13 +230,17 @@ class UniversalBleCharacteristic {
|
|||||||
|
|
||||||
List<int> properties;
|
List<int> properties;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
uuid,
|
uuid,
|
||||||
properties,
|
properties,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalBleCharacteristic decode(Object result) {
|
static UniversalBleCharacteristic decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalBleCharacteristic(
|
return UniversalBleCharacteristic(
|
||||||
@@ -121,6 +248,23 @@ class UniversalBleCharacteristic {
|
|||||||
properties: (result[1] as List<Object?>?)!.cast<int>(),
|
properties: (result[1] as List<Object?>?)!.cast<int>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalBleCharacteristic ||
|
||||||
|
other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan Filters
|
/// Scan Filters
|
||||||
@@ -137,7 +281,7 @@ class UniversalScanFilter {
|
|||||||
|
|
||||||
List<UniversalManufacturerDataFilter> withManufacturerData;
|
List<UniversalManufacturerDataFilter> withManufacturerData;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
withServices,
|
withServices,
|
||||||
withNamePrefix,
|
withNamePrefix,
|
||||||
@@ -145,14 +289,35 @@ class UniversalScanFilter {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalScanFilter decode(Object result) {
|
static UniversalScanFilter decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalScanFilter(
|
return UniversalScanFilter(
|
||||||
withServices: (result[0] as List<Object?>?)!.cast<String>(),
|
withServices: (result[0] as List<Object?>?)!.cast<String>(),
|
||||||
withNamePrefix: (result[1] as List<Object?>?)!.cast<String>(),
|
withNamePrefix: (result[1] as List<Object?>?)!.cast<String>(),
|
||||||
withManufacturerData: (result[2] as List<Object?>?)!.cast<UniversalManufacturerDataFilter>(),
|
withManufacturerData: (result[2] as List<Object?>?)!
|
||||||
|
.cast<UniversalManufacturerDataFilter>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalScanFilter || other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalManufacturerDataFilter {
|
class UniversalManufacturerDataFilter {
|
||||||
@@ -168,7 +333,7 @@ class UniversalManufacturerDataFilter {
|
|||||||
|
|
||||||
Uint8List? mask;
|
Uint8List? mask;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
companyIdentifier,
|
companyIdentifier,
|
||||||
data,
|
data,
|
||||||
@@ -176,6 +341,10 @@ class UniversalManufacturerDataFilter {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalManufacturerDataFilter decode(Object result) {
|
static UniversalManufacturerDataFilter decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalManufacturerDataFilter(
|
return UniversalManufacturerDataFilter(
|
||||||
@@ -184,6 +353,23 @@ class UniversalManufacturerDataFilter {
|
|||||||
mask: result[2] as Uint8List?,
|
mask: result[2] as Uint8List?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalManufacturerDataFilter ||
|
||||||
|
other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalManufacturerData {
|
class UniversalManufacturerData {
|
||||||
@@ -196,13 +382,17 @@ class UniversalManufacturerData {
|
|||||||
|
|
||||||
Uint8List data;
|
Uint8List data;
|
||||||
|
|
||||||
Object encode() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[
|
return <Object?>[
|
||||||
companyIdentifier,
|
companyIdentifier,
|
||||||
data,
|
data,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
static UniversalManufacturerData decode(Object result) {
|
static UniversalManufacturerData decode(Object result) {
|
||||||
result as List<Object?>;
|
result as List<Object?>;
|
||||||
return UniversalManufacturerData(
|
return UniversalManufacturerData(
|
||||||
@@ -210,8 +400,24 @@ class UniversalManufacturerData {
|
|||||||
data: result[1]! as Uint8List,
|
data: result[1]! as Uint8List,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! UniversalManufacturerData ||
|
||||||
|
other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
|
}
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@@ -220,24 +426,27 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
if (value is int) {
|
if (value is int) {
|
||||||
buffer.putUint8(4);
|
buffer.putUint8(4);
|
||||||
buffer.putInt64(value);
|
buffer.putInt64(value);
|
||||||
} else if (value is UniversalBleScanResult) {
|
} else if (value is UniversalBleErrorCode) {
|
||||||
buffer.putUint8(129);
|
buffer.putUint8(129);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.index);
|
||||||
} else if (value is UniversalBleService) {
|
} else if (value is UniversalBleScanResult) {
|
||||||
buffer.putUint8(130);
|
buffer.putUint8(130);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is UniversalBleCharacteristic) {
|
} else if (value is UniversalBleService) {
|
||||||
buffer.putUint8(131);
|
buffer.putUint8(131);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is UniversalScanFilter) {
|
} else if (value is UniversalBleCharacteristic) {
|
||||||
buffer.putUint8(132);
|
buffer.putUint8(132);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is UniversalManufacturerDataFilter) {
|
} else if (value is UniversalScanFilter) {
|
||||||
buffer.putUint8(133);
|
buffer.putUint8(133);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is UniversalManufacturerData) {
|
} else if (value is UniversalManufacturerDataFilter) {
|
||||||
buffer.putUint8(134);
|
buffer.putUint8(134);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
|
} else if (value is UniversalManufacturerData) {
|
||||||
|
buffer.putUint8(135);
|
||||||
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(buffer, value);
|
super.writeValue(buffer, value);
|
||||||
}
|
}
|
||||||
@@ -247,16 +456,19 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 129:
|
case 129:
|
||||||
return UniversalBleScanResult.decode(readValue(buffer)!);
|
final int? value = readValue(buffer) as int?;
|
||||||
|
return value == null ? null : UniversalBleErrorCode.values[value];
|
||||||
case 130:
|
case 130:
|
||||||
return UniversalBleService.decode(readValue(buffer)!);
|
return UniversalBleScanResult.decode(readValue(buffer)!);
|
||||||
case 131:
|
case 131:
|
||||||
return UniversalBleCharacteristic.decode(readValue(buffer)!);
|
return UniversalBleService.decode(readValue(buffer)!);
|
||||||
case 132:
|
case 132:
|
||||||
return UniversalScanFilter.decode(readValue(buffer)!);
|
return UniversalBleCharacteristic.decode(readValue(buffer)!);
|
||||||
case 133:
|
case 133:
|
||||||
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
|
return UniversalScanFilter.decode(readValue(buffer)!);
|
||||||
case 134:
|
case 134:
|
||||||
|
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
|
||||||
|
case 135:
|
||||||
return UniversalManufacturerData.decode(readValue(buffer)!);
|
return UniversalManufacturerData.decode(readValue(buffer)!);
|
||||||
default:
|
default:
|
||||||
return super.readValueOfType(type, buffer);
|
return super.readValueOfType(type, buffer);
|
||||||
@@ -269,9 +481,11 @@ class UniversalBlePlatformChannel {
|
|||||||
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
|
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
UniversalBlePlatformChannel(
|
||||||
|
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
: pigeonVar_binaryMessenger = binaryMessenger,
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
pigeonVar_messageChannelSuffix =
|
||||||
|
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
@@ -279,14 +493,17 @@ class UniversalBlePlatformChannel {
|
|||||||
final String pigeonVar_messageChannelSuffix;
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
Future<int> getBluetoothAvailabilityState() async {
|
Future<int> getBluetoothAvailabilityState() async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(null) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -306,14 +523,17 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> enableBluetooth() async {
|
Future<bool> enableBluetooth() async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(null) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -333,14 +553,17 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> disableBluetooth() async {
|
Future<bool> disableBluetooth() async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(null) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -360,14 +583,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> startScan(UniversalScanFilter? filter) async {
|
Future<void> startScan(UniversalScanFilter? filter) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[filter]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[filter]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -382,14 +609,17 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> stopScan() async {
|
Future<void> stopScan() async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(null) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -404,14 +634,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> connect(String deviceId) async {
|
Future<void> connect(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -426,14 +660,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> disconnect(String deviceId) async {
|
Future<void> disconnect(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -447,15 +685,20 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async {
|
Future<void> setNotifiable(String deviceId, String service,
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$pigeonVar_messageChannelSuffix';
|
String characteristic, int bleInputProperty) async {
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel
|
||||||
|
.send(<Object?>[deviceId, service, characteristic, bleInputProperty]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId, service, characteristic, bleInputProperty]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -470,14 +713,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<UniversalBleService>> discoverServices(String deviceId) async {
|
Future<List<UniversalBleService>> discoverServices(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -492,19 +739,25 @@ class UniversalBlePlatformChannel {
|
|||||||
message: 'Host platform returned null value for non-null return value.',
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<UniversalBleService>();
|
return (pigeonVar_replyList[0] as List<Object?>?)!
|
||||||
|
.cast<UniversalBleService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> readValue(String deviceId, String service, String characteristic) async {
|
Future<Uint8List> readValue(
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$pigeonVar_messageChannelSuffix';
|
String deviceId, String service, String characteristic) async {
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId, service, characteristic]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -524,14 +777,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<int> requestMtu(String deviceId, int expectedMtu) async {
|
Future<int> requestMtu(String deviceId, int expectedMtu) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId, expectedMtu]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -550,15 +807,20 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async {
|
Future<void> writeValue(String deviceId, String service,
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$pigeonVar_messageChannelSuffix';
|
String characteristic, Uint8List value, int bleOutputProperty) async {
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
|
||||||
|
<Object?>[deviceId, service, characteristic, value, bleOutputProperty]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId, service, characteristic, value, bleOutputProperty]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -573,14 +835,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isPaired(String deviceId) async {
|
Future<bool> isPaired(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -600,14 +866,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> pair(String deviceId) async {
|
Future<bool> pair(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -627,14 +897,18 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> unPair(String deviceId) async {
|
Future<void> unPair(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -648,15 +922,20 @@ class UniversalBlePlatformChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<UniversalBleScanResult>> getSystemDevices(List<String> withServices) async {
|
Future<List<UniversalBleScanResult>> getSystemDevices(
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$pigeonVar_messageChannelSuffix';
|
List<String> withServices) async {
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[withServices]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[withServices]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -671,19 +950,24 @@ class UniversalBlePlatformChannel {
|
|||||||
message: 'Host platform returned null value for non-null return value.',
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult>();
|
return (pigeonVar_replyList[0] as List<Object?>?)!
|
||||||
|
.cast<UniversalBleScanResult>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> getConnectionState(String deviceId) async {
|
Future<int> getConnectionState(String deviceId) async {
|
||||||
final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$pigeonVar_messageChannelSuffix';
|
final String pigeonVar_channelName =
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||||
|
BasicMessageChannel<Object?>(
|
||||||
pigeonVar_channelName,
|
pigeonVar_channelName,
|
||||||
pigeonChannelCodec,
|
pigeonChannelCodec,
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
);
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture =
|
||||||
|
pigeonVar_channel.send(<Object?>[deviceId]);
|
||||||
final List<Object?>? pigeonVar_replyList =
|
final List<Object?>? pigeonVar_replyList =
|
||||||
await pigeonVar_channel.send(<Object?>[deviceId]) as List<Object?>?;
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
if (pigeonVar_replyList == null) {
|
if (pigeonVar_replyList == null) {
|
||||||
throw _createConnectionError(pigeonVar_channelName);
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
} else if (pigeonVar_replyList.length > 1) {
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
@@ -713,15 +997,24 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
|
|
||||||
void onScanResult(UniversalBleScanResult result);
|
void onScanResult(UniversalBleScanResult result);
|
||||||
|
|
||||||
void onValueChanged(String deviceId, String characteristicId, Uint8List value);
|
void onValueChanged(
|
||||||
|
String deviceId, String characteristicId, Uint8List value);
|
||||||
|
|
||||||
void onConnectionChanged(String deviceId, bool connected, String? error);
|
void onConnectionChanged(String deviceId, bool connected, String? error);
|
||||||
|
|
||||||
static void setUp(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
static void setUp(
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
UniversalBleCallbackChannel? api, {
|
||||||
|
BinaryMessenger? binaryMessenger,
|
||||||
|
String messageChannelSuffix = '',
|
||||||
|
}) {
|
||||||
|
messageChannelSuffix =
|
||||||
|
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<
|
||||||
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix', pigeonChannelCodec,
|
Object?> pigeonVar_channel = BasicMessageChannel<
|
||||||
|
Object?>(
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
|
||||||
|
pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
@@ -739,14 +1032,18 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
return wrapResponse(
|
||||||
|
error: PlatformException(code: 'error', message: e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<
|
||||||
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix', pigeonChannelCodec,
|
Object?> pigeonVar_channel = BasicMessageChannel<
|
||||||
|
Object?>(
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
|
||||||
|
pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
@@ -768,14 +1065,18 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
return wrapResponse(
|
||||||
|
error: PlatformException(code: 'error', message: e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<
|
||||||
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix', pigeonChannelCodec,
|
Object?> pigeonVar_channel = BasicMessageChannel<
|
||||||
|
Object?>(
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
|
||||||
|
pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
@@ -784,7 +1085,8 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
assert(message != null,
|
assert(message != null,
|
||||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
|
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
final List<Object?> args = (message as List<Object?>?)!;
|
||||||
final UniversalBleScanResult? arg_result = (args[0] as UniversalBleScanResult?);
|
final UniversalBleScanResult? arg_result =
|
||||||
|
(args[0] as UniversalBleScanResult?);
|
||||||
assert(arg_result != null,
|
assert(arg_result != null,
|
||||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
|
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
|
||||||
try {
|
try {
|
||||||
@@ -793,14 +1095,18 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
return wrapResponse(
|
||||||
|
error: PlatformException(code: 'error', message: e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<
|
||||||
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix', pigeonChannelCodec,
|
Object?> pigeonVar_channel = BasicMessageChannel<
|
||||||
|
Object?>(
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
|
||||||
|
pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
@@ -819,19 +1125,24 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
assert(arg_value != null,
|
assert(arg_value != null,
|
||||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
|
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
|
||||||
try {
|
try {
|
||||||
api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!);
|
api.onValueChanged(
|
||||||
|
arg_deviceId!, arg_characteristicId!, arg_value!);
|
||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
return wrapResponse(
|
||||||
|
error: PlatformException(code: 'error', message: e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<
|
||||||
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix', pigeonChannelCodec,
|
Object?> pigeonVar_channel = BasicMessageChannel<
|
||||||
|
Object?>(
|
||||||
|
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
|
||||||
|
pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
@@ -853,7 +1164,8 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
return wrapResponse(
|
||||||
|
error: PlatformException(code: 'error', message: e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
import 'package:universal_ble/src/utils/universal_ble_filter_util.dart';
|
import 'package:universal_ble/src/utils/universal_ble_filter_util.dart';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
@@ -18,7 +17,9 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<AvailabilityState> getBluetoothAvailabilityState() async {
|
Future<AvailabilityState> getBluetoothAvailabilityState() async {
|
||||||
int state = await _channel.getBluetoothAvailabilityState();
|
int state = await _executeWithErrorHandling(
|
||||||
|
() => _channel.getBluetoothAvailabilityState(),
|
||||||
|
);
|
||||||
return AvailabilityState.parse(state);
|
return AvailabilityState.parse(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
if (!BleCapabilities.supportsBluetoothEnableApi) {
|
if (!BleCapabilities.supportsBluetoothEnableApi) {
|
||||||
throw UnsupportedError("Not supported");
|
throw UnsupportedError("Not supported");
|
||||||
}
|
}
|
||||||
return _channel.enableBluetooth();
|
return _executeWithErrorHandling(() => _channel.enableBluetooth());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -35,7 +36,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
if (!BleCapabilities.supportsBluetoothEnableApi) {
|
if (!BleCapabilities.supportsBluetoothEnableApi) {
|
||||||
throw UnsupportedError("Not supported");
|
throw UnsupportedError("Not supported");
|
||||||
}
|
}
|
||||||
return _channel.disableBluetooth();
|
return _executeWithErrorHandling(() => _channel.disableBluetooth());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -45,31 +46,37 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
}) async {
|
}) async {
|
||||||
await _ensureInitialized();
|
await _ensureInitialized();
|
||||||
_bleFilter.scanFilter = scanFilter;
|
_bleFilter.scanFilter = scanFilter;
|
||||||
await _channel.startScan(
|
await _executeWithErrorHandling(
|
||||||
|
() => _channel.startScan(
|
||||||
scanFilter.toUniversalScanFilter(),
|
scanFilter.toUniversalScanFilter(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> stopScan() => _channel.stopScan();
|
Future<void> stopScan() =>
|
||||||
|
_executeWithErrorHandling(() => _channel.stopScan());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||||
int state = await _channel.getConnectionState(deviceId);
|
int state = await _executeWithErrorHandling(
|
||||||
|
() => _channel.getConnectionState(deviceId));
|
||||||
return BleConnectionState.parse(state);
|
return BleConnectionState.parse(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) =>
|
Future<void> connect(String deviceId, {Duration? connectionTimeout}) =>
|
||||||
_channel.connect(deviceId);
|
_executeWithErrorHandling(() => _channel.connect(deviceId));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> disconnect(String deviceId) => _channel.disconnect(deviceId);
|
Future<void> disconnect(String deviceId) =>
|
||||||
|
_executeWithErrorHandling(() => _channel.disconnect(deviceId));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<BleService>> discoverServices(String deviceId) async {
|
Future<List<BleService>> discoverServices(String deviceId) async {
|
||||||
List<UniversalBleService?> universalBleServices =
|
List<UniversalBleService?> universalBleServices =
|
||||||
await _channel.discoverServices(deviceId);
|
await _executeWithErrorHandling(
|
||||||
|
() => _channel.discoverServices(deviceId));
|
||||||
return List<BleService>.from(universalBleServices
|
return List<BleService>.from(universalBleServices
|
||||||
.where((e) => e != null)
|
.where((e) => e != null)
|
||||||
.map((e) => e!.toBleService(deviceId))
|
.map((e) => e!.toBleService(deviceId))
|
||||||
@@ -79,12 +86,12 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
@override
|
@override
|
||||||
Future<void> setNotifiable(String deviceId, String service,
|
Future<void> setNotifiable(String deviceId, String service,
|
||||||
String characteristic, BleInputProperty bleInputProperty) {
|
String characteristic, BleInputProperty bleInputProperty) {
|
||||||
return _channel.setNotifiable(
|
return _executeWithErrorHandling(() => _channel.setNotifiable(
|
||||||
deviceId,
|
deviceId,
|
||||||
service,
|
service,
|
||||||
characteristic,
|
characteristic,
|
||||||
bleInputProperty.index,
|
bleInputProperty.index,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -94,7 +101,8 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
String characteristic, {
|
String characteristic, {
|
||||||
final Duration? timeout,
|
final Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
return _channel.readValue(deviceId, service, characteristic);
|
return _executeWithErrorHandling(
|
||||||
|
() => _channel.readValue(deviceId, service, characteristic));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -104,33 +112,38 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
String characteristic,
|
String characteristic,
|
||||||
Uint8List value,
|
Uint8List value,
|
||||||
BleOutputProperty bleOutputProperty) {
|
BleOutputProperty bleOutputProperty) {
|
||||||
return _channel.writeValue(
|
return _executeWithErrorHandling(() => _channel.writeValue(
|
||||||
deviceId,
|
deviceId,
|
||||||
service,
|
service,
|
||||||
characteristic,
|
characteristic,
|
||||||
value,
|
value,
|
||||||
bleOutputProperty.index,
|
bleOutputProperty.index,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> requestMtu(String deviceId, int expectedMtu) =>
|
Future<int> requestMtu(String deviceId, int expectedMtu) =>
|
||||||
_channel.requestMtu(deviceId, expectedMtu);
|
_executeWithErrorHandling(
|
||||||
|
() => _channel.requestMtu(deviceId, expectedMtu));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> isPaired(String deviceId) => _channel.isPaired(deviceId);
|
Future<bool> isPaired(String deviceId) =>
|
||||||
|
_executeWithErrorHandling(() => _channel.isPaired(deviceId));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> pair(String deviceId) => _channel.pair(deviceId);
|
Future<bool> pair(String deviceId) =>
|
||||||
|
_executeWithErrorHandling(() => _channel.pair(deviceId));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> unpair(String deviceId) => _channel.unPair(deviceId);
|
Future<void> unpair(String deviceId) =>
|
||||||
|
_executeWithErrorHandling(() => _channel.unPair(deviceId));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<BleDevice>> getSystemDevices(
|
Future<List<BleDevice>> getSystemDevices(
|
||||||
List<String>? withServices,
|
List<String>? withServices,
|
||||||
) async {
|
) async {
|
||||||
var devices = await _channel.getSystemDevices(withServices ?? []);
|
var devices = await _executeWithErrorHandling(
|
||||||
|
() => _channel.getSystemDevices(withServices ?? []));
|
||||||
return List<BleDevice>.from(
|
return List<BleDevice>.from(
|
||||||
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
|
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
|
||||||
);
|
);
|
||||||
@@ -152,6 +165,16 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes a platform call with error handling
|
||||||
|
/// Converts any errors to UniversalBleException
|
||||||
|
Future<T> _executeWithErrorHandling<T>(Future<T> Function() future) async {
|
||||||
|
try {
|
||||||
|
return await future();
|
||||||
|
} catch (error) {
|
||||||
|
throw UniversalBleException.fromError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _ensureInitialized() async {
|
Future<void> _ensureInitialized() async {
|
||||||
// Check bluetooth availability on Apple
|
// Check bluetooth availability on Apple
|
||||||
// so that it will ask permission only when required, and throw error on failed
|
// so that it will ask permission only when required, and throw error on failed
|
||||||
@@ -160,13 +183,13 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
AvailabilityState state = await getBluetoothAvailabilityState();
|
AvailabilityState state = await getBluetoothAvailabilityState();
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AvailabilityState.unauthorized:
|
case AvailabilityState.unauthorized:
|
||||||
throw PlatformException(
|
throw UniversalBleException(
|
||||||
code: "Unauthorized",
|
code: UniversalBleErrorCode.bluetoothUnauthorized,
|
||||||
message: "Not authorized to access Bluetooth",
|
message: "Not authorized to access Bluetooth",
|
||||||
);
|
);
|
||||||
case AvailabilityState.unsupported:
|
case AvailabilityState.unsupported:
|
||||||
throw PlatformException(
|
throw UniversalBleException(
|
||||||
code: "Unsupported",
|
code: UniversalBleErrorCode.notSupported,
|
||||||
message: "Bluetooth is not supported",
|
message: "Bluetooth is not supported",
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'dart:collection';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart';
|
import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart';
|
||||||
import 'package:universal_ble/src/utils/universal_logger.dart';
|
import 'package:universal_ble/src/utils/universal_logger.dart';
|
||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
|
|
||||||
class UniversalBleWeb extends UniversalBlePlatform {
|
class UniversalBleWeb extends UniversalBlePlatform {
|
||||||
@@ -35,7 +36,12 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
Duration? connectionTimeout = const Duration(seconds: 10),
|
Duration? connectionTimeout = const Duration(seconds: 10),
|
||||||
}) async {
|
}) async {
|
||||||
var device = _getDeviceById(deviceId);
|
var device = _getDeviceById(deviceId);
|
||||||
if (device == null) throw "$deviceId Not Found";
|
if (device == null) {
|
||||||
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.deviceNotFound,
|
||||||
|
message: "$deviceId Not Found",
|
||||||
|
);
|
||||||
|
}
|
||||||
await device.connect(timeout: connectionTimeout);
|
await device.connect(timeout: connectionTimeout);
|
||||||
|
|
||||||
// Subscribe to Connection Stream
|
// Subscribe to Connection Stream
|
||||||
@@ -92,7 +98,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
String error = e.toString().replaceAll("DeviceNotFoundError:", "").trim();
|
String error = e.toString().replaceAll("DeviceNotFoundError:", "").trim();
|
||||||
if (error.toLowerCase().contains("api globally disabled")) {
|
if (error.toLowerCase().contains("api globally disabled")) {
|
||||||
throw WebBluetoothGloballyDisabled(error);
|
throw WebBluetoothGloballyDisabled(message: error);
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@@ -154,7 +160,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (bleCharacteristic == null) {
|
if (bleCharacteristic == null) {
|
||||||
throw Exception(
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message:
|
||||||
'Characteristic $characteristic for service $service not found',
|
'Characteristic $characteristic for service $service not found',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -195,7 +203,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (bleCharacteristic == null) {
|
if (bleCharacteristic == null) {
|
||||||
throw Exception(
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message:
|
||||||
'Characteristic $characteristic for service $service not found',
|
'Characteristic $characteristic for service $service not found',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -221,8 +231,11 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
characteristicId: characteristic,
|
characteristicId: characteristic,
|
||||||
);
|
);
|
||||||
if (bleCharacteristic == null) {
|
if (bleCharacteristic == null) {
|
||||||
throw Exception(
|
throw UniversalBleException(
|
||||||
'Characteristic $characteristic for service $service not found');
|
code: UniversalBleErrorCode.characteristicNotFound,
|
||||||
|
message:
|
||||||
|
'Characteristic $characteristic for service $service not found',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var data = timeout != null
|
var data = timeout != null
|
||||||
? bleCharacteristic.readValue(timeout: timeout)
|
? bleCharacteristic.readValue(timeout: timeout)
|
||||||
@@ -233,29 +246,44 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
/// `Unimplemented`
|
/// `Unimplemented`
|
||||||
@override
|
@override
|
||||||
Future<int> requestMtu(String deviceId, int expectedMtu) {
|
Future<int> requestMtu(String deviceId, int expectedMtu) {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "requestMtu is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> isPaired(String deviceId) {
|
Future<bool> isPaired(String deviceId) {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "isPaired is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> pair(String deviceId) {
|
Future<bool> pair(String deviceId) {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "pair is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> unpair(String deviceId) {
|
Future<void> unpair(String deviceId) {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "unpair is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<BleDevice>> getSystemDevices(
|
Future<List<BleDevice>> getSystemDevices(
|
||||||
List<String>? withServices,
|
List<String>? withServices,
|
||||||
) {
|
) {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "getSystemDevices is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helpers
|
/// Helpers
|
||||||
@@ -335,12 +363,18 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> enableBluetooth() {
|
Future<bool> enableBluetooth() {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "enableBluetooth is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> disableBluetooth() {
|
Future<bool> disableBluetooth() {
|
||||||
throw UnimplementedError();
|
throw UniversalBleException(
|
||||||
|
code: UniversalBleErrorCode.notImplemented,
|
||||||
|
message: "disableBluetooth is not implemented on Web platform",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestOptionsBuilder _getRequestOptionBuilder(
|
RequestOptionsBuilder _getRequestOptionBuilder(
|
||||||
|
|||||||
@@ -0,0 +1,417 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
|
||||||
|
|
||||||
|
/// Utility class to parse error codes from dynamic errors
|
||||||
|
class UniversalBleErrorParser {
|
||||||
|
static UniversalBleErrorCode getCode(dynamic error) {
|
||||||
|
if (error is UniversalBleErrorCode) return error;
|
||||||
|
|
||||||
|
if (error is PlatformException) {
|
||||||
|
int? errorCodeInt = int.tryParse((error).code);
|
||||||
|
if (errorCodeInt != null) {
|
||||||
|
return UniversalBleErrorCode.values[errorCodeInt];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error is num) {
|
||||||
|
return _parseNumericErrorCode((error).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error is String) {
|
||||||
|
int? errorCodeInt = int.tryParse(error);
|
||||||
|
if (errorCodeInt != null) {
|
||||||
|
return _parseNumericErrorCode(errorCodeInt);
|
||||||
|
} else {
|
||||||
|
return _parseStringErrorCode(error) ??
|
||||||
|
UniversalBleErrorCode.unknownError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UniversalBleErrorCode.unknownError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UniversalBleErrorCode? _parseStringErrorCode(String code) {
|
||||||
|
switch (code.toLowerCase()) {
|
||||||
|
case 'notsupported':
|
||||||
|
case 'not_supported':
|
||||||
|
return UniversalBleErrorCode.notSupported;
|
||||||
|
case 'notimplemented':
|
||||||
|
case 'not_implemented':
|
||||||
|
return UniversalBleErrorCode.notImplemented;
|
||||||
|
case 'channel-error':
|
||||||
|
case 'channelerror':
|
||||||
|
return UniversalBleErrorCode.channelError;
|
||||||
|
case 'failed':
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 'bluetoothnotavailable':
|
||||||
|
case 'bluetooth_not_available':
|
||||||
|
return UniversalBleErrorCode.bluetoothNotAvailable;
|
||||||
|
case 'bluetoothnotenabled':
|
||||||
|
case 'bluetooth_not_enabled':
|
||||||
|
return UniversalBleErrorCode.bluetoothNotEnabled;
|
||||||
|
case 'bluetoothnotallowed':
|
||||||
|
case 'bluetooth_not_allowed':
|
||||||
|
return UniversalBleErrorCode.bluetoothNotAllowed;
|
||||||
|
case 'bluetoothunauthorized':
|
||||||
|
case 'bluetooth_unauthorized':
|
||||||
|
return UniversalBleErrorCode.bluetoothUnauthorized;
|
||||||
|
case 'devicedisconnected':
|
||||||
|
case 'device_disconnected':
|
||||||
|
return UniversalBleErrorCode.deviceDisconnected;
|
||||||
|
case 'connectiontimeout':
|
||||||
|
case 'connection_timeout':
|
||||||
|
return UniversalBleErrorCode.connectionTimeout;
|
||||||
|
case 'connectionfailed':
|
||||||
|
case 'connection_failed':
|
||||||
|
return UniversalBleErrorCode.connectionFailed;
|
||||||
|
case 'connectionrejected':
|
||||||
|
case 'connection_rejected':
|
||||||
|
return UniversalBleErrorCode.connectionRejected;
|
||||||
|
case 'connecting':
|
||||||
|
case 'connectioninprogress':
|
||||||
|
case 'connection_in_progress':
|
||||||
|
return UniversalBleErrorCode.connectionInProgress;
|
||||||
|
case 'connectionterminated':
|
||||||
|
case 'connection_terminated':
|
||||||
|
return UniversalBleErrorCode.connectionTerminated;
|
||||||
|
case 'illegalargument':
|
||||||
|
case 'illegal_argument':
|
||||||
|
return UniversalBleErrorCode.illegalArgument;
|
||||||
|
case 'devicenotfound':
|
||||||
|
case 'device_not_found':
|
||||||
|
return UniversalBleErrorCode.deviceNotFound;
|
||||||
|
case 'servicenotfound':
|
||||||
|
case 'service_not_found':
|
||||||
|
return UniversalBleErrorCode.serviceNotFound;
|
||||||
|
case 'characteristicnotfound':
|
||||||
|
case 'characteristic_not_found':
|
||||||
|
return UniversalBleErrorCode.characteristicNotFound;
|
||||||
|
case 'invalidserviceuuid':
|
||||||
|
case 'invalid_service_uuid':
|
||||||
|
return UniversalBleErrorCode.invalidServiceUuid;
|
||||||
|
case 'invalidcharacteristicuuid':
|
||||||
|
case 'invalid_characteristic_uuid':
|
||||||
|
return UniversalBleErrorCode.invalidCharacteristicUuid;
|
||||||
|
case 'readfailed':
|
||||||
|
case 'read_failed':
|
||||||
|
return UniversalBleErrorCode.readFailed;
|
||||||
|
case 'writefailed':
|
||||||
|
case 'write_failed':
|
||||||
|
case 'writeerror':
|
||||||
|
case 'write_error':
|
||||||
|
return UniversalBleErrorCode.writeFailed;
|
||||||
|
case 'invalidaction':
|
||||||
|
case 'invalid_action':
|
||||||
|
return UniversalBleErrorCode.invalidAction;
|
||||||
|
case 'operationnotsupported':
|
||||||
|
case 'operation_not_supported':
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
case 'operationtimeout':
|
||||||
|
case 'operation_timeout':
|
||||||
|
return UniversalBleErrorCode.operationTimeout;
|
||||||
|
case 'operationcancelled':
|
||||||
|
case 'operation_cancelled':
|
||||||
|
return UniversalBleErrorCode.operationCancelled;
|
||||||
|
case 'inprogress':
|
||||||
|
case 'alreadyinprogress':
|
||||||
|
case 'already_in_progress':
|
||||||
|
return UniversalBleErrorCode.operationInProgress;
|
||||||
|
case 'notpaired':
|
||||||
|
case 'not_paired':
|
||||||
|
return UniversalBleErrorCode.notPaired;
|
||||||
|
case 'notpairable':
|
||||||
|
case 'not_pairable':
|
||||||
|
return UniversalBleErrorCode.notPairable;
|
||||||
|
case 'alreadypaired':
|
||||||
|
case 'already_paired':
|
||||||
|
return UniversalBleErrorCode.alreadyPaired;
|
||||||
|
case 'pairingfailed':
|
||||||
|
case 'pairing_failed':
|
||||||
|
return UniversalBleErrorCode.pairingFailed;
|
||||||
|
case 'pairingcancelled':
|
||||||
|
case 'pairing_cancelled':
|
||||||
|
return UniversalBleErrorCode.pairingCancelled;
|
||||||
|
case 'pairingtimeout':
|
||||||
|
case 'pairing_timeout':
|
||||||
|
return UniversalBleErrorCode.pairingTimeout;
|
||||||
|
case 'pairingnotallowed':
|
||||||
|
case 'pairing_not_allowed':
|
||||||
|
return UniversalBleErrorCode.pairingNotAllowed;
|
||||||
|
case 'authenticationfailure':
|
||||||
|
case 'authentication_failure':
|
||||||
|
return UniversalBleErrorCode.authenticationFailure;
|
||||||
|
case 'authenticationtimeout':
|
||||||
|
case 'authentication_timeout':
|
||||||
|
case 'authenticationnotallowed':
|
||||||
|
case 'authentication_not_allowed':
|
||||||
|
return UniversalBleErrorCode.authenticationFailure;
|
||||||
|
case 'hardwarefailure':
|
||||||
|
case 'hardware_failure':
|
||||||
|
case 'toomanyconnections':
|
||||||
|
case 'too_many_connections':
|
||||||
|
case 'notreadytopair':
|
||||||
|
case 'not_ready_to_pair':
|
||||||
|
case 'nonsupportedprofiles':
|
||||||
|
case 'no_supported_profiles':
|
||||||
|
case 'invalidceremonydata':
|
||||||
|
case 'invalid_ceremony_data':
|
||||||
|
case 'requiredhandlernotregistered':
|
||||||
|
case 'required_handler_not_registered':
|
||||||
|
case 'rejectedbyhandler':
|
||||||
|
case 'rejected_by_handler':
|
||||||
|
case 'remotedevicehasassociation':
|
||||||
|
case 'remote_device_has_association':
|
||||||
|
return UniversalBleErrorCode.pairingFailed;
|
||||||
|
case 'protectionlevelcouldnotbemet':
|
||||||
|
case 'protection_level_could_not_be_met':
|
||||||
|
return UniversalBleErrorCode.protectionLevelNotMet;
|
||||||
|
case 'unpairingfailed':
|
||||||
|
case 'unpairing_failed':
|
||||||
|
return UniversalBleErrorCode.unpairingFailed;
|
||||||
|
case 'alreadyunpaired':
|
||||||
|
case 'already_unpaired':
|
||||||
|
return UniversalBleErrorCode.alreadyUnpaired;
|
||||||
|
case 'accessdenied':
|
||||||
|
case 'access_denied':
|
||||||
|
return UniversalBleErrorCode.accessDenied;
|
||||||
|
case 'scan_failed_already_started':
|
||||||
|
case 'scanfailedalreadystarted':
|
||||||
|
case 'scan_failed_application_registration_failed':
|
||||||
|
case 'scanfailedapplicationregistrationfailed':
|
||||||
|
case 'scan_failed_feature_unsupported':
|
||||||
|
case 'scanfailedfeatureunsupported':
|
||||||
|
case 'scan_failed_internal_error':
|
||||||
|
case 'scanfailedinternalerror':
|
||||||
|
case 'scan_failed_out_of_hardware_resources':
|
||||||
|
case 'scanfailedoutofhardwareresources':
|
||||||
|
case 'scan_failed_scanning_too_frequently':
|
||||||
|
case 'scanfailedscanningtoofrequently':
|
||||||
|
return UniversalBleErrorCode.scanFailed;
|
||||||
|
case 'stoppingscaninprogress':
|
||||||
|
case 'stopping_scan_in_progress':
|
||||||
|
return UniversalBleErrorCode.stoppingScanInProgress;
|
||||||
|
case 'gatt_failure':
|
||||||
|
case 'gattfailure':
|
||||||
|
case 'unreachable':
|
||||||
|
case 'protocolerror':
|
||||||
|
case 'protocol_error':
|
||||||
|
case 'gattunreachable':
|
||||||
|
case 'gatt_protocol_error':
|
||||||
|
case 'gatt_unlikely':
|
||||||
|
case 'gattunlikely':
|
||||||
|
case 'gatt_insufficient_resources':
|
||||||
|
case 'gattinsufficientresources':
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 'gatt_read_not_permitted':
|
||||||
|
case 'gattreadnotpermitted':
|
||||||
|
return UniversalBleErrorCode.readNotPermitted;
|
||||||
|
case 'gatt_write_not_permitted':
|
||||||
|
case 'gattwritenotpermitted':
|
||||||
|
return UniversalBleErrorCode.writeNotPermitted;
|
||||||
|
case 'gatt_insufficient_authentication':
|
||||||
|
case 'gattinsufficientauthentication':
|
||||||
|
return UniversalBleErrorCode.insufficientAuthentication;
|
||||||
|
case 'gatt_insufficient_authorization':
|
||||||
|
case 'gattinsufficientauthorization':
|
||||||
|
return UniversalBleErrorCode.insufficientAuthorization;
|
||||||
|
case 'gatt_insufficient_encryption':
|
||||||
|
case 'gattinsufficientencryption':
|
||||||
|
return UniversalBleErrorCode.insufficientEncryption;
|
||||||
|
case 'gatt_insufficient_key_size':
|
||||||
|
case 'gattinsufficientkeysize':
|
||||||
|
return UniversalBleErrorCode.insufficientKeySize;
|
||||||
|
case 'gatt_request_not_supported':
|
||||||
|
case 'gattrequestnotsupported':
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
case 'gatt_invalid_offset':
|
||||||
|
case 'gattinvalidoffset':
|
||||||
|
return UniversalBleErrorCode.invalidOffset;
|
||||||
|
case 'gatt_invalid_attribute_length':
|
||||||
|
case 'gattinvalidattributelength':
|
||||||
|
return UniversalBleErrorCode.invalidAttributeLength;
|
||||||
|
case 'gatt_connection_congested':
|
||||||
|
case 'gattconnectioncongested':
|
||||||
|
return UniversalBleErrorCode.connectionFailed;
|
||||||
|
case 'gatt_invalid_handle':
|
||||||
|
case 'gattinvalidhandle':
|
||||||
|
return UniversalBleErrorCode.invalidHandle;
|
||||||
|
case 'gatt_invalid_pdu':
|
||||||
|
case 'gattinvalidpdu':
|
||||||
|
return UniversalBleErrorCode.invalidPdu;
|
||||||
|
case 'gatt_prepare_queue_full':
|
||||||
|
case 'gattpreparequeuefull':
|
||||||
|
return UniversalBleErrorCode.operationInProgress;
|
||||||
|
case 'gatt_attr_not_found':
|
||||||
|
case 'gattattrnotfound':
|
||||||
|
return UniversalBleErrorCode.serviceNotFound;
|
||||||
|
case 'gatt_attr_not_long':
|
||||||
|
case 'gattattrnotlong':
|
||||||
|
return UniversalBleErrorCode.invalidAttributeLength;
|
||||||
|
case 'gatt_unsupported_group':
|
||||||
|
case 'gattunsupportedgroup':
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
case 'feature_not_configured':
|
||||||
|
case 'featurenotconfigured':
|
||||||
|
case 'feature_not_supported':
|
||||||
|
case 'featurenotsupported':
|
||||||
|
case 'feature_supported':
|
||||||
|
case 'featuresupported':
|
||||||
|
return UniversalBleErrorCode.notSupported;
|
||||||
|
case 'error_profile_service_not_bound':
|
||||||
|
case 'errorprofileservicenotbound':
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 'error_missing_bluetooth_connect_permission':
|
||||||
|
case 'errormissingbluetoothconnectpermission':
|
||||||
|
return UniversalBleErrorCode.bluetoothNotAllowed;
|
||||||
|
case 'error_device_not_bonded':
|
||||||
|
case 'errordevicenotbonded':
|
||||||
|
return UniversalBleErrorCode.notPaired;
|
||||||
|
case 'error_gatt_write_not_allowed':
|
||||||
|
case 'errorgattwritenotallowed':
|
||||||
|
return UniversalBleErrorCode.writeNotPermitted;
|
||||||
|
case 'error_gatt_write_request_busy':
|
||||||
|
case 'errorgattwriterequestbusy':
|
||||||
|
return UniversalBleErrorCode.writeRequestBusy;
|
||||||
|
case 'error_unknown':
|
||||||
|
case 'errorunknown':
|
||||||
|
return UniversalBleErrorCode.unknownError;
|
||||||
|
case 'webbluetoothgloballydisabled':
|
||||||
|
case 'web_bluetooth_globally_disabled':
|
||||||
|
return UniversalBleErrorCode.webBluetoothGloballyDisabled;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UniversalBleErrorCode _parseNumericErrorCode(int code) {
|
||||||
|
switch (code) {
|
||||||
|
case 0x00:
|
||||||
|
return UniversalBleErrorCode.unknownError;
|
||||||
|
case 0x01:
|
||||||
|
return UniversalBleErrorCode.invalidHandle;
|
||||||
|
case 0x02:
|
||||||
|
return UniversalBleErrorCode.readNotPermitted;
|
||||||
|
case 0x03:
|
||||||
|
return UniversalBleErrorCode.writeNotPermitted;
|
||||||
|
case 0x04:
|
||||||
|
return UniversalBleErrorCode.invalidPdu;
|
||||||
|
case 0x05:
|
||||||
|
return UniversalBleErrorCode.insufficientAuthentication;
|
||||||
|
// Consolidated: gattRequestNotSupported -> operationNotSupported
|
||||||
|
case 0x06:
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
case 0x07:
|
||||||
|
return UniversalBleErrorCode.invalidOffset;
|
||||||
|
case 0x08:
|
||||||
|
return UniversalBleErrorCode.insufficientAuthorization;
|
||||||
|
// Consolidated: gattPrepareQueueFull -> operationInProgress
|
||||||
|
case 0x09:
|
||||||
|
return UniversalBleErrorCode.operationInProgress;
|
||||||
|
// Consolidated: gattAttrNotFound -> serviceNotFound
|
||||||
|
case 0x0A:
|
||||||
|
return UniversalBleErrorCode.serviceNotFound;
|
||||||
|
// Consolidated: gattAttrNotLong -> invalidAttributeLength
|
||||||
|
case 0x0B:
|
||||||
|
return UniversalBleErrorCode.invalidAttributeLength;
|
||||||
|
case 0x0C:
|
||||||
|
return UniversalBleErrorCode.insufficientKeySize;
|
||||||
|
case 0x0D:
|
||||||
|
return UniversalBleErrorCode.invalidAttributeLength;
|
||||||
|
// Consolidated: gattUnlikely -> failed
|
||||||
|
case 0x0E:
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 0x0F:
|
||||||
|
return UniversalBleErrorCode.insufficientEncryption;
|
||||||
|
// Consolidated: gattUnsupportedGroup -> operationNotSupported
|
||||||
|
case 0x10:
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
// Consolidated: gattInsufficientResources -> failed
|
||||||
|
case 0x11:
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
// Consolidated: gattConnectionCongested -> connectionFailed
|
||||||
|
case 0x85:
|
||||||
|
return UniversalBleErrorCode.connectionFailed;
|
||||||
|
// Consolidated: gattFailure -> failed
|
||||||
|
case 0x101:
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
}
|
||||||
|
// HCI error codes - consolidated to higher-level errors
|
||||||
|
switch (code) {
|
||||||
|
// Connection errors
|
||||||
|
case 0x08: // Connection Timeout
|
||||||
|
case 0x10: // Connection Accept Timeout Exceeded
|
||||||
|
return UniversalBleErrorCode.connectionTimeout;
|
||||||
|
case 0x09: // Connection Limit Exceeded
|
||||||
|
case 0x0A: // Synchronous Connection Limit To A Device Exceeded
|
||||||
|
return UniversalBleErrorCode.connectionLimitExceeded;
|
||||||
|
case 0x0B: // Connection Already Exists
|
||||||
|
return UniversalBleErrorCode.connectionAlreadyExists;
|
||||||
|
case 0x0D: // Connection Rejected due to Limited Resources
|
||||||
|
case 0x0F: // Connection Rejected due to Unacceptable BD_ADDR
|
||||||
|
case 0x39: // Connection Rejected due to No Suitable Channel Found
|
||||||
|
return UniversalBleErrorCode.connectionRejected;
|
||||||
|
case 0x0E: // Connection Rejected Due To Security Reasons
|
||||||
|
return UniversalBleErrorCode.connectionRejected;
|
||||||
|
case 0x13: // Remote User Terminated Connection
|
||||||
|
case 0x14: // Remote Device Terminated Connection due to Low Resources
|
||||||
|
case 0x15: // Remote Device Terminated Connection due to Power Off
|
||||||
|
case 0x16: // Connection Terminated By Local Host
|
||||||
|
case 0x3D: // Connection Terminated due to MIC Failure
|
||||||
|
return UniversalBleErrorCode.connectionTerminated;
|
||||||
|
case 0x3E: // Connection Failed to be Established
|
||||||
|
case 0x3F: // MAC Connection Failed
|
||||||
|
return UniversalBleErrorCode.connectionFailed;
|
||||||
|
// Pairing/Authentication errors
|
||||||
|
case 0x05: // Authentication Failure
|
||||||
|
return UniversalBleErrorCode.authenticationFailure;
|
||||||
|
case 0x18: // Pairing Not Allowed
|
||||||
|
return UniversalBleErrorCode.pairingNotAllowed;
|
||||||
|
case 0x03: // Hardware Failure
|
||||||
|
case 0x29: // Pairing With Unit Key Not Supported
|
||||||
|
case 0x37: // Secure Simple Pairing Not Supported By Host
|
||||||
|
case 0x38: // Host Busy - Pairing
|
||||||
|
return UniversalBleErrorCode.pairingFailed;
|
||||||
|
case 0x2F: // Insufficient Security
|
||||||
|
return UniversalBleErrorCode.insufficientEncryption;
|
||||||
|
// Operation errors
|
||||||
|
case 0x0C: // Command Disallowed
|
||||||
|
case 0x11: // Unsupported Feature or Parameter Value
|
||||||
|
case 0x12: // Invalid HCI Command Parameters
|
||||||
|
case 0x1A: // Unsupported Remote Feature
|
||||||
|
case 0x1E: // Invalid LMP Parameters
|
||||||
|
case 0x20: // Unsupported LMP Parameter Value
|
||||||
|
return UniversalBleErrorCode.operationNotSupported;
|
||||||
|
case 0x22: // LMP Response Timeout
|
||||||
|
return UniversalBleErrorCode.operationTimeout;
|
||||||
|
// General errors
|
||||||
|
case 0x01: // Unknown HCI Command
|
||||||
|
case 0x02: // Unknown Connection Identifier
|
||||||
|
return UniversalBleErrorCode.unknownError;
|
||||||
|
case 0x04: // Page Timeout
|
||||||
|
return UniversalBleErrorCode.connectionTimeout;
|
||||||
|
case 0x06: // PIN or Key Missing
|
||||||
|
return UniversalBleErrorCode.authenticationFailure;
|
||||||
|
case 0x07: // Memory Capacity Exceeded
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 0x17: // Repeated Attempts
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
case 0x25: // Encryption Mode Not Acceptable
|
||||||
|
return UniversalBleErrorCode.insufficientEncryption;
|
||||||
|
case 0x26: // Link Key cannot be Changed
|
||||||
|
case 0x27: // Requested QoS Not Supported
|
||||||
|
case 0x2C: // QoS Unacceptable Parameter
|
||||||
|
case 0x2D: // QoS Rejected
|
||||||
|
case 0x2E: // Channel Classification Not Supported
|
||||||
|
case 0x30: // Parameter Out Of Mandatory Range
|
||||||
|
case 0x32: // Role Switch Pending
|
||||||
|
case 0x35: // Role Switch Failed
|
||||||
|
case 0x36: // Extended Inquiry Response Too Large
|
||||||
|
case 0x3A: // Controller Busy
|
||||||
|
case 0x3B: // Unacceptable Connection Parameters
|
||||||
|
case 0x3C: // Advertising Timeout
|
||||||
|
return UniversalBleErrorCode.failed;
|
||||||
|
}
|
||||||
|
// Default to unknown error for unmapped codes
|
||||||
|
return UniversalBleErrorCode.unknownError;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -169,3 +169,87 @@ class UniversalManufacturerData {
|
|||||||
required this.data,
|
required this.data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unified error codes for all platforms
|
||||||
|
enum UniversalBleErrorCode {
|
||||||
|
// General errors
|
||||||
|
unknownError,
|
||||||
|
failed,
|
||||||
|
notSupported,
|
||||||
|
notImplemented,
|
||||||
|
channelError,
|
||||||
|
|
||||||
|
// Bluetooth availability errors
|
||||||
|
bluetoothNotAvailable,
|
||||||
|
bluetoothNotEnabled,
|
||||||
|
bluetoothNotAllowed,
|
||||||
|
bluetoothUnauthorized,
|
||||||
|
|
||||||
|
// Connection errors
|
||||||
|
deviceDisconnected,
|
||||||
|
connectionTimeout,
|
||||||
|
connectionFailed,
|
||||||
|
connectionRejected,
|
||||||
|
connectionLimitExceeded,
|
||||||
|
connectionAlreadyExists,
|
||||||
|
connectionTerminated,
|
||||||
|
connectionInProgress,
|
||||||
|
|
||||||
|
// Device/Service/Characteristic errors
|
||||||
|
illegalArgument,
|
||||||
|
deviceNotFound,
|
||||||
|
serviceNotFound,
|
||||||
|
characteristicNotFound,
|
||||||
|
invalidServiceUuid,
|
||||||
|
invalidCharacteristicUuid,
|
||||||
|
invalidOffset,
|
||||||
|
invalidAttributeLength,
|
||||||
|
invalidPdu,
|
||||||
|
invalidHandle,
|
||||||
|
|
||||||
|
// Operation errors
|
||||||
|
readFailed,
|
||||||
|
readNotPermitted,
|
||||||
|
writeFailed,
|
||||||
|
writeNotPermitted,
|
||||||
|
writeRequestBusy,
|
||||||
|
invalidAction,
|
||||||
|
operationNotSupported,
|
||||||
|
operationTimeout,
|
||||||
|
operationCancelled,
|
||||||
|
operationInProgress,
|
||||||
|
|
||||||
|
// Characteristic property errors
|
||||||
|
characteristicDoesNotSupportRead,
|
||||||
|
characteristicDoesNotSupportWrite,
|
||||||
|
characteristicDoesNotSupportWriteWithoutResponse,
|
||||||
|
characteristicDoesNotSupportNotify,
|
||||||
|
characteristicDoesNotSupportIndicate,
|
||||||
|
|
||||||
|
// Pairing errors
|
||||||
|
notPaired,
|
||||||
|
notPairable,
|
||||||
|
alreadyPaired,
|
||||||
|
pairingFailed,
|
||||||
|
pairingCancelled,
|
||||||
|
pairingTimeout,
|
||||||
|
pairingNotAllowed,
|
||||||
|
authenticationFailure,
|
||||||
|
insufficientAuthentication,
|
||||||
|
insufficientAuthorization,
|
||||||
|
insufficientEncryption,
|
||||||
|
insufficientKeySize,
|
||||||
|
protectionLevelNotMet,
|
||||||
|
accessDenied,
|
||||||
|
|
||||||
|
// Unpairing errors
|
||||||
|
unpairingFailed,
|
||||||
|
alreadyUnpaired,
|
||||||
|
|
||||||
|
// Scan errors
|
||||||
|
scanFailed,
|
||||||
|
stoppingScanInProgress,
|
||||||
|
|
||||||
|
// Web-specific errors
|
||||||
|
webBluetoothGloballyDisabled,
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
name: universal_ble
|
name: universal_ble
|
||||||
description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
|
description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
|
||||||
version: 0.21.1
|
version: 1.0.0
|
||||||
homepage: https://navideck.com
|
homepage: https://navideck.com
|
||||||
repository: https://github.com/Navideck/universal_ble
|
repository: https://github.com/Navideck/universal_ble
|
||||||
issue_tracker: https://github.com/Navideck/universal_ble/issues
|
issue_tracker: https://github.com/Navideck/universal_ble/issues
|
||||||
@@ -38,7 +38,7 @@ dev_dependencies:
|
|||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^6.0.0
|
flutter_lints: ^6.0.0
|
||||||
pigeon: ^22.4.0
|
pigeon: ^26.0.5
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
plugin:
|
plugin:
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include "helper/universal_enum.h"
|
||||||
|
#include "helper/universal_ble_base.h"
|
||||||
|
#include "generated/universal_ble.g.h"
|
||||||
|
|
||||||
namespace universal_ble
|
namespace universal_ble
|
||||||
{
|
{
|
||||||
@@ -46,9 +50,9 @@ namespace universal_ble
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::optional<std::string> parse_pairing_fail_error(const DevicePairingResult& result)
|
inline std::optional<std::string> device_pairing_result_to_string(const DevicePairingResultStatus result)
|
||||||
{
|
{
|
||||||
switch (result.Status())
|
switch (result)
|
||||||
{
|
{
|
||||||
case DevicePairingResultStatus::Paired: return std::nullopt;
|
case DevicePairingResultStatus::Paired: return std::nullopt;
|
||||||
case DevicePairingResultStatus::AlreadyPaired: return "AlreadyPaired";
|
case DevicePairingResultStatus::AlreadyPaired: return "AlreadyPaired";
|
||||||
|
|||||||
@@ -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
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
|
||||||
#undef _HAS_EXCEPTIONS
|
#undef _HAS_EXCEPTIONS
|
||||||
@@ -425,21 +425,26 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType(
|
|||||||
flutter::ByteStreamReader* stream) const {
|
flutter::ByteStreamReader* stream) const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 129: {
|
case 129: {
|
||||||
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
const auto& encodable_enum_arg = ReadValue(stream);
|
||||||
|
const int64_t enum_arg_value = encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue();
|
||||||
|
return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast<UniversalBleErrorCode>(enum_arg_value));
|
||||||
}
|
}
|
||||||
case 130: {
|
case 130: {
|
||||||
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
}
|
}
|
||||||
case 131: {
|
case 131: {
|
||||||
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
}
|
}
|
||||||
case 132: {
|
case 132: {
|
||||||
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
}
|
}
|
||||||
case 133: {
|
case 133: {
|
||||||
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
}
|
}
|
||||||
case 134: {
|
case 134: {
|
||||||
|
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
|
}
|
||||||
|
case 135: {
|
||||||
return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -451,33 +456,38 @@ void PigeonInternalCodecSerializer::WriteValue(
|
|||||||
const EncodableValue& value,
|
const EncodableValue& value,
|
||||||
flutter::ByteStreamWriter* stream) const {
|
flutter::ByteStreamWriter* stream) const {
|
||||||
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
|
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
|
||||||
if (custom_value->type() == typeid(UniversalBleScanResult)) {
|
if (custom_value->type() == typeid(UniversalBleErrorCode)) {
|
||||||
stream->WriteByte(129);
|
stream->WriteByte(129);
|
||||||
|
WriteValue(EncodableValue(static_cast<int>(std::any_cast<UniversalBleErrorCode>(*custom_value))), stream);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (custom_value->type() == typeid(UniversalBleScanResult)) {
|
||||||
|
stream->WriteByte(130);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_value->type() == typeid(UniversalBleService)) {
|
if (custom_value->type() == typeid(UniversalBleService)) {
|
||||||
stream->WriteByte(130);
|
stream->WriteByte(131);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalBleService>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalBleService>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
|
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
|
||||||
stream->WriteByte(131);
|
stream->WriteByte(132);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_value->type() == typeid(UniversalScanFilter)) {
|
if (custom_value->type() == typeid(UniversalScanFilter)) {
|
||||||
stream->WriteByte(132);
|
stream->WriteByte(133);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalScanFilter>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalScanFilter>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) {
|
if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) {
|
||||||
stream->WriteByte(133);
|
stream->WriteByte(134);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerDataFilter>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerDataFilter>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_value->type() == typeid(UniversalManufacturerData)) {
|
if (custom_value->type() == typeid(UniversalManufacturerData)) {
|
||||||
stream->WriteByte(134);
|
stream->WriteByte(135);
|
||||||
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerData>(*custom_value).ToEncodableList()), stream);
|
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerData>(*custom_value).ToEncodableList()), stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
|
||||||
#ifndef PIGEON_UNIVERSAL_BLE_G_H_
|
#ifndef PIGEON_UNIVERSAL_BLE_G_H_
|
||||||
@@ -57,6 +57,71 @@ template<class T> class ErrorOr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Unified error codes for all platforms
|
||||||
|
enum class UniversalBleErrorCode {
|
||||||
|
kUnknownError = 0,
|
||||||
|
kFailed = 1,
|
||||||
|
kNotSupported = 2,
|
||||||
|
kNotImplemented = 3,
|
||||||
|
kChannelError = 4,
|
||||||
|
kBluetoothNotAvailable = 5,
|
||||||
|
kBluetoothNotEnabled = 6,
|
||||||
|
kBluetoothNotAllowed = 7,
|
||||||
|
kBluetoothUnauthorized = 8,
|
||||||
|
kDeviceDisconnected = 9,
|
||||||
|
kConnectionTimeout = 10,
|
||||||
|
kConnectionFailed = 11,
|
||||||
|
kConnectionRejected = 12,
|
||||||
|
kConnectionLimitExceeded = 13,
|
||||||
|
kConnectionAlreadyExists = 14,
|
||||||
|
kConnectionTerminated = 15,
|
||||||
|
kConnectionInProgress = 16,
|
||||||
|
kIllegalArgument = 17,
|
||||||
|
kDeviceNotFound = 18,
|
||||||
|
kServiceNotFound = 19,
|
||||||
|
kCharacteristicNotFound = 20,
|
||||||
|
kInvalidServiceUuid = 21,
|
||||||
|
kInvalidCharacteristicUuid = 22,
|
||||||
|
kInvalidOffset = 23,
|
||||||
|
kInvalidAttributeLength = 24,
|
||||||
|
kInvalidPdu = 25,
|
||||||
|
kInvalidHandle = 26,
|
||||||
|
kReadFailed = 27,
|
||||||
|
kReadNotPermitted = 28,
|
||||||
|
kWriteFailed = 29,
|
||||||
|
kWriteNotPermitted = 30,
|
||||||
|
kWriteRequestBusy = 31,
|
||||||
|
kInvalidAction = 32,
|
||||||
|
kOperationNotSupported = 33,
|
||||||
|
kOperationTimeout = 34,
|
||||||
|
kOperationCancelled = 35,
|
||||||
|
kOperationInProgress = 36,
|
||||||
|
kCharacteristicDoesNotSupportRead = 37,
|
||||||
|
kCharacteristicDoesNotSupportWrite = 38,
|
||||||
|
kCharacteristicDoesNotSupportWriteWithoutResponse = 39,
|
||||||
|
kCharacteristicDoesNotSupportNotify = 40,
|
||||||
|
kCharacteristicDoesNotSupportIndicate = 41,
|
||||||
|
kNotPaired = 42,
|
||||||
|
kNotPairable = 43,
|
||||||
|
kAlreadyPaired = 44,
|
||||||
|
kPairingFailed = 45,
|
||||||
|
kPairingCancelled = 46,
|
||||||
|
kPairingTimeout = 47,
|
||||||
|
kPairingNotAllowed = 48,
|
||||||
|
kAuthenticationFailure = 49,
|
||||||
|
kInsufficientAuthentication = 50,
|
||||||
|
kInsufficientAuthorization = 51,
|
||||||
|
kInsufficientEncryption = 52,
|
||||||
|
kInsufficientKeySize = 53,
|
||||||
|
kProtectionLevelNotMet = 54,
|
||||||
|
kAccessDenied = 55,
|
||||||
|
kUnpairingFailed = 56,
|
||||||
|
kAlreadyUnpaired = 57,
|
||||||
|
kScanFailed = 58,
|
||||||
|
kStoppingScanInProgress = 59,
|
||||||
|
kWebBluetoothGloballyDisabled = 60
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Generated class from Pigeon that represents data sent in messages.
|
// Generated class from Pigeon that represents data sent in messages.
|
||||||
class UniversalBleScanResult {
|
class UniversalBleScanResult {
|
||||||
@@ -96,7 +161,6 @@ class UniversalBleScanResult {
|
|||||||
void set_services(const flutter::EncodableList* value_arg);
|
void set_services(const flutter::EncodableList* value_arg);
|
||||||
void set_services(const flutter::EncodableList& value_arg);
|
void set_services(const flutter::EncodableList& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list);
|
static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -109,7 +173,6 @@ class UniversalBleScanResult {
|
|||||||
std::optional<int64_t> rssi_;
|
std::optional<int64_t> rssi_;
|
||||||
std::optional<flutter::EncodableList> manufacturer_data_list_;
|
std::optional<flutter::EncodableList> manufacturer_data_list_;
|
||||||
std::optional<flutter::EncodableList> services_;
|
std::optional<flutter::EncodableList> services_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +194,6 @@ class UniversalBleService {
|
|||||||
void set_characteristics(const flutter::EncodableList* value_arg);
|
void set_characteristics(const flutter::EncodableList* value_arg);
|
||||||
void set_characteristics(const flutter::EncodableList& value_arg);
|
void set_characteristics(const flutter::EncodableList& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalBleService FromEncodableList(const flutter::EncodableList& list);
|
static UniversalBleService FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -140,7 +202,6 @@ class UniversalBleService {
|
|||||||
friend class PigeonInternalCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
std::string uuid_;
|
std::string uuid_;
|
||||||
std::optional<flutter::EncodableList> characteristics_;
|
std::optional<flutter::EncodableList> characteristics_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -158,7 +219,6 @@ class UniversalBleCharacteristic {
|
|||||||
const flutter::EncodableList& properties() const;
|
const flutter::EncodableList& properties() const;
|
||||||
void set_properties(const flutter::EncodableList& value_arg);
|
void set_properties(const flutter::EncodableList& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list);
|
static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -167,7 +227,6 @@ class UniversalBleCharacteristic {
|
|||||||
friend class PigeonInternalCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
std::string uuid_;
|
std::string uuid_;
|
||||||
flutter::EncodableList properties_;
|
flutter::EncodableList properties_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +250,6 @@ class UniversalScanFilter {
|
|||||||
const flutter::EncodableList& with_manufacturer_data() const;
|
const flutter::EncodableList& with_manufacturer_data() const;
|
||||||
void set_with_manufacturer_data(const flutter::EncodableList& value_arg);
|
void set_with_manufacturer_data(const flutter::EncodableList& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalScanFilter FromEncodableList(const flutter::EncodableList& list);
|
static UniversalScanFilter FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -201,7 +259,6 @@ class UniversalScanFilter {
|
|||||||
flutter::EncodableList with_services_;
|
flutter::EncodableList with_services_;
|
||||||
flutter::EncodableList with_name_prefix_;
|
flutter::EncodableList with_name_prefix_;
|
||||||
flutter::EncodableList with_manufacturer_data_;
|
flutter::EncodableList with_manufacturer_data_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -228,7 +285,6 @@ class UniversalManufacturerDataFilter {
|
|||||||
void set_mask(const std::vector<uint8_t>* value_arg);
|
void set_mask(const std::vector<uint8_t>* value_arg);
|
||||||
void set_mask(const std::vector<uint8_t>& value_arg);
|
void set_mask(const std::vector<uint8_t>& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalManufacturerDataFilter FromEncodableList(const flutter::EncodableList& list);
|
static UniversalManufacturerDataFilter FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -238,7 +294,6 @@ class UniversalManufacturerDataFilter {
|
|||||||
int64_t company_identifier_;
|
int64_t company_identifier_;
|
||||||
std::optional<std::vector<uint8_t>> data_;
|
std::optional<std::vector<uint8_t>> data_;
|
||||||
std::optional<std::vector<uint8_t>> mask_;
|
std::optional<std::vector<uint8_t>> mask_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -256,7 +311,6 @@ class UniversalManufacturerData {
|
|||||||
const std::vector<uint8_t>& data() const;
|
const std::vector<uint8_t>& data() const;
|
||||||
void set_data(const std::vector<uint8_t>& value_arg);
|
void set_data(const std::vector<uint8_t>& value_arg);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UniversalManufacturerData FromEncodableList(const flutter::EncodableList& list);
|
static UniversalManufacturerData FromEncodableList(const flutter::EncodableList& list);
|
||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
@@ -265,7 +319,6 @@ class UniversalManufacturerData {
|
|||||||
friend class PigeonInternalCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
int64_t company_identifier_;
|
int64_t company_identifier_;
|
||||||
std::vector<uint8_t> data_;
|
std::vector<uint8_t> data_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -280,12 +333,10 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer {
|
|||||||
void WriteValue(
|
void WriteValue(
|
||||||
const flutter::EncodableValue& value,
|
const flutter::EncodableValue& value,
|
||||||
flutter::ByteStreamWriter* stream) const override;
|
flutter::ByteStreamWriter* stream) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
flutter::EncodableValue ReadValueOfType(
|
flutter::EncodableValue ReadValueOfType(
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
flutter::ByteStreamReader* stream) const override;
|
flutter::ByteStreamReader* stream) const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flutter -> Native
|
// Flutter -> Native
|
||||||
@@ -352,10 +403,8 @@ class UniversalBlePlatformChannel {
|
|||||||
const std::string& message_channel_suffix);
|
const std::string& message_channel_suffix);
|
||||||
static flutter::EncodableValue WrapError(std::string_view error_message);
|
static flutter::EncodableValue WrapError(std::string_view error_message);
|
||||||
static flutter::EncodableValue WrapError(const FlutterError& error);
|
static flutter::EncodableValue WrapError(const FlutterError& error);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UniversalBlePlatformChannel() = default;
|
UniversalBlePlatformChannel() = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
// Native -> Flutter
|
// Native -> Flutter
|
||||||
//
|
//
|
||||||
@@ -393,7 +442,6 @@ class UniversalBleCallbackChannel {
|
|||||||
const std::string* error,
|
const std::string* error,
|
||||||
std::function<void(void)>&& on_success,
|
std::function<void(void)>&& on_success,
|
||||||
std::function<void(const FlutterError&)>&& on_error);
|
std::function<void(const FlutterError&)>&& on_error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
flutter::BinaryMessenger* binary_messenger_;
|
flutter::BinaryMessenger* binary_messenger_;
|
||||||
std::string message_channel_suffix_;
|
std::string message_channel_suffix_;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "Utils.h"
|
#include "utils.h"
|
||||||
|
#include "../generated/universal_ble.g.h"
|
||||||
|
#include "../enum_parser.h"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sdkddkver.h>
|
#include <sdkddkver.h>
|
||||||
@@ -158,4 +161,142 @@ namespace universal_ble
|
|||||||
return rove.dwMajorVersion == 10 && rove.dwBuildNumber >= 22000;
|
return rove.dwMajorVersion == 10 && rove.dwBuildNumber >= 22000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlutterError create_flutter_error(
|
||||||
|
UniversalBleErrorCode code,
|
||||||
|
const std::string& message,
|
||||||
|
const std::string& details
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Pass the enum's underlying integer value as string in code, and enum name or details in details
|
||||||
|
std::string code_str = std::to_string(static_cast<int>(code));
|
||||||
|
std::string details_str = details.empty() ? std::to_string(static_cast<int>(code)) : details;
|
||||||
|
return FlutterError(code_str, message, details_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlutterError create_flutter_error_from_gatt_communication_status(
|
||||||
|
GattCommunicationStatus status,
|
||||||
|
const std::string& message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (status == GattCommunicationStatus::Success) {
|
||||||
|
// Success case - shouldn't normally create an error, but if called, return unknown
|
||||||
|
return create_flutter_error(UniversalBleErrorCode::kUnknownError, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniversalBleErrorCode error_code;
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case GattCommunicationStatus::Unreachable:
|
||||||
|
case GattCommunicationStatus::ProtocolError:
|
||||||
|
case GattCommunicationStatus::AccessDenied:
|
||||||
|
default:
|
||||||
|
error_code = UniversalBleErrorCode::kFailed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto error_message = gatt_communication_status_to_error(status);
|
||||||
|
std::string final_message = message.empty() && error_message.has_value()
|
||||||
|
? error_message.value()
|
||||||
|
: message;
|
||||||
|
return create_flutter_error(error_code, final_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlutterError create_flutter_error_from_pairing_status(
|
||||||
|
DevicePairingResultStatus status,
|
||||||
|
const std::string& message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (status == DevicePairingResultStatus::Paired) {
|
||||||
|
// Success case - shouldn't normally create an error, but if called, return unknown
|
||||||
|
return create_flutter_error(UniversalBleErrorCode::kUnknownError, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniversalBleErrorCode error_code;
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case DevicePairingResultStatus::AlreadyPaired:
|
||||||
|
error_code = UniversalBleErrorCode::kAlreadyPaired;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::ConnectionRejected:
|
||||||
|
error_code = UniversalBleErrorCode::kConnectionRejected;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::NotPaired:
|
||||||
|
error_code = UniversalBleErrorCode::kNotPaired;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::NotReadyToPair:
|
||||||
|
case DevicePairingResultStatus::TooManyConnections:
|
||||||
|
case DevicePairingResultStatus::HardwareFailure:
|
||||||
|
case DevicePairingResultStatus::NoSupportedProfiles:
|
||||||
|
case DevicePairingResultStatus::InvalidCeremonyData:
|
||||||
|
case DevicePairingResultStatus::RequiredHandlerNotRegistered:
|
||||||
|
case DevicePairingResultStatus::RejectedByHandler:
|
||||||
|
case DevicePairingResultStatus::RemoteDeviceHasAssociation:
|
||||||
|
error_code = UniversalBleErrorCode::kPairingFailed;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::AuthenticationTimeout:
|
||||||
|
case DevicePairingResultStatus::AuthenticationNotAllowed:
|
||||||
|
case DevicePairingResultStatus::AuthenticationFailure:
|
||||||
|
error_code = UniversalBleErrorCode::kAuthenticationFailure;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::ProtectionLevelCouldNotBeMet:
|
||||||
|
error_code = UniversalBleErrorCode::kProtectionLevelNotMet;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::AccessDenied:
|
||||||
|
error_code = UniversalBleErrorCode::kAccessDenied;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::PairingCanceled:
|
||||||
|
error_code = UniversalBleErrorCode::kPairingCancelled;
|
||||||
|
break;
|
||||||
|
case DevicePairingResultStatus::OperationAlreadyInProgress:
|
||||||
|
error_code = UniversalBleErrorCode::kOperationInProgress;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error_code = UniversalBleErrorCode::kPairingFailed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto error_message = device_pairing_result_to_string(status);
|
||||||
|
std::string final_message = message.empty() && error_message.has_value()
|
||||||
|
? error_message.value()
|
||||||
|
: message;
|
||||||
|
return create_flutter_error(error_code, final_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlutterError create_flutter_error_from_unpairing_status(
|
||||||
|
DeviceUnpairingResultStatus status,
|
||||||
|
const std::string& message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (status == DeviceUnpairingResultStatus::Unpaired) {
|
||||||
|
// Success case - shouldn't normally create an error, but if called, return unknown
|
||||||
|
return create_flutter_error(UniversalBleErrorCode::kUnknownError, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniversalBleErrorCode error_code;
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case DeviceUnpairingResultStatus::Failed:
|
||||||
|
error_code = UniversalBleErrorCode::kUnpairingFailed;
|
||||||
|
break;
|
||||||
|
case DeviceUnpairingResultStatus::AlreadyUnpaired:
|
||||||
|
error_code = UniversalBleErrorCode::kAlreadyUnpaired;
|
||||||
|
break;
|
||||||
|
case DeviceUnpairingResultStatus::AccessDenied:
|
||||||
|
error_code = UniversalBleErrorCode::kAccessDenied;
|
||||||
|
break;
|
||||||
|
case DeviceUnpairingResultStatus::OperationAlreadyInProgress:
|
||||||
|
error_code = UniversalBleErrorCode::kOperationInProgress;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error_code = UniversalBleErrorCode::kUnpairingFailed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto error_message = device_unpairing_result_to_string(status);
|
||||||
|
std::string final_message = message.empty() && error_message.has_value()
|
||||||
|
? error_message.value()
|
||||||
|
: message;
|
||||||
|
return create_flutter_error(error_code, final_message);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace universal_ble
|
} // namespace universal_ble
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
|
|
||||||
#include "winrt/Windows.Foundation.h"
|
#include "winrt/Windows.Foundation.h"
|
||||||
#include "winrt/Windows.Storage.Streams.h"
|
#include "winrt/Windows.Storage.Streams.h"
|
||||||
|
#include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h"
|
||||||
#include "winrt/base.h"
|
#include "winrt/base.h"
|
||||||
#include "universal_ble_base.h"
|
#include "universal_ble_base.h"
|
||||||
|
#include "../generated/universal_ble.g.h"
|
||||||
|
|
||||||
constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000;
|
constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000;
|
||||||
|
|
||||||
@@ -28,6 +30,40 @@ namespace universal_ble
|
|||||||
bool is_little_endian();
|
bool is_little_endian();
|
||||||
bool is_windows11_or_greater();
|
bool is_windows11_or_greater();
|
||||||
|
|
||||||
|
/// Creates a FlutterError with the error code enum in details
|
||||||
|
FlutterError create_flutter_error(
|
||||||
|
UniversalBleErrorCode code,
|
||||||
|
const std::string& message = "",
|
||||||
|
const std::string& details = ""
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Error creation functions
|
||||||
|
/// Creates a FlutterError from GATT communication status
|
||||||
|
FlutterError create_flutter_error_from_gatt_communication_status(
|
||||||
|
GattCommunicationStatus status,
|
||||||
|
const std::string& message = ""
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Creates a FlutterError from device pairing result status
|
||||||
|
FlutterError create_flutter_error_from_pairing_status(
|
||||||
|
DevicePairingResultStatus status,
|
||||||
|
const std::string& message = ""
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Creates a FlutterError from device unpairing result status
|
||||||
|
FlutterError create_flutter_error_from_unpairing_status(
|
||||||
|
DeviceUnpairingResultStatus status,
|
||||||
|
const std::string& message = ""
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create Flutter unknown error
|
||||||
|
inline FlutterError create_flutter_unknown_error(
|
||||||
|
const std::string& message = "Unknown error"
|
||||||
|
) {
|
||||||
|
return create_flutter_error(UniversalBleErrorCode::kUnknownError, message);
|
||||||
|
}
|
||||||
|
|
||||||
/// To call async functions synchronously
|
/// To call async functions synchronously
|
||||||
template <typename AsyncT>
|
template <typename AsyncT>
|
||||||
static auto async_get(AsyncT const &async)
|
static auto async_get(AsyncT const &async)
|
||||||
@@ -42,11 +78,11 @@ namespace universal_ble
|
|||||||
}
|
}
|
||||||
catch (const hresult_error &err)
|
catch (const hresult_error &err)
|
||||||
{
|
{
|
||||||
throw FlutterError("Failed", to_string(err.message()));
|
throw create_flutter_error(UniversalBleErrorCode::kFailed, to_string(err.message()));
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
throw FlutterError("Failed", "Unknown error");
|
throw create_flutter_unknown_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -61,11 +61,11 @@ namespace universal_ble
|
|||||||
{
|
{
|
||||||
if (gatt_map.count(service_uuid) == 0)
|
if (gatt_map.count(service_uuid) == 0)
|
||||||
{
|
{
|
||||||
throw FlutterError("IllegalArgument", "Service not found");
|
throw create_flutter_error(UniversalBleErrorCode::kServiceNotFound, "Service not found");
|
||||||
}
|
}
|
||||||
if (gatt_map[service_uuid].characteristics.count(characteristic_uuid) == 0)
|
if (gatt_map[service_uuid].characteristics.count(characteristic_uuid) == 0)
|
||||||
{
|
{
|
||||||
throw FlutterError("IllegalArgument", "Characteristic not found");
|
throw create_flutter_error(UniversalBleErrorCode::kCharacteristicNotFound, "Characteristic not found");
|
||||||
}
|
}
|
||||||
return gatt_map[service_uuid].characteristics.at(characteristic_uuid);
|
return gatt_map[service_uuid].characteristics.at(characteristic_uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user