Add error in connection updates (#89)
* Add error in connection updates * implement windows * Update changelog and Docs * minor fix in connect() * Add default timeout in connect * Document new pair and connect API * Fix Connect and Pair apis to throw proper errors and Improve logging * remove import * Rename PairingException and update Exception doc * Update changelog * Update comments --------- Co-authored-by: Foti Dim <fdimanidis@gmail.com>
This commit is contained in:
+6
-3
@@ -1,8 +1,11 @@
|
|||||||
## 0.13.0
|
## 0.13.0
|
||||||
* BREAKING CHANGE: `scanFilter` filters are now in OR relation
|
* BREAKING CHANGE: `scanFilter` filters are now in OR relation
|
||||||
* BREAKING CHANGE: `manufacturerDataHead` is removed from `BleDevice`
|
* BREAKING CHANGE: `manufacturerDataHead` is removed from `BleDevice`
|
||||||
* BREAKING CHANGE: rename `WebConfig` to `WebOptions`
|
* BREAKING CHANGE: `WebConfig` is now `WebOptions`
|
||||||
* BREAKING CHANGE: rename `ManufacturerDataFilter.data` to `ManufacturerDataFilter.payload`
|
* BREAKING CHANGE: `ManufacturerDataFilter.data` is now `ManufacturerDataFilter.payload`
|
||||||
|
* BREAKING CHANGE: `connect()` does not return a boolean anymore. It will throw error on connection failure
|
||||||
|
* BREAKING CHANGE: `pair()` does not return a boolean anymore. It will throw error on connection failure
|
||||||
|
* BREAKING CHANGE: `onConnectionChange` returns error as well
|
||||||
* BREAKING CHANGE: rename in-app pairing capabilities
|
* BREAKING CHANGE: rename in-app pairing capabilities
|
||||||
* Deprecation: `manufacturerData` is deprecated in BleDevice and will be removed in the future
|
* Deprecation: `manufacturerData` is deprecated in BleDevice and will be removed in the future
|
||||||
* Improve `scanFilter` handling
|
* Improve `scanFilter` handling
|
||||||
@@ -11,6 +14,7 @@
|
|||||||
* Auto convert all services passed to `getSystemDevices()`
|
* Auto convert all services passed to `getSystemDevices()`
|
||||||
* Return false for receivesAdvertisements on Linux/Web
|
* Return false for receivesAdvertisements on Linux/Web
|
||||||
* Add 1s delay in discoverServices on Linux
|
* Add 1s delay in discoverServices on Linux
|
||||||
|
* Add `connectionStream` API to get connection updates as stream
|
||||||
|
|
||||||
## 0.12.0
|
## 0.12.0
|
||||||
* BREAKING CHANGE: `unPair` is now `unpair`
|
* BREAKING CHANGE: `unPair` is now `unpair`
|
||||||
@@ -20,7 +24,6 @@
|
|||||||
* Add `PlatformConfig` property in `StartScan`
|
* Add `PlatformConfig` property in `StartScan`
|
||||||
* Add `WebConfig` property in `PlatformConfig`
|
* Add `WebConfig` property in `PlatformConfig`
|
||||||
* Fix notifications for characteristics without cccd on Android
|
* Fix notifications for characteristics without cccd on Android
|
||||||
* Add `connectionStream` API to get connection updates as stream
|
|
||||||
* Promote Linux to stable
|
* Promote Linux to stable
|
||||||
|
|
||||||
## 0.11.1
|
## 0.11.1
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ UniversalBle.connect(deviceId);
|
|||||||
UniversalBle.disconnect(deviceId);
|
UniversalBle.disconnect(deviceId);
|
||||||
|
|
||||||
// Get connection/disconnection updates
|
// Get connection/disconnection updates
|
||||||
UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
|
UniversalBle.onConnectionChange = (String deviceId, bool isConnected, String? error) {
|
||||||
debugPrint('OnConnectionChange $deviceId, $isConnected');
|
debugPrint('OnConnectionChange $deviceId, $isConnected Error: $error');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current connection state
|
// Get current connection state
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
|
// Autogenerated from Pigeon (v22.4.0), 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")
|
||||||
|
|
||||||
@@ -53,19 +53,18 @@ data class UniversalBleScanResult (
|
|||||||
val name: String? = null,
|
val name: String? = null,
|
||||||
val isPaired: Boolean? = null,
|
val isPaired: Boolean? = null,
|
||||||
val rssi: Long? = null,
|
val rssi: Long? = null,
|
||||||
val manufacturerDataList: List<UniversalManufacturerData?>? = null,
|
val manufacturerDataList: List<UniversalManufacturerData>? = null,
|
||||||
val services: List<String?>? = null
|
val services: List<String>? = null
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalBleScanResult {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleScanResult {
|
val deviceId = pigeonVar_list[0] as String
|
||||||
val deviceId = __pigeon_list[0] as String
|
val name = pigeonVar_list[1] as String?
|
||||||
val name = __pigeon_list[1] as String?
|
val isPaired = pigeonVar_list[2] as Boolean?
|
||||||
val isPaired = __pigeon_list[2] as Boolean?
|
val rssi = pigeonVar_list[3] as Long?
|
||||||
val rssi = __pigeon_list[3].let { num -> if (num is Int) num.toLong() else num as Long? }
|
val manufacturerDataList = pigeonVar_list[4] as List<UniversalManufacturerData>?
|
||||||
val manufacturerDataList = __pigeon_list[4] as List<UniversalManufacturerData?>?
|
val services = pigeonVar_list[5] as List<String>?
|
||||||
val services = __pigeon_list[5] as List<String?>?
|
|
||||||
return UniversalBleScanResult(deviceId, name, isPaired, rssi, manufacturerDataList, services)
|
return UniversalBleScanResult(deviceId, name, isPaired, rssi, manufacturerDataList, services)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,14 +83,13 @@ data class UniversalBleScanResult (
|
|||||||
/** Generated class from Pigeon that represents data sent in messages. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
data class UniversalBleService (
|
data class UniversalBleService (
|
||||||
val uuid: String,
|
val uuid: String,
|
||||||
val characteristics: List<UniversalBleCharacteristic?>? = null
|
val characteristics: List<UniversalBleCharacteristic>? = null
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalBleService {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleService {
|
val uuid = pigeonVar_list[0] as String
|
||||||
val uuid = __pigeon_list[0] as String
|
val characteristics = pigeonVar_list[1] as List<UniversalBleCharacteristic>?
|
||||||
val characteristics = __pigeon_list[1] as List<UniversalBleCharacteristic?>?
|
|
||||||
return UniversalBleService(uuid, characteristics)
|
return UniversalBleService(uuid, characteristics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,14 +104,13 @@ data class UniversalBleService (
|
|||||||
/** Generated class from Pigeon that represents data sent in messages. */
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
data class UniversalBleCharacteristic (
|
data class UniversalBleCharacteristic (
|
||||||
val uuid: String,
|
val uuid: String,
|
||||||
val properties: List<Long?>
|
val properties: List<Long>
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalBleCharacteristic {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleCharacteristic {
|
val uuid = pigeonVar_list[0] as String
|
||||||
val uuid = __pigeon_list[0] as String
|
val properties = pigeonVar_list[1] as List<Long>
|
||||||
val properties = __pigeon_list[1] as List<Long?>
|
|
||||||
return UniversalBleCharacteristic(uuid, properties)
|
return UniversalBleCharacteristic(uuid, properties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,17 +128,16 @@ data class UniversalBleCharacteristic (
|
|||||||
* Generated class from Pigeon that represents data sent in messages.
|
* Generated class from Pigeon that represents data sent in messages.
|
||||||
*/
|
*/
|
||||||
data class UniversalScanFilter (
|
data class UniversalScanFilter (
|
||||||
val withServices: List<String?>,
|
val withServices: List<String>,
|
||||||
val withNamePrefix: List<String?>,
|
val withNamePrefix: List<String>,
|
||||||
val withManufacturerData: List<UniversalManufacturerDataFilter?>
|
val withManufacturerData: List<UniversalManufacturerDataFilter>
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalScanFilter {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalScanFilter {
|
val withServices = pigeonVar_list[0] as List<String>
|
||||||
val withServices = __pigeon_list[0] as List<String?>
|
val withNamePrefix = pigeonVar_list[1] as List<String>
|
||||||
val withNamePrefix = __pigeon_list[1] as List<String?>
|
val withManufacturerData = pigeonVar_list[2] as List<UniversalManufacturerDataFilter>
|
||||||
val withManufacturerData = __pigeon_list[2] as List<UniversalManufacturerDataFilter?>
|
|
||||||
return UniversalScanFilter(withServices, withNamePrefix, withManufacturerData)
|
return UniversalScanFilter(withServices, withNamePrefix, withManufacturerData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,14 +155,13 @@ data class UniversalManufacturerDataFilter (
|
|||||||
val companyIdentifier: Long,
|
val companyIdentifier: Long,
|
||||||
val data: ByteArray? = null,
|
val data: ByteArray? = null,
|
||||||
val mask: ByteArray? = null
|
val mask: ByteArray? = null
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalManufacturerDataFilter {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalManufacturerDataFilter {
|
val companyIdentifier = pigeonVar_list[0] as Long
|
||||||
val companyIdentifier = __pigeon_list[0].let { num -> if (num is Int) num.toLong() else num as Long }
|
val data = pigeonVar_list[1] as ByteArray?
|
||||||
val data = __pigeon_list[1] as ByteArray?
|
val mask = pigeonVar_list[2] as ByteArray?
|
||||||
val mask = __pigeon_list[2] as ByteArray?
|
|
||||||
return UniversalManufacturerDataFilter(companyIdentifier, data, mask)
|
return UniversalManufacturerDataFilter(companyIdentifier, data, mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,13 +178,12 @@ data class UniversalManufacturerDataFilter (
|
|||||||
data class UniversalManufacturerData (
|
data class UniversalManufacturerData (
|
||||||
val companyIdentifier: Long,
|
val companyIdentifier: Long,
|
||||||
val data: ByteArray
|
val data: ByteArray
|
||||||
|
)
|
||||||
) {
|
{
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("LocalVariableName")
|
fun fromList(pigeonVar_list: List<Any?>): UniversalManufacturerData {
|
||||||
fun fromList(__pigeon_list: List<Any?>): UniversalManufacturerData {
|
val companyIdentifier = pigeonVar_list[0] as Long
|
||||||
val companyIdentifier = __pigeon_list[0].let { num -> if (num is Int) num.toLong() else num as Long }
|
val data = pigeonVar_list[1] as ByteArray
|
||||||
val data = __pigeon_list[1] as ByteArray
|
|
||||||
return UniversalManufacturerData(companyIdentifier, data)
|
return UniversalManufacturerData(companyIdentifier, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +194,7 @@ data class UniversalManufacturerData (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private object 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() -> {
|
||||||
@@ -294,7 +288,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
companion object {
|
companion object {
|
||||||
/** The codec used by UniversalBlePlatformChannel. */
|
/** The codec used by UniversalBlePlatformChannel. */
|
||||||
val codec: MessageCodec<Any?> by lazy {
|
val codec: MessageCodec<Any?> by lazy {
|
||||||
UniversalBlePigeonCodec
|
UniversalBlePigeonCodec()
|
||||||
}
|
}
|
||||||
/** Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. */
|
/** Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. */
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@@ -414,7 +408,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
val deviceIdArg = args[0] as String
|
val deviceIdArg = args[0] as String
|
||||||
val serviceArg = args[1] as String
|
val serviceArg = args[1] as String
|
||||||
val characteristicArg = args[2] as String
|
val characteristicArg = args[2] as String
|
||||||
val bleInputPropertyArg = args[3].let { num -> if (num is Int) num.toLong() else num as Long }
|
val bleInputPropertyArg = args[3] as Long
|
||||||
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) {
|
||||||
@@ -476,7 +470,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
channel.setMessageHandler { message, reply ->
|
channel.setMessageHandler { message, reply ->
|
||||||
val args = message as List<Any?>
|
val args = message as List<Any?>
|
||||||
val deviceIdArg = args[0] as String
|
val deviceIdArg = args[0] as String
|
||||||
val expectedMtuArg = args[1].let { num -> if (num is Int) num.toLong() else num as Long }
|
val expectedMtuArg = args[1] as Long
|
||||||
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) {
|
||||||
@@ -500,7 +494,7 @@ interface UniversalBlePlatformChannel {
|
|||||||
val serviceArg = args[1] as String
|
val serviceArg = args[1] as String
|
||||||
val characteristicArg = args[2] as String
|
val characteristicArg = args[2] as String
|
||||||
val valueArg = args[3] as ByteArray
|
val valueArg = args[3] as ByteArray
|
||||||
val bleOutputPropertyArg = args[4].let { num -> if (num is Int) num.toLong() else num as Long }
|
val bleOutputPropertyArg = args[4] as Long
|
||||||
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) {
|
||||||
@@ -621,7 +615,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
|||||||
companion object {
|
companion object {
|
||||||
/** The codec used by UniversalBleCallbackChannel. */
|
/** The codec used by UniversalBleCallbackChannel. */
|
||||||
val codec: MessageCodec<Any?> by lazy {
|
val codec: MessageCodec<Any?> by lazy {
|
||||||
UniversalBlePigeonCodec
|
UniversalBlePigeonCodec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun onAvailabilityChanged(stateArg: Long, callback: (Result<Unit>) -> Unit)
|
fun onAvailabilityChanged(stateArg: Long, callback: (Result<Unit>) -> Unit)
|
||||||
@@ -692,12 +686,12 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
|
||||||
{
|
{
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$separatedMessageChannelSuffix"
|
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$separatedMessageChannelSuffix"
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||||
channel.send(listOf(deviceIdArg, connectedArg)) {
|
channel.send(listOf(deviceIdArg, connectedArg, errorArg)) {
|
||||||
if (it is List<*>) {
|
if (it is List<*>) {
|
||||||
if (it.size > 1) {
|
if (it.size > 1) {
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||||
|
|||||||
@@ -245,6 +245,82 @@ val DeviceDisconnectedError: FlutterError = FlutterError(
|
|||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun Int.parseHciErrorCode(): String? {
|
||||||
|
return when (this) {
|
||||||
|
BluetoothGatt.GATT_SUCCESS -> null
|
||||||
|
0x01 -> "Unknown HCI Command"
|
||||||
|
0x02 -> "Unknown Connection Identifier"
|
||||||
|
0x03 -> "Hardware Failure"
|
||||||
|
0x04 -> "Page Timeout"
|
||||||
|
0x05 -> "Authentication Failure"
|
||||||
|
0x06 -> "PIN or Key Missing"
|
||||||
|
0x07 -> "Memory Capacity Exceeded"
|
||||||
|
0x08 -> "Connection Timeout"
|
||||||
|
0x09 -> "Connection Limit Exceeded"
|
||||||
|
0x0A -> "Synchronous Connection Limit To A Device Exceeded"
|
||||||
|
0x0B -> "Connection Already Exists"
|
||||||
|
0x0C -> "Command Disallowed"
|
||||||
|
0x0D -> "Connection Rejected due to Limited Resources"
|
||||||
|
0x0E -> "Connection Rejected Due To Security Reasons"
|
||||||
|
0x0F -> "Connection Rejected due to Unacceptable BD_ADDR"
|
||||||
|
0x10 -> "Connection Accept Timeout Exceeded"
|
||||||
|
0x11 -> "Unsupported Feature or Parameter Value"
|
||||||
|
0x12 -> "Invalid HCI Command Parameters"
|
||||||
|
0x13 -> "Remote User Terminated Connection"
|
||||||
|
0x14 -> "Remote Device Terminated Connection due to Low Resources"
|
||||||
|
0x15 -> "Remote Device Terminated Connection due to Power Off"
|
||||||
|
0x16 -> "Connection Terminated By Local Host"
|
||||||
|
0x17 -> "Repeated Attempts"
|
||||||
|
0x18 -> "Pairing Not Allowed"
|
||||||
|
0x19 -> "Unknown LMP PDU"
|
||||||
|
0x1A -> "Unsupported Remote Feature / Unsupported LMP Feature"
|
||||||
|
0x1B -> "SCO Offset Rejected"
|
||||||
|
0x1C -> "SCO Interval Rejected"
|
||||||
|
0x1D -> "SCO Air Mode Rejected"
|
||||||
|
0x1E -> "Invalid LMP Parameters / Invalid LL Parameters"
|
||||||
|
0x1F -> "Unspecified Error"
|
||||||
|
0x20 -> "Unsupported LMP Parameter Value / Unsupported LL Parameter Value"
|
||||||
|
0x21 -> "Role Change Not Allowed"
|
||||||
|
0x22 -> "LMP Response Timeout / LL Response Timeout"
|
||||||
|
0x23 -> "LMP Error Transaction Collision / LL Procedure Collision"
|
||||||
|
0x24 -> "LMP PDU Not Allowed"
|
||||||
|
0x25 -> "Encryption Mode Not Acceptable"
|
||||||
|
0x26 -> "Link Key cannot be Changed"
|
||||||
|
0x27 -> "Requested QoS Not Supported"
|
||||||
|
0x28 -> "Instant Passed"
|
||||||
|
0x29 -> "Pairing With Unit Key Not Supported"
|
||||||
|
0x2A -> "Different Transaction Collision"
|
||||||
|
0x2B -> "Reserved for future use"
|
||||||
|
0x2C -> "QoS Unacceptable Parameter"
|
||||||
|
0x2D -> "QoS Rejected"
|
||||||
|
0x2E -> "Channel Classification Not Supported"
|
||||||
|
0x2F -> "Insufficient Security"
|
||||||
|
0x30 -> "Parameter Out Of Mandatory Range"
|
||||||
|
0x31 -> "Reserved for future use"
|
||||||
|
0x32 -> "Role Switch Pending"
|
||||||
|
0x33 -> "Reserved for future use"
|
||||||
|
0x34 -> "Reserved Slot Violation"
|
||||||
|
0x35 -> "Role Switch Failed"
|
||||||
|
0x36 -> "Extended Inquiry Response Too Large"
|
||||||
|
0x37 -> "Secure Simple Pairing Not Supported By Host"
|
||||||
|
0x38 -> "Host Busy - Pairing"
|
||||||
|
0x39 -> "Connection Rejected due to No Suitable Channel Found"
|
||||||
|
0x3A -> "Controller Busy"
|
||||||
|
0x3B -> "Unacceptable Connection Parameters"
|
||||||
|
0x3C -> "Advertising Timeout"
|
||||||
|
0x3D -> "Connection Terminated due to MIC Failure"
|
||||||
|
0x3E -> "Connection Failed to be Established / Synchronization Timeout"
|
||||||
|
0x3F -> "MAC Connection Failed"
|
||||||
|
0x40 -> "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging"
|
||||||
|
0x41 -> "Type0 Submap Not Defined"
|
||||||
|
0x42 -> "Unknown Advertising Identifier"
|
||||||
|
0x43 -> "Limit Reached"
|
||||||
|
0x44 -> "Operation Cancelled by Host"
|
||||||
|
0x45 -> "Packet Too Long"
|
||||||
|
else -> "Unknown Error $this"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Future result classes
|
// Future result classes
|
||||||
class DiscoverServicesFuture(
|
class DiscoverServicesFuture(
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
if (currentState == BluetoothGatt.STATE_CONNECTED) {
|
if (currentState == BluetoothGatt.STATE_CONNECTED) {
|
||||||
Log.e(TAG, "$deviceId Already connected")
|
Log.e(TAG, "$deviceId Already connected")
|
||||||
mainThreadHandler?.post {
|
mainThreadHandler?.post {
|
||||||
callbackChannel?.onConnectionChanged(deviceId, true) {}
|
callbackChannel?.onConnectionChanged(deviceId, true, null) {}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
||||||
@@ -864,19 +864,22 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
|||||||
|
|
||||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||||
devicesStateMap[gatt.device.address] = newState
|
devicesStateMap[gatt.device.address] = newState
|
||||||
Log.d(TAG, "onConnectionStateChange-> Status: ${status}, NewState: $newState")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"onConnectionStateChange-> Status: $status ${status.parseHciErrorCode()}, NewState: $newState"
|
||||||
|
)
|
||||||
|
|
||||||
if (newState == BluetoothGatt.STATE_CONNECTED) {
|
if (newState == BluetoothGatt.STATE_CONNECTED) {
|
||||||
mainThreadHandler?.post {
|
mainThreadHandler?.post {
|
||||||
callbackChannel?.onConnectionChanged(
|
callbackChannel?.onConnectionChanged(
|
||||||
gatt.device.address, true
|
gatt.device.address, true, status.parseHciErrorCode()
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
|
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
|
||||||
cleanConnection(gatt)
|
cleanConnection(gatt)
|
||||||
mainThreadHandler?.post {
|
mainThreadHandler?.post {
|
||||||
callbackChannel?.onConnectionChanged(
|
callbackChannel?.onConnectionChanged(
|
||||||
gatt.device.address, false
|
gatt.device.address, false, status.parseHciErrorCode()
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
|
// Autogenerated from Pigeon (v22.4.0), do not edit directly.
|
||||||
// See also: https://pub.dev/packages/pigeon
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -74,17 +74,19 @@ struct UniversalBleScanResult {
|
|||||||
var name: String? = nil
|
var name: String? = nil
|
||||||
var isPaired: Bool? = nil
|
var isPaired: Bool? = nil
|
||||||
var rssi: Int64? = nil
|
var rssi: Int64? = nil
|
||||||
var manufacturerDataList: [UniversalManufacturerData?]? = nil
|
var manufacturerDataList: [UniversalManufacturerData]? = nil
|
||||||
var services: [String?]? = nil
|
var services: [String]? = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalBleScanResult? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleScanResult? {
|
||||||
let deviceId = __pigeon_list[0] as! String
|
let deviceId = pigeonVar_list[0] as! String
|
||||||
let name: String? = nilOrValue(__pigeon_list[1])
|
let name: String? = nilOrValue(pigeonVar_list[1])
|
||||||
let isPaired: Bool? = nilOrValue(__pigeon_list[2])
|
let isPaired: Bool? = nilOrValue(pigeonVar_list[2])
|
||||||
let rssi: Int64? = isNullish(__pigeon_list[3]) ? nil : (__pigeon_list[3] is Int64? ? __pigeon_list[3] as! Int64? : Int64(__pigeon_list[3] as! Int32))
|
let rssi: Int64? = nilOrValue(pigeonVar_list[3])
|
||||||
let manufacturerDataList: [UniversalManufacturerData?]? = nilOrValue(__pigeon_list[4])
|
let manufacturerDataList: [UniversalManufacturerData]? = nilOrValue(pigeonVar_list[4])
|
||||||
let services: [String?]? = nilOrValue(__pigeon_list[5])
|
let services: [String]? = nilOrValue(pigeonVar_list[5])
|
||||||
|
|
||||||
return UniversalBleScanResult(
|
return UniversalBleScanResult(
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
@@ -110,12 +112,14 @@ struct UniversalBleScanResult {
|
|||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalBleService {
|
struct UniversalBleService {
|
||||||
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(_ __pigeon_list: [Any?]) -> UniversalBleService? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleService? {
|
||||||
let uuid = __pigeon_list[0] as! String
|
let uuid = pigeonVar_list[0] as! String
|
||||||
let characteristics: [UniversalBleCharacteristic?]? = nilOrValue(__pigeon_list[1])
|
let characteristics: [UniversalBleCharacteristic]? = nilOrValue(pigeonVar_list[1])
|
||||||
|
|
||||||
return UniversalBleService(
|
return UniversalBleService(
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
@@ -133,12 +137,14 @@ struct UniversalBleService {
|
|||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalBleCharacteristic {
|
struct UniversalBleCharacteristic {
|
||||||
var uuid: String
|
var uuid: String
|
||||||
var properties: [Int64?]
|
var properties: [Int64]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalBleCharacteristic? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleCharacteristic? {
|
||||||
let uuid = __pigeon_list[0] as! String
|
let uuid = pigeonVar_list[0] as! String
|
||||||
let properties = __pigeon_list[1] as! [Int64?]
|
let properties = pigeonVar_list[1] as! [Int64]
|
||||||
|
|
||||||
return UniversalBleCharacteristic(
|
return UniversalBleCharacteristic(
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
@@ -157,15 +163,17 @@ struct UniversalBleCharacteristic {
|
|||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents data sent in messages.
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
struct UniversalScanFilter {
|
struct UniversalScanFilter {
|
||||||
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(_ __pigeon_list: [Any?]) -> UniversalScanFilter? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanFilter? {
|
||||||
let withServices = __pigeon_list[0] as! [String?]
|
let withServices = pigeonVar_list[0] as! [String]
|
||||||
let withNamePrefix = __pigeon_list[1] as! [String?]
|
let withNamePrefix = pigeonVar_list[1] as! [String]
|
||||||
let withManufacturerData = __pigeon_list[2] as! [UniversalManufacturerDataFilter?]
|
let withManufacturerData = pigeonVar_list[2] as! [UniversalManufacturerDataFilter]
|
||||||
|
|
||||||
return UniversalScanFilter(
|
return UniversalScanFilter(
|
||||||
withServices: withServices,
|
withServices: withServices,
|
||||||
@@ -188,11 +196,13 @@ struct UniversalManufacturerDataFilter {
|
|||||||
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(_ __pigeon_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
||||||
let companyIdentifier = __pigeon_list[0] is Int64 ? __pigeon_list[0] as! Int64 : Int64(__pigeon_list[0] as! Int32)
|
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||||
let data: FlutterStandardTypedData? = nilOrValue(__pigeon_list[1])
|
let data: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[1])
|
||||||
let mask: FlutterStandardTypedData? = nilOrValue(__pigeon_list[2])
|
let mask: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[2])
|
||||||
|
|
||||||
return UniversalManufacturerDataFilter(
|
return UniversalManufacturerDataFilter(
|
||||||
companyIdentifier: companyIdentifier,
|
companyIdentifier: companyIdentifier,
|
||||||
@@ -214,10 +224,12 @@ struct UniversalManufacturerData {
|
|||||||
var companyIdentifier: Int64
|
var companyIdentifier: Int64
|
||||||
var data: FlutterStandardTypedData
|
var data: FlutterStandardTypedData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalManufacturerData? {
|
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerData? {
|
||||||
let companyIdentifier = __pigeon_list[0] is Int64 ? __pigeon_list[0] as! Int64 : Int64(__pigeon_list[0] as! Int32)
|
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||||
let data = __pigeon_list[1] as! FlutterStandardTypedData
|
let data = pigeonVar_list[1] as! FlutterStandardTypedData
|
||||||
|
|
||||||
return UniversalManufacturerData(
|
return UniversalManufacturerData(
|
||||||
companyIdentifier: companyIdentifier,
|
companyIdentifier: companyIdentifier,
|
||||||
@@ -231,6 +243,7 @@ struct UniversalManufacturerData {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
@@ -416,7 +429,7 @@ class UniversalBlePlatformChannelSetup {
|
|||||||
let deviceIdArg = args[0] as! String
|
let deviceIdArg = args[0] as! String
|
||||||
let serviceArg = args[1] as! String
|
let serviceArg = args[1] as! String
|
||||||
let characteristicArg = args[2] as! String
|
let characteristicArg = args[2] as! String
|
||||||
let bleInputPropertyArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
let bleInputPropertyArg = args[3] as! Int64
|
||||||
api.setNotifiable(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, bleInputProperty: bleInputPropertyArg) { result in
|
api.setNotifiable(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, bleInputProperty: bleInputPropertyArg) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
@@ -470,7 +483,7 @@ class UniversalBlePlatformChannelSetup {
|
|||||||
requestMtuChannel.setMessageHandler { message, reply in
|
requestMtuChannel.setMessageHandler { message, reply in
|
||||||
let args = message as! [Any?]
|
let args = message as! [Any?]
|
||||||
let deviceIdArg = args[0] as! String
|
let deviceIdArg = args[0] as! String
|
||||||
let expectedMtuArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
let expectedMtuArg = args[1] as! Int64
|
||||||
api.requestMtu(deviceId: deviceIdArg, expectedMtu: expectedMtuArg) { result in
|
api.requestMtu(deviceId: deviceIdArg, expectedMtu: expectedMtuArg) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let res):
|
case .success(let res):
|
||||||
@@ -491,7 +504,7 @@ class UniversalBlePlatformChannelSetup {
|
|||||||
let serviceArg = args[1] as! String
|
let serviceArg = args[1] as! String
|
||||||
let characteristicArg = args[2] as! String
|
let characteristicArg = args[2] as! String
|
||||||
let valueArg = args[3] as! FlutterStandardTypedData
|
let valueArg = args[3] as! FlutterStandardTypedData
|
||||||
let bleOutputPropertyArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32)
|
let bleOutputPropertyArg = args[4] as! Int64
|
||||||
api.writeValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, value: valueArg, bleOutputProperty: bleOutputPropertyArg) { result in
|
api.writeValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, value: valueArg, bleOutputProperty: bleOutputPropertyArg) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
@@ -595,7 +608,7 @@ protocol UniversalBleCallbackChannelProtocol {
|
|||||||
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
}
|
}
|
||||||
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
@@ -679,10 +692,10 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||||
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged\(messageChannelSuffix)"
|
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged\(messageChannelSuffix)"
|
||||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||||
channel.sendMessage([deviceIdArg, connectedArg] as [Any?]) { response in
|
channel.sendMessage([deviceIdArg, connectedArg, errorArg] as [Any?]) { response in
|
||||||
guard let listResponse = response as? [Any?] else {
|
guard let listResponse = response as? [Any?] else {
|
||||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -104,11 +104,11 @@ extension CBManagerState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Error {
|
extension Error {
|
||||||
func toFlutterError() -> FlutterError {
|
func toPigeonError() -> 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 FlutterError(code: errorCode, message: errorDescription, details: nil)
|
return PigeonError(code: errorCode, message: errorDescription, details: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ 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(FlutterError(code: "NotSupported", message: nil, details: nil)))
|
completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func startScan(filter: UniversalScanFilter?) throws {
|
func startScan(filter: UniversalScanFilter?) throws {
|
||||||
@@ -117,7 +117,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(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,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(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,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(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,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(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,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 = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(
|
completion(
|
||||||
Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -193,22 +193,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 = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if bleInputProperty == BleInputProperty.notification.rawValue && !gattCharacteristic.properties.contains(.notify) {
|
if bleInputProperty == BleInputProperty.notification.rawValue && !gattCharacteristic.properties.contains(.notify) {
|
||||||
completion(Result.failure(FlutterError(code: "InvalidAction", message: "Characteristic does not support notify", details: nil)))
|
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support notify", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if bleInputProperty == BleInputProperty.indication.rawValue && !gattCharacteristic.properties.contains(.indicate) {
|
if bleInputProperty == BleInputProperty.indication.rawValue && !gattCharacteristic.properties.contains(.indicate) {
|
||||||
completion(Result.failure(FlutterError(code: "InvalidAction", message: "Characteristic does not support indicate", details: nil)))
|
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support indicate", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,15 +219,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 = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !gattCharacteristic.properties.contains(.read) {
|
if !gattCharacteristic.properties.contains(.read) {
|
||||||
completion(Result.failure(FlutterError(code: "InvalidAction", message: "Characteristic does not support read", details: nil)))
|
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support read", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
peripheral.readValue(for: gattCharacteristic)
|
peripheral.readValue(for: gattCharacteristic)
|
||||||
@@ -236,11 +236,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 = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,12 +248,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(FlutterError(code: "InvalidAction", message: "Characteristic does not support write withResponse", details: nil)))
|
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withResponse", details: nil)))
|
||||||
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(FlutterError(code: "InvalidAction", message: "Characteristic does not support write withoutResponse", details: nil)))
|
completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withoutResponse", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,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 = discoveredPeripherals[deviceId] else {
|
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||||
completion(Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mtu = peripheral.maximumWriteValueLength(for: CBCharacteristicWriteType.withoutResponse)
|
let mtu = peripheral.maximumWriteValueLength(for: CBCharacteristicWriteType.withoutResponse)
|
||||||
@@ -279,15 +279,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(FlutterError(code: "NotSupported", message: nil, details: nil)))
|
completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func pair(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
func pair(deviceId _: String, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||||
completion(Result.failure(FlutterError(code: "Implemented in Dart", message: nil, details: nil)))
|
completion(Result.failure(PigeonError(code: "Implemented in Dart", message: nil, details: nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func unPair(deviceId _: String) throws {
|
func unPair(deviceId _: String) throws {
|
||||||
throw FlutterError(code: "NotSupported", message: nil, details: nil)
|
throw PigeonError(code: "NotSupported", message: nil, details: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
||||||
@@ -345,17 +345,17 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
public func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: true) { _ in }
|
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: true, error: nil) { _ in }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
||||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false) { _ in }
|
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: nil) { _ in }
|
||||||
// Cleanup on disconnect
|
|
||||||
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
public func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||||
print("Failed to connect: \(peripheral.uuid.uuidString): \(String(describing: error))")
|
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: error?.localizedDescription) { _ in }
|
||||||
|
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) {
|
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) {
|
||||||
@@ -397,8 +397,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 flutterError = error?.toFlutterError() {
|
if let pigeonError = error?.toPigeonError() {
|
||||||
future.result(Result.failure(flutterError))
|
future.result(Result.failure(pigeonError))
|
||||||
} else {
|
} else {
|
||||||
future.result(Result.success({}()))
|
future.result(Result.success({}()))
|
||||||
}
|
}
|
||||||
@@ -411,8 +411,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 flutterError = error?.toFlutterError() {
|
if let pigeonError = error?.toPigeonError() {
|
||||||
future.result(Result.failure(flutterError))
|
future.result(Result.failure(pigeonError))
|
||||||
} else {
|
} else {
|
||||||
future.result(Result.success({}()))
|
future.result(Result.success({}()))
|
||||||
}
|
}
|
||||||
@@ -437,13 +437,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 flutterError = error?.toFlutterError() {
|
if let pigeonError = error?.toPigeonError() {
|
||||||
future.result(Result.failure(flutterError))
|
future.result(Result.failure(pigeonError))
|
||||||
} 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(FlutterError(code: "ReadFailed", message: "No value", details: nil)))
|
future.result(Result.failure(PigeonError(code: "ReadFailed", message: "No value", details: nil)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -456,7 +456,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
|||||||
extension String {
|
extension String {
|
||||||
func getPeripheral() throws -> CBPeripheral {
|
func getPeripheral() throws -> CBPeripheral {
|
||||||
guard let peripheral = discoveredPeripherals[self] else {
|
guard let peripheral = discoveredPeripherals[self] else {
|
||||||
throw FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)
|
throw PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)
|
||||||
}
|
}
|
||||||
return peripheral
|
return peripheral
|
||||||
}
|
}
|
||||||
@@ -466,11 +466,9 @@ extension [String] {
|
|||||||
func toCBUUID() throws -> [CBUUID] {
|
func toCBUUID() throws -> [CBUUID] {
|
||||||
return try compactMap { serviceUUID in
|
return try compactMap { serviceUUID in
|
||||||
guard UUID(uuidString: serviceUUID.validFullUUID) != nil else {
|
guard UUID(uuidString: serviceUUID.validFullUUID) != nil else {
|
||||||
throw FlutterError(code: "IllegalArgument", message: "Invalid service UUID:\(serviceUUID)", details: nil)
|
throw PigeonError(code: "IllegalArgument", message: "Invalid service UUID:\(serviceUUID)", details: nil)
|
||||||
}
|
}
|
||||||
return CBUUID(string: serviceUUID)
|
return CBUUID(string: serviceUUID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FlutterError: Error {}
|
|
||||||
|
|||||||
@@ -59,8 +59,14 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleConnectionChange(String deviceId, bool isConnected) {
|
void _handleConnectionChange(
|
||||||
print('_handleConnectionChange $deviceId, $isConnected');
|
String deviceId,
|
||||||
|
bool isConnected,
|
||||||
|
String? error,
|
||||||
|
) {
|
||||||
|
print(
|
||||||
|
'_handleConnectionChange $deviceId, $isConnected ${error != null ? 'Error: $error' : ''}',
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
if (deviceId == widget.deviceId) {
|
if (deviceId == widget.deviceId) {
|
||||||
this.isConnected = isConnected;
|
this.isConnected = isConnected;
|
||||||
@@ -248,12 +254,12 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
|||||||
enabled: !isConnected,
|
enabled: !isConnected,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
try {
|
try {
|
||||||
bool connected = await UniversalBle.connect(
|
await UniversalBle.connect(
|
||||||
widget.deviceId,
|
widget.deviceId,
|
||||||
);
|
);
|
||||||
_addLog("ConnectionResult", connected);
|
_addLog("ConnectionResult", true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_addLog('ConnectError', e);
|
_addLog('ConnectError (${e.runtimeType})', e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -405,14 +411,18 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
|||||||
PlatformButton(
|
PlatformButton(
|
||||||
enabled: BleCapabilities.supportsAllPairingKinds,
|
enabled: BleCapabilities.supportsAllPairingKinds,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
bool? pairingResult = await UniversalBle.pair(
|
try {
|
||||||
widget.deviceId,
|
await UniversalBle.pair(
|
||||||
// pairingCommand: BleCommand(
|
widget.deviceId,
|
||||||
// service: "",
|
// pairingCommand: BleCommand(
|
||||||
// characteristic: "",
|
// service: "",
|
||||||
// ),
|
// characteristic: "",
|
||||||
);
|
// ),
|
||||||
_addLog("Pairing Result", pairingResult);
|
);
|
||||||
|
_addLog("Pairing Result", true);
|
||||||
|
} catch (e) {
|
||||||
|
_addLog('PairError (${e.runtimeType})', e);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
text: 'Pair',
|
text: 'Pair',
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class BleConnectionUpdate {
|
||||||
|
final bool isConnected;
|
||||||
|
final String? error;
|
||||||
|
|
||||||
|
BleConnectionUpdate({
|
||||||
|
required this.isConnected,
|
||||||
|
this.error,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -7,6 +7,11 @@ class BleService {
|
|||||||
BleService(String uuid, this.characteristics) {
|
BleService(String uuid, this.characteristics) {
|
||||||
this.uuid = BleUuidParser.string(uuid);
|
this.uuid = BleUuidParser.string(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'BleService{uuid: $uuid, characteristics: $characteristics}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BleCharacteristic {
|
class BleCharacteristic {
|
||||||
@@ -16,6 +21,11 @@ class BleCharacteristic {
|
|||||||
BleCharacteristic(String uuid, this.properties) {
|
BleCharacteristic(String uuid, this.properties) {
|
||||||
this.uuid = BleUuidParser.string(uuid);
|
this.uuid = BleUuidParser.string(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'BleCharacteristic{uuid: $uuid, properties: $properties}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CharacteristicProperty {
|
enum CharacteristicProperty {
|
||||||
@@ -32,4 +42,7 @@ enum CharacteristicProperty {
|
|||||||
|
|
||||||
factory CharacteristicProperty.parse(int index) =>
|
factory CharacteristicProperty.parse(int index) =>
|
||||||
CharacteristicProperty.values[index];
|
CharacteristicProperty.values[index];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export 'package:universal_ble/src/models/ble_connection_update.dart';
|
||||||
export 'package:universal_ble/src/models/manufacturer_data.dart';
|
export 'package:universal_ble/src/models/manufacturer_data.dart';
|
||||||
export 'package:universal_ble/src/models/platform_config.dart';
|
export 'package:universal_ble/src/models/platform_config.dart';
|
||||||
export 'package:universal_ble/src/models/queue_type.dart';
|
export 'package:universal_ble/src/models/queue_type.dart';
|
||||||
|
|||||||
+114
-75
@@ -5,6 +5,7 @@ import 'package:universal_ble/src/ble_command_queue.dart';
|
|||||||
import 'package:universal_ble/src/universal_ble_linux/universal_ble_linux.dart';
|
import 'package:universal_ble/src/universal_ble_linux/universal_ble_linux.dart';
|
||||||
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart';
|
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart';
|
||||||
import 'package:universal_ble/src/universal_ble_web/universal_ble_web.dart';
|
import 'package:universal_ble/src/universal_ble_web/universal_ble_web.dart';
|
||||||
|
import 'package:universal_ble/src/universal_logger.dart';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
|
|
||||||
class UniversalBle {
|
class UniversalBle {
|
||||||
@@ -31,7 +32,7 @@ class UniversalBle {
|
|||||||
/// [QueueType.none] will execute all commands in parallel.
|
/// [QueueType.none] will execute all commands in parallel.
|
||||||
static set queueType(QueueType queueType) {
|
static set queueType(QueueType queueType) {
|
||||||
_bleCommandQueue.queueType = queueType;
|
_bleCommandQueue.queueType = queueType;
|
||||||
UniversalBlePlatform.logInfo('Queue ${queueType.name}');
|
UniversalLogger.logInfo('Queue ${queueType.name}');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Bluetooth availability state.
|
/// Get Bluetooth availability state.
|
||||||
@@ -70,28 +71,37 @@ class UniversalBle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connection stream of a device
|
/// Connection stream of a device
|
||||||
Stream<bool> connectionStream(String deviceId) =>
|
static Stream<BleConnectionUpdate> connectionStream(String deviceId) =>
|
||||||
_platform.connectionStream(deviceId);
|
_platform.connectionStream(deviceId);
|
||||||
|
|
||||||
/// Connect to a device.
|
/// Connect to a device.
|
||||||
/// It is advised to stop scanning before connecting.
|
/// It is advised to stop scanning before connecting.
|
||||||
/// It might throw errors if device is not connectable.
|
/// It throws error if device connection fails.
|
||||||
/// `connectionTimeout` is supported on Web only.
|
/// Default connection timeout is 60 sec.
|
||||||
static Future<bool> connect(
|
/// Can throw `ConnectionException` or `PlatformException`.
|
||||||
|
static Future<void> connect(
|
||||||
String deviceId, {
|
String deviceId, {
|
||||||
Duration? connectionTimeout,
|
Duration? connectionTimeout,
|
||||||
}) async {
|
}) async {
|
||||||
|
connectionTimeout ??= const Duration(seconds: 60);
|
||||||
StreamSubscription? connectionSubscription;
|
StreamSubscription? connectionSubscription;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Completer<bool> completer = Completer();
|
Completer<bool> completer = Completer();
|
||||||
|
|
||||||
connectionSubscription =
|
connectionSubscription = connectionStream(deviceId).listen(
|
||||||
_platform.connectionStream(deviceId).listen((bool event) {
|
(BleConnectionUpdate event) {
|
||||||
connectionSubscription?.cancel();
|
connectionSubscription?.cancel();
|
||||||
if (!completer.isCompleted) {
|
if (!completer.isCompleted) {
|
||||||
completer.complete(event);
|
String? error = event.error;
|
||||||
}
|
if (error != null) {
|
||||||
});
|
completer.completeError(ConnectionException(error));
|
||||||
|
} else {
|
||||||
|
completer.complete(event.isConnected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
_platform
|
_platform
|
||||||
.connect(deviceId, connectionTimeout: connectionTimeout)
|
.connect(deviceId, connectionTimeout: connectionTimeout)
|
||||||
@@ -99,15 +109,14 @@ class UniversalBle {
|
|||||||
(error) {
|
(error) {
|
||||||
if (completer.isCompleted == false) {
|
if (completer.isCompleted == false) {
|
||||||
connectionSubscription?.cancel();
|
connectionSubscription?.cancel();
|
||||||
completer.completeError(error);
|
completer.completeError(ConnectionException(error));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (connectionTimeout != null) {
|
if (!await completer.future.timeout(connectionTimeout)) {
|
||||||
return await completer.future.timeout(connectionTimeout);
|
throw ConnectionException("Failed to connect");
|
||||||
}
|
}
|
||||||
return await completer.future;
|
|
||||||
} finally {
|
} finally {
|
||||||
connectionSubscription?.cancel();
|
connectionSubscription?.cancel();
|
||||||
}
|
}
|
||||||
@@ -211,36 +220,65 @@ class UniversalBle {
|
|||||||
static Future<bool?> isPaired(
|
static Future<bool?> isPaired(
|
||||||
String deviceId, {
|
String deviceId, {
|
||||||
BleCommand? pairingCommand,
|
BleCommand? pairingCommand,
|
||||||
|
Duration? connectionTimeout,
|
||||||
}) async {
|
}) async {
|
||||||
if (BleCapabilities.hasSystemPairingApi) {
|
if (BleCapabilities.hasSystemPairingApi) {
|
||||||
return _bleCommandQueue.queueCommand(
|
return _bleCommandQueue.queueCommand(
|
||||||
() => _platform.isPaired(deviceId),
|
() => _platform.isPaired(deviceId),
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
);
|
);
|
||||||
} else if (pairingCommand != null) {
|
|
||||||
return _connectAndExecuteBleCommand(deviceId, pairingCommand,
|
|
||||||
updateCallbackValue: false);
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
if (pairingCommand == null) {
|
||||||
|
UniversalLogger.logWarning("PairingCommand required to get result");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await _connectAndExecuteBleCommand(
|
||||||
|
deviceId,
|
||||||
|
pairingCommand,
|
||||||
|
connectionTimeout: connectionTimeout,
|
||||||
|
updateCallbackValue: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Because pairingCommand will be never null, so we wont get Unknown result here
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
UniversalLogger.logError("ExecuteBleCommandFailed: $e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pair a device.
|
/// Pair a device.
|
||||||
///
|
///
|
||||||
|
/// It throws error if pairing fails.
|
||||||
|
///
|
||||||
/// On `Apple` and `Web`, it only works on devices with encrypted characteristics.
|
/// On `Apple` and `Web`, it only works on devices with encrypted characteristics.
|
||||||
/// It returns null if there is no readable characteristic.
|
/// It is advised to pass a pairingCommand with an encrypted read or write characteristic.
|
||||||
|
/// When not passing a pairingCommand, you should afterwards use [isPaired] with a pairingCommand
|
||||||
|
/// to verify the pairing state.
|
||||||
///
|
///
|
||||||
/// You can optionally pass a pairingCommand if you know an encrypted read or write characteristic.
|
/// On `Web/Windows` and `Web/Linux`, it does not work for devices that use `ConfirmOnly` pairing.
|
||||||
/// If you do, it returns true if it can successfully execute the command after pairing.
|
/// Can throw `PairingException`, `ConnectionException` or `PlatformException`.
|
||||||
///
|
static Future<void> pair(
|
||||||
/// On `Web/Windows` and `Web/Linux`, it does not work for devices where `BleCapabilities.triggersConfirmOnlyPairing` is false.
|
|
||||||
static Future<bool?> pair(
|
|
||||||
String deviceId, {
|
String deviceId, {
|
||||||
BleCommand? pairingCommand,
|
BleCommand? pairingCommand,
|
||||||
|
Duration? connectionTimeout,
|
||||||
}) async {
|
}) async {
|
||||||
if (BleCapabilities.hasSystemPairingApi) {
|
if (BleCapabilities.hasSystemPairingApi) {
|
||||||
return _platform.pair(deviceId);
|
bool paired = await _platform.pair(deviceId);
|
||||||
|
if (!paired) throw PairingException();
|
||||||
|
} else {
|
||||||
|
if (pairingCommand == null) {
|
||||||
|
UniversalLogger.logWarning("PairingCommand required to get result");
|
||||||
|
}
|
||||||
|
await _connectAndExecuteBleCommand(
|
||||||
|
deviceId,
|
||||||
|
pairingCommand,
|
||||||
|
connectionTimeout: connectionTimeout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _connectAndExecuteBleCommand(deviceId, pairingCommand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpair a device.
|
/// Unpair a device.
|
||||||
@@ -303,38 +341,32 @@ class UniversalBle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool?> _connectAndExecuteBleCommand(
|
static Future<void> _connectAndExecuteBleCommand(
|
||||||
String deviceId,
|
String deviceId,
|
||||||
BleCommand? bleCommand, {
|
BleCommand? bleCommand, {
|
||||||
|
Duration? connectionTimeout,
|
||||||
bool updateCallbackValue = false,
|
bool updateCallbackValue = false,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
// Try to connect first
|
||||||
if (await getConnectionState(deviceId) != BleConnectionState.connected) {
|
if (await getConnectionState(deviceId) != BleConnectionState.connected) {
|
||||||
await connect(deviceId);
|
UniversalLogger.logInfo("Connecting to $deviceId");
|
||||||
}
|
await connect(
|
||||||
|
deviceId,
|
||||||
List<BleService> services = await discoverServices(deviceId);
|
connectionTimeout: connectionTimeout,
|
||||||
|
|
||||||
if (bleCommand == null) {
|
|
||||||
await _attemptPairingReadingAll(deviceId, services);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
bool commandResult =
|
|
||||||
await _executeBleCommand(deviceId, services, bleCommand);
|
|
||||||
if (updateCallbackValue) {
|
|
||||||
_platform.updatePairingState(deviceId, commandResult);
|
|
||||||
}
|
|
||||||
return commandResult;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
UniversalBlePlatform.logInfo(
|
|
||||||
"FailedToPerform EncryptedCharOperation: $e",
|
|
||||||
);
|
);
|
||||||
if (updateCallbackValue) {
|
|
||||||
_platform.updatePairingState(deviceId, false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<BleService> services = await discoverServices(deviceId);
|
||||||
|
UniversalLogger.logInfo("Discovered services: ${services.length}");
|
||||||
|
|
||||||
|
if (bleCommand == null) {
|
||||||
|
// Just attempt pairing
|
||||||
|
await _attemptPairingReadingAll(deviceId, services);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _executeBleCommand(deviceId, services, bleCommand);
|
||||||
|
if (updateCallbackValue) _platform.updatePairingState(deviceId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire and forget, and do not rely on result
|
// Fire and forget, and do not rely on result
|
||||||
@@ -359,12 +391,13 @@ class UniversalBle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
if (!containsReadCharacteristics) {
|
if (!containsReadCharacteristics) {
|
||||||
throw "No readable characteristic found";
|
throw PairingException("No readable characteristic found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> _executeBleCommand(
|
static Future<void> _executeBleCommand(
|
||||||
String deviceId,
|
String deviceId,
|
||||||
List<BleService> services,
|
List<BleService> services,
|
||||||
BleCommand bleCommand,
|
BleCommand bleCommand,
|
||||||
@@ -384,7 +417,7 @@ class UniversalBle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (characteristic == null) {
|
if (characteristic == null) {
|
||||||
return false;
|
throw PairingException("BleCommand not found in discovered services");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if BleCommand Supports Read or Write
|
// Check if BleCommand Supports Read or Write
|
||||||
@@ -396,28 +429,34 @@ class UniversalBle {
|
|||||||
bleOutputProperty = BleOutputProperty.withoutResponse;
|
bleOutputProperty = BleOutputProperty.withoutResponse;
|
||||||
} else if (!characteristic.properties
|
} else if (!characteristic.properties
|
||||||
.contains(CharacteristicProperty.read)) {
|
.contains(CharacteristicProperty.read)) {
|
||||||
return false;
|
throw PairingException(
|
||||||
|
"BleCommand does not support read or write operation",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List? value = bleCommand.writeValue;
|
Uint8List? value = bleCommand.writeValue;
|
||||||
if (value != null && bleOutputProperty != null) {
|
|
||||||
await writeValue(
|
try {
|
||||||
deviceId,
|
if (value != null && bleOutputProperty != null) {
|
||||||
bleCommand.service,
|
await writeValue(
|
||||||
bleCommand.characteristic,
|
deviceId,
|
||||||
value,
|
bleCommand.service,
|
||||||
bleOutputProperty,
|
bleCommand.characteristic,
|
||||||
);
|
value,
|
||||||
} else {
|
bleOutputProperty,
|
||||||
// Fallback to read if supported
|
);
|
||||||
await readValue(
|
} else {
|
||||||
deviceId,
|
// Fallback to read if supported
|
||||||
bleCommand.service,
|
await readValue(
|
||||||
bleCommand.characteristic,
|
deviceId,
|
||||||
timeout: const Duration(seconds: 30),
|
bleCommand.service,
|
||||||
);
|
bleCommand.characteristic,
|
||||||
|
timeout: const Duration(seconds: 30),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw PairingException(e.toString());
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get updates of remaining items of a queue.
|
/// Get updates of remaining items of a queue.
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class ConnectionException implements Exception {
|
||||||
|
late String message;
|
||||||
|
|
||||||
|
ConnectionException([dynamic error]) {
|
||||||
|
message = _errorParser(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => message;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PairingException implements Exception {
|
||||||
|
late String message;
|
||||||
|
|
||||||
|
PairingException([dynamic error]) {
|
||||||
|
message = _errorParser(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => message;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _errorParser(dynamic error) {
|
||||||
|
if (error == null) {
|
||||||
|
return "Failed";
|
||||||
|
} else if (error is PlatformException) {
|
||||||
|
return error.message ?? error.details ?? error.code;
|
||||||
|
} else if (error is String) {
|
||||||
|
return error;
|
||||||
|
} else {
|
||||||
|
return error.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ 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/universal_ble_filter_util.dart';
|
import 'package:universal_ble/src/universal_ble_filter_util.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/universal_logger.dart';
|
||||||
|
|
||||||
class UniversalBleLinux extends UniversalBlePlatform {
|
class UniversalBleLinux extends UniversalBlePlatform {
|
||||||
UniversalBleLinux._();
|
UniversalBleLinux._();
|
||||||
@@ -45,10 +46,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
await _activeAdapter?.setPowered(true);
|
await _activeAdapter?.setPowered(true);
|
||||||
return _activeAdapter?.powered ?? false;
|
return _activeAdapter?.powered ?? false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logError('Error enabling bluetooth: $e');
|
||||||
'Error enabling bluetooth: $e',
|
|
||||||
isError: true,
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,10 +111,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logError("stopScan error: $e");
|
||||||
"stopScan error: $e",
|
|
||||||
isError: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +154,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
await device.propertiesChanged.firstWhere((element) {
|
await device.propertiesChanged.firstWhere((element) {
|
||||||
if (element.contains(BluezProperty.connected)) {
|
if (element.contains(BluezProperty.connected)) {
|
||||||
if (!device.connected) {
|
if (!device.connected) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
"DiscoverServicesFailed: Device disconnected",
|
"DiscoverServicesFailed: Device disconnected",
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
@@ -167,7 +162,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
}
|
}
|
||||||
return element.contains(BluezProperty.servicesResolved);
|
return element.contains(BluezProperty.servicesResolved);
|
||||||
}).timeout(const Duration(seconds: 10), onTimeout: () {
|
}).timeout(const Duration(seconds: 10), onTimeout: () {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
"DiscoverServicesFailed: Timeout",
|
"DiscoverServicesFailed: Timeout",
|
||||||
);
|
);
|
||||||
return [];
|
return [];
|
||||||
@@ -238,8 +233,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
"UnhandledCharValuePropertyChange: $property");
|
"UnhandledCharValuePropertyChange: $property",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -351,8 +347,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
.map((e) => e.uuid.toString())
|
.map((e) => e.uuid.toString())
|
||||||
.any((service) => withServices.contains(service));
|
.any((service) => withServices.contains(service));
|
||||||
} else {
|
} else {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
'Skipping: ${device.address}: Services not resolved yet.');
|
'Skipping: ${device.address}: Services not resolved yet.',
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}).toList();
|
}).toList();
|
||||||
@@ -394,7 +391,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
|
|
||||||
_activeAdapter ??= _client.adapters.first;
|
_activeAdapter ??= _client.adapters.first;
|
||||||
|
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
'BleAdapter: ${_activeAdapter?.name} - ${_activeAdapter?.address}',
|
'BleAdapter: ${_activeAdapter?.name} - ${_activeAdapter?.address}',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -411,7 +408,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
break;
|
break;
|
||||||
case BluezProperty.propertyClass:
|
case BluezProperty.propertyClass:
|
||||||
default:
|
default:
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
"UnhandledPropertyChanged: $property",
|
"UnhandledPropertyChanged: $property",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -426,10 +423,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
_initializationCompleter?.complete();
|
_initializationCompleter?.complete();
|
||||||
_initializationCompleter = null;
|
_initializationCompleter = null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logError('Error initializing: $e');
|
||||||
'Error initializing: $e',
|
|
||||||
isError: true,
|
|
||||||
);
|
|
||||||
_initializationCompleter?.completeError(e);
|
_initializationCompleter?.completeError(e);
|
||||||
await _client.close();
|
await _client.close();
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -501,7 +495,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
|||||||
case BluezProperty.manufacturerData:
|
case BluezProperty.manufacturerData:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logInfo(
|
||||||
"UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property",
|
"UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property",
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -119,10 +119,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
|||||||
) async {
|
) async {
|
||||||
var devices = await _channel.getSystemDevices(withServices ?? []);
|
var devices = await _channel.getSystemDevices(withServices ?? []);
|
||||||
return List<BleDevice>.from(
|
return List<BleDevice>.from(
|
||||||
devices
|
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
|
||||||
.map((e) => e?.toBleDevice(isSystemDevice: true))
|
|
||||||
.where((e) => e != null)
|
|
||||||
.toList(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +172,8 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
|||||||
availabilityChange(AvailabilityState.parse(state));
|
availabilityChange(AvailabilityState.parse(state));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onConnectionChanged(String deviceId, bool connected) =>
|
void onConnectionChanged(String deviceId, bool connected, String? error) =>
|
||||||
connectionChanged(deviceId, connected);
|
connectionChanged(deviceId, connected, error);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onScanResult(UniversalBleScanResult result) =>
|
void onScanResult(UniversalBleScanResult result) =>
|
||||||
@@ -200,9 +197,9 @@ extension _UniversalBleScanResultExtension on UniversalBleScanResult {
|
|||||||
rssi: rssi,
|
rssi: rssi,
|
||||||
isPaired: isPaired,
|
isPaired: isPaired,
|
||||||
isSystemDevice: isSystemDevice,
|
isSystemDevice: isSystemDevice,
|
||||||
services: services?.nonNulls.map(BleUuidParser.string).toList() ?? [],
|
services: services?.map(BleUuidParser.string).toList() ?? [],
|
||||||
manufacturerDataList: manufacturerDataList?.nonNulls
|
manufacturerDataList: manufacturerDataList
|
||||||
.map((e) => ManufacturerData(e.companyIdentifier, e.data))
|
?.map((e) => ManufacturerData(e.companyIdentifier, e.data))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:universal_ble/universal_ble.dart';
|
import 'package:universal_ble/universal_ble.dart';
|
||||||
|
|
||||||
abstract class UniversalBlePlatform {
|
abstract class UniversalBlePlatform {
|
||||||
StreamController? _connectionStreamController;
|
StreamController<({String deviceId, bool isConnected, String? error})>?
|
||||||
|
_connectionStreamController;
|
||||||
|
|
||||||
final Map<String, bool> _pairStateMap = {};
|
final Map<String, bool> _pairStateMap = {};
|
||||||
|
|
||||||
Future<AvailabilityState> getBluetoothAvailabilityState();
|
Future<AvailabilityState> getBluetoothAvailabilityState();
|
||||||
@@ -57,21 +58,27 @@ abstract class UniversalBlePlatform {
|
|||||||
|
|
||||||
bool receivesAdvertisements(String deviceId) => true;
|
bool receivesAdvertisements(String deviceId) => true;
|
||||||
|
|
||||||
Stream<bool> connectionStream(String deviceId) {
|
Stream<BleConnectionUpdate> connectionStream(String deviceId) {
|
||||||
_setupConnectionStreamIfRequired();
|
_setupConnectionStreamIfRequired();
|
||||||
return _connectionStreamController!.stream
|
return _connectionStreamController!.stream
|
||||||
.where((event) => event.deviceId == deviceId)
|
.where((event) => event.deviceId == deviceId)
|
||||||
.map((event) => event.isConnected);
|
.map((event) => BleConnectionUpdate(
|
||||||
|
isConnected: event.isConnected,
|
||||||
|
error: event.error,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateScanResult(BleDevice bleDevice) {
|
void updateScanResult(BleDevice bleDevice) {
|
||||||
onScanResult?.call(bleDevice);
|
onScanResult?.call(bleDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateConnection(String deviceId, bool isConnected) {
|
void updateConnection(String deviceId, bool isConnected, [String? error]) {
|
||||||
onConnectionChange?.call(deviceId, isConnected);
|
onConnectionChange?.call(deviceId, isConnected, error);
|
||||||
_connectionStreamController
|
_connectionStreamController?.add((
|
||||||
?.add((deviceId: deviceId, isConnected: isConnected));
|
deviceId: deviceId,
|
||||||
|
isConnected: isConnected,
|
||||||
|
error: error,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCharacteristicValue(
|
void updateCharacteristicValue(
|
||||||
@@ -97,17 +104,11 @@ abstract class UniversalBlePlatform {
|
|||||||
OnAvailabilityChange? onAvailabilityChange;
|
OnAvailabilityChange? onAvailabilityChange;
|
||||||
OnPairingStateChange? onPairingStateChange;
|
OnPairingStateChange? onPairingStateChange;
|
||||||
|
|
||||||
static void logInfo(String message, {bool isError = false}) {
|
|
||||||
if (isError) message = '\x1B[31m$message\x1B[31m';
|
|
||||||
log(message, name: 'UniversalBle');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an auto disposable streamController
|
/// Creates an auto disposable streamController
|
||||||
void _setupConnectionStreamIfRequired() {
|
void _setupConnectionStreamIfRequired() {
|
||||||
if (_connectionStreamController != null) return;
|
if (_connectionStreamController != null) return;
|
||||||
|
|
||||||
_connectionStreamController =
|
_connectionStreamController = StreamController.broadcast();
|
||||||
StreamController<({String deviceId, bool isConnected})>.broadcast();
|
|
||||||
|
|
||||||
// Auto dispose if no more subscribers
|
// Auto dispose if no more subscribers
|
||||||
_connectionStreamController?.onCancel = () {
|
_connectionStreamController?.onCancel = () {
|
||||||
@@ -119,7 +120,8 @@ abstract class UniversalBlePlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Callback types
|
// Callback types
|
||||||
typedef OnConnectionChange = void Function(String deviceId, bool isConnected);
|
typedef OnConnectionChange = void Function(
|
||||||
|
String deviceId, bool isConnected, String? error);
|
||||||
|
|
||||||
typedef OnValueChange = void Function(
|
typedef OnValueChange = void Function(
|
||||||
String deviceId, String characteristicId, Uint8List value);
|
String deviceId, String characteristicId, Uint8List value);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ 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/models/model_exports.dart';
|
import 'package:universal_ble/src/models/model_exports.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/universal_logger.dart';
|
||||||
|
|
||||||
class UniversalBleWeb extends UniversalBlePlatform {
|
class UniversalBleWeb extends UniversalBlePlatform {
|
||||||
static UniversalBleWeb? _instance;
|
static UniversalBleWeb? _instance;
|
||||||
@@ -127,10 +128,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
device.advertisementsUseMemory = true;
|
device.advertisementsUseMemory = true;
|
||||||
await device.watchAdvertisements();
|
await device.watchAdvertisements();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logError("WebWatchAdvertisementError: $e");
|
||||||
"WebWatchAdvertisementError: $e",
|
|
||||||
isError: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,9 +393,8 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (optionalServices.isEmpty) {
|
if (optionalServices.isEmpty) {
|
||||||
UniversalBlePlatform.logInfo(
|
UniversalLogger.logError(
|
||||||
"OptionalServices list is empty on web, you have to specify services in the ScanFilter in order to be able to access those after connecting",
|
"OptionalServices list is empty on web, you have to specify services in the ScanFilter in order to be able to access those after connecting",
|
||||||
isError: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
class UniversalLogger {
|
||||||
|
static void logInfo(message) {
|
||||||
|
log(
|
||||||
|
message.toString(),
|
||||||
|
name: 'UniversalBle:INFO',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logError(message) {
|
||||||
|
log(
|
||||||
|
'\x1B[31m$message\x1B[31m',
|
||||||
|
name: 'UniversalBle:ERROR',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logWarning(message) {
|
||||||
|
log(
|
||||||
|
'\x1B[33m$message\x1B[33m',
|
||||||
|
name: 'UniversalBle:WARN',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
library universal_ble;
|
library universal_ble;
|
||||||
|
|
||||||
|
export 'package:universal_ble/src/universal_ble_exceptions.dart';
|
||||||
export 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
export 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
||||||
export 'package:universal_ble/src/universal_ble.dart';
|
export 'package:universal_ble/src/universal_ble.dart';
|
||||||
export 'package:universal_ble/src/models/model_exports.dart';
|
export 'package:universal_ble/src/models/model_exports.dart';
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ abstract class UniversalBleCallbackChannel {
|
|||||||
void onConnectionChanged(
|
void onConnectionChanged(
|
||||||
String deviceId,
|
String deviceId,
|
||||||
bool connected,
|
bool connected,
|
||||||
|
String? error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +108,8 @@ class UniversalBleScanResult {
|
|||||||
final String? name;
|
final String? name;
|
||||||
final bool? isPaired;
|
final bool? isPaired;
|
||||||
final int? rssi;
|
final int? rssi;
|
||||||
final List<UniversalManufacturerData?>? manufacturerDataList;
|
final List<UniversalManufacturerData>? manufacturerDataList;
|
||||||
final List<String?>? services;
|
final List<String>? services;
|
||||||
|
|
||||||
UniversalBleScanResult({
|
UniversalBleScanResult({
|
||||||
required this.name,
|
required this.name,
|
||||||
@@ -122,21 +123,21 @@ class UniversalBleScanResult {
|
|||||||
|
|
||||||
class UniversalBleService {
|
class UniversalBleService {
|
||||||
String uuid;
|
String uuid;
|
||||||
List<UniversalBleCharacteristic?>? characteristics;
|
List<UniversalBleCharacteristic>? characteristics;
|
||||||
UniversalBleService(this.uuid, this.characteristics);
|
UniversalBleService(this.uuid, this.characteristics);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalBleCharacteristic {
|
class UniversalBleCharacteristic {
|
||||||
String uuid;
|
String uuid;
|
||||||
List<int?> properties;
|
List<int> properties;
|
||||||
UniversalBleCharacteristic(this.uuid, this.properties);
|
UniversalBleCharacteristic(this.uuid, this.properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan Filters
|
/// Scan Filters
|
||||||
class UniversalScanFilter {
|
class UniversalScanFilter {
|
||||||
final List<String?> withServices;
|
final List<String> withServices;
|
||||||
final List<String?> withNamePrefix;
|
final List<String> withNamePrefix;
|
||||||
final List<UniversalManufacturerDataFilter?> withManufacturerData;
|
final List<UniversalManufacturerDataFilter> withManufacturerData;
|
||||||
|
|
||||||
UniversalScanFilter(
|
UniversalScanFilter(
|
||||||
this.withServices,
|
this.withServices,
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ dev_dependencies:
|
|||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
pigeon: ^21.1.0
|
pigeon: ^22.4.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
plugin:
|
plugin:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
|
// Autogenerated from Pigeon (v22.4.0), do not edit directly.
|
||||||
// See also: https://pub.dev/packages/pigeon
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
|
||||||
#undef _HAS_EXCEPTIONS
|
#undef _HAS_EXCEPTIONS
|
||||||
@@ -22,10 +22,10 @@ using flutter::EncodableMap;
|
|||||||
using flutter::EncodableValue;
|
using flutter::EncodableValue;
|
||||||
|
|
||||||
FlutterError CreateConnectionError(const std::string channel_name) {
|
FlutterError CreateConnectionError(const std::string channel_name) {
|
||||||
return FlutterError(
|
return FlutterError(
|
||||||
"channel-error",
|
"channel-error",
|
||||||
"Unable to establish connection on channel: '" + channel_name + "'.",
|
"Unable to establish connection on channel: '" + channel_name + "'.",
|
||||||
EncodableValue(""));
|
EncodableValue(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// UniversalBleScanResult
|
// UniversalBleScanResult
|
||||||
@@ -146,7 +146,7 @@ UniversalBleScanResult UniversalBleScanResult::FromEncodableList(const Encodable
|
|||||||
}
|
}
|
||||||
auto& encodable_rssi = list[3];
|
auto& encodable_rssi = list[3];
|
||||||
if (!encodable_rssi.IsNull()) {
|
if (!encodable_rssi.IsNull()) {
|
||||||
decoded.set_rssi(encodable_rssi.LongValue());
|
decoded.set_rssi(std::get<int64_t>(encodable_rssi));
|
||||||
}
|
}
|
||||||
auto& encodable_manufacturer_data_list = list[4];
|
auto& encodable_manufacturer_data_list = list[4];
|
||||||
if (!encodable_manufacturer_data_list.IsNull()) {
|
if (!encodable_manufacturer_data_list.IsNull()) {
|
||||||
@@ -364,7 +364,7 @@ EncodableList UniversalManufacturerDataFilter::ToEncodableList() const {
|
|||||||
|
|
||||||
UniversalManufacturerDataFilter UniversalManufacturerDataFilter::FromEncodableList(const EncodableList& list) {
|
UniversalManufacturerDataFilter UniversalManufacturerDataFilter::FromEncodableList(const EncodableList& list) {
|
||||||
UniversalManufacturerDataFilter decoded(
|
UniversalManufacturerDataFilter decoded(
|
||||||
list[0].LongValue());
|
std::get<int64_t>(list[0]));
|
||||||
auto& encodable_data = list[1];
|
auto& encodable_data = list[1];
|
||||||
if (!encodable_data.IsNull()) {
|
if (!encodable_data.IsNull()) {
|
||||||
decoded.set_data(std::get<std::vector<uint8_t>>(encodable_data));
|
decoded.set_data(std::get<std::vector<uint8_t>>(encodable_data));
|
||||||
@@ -412,36 +412,42 @@ EncodableList UniversalManufacturerData::ToEncodableList() const {
|
|||||||
|
|
||||||
UniversalManufacturerData UniversalManufacturerData::FromEncodableList(const EncodableList& list) {
|
UniversalManufacturerData UniversalManufacturerData::FromEncodableList(const EncodableList& list) {
|
||||||
UniversalManufacturerData decoded(
|
UniversalManufacturerData decoded(
|
||||||
list[0].LongValue(),
|
std::get<int64_t>(list[0]),
|
||||||
std::get<std::vector<uint8_t>>(list[1]));
|
std::get<std::vector<uint8_t>>(list[1]));
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PigeonCodecSerializer::PigeonCodecSerializer() {}
|
PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {}
|
||||||
|
|
||||||
EncodableValue PigeonCodecSerializer::ReadValueOfType(
|
EncodableValue PigeonInternalCodecSerializer::ReadValueOfType(
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
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))));
|
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
case 130:
|
}
|
||||||
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
case 130: {
|
||||||
case 131:
|
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
}
|
||||||
case 132:
|
case 131: {
|
||||||
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
case 133:
|
}
|
||||||
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
case 132: {
|
||||||
case 134:
|
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
}
|
||||||
|
case 133: {
|
||||||
|
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
|
}
|
||||||
|
case 134: {
|
||||||
|
return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
|
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PigeonCodecSerializer::WriteValue(
|
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)) {
|
||||||
@@ -481,7 +487,7 @@ void PigeonCodecSerializer::WriteValue(
|
|||||||
|
|
||||||
/// The codec used by UniversalBlePlatformChannel.
|
/// The codec used by UniversalBlePlatformChannel.
|
||||||
const flutter::StandardMessageCodec& UniversalBlePlatformChannel::GetCodec() {
|
const flutter::StandardMessageCodec& UniversalBlePlatformChannel::GetCodec() {
|
||||||
return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance());
|
return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
|
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
|
||||||
@@ -1019,7 +1025,7 @@ UniversalBleCallbackChannel::UniversalBleCallbackChannel(
|
|||||||
message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {}
|
message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {}
|
||||||
|
|
||||||
const flutter::StandardMessageCodec& UniversalBleCallbackChannel::GetCodec() {
|
const flutter::StandardMessageCodec& UniversalBleCallbackChannel::GetCodec() {
|
||||||
return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance());
|
return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniversalBleCallbackChannel::OnAvailabilityChanged(
|
void UniversalBleCallbackChannel::OnAvailabilityChanged(
|
||||||
@@ -1133,6 +1139,7 @@ void UniversalBleCallbackChannel::OnValueChanged(
|
|||||||
void UniversalBleCallbackChannel::OnConnectionChanged(
|
void UniversalBleCallbackChannel::OnConnectionChanged(
|
||||||
const std::string& device_id_arg,
|
const std::string& device_id_arg,
|
||||||
bool connected_arg,
|
bool connected_arg,
|
||||||
|
const std::string* error_arg,
|
||||||
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) {
|
||||||
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged" + message_channel_suffix_;
|
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged" + message_channel_suffix_;
|
||||||
@@ -1140,6 +1147,7 @@ void UniversalBleCallbackChannel::OnConnectionChanged(
|
|||||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||||
EncodableValue(device_id_arg),
|
EncodableValue(device_id_arg),
|
||||||
EncodableValue(connected_arg),
|
EncodableValue(connected_arg),
|
||||||
|
error_arg ? EncodableValue(*error_arg) : EncodableValue(),
|
||||||
});
|
});
|
||||||
channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
|
// Autogenerated from Pigeon (v22.4.0), 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,7 @@ template<class T> class ErrorOr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Generated class from Pigeon that represents data sent in messages.
|
// Generated class from Pigeon that represents data sent in messages.
|
||||||
class UniversalBleScanResult {
|
class UniversalBleScanResult {
|
||||||
public:
|
public:
|
||||||
@@ -101,7 +102,7 @@ class UniversalBleScanResult {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
std::string device_id_;
|
std::string device_id_;
|
||||||
std::optional<std::string> name_;
|
std::optional<std::string> name_;
|
||||||
std::optional<bool> is_paired_;
|
std::optional<bool> is_paired_;
|
||||||
@@ -136,7 +137,7 @@ class UniversalBleService {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
std::string uuid_;
|
std::string uuid_;
|
||||||
std::optional<flutter::EncodableList> characteristics_;
|
std::optional<flutter::EncodableList> characteristics_;
|
||||||
|
|
||||||
@@ -163,7 +164,7 @@ class UniversalBleCharacteristic {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
std::string uuid_;
|
std::string uuid_;
|
||||||
flutter::EncodableList properties_;
|
flutter::EncodableList properties_;
|
||||||
|
|
||||||
@@ -196,7 +197,7 @@ class UniversalScanFilter {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
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_;
|
||||||
@@ -233,7 +234,7 @@ class UniversalManufacturerDataFilter {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
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_;
|
||||||
@@ -261,17 +262,18 @@ class UniversalManufacturerData {
|
|||||||
flutter::EncodableList ToEncodableList() const;
|
flutter::EncodableList ToEncodableList() const;
|
||||||
friend class UniversalBlePlatformChannel;
|
friend class UniversalBlePlatformChannel;
|
||||||
friend class UniversalBleCallbackChannel;
|
friend class UniversalBleCallbackChannel;
|
||||||
friend class PigeonCodecSerializer;
|
friend class PigeonInternalCodecSerializer;
|
||||||
int64_t company_identifier_;
|
int64_t company_identifier_;
|
||||||
std::vector<uint8_t> data_;
|
std::vector<uint8_t> data_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PigeonCodecSerializer : public flutter::StandardCodecSerializer {
|
|
||||||
|
class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer {
|
||||||
public:
|
public:
|
||||||
PigeonCodecSerializer();
|
PigeonInternalCodecSerializer();
|
||||||
inline static PigeonCodecSerializer& GetInstance() {
|
inline static PigeonInternalCodecSerializer& GetInstance() {
|
||||||
static PigeonCodecSerializer sInstance;
|
static PigeonInternalCodecSerializer sInstance;
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +389,7 @@ class UniversalBleCallbackChannel {
|
|||||||
void OnConnectionChanged(
|
void OnConnectionChanged(
|
||||||
const std::string& device_id,
|
const std::string& device_id,
|
||||||
bool connected,
|
bool connected,
|
||||||
|
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);
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace universal_ble
|
|||||||
CleanConnection(deviceAddress);
|
CleanConnection(deviceAddress);
|
||||||
// TODO: send disconnect event only after disconnect is complete
|
// TODO: send disconnect event only after disconnect is complete
|
||||||
uiThreadHandler_.Post([deviceAddress]
|
uiThreadHandler_.Post([deviceAddress]
|
||||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(deviceAddress), false, SuccessCallback, ErrorCallback); });
|
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(deviceAddress), false, nullptr, SuccessCallback, ErrorCallback); });
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
};
|
};
|
||||||
@@ -925,7 +925,7 @@ namespace universal_ble
|
|||||||
{
|
{
|
||||||
std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl;
|
std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl;
|
||||||
uiThreadHandler_.Post([bluetoothAddress]
|
uiThreadHandler_.Post([bluetoothAddress]
|
||||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, new std::string("Failed to get device"), SuccessCallback, ErrorCallback); });
|
||||||
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
@@ -933,9 +933,10 @@ namespace universal_ble
|
|||||||
auto status = servicesResult.Status();
|
auto status = servicesResult.Status();
|
||||||
if (status != GattCommunicationStatus::Success)
|
if (status != GattCommunicationStatus::Success)
|
||||||
{
|
{
|
||||||
std::cout << "ConnectionFailed: Failed to get services: " << GattCommunicationStatusToString(status) << std::endl;
|
std::string error = GattCommunicationStatusToString(status);
|
||||||
uiThreadHandler_.Post([bluetoothAddress]
|
std::cout << "ConnectionFailed: Failed to get services: " << error << std::endl;
|
||||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
uiThreadHandler_.Post([bluetoothAddress, error]
|
||||||
|
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, &error, SuccessCallback, ErrorCallback); });
|
||||||
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
@@ -972,7 +973,7 @@ namespace universal_ble
|
|||||||
connectedDevices.insert(std::move(pair));
|
connectedDevices.insert(std::move(pair));
|
||||||
std::cout << "ConnectionLog: Connected" << std::endl;
|
std::cout << "ConnectionLog: Connected" << std::endl;
|
||||||
uiThreadHandler_.Post([bluetoothAddress]
|
uiThreadHandler_.Post([bluetoothAddress]
|
||||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), true, SuccessCallback, ErrorCallback); });
|
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), true, nullptr, SuccessCallback, ErrorCallback); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args)
|
void UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args)
|
||||||
@@ -982,7 +983,7 @@ namespace universal_ble
|
|||||||
CleanConnection(sender.BluetoothAddress());
|
CleanConnection(sender.BluetoothAddress());
|
||||||
auto bluetoothAddress = sender.BluetoothAddress();
|
auto bluetoothAddress = sender.BluetoothAddress();
|
||||||
uiThreadHandler_.Post([bluetoothAddress]
|
uiThreadHandler_.Post([bluetoothAddress]
|
||||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, nullptr, SuccessCallback, ErrorCallback); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user