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:
Rohit Sangwan
2024-06-20 23:55:59 +05:30
committed by Foti Dim
parent 2bb3d1dcf4
commit 8d0cfe98d9
23 changed files with 159 additions and 112 deletions
+14 -9
View File
@@ -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(
+8 -8
View File
@@ -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
+2
View File
@@ -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 {
+19 -6
View File
@@ -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 {
+3 -3
View File
@@ -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(
+1 -1
View File
@@ -410,7 +410,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.9.12"
version: "0.10.0"
vector_math:
dependency: transitive
description:
+3 -1
View File
@@ -1,6 +1,8 @@
enum BleConnectionState {
connected,
disconnected;
disconnected,
connecting,
disconnecting;
const BleConnectionState();
+5 -4
View File
@@ -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,
+5 -3
View File
@@ -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();
}
+2 -2
View File
@@ -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,
);
}
+4 -4
View File
@@ -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);
+2 -2
View File
@@ -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);
+13 -8
View File
@@ -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); });
}
}
+2 -2
View File
@@ -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;