Return pair result

This commit is contained in:
Foti Dim
2024-08-12 21:07:55 +02:00
committed by Foti Dim
parent 7606e8fd29
commit 40819d5796
29 changed files with 573 additions and 657 deletions
+3 -2
View File
@@ -1,11 +1,12 @@
## 0.12.0
* BREAKING CHANGE: `unPair` is now `unpair`
* Add isPaired support on Apple
* `connect` will now return the connection result
* Add `pair()`, `isPaired` and `onPairingStateChange` support for Apple and web
* `connect()` and `pair()` now return a bool result
* 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
* Trim spaces in UUIDs
+13 -9
View File
@@ -22,7 +22,7 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
### API Support Matrix
| API | Android | iOS | macOS | Windows | Linux (beta) | Web |
| API | Android | iOS | macOS | Windows | Linux | Web |
| :------------------- | :-----: | :-: | :---: | :-----: | :----------: | :-: |
| startScan/stopScan | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| connect/disconnect | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
@@ -31,11 +31,11 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
| readValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| writeValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| setNotifiable | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| pair | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| pair | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| unpair | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ |
| isPaired | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ? |
| getBluetoothAvailabilityState | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| onPairingStateChange | ✔️ | | | ✔️ | ✔️ | ❌ |
| isPaired | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| onPairingStateChange | ✔️ | | | ✔️ | ✔️ | |
| getBluetoothAvailabilityState | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
| enableBluetooth | ✔️ | ❌ | ❌ | ✔️ | ✔️ | ❌ |
| onAvailabilityChange | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| requestMtu | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
@@ -196,18 +196,22 @@ UniversalBle.setNotifiable(deviceId, serviceId, characteristicId, BleInputProper
```dart
// Pair
UniversalBle.pair(deviceId);
bool? isPaired = await UniversalBle.pair(deviceId); // Returns true if successful
// Get the pairing result
// For Apple and Web, you can optionally pass a pairingCommand if you know an encrypted read or write characteristic.
// Not supported on Web/Windows
UniversalBle.pair(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC",));
// Receive pairing state changes
UniversalBle.onPairingStateChange = (String deviceId, bool isPaired, String? error) {
// Handle Pairing state change
// Handle pairing state change
}
// Unpair
UniversalBle.unpair(deviceId);
// Check current pairing state
bool isPaired = UniversalBle.isPaired(deviceId);
bool? isPaired = UniversalBle.isPaired(deviceId);
```
### Bluetooth Availability
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v18.0.1), do not edit directly.
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -72,7 +72,7 @@ data class UniversalBleScanResult (
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
deviceId,
name,
isPaired,
@@ -99,7 +99,7 @@ data class UniversalBleService (
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
uuid,
characteristics,
)
@@ -121,7 +121,7 @@ data class UniversalBleCharacteristic (
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
uuid,
properties,
)
@@ -147,7 +147,7 @@ data class UniversalScanFilter (
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
withServices,
withManufacturerData,
)
@@ -171,22 +171,16 @@ data class UniversalManufacturerDataFilter (
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
companyIdentifier,
data,
mask,
)
}
}
private object UniversalBlePlatformChannelCodec : StandardMessageCodec() {
private object UniversalBlePigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
128.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleCharacteristic.fromList(it)
}
}
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleScanResult.fromList(it)
@@ -199,7 +193,7 @@ private object UniversalBlePlatformChannelCodec : StandardMessageCodec() {
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalManufacturerDataFilter.fromList(it)
UniversalBleCharacteristic.fromList(it)
}
}
132.toByte() -> {
@@ -207,15 +201,16 @@ private object UniversalBlePlatformChannelCodec : StandardMessageCodec() {
UniversalScanFilter.fromList(it)
}
}
133.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalManufacturerDataFilter.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is UniversalBleCharacteristic -> {
stream.write(128)
writeValue(stream, value.toList())
}
is UniversalBleScanResult -> {
stream.write(129)
writeValue(stream, value.toList())
@@ -224,7 +219,7 @@ private object UniversalBlePlatformChannelCodec : StandardMessageCodec() {
stream.write(130)
writeValue(stream, value.toList())
}
is UniversalManufacturerDataFilter -> {
is UniversalBleCharacteristic -> {
stream.write(131)
writeValue(stream, value.toList())
}
@@ -232,11 +227,16 @@ private object UniversalBlePlatformChannelCodec : StandardMessageCodec() {
stream.write(132)
writeValue(stream, value.toList())
}
is UniversalManufacturerDataFilter -> {
stream.write(133)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}
/**
* Flutter -> Native
*
@@ -255,7 +255,7 @@ interface UniversalBlePlatformChannel {
fun requestMtu(deviceId: String, expectedMtu: Long, callback: (Result<Long>) -> Unit)
fun writeValue(deviceId: String, service: String, characteristic: String, value: ByteArray, bleOutputProperty: Long, callback: (Result<Unit>) -> Unit)
fun isPaired(deviceId: String, callback: (Result<Boolean>) -> Unit)
fun pair(deviceId: String)
fun pair(deviceId: String, callback: (Result<Boolean>) -> Unit)
fun unPair(deviceId: String)
fun getSystemDevices(withServices: List<String>, callback: (Result<List<UniversalBleScanResult>>) -> Unit)
fun getConnectionState(deviceId: String): Long
@@ -263,16 +263,17 @@ interface UniversalBlePlatformChannel {
companion object {
/** The codec used by UniversalBlePlatformChannel. */
val codec: MessageCodec<Any?> by lazy {
UniversalBlePlatformChannelCodec
UniversalBlePigeonCodec
}
/** Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(binaryMessenger: BinaryMessenger, api: UniversalBlePlatformChannel?, messageChannelSuffix: String = "") {
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
api.getBluetoothAvailabilityState() { result: Result<Long> ->
api.getBluetoothAvailabilityState{ result: Result<Long> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
@@ -290,7 +291,7 @@ interface UniversalBlePlatformChannel {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
api.enableBluetooth() { result: Result<Boolean> ->
api.enableBluetooth{ result: Result<Boolean> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
@@ -312,7 +313,7 @@ interface UniversalBlePlatformChannel {
val filterArg = args[0] as UniversalScanFilter?
val wrapped: List<Any?> = try {
api.startScan(filterArg)
listOf<Any?>(null)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -328,7 +329,7 @@ interface UniversalBlePlatformChannel {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
api.stopScan()
listOf<Any?>(null)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -346,7 +347,7 @@ interface UniversalBlePlatformChannel {
val deviceIdArg = args[0] as String
val wrapped: List<Any?> = try {
api.connect(deviceIdArg)
listOf<Any?>(null)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -364,7 +365,7 @@ interface UniversalBlePlatformChannel {
val deviceIdArg = args[0] as String
val wrapped: List<Any?> = try {
api.disconnect(deviceIdArg)
listOf<Any?>(null)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -508,13 +509,15 @@ interface UniversalBlePlatformChannel {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val deviceIdArg = args[0] as String
val wrapped: List<Any?> = try {
api.pair(deviceIdArg)
listOf<Any?>(null)
} catch (exception: Throwable) {
wrapError(exception)
api.pair(deviceIdArg) { result: Result<Boolean> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(wrapResult(data))
}
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
@@ -528,7 +531,7 @@ interface UniversalBlePlatformChannel {
val deviceIdArg = args[0] as String
val wrapped: List<Any?> = try {
api.unPair(deviceIdArg)
listOf<Any?>(null)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -565,7 +568,7 @@ interface UniversalBlePlatformChannel {
val args = message as List<Any?>
val deviceIdArg = args[0] as String
val wrapped: List<Any?> = try {
listOf<Any?>(api.getConnectionState(deviceIdArg))
listOf(api.getConnectionState(deviceIdArg))
} catch (exception: Throwable) {
wrapError(exception)
}
@@ -578,28 +581,6 @@ interface UniversalBlePlatformChannel {
}
}
}
private object UniversalBleCallbackChannelCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
128.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleScanResult.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is UniversalBleScanResult -> {
stream.write(128)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}
/**
* Native -> Flutter
*
@@ -609,7 +590,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
companion object {
/** The codec used by UniversalBleCallbackChannel. */
val codec: MessageCodec<Any?> by lazy {
UniversalBleCallbackChannelCodec
UniversalBlePigeonCodec
}
}
fun onAvailabilityChanged(stateArg: Long, callback: (Result<Unit>) -> Unit)
@@ -25,7 +25,7 @@ import java.util.UUID
private const val TAG = "UniversalBlePlugin"
val knownGatts = mutableListOf<BluetoothGatt>()
val ccdCharacteristic = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
val ccdCharacteristic: UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
enum class BleConnectionState(val value: Long) {
Connected(0),
@@ -157,8 +157,7 @@ fun Int.parseGattErrorCode(): String? {
}
fun UniversalScanFilter.toScanFilters(): List<ScanFilter> {
var scanFilters: ArrayList<ScanFilter> = arrayListOf()
val scanFilters: ArrayList<ScanFilter> = arrayListOf()
// Add withServices Filter
for (service in this.withServices) {
try {
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.bluetooth.*
import android.bluetooth.BluetoothDevice.BOND_BONDED
import android.bluetooth.BluetoothDevice.BOND_NONE
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
@@ -37,14 +36,18 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
private lateinit var context: Context
private var activity: Activity? = null
private lateinit var bluetoothManager: BluetoothManager
private val cachedServicesMap = mutableMapOf<String, List<String>>()
private val devicesStateMap = mutableMapOf<String, Int>()
// Flutter Futures
private var bluetoothEnableRequestFuture: ((Result<Boolean>) -> Unit)? = null
private val discoverServicesFutureList = mutableListOf<DiscoverServicesFuture>()
private val mtuResultFutureList = mutableListOf<MtuResultFuture>()
private val readResultFutureList = mutableListOf<ReadResultFuture>()
private val writeResultFutureList = mutableListOf<WriteResultFuture>()
private val subscriptionResultFutureList = mutableListOf<SubscriptionResultFuture>()
private val cachedServicesMap = mutableMapOf<String, List<String>>()
private val devicesStateMap = mutableMapOf<String, Int>()
private var bluetoothEnableRequestFuture: ((Result<Boolean>) -> Unit)? = null
private val pairResultFutures = mutableMapOf<String, (Result<Boolean>) -> Unit>()
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
UniversalBlePlatformChannel.setUp(flutterPluginBinding.binaryMessenger, this)
@@ -504,16 +507,46 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
callback(Result.success(remoteDevice.bondState == BOND_BONDED))
}
override fun pair(deviceId: String) {
val remoteDevice =
bluetoothManager.adapter.getRemoteDevice(deviceId)
if (remoteDevice.bondState == BOND_NONE) {
if (!remoteDevice.createBond()) {
throw FlutterError("Failed", "Failed to pair", null)
override fun pair(deviceId: String, callback: (Result<Boolean>) -> Unit) {
try {
val remoteDevice = bluetoothManager.adapter.getRemoteDevice(deviceId)
val pendingFuture = pairResultFutures.remove(deviceId)
// If already paired, return and complete pending futures
if (remoteDevice.bondState == BOND_BONDED) {
pendingFuture?.let { it(Result.success(true)) }
callback(Result.success(true))
return
}
} else {
throw FlutterError("AlreadyPair", "Already paired", null)
// throw error if we already have a pending future
if (pendingFuture != null) {
callback(
Result.failure(
FlutterError(
"InProgress",
"Pairing already in progress",
null
)
)
)
return
}
// Make a Pair request and complete future from Pair Update intent
if (remoteDevice.createBond()) {
pairResultFutures[deviceId] = callback
} else {
callback(Result.failure(FlutterError("Failed", "Failed to pair", null)))
}
} catch (e: Exception) {
callback(
Result.failure(
FlutterError("Failed", e.toString(), null)
)
)
}
}
override fun unPair(deviceId: String) {
@@ -702,6 +735,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
}
}
private fun onBondStateUpdate(deviceId: String, bonded: Boolean, error: String? = null) {
val future = pairResultFutures.remove(deviceId)
future?.let { it(Result.success(bonded)) }
mainThreadHandler?.post {
callbackChannel?.onPairStateChange(deviceId, bonded, error) {}
}
}
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
@@ -712,52 +753,37 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
) {}
}
} else if (intent.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) {
val device: BluetoothDevice =
val device: BluetoothDevice? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(
BluetoothDevice.EXTRA_DEVICE,
BluetoothDevice::class.java
)
?: return
} else {
@Suppress("DEPRECATION")
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) ?: return
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
}
if (device == null) {
Log.e(TAG, "No device found in ACTION_BOND_STATE_CHANGED intent")
return
}
// get pairing failed error
when (intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)) {
BluetoothDevice.BOND_BONDING -> {
Log.v(TAG, "${device.address} BOND_BONDING")
}
BluetoothDevice.BOND_BONDED -> {
onBondStateUpdate(device.address, true)
}
BluetoothDevice.ERROR -> {
mainThreadHandler?.post {
callbackChannel?.onPairStateChange(
device.address,
false,
"No pairing state received"
) {}
}
onBondStateUpdate(device.address, false, "Failed to Pair")
}
BOND_BONDED -> {
mainThreadHandler?.post {
callbackChannel?.onPairStateChange(
device.address,
true,
null
) {}
}
}
BOND_NONE -> {
mainThreadHandler?.post {
callbackChannel?.onPairStateChange(
device.address,
false,
null
) {}
}
BluetoothDevice.BOND_NONE -> {
Log.e(TAG, "${device.address} BOND_NONE")
onBondStateUpdate(device.address, false)
}
}
}
+70 -80
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v18.0.1), do not edit directly.
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -11,11 +11,36 @@ import Foundation
#error("Unsupported platform.")
#endif
/// Error class for passing custom error details to Dart side.
final class PigeonError: Error {
let code: String
let message: String?
let details: Any?
init(code: String, message: String?, details: Any?) {
self.code = code
self.message = message
self.details = details
}
var localizedDescription: String {
return
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
}
}
private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}
private func wrapError(_ error: Any) -> [Any?] {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
return [
flutterError.code,
@@ -30,8 +55,8 @@ private func wrapError(_ error: Any) -> [Any?] {
]
}
private func createConnectionError(withChannelName channelName: String) -> FlutterError {
return FlutterError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
private func createConnectionError(withChannelName channelName: String) -> PigeonError {
return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
}
private func isNullish(_ value: Any?) -> Bool {
@@ -183,63 +208,63 @@ struct UniversalManufacturerDataFilter {
]
}
}
private class UniversalBlePlatformChannelCodecReader: FlutterStandardReader {
private class UniversalBlePigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
case 129:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
case 130:
return UniversalBleService.fromList(self.readValue() as! [Any?])
case 131:
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
case 132:
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
case 133:
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
private class UniversalBlePlatformChannelCodecWriter: FlutterStandardWriter {
private class UniversalBlePigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? UniversalBleCharacteristic {
super.writeByte(128)
super.writeValue(value.toList())
} else if let value = value as? UniversalBleScanResult {
if let value = value as? UniversalBleScanResult {
super.writeByte(129)
super.writeValue(value.toList())
} else if let value = value as? UniversalBleService {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerDataFilter {
} else if let value = value as? UniversalBleCharacteristic {
super.writeByte(131)
super.writeValue(value.toList())
} else if let value = value as? UniversalScanFilter {
super.writeByte(132)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerDataFilter {
super.writeByte(133)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class UniversalBlePlatformChannelCodecReaderWriter: FlutterStandardReaderWriter {
private class UniversalBlePigeonCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return UniversalBlePlatformChannelCodecReader(data: data)
return UniversalBlePigeonCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return UniversalBlePlatformChannelCodecWriter(data: data)
return UniversalBlePigeonCodecWriter(data: data)
}
}
class UniversalBlePlatformChannelCodec: FlutterStandardMessageCodec {
static let shared = UniversalBlePlatformChannelCodec(readerWriter: UniversalBlePlatformChannelCodecReaderWriter())
class UniversalBlePigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = UniversalBlePigeonCodec(readerWriter: UniversalBlePigeonCodecReaderWriter())
}
/// Flutter -> Native
///
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
@@ -256,7 +281,7 @@ protocol UniversalBlePlatformChannel {
func requestMtu(deviceId: String, expectedMtu: Int64, completion: @escaping (Result<Int64, Error>) -> Void)
func writeValue(deviceId: String, service: String, characteristic: String, value: FlutterStandardTypedData, bleOutputProperty: Int64, completion: @escaping (Result<Void, Error>) -> Void)
func isPaired(deviceId: String, completion: @escaping (Result<Bool, Error>) -> Void)
func pair(deviceId: String) throws
func pair(deviceId: String, completion: @escaping (Result<Bool, Error>) -> Void)
func unPair(deviceId: String) throws
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void)
func getConnectionState(deviceId: String) throws -> Int64
@@ -264,8 +289,7 @@ protocol UniversalBlePlatformChannel {
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class UniversalBlePlatformChannelSetup {
/// The codec used by UniversalBlePlatformChannel.
static var codec: FlutterStandardMessageCodec { UniversalBlePlatformChannelCodec.shared }
static var codec: FlutterStandardMessageCodec { UniversalBlePigeonCodec.shared }
/// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: UniversalBlePlatformChannel?, messageChannelSuffix: String = "") {
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
@@ -474,11 +498,13 @@ class UniversalBlePlatformChannelSetup {
pairChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let deviceIdArg = args[0] as! String
do {
try api.pair(deviceId: deviceIdArg)
reply(wrapResult(nil))
} catch {
reply(wrapError(error))
api.pair(deviceId: deviceIdArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
@@ -533,51 +559,15 @@ class UniversalBlePlatformChannelSetup {
}
}
}
private class UniversalBleCallbackChannelCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
private class UniversalBleCallbackChannelCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? UniversalBleScanResult {
super.writeByte(128)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class UniversalBleCallbackChannelCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return UniversalBleCallbackChannelCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return UniversalBleCallbackChannelCodecWriter(data: data)
}
}
class UniversalBleCallbackChannelCodec: FlutterStandardMessageCodec {
static let shared = UniversalBleCallbackChannelCodec(readerWriter: UniversalBleCallbackChannelCodecReaderWriter())
}
/// Native -> Flutter
///
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
protocol UniversalBleCallbackChannelProtocol {
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onAvailabilityChanged(state stateArg: Int64, 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 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)
}
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
private let binaryMessenger: FlutterBinaryMessenger
@@ -586,10 +576,10 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
self.binaryMessenger = binaryMessenger
self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
}
var codec: FlutterStandardMessageCodec {
return UniversalBleCallbackChannelCodec.shared
var codec: UniversalBlePigeonCodec {
return UniversalBlePigeonCodec.shared
}
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, PigeonError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([stateArg] as [Any?]) { response in
@@ -601,13 +591,13 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
completion(.failure(FlutterError(code: code, message: message, details: details)))
completion(.failure(PigeonError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void) {
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, isPairedArg, errorArg] as [Any?]) { response in
@@ -619,13 +609,13 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
completion(.failure(FlutterError(code: code, message: message, details: details)))
completion(.failure(PigeonError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void) {
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, PigeonError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([resultArg] as [Any?]) { response in
@@ -637,13 +627,13 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
completion(.failure(FlutterError(code: code, message: message, details: details)))
completion(.failure(PigeonError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, PigeonError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, characteristicIdArg, valueArg] as [Any?]) { response in
@@ -655,13 +645,13 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
completion(.failure(FlutterError(code: code, message: message, details: details)))
completion(.failure(PigeonError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, 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
@@ -673,7 +663,7 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
completion(.failure(FlutterError(code: code, message: message, details: details)))
completion(.failure(PigeonError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
+2 -2
View File
@@ -280,8 +280,8 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
completion(Result.failure(FlutterError(code: "NotSupported", message: nil, details: nil)))
}
func pair(deviceId _: String) throws {
throw FlutterError(code: "Implemented in Dart", 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)))
}
func unPair(deviceId _: String) throws {
-2
View File
@@ -41,7 +41,6 @@ android {
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.navideck.universal_ble_example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
@@ -53,7 +52,6 @@ android {
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
-29
View File
@@ -1,29 +0,0 @@
import 'package:flutter/foundation.dart';
class Capabilities {
static bool requiresRuntimePermission =
!Platform.isWeb && !Platform.isWindows && !Platform.isLinux;
static bool supportsBluetoothEnableApi =
!Platform.isWeb && !Platform.isCupertino;
static bool supportsConnectedDevicesApi = !Platform.isWeb;
static bool supportsPairingApi = !Platform.isWeb;
static bool supportsRequestMtuApi = !Platform.isWeb;
}
class Platform {
static bool isWeb = kIsWeb;
static bool isIOS = !isWeb && defaultTargetPlatform == TargetPlatform.iOS;
static bool isAndroid =
!isWeb && defaultTargetPlatform == TargetPlatform.android;
static bool isMacos = !isWeb && defaultTargetPlatform == TargetPlatform.macOS;
static bool isWindows =
!isWeb && defaultTargetPlatform == TargetPlatform.windows;
static bool isLinux = !isWeb && defaultTargetPlatform == TargetPlatform.linux;
static bool get isMobile => isIOS || isAndroid;
static bool get isCupertino => isIOS || isMacos;
static bool get isDesktop => isWindows || isLinux || isMacos;
}
+7 -2
View File
@@ -65,7 +65,11 @@ class MockUniversalBle extends UniversalBlePlatform {
@override
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
String deviceId,
String service,
String characteristic, {
final Duration? timeout,
}) async {
await Future.delayed(const Duration(milliseconds: 500));
return _serviceValue;
}
@@ -98,8 +102,9 @@ class MockUniversalBle extends UniversalBlePlatform {
}
@override
Future<void> pair(String deviceId) async {
Future<bool> pair(String deviceId) async {
updatePairingState(deviceId, true, null);
return true;
}
@override
+4 -7
View File
@@ -1,10 +1,7 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:universal_ble/universal_ble.dart';
import 'package:universal_ble_example/data/capabilities.dart';
import 'package:universal_ble_example/data/mock_universal_ble.dart';
import 'package:universal_ble_example/home/widgets/scan_filter_widget.dart';
import 'package:universal_ble_example/home/widgets/scanned_devices_placeholder_widget.dart';
@@ -52,7 +49,7 @@ class _MyAppState extends State<MyApp> {
};
UniversalBle.onScanResult = (result) {
log(result.toString());
// log(result.toString());
int index = _bleDevices.indexWhere((e) => e.deviceId == result.deviceId);
if (index == -1) {
_bleDevices.add(result);
@@ -148,7 +145,7 @@ class _MyAppState extends State<MyApp> {
});
},
),
if (Capabilities.supportsBluetoothEnableApi &&
if (BleCapabilities.supportsBluetoothEnableApi &&
bleAvailabilityState == AvailabilityState.poweredOff)
PlatformButton(
text: 'Enable Bluetooth',
@@ -159,7 +156,7 @@ class _MyAppState extends State<MyApp> {
);
},
),
if (Capabilities.requiresRuntimePermission)
if (BleCapabilities.requiresRuntimePermission)
PlatformButton(
text: 'Check Permissions',
onPressed: () async {
@@ -172,7 +169,7 @@ class _MyAppState extends State<MyApp> {
}
},
),
if (Capabilities.supportsConnectedDevicesApi)
if (BleCapabilities.supportsConnectedDevicesApi)
PlatformButton(
text: 'Connected Devices',
onPressed: () async {
@@ -1,7 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:universal_ble/universal_ble.dart';
import 'package:universal_ble_example/data/capabilities.dart';
class ScannedItemWidget extends StatelessWidget {
final BleDevice bleDevice;
@@ -31,9 +30,7 @@ class ScannedItemWidget extends StatelessWidget {
Visibility(
visible: manufacturerData != null,
child: Text(
Platform.isWeb || Platform.isDesktop
? manufacturerData.toString()
: 'ManufacturerCompanyId: ${manufacturerData?.companyIdRadix16}',
'CompanyIdentifier: ${manufacturerData.toString()} (${manufacturerData?.companyIdRadix16})',
),
),
bleDevice.isPaired == true
@@ -6,7 +6,6 @@ import 'package:convert/convert.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:universal_ble/universal_ble.dart';
import 'package:universal_ble_example/data/capabilities.dart';
import 'package:universal_ble_example/peripheral_details/widgets/result_widget.dart';
import 'package:universal_ble_example/peripheral_details/widgets/services_list_widget.dart';
import 'package:universal_ble_example/widgets/platform_button.dart';
@@ -86,9 +85,9 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
String deviceId, bool isPaired, String? error) {
print('isPaired $deviceId, $isPaired');
if (error != null && error.isNotEmpty) {
_addLog("PairStateChangeError", "(Paired: $isPaired): $error ");
_addLog("PairingStateChangeError", "(Paired: $isPaired): $error ");
} else {
_addLog("PairStateChange - isPaired", isPaired);
_addLog("PairingStateChange - isPaired", isPaired);
}
}
@@ -357,7 +356,7 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
},
text: 'Connection State',
),
if (Capabilities.supportsRequestMtuApi)
if (BleCapabilities.supportsRequestMtuApi)
PlatformButton(
enabled: isConnected,
onPressed: () async {
@@ -408,29 +407,29 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
BleInputProperty.disabled),
text: 'Unsubscribe',
),
PlatformButton(
onPressed: () async {
await UniversalBle.pair(
widget.deviceId,
// pairingCommand: BleCommand(
// service:
// "",
// characteristic:
// "",
// ),
);
},
text: 'Pair',
Visibility(
visible: BleCapabilities.supportsInAppPairing,
child: PlatformButton(
onPressed: () async {
bool? pairingResult = await UniversalBle.pair(
widget.deviceId,
// pairingCommand: BleCommand(
// service: "",
// characteristic: "",
// ),
);
_addLog("Pairing Result", pairingResult);
},
text: 'Pair',
),
),
PlatformButton(
onPressed: () async {
bool? isPaired = await UniversalBle.isPaired(
widget.deviceId,
// pairingCheckCommand: BleCommand(
// service:
// "",
// characteristic:
// "",
// pairingCommand: BleCommand(
// service: "",
// characteristic: "",
// ),
);
_addLog('IsPaired', isPaired);
+4 -4
View File
@@ -15,12 +15,12 @@ class BleCommandQueue {
Future<T> Function() command, {
bool withTimeout = true,
String? deviceId,
Duration? timeout,
}) {
Duration? duration = withTimeout ? timeout : null;
Duration? duration = timeout ?? (withTimeout ? this.timeout : null);
return switch (queueType) {
QueueType.global => _queue().add(command, timeout: duration),
QueueType.perDevice => _queue(deviceId).add(command, timeout: duration),
QueueType.global => _queue().add(command, duration),
QueueType.perDevice => _queue(deviceId).add(command, duration),
QueueType.none =>
duration != null ? command().timeout(duration) : command(),
};
+36
View File
@@ -0,0 +1,36 @@
import 'package:flutter/foundation.dart';
class BleCapabilities {
/// Returns true if pairing is possible either by API or by encrypted characteristic.
/// All platforms support this except Windows/Web.
static final bool supportsInAppPairing =
_triggersPairingWithEncryptedChar || hasSystemPairingApi;
static final _triggersPairingWithEncryptedChar =
defaultTargetPlatform != TargetPlatform.windows;
static bool hasSystemPairingApi = !kIsWeb &&
(defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.windows ||
defaultTargetPlatform == TargetPlatform.linux);
static bool requiresRuntimePermission =
!_Platform.isWeb && !_Platform.isWindows && !_Platform.isLinux;
static bool supportsBluetoothEnableApi =
!_Platform.isWeb && !_Platform.isCupertino;
static bool supportsConnectedDevicesApi = !_Platform.isWeb;
static bool supportsRequestMtuApi = !_Platform.isWeb;
}
class _Platform {
static bool isWeb = kIsWeb;
static bool isIOS = !isWeb && defaultTargetPlatform == TargetPlatform.iOS;
static bool isMacos = !isWeb && defaultTargetPlatform == TargetPlatform.macOS;
static bool isWindows =
!isWeb && defaultTargetPlatform == TargetPlatform.windows;
static bool isLinux = !isWeb && defaultTargetPlatform == TargetPlatform.linux;
static bool get isCupertino => isIOS || isMacos;
}
+1
View File
@@ -8,4 +8,5 @@ export 'package:universal_ble/src/models/availability_state.dart';
export 'package:universal_ble/src/models/ble_connection_state.dart';
export 'package:universal_ble/src/models/ble_device.dart';
export 'package:universal_ble/src/models/ble_command.dart';
export 'package:universal_ble/src/models/ble_capabilities.dart';
+1 -1
View File
@@ -11,7 +11,7 @@ class Queue {
final List<_QueuedFuture> _nextCycle = [];
Function(int)? onRemainingItemsUpdate;
Future<T> add<T>(Future<T> Function() closure, {Duration? timeout}) {
Future<T> add<T>(Future<T> Function() closure, [Duration? timeout]) {
if (_isCancelled) throw Exception('Queue Cancelled');
final completer = Completer<T>();
_nextCycle.add(_QueuedFuture<T>(closure, completer, timeout));
+57 -39
View File
@@ -1,5 +1,4 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:universal_ble/src/ble_command_queue.dart';
@@ -157,14 +156,17 @@ class UniversalBle {
static Future<Uint8List> readValue(
String deviceId,
String service,
String characteristic,
) async {
String characteristic, {
final Duration? timeout,
}) async {
return await _bleCommandQueue.queueCommand(
() => _platform.readValue(
deviceId,
BleUuidParser.string(service),
BleUuidParser.string(characteristic),
timeout: timeout ?? _bleCommandQueue.timeout,
),
timeout: timeout,
deviceId: deviceId,
);
}
@@ -200,45 +202,49 @@ class UniversalBle {
}
/// Check if a device is paired.
/// Returns null on `Apple` and `Web` when no `bleCommand` is passed.
///
/// On Apple and Web, you can optionally pass a pairingCheckCommand if you know an encrypted read or write characteristic.
/// It will trigger pairing if the device is not already paired.
/// For Apple and Web, you can optionally pass a pairingCommand if you know an encrypted read or write characteristic.
/// It will return true/false if it manages to execute the command.
/// Note that it will trigger pairing if the device is not already paired.
///
/// Returns null on `Apple` and `Web` when no `bleCommand` is passed.
static Future<bool?> isPaired(
String deviceId, {
BleCommand? pairingCheckCommand,
BleCommand? pairingCommand,
}) async {
bool lacksPairingApi = kIsWeb || Platform.isMacOS || Platform.isIOS;
if (lacksPairingApi && pairingCheckCommand == null) {
return null;
if (BleCapabilities.hasSystemPairingApi) {
return _bleCommandQueue.queueCommand(
() => _platform.isPaired(deviceId),
deviceId: deviceId,
);
} else if (pairingCommand != null) {
return _connectAndExecuteBleCommand(deviceId, pairingCommand,
updateCallbackValue: false);
}
return lacksPairingApi
? await _connectAndExecuteBleCommand(deviceId, pairingCheckCommand)
: await _bleCommandQueue.queueCommand(
() => _platform.isPaired(deviceId),
deviceId: deviceId,
);
return null;
}
/// Pair a device.
/// It might throw an error if device is already paired.
///
/// On Apple, it only works on devices with encrypted characteristics.
/// It throws an error if there is no readable characteristic.
/// On `Apple` and `Web`, it only works on devices with encrypted characteristics.
/// It returns null if there is no readable characteristic.
///
/// You can optionally pass a pairingCommand if you know an encrypted read or write characteristic.
static Future<void> pair(
/// If you do, it returns true if it can successfully execute the command after pairing.
///
/// Throws UnsupportedError on `Web/Windows`
static Future<bool?> pair(
String deviceId, {
BleCommand? pairingCommand,
}) =>
kIsWeb || Platform.isMacOS || Platform.isIOS
? _connectAndExecuteBleCommand(deviceId, pairingCommand)
: _bleCommandQueue.queueCommand(
() => _platform.pair(deviceId),
deviceId: deviceId,
);
}) async {
if (!BleCapabilities.supportsInAppPairing) {
throw UnsupportedError("Not supported");
}
if (BleCapabilities.hasSystemPairingApi) {
return _platform.pair(deviceId);
}
return _connectAndExecuteBleCommand(deviceId, pairingCommand);
}
/// Unpair a device.
/// It might throw an error if device is not paired.
@@ -302,8 +308,9 @@ class UniversalBle {
static Future<bool?> _connectAndExecuteBleCommand(
String deviceId,
BleCommand? bleCommand,
) async {
BleCommand? bleCommand, {
bool updateCallbackValue = false,
}) async {
try {
if (await getConnectionState(deviceId) != BleConnectionState.connected) {
await connect(deviceId);
@@ -315,16 +322,20 @@ class UniversalBle {
await _attemptPairingReadingAll(deviceId, services);
return null;
} else {
await _executeBleCommand(deviceId, services, bleCommand);
_platform.updatePairingState(deviceId, true, null);
return true;
bool commandResult =
await _executeBleCommand(deviceId, services, bleCommand);
if (updateCallbackValue) {
_platform.updatePairingState(deviceId, commandResult, null);
}
return commandResult;
}
} catch (e) {
UniversalBlePlatform.logInfo(
"FailedToPerform EncryptedCharOperation: $e",
);
// Probably failed to pair, Notify callback
_platform.updatePairingState(deviceId, false, e.toString());
if (updateCallbackValue) {
_platform.updatePairingState(deviceId, false, e.toString());
}
return false;
}
}
@@ -341,7 +352,12 @@ class UniversalBle {
for (BleCharacteristic characteristic in service.characteristics) {
if (characteristic.properties.contains(CharacteristicProperty.read)) {
containsReadCharacteristics = true;
await readValue(deviceId, service.uuid, characteristic.uuid);
await readValue(
deviceId,
service.uuid,
characteristic.uuid,
timeout: const Duration(seconds: 30),
);
}
}
}
@@ -351,7 +367,7 @@ class UniversalBle {
}
}
static Future<void> _executeBleCommand(
static Future<bool> _executeBleCommand(
String deviceId,
List<BleService> services,
BleCommand bleCommand,
@@ -371,7 +387,7 @@ class UniversalBle {
}
if (characteristic == null) {
throw "BleCommand char not found";
return false;
}
// Check if BleCommand Supports Read or Write
@@ -383,7 +399,7 @@ class UniversalBle {
bleOutputProperty = BleOutputProperty.withoutResponse;
} else if (!characteristic.properties
.contains(CharacteristicProperty.read)) {
throw "BleCommand does not support read or write operations";
return false;
}
Uint8List? value = bleCommand.writeValue;
@@ -401,8 +417,10 @@ class UniversalBle {
deviceId,
bleCommand.service,
bleCommand.characteristic,
timeout: const Duration(seconds: 30),
);
}
return true;
}
/// Get updates of remaining items of a queue.
@@ -214,7 +214,11 @@ class UniversalBleLinux extends UniversalBlePlatform {
@override
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
String deviceId,
String service,
String characteristic, {
final Duration? timeout,
}) async {
try {
final c = _getCharacteristic(deviceId, service, characteristic);
final data = await c.readValue();
@@ -270,11 +274,16 @@ class UniversalBleLinux extends UniversalBlePlatform {
}
@override
Future<void> pair(String deviceId) async {
Future<bool> pair(String deviceId) async {
BlueZDevice device = _findDeviceById(deviceId);
device.pair().onError((error, _) {
try {
if (device.paired) return true;
await device.pair();
return true;
} catch (error) {
updatePairingState(deviceId, false, error.toString());
});
return false;
}
}
@override
+108 -200
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v18.0.1), do not edit directly.
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
@@ -15,8 +15,7 @@ PlatformException _createConnectionError(String channelName) {
);
}
List<Object?> wrapResponse(
{Object? result, PlatformException? error, bool empty = false}) {
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
}
@@ -98,8 +97,7 @@ class UniversalBleService {
result as List<Object?>;
return UniversalBleService(
uuid: result[0]! as String,
characteristics:
(result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
characteristics: (result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
);
}
}
@@ -152,8 +150,7 @@ class UniversalScanFilter {
result as List<Object?>;
return UniversalScanFilter(
withServices: (result[0] as List<Object?>?)!.cast<String?>(),
withManufacturerData: (result[1] as List<Object?>?)!
.cast<UniversalManufacturerDataFilter?>(),
withManufacturerData: (result[1] as List<Object?>?)!.cast<UniversalManufacturerDataFilter?>(),
);
}
}
@@ -189,25 +186,26 @@ class UniversalManufacturerDataFilter {
}
}
class _UniversalBlePlatformChannelCodec extends StandardMessageCodec {
const _UniversalBlePlatformChannelCodec();
class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is UniversalBleCharacteristic) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else if (value is UniversalBleScanResult) {
if (value is UniversalBleScanResult) {
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is UniversalBleService) {
} else if (value is UniversalBleService) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerDataFilter) {
} else if (value is UniversalBleCharacteristic) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is UniversalScanFilter) {
} else if (value is UniversalScanFilter) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerDataFilter) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@@ -216,16 +214,16 @@ class _UniversalBlePlatformChannelCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return UniversalBleCharacteristic.decode(readValue(buffer)!);
case 129:
case 129:
return UniversalBleScanResult.decode(readValue(buffer)!);
case 130:
case 130:
return UniversalBleService.decode(readValue(buffer)!);
case 131:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
case 132:
case 131:
return UniversalBleCharacteristic.decode(readValue(buffer)!);
case 132:
return UniversalScanFilter.decode(readValue(buffer)!);
case 133:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@@ -237,23 +235,18 @@ class UniversalBlePlatformChannel {
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UniversalBlePlatformChannel(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: __pigeon_binaryMessenger = binaryMessenger,
__pigeon_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
__pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? __pigeon_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec =
_UniversalBlePlatformChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
final String __pigeon_messageChannelSuffix;
Future<int> getBluetoothAvailabilityState() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -279,10 +272,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> enableBluetooth() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -308,10 +299,8 @@ class UniversalBlePlatformChannel {
}
Future<void> startScan(UniversalScanFilter? filter) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -332,10 +321,8 @@ class UniversalBlePlatformChannel {
}
Future<void> stopScan() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -356,10 +343,8 @@ class UniversalBlePlatformChannel {
}
Future<void> connect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -380,10 +365,8 @@ class UniversalBlePlatformChannel {
}
Future<void> disconnect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -403,19 +386,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> setNotifiable(String deviceId, String service,
String characteristic, int bleInputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel.send(
<Object?>[deviceId, service, characteristic, bleInputProperty])
as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, bleInputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -430,10 +409,8 @@ class UniversalBlePlatformChannel {
}
Future<List<UniversalBleService?>> discoverServices(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -454,23 +431,19 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleService?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleService?>();
}
}
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<Uint8List> readValue(String deviceId, String service, String characteristic) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -490,16 +463,14 @@ class UniversalBlePlatformChannel {
}
Future<int> requestMtu(String deviceId, int expectedMtu) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -518,24 +489,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> writeValue(String deviceId, String service,
String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[
deviceId,
service,
characteristic,
value,
bleOutputProperty
]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, value, bleOutputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -550,10 +512,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> isPaired(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -578,11 +538,9 @@ class UniversalBlePlatformChannel {
}
}
Future<void> pair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<bool> pair(String deviceId) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -597,16 +555,19 @@ class UniversalBlePlatformChannel {
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return;
return (__pigeon_replyList[0] as bool?)!;
}
}
Future<void> unPair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -626,12 +587,9 @@ class UniversalBlePlatformChannel {
}
}
Future<List<UniversalBleScanResult?>> getSystemDevices(
List<String?> withServices) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<List<UniversalBleScanResult?>> getSystemDevices(List<String?> withServices) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -652,16 +610,13 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleScanResult?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
}
}
Future<int> getConnectionState(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -687,33 +642,9 @@ class UniversalBlePlatformChannel {
}
}
class _UniversalBleCallbackChannelCodec extends StandardMessageCodec {
const _UniversalBleCallbackChannelCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is UniversalBleScanResult) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return UniversalBleScanResult.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
/// Native -> Flutter
abstract class UniversalBleCallbackChannel {
static const MessageCodec<Object?> pigeonChannelCodec =
_UniversalBleCallbackChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
void onAvailabilityChanged(int state);
@@ -721,30 +652,22 @@ abstract class UniversalBleCallbackChannel {
void onScanResult(UniversalBleScanResult result);
void onValueChanged(
String deviceId, String characteristicId, Uint8List value);
void onValueChanged(String deviceId, String characteristicId, Uint8List value);
void onConnectionChanged(String deviceId, bool connected);
static void setUp(
UniversalBleCallbackChannel? api, {
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
static void setUp(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_state = (args[0] as int?);
assert(arg_state != null,
@@ -754,25 +677,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -786,28 +706,24 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
final List<Object?> args = (message as List<Object?>?)!;
final UniversalBleScanResult? arg_result =
(args[0] as UniversalBleScanResult?);
final UniversalBleScanResult? arg_result = (args[0] as UniversalBleScanResult?);
assert(arg_result != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
try {
@@ -815,25 +731,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -845,30 +758,26 @@ abstract class UniversalBleCallbackChannel {
assert(arg_value != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
try {
api.onValueChanged(
arg_deviceId!, arg_characteristicId!, arg_value!);
api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -881,9 +790,8 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
import 'package:universal_ble/universal_ble.dart';
@@ -23,7 +21,9 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
@override
Future<bool> enableBluetooth() {
if (Platform.isIOS || Platform.isMacOS) throw UnimplementedError();
if (!BleCapabilities.supportsBluetoothEnableApi) {
throw UnsupportedError("Not supported");
}
return _channel.enableBluetooth();
}
@@ -77,7 +77,11 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
@override
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) {
String deviceId,
String service,
String characteristic, {
final Duration? timeout,
}) {
return _channel.readValue(deviceId, service, characteristic);
}
@@ -105,7 +109,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
Future<bool> isPaired(String deviceId) => _channel.isPaired(deviceId);
@override
Future<void> pair(String deviceId) => _channel.pair(deviceId);
Future<bool> pair(String deviceId) => _channel.pair(deviceId);
@override
Future<void> unpair(String deviceId) => _channel.unPair(deviceId);
@@ -30,7 +30,11 @@ abstract class UniversalBlePlatform {
String characteristic, BleInputProperty bleInputProperty);
Future<Uint8List> readValue(
String deviceId, String service, String characteristic);
String deviceId,
String service,
String characteristic, {
final Duration? timeout,
});
Future<void> writeValue(
String deviceId,
@@ -43,7 +47,7 @@ abstract class UniversalBlePlatform {
Future<bool> isPaired(String deviceId);
Future<void> pair(String deviceId);
Future<bool> pair(String deviceId);
Future<void> unpair(String deviceId);
@@ -214,8 +214,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
Future<Uint8List> readValue(
String deviceId,
String service,
String characteristic,
) async {
String characteristic, {
final Duration? timeout,
}) async {
var bleCharacteristic = await _getBleCharacteristic(
deviceId: deviceId,
serviceId: service,
@@ -225,8 +226,10 @@ class UniversalBleWeb extends UniversalBlePlatform {
throw Exception(
'Characteristic $characteristic for service $service not found');
}
var data = await bleCharacteristic.readValue();
return data.buffer.asUint8List();
var data = timeout != null
? bleCharacteristic.readValue(timeout: timeout)
: bleCharacteristic.readValue();
return (await data).buffer.asUint8List();
}
/// `Unimplemented`
@@ -241,7 +244,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
}
@override
Future<void> pair(String deviceId) {
Future<bool> pair(String deviceId) {
throw UnimplementedError();
}
+2 -1
View File
@@ -68,7 +68,8 @@ abstract class UniversalBlePlatformChannel {
@async
bool isPaired(String deviceId);
void pair(String deviceId);
@async
bool pair(String deviceId);
void unPair(String deviceId);
+1 -1
View File
@@ -30,7 +30,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
pigeon: ^18.0.1
pigeon: ^21.1.0
flutter:
plugin:
+27 -53
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v18.0.1), do not edit directly.
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#undef _HAS_EXCEPTIONS
@@ -390,36 +390,31 @@ UniversalManufacturerDataFilter UniversalManufacturerDataFilter::FromEncodableLi
}
UniversalBlePlatformChannelCodecSerializer::UniversalBlePlatformChannelCodecSerializer() {}
PigeonCodecSerializer::PigeonCodecSerializer() {}
EncodableValue UniversalBlePlatformChannelCodecSerializer::ReadValueOfType(
EncodableValue PigeonCodecSerializer::ReadValueOfType(
uint8_t type,
flutter::ByteStreamReader* stream) const {
switch (type) {
case 128:
return CustomEncodableValue(UniversalBleCharacteristic::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(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
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))));
default:
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
}
}
}
void UniversalBlePlatformChannelCodecSerializer::WriteValue(
void PigeonCodecSerializer::WriteValue(
const EncodableValue& value,
flutter::ByteStreamWriter* stream) const {
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
stream->WriteByte(128);
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleScanResult)) {
stream->WriteByte(129);
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
@@ -430,9 +425,9 @@ void UniversalBlePlatformChannelCodecSerializer::WriteValue(
WriteValue(EncodableValue(std::any_cast<UniversalBleService>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) {
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
stream->WriteByte(131);
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerDataFilter>(*custom_value).ToEncodableList()), stream);
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalScanFilter)) {
@@ -440,13 +435,18 @@ void UniversalBlePlatformChannelCodecSerializer::WriteValue(
WriteValue(EncodableValue(std::any_cast<UniversalScanFilter>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) {
stream->WriteByte(133);
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerDataFilter>(*custom_value).ToEncodableList()), stream);
return;
}
}
flutter::StandardCodecSerializer::WriteValue(value, stream);
}
/// The codec used by UniversalBlePlatformChannel.
const flutter::StandardMessageCodec& UniversalBlePlatformChannel::GetCodec() {
return flutter::StandardMessageCodec::GetInstance(&UniversalBlePlatformChannelCodecSerializer::GetInstance());
return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance());
}
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
@@ -512,7 +512,7 @@ void UniversalBlePlatformChannel::SetUp(
try {
const auto& args = std::get<EncodableList>(message);
const auto& encodable_filter_arg = args.at(0);
const auto* filter_arg = &(std::any_cast<const UniversalScanFilter&>(std::get<CustomEncodableValue>(encodable_filter_arg)));
const auto* filter_arg = encodable_filter_arg.IsNull() ? nullptr : &(std::any_cast<const UniversalScanFilter&>(std::get<CustomEncodableValue>(encodable_filter_arg)));
std::optional<FlutterError> output = api->StartScan(filter_arg);
if (output.has_value()) {
reply(WrapError(output.value()));
@@ -852,14 +852,15 @@ void UniversalBlePlatformChannel::SetUp(
return;
}
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
std::optional<FlutterError> output = api->Pair(device_id_arg);
if (output.has_value()) {
reply(WrapError(output.value()));
return;
}
EncodableList wrapped;
wrapped.push_back(EncodableValue());
reply(EncodableValue(std::move(wrapped)));
api->Pair(device_id_arg, [reply](ErrorOr<bool>&& output) {
if (output.has_error()) {
reply(WrapError(output.error()));
return;
}
EncodableList wrapped;
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
reply(EncodableValue(std::move(wrapped)));
});
} catch (const std::exception& exception) {
reply(WrapError(exception.what()));
}
@@ -971,33 +972,6 @@ EncodableValue UniversalBlePlatformChannel::WrapError(const FlutterError& error)
});
}
UniversalBleCallbackChannelCodecSerializer::UniversalBleCallbackChannelCodecSerializer() {}
EncodableValue UniversalBleCallbackChannelCodecSerializer::ReadValueOfType(
uint8_t type,
flutter::ByteStreamReader* stream) const {
switch (type) {
case 128:
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
default:
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
}
}
void UniversalBleCallbackChannelCodecSerializer::WriteValue(
const EncodableValue& value,
flutter::ByteStreamWriter* stream) const {
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
if (custom_value->type() == typeid(UniversalBleScanResult)) {
stream->WriteByte(128);
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
return;
}
}
flutter::StandardCodecSerializer::WriteValue(value, stream);
}
// Generated class from Pigeon that represents Flutter messages that can be called from C++.
UniversalBleCallbackChannel::UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger)
: binary_messenger_(binary_messenger),
@@ -1010,7 +984,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(&UniversalBleCallbackChannelCodecSerializer::GetInstance());
return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance());
}
void UniversalBleCallbackChannel::OnAvailabilityChanged(
+13 -35
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v18.0.1), do not edit directly.
// Autogenerated from Pigeon (v21.1.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#ifndef PIGEON_UNIVERSAL_BLE_G_H_
@@ -105,9 +105,8 @@ class UniversalBleScanResult {
static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBlePlatformChannelCodecSerializer;
friend class UniversalBleCallbackChannel;
friend class UniversalBleCallbackChannelCodecSerializer;
friend class PigeonCodecSerializer;
std::string device_id_;
std::optional<std::string> name_;
std::optional<bool> is_paired_;
@@ -142,9 +141,8 @@ class UniversalBleService {
static UniversalBleService FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBlePlatformChannelCodecSerializer;
friend class UniversalBleCallbackChannel;
friend class UniversalBleCallbackChannelCodecSerializer;
friend class PigeonCodecSerializer;
std::string uuid_;
std::optional<flutter::EncodableList> characteristics_;
@@ -170,9 +168,8 @@ class UniversalBleCharacteristic {
static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBlePlatformChannelCodecSerializer;
friend class UniversalBleCallbackChannel;
friend class UniversalBleCallbackChannelCodecSerializer;
friend class PigeonCodecSerializer;
std::string uuid_;
flutter::EncodableList properties_;
@@ -200,9 +197,8 @@ class UniversalScanFilter {
static UniversalScanFilter FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBlePlatformChannelCodecSerializer;
friend class UniversalBleCallbackChannel;
friend class UniversalBleCallbackChannelCodecSerializer;
friend class PigeonCodecSerializer;
flutter::EncodableList with_services_;
flutter::EncodableList with_manufacturer_data_;
@@ -238,20 +234,19 @@ class UniversalManufacturerDataFilter {
static UniversalManufacturerDataFilter FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBlePlatformChannelCodecSerializer;
friend class UniversalBleCallbackChannel;
friend class UniversalBleCallbackChannelCodecSerializer;
friend class PigeonCodecSerializer;
std::optional<int64_t> company_identifier_;
std::optional<std::vector<uint8_t>> data_;
std::optional<std::vector<uint8_t>> mask_;
};
class UniversalBlePlatformChannelCodecSerializer : public flutter::StandardCodecSerializer {
class PigeonCodecSerializer : public flutter::StandardCodecSerializer {
public:
UniversalBlePlatformChannelCodecSerializer();
inline static UniversalBlePlatformChannelCodecSerializer& GetInstance() {
static UniversalBlePlatformChannelCodecSerializer sInstance;
PigeonCodecSerializer();
inline static PigeonCodecSerializer& GetInstance() {
static PigeonCodecSerializer sInstance;
return sInstance;
}
@@ -308,7 +303,9 @@ class UniversalBlePlatformChannel {
virtual void IsPaired(
const std::string& device_id,
std::function<void(ErrorOr<bool> reply)> result) = 0;
virtual std::optional<FlutterError> Pair(const std::string& device_id) = 0;
virtual void Pair(
const std::string& device_id,
std::function<void(ErrorOr<bool> reply)> result) = 0;
virtual std::optional<FlutterError> UnPair(const std::string& device_id) = 0;
virtual void GetSystemDevices(
const flutter::EncodableList& with_services,
@@ -332,25 +329,6 @@ class UniversalBlePlatformChannel {
UniversalBlePlatformChannel() = default;
};
class UniversalBleCallbackChannelCodecSerializer : public flutter::StandardCodecSerializer {
public:
UniversalBleCallbackChannelCodecSerializer();
inline static UniversalBleCallbackChannelCodecSerializer& GetInstance() {
static UniversalBleCallbackChannelCodecSerializer sInstance;
return sInstance;
}
void WriteValue(
const flutter::EncodableValue& value,
flutter::ByteStreamWriter* stream) const override;
protected:
flutter::EncodableValue ReadValueOfType(
uint8_t type,
flutter::ByteStreamReader* stream) const override;
};
// Native -> Flutter
//
// Generated class from Pigeon that represents Flutter messages that can be called from C++.
+53 -43
View File
@@ -416,36 +416,20 @@ namespace universal_ble
IsPairedAsync(device_id, result);
};
std::optional<FlutterError> UniversalBlePlugin::Pair(const std::string &device_id)
void UniversalBlePlugin::Pair(
const std::string &device_id,
std::function<void(ErrorOr<bool> reply)> result)
{
try
{
auto device = async_get(BluetoothLEDevice::FromBluetoothAddressAsync(_str_to_mac_address(device_id)));
std::cout << "PairLog: Device to be paired was found" << std::endl;
auto deviceInformation = device.DeviceInformation();
if (deviceInformation.Pairing().IsPaired())
{
return FlutterError("PairLog: Device is already paired");
}
if (!deviceInformation.Pairing().CanPair())
{
return FlutterError("PairLog: Device is not pairable");
}
if (isWindows11OrGreater())
{
PairAsync(device_id, deviceInformation);
}
PairAsync(device_id, result);
else
{
CustomPairAsync(device_id, deviceInformation);
}
return std::nullopt;
CustomPairAsync(device_id, result);
}
catch (const FlutterError &err)
{
return err;
result(err);
}
};
@@ -556,43 +540,69 @@ namespace universal_ble
}
}
winrt::fire_and_forget UniversalBlePlugin::PairAsync(std::string device_id, const DeviceInformation deviceInformation)
winrt::fire_and_forget UniversalBlePlugin::PairAsync(
std::string device_id,
std::function<void(ErrorOr<bool> reply)> result)
{
try
{
auto result = co_await deviceInformation.Pairing().PairAsync();
std::cout << "PairLog: Received pairing status" << std::endl;
auto isPaired = result.Status() == Enumeration::DevicePairingResultStatus::Paired;
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(_str_to_mac_address(device_id));
auto deviceInformation = device.DeviceInformation();
if (deviceInformation.Pairing().IsPaired())
result(true);
else if (!deviceInformation.Pairing().CanPair())
result(FlutterError("Device is not pairable"));
else
{
auto pairResult = co_await deviceInformation.Pairing().PairAsync();
std::cout << "PairLog: Received pairing status" << std::endl;
bool isPaired = pairResult.Status() == Enumeration::DevicePairingResultStatus::Paired;
result(isPaired);
std::string errorStr = parsePairingFailError(pairResult);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
}
}
catch (...)
{
result(false);
std::cout << "PairLog: Unknown error" << std::endl;
}
}
winrt::fire_and_forget UniversalBlePlugin::CustomPairAsync(std::string device_id, const DeviceInformation deviceInformation)
winrt::fire_and_forget UniversalBlePlugin::CustomPairAsync(
std::string device_id,
std::function<void(ErrorOr<bool> reply)> result)
{
try
{
auto customPairing = deviceInformation.Pairing().Custom();
winrt::event_token token = customPairing.PairingRequested({this, &UniversalBlePlugin::PairingRequestedHandler});
std::cout << "PairLog: Trying to pair" << std::endl;
DevicePairingProtectionLevel protectionLevel = deviceInformation.Pairing().ProtectionLevel();
// DevicePairingKinds => None, ConfirmOnly, DisplayPin, ProvidePin, ConfirmPinMatch, ProvidePasswordCredential
auto result = co_await customPairing.PairAsync(DevicePairingKinds::ConfirmOnly | DevicePairingKinds::ProvidePin, protectionLevel);
std::cout << "PairLog: Got Pair Result" << std::endl;
DevicePairingResultStatus status = result.Status();
customPairing.PairingRequested(token);
auto isPaired = status == Enumeration::DevicePairingResultStatus::Paired;
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(_str_to_mac_address(device_id));
auto deviceInformation = device.DeviceInformation();
if (deviceInformation.Pairing().IsPaired())
result(true);
else if (!deviceInformation.Pairing().CanPair())
result(FlutterError("Device is not pairable"));
else
{
auto customPairing = deviceInformation.Pairing().Custom();
winrt::event_token token = customPairing.PairingRequested({this, &UniversalBlePlugin::PairingRequestedHandler});
std::cout << "PairLog: Trying to pair" << std::endl;
DevicePairingProtectionLevel protectionLevel = deviceInformation.Pairing().ProtectionLevel();
// DevicePairingKinds => None, ConfirmOnly, DisplayPin, ProvidePin, ConfirmPinMatch, ProvidePasswordCredential
auto pairResult = co_await customPairing.PairAsync(DevicePairingKinds::ConfirmOnly | DevicePairingKinds::ProvidePin, protectionLevel);
std::cout << "PairLog: Got Pair Result" << std::endl;
DevicePairingResultStatus status = pairResult.Status();
customPairing.PairingRequested(token);
bool isPaired = status == Enumeration::DevicePairingResultStatus::Paired;
result(isPaired);
std::string errorStr = parsePairingFailError(pairResult);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
}
}
catch (...)
{
result(false);
std::cout << "PairLog Error: Pairing Failed" << std::endl;
}
}
+5 -3
View File
@@ -125,8 +125,8 @@ namespace universal_ble
const std::vector<uint8_t> &value,
std::function<void(std::optional<FlutterError> reply)> result);
bool filterByManufacturerData(IVector<BluetoothLEManufacturerData> deviceManufactureData);
winrt::fire_and_forget PairAsync(std::string device_id, const DeviceInformation deviceInformation);
winrt::fire_and_forget CustomPairAsync(std::string device_id, const DeviceInformation deviceInformation);
winrt::fire_and_forget PairAsync(std::string device_id, std::function<void(ErrorOr<bool> reply)> result);
winrt::fire_and_forget CustomPairAsync(std::string device_id, std::function<void(ErrorOr<bool> reply)> result);
void PairingRequestedHandler(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs eventArgs);
// UniversalBlePlatformChannel implementation.
@@ -165,7 +165,9 @@ namespace universal_ble
void IsPaired(
const std::string &device_id,
std::function<void(ErrorOr<bool> reply)> result) override;
std::optional<FlutterError> Pair(const std::string &device_id) override;
void Pair(
const std::string &device_id,
std::function<void(ErrorOr<bool> reply)> result) override;
std::optional<FlutterError> UnPair(const std::string &device_id) override;
void GetSystemDevices(
const flutter::EncodableList &with_services,