Add connecting and disconnecting states to BleConnectionState (#54)
* Add connecting and disconnecting state * Replace BleConnectionState with boolean in onConnectionChanged callback * Improve Docs and Changelog * Implement GetConnectionState in Windows * Update CHANGELOG.md Co-authored-by: Foti Dim <foti@navideck.com> * Add code level doc of connectionState getter --------- Co-authored-by: Foti Dim <foti@navideck.com>
This commit is contained in:
@@ -75,7 +75,7 @@ UniversalBle.stopScan();
|
||||
Before initiating a scan, ensure that Bluetooth is available:
|
||||
|
||||
```dart
|
||||
AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState()
|
||||
AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState();
|
||||
// Start scan only if Bluetooth is powered on
|
||||
if (state == AvailabilityState.poweredOn) {
|
||||
UniversalBle.startScan();
|
||||
@@ -91,18 +91,19 @@ UniversalBle.onAvailabilityChange = (state) {
|
||||
|
||||
See the [Bluetooth Availability](#bluetooth-availability) section for more.
|
||||
|
||||
#### Connected Devices
|
||||
#### System Devices
|
||||
|
||||
Already connected devices, either through previous sessions or connected through system settings, won't show up as scan results.
|
||||
You can list those devices using `getSystemDevices()`. You still need to explicitly connect before using them.
|
||||
Already connected devices, connected either through previous sessions, other apps or through system settings, won't show up as scan results. You can get those using `getSystemDevices()`.
|
||||
|
||||
```dart
|
||||
// Get connected devices
|
||||
// Get already connected devices
|
||||
// You can set `withServices` to narrow down the results
|
||||
// On `Apple`, `withServices` is required to get connected devices, else [1800] service will be used as default filter.
|
||||
List<BleDevice> devices = await UniversalBle.getSystemDevices(withServices: []);
|
||||
```
|
||||
For each such device the `isSystemDevice` property will be `true`.
|
||||
|
||||
For each connected device the `isConnected` property will be `true`.
|
||||
You still need to explicitly [connect](#connecting) to them before being able to use them.
|
||||
|
||||
#### Scan Filter
|
||||
|
||||
@@ -142,10 +143,14 @@ UniversalBle.connect(deviceId);
|
||||
// Disconnect from a device
|
||||
UniversalBle.disconnect(deviceId);
|
||||
|
||||
// Get connection state updates
|
||||
UniversalBle.onConnectionChange = (String deviceId, BleConnectionState state) {
|
||||
debugPrint('OnConnectionChange $deviceId, $state');
|
||||
// Get connection/disconnection updates
|
||||
UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
|
||||
debugPrint('OnConnectionChange $deviceId, $isConnected');
|
||||
}
|
||||
|
||||
// Get current connection state
|
||||
// Can be connected, disconnected, connecting or disconnecting
|
||||
BleConnectionState connectionState = await bleDevice.connectionState;
|
||||
```
|
||||
|
||||
### Discovering Services
|
||||
|
||||
@@ -258,7 +258,7 @@ interface UniversalBlePlatformChannel {
|
||||
fun pair(deviceId: String)
|
||||
fun unPair(deviceId: String)
|
||||
fun getSystemDevices(withServices: List<String>, callback: (Result<List<UniversalBleScanResult>>) -> Unit)
|
||||
fun isConnected(deviceId: String): Boolean
|
||||
fun getConnectionState(deviceId: String): Long
|
||||
|
||||
companion object {
|
||||
/** The codec used by UniversalBlePlatformChannel. */
|
||||
@@ -559,13 +559,13 @@ interface UniversalBlePlatformChannel {
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected$separatedMessageChannelSuffix", codec)
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val deviceIdArg = args[0] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf<Any?>(api.isConnected(deviceIdArg))
|
||||
listOf<Any?>(api.getConnectionState(deviceIdArg))
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
}
|
||||
@@ -680,12 +680,12 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onConnectionChanged(deviceIdArg: String, stateArg: Long, callback: (Result<Unit>) -> Unit)
|
||||
fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, stateArg)) {
|
||||
channel.send(listOf(deviceIdArg, connectedArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
|
||||
@@ -29,7 +29,9 @@ const val ccdCharacteristic = "00002902-0000-1000-8000-00805f9b34fb"
|
||||
|
||||
enum class BleConnectionState(val value: Long) {
|
||||
Connected(0),
|
||||
Disconnected(1)
|
||||
Disconnected(1),
|
||||
Connecting(2),
|
||||
Disconnecting(3)
|
||||
}
|
||||
|
||||
enum class AvailabilityState(val value: Long) {
|
||||
@@ -65,6 +67,16 @@ enum class CharacteristicProperty(val value: Long) {
|
||||
}
|
||||
|
||||
|
||||
fun Int.toBleConnectionState(): BleConnectionState {
|
||||
return when (this) {
|
||||
BluetoothGatt.STATE_CONNECTED -> BleConnectionState.Connected
|
||||
BluetoothGatt.STATE_CONNECTING -> BleConnectionState.Connecting
|
||||
BluetoothGatt.STATE_DISCONNECTING -> BleConnectionState.Disconnecting
|
||||
BluetoothGatt.STATE_DISCONNECTED -> BleConnectionState.Disconnected
|
||||
else -> BleConnectionState.Disconnected
|
||||
}
|
||||
}
|
||||
|
||||
fun String.validFullUUID(): String {
|
||||
return when (this.count()) {
|
||||
4 -> "0000$this-0000-1000-8000-00805F9B34FB"
|
||||
|
||||
@@ -137,10 +137,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
if (currentState == BluetoothGatt.STATE_CONNECTED) {
|
||||
Log.e(TAG, "$deviceId Already connected")
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onConnectionChanged(
|
||||
deviceId,
|
||||
BleConnectionState.Connected.value
|
||||
) {}
|
||||
callbackChannel?.onConnectionChanged(deviceId, true) {}
|
||||
}
|
||||
return
|
||||
} else if (currentState == BluetoothGatt.STATE_CONNECTING) {
|
||||
@@ -180,8 +177,11 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
cleanConnection(deviceId.toBluetoothGatt())
|
||||
}
|
||||
|
||||
override fun isConnected(deviceId: String): Boolean {
|
||||
return devicesStateMap[deviceId] == BluetoothGatt.STATE_CONNECTED
|
||||
override fun getConnectionState(deviceId: String): Long {
|
||||
return bluetoothManager.getConnectionState(
|
||||
bluetoothManager.adapter.getRemoteDevice(deviceId),
|
||||
BluetoothProfile.GATT
|
||||
).toBleConnectionState().value
|
||||
}
|
||||
|
||||
override fun discoverServices(
|
||||
@@ -749,22 +749,27 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
devicesStateMap[gatt.device.address] = newState
|
||||
if (newState == BluetoothGatt.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) {
|
||||
if (status != BluetoothGatt.GATT_SUCCESS) {
|
||||
Log.e(TAG, "Failed to update connected state: $status")
|
||||
return
|
||||
}
|
||||
|
||||
if (newState == BluetoothGatt.STATE_CONNECTED) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onConnectionChanged(
|
||||
gatt.device.address,
|
||||
BleConnectionState.Connected.value
|
||||
gatt.device.address, true
|
||||
) {}
|
||||
}
|
||||
} else {
|
||||
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
|
||||
cleanConnection(gatt)
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onConnectionChanged(
|
||||
gatt.device.address,
|
||||
BleConnectionState.Disconnected.value
|
||||
gatt.device.address, false
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onCharacteristicChanged(
|
||||
|
||||
@@ -259,7 +259,7 @@ protocol UniversalBlePlatformChannel {
|
||||
func pair(deviceId: String) throws
|
||||
func unPair(deviceId: String) throws
|
||||
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void)
|
||||
func isConnected(deviceId: String) throws -> Bool
|
||||
func getConnectionState(deviceId: String) throws -> Int64
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@@ -516,20 +516,20 @@ class UniversalBlePlatformChannelSetup {
|
||||
} else {
|
||||
getSystemDevicesChannel.setMessageHandler(nil)
|
||||
}
|
||||
let isConnectedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let getConnectionStateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isConnectedChannel.setMessageHandler { message, reply in
|
||||
getConnectionStateChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let deviceIdArg = args[0] as! String
|
||||
do {
|
||||
let result = try api.isConnected(deviceId: deviceIdArg)
|
||||
let result = try api.getConnectionState(deviceId: deviceIdArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isConnectedChannel.setMessageHandler(nil)
|
||||
getConnectionStateChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,7 +577,7 @@ protocol UniversalBleCallbackChannelProtocol {
|
||||
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, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
}
|
||||
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
@@ -661,10 +661,10 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
func onConnectionChanged(deviceId deviceIdArg: String, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([deviceIdArg, stateArg] as [Any?]) { response in
|
||||
channel.sendMessage([deviceIdArg, connectedArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
|
||||
@@ -27,6 +27,8 @@ enum BleOutputProperty: Int {
|
||||
enum BlueConnectionState: Int64 {
|
||||
case connected = 0
|
||||
case disconnected = 1
|
||||
case connecting = 2
|
||||
case disconnecting = 3
|
||||
}
|
||||
|
||||
enum AvailabilityState: Int64 {
|
||||
|
||||
@@ -95,11 +95,20 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
cleanUpConnection(deviceId: deviceId)
|
||||
}
|
||||
|
||||
func isConnected(deviceId: String) -> Bool {
|
||||
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||
return false
|
||||
func getConnectionState(deviceId: String) throws -> Int64 {
|
||||
let peripheral = try deviceId.getPeripheral()
|
||||
switch peripheral.state {
|
||||
case .connecting:
|
||||
return BlueConnectionState.connecting.rawValue
|
||||
case .connected:
|
||||
return BlueConnectionState.connected.rawValue
|
||||
case .disconnecting:
|
||||
return BlueConnectionState.disconnecting.rawValue
|
||||
case .disconnected:
|
||||
return BlueConnectionState.disconnected.rawValue
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
return peripheral.state == CBPeripheralState.connected
|
||||
}
|
||||
|
||||
func cleanUpConnection(deviceId: String) {
|
||||
@@ -307,15 +316,19 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, state: BlueConnectionState.connected.rawValue) { _ in }
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: true) { _ in }
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, state: BlueConnectionState.disconnected.rawValue) { _ in }
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false) { _ in }
|
||||
// Cleanup on disconnect
|
||||
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
print("Failed to connect: \(peripheral.uuid.uuidString): \(String(describing: error))")
|
||||
}
|
||||
|
||||
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) {
|
||||
let deviceId = peripheral.identifier.uuidString
|
||||
guard let services = peripheral.services else {
|
||||
|
||||
@@ -31,12 +31,12 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) async {
|
||||
onConnectionChange?.call(deviceId, BleConnectionState.connected);
|
||||
onConnectionChange?.call(deviceId, true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(String deviceId) async {
|
||||
onConnectionChange?.call(deviceId, BleConnectionState.disconnected);
|
||||
onConnectionChange?.call(deviceId, false);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -105,7 +105,7 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) {
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,16 +62,16 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
});
|
||||
}
|
||||
|
||||
void _handleConnectionChange(String deviceId, BleConnectionState state) {
|
||||
print('_handleConnectionChange $deviceId, ${state.name}');
|
||||
void _handleConnectionChange(String deviceId, bool isConnected) {
|
||||
print('_handleConnectionChange $deviceId, $isConnected');
|
||||
setState(() {
|
||||
if (deviceId == widget.deviceId) {
|
||||
isConnected = (state == BleConnectionState.connected);
|
||||
this.isConnected = isConnected;
|
||||
}
|
||||
});
|
||||
_addLog('Connection', state.name.toUpperCase());
|
||||
_addLog('Connection', isConnected ? "Connected" : "Disconnected");
|
||||
// Auto Discover Services
|
||||
if (isConnected) {
|
||||
if (this.isConnected) {
|
||||
_discoverServices();
|
||||
}
|
||||
}
|
||||
@@ -347,13 +347,13 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
PlatformButton(
|
||||
onPressed: () async {
|
||||
_addLog(
|
||||
'IsConnected',
|
||||
await UniversalBle.isConnected(
|
||||
'ConnectionState',
|
||||
await UniversalBle.getConnectionState(
|
||||
widget.deviceId,
|
||||
),
|
||||
);
|
||||
},
|
||||
text: 'IsConnected',
|
||||
text: 'Connection State',
|
||||
),
|
||||
if (Capabilities.supportsRequestMtuApi)
|
||||
PlatformButton(
|
||||
|
||||
@@ -410,7 +410,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.9.12"
|
||||
version: "0.10.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
enum BleConnectionState {
|
||||
connected,
|
||||
disconnected;
|
||||
disconnected,
|
||||
connecting,
|
||||
disconnecting;
|
||||
|
||||
const BleConnectionState();
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@ class BleDevice {
|
||||
Uint8List? manufacturerDataHead;
|
||||
Uint8List? manufacturerData;
|
||||
|
||||
Future<BleConnectionState> get connectionState async =>
|
||||
await UniversalBle.isConnected(deviceId)
|
||||
? BleConnectionState.connected
|
||||
: BleConnectionState.disconnected;
|
||||
/// Returns connection state of device,
|
||||
/// All platforms will return `Connected/Disconnected` states
|
||||
/// `Android` and `Apple` can also return `Connecting/Disconnecting` states
|
||||
Future<BleConnectionState> get connectionState =>
|
||||
UniversalBle.getConnectionState(deviceId);
|
||||
|
||||
BleDevice({
|
||||
required this.deviceId,
|
||||
|
||||
@@ -203,10 +203,12 @@ class UniversalBle {
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns true if device is connected to the app
|
||||
static Future<bool> isConnected(String deviceId) async {
|
||||
/// Returns connection state of device,
|
||||
/// All platforms will return `Connected/Disconnected` states
|
||||
/// `Android` and `Apple` can also return `Connecting/Disconnecting` states
|
||||
static Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||
return await _bleCommandQueue.queueCommand(
|
||||
() => _platform.isConnected(deviceId),
|
||||
() => _platform.getConnectionState(deviceId),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,19 +85,22 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||
BlueZDevice? device = _devices[deviceId] ??
|
||||
_client.devices.cast<BlueZDevice?>().firstWhere(
|
||||
(device) => device?.address == deviceId,
|
||||
orElse: () => null);
|
||||
return device?.connected ?? false;
|
||||
bool connected = device?.connected ?? false;
|
||||
return connected
|
||||
? BleConnectionState.connected
|
||||
: BleConnectionState.disconnected;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) async {
|
||||
final device = _findDeviceById(deviceId);
|
||||
if (device.connected) {
|
||||
onConnectionChange?.call(deviceId, BleConnectionState.connected);
|
||||
onConnectionChange?.call(deviceId, true);
|
||||
return;
|
||||
}
|
||||
await device.connect();
|
||||
@@ -107,7 +110,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
Future<void> disconnect(String deviceId) async {
|
||||
final device = _findDeviceById(deviceId);
|
||||
if (!device.connected) {
|
||||
onConnectionChange?.call(deviceId, BleConnectionState.disconnected);
|
||||
onConnectionChange?.call(deviceId, false);
|
||||
return;
|
||||
}
|
||||
await device.disconnect();
|
||||
@@ -429,12 +432,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
updateScanResult(device.toBleDevice());
|
||||
break;
|
||||
case BluezProperty.connected:
|
||||
onConnectionChange?.call(
|
||||
device.address,
|
||||
device.connected
|
||||
? BleConnectionState.connected
|
||||
: BleConnectionState.disconnected,
|
||||
);
|
||||
onConnectionChange?.call(device.address, device.connected);
|
||||
break;
|
||||
case BluezProperty.manufacturerData:
|
||||
updateScanResult(device.toBleDevice());
|
||||
|
||||
@@ -657,9 +657,9 @@ class UniversalBlePlatformChannel {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
Future<int> getConnectionState(String deviceId) async {
|
||||
final String __pigeon_channelName =
|
||||
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected$__pigeon_messageChannelSuffix';
|
||||
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$__pigeon_messageChannelSuffix';
|
||||
final BasicMessageChannel<Object?> __pigeon_channel =
|
||||
BasicMessageChannel<Object?>(
|
||||
__pigeon_channelName,
|
||||
@@ -682,7 +682,7 @@ class UniversalBlePlatformChannel {
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (__pigeon_replyList[0] as bool?)!;
|
||||
return (__pigeon_replyList[0] as int?)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,7 +724,7 @@ abstract class UniversalBleCallbackChannel {
|
||||
void onValueChanged(
|
||||
String deviceId, String characteristicId, Uint8List value);
|
||||
|
||||
void onConnectionChanged(String deviceId, int state);
|
||||
void onConnectionChanged(String deviceId, bool connected);
|
||||
|
||||
static void setUp(
|
||||
UniversalBleCallbackChannel? api, {
|
||||
@@ -873,11 +873,11 @@ abstract class UniversalBleCallbackChannel {
|
||||
final String? arg_deviceId = (args[0] as String?);
|
||||
assert(arg_deviceId != null,
|
||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null String.');
|
||||
final int? arg_state = (args[1] as int?);
|
||||
assert(arg_state != null,
|
||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null int.');
|
||||
final bool? arg_connected = (args[1] as bool?);
|
||||
assert(arg_connected != null,
|
||||
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null bool.');
|
||||
try {
|
||||
api.onConnectionChanged(arg_deviceId!, arg_state!);
|
||||
api.onConnectionChanged(arg_deviceId!, arg_connected!);
|
||||
return wrapResponse(empty: true);
|
||||
} on PlatformException catch (e) {
|
||||
return wrapResponse(error: e);
|
||||
|
||||
@@ -41,7 +41,10 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
Future<void> stopScan() => _channel.stopScan();
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) => _channel.isConnected(deviceId);
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||
int state = await _channel.getConnectionState(deviceId);
|
||||
return BleConnectionState.parse(state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) =>
|
||||
@@ -125,8 +128,8 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
scanResult: (BleDevice bleDevice) => updateScanResult(bleDevice),
|
||||
availabilityChange: (AvailabilityState state) =>
|
||||
onAvailabilityChange?.call(state),
|
||||
connectionChanged: (String deviceId, BleConnectionState state) =>
|
||||
onConnectionChange?.call(deviceId, state),
|
||||
connectionChanged: (String deviceId, bool connected) =>
|
||||
onConnectionChange?.call(deviceId, connected),
|
||||
valueChanged:
|
||||
(String deviceId, String characteristicId, Uint8List value) =>
|
||||
onValueChange?.call(deviceId, characteristicId, value),
|
||||
@@ -173,8 +176,8 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
availabilityChange(AvailabilityState.parse(state));
|
||||
|
||||
@override
|
||||
void onConnectionChanged(String deviceId, int state) =>
|
||||
connectionChanged(deviceId, BleConnectionState.parse(state));
|
||||
void onConnectionChanged(String deviceId, bool connected) =>
|
||||
connectionChanged(deviceId, connected);
|
||||
|
||||
@override
|
||||
void onScanResult(UniversalBleScanResult result) =>
|
||||
|
||||
@@ -44,7 +44,7 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
Future<void> unPair(String deviceId);
|
||||
|
||||
Future<bool> isConnected(String deviceId);
|
||||
Future<BleConnectionState> getConnectionState(String deviceId);
|
||||
|
||||
Future<List<BleDevice>> getSystemDevices(
|
||||
List<String>? withServices,
|
||||
@@ -74,8 +74,7 @@ abstract class UniversalBlePlatform {
|
||||
}
|
||||
|
||||
// Callback types
|
||||
typedef OnConnectionChange = void Function(
|
||||
String deviceId, BleConnectionState state);
|
||||
typedef OnConnectionChange = void Function(String deviceId, bool isConnected);
|
||||
|
||||
typedef OnValueChange = void Function(
|
||||
String deviceId, String characteristicId, Uint8List value);
|
||||
|
||||
@@ -20,10 +20,13 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
final Map<String, StreamSubscription> _characteristicStreamList = {};
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||
// TODO: Test this on Web (All platforms)
|
||||
BluetoothDevice? device = _getDeviceById(deviceId);
|
||||
return await device?.connected.first ?? false;
|
||||
bool connected = await device?.connected.first ?? false;
|
||||
return connected
|
||||
? BleConnectionState.connected
|
||||
: BleConnectionState.disconnected;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -42,17 +45,14 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
|
||||
_connectedDeviceStreamList[deviceId] = device.connected.listen((event) {
|
||||
if (!event) _cleanConnection(deviceId);
|
||||
onConnectionChange?.call(
|
||||
deviceId,
|
||||
event ? BleConnectionState.connected : BleConnectionState.disconnected,
|
||||
);
|
||||
onConnectionChange?.call(deviceId, event);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(String deviceId) async {
|
||||
_cleanConnection(deviceId);
|
||||
onConnectionChange?.call(deviceId, BleConnectionState.disconnected);
|
||||
onConnectionChange?.call(deviceId, false);
|
||||
_getDeviceById(deviceId)?.disconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ abstract class UniversalBlePlatformChannel {
|
||||
List<String> withServices,
|
||||
);
|
||||
|
||||
bool isConnected(String deviceId);
|
||||
int getConnectionState(String deviceId);
|
||||
}
|
||||
|
||||
/// Native -> Flutter
|
||||
@@ -97,7 +97,7 @@ abstract class UniversalBleCallbackChannel {
|
||||
|
||||
void onConnectionChanged(
|
||||
String deviceId,
|
||||
int state,
|
||||
bool connected,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -926,7 +926,7 @@ void UniversalBlePlatformChannel::SetUp(
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected" + prepended_suffix, &GetCodec());
|
||||
BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState" + prepended_suffix, &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
@@ -937,7 +937,7 @@ void UniversalBlePlatformChannel::SetUp(
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
ErrorOr<bool> output = api->IsConnected(device_id_arg);
|
||||
ErrorOr<int64_t> output = api->GetConnectionState(device_id_arg);
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
@@ -1123,14 +1123,14 @@ void UniversalBleCallbackChannel::OnValueChanged(
|
||||
|
||||
void UniversalBleCallbackChannel::OnConnectionChanged(
|
||||
const std::string& device_id_arg,
|
||||
int64_t state_arg,
|
||||
bool connected_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged" + message_channel_suffix_;
|
||||
BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
EncodableValue(device_id_arg),
|
||||
EncodableValue(state_arg),
|
||||
EncodableValue(connected_arg),
|
||||
});
|
||||
channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
|
||||
@@ -313,7 +313,7 @@ class UniversalBlePlatformChannel {
|
||||
virtual void GetSystemDevices(
|
||||
const flutter::EncodableList& with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) = 0;
|
||||
virtual ErrorOr<bool> IsConnected(const std::string& device_id) = 0;
|
||||
virtual ErrorOr<int64_t> GetConnectionState(const std::string& device_id) = 0;
|
||||
|
||||
// The codec used by UniversalBlePlatformChannel.
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
@@ -383,7 +383,7 @@ class UniversalBleCallbackChannel {
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnConnectionChanged(
|
||||
const std::string& device_id,
|
||||
int64_t state,
|
||||
bool connected,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
|
||||
|
||||
@@ -164,13 +164,18 @@ namespace universal_ble
|
||||
}
|
||||
};
|
||||
|
||||
ErrorOr<bool> UniversalBlePlugin::IsConnected(const std::string &device_id)
|
||||
ErrorOr<int64_t> UniversalBlePlugin::GetConnectionState(const std::string &device_id)
|
||||
{
|
||||
auto it = connectedDevices.find(_str_to_mac_address(device_id));
|
||||
if (it == connectedDevices.end())
|
||||
return false;
|
||||
return static_cast<int>(ConnectionState::disconnected);
|
||||
|
||||
auto deviceAgent = *it->second;
|
||||
return deviceAgent.device.ConnectionStatus() == BluetoothConnectionStatus::Connected;
|
||||
|
||||
if (deviceAgent.device.ConnectionStatus() == BluetoothConnectionStatus::Connected)
|
||||
return static_cast<int>(ConnectionState::connected);
|
||||
else
|
||||
return static_cast<int>(ConnectionState::disconnected);
|
||||
}
|
||||
|
||||
std::optional<FlutterError> UniversalBlePlugin::Connect(const std::string &device_id)
|
||||
@@ -185,7 +190,7 @@ namespace universal_ble
|
||||
CleanConnection(deviceAddress);
|
||||
// TODO: send disconnect event only after disconnect is complete
|
||||
uiThreadHandler_.Post([deviceAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(deviceAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(deviceAddress), false, SuccessCallback, ErrorCallback); });
|
||||
|
||||
return std::nullopt;
|
||||
};
|
||||
@@ -1007,7 +1012,7 @@ namespace universal_ble
|
||||
{
|
||||
std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl;
|
||||
uiThreadHandler_.Post([bluetoothAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -1017,7 +1022,7 @@ namespace universal_ble
|
||||
{
|
||||
std::cout << "ConnectionFailed: Failed to get services: " << GattCommunicationStatusToString(status) << std::endl;
|
||||
uiThreadHandler_.Post([bluetoothAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -1054,7 +1059,7 @@ namespace universal_ble
|
||||
connectedDevices.insert(std::move(pair));
|
||||
std::cout << "ConnectionLog: Connected" << std::endl;
|
||||
uiThreadHandler_.Post([bluetoothAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::connected), SuccessCallback, ErrorCallback); });
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), true, SuccessCallback, ErrorCallback); });
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args)
|
||||
@@ -1064,7 +1069,7 @@ namespace universal_ble
|
||||
CleanConnection(sender.BluetoothAddress());
|
||||
auto bluetoothAddress = sender.BluetoothAddress();
|
||||
uiThreadHandler_.Post([bluetoothAddress]
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
|
||||
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), false, SuccessCallback, ErrorCallback); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace universal_ble
|
||||
AvailabilityState getAvailabilityStateFromRadio(RadioState radioState);
|
||||
std::string parsePairingFailError(Enumeration::DevicePairingResult result);
|
||||
winrt::fire_and_forget GetSystemDevicesAsync(std::vector<std::string> with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
|
||||
winrt::fire_and_forget IsPairedAsync(std::string device_id, std::function<void(ErrorOr<bool> reply)> result);
|
||||
winrt::fire_and_forget WriteAsync(GattCharacteristic characteristic, GattWriteOption writeOption,
|
||||
const std::vector<uint8_t> &value,
|
||||
@@ -132,7 +132,7 @@ namespace universal_ble
|
||||
// UniversalBlePlatformChannel implementation.
|
||||
void GetBluetoothAvailabilityState(std::function<void(ErrorOr<int64_t> reply)> result) override;
|
||||
void EnableBluetooth(std::function<void(ErrorOr<bool> reply)> result) override;
|
||||
ErrorOr<bool> IsConnected(const std::string& device_id) override;
|
||||
ErrorOr<int64_t> GetConnectionState(const std::string &device_id) override;
|
||||
std::optional<FlutterError> StartScan(const UniversalScanFilter *filter) override;
|
||||
std::optional<FlutterError> StopScan() override;
|
||||
std::optional<FlutterError> Connect(const std::string &device_id) override;
|
||||
|
||||
Reference in New Issue
Block a user