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
|
||||
* BREAKING CHANGE: `scanFilter` filters are now in OR relation
|
||||
* BREAKING CHANGE: `manufacturerDataHead` is removed from `BleDevice`
|
||||
* BREAKING CHANGE: rename `WebConfig` to `WebOptions`
|
||||
* BREAKING CHANGE: rename `ManufacturerDataFilter.data` to `ManufacturerDataFilter.payload`
|
||||
* BREAKING CHANGE: `WebConfig` is now `WebOptions`
|
||||
* 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
|
||||
* Deprecation: `manufacturerData` is deprecated in BleDevice and will be removed in the future
|
||||
* Improve `scanFilter` handling
|
||||
@@ -11,6 +14,7 @@
|
||||
* Auto convert all services passed to `getSystemDevices()`
|
||||
* Return false for receivesAdvertisements on Linux/Web
|
||||
* Add 1s delay in discoverServices on Linux
|
||||
* Add `connectionStream` API to get connection updates as stream
|
||||
|
||||
## 0.12.0
|
||||
* BREAKING CHANGE: `unPair` is now `unpair`
|
||||
@@ -20,7 +24,6 @@
|
||||
* Add `PlatformConfig` property in `StartScan`
|
||||
* Add `WebConfig` property in `PlatformConfig`
|
||||
* Fix notifications for characteristics without cccd on Android
|
||||
* Add `connectionStream` API to get connection updates as stream
|
||||
* Promote Linux to stable
|
||||
|
||||
## 0.11.1
|
||||
|
||||
@@ -153,8 +153,8 @@ UniversalBle.connect(deviceId);
|
||||
UniversalBle.disconnect(deviceId);
|
||||
|
||||
// Get connection/disconnection updates
|
||||
UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
|
||||
debugPrint('OnConnectionChange $deviceId, $isConnected');
|
||||
UniversalBle.onConnectionChange = (String deviceId, bool isConnected, String? error) {
|
||||
debugPrint('OnConnectionChange $deviceId, $isConnected Error: $error');
|
||||
}
|
||||
|
||||
// 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
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
@@ -53,19 +53,18 @@ data class UniversalBleScanResult (
|
||||
val name: String? = null,
|
||||
val isPaired: Boolean? = null,
|
||||
val rssi: Long? = null,
|
||||
val manufacturerDataList: List<UniversalManufacturerData?>? = null,
|
||||
val services: List<String?>? = null
|
||||
|
||||
) {
|
||||
val manufacturerDataList: List<UniversalManufacturerData>? = null,
|
||||
val services: List<String>? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleScanResult {
|
||||
val deviceId = __pigeon_list[0] as String
|
||||
val name = __pigeon_list[1] as String?
|
||||
val isPaired = __pigeon_list[2] as Boolean?
|
||||
val rssi = __pigeon_list[3].let { num -> if (num is Int) num.toLong() else num as Long? }
|
||||
val manufacturerDataList = __pigeon_list[4] as List<UniversalManufacturerData?>?
|
||||
val services = __pigeon_list[5] as List<String?>?
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBleScanResult {
|
||||
val deviceId = pigeonVar_list[0] as String
|
||||
val name = pigeonVar_list[1] as String?
|
||||
val isPaired = pigeonVar_list[2] as Boolean?
|
||||
val rssi = pigeonVar_list[3] as Long?
|
||||
val manufacturerDataList = pigeonVar_list[4] as List<UniversalManufacturerData>?
|
||||
val services = pigeonVar_list[5] as List<String>?
|
||||
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. */
|
||||
data class UniversalBleService (
|
||||
val uuid: String,
|
||||
val characteristics: List<UniversalBleCharacteristic?>? = null
|
||||
|
||||
) {
|
||||
val characteristics: List<UniversalBleCharacteristic>? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleService {
|
||||
val uuid = __pigeon_list[0] as String
|
||||
val characteristics = __pigeon_list[1] as List<UniversalBleCharacteristic?>?
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBleService {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val characteristics = pigeonVar_list[1] as List<UniversalBleCharacteristic>?
|
||||
return UniversalBleService(uuid, characteristics)
|
||||
}
|
||||
}
|
||||
@@ -106,14 +104,13 @@ data class UniversalBleService (
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBleCharacteristic (
|
||||
val uuid: String,
|
||||
val properties: List<Long?>
|
||||
|
||||
) {
|
||||
val properties: List<Long>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalBleCharacteristic {
|
||||
val uuid = __pigeon_list[0] as String
|
||||
val properties = __pigeon_list[1] as List<Long?>
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBleCharacteristic {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val properties = pigeonVar_list[1] as List<Long>
|
||||
return UniversalBleCharacteristic(uuid, properties)
|
||||
}
|
||||
}
|
||||
@@ -131,17 +128,16 @@ data class UniversalBleCharacteristic (
|
||||
* Generated class from Pigeon that represents data sent in messages.
|
||||
*/
|
||||
data class UniversalScanFilter (
|
||||
val withServices: List<String?>,
|
||||
val withNamePrefix: List<String?>,
|
||||
val withManufacturerData: List<UniversalManufacturerDataFilter?>
|
||||
|
||||
) {
|
||||
val withServices: List<String>,
|
||||
val withNamePrefix: List<String>,
|
||||
val withManufacturerData: List<UniversalManufacturerDataFilter>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalScanFilter {
|
||||
val withServices = __pigeon_list[0] as List<String?>
|
||||
val withNamePrefix = __pigeon_list[1] as List<String?>
|
||||
val withManufacturerData = __pigeon_list[2] as List<UniversalManufacturerDataFilter?>
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalScanFilter {
|
||||
val withServices = pigeonVar_list[0] as List<String>
|
||||
val withNamePrefix = pigeonVar_list[1] as List<String>
|
||||
val withManufacturerData = pigeonVar_list[2] as List<UniversalManufacturerDataFilter>
|
||||
return UniversalScanFilter(withServices, withNamePrefix, withManufacturerData)
|
||||
}
|
||||
}
|
||||
@@ -159,14 +155,13 @@ data class UniversalManufacturerDataFilter (
|
||||
val companyIdentifier: Long,
|
||||
val data: ByteArray? = null,
|
||||
val mask: ByteArray? = null
|
||||
|
||||
) {
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalManufacturerDataFilter {
|
||||
val companyIdentifier = __pigeon_list[0].let { num -> if (num is Int) num.toLong() else num as Long }
|
||||
val data = __pigeon_list[1] as ByteArray?
|
||||
val mask = __pigeon_list[2] as ByteArray?
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalManufacturerDataFilter {
|
||||
val companyIdentifier = pigeonVar_list[0] as Long
|
||||
val data = pigeonVar_list[1] as ByteArray?
|
||||
val mask = pigeonVar_list[2] as ByteArray?
|
||||
return UniversalManufacturerDataFilter(companyIdentifier, data, mask)
|
||||
}
|
||||
}
|
||||
@@ -183,13 +178,12 @@ data class UniversalManufacturerDataFilter (
|
||||
data class UniversalManufacturerData (
|
||||
val companyIdentifier: Long,
|
||||
val data: ByteArray
|
||||
|
||||
) {
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
@Suppress("LocalVariableName")
|
||||
fun fromList(__pigeon_list: List<Any?>): UniversalManufacturerData {
|
||||
val companyIdentifier = __pigeon_list[0].let { num -> if (num is Int) num.toLong() else num as Long }
|
||||
val data = __pigeon_list[1] as ByteArray
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalManufacturerData {
|
||||
val companyIdentifier = pigeonVar_list[0] as Long
|
||||
val data = pigeonVar_list[1] as ByteArray
|
||||
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? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
@@ -294,7 +288,7 @@ interface UniversalBlePlatformChannel {
|
||||
companion object {
|
||||
/** The codec used by UniversalBlePlatformChannel. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
UniversalBlePigeonCodec
|
||||
UniversalBlePigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
@@ -414,7 +408,7 @@ interface UniversalBlePlatformChannel {
|
||||
val deviceIdArg = args[0] as String
|
||||
val serviceArg = args[1] 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> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
@@ -476,7 +470,7 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
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> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
@@ -500,7 +494,7 @@ interface UniversalBlePlatformChannel {
|
||||
val serviceArg = args[1] as String
|
||||
val characteristicArg = args[2] as String
|
||||
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> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
@@ -621,7 +615,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
companion object {
|
||||
/** The codec used by UniversalBleCallbackChannel. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
UniversalBlePigeonCodec
|
||||
UniversalBlePigeonCodec()
|
||||
}
|
||||
}
|
||||
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 channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, connectedArg)) {
|
||||
channel.send(listOf(deviceIdArg, connectedArg, errorArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
class DiscoverServicesFuture(
|
||||
val deviceId: String,
|
||||
|
||||
@@ -162,7 +162,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (currentState == BluetoothGatt.STATE_CONNECTED) {
|
||||
Log.e(TAG, "$deviceId Already connected")
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onConnectionChanged(deviceId, true) {}
|
||||
callbackChannel?.onConnectionChanged(deviceId, true, null) {}
|
||||
}
|
||||
return
|
||||
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
||||
@@ -864,19 +864,22 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
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) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onConnectionChanged(
|
||||
gatt.device.address, true
|
||||
gatt.device.address, true, status.parseHciErrorCode()
|
||||
) {}
|
||||
}
|
||||
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
|
||||
cleanConnection(gatt)
|
||||
mainThreadHandler?.post {
|
||||
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
|
||||
|
||||
import Foundation
|
||||
@@ -74,17 +74,19 @@ struct UniversalBleScanResult {
|
||||
var name: String? = nil
|
||||
var isPaired: Bool? = nil
|
||||
var rssi: Int64? = nil
|
||||
var manufacturerDataList: [UniversalManufacturerData?]? = nil
|
||||
var services: [String?]? = nil
|
||||
var manufacturerDataList: [UniversalManufacturerData]? = nil
|
||||
var services: [String]? = nil
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalBleScanResult? {
|
||||
let deviceId = __pigeon_list[0] as! String
|
||||
let name: String? = nilOrValue(__pigeon_list[1])
|
||||
let isPaired: Bool? = nilOrValue(__pigeon_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 manufacturerDataList: [UniversalManufacturerData?]? = nilOrValue(__pigeon_list[4])
|
||||
let services: [String?]? = nilOrValue(__pigeon_list[5])
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleScanResult? {
|
||||
let deviceId = pigeonVar_list[0] as! String
|
||||
let name: String? = nilOrValue(pigeonVar_list[1])
|
||||
let isPaired: Bool? = nilOrValue(pigeonVar_list[2])
|
||||
let rssi: Int64? = nilOrValue(pigeonVar_list[3])
|
||||
let manufacturerDataList: [UniversalManufacturerData]? = nilOrValue(pigeonVar_list[4])
|
||||
let services: [String]? = nilOrValue(pigeonVar_list[5])
|
||||
|
||||
return UniversalBleScanResult(
|
||||
deviceId: deviceId,
|
||||
@@ -110,12 +112,14 @@ struct UniversalBleScanResult {
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBleService {
|
||||
var uuid: String
|
||||
var characteristics: [UniversalBleCharacteristic?]? = nil
|
||||
var characteristics: [UniversalBleCharacteristic]? = nil
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalBleService? {
|
||||
let uuid = __pigeon_list[0] as! String
|
||||
let characteristics: [UniversalBleCharacteristic?]? = nilOrValue(__pigeon_list[1])
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleService? {
|
||||
let uuid = pigeonVar_list[0] as! String
|
||||
let characteristics: [UniversalBleCharacteristic]? = nilOrValue(pigeonVar_list[1])
|
||||
|
||||
return UniversalBleService(
|
||||
uuid: uuid,
|
||||
@@ -133,12 +137,14 @@ struct UniversalBleService {
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBleCharacteristic {
|
||||
var uuid: String
|
||||
var properties: [Int64?]
|
||||
var properties: [Int64]
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalBleCharacteristic? {
|
||||
let uuid = __pigeon_list[0] as! String
|
||||
let properties = __pigeon_list[1] as! [Int64?]
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleCharacteristic? {
|
||||
let uuid = pigeonVar_list[0] as! String
|
||||
let properties = pigeonVar_list[1] as! [Int64]
|
||||
|
||||
return UniversalBleCharacteristic(
|
||||
uuid: uuid,
|
||||
@@ -157,15 +163,17 @@ struct UniversalBleCharacteristic {
|
||||
///
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalScanFilter {
|
||||
var withServices: [String?]
|
||||
var withNamePrefix: [String?]
|
||||
var withManufacturerData: [UniversalManufacturerDataFilter?]
|
||||
var withServices: [String]
|
||||
var withNamePrefix: [String]
|
||||
var withManufacturerData: [UniversalManufacturerDataFilter]
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalScanFilter? {
|
||||
let withServices = __pigeon_list[0] as! [String?]
|
||||
let withNamePrefix = __pigeon_list[1] as! [String?]
|
||||
let withManufacturerData = __pigeon_list[2] as! [UniversalManufacturerDataFilter?]
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanFilter? {
|
||||
let withServices = pigeonVar_list[0] as! [String]
|
||||
let withNamePrefix = pigeonVar_list[1] as! [String]
|
||||
let withManufacturerData = pigeonVar_list[2] as! [UniversalManufacturerDataFilter]
|
||||
|
||||
return UniversalScanFilter(
|
||||
withServices: withServices,
|
||||
@@ -188,11 +196,13 @@ struct UniversalManufacturerDataFilter {
|
||||
var data: FlutterStandardTypedData? = nil
|
||||
var mask: FlutterStandardTypedData? = nil
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
||||
let companyIdentifier = __pigeon_list[0] is Int64 ? __pigeon_list[0] as! Int64 : Int64(__pigeon_list[0] as! Int32)
|
||||
let data: FlutterStandardTypedData? = nilOrValue(__pigeon_list[1])
|
||||
let mask: FlutterStandardTypedData? = nilOrValue(__pigeon_list[2])
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerDataFilter? {
|
||||
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||
let data: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[1])
|
||||
let mask: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[2])
|
||||
|
||||
return UniversalManufacturerDataFilter(
|
||||
companyIdentifier: companyIdentifier,
|
||||
@@ -214,10 +224,12 @@ struct UniversalManufacturerData {
|
||||
var companyIdentifier: Int64
|
||||
var data: FlutterStandardTypedData
|
||||
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ __pigeon_list: [Any?]) -> UniversalManufacturerData? {
|
||||
let companyIdentifier = __pigeon_list[0] is Int64 ? __pigeon_list[0] as! Int64 : Int64(__pigeon_list[0] as! Int32)
|
||||
let data = __pigeon_list[1] as! FlutterStandardTypedData
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerData? {
|
||||
let companyIdentifier = pigeonVar_list[0] as! Int64
|
||||
let data = pigeonVar_list[1] as! FlutterStandardTypedData
|
||||
|
||||
return UniversalManufacturerData(
|
||||
companyIdentifier: companyIdentifier,
|
||||
@@ -231,6 +243,7 @@ struct UniversalManufacturerData {
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class UniversalBlePigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
@@ -416,7 +429,7 @@ class UniversalBlePlatformChannelSetup {
|
||||
let deviceIdArg = args[0] as! String
|
||||
let serviceArg = args[1] 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
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -470,7 +483,7 @@ class UniversalBlePlatformChannelSetup {
|
||||
requestMtuChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
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
|
||||
switch result {
|
||||
case .success(let res):
|
||||
@@ -491,7 +504,7 @@ class UniversalBlePlatformChannelSetup {
|
||||
let serviceArg = args[1] as! String
|
||||
let characteristicArg = args[2] as! String
|
||||
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
|
||||
switch result {
|
||||
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 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 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 {
|
||||
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 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 {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
|
||||
@@ -104,11 +104,11 @@ extension CBManagerState {
|
||||
}
|
||||
|
||||
extension Error {
|
||||
func toFlutterError() -> FlutterError {
|
||||
func toPigeonError() -> PigeonError {
|
||||
let nsError = self as NSError
|
||||
let errorCode: String = .init(nsError.code)
|
||||
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) {
|
||||
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 {
|
||||
@@ -117,7 +117,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
characteristicReadFutures.removeAll { future in
|
||||
if future.deviceId == deviceId {
|
||||
future.result(
|
||||
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
)
|
||||
return true
|
||||
}
|
||||
@@ -126,7 +126,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
characteristicWriteFutures.removeAll { future in
|
||||
if future.deviceId == deviceId {
|
||||
future.result(
|
||||
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
)
|
||||
return true
|
||||
}
|
||||
@@ -135,7 +135,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
characteristicNotifyFutures.removeAll { future in
|
||||
if future.deviceId == deviceId {
|
||||
future.result(
|
||||
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
)
|
||||
return true
|
||||
}
|
||||
@@ -144,7 +144,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
discoverServicesFutures.removeAll { future in
|
||||
if future.deviceId == deviceId {
|
||||
future.result(
|
||||
Result.failure(FlutterError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil))
|
||||
)
|
||||
return true
|
||||
}
|
||||
@@ -156,7 +156,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) {
|
||||
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||
completion(
|
||||
Result.failure(FlutterError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
||||
Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))
|
||||
)
|
||||
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) {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -219,15 +219,15 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
|
||||
func readValue(deviceId: String, service: String, characteristic: String, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -248,12 +248,12 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
|
||||
if type == CBCharacteristicWriteType.withResponse {
|
||||
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
|
||||
}
|
||||
} else if type == CBCharacteristicWriteType.withoutResponse {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
|
||||
func requestMtu(deviceId: String, expectedMtu _: Int64, completion: @escaping (Result<Int64, Error>) -> Void) {
|
||||
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
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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) {
|
||||
@@ -345,17 +345,17 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
}
|
||||
|
||||
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?) {
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false) { _ in }
|
||||
// Cleanup on disconnect
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: nil) { _ in }
|
||||
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||
}
|
||||
|
||||
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?) {
|
||||
@@ -397,8 +397,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||
characteristicWriteFutures.removeAll { future in
|
||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||
if let flutterError = error?.toFlutterError() {
|
||||
future.result(Result.failure(flutterError))
|
||||
if let pigeonError = error?.toPigeonError() {
|
||||
future.result(Result.failure(pigeonError))
|
||||
} else {
|
||||
future.result(Result.success({}()))
|
||||
}
|
||||
@@ -411,8 +411,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
||||
characteristicNotifyFutures.removeAll { future in
|
||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||
if let flutterError = error?.toFlutterError() {
|
||||
future.result(Result.failure(flutterError))
|
||||
if let pigeonError = error?.toPigeonError() {
|
||||
future.result(Result.failure(pigeonError))
|
||||
} else {
|
||||
future.result(Result.success({}()))
|
||||
}
|
||||
@@ -437,13 +437,13 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
// Update futures for readValue
|
||||
characteristicReadFutures.removeAll { future in
|
||||
if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr {
|
||||
if let flutterError = error?.toFlutterError() {
|
||||
future.result(Result.failure(flutterError))
|
||||
if let pigeonError = error?.toPigeonError() {
|
||||
future.result(Result.failure(pigeonError))
|
||||
} else {
|
||||
if let characteristicValue = characteristic.value {
|
||||
future.result(Result.success(FlutterStandardTypedData(bytes: characteristicValue)))
|
||||
} 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
|
||||
@@ -456,7 +456,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
extension String {
|
||||
func getPeripheral() throws -> CBPeripheral {
|
||||
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
|
||||
}
|
||||
@@ -466,11 +466,9 @@ extension [String] {
|
||||
func toCBUUID() throws -> [CBUUID] {
|
||||
return try compactMap { serviceUUID in
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FlutterError: Error {}
|
||||
|
||||
@@ -59,8 +59,14 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
});
|
||||
}
|
||||
|
||||
void _handleConnectionChange(String deviceId, bool isConnected) {
|
||||
print('_handleConnectionChange $deviceId, $isConnected');
|
||||
void _handleConnectionChange(
|
||||
String deviceId,
|
||||
bool isConnected,
|
||||
String? error,
|
||||
) {
|
||||
print(
|
||||
'_handleConnectionChange $deviceId, $isConnected ${error != null ? 'Error: $error' : ''}',
|
||||
);
|
||||
setState(() {
|
||||
if (deviceId == widget.deviceId) {
|
||||
this.isConnected = isConnected;
|
||||
@@ -248,12 +254,12 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
enabled: !isConnected,
|
||||
onPressed: () async {
|
||||
try {
|
||||
bool connected = await UniversalBle.connect(
|
||||
await UniversalBle.connect(
|
||||
widget.deviceId,
|
||||
);
|
||||
_addLog("ConnectionResult", connected);
|
||||
_addLog("ConnectionResult", true);
|
||||
} catch (e) {
|
||||
_addLog('ConnectError', e);
|
||||
_addLog('ConnectError (${e.runtimeType})', e);
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -405,14 +411,18 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
PlatformButton(
|
||||
enabled: BleCapabilities.supportsAllPairingKinds,
|
||||
onPressed: () async {
|
||||
bool? pairingResult = await UniversalBle.pair(
|
||||
widget.deviceId,
|
||||
// pairingCommand: BleCommand(
|
||||
// service: "",
|
||||
// characteristic: "",
|
||||
// ),
|
||||
);
|
||||
_addLog("Pairing Result", pairingResult);
|
||||
try {
|
||||
await UniversalBle.pair(
|
||||
widget.deviceId,
|
||||
// pairingCommand: BleCommand(
|
||||
// service: "",
|
||||
// characteristic: "",
|
||||
// ),
|
||||
);
|
||||
_addLog("Pairing Result", true);
|
||||
} catch (e) {
|
||||
_addLog('PairError (${e.runtimeType})', e);
|
||||
}
|
||||
},
|
||||
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) {
|
||||
this.uuid = BleUuidParser.string(uuid);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BleService{uuid: $uuid, characteristics: $characteristics}';
|
||||
}
|
||||
}
|
||||
|
||||
class BleCharacteristic {
|
||||
@@ -16,6 +21,11 @@ class BleCharacteristic {
|
||||
BleCharacteristic(String uuid, this.properties) {
|
||||
this.uuid = BleUuidParser.string(uuid);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BleCharacteristic{uuid: $uuid, properties: $properties}';
|
||||
}
|
||||
}
|
||||
|
||||
enum CharacteristicProperty {
|
||||
@@ -32,4 +42,7 @@ enum CharacteristicProperty {
|
||||
|
||||
factory CharacteristicProperty.parse(int 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/platform_config.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_pigeon/universal_ble_pigeon_channel.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';
|
||||
|
||||
class UniversalBle {
|
||||
@@ -31,7 +32,7 @@ class UniversalBle {
|
||||
/// [QueueType.none] will execute all commands in parallel.
|
||||
static set queueType(QueueType queueType) {
|
||||
_bleCommandQueue.queueType = queueType;
|
||||
UniversalBlePlatform.logInfo('Queue ${queueType.name}');
|
||||
UniversalLogger.logInfo('Queue ${queueType.name}');
|
||||
}
|
||||
|
||||
/// Get Bluetooth availability state.
|
||||
@@ -70,28 +71,37 @@ class UniversalBle {
|
||||
}
|
||||
|
||||
/// Connection stream of a device
|
||||
Stream<bool> connectionStream(String deviceId) =>
|
||||
static Stream<BleConnectionUpdate> connectionStream(String deviceId) =>
|
||||
_platform.connectionStream(deviceId);
|
||||
|
||||
/// Connect to a device.
|
||||
/// It is advised to stop scanning before connecting.
|
||||
/// It might throw errors if device is not connectable.
|
||||
/// `connectionTimeout` is supported on Web only.
|
||||
static Future<bool> connect(
|
||||
/// It throws error if device connection fails.
|
||||
/// Default connection timeout is 60 sec.
|
||||
/// Can throw `ConnectionException` or `PlatformException`.
|
||||
static Future<void> connect(
|
||||
String deviceId, {
|
||||
Duration? connectionTimeout,
|
||||
}) async {
|
||||
connectionTimeout ??= const Duration(seconds: 60);
|
||||
StreamSubscription? connectionSubscription;
|
||||
|
||||
try {
|
||||
Completer<bool> completer = Completer();
|
||||
|
||||
connectionSubscription =
|
||||
_platform.connectionStream(deviceId).listen((bool event) {
|
||||
connectionSubscription?.cancel();
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(event);
|
||||
}
|
||||
});
|
||||
connectionSubscription = connectionStream(deviceId).listen(
|
||||
(BleConnectionUpdate event) {
|
||||
connectionSubscription?.cancel();
|
||||
if (!completer.isCompleted) {
|
||||
String? error = event.error;
|
||||
if (error != null) {
|
||||
completer.completeError(ConnectionException(error));
|
||||
} else {
|
||||
completer.complete(event.isConnected);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
_platform
|
||||
.connect(deviceId, connectionTimeout: connectionTimeout)
|
||||
@@ -99,15 +109,14 @@ class UniversalBle {
|
||||
(error) {
|
||||
if (completer.isCompleted == false) {
|
||||
connectionSubscription?.cancel();
|
||||
completer.completeError(error);
|
||||
completer.completeError(ConnectionException(error));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (connectionTimeout != null) {
|
||||
return await completer.future.timeout(connectionTimeout);
|
||||
if (!await completer.future.timeout(connectionTimeout)) {
|
||||
throw ConnectionException("Failed to connect");
|
||||
}
|
||||
return await completer.future;
|
||||
} finally {
|
||||
connectionSubscription?.cancel();
|
||||
}
|
||||
@@ -211,36 +220,65 @@ class UniversalBle {
|
||||
static Future<bool?> isPaired(
|
||||
String deviceId, {
|
||||
BleCommand? pairingCommand,
|
||||
Duration? connectionTimeout,
|
||||
}) async {
|
||||
if (BleCapabilities.hasSystemPairingApi) {
|
||||
return _bleCommandQueue.queueCommand(
|
||||
() => _platform.isPaired(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.
|
||||
///
|
||||
/// It throws error if pairing fails.
|
||||
///
|
||||
/// 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.
|
||||
/// If you do, it returns true if it can successfully execute the command after pairing.
|
||||
///
|
||||
/// On `Web/Windows` and `Web/Linux`, it does not work for devices where `BleCapabilities.triggersConfirmOnlyPairing` is false.
|
||||
static Future<bool?> pair(
|
||||
/// On `Web/Windows` and `Web/Linux`, it does not work for devices that use `ConfirmOnly` pairing.
|
||||
/// Can throw `PairingException`, `ConnectionException` or `PlatformException`.
|
||||
static Future<void> pair(
|
||||
String deviceId, {
|
||||
BleCommand? pairingCommand,
|
||||
Duration? connectionTimeout,
|
||||
}) async {
|
||||
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.
|
||||
@@ -303,38 +341,32 @@ class UniversalBle {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool?> _connectAndExecuteBleCommand(
|
||||
static Future<void> _connectAndExecuteBleCommand(
|
||||
String deviceId,
|
||||
BleCommand? bleCommand, {
|
||||
Duration? connectionTimeout,
|
||||
bool updateCallbackValue = false,
|
||||
}) async {
|
||||
try {
|
||||
if (await getConnectionState(deviceId) != BleConnectionState.connected) {
|
||||
await connect(deviceId);
|
||||
}
|
||||
|
||||
List<BleService> services = await discoverServices(deviceId);
|
||||
|
||||
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",
|
||||
// Try to connect first
|
||||
if (await getConnectionState(deviceId) != BleConnectionState.connected) {
|
||||
UniversalLogger.logInfo("Connecting to $deviceId");
|
||||
await connect(
|
||||
deviceId,
|
||||
connectionTimeout: connectionTimeout,
|
||||
);
|
||||
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
|
||||
@@ -359,12 +391,13 @@ class UniversalBle {
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
if (!containsReadCharacteristics) {
|
||||
throw "No readable characteristic found";
|
||||
throw PairingException("No readable characteristic found");
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> _executeBleCommand(
|
||||
static Future<void> _executeBleCommand(
|
||||
String deviceId,
|
||||
List<BleService> services,
|
||||
BleCommand bleCommand,
|
||||
@@ -384,7 +417,7 @@ class UniversalBle {
|
||||
}
|
||||
|
||||
if (characteristic == null) {
|
||||
return false;
|
||||
throw PairingException("BleCommand not found in discovered services");
|
||||
}
|
||||
|
||||
// Check if BleCommand Supports Read or Write
|
||||
@@ -396,28 +429,34 @@ class UniversalBle {
|
||||
bleOutputProperty = BleOutputProperty.withoutResponse;
|
||||
} else if (!characteristic.properties
|
||||
.contains(CharacteristicProperty.read)) {
|
||||
return false;
|
||||
throw PairingException(
|
||||
"BleCommand does not support read or write operation",
|
||||
);
|
||||
}
|
||||
|
||||
Uint8List? value = bleCommand.writeValue;
|
||||
if (value != null && bleOutputProperty != null) {
|
||||
await writeValue(
|
||||
deviceId,
|
||||
bleCommand.service,
|
||||
bleCommand.characteristic,
|
||||
value,
|
||||
bleOutputProperty,
|
||||
);
|
||||
} else {
|
||||
// Fallback to read if supported
|
||||
await readValue(
|
||||
deviceId,
|
||||
bleCommand.service,
|
||||
bleCommand.characteristic,
|
||||
timeout: const Duration(seconds: 30),
|
||||
);
|
||||
|
||||
try {
|
||||
if (value != null && bleOutputProperty != null) {
|
||||
await writeValue(
|
||||
deviceId,
|
||||
bleCommand.service,
|
||||
bleCommand.characteristic,
|
||||
value,
|
||||
bleOutputProperty,
|
||||
);
|
||||
} else {
|
||||
// Fallback to read if supported
|
||||
await readValue(
|
||||
deviceId,
|
||||
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.
|
||||
|
||||
@@ -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/universal_ble_filter_util.dart';
|
||||
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
||||
import 'package:universal_ble/src/universal_logger.dart';
|
||||
|
||||
class UniversalBleLinux extends UniversalBlePlatform {
|
||||
UniversalBleLinux._();
|
||||
@@ -45,10 +46,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
await _activeAdapter?.setPowered(true);
|
||||
return _activeAdapter?.powered ?? false;
|
||||
} catch (e) {
|
||||
UniversalBlePlatform.logInfo(
|
||||
'Error enabling bluetooth: $e',
|
||||
isError: true,
|
||||
);
|
||||
UniversalLogger.logError('Error enabling bluetooth: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -113,10 +111,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
return true;
|
||||
});
|
||||
} catch (e) {
|
||||
UniversalBlePlatform.logInfo(
|
||||
"stopScan error: $e",
|
||||
isError: true,
|
||||
);
|
||||
UniversalLogger.logError("stopScan error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +154,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
await device.propertiesChanged.firstWhere((element) {
|
||||
if (element.contains(BluezProperty.connected)) {
|
||||
if (!device.connected) {
|
||||
UniversalBlePlatform.logInfo(
|
||||
UniversalLogger.logInfo(
|
||||
"DiscoverServicesFailed: Device disconnected",
|
||||
);
|
||||
return true;
|
||||
@@ -167,7 +162,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
return element.contains(BluezProperty.servicesResolved);
|
||||
}).timeout(const Duration(seconds: 10), onTimeout: () {
|
||||
UniversalBlePlatform.logInfo(
|
||||
UniversalLogger.logInfo(
|
||||
"DiscoverServicesFailed: Timeout",
|
||||
);
|
||||
return [];
|
||||
@@ -238,8 +233,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
UniversalBlePlatform.logInfo(
|
||||
"UnhandledCharValuePropertyChange: $property");
|
||||
UniversalLogger.logInfo(
|
||||
"UnhandledCharValuePropertyChange: $property",
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -351,8 +347,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
.map((e) => e.uuid.toString())
|
||||
.any((service) => withServices.contains(service));
|
||||
} else {
|
||||
UniversalBlePlatform.logInfo(
|
||||
'Skipping: ${device.address}: Services not resolved yet.');
|
||||
UniversalLogger.logInfo(
|
||||
'Skipping: ${device.address}: Services not resolved yet.',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}).toList();
|
||||
@@ -394,7 +391,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
|
||||
_activeAdapter ??= _client.adapters.first;
|
||||
|
||||
UniversalBlePlatform.logInfo(
|
||||
UniversalLogger.logInfo(
|
||||
'BleAdapter: ${_activeAdapter?.name} - ${_activeAdapter?.address}',
|
||||
);
|
||||
|
||||
@@ -411,7 +408,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
break;
|
||||
case BluezProperty.propertyClass:
|
||||
default:
|
||||
UniversalBlePlatform.logInfo(
|
||||
UniversalLogger.logInfo(
|
||||
"UnhandledPropertyChanged: $property",
|
||||
);
|
||||
}
|
||||
@@ -426,10 +423,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
_initializationCompleter?.complete();
|
||||
_initializationCompleter = null;
|
||||
} catch (e) {
|
||||
UniversalBlePlatform.logInfo(
|
||||
'Error initializing: $e',
|
||||
isError: true,
|
||||
);
|
||||
UniversalLogger.logError('Error initializing: $e');
|
||||
_initializationCompleter?.completeError(e);
|
||||
await _client.close();
|
||||
rethrow;
|
||||
@@ -501,7 +495,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
case BluezProperty.manufacturerData:
|
||||
break;
|
||||
default:
|
||||
UniversalBlePlatform.logInfo(
|
||||
UniversalLogger.logInfo(
|
||||
"UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property",
|
||||
);
|
||||
break;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -119,10 +119,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
) async {
|
||||
var devices = await _channel.getSystemDevices(withServices ?? []);
|
||||
return List<BleDevice>.from(
|
||||
devices
|
||||
.map((e) => e?.toBleDevice(isSystemDevice: true))
|
||||
.where((e) => e != null)
|
||||
.toList(),
|
||||
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -175,8 +172,8 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
availabilityChange(AvailabilityState.parse(state));
|
||||
|
||||
@override
|
||||
void onConnectionChanged(String deviceId, bool connected) =>
|
||||
connectionChanged(deviceId, connected);
|
||||
void onConnectionChanged(String deviceId, bool connected, String? error) =>
|
||||
connectionChanged(deviceId, connected, error);
|
||||
|
||||
@override
|
||||
void onScanResult(UniversalBleScanResult result) =>
|
||||
@@ -200,9 +197,9 @@ extension _UniversalBleScanResultExtension on UniversalBleScanResult {
|
||||
rssi: rssi,
|
||||
isPaired: isPaired,
|
||||
isSystemDevice: isSystemDevice,
|
||||
services: services?.nonNulls.map(BleUuidParser.string).toList() ?? [],
|
||||
manufacturerDataList: manufacturerDataList?.nonNulls
|
||||
.map((e) => ManufacturerData(e.companyIdentifier, e.data))
|
||||
services: services?.map(BleUuidParser.string).toList() ?? [],
|
||||
manufacturerDataList: manufacturerDataList
|
||||
?.map((e) => ManufacturerData(e.companyIdentifier, e.data))
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:typed_data';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
abstract class UniversalBlePlatform {
|
||||
StreamController? _connectionStreamController;
|
||||
StreamController<({String deviceId, bool isConnected, String? error})>?
|
||||
_connectionStreamController;
|
||||
|
||||
final Map<String, bool> _pairStateMap = {};
|
||||
|
||||
Future<AvailabilityState> getBluetoothAvailabilityState();
|
||||
@@ -57,21 +58,27 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
bool receivesAdvertisements(String deviceId) => true;
|
||||
|
||||
Stream<bool> connectionStream(String deviceId) {
|
||||
Stream<BleConnectionUpdate> connectionStream(String deviceId) {
|
||||
_setupConnectionStreamIfRequired();
|
||||
return _connectionStreamController!.stream
|
||||
.where((event) => event.deviceId == deviceId)
|
||||
.map((event) => event.isConnected);
|
||||
.map((event) => BleConnectionUpdate(
|
||||
isConnected: event.isConnected,
|
||||
error: event.error,
|
||||
));
|
||||
}
|
||||
|
||||
void updateScanResult(BleDevice bleDevice) {
|
||||
onScanResult?.call(bleDevice);
|
||||
}
|
||||
|
||||
void updateConnection(String deviceId, bool isConnected) {
|
||||
onConnectionChange?.call(deviceId, isConnected);
|
||||
_connectionStreamController
|
||||
?.add((deviceId: deviceId, isConnected: isConnected));
|
||||
void updateConnection(String deviceId, bool isConnected, [String? error]) {
|
||||
onConnectionChange?.call(deviceId, isConnected, error);
|
||||
_connectionStreamController?.add((
|
||||
deviceId: deviceId,
|
||||
isConnected: isConnected,
|
||||
error: error,
|
||||
));
|
||||
}
|
||||
|
||||
void updateCharacteristicValue(
|
||||
@@ -97,17 +104,11 @@ abstract class UniversalBlePlatform {
|
||||
OnAvailabilityChange? onAvailabilityChange;
|
||||
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
|
||||
void _setupConnectionStreamIfRequired() {
|
||||
if (_connectionStreamController != null) return;
|
||||
|
||||
_connectionStreamController =
|
||||
StreamController<({String deviceId, bool isConnected})>.broadcast();
|
||||
_connectionStreamController = StreamController.broadcast();
|
||||
|
||||
// Auto dispose if no more subscribers
|
||||
_connectionStreamController?.onCancel = () {
|
||||
@@ -119,7 +120,8 @@ abstract class UniversalBlePlatform {
|
||||
}
|
||||
|
||||
// Callback types
|
||||
typedef OnConnectionChange = void Function(String deviceId, bool isConnected);
|
||||
typedef OnConnectionChange = void Function(
|
||||
String deviceId, bool isConnected, String? error);
|
||||
|
||||
typedef OnValueChange = void Function(
|
||||
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:universal_ble/src/models/model_exports.dart';
|
||||
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
|
||||
import 'package:universal_ble/src/universal_logger.dart';
|
||||
|
||||
class UniversalBleWeb extends UniversalBlePlatform {
|
||||
static UniversalBleWeb? _instance;
|
||||
@@ -127,10 +128,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
device.advertisementsUseMemory = true;
|
||||
await device.watchAdvertisements();
|
||||
} catch (e) {
|
||||
UniversalBlePlatform.logInfo(
|
||||
"WebWatchAdvertisementError: $e",
|
||||
isError: true,
|
||||
);
|
||||
UniversalLogger.logError("WebWatchAdvertisementError: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,9 +393,8 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
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",
|
||||
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;
|
||||
|
||||
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.dart';
|
||||
export 'package:universal_ble/src/models/model_exports.dart';
|
||||
|
||||
@@ -99,6 +99,7 @@ abstract class UniversalBleCallbackChannel {
|
||||
void onConnectionChanged(
|
||||
String deviceId,
|
||||
bool connected,
|
||||
String? error,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -107,8 +108,8 @@ class UniversalBleScanResult {
|
||||
final String? name;
|
||||
final bool? isPaired;
|
||||
final int? rssi;
|
||||
final List<UniversalManufacturerData?>? manufacturerDataList;
|
||||
final List<String?>? services;
|
||||
final List<UniversalManufacturerData>? manufacturerDataList;
|
||||
final List<String>? services;
|
||||
|
||||
UniversalBleScanResult({
|
||||
required this.name,
|
||||
@@ -122,21 +123,21 @@ class UniversalBleScanResult {
|
||||
|
||||
class UniversalBleService {
|
||||
String uuid;
|
||||
List<UniversalBleCharacteristic?>? characteristics;
|
||||
List<UniversalBleCharacteristic>? characteristics;
|
||||
UniversalBleService(this.uuid, this.characteristics);
|
||||
}
|
||||
|
||||
class UniversalBleCharacteristic {
|
||||
String uuid;
|
||||
List<int?> properties;
|
||||
List<int> properties;
|
||||
UniversalBleCharacteristic(this.uuid, this.properties);
|
||||
}
|
||||
|
||||
/// Scan Filters
|
||||
class UniversalScanFilter {
|
||||
final List<String?> withServices;
|
||||
final List<String?> withNamePrefix;
|
||||
final List<UniversalManufacturerDataFilter?> withManufacturerData;
|
||||
final List<String> withServices;
|
||||
final List<String> withNamePrefix;
|
||||
final List<UniversalManufacturerDataFilter> withManufacturerData;
|
||||
|
||||
UniversalScanFilter(
|
||||
this.withServices,
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
pigeon: ^21.1.0
|
||||
pigeon: ^22.4.0
|
||||
|
||||
flutter:
|
||||
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
|
||||
|
||||
#undef _HAS_EXCEPTIONS
|
||||
@@ -22,10 +22,10 @@ using flutter::EncodableMap;
|
||||
using flutter::EncodableValue;
|
||||
|
||||
FlutterError CreateConnectionError(const std::string channel_name) {
|
||||
return FlutterError(
|
||||
"channel-error",
|
||||
"Unable to establish connection on channel: '" + channel_name + "'.",
|
||||
EncodableValue(""));
|
||||
return FlutterError(
|
||||
"channel-error",
|
||||
"Unable to establish connection on channel: '" + channel_name + "'.",
|
||||
EncodableValue(""));
|
||||
}
|
||||
|
||||
// UniversalBleScanResult
|
||||
@@ -146,7 +146,7 @@ UniversalBleScanResult UniversalBleScanResult::FromEncodableList(const Encodable
|
||||
}
|
||||
auto& encodable_rssi = list[3];
|
||||
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];
|
||||
if (!encodable_manufacturer_data_list.IsNull()) {
|
||||
@@ -364,7 +364,7 @@ EncodableList UniversalManufacturerDataFilter::ToEncodableList() const {
|
||||
|
||||
UniversalManufacturerDataFilter UniversalManufacturerDataFilter::FromEncodableList(const EncodableList& list) {
|
||||
UniversalManufacturerDataFilter decoded(
|
||||
list[0].LongValue());
|
||||
std::get<int64_t>(list[0]));
|
||||
auto& encodable_data = list[1];
|
||||
if (!encodable_data.IsNull()) {
|
||||
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 decoded(
|
||||
list[0].LongValue(),
|
||||
std::get<int64_t>(list[0]),
|
||||
std::get<std::vector<uint8_t>>(list[1]));
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
||||
PigeonCodecSerializer::PigeonCodecSerializer() {}
|
||||
PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {}
|
||||
|
||||
EncodableValue PigeonCodecSerializer::ReadValueOfType(
|
||||
EncodableValue PigeonInternalCodecSerializer::ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const {
|
||||
switch (type) {
|
||||
case 129:
|
||||
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
case 130:
|
||||
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
case 131:
|
||||
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
case 132:
|
||||
return CustomEncodableValue(UniversalScanFilter::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))));
|
||||
case 129: {
|
||||
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
}
|
||||
case 130: {
|
||||
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
}
|
||||
case 131: {
|
||||
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
}
|
||||
case 132: {
|
||||
return CustomEncodableValue(UniversalScanFilter::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:
|
||||
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void PigeonCodecSerializer::WriteValue(
|
||||
void PigeonInternalCodecSerializer::WriteValue(
|
||||
const EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const {
|
||||
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
|
||||
@@ -481,7 +487,7 @@ void PigeonCodecSerializer::WriteValue(
|
||||
|
||||
/// The codec used by UniversalBlePlatformChannel.
|
||||
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`.
|
||||
@@ -1019,7 +1025,7 @@ UniversalBleCallbackChannel::UniversalBleCallbackChannel(
|
||||
message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {}
|
||||
|
||||
const flutter::StandardMessageCodec& UniversalBleCallbackChannel::GetCodec() {
|
||||
return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance());
|
||||
return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance());
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnAvailabilityChanged(
|
||||
@@ -1133,6 +1139,7 @@ void UniversalBleCallbackChannel::OnValueChanged(
|
||||
void UniversalBleCallbackChannel::OnConnectionChanged(
|
||||
const std::string& device_id_arg,
|
||||
bool connected_arg,
|
||||
const std::string* error_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
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(device_id_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) {
|
||||
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
|
||||
|
||||
#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.
|
||||
class UniversalBleScanResult {
|
||||
public:
|
||||
@@ -101,7 +102,7 @@ class UniversalBleScanResult {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string device_id_;
|
||||
std::optional<std::string> name_;
|
||||
std::optional<bool> is_paired_;
|
||||
@@ -136,7 +137,7 @@ class UniversalBleService {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
std::optional<flutter::EncodableList> characteristics_;
|
||||
|
||||
@@ -163,7 +164,7 @@ class UniversalBleCharacteristic {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
flutter::EncodableList properties_;
|
||||
|
||||
@@ -196,7 +197,7 @@ class UniversalScanFilter {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
flutter::EncodableList with_services_;
|
||||
flutter::EncodableList with_name_prefix_;
|
||||
flutter::EncodableList with_manufacturer_data_;
|
||||
@@ -233,7 +234,7 @@ class UniversalManufacturerDataFilter {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
int64_t company_identifier_;
|
||||
std::optional<std::vector<uint8_t>> data_;
|
||||
std::optional<std::vector<uint8_t>> mask_;
|
||||
@@ -261,17 +262,18 @@ class UniversalManufacturerData {
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonCodecSerializer;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
int64_t company_identifier_;
|
||||
std::vector<uint8_t> data_;
|
||||
|
||||
};
|
||||
|
||||
class PigeonCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
|
||||
class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
public:
|
||||
PigeonCodecSerializer();
|
||||
inline static PigeonCodecSerializer& GetInstance() {
|
||||
static PigeonCodecSerializer sInstance;
|
||||
PigeonInternalCodecSerializer();
|
||||
inline static PigeonInternalCodecSerializer& GetInstance() {
|
||||
static PigeonInternalCodecSerializer sInstance;
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@@ -387,6 +389,7 @@ class UniversalBleCallbackChannel {
|
||||
void OnConnectionChanged(
|
||||
const std::string& device_id,
|
||||
bool connected,
|
||||
const std::string* error,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace universal_ble
|
||||
CleanConnection(deviceAddress);
|
||||
// TODO: send disconnect event only after disconnect is complete
|
||||
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;
|
||||
};
|
||||
@@ -925,7 +925,7 @@ namespace universal_ble
|
||||
{
|
||||
std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl;
|
||||
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;
|
||||
}
|
||||
@@ -933,9 +933,10 @@ namespace universal_ble
|
||||
auto status = servicesResult.Status();
|
||||
if (status != GattCommunicationStatus::Success)
|
||||
{
|
||||
std::cout << "ConnectionFailed: Failed to get services: " << GattCommunicationStatusToString(status) << std::endl;
|
||||
uiThreadHandler_.Post([bluetoothAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
||||
std::string error = GattCommunicationStatusToString(status);
|
||||
std::cout << "ConnectionFailed: Failed to get services: " << error << std::endl;
|
||||
uiThreadHandler_.Post([bluetoothAddress, error]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, &error, SuccessCallback, ErrorCallback); });
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -972,7 +973,7 @@ namespace universal_ble
|
||||
connectedDevices.insert(std::move(pair));
|
||||
std::cout << "ConnectionLog: Connected" << std::endl;
|
||||
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)
|
||||
@@ -982,7 +983,7 @@ namespace universal_ble
|
||||
CleanConnection(sender.BluetoothAddress());
|
||||
auto bluetoothAddress = sender.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