Add connection properties in BleDevice (#50)
* Rename to BleDevice * Add isConnected property * Make isConnected true * Add isConnected api * Implement Windows * Merge add-isConnected-api * Rename getConnectedDevices to getSystemDevices * Add code level Doc for isConnected * Add isPaired * Revert isPaired * Add isSystemDevice property in BleDevice * Return enum instead of bool --------- Co-authored-by: Rohit Sangwan <rohitsangwan647@gmail.com>
This commit is contained in:
+6
-2
@@ -1,8 +1,12 @@
|
||||
## 0.9.12
|
||||
* Add .perDevice queue
|
||||
* Improve code level documentation
|
||||
* BREAKING CHANGE: Rename ScanResult to BleDevice
|
||||
* Add `connectionState` property to BleDevice
|
||||
* Add `isSystemDevice` property to BleDevice
|
||||
* Add `.perDevice` queue
|
||||
* Support "ProvidePin" pairing on Windows 10/11
|
||||
* Get RRSI updates on Apple platforms
|
||||
* Improve code level documentation
|
||||
* Improve enum parsing performance
|
||||
|
||||
## 0.9.11
|
||||
* Add device name prefix filtering
|
||||
|
||||
@@ -23,7 +23,7 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
|
||||
| :------------------- | :-----: | :-: | :---: | :-----: | :----------: | :-: |
|
||||
| startScan/stopScan | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| connect/disconnect | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| getConnectedDevices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
|
||||
| getSystemDevices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
|
||||
| discoverServices | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| readValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| writeValue | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
@@ -53,8 +53,8 @@ import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
```dart
|
||||
// Set a scan result handler
|
||||
UniversalBle.onScanResult = (scanResult) {
|
||||
// e.g. Use scan result to connect
|
||||
UniversalBle.onScanResult = (bleDevice) {
|
||||
// e.g. Use BleDevice ID to connect
|
||||
}
|
||||
|
||||
// Perform a scan
|
||||
@@ -73,6 +73,7 @@ UniversalBle.stopScan();
|
||||
```
|
||||
|
||||
Before initiating a scan, ensure that Bluetooth is available:
|
||||
|
||||
```dart
|
||||
AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState()
|
||||
// Start scan only if Bluetooth is powered on
|
||||
@@ -93,13 +94,16 @@ See the [Bluetooth Availability](#bluetooth-availability) section for more.
|
||||
#### Connected 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 `getConnectedDevices()`. You still need to explicitly connect before using them.
|
||||
You can list those devices using `getSystemDevices()`. You still need to explicitly connect before using them.
|
||||
|
||||
```dart
|
||||
// Get connected devices
|
||||
// You can set `withServices` to narrow down the results
|
||||
await UniversalBle.getConnectedDevices(withServices: []);
|
||||
List<BleDevice> devices = await UniversalBle.getSystemDevices(withServices: []);
|
||||
```
|
||||
|
||||
For each connected device the `isConnected` property will be `true`.
|
||||
|
||||
#### Scan Filter
|
||||
|
||||
You can optionally set filters when scanning.
|
||||
@@ -119,6 +123,7 @@ Use the `withManufacturerData` parameter to filter devices by manufacturer data.
|
||||
```dart
|
||||
List<ManufacturerDataFilter> withManufacturerData;
|
||||
```
|
||||
|
||||
##### With namePrefix
|
||||
|
||||
Use the `withNamePrefix` parameter to filter devices by names (case sensitive). When you pass a list of names, the scan results will only include devices that have this name or start with the provided parameter.
|
||||
@@ -130,8 +135,8 @@ List<String> withNamePrefix;
|
||||
### Connecting
|
||||
|
||||
```dart
|
||||
// Connect to a device using the `deviceId` of the scanResult received from `UniversalBle.onScanResult`
|
||||
String deviceId = scanResult.deviceId;
|
||||
// Connect to a device using the `deviceId` of the BleDevice received from `UniversalBle.onScanResult`
|
||||
String deviceId = bleDevice.deviceId;
|
||||
UniversalBle.connect(deviceId);
|
||||
|
||||
// Disconnect from a device
|
||||
@@ -215,7 +220,7 @@ By default, all commands are executed in a global queue (`QueueType.global`), wi
|
||||
If you want to parallelize commands between multiple devices, you can set:
|
||||
|
||||
```dart
|
||||
// Create a separate queue for each device.
|
||||
// Create a separate queue for each device.
|
||||
UniversalBle.queueType = QueueType.perDevice;
|
||||
```
|
||||
|
||||
|
||||
@@ -257,7 +257,8 @@ interface UniversalBlePlatformChannel {
|
||||
fun isPaired(deviceId: String, callback: (Result<Boolean>) -> Unit)
|
||||
fun pair(deviceId: String)
|
||||
fun unPair(deviceId: String)
|
||||
fun getConnectedDevices(withServices: List<String>, callback: (Result<List<UniversalBleScanResult>>) -> Unit)
|
||||
fun getSystemDevices(withServices: List<String>, callback: (Result<List<UniversalBleScanResult>>) -> Unit)
|
||||
fun isConnected(deviceId: String): Boolean
|
||||
|
||||
companion object {
|
||||
/** The codec used by UniversalBlePlatformChannel. */
|
||||
@@ -538,12 +539,12 @@ interface UniversalBlePlatformChannel {
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices$separatedMessageChannelSuffix", codec)
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val withServicesArg = args[0] as List<String>
|
||||
api.getConnectedDevices(withServicesArg) { result: Result<List<UniversalBleScanResult>> ->
|
||||
api.getSystemDevices(withServicesArg) { result: Result<List<UniversalBleScanResult>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
@@ -557,6 +558,23 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected$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))
|
||||
} catch (exception: Throwable) {
|
||||
wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.UUID
|
||||
private const val TAG = "UniversalBlePlugin"
|
||||
|
||||
val knownGatts = mutableListOf<BluetoothGatt>()
|
||||
val ccdCharacteristic = "00002902-0000-1000-8000-00805f9b34fb"
|
||||
const val ccdCharacteristic = "00002902-0000-1000-8000-00805f9b34fb"
|
||||
|
||||
enum class BleConnectionState(val value: Long) {
|
||||
Connected(0),
|
||||
|
||||
@@ -180,6 +180,10 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
cleanConnection(deviceId.toBluetoothGatt())
|
||||
}
|
||||
|
||||
override fun isConnected(deviceId: String): Boolean {
|
||||
return devicesStateMap[deviceId] == BluetoothGatt.STATE_CONNECTED
|
||||
}
|
||||
|
||||
override fun discoverServices(
|
||||
deviceId: String,
|
||||
callback: (Result<List<UniversalBleService>>) -> Unit,
|
||||
@@ -498,7 +502,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun getConnectedDevices(
|
||||
override fun getSystemDevices(
|
||||
withServices: List<String>,
|
||||
callback: (Result<List<UniversalBleScanResult>>) -> Unit,
|
||||
) {
|
||||
|
||||
@@ -258,7 +258,8 @@ protocol UniversalBlePlatformChannel {
|
||||
func isPaired(deviceId: String, completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func pair(deviceId: String) throws
|
||||
func unPair(deviceId: String) throws
|
||||
func getConnectedDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void)
|
||||
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void)
|
||||
func isConnected(deviceId: String) throws -> Bool
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@@ -498,12 +499,12 @@ class UniversalBlePlatformChannelSetup {
|
||||
} else {
|
||||
unPairChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getConnectedDevicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let getSystemDevicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getConnectedDevicesChannel.setMessageHandler { message, reply in
|
||||
getSystemDevicesChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let withServicesArg = args[0] as! [String]
|
||||
api.getConnectedDevices(withServices: withServicesArg) { result in
|
||||
api.getSystemDevices(withServices: withServicesArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@@ -513,7 +514,22 @@ class UniversalBlePlatformChannelSetup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getConnectedDevicesChannel.setMessageHandler(nil)
|
||||
getSystemDevicesChannel.setMessageHandler(nil)
|
||||
}
|
||||
let isConnectedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isConnectedChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let deviceIdArg = args[0] as! String
|
||||
do {
|
||||
let result = try api.isConnected(deviceId: deviceIdArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isConnectedChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,13 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
cleanUpConnection(deviceId: deviceId)
|
||||
}
|
||||
|
||||
func isConnected(deviceId: String) -> Bool {
|
||||
guard let peripheral = discoveredPeripherals[deviceId] else {
|
||||
return false
|
||||
}
|
||||
return peripheral.state == CBPeripheralState.connected
|
||||
}
|
||||
|
||||
func cleanUpConnection(deviceId: String) {
|
||||
characteristicReadFutures.removeAll { future in
|
||||
if future.deviceId == deviceId {
|
||||
@@ -254,7 +261,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
throw FlutterError(code: "NotSupported", message: nil, details: nil)
|
||||
}
|
||||
|
||||
func getConnectedDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
||||
func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) {
|
||||
var filterCBUUID = withServices.map { CBUUID(string: $0) }
|
||||
// We can't keep this filter empty, so adding a default filter
|
||||
if filterCBUUID.isEmpty { filterCBUUID.append(CBUUID(string: "1800")) }
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
/// Mock implementation of [UniversalBlePlatform] for testing
|
||||
class MockUniversalBle extends UniversalBlePlatform {
|
||||
final _mockBleScanResult = BleScanResult(
|
||||
final _mockBleDevice = BleDevice(
|
||||
name: 'MockDevice',
|
||||
deviceId: 'MockDeviceId',
|
||||
rssi: 50,
|
||||
@@ -23,11 +23,8 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
]);
|
||||
|
||||
@override
|
||||
Future<void> startScan({
|
||||
ScanFilter? scanFilter,
|
||||
}) async {
|
||||
onScanResult?.call(_mockBleScanResult);
|
||||
}
|
||||
Future<void> startScan({ScanFilter? scanFilter}) async =>
|
||||
onScanResult?.call(_mockBleDevice);
|
||||
|
||||
@override
|
||||
Future<void> stopScan() async {}
|
||||
@@ -59,8 +56,7 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleScanResult>> getConnectedDevices(
|
||||
List<String>? withServices) async {
|
||||
Future<List<BleDevice>> getSystemDevices(List<String>? withServices) async {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -107,4 +103,9 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
Future<void> unPair(String deviceId) async {
|
||||
onPairingStateChange?.call(deviceId, false, null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
+22
-21
@@ -20,7 +20,7 @@ class MyApp extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
final _scanResults = <BleScanResult>[];
|
||||
final _bleDevices = <BleDevice>[];
|
||||
bool _isScanning = false;
|
||||
QueueType _queueType = QueueType.global;
|
||||
|
||||
@@ -55,16 +55,16 @@ class _MyAppState extends State<MyApp> {
|
||||
};
|
||||
|
||||
UniversalBle.onScanResult = (result) {
|
||||
// debugPrint("ScanResult: ${result.name} ${result.services}");
|
||||
// debugPrint("BleDevice: ${result.name} ${result.services}");
|
||||
// debugPrint("${result.name} ${result.manufacturerData}");
|
||||
int index = _scanResults.indexWhere((e) => e.deviceId == result.deviceId);
|
||||
int index = _bleDevices.indexWhere((e) => e.deviceId == result.deviceId);
|
||||
if (index == -1) {
|
||||
_scanResults.add(result);
|
||||
_bleDevices.add(result);
|
||||
} else {
|
||||
if (result.name == null && _scanResults[index].name != null) {
|
||||
result.name = _scanResults[index].name;
|
||||
if (result.name == null && _bleDevices[index].name != null) {
|
||||
result.name = _bleDevices[index].name;
|
||||
}
|
||||
_scanResults[index] = result;
|
||||
_bleDevices[index] = result;
|
||||
}
|
||||
setState(() {});
|
||||
};
|
||||
@@ -119,7 +119,7 @@ class _MyAppState extends State<MyApp> {
|
||||
text: 'Start Scan',
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
_scanResults.clear();
|
||||
_bleDevices.clear();
|
||||
_isScanning = true;
|
||||
});
|
||||
try {
|
||||
@@ -171,7 +171,8 @@ class _MyAppState extends State<MyApp> {
|
||||
PlatformButton(
|
||||
text: 'Connected Devices',
|
||||
onPressed: () async {
|
||||
var devices = await UniversalBle.getConnectedDevices(
|
||||
List<BleDevice> devices =
|
||||
await UniversalBle.getSystemDevices(
|
||||
withServices: _services,
|
||||
);
|
||||
if (devices.isEmpty) {
|
||||
@@ -182,8 +183,8 @@ class _MyAppState extends State<MyApp> {
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_scanResults.clear();
|
||||
_scanResults.addAll(devices);
|
||||
_bleDevices.clear();
|
||||
_bleDevices.addAll(devices);
|
||||
});
|
||||
},
|
||||
),
|
||||
@@ -200,12 +201,12 @@ class _MyAppState extends State<MyApp> {
|
||||
});
|
||||
},
|
||||
),
|
||||
if (_scanResults.isNotEmpty)
|
||||
if (_bleDevices.isNotEmpty)
|
||||
PlatformButton(
|
||||
text: 'Clear List',
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_scanResults.clear();
|
||||
_bleDevices.clear();
|
||||
});
|
||||
},
|
||||
),
|
||||
@@ -225,25 +226,25 @@ class _MyAppState extends State<MyApp> {
|
||||
),
|
||||
const Divider(color: Colors.blue),
|
||||
Expanded(
|
||||
child: _isScanning && _scanResults.isEmpty
|
||||
child: _isScanning && _bleDevices.isEmpty
|
||||
? const Center(child: CircularProgressIndicator.adaptive())
|
||||
: !_isScanning && _scanResults.isEmpty
|
||||
: !_isScanning && _bleDevices.isEmpty
|
||||
? const ScannedDevicesPlaceholderWidget()
|
||||
: ListView.separated(
|
||||
itemCount: _scanResults.length,
|
||||
itemCount: _bleDevices.length,
|
||||
separatorBuilder: (context, index) => const Divider(),
|
||||
itemBuilder: (context, index) {
|
||||
BleScanResult scanResult =
|
||||
_scanResults[_scanResults.length - index - 1];
|
||||
BleDevice device =
|
||||
_bleDevices[_bleDevices.length - index - 1];
|
||||
return ScannedItemWidget(
|
||||
scanResult: scanResult,
|
||||
bleDevice: device,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PeripheralDetailPage(
|
||||
scanResult.deviceId,
|
||||
scanResult.name ?? "Unknown Peripheral",
|
||||
device.deviceId,
|
||||
device.name ?? "Unknown Peripheral",
|
||||
),
|
||||
));
|
||||
UniversalBle.stopScan();
|
||||
|
||||
@@ -4,14 +4,14 @@ import 'package:universal_ble/universal_ble.dart';
|
||||
import 'package:universal_ble_example/data/capabilities.dart';
|
||||
|
||||
class ScannedItemWidget extends StatelessWidget {
|
||||
final BleScanResult scanResult;
|
||||
final BleDevice bleDevice;
|
||||
final VoidCallback? onTap;
|
||||
const ScannedItemWidget({super.key, required this.scanResult, this.onTap});
|
||||
const ScannedItemWidget({super.key, required this.bleDevice, this.onTap});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String? name = scanResult.name;
|
||||
Uint8List? rawManufacturerData = scanResult.manufacturerData;
|
||||
String? name = bleDevice.name;
|
||||
Uint8List? rawManufacturerData = bleDevice.manufacturerData;
|
||||
ManufacturerData? manufacturerData;
|
||||
if (rawManufacturerData != null && rawManufacturerData.isNotEmpty) {
|
||||
manufacturerData = ManufacturerData.fromData(rawManufacturerData);
|
||||
@@ -22,12 +22,12 @@ class ScannedItemWidget extends StatelessWidget {
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
'$name (${scanResult.rssi})',
|
||||
'$name (${bleDevice.rssi})',
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(scanResult.deviceId),
|
||||
Text(bleDevice.deviceId),
|
||||
Visibility(
|
||||
visible: manufacturerData != null,
|
||||
child: Text(
|
||||
@@ -36,18 +36,15 @@ class ScannedItemWidget extends StatelessWidget {
|
||||
: 'ManufacturerCompanyId: ${manufacturerData?.companyIdRadix16}',
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: scanResult.isPaired != null,
|
||||
child: scanResult.isPaired == true
|
||||
? const Text(
|
||||
"Paired",
|
||||
style: TextStyle(color: Colors.green),
|
||||
)
|
||||
: const Text(
|
||||
"Not Paired",
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
bleDevice.isPaired == true
|
||||
? const Text(
|
||||
"Paired",
|
||||
style: TextStyle(color: Colors.green),
|
||||
)
|
||||
: const Text(
|
||||
"Not Paired",
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: const Icon(Icons.arrow_forward_ios),
|
||||
|
||||
@@ -344,6 +344,17 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
enabled: isConnected,
|
||||
text: 'Discover Services',
|
||||
),
|
||||
PlatformButton(
|
||||
onPressed: () async {
|
||||
_addLog(
|
||||
'IsConnected',
|
||||
await UniversalBle.isConnected(
|
||||
widget.deviceId,
|
||||
),
|
||||
);
|
||||
},
|
||||
text: 'IsConnected',
|
||||
),
|
||||
if (Capabilities.supportsRequestMtuApi)
|
||||
PlatformButton(
|
||||
enabled: isConnected,
|
||||
@@ -405,7 +416,7 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
if (Capabilities.supportsPairingApi)
|
||||
PlatformButton(
|
||||
onPressed: () async {
|
||||
bool isPaired = await UniversalBle.isPaired(
|
||||
bool? isPaired = await UniversalBle.isPaired(
|
||||
widget.deviceId);
|
||||
_addLog('IsPaired', isPaired);
|
||||
},
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
enum AvailabilityState {
|
||||
unknown(0),
|
||||
resetting(1),
|
||||
unsupported(2),
|
||||
unauthorized(3),
|
||||
poweredOff(4),
|
||||
poweredOn(5);
|
||||
unknown,
|
||||
resetting,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn;
|
||||
|
||||
final int value;
|
||||
const AvailabilityState(this.value);
|
||||
const AvailabilityState();
|
||||
|
||||
factory AvailabilityState.parse(int value) =>
|
||||
AvailabilityState.values.firstWhere((element) => element.value == value);
|
||||
factory AvailabilityState.parse(int index) => AvailabilityState.values[index];
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
enum BleConnectionState {
|
||||
connected(0),
|
||||
disconnected(1);
|
||||
connected,
|
||||
disconnected;
|
||||
|
||||
final int value;
|
||||
const BleConnectionState(this.value);
|
||||
const BleConnectionState();
|
||||
|
||||
factory BleConnectionState.parse(int value) =>
|
||||
BleConnectionState.values.firstWhere((element) => element.value == value);
|
||||
factory BleConnectionState.parse(int index) =>
|
||||
BleConnectionState.values[index];
|
||||
}
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
class BleScanResult {
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
class BleDevice {
|
||||
String deviceId;
|
||||
String? name;
|
||||
int? rssi;
|
||||
bool? isPaired;
|
||||
List<String> services;
|
||||
bool? isSystemDevice;
|
||||
Uint8List? manufacturerDataHead;
|
||||
Uint8List? manufacturerData;
|
||||
int? rssi;
|
||||
List<String> services;
|
||||
|
||||
BleScanResult({
|
||||
required this.name,
|
||||
Future<BleConnectionState> get connectionState async => await UniversalBle.isConnected(deviceId) ? BleConnectionState.connected : BleConnectionState.disconnected;
|
||||
|
||||
BleDevice({
|
||||
required this.deviceId,
|
||||
required this.name,
|
||||
this.rssi,
|
||||
this.isPaired,
|
||||
this.services = const [],
|
||||
this.isSystemDevice,
|
||||
Uint8List? manufacturerData,
|
||||
Uint8List? manufacturerDataHead,
|
||||
this.services = const [],
|
||||
}) {
|
||||
this.manufacturerDataHead = manufacturerDataHead ?? Uint8List.fromList([]);
|
||||
this.manufacturerData = manufacturerData ?? manufacturerDataHead;
|
||||
@@ -24,7 +30,7 @@ class BleScanResult {
|
||||
}
|
||||
|
||||
/// Represents the manufacturer data of a BLE device.
|
||||
/// Use [BleScanResult.manufacturerData] with [ManufacturerData.fromData] to create an instance of this class.
|
||||
/// Use [BleDevice.manufacturerData] with [ManufacturerData.fromData] to create an instance of this class.
|
||||
class ManufacturerData {
|
||||
final int? companyId;
|
||||
final Uint8List? data;
|
||||
@@ -1,22 +1,18 @@
|
||||
enum BleInputProperty {
|
||||
disabled(0),
|
||||
notification(1),
|
||||
indication(2);
|
||||
disabled,
|
||||
notification,
|
||||
indication;
|
||||
|
||||
final int value;
|
||||
const BleInputProperty(this.value);
|
||||
const BleInputProperty();
|
||||
|
||||
factory BleInputProperty.parse(int value) =>
|
||||
BleInputProperty.values.firstWhere((element) => element.value == value);
|
||||
factory BleInputProperty.parse(int index) => BleInputProperty.values[index];
|
||||
}
|
||||
|
||||
enum BleOutputProperty {
|
||||
withResponse(0),
|
||||
withoutResponse(1);
|
||||
withResponse,
|
||||
withoutResponse;
|
||||
|
||||
final int value;
|
||||
const BleOutputProperty(this.value);
|
||||
const BleOutputProperty();
|
||||
|
||||
factory BleOutputProperty.parse(int value) =>
|
||||
BleOutputProperty.values.firstWhere((element) => element.value == value);
|
||||
factory BleOutputProperty.parse(int index) => BleOutputProperty.values[index];
|
||||
}
|
||||
|
||||
@@ -11,19 +11,17 @@ class BleCharacteristic {
|
||||
}
|
||||
|
||||
enum CharacteristicProperty {
|
||||
broadcast(0),
|
||||
read(1),
|
||||
writeWithoutResponse(2),
|
||||
write(3),
|
||||
notify(4),
|
||||
indicate(5),
|
||||
authenticatedSignedWrites(6),
|
||||
extendedProperties(7);
|
||||
broadcast,
|
||||
read,
|
||||
writeWithoutResponse,
|
||||
write,
|
||||
notify,
|
||||
indicate,
|
||||
authenticatedSignedWrites,
|
||||
extendedProperties;
|
||||
|
||||
final int value;
|
||||
const CharacteristicProperty(this.value);
|
||||
const CharacteristicProperty();
|
||||
|
||||
factory CharacteristicProperty.parse(int value) =>
|
||||
CharacteristicProperty.values
|
||||
.firstWhere((element) => element.value == value);
|
||||
factory CharacteristicProperty.parse(int index) =>
|
||||
CharacteristicProperty.values[index];
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ export 'package:universal_ble/src/models/ble_property.dart';
|
||||
export 'package:universal_ble/src/models/ble_service.dart';
|
||||
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_scan_result.dart';
|
||||
export 'package:universal_ble/src/models/ble_device.dart';
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:universal_ble/src/ble_command_queue.dart';
|
||||
@@ -161,8 +162,9 @@ class UniversalBle {
|
||||
}
|
||||
|
||||
/// Check if a device is paired
|
||||
/// Pair commands are not supported on `Apple` and `Web`
|
||||
static Future<bool> isPaired(String deviceId) async {
|
||||
/// Returns null on `Apple` and `Web`
|
||||
static Future<bool?> isPaired(String deviceId) async {
|
||||
if (kIsWeb || Platform.isIOS || Platform.isMacOS) return null;
|
||||
return await _bleCommandQueue.executeCommand(
|
||||
() => _platform.isPaired(deviceId),
|
||||
deviceId: deviceId,
|
||||
@@ -192,11 +194,18 @@ class UniversalBle {
|
||||
/// On `Apple`, [withServices] is required to get connected devices, else [1800] service will be used as default filter
|
||||
/// On `Android`, `Linux` and `Windows`, if [withServices] is used, then internally all services will be discovered for each device first (either by connecting or by using cached services)
|
||||
/// Not supported on `Web`
|
||||
static Future<List<BleScanResult>> getConnectedDevices({
|
||||
static Future<List<BleDevice>> getSystemDevices({
|
||||
List<String>? withServices,
|
||||
}) async {
|
||||
return await _bleCommandQueue.executeCommand(
|
||||
() => _platform.getConnectedDevices(withServices),
|
||||
() => _platform.getSystemDevices(withServices),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns true if device is connected to the app
|
||||
static Future<bool> isConnected(String deviceId) async {
|
||||
return await _bleCommandQueue.executeCommand(
|
||||
() => _platform.isConnected(deviceId),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -224,8 +233,8 @@ class UniversalBle {
|
||||
_bleCommandQueue.onQueueUpdate = onQueueUpdate;
|
||||
|
||||
/// Get scan results
|
||||
static set onScanResult(OnScanResult? onScanResult) =>
|
||||
_platform.onScanResult = onScanResult;
|
||||
static set onScanResult(OnScanResult? bleDevice) =>
|
||||
_platform.onScanResult = bleDevice;
|
||||
|
||||
/// Get connection state changes
|
||||
static set onConnectionChanged(OnConnectionChanged? onConnectionChanged) =>
|
||||
|
||||
@@ -84,6 +84,15 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
BlueZDevice? device = _devices[deviceId] ??
|
||||
_client.devices.cast<BlueZDevice?>().firstWhere(
|
||||
(device) => device?.address == deviceId,
|
||||
orElse: () => null);
|
||||
return device?.connected ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) async {
|
||||
final device = _findDeviceById(deviceId);
|
||||
@@ -279,7 +288,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleScanResult>> getConnectedDevices(
|
||||
Future<List<BleDevice>> getSystemDevices(
|
||||
List<String>? withServices,
|
||||
) async {
|
||||
List<BlueZDevice> devices =
|
||||
@@ -297,7 +306,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
return devices.map((device) => device.toBleScanResult()).toList();
|
||||
return devices
|
||||
.map((device) => device.toBleDevice(isSystemDevice: true))
|
||||
.toList();
|
||||
}
|
||||
|
||||
AvailabilityState get _availabilityState {
|
||||
@@ -400,7 +411,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
// Update scan results only if rssi is available
|
||||
if (device.rssi != 0) updateScanResult(device.toBleScanResult());
|
||||
if (device.rssi != 0) updateScanResult(device.toBleDevice());
|
||||
|
||||
// Setup Cache
|
||||
_devices[device.address] = device;
|
||||
@@ -415,7 +426,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
for (final property in properties) {
|
||||
switch (property) {
|
||||
case BluezProperty.rssi:
|
||||
updateScanResult(device.toBleScanResult());
|
||||
updateScanResult(device.toBleDevice());
|
||||
break;
|
||||
case BluezProperty.connected:
|
||||
onConnectionChanged?.call(
|
||||
@@ -426,7 +437,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
|
||||
);
|
||||
break;
|
||||
case BluezProperty.manufacturerData:
|
||||
updateScanResult(device.toBleScanResult());
|
||||
updateScanResult(device.toBleDevice());
|
||||
break;
|
||||
case BluezProperty.paired:
|
||||
onPairingStateChange?.call(device.address, device.paired, null);
|
||||
@@ -591,14 +602,17 @@ extension BlueZDeviceExtension on BlueZDevice {
|
||||
}
|
||||
}
|
||||
|
||||
BleScanResult toBleScanResult() {
|
||||
return BleScanResult(
|
||||
BleDevice toBleDevice({
|
||||
bool? isSystemDevice,
|
||||
}) {
|
||||
return BleDevice(
|
||||
name: alias,
|
||||
deviceId: address,
|
||||
isPaired: paired,
|
||||
manufacturerData: manufacturerDataHead,
|
||||
manufacturerDataHead: manufacturerDataHead,
|
||||
rssi: rssi,
|
||||
isSystemDevice: isSystemDevice,
|
||||
services: uuids.map((e) => e.toString()).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -581,8 +581,8 @@ class UniversalBlePlatformChannel {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<UniversalBleScanResult?>> getConnectedDevices(List<String?> withServices) async {
|
||||
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices$__pigeon_messageChannelSuffix';
|
||||
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,
|
||||
@@ -607,6 +607,33 @@ class UniversalBlePlatformChannel {
|
||||
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected$__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]) as List<Object?>?;
|
||||
if (__pigeon_replyList == null) {
|
||||
throw _createConnectionError(__pigeon_channelName);
|
||||
} else if (__pigeon_replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: __pigeon_replyList[0]! as String,
|
||||
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 (__pigeon_replyList[0] as bool?)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _UniversalBleCallbackChannelCodec extends StandardMessageCodec {
|
||||
|
||||
@@ -40,6 +40,9 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
@override
|
||||
Future<void> stopScan() => _channel.stopScan();
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) => _channel.isConnected(deviceId);
|
||||
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) =>
|
||||
_channel.connect(deviceId);
|
||||
@@ -64,7 +67,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
bleInputProperty.value,
|
||||
bleInputProperty.index,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -86,7 +89,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
bleOutputProperty.value,
|
||||
bleOutputProperty.index,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,32 +107,32 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
Future<void> unPair(String deviceId) => _channel.unPair(deviceId);
|
||||
|
||||
@override
|
||||
Future<List<BleScanResult>> getConnectedDevices(
|
||||
Future<List<BleDevice>> getSystemDevices(
|
||||
List<String>? withServices,
|
||||
) async {
|
||||
var devices = await _channel.getConnectedDevices(withServices ?? []);
|
||||
return List<BleScanResult>.from(devices
|
||||
.map((e) => e?.toBleScanResult())
|
||||
.where((e) => e != null)
|
||||
.toList());
|
||||
var devices = await _channel.getSystemDevices(withServices ?? []);
|
||||
return List<BleDevice>.from(
|
||||
devices
|
||||
.map((e) => e?.toBleDevice(isSystemDevice: true))
|
||||
.where((e) => e != null)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// To set listeners
|
||||
void _setupListeners() {
|
||||
UniversalBleCallbackChannel.setUp(
|
||||
_UniversalBleCallbackHandler(
|
||||
scanResult: (BleScanResult scanResult) => updateScanResult(scanResult),
|
||||
availabilityChange: (AvailabilityState state) =>
|
||||
onAvailabilityChange?.call(state),
|
||||
connectionChanged: (String deviceId, BleConnectionState state) =>
|
||||
onConnectionChanged?.call(deviceId, state),
|
||||
valueChanged:
|
||||
(String deviceId, String characteristicId, Uint8List value) =>
|
||||
onValueChanged?.call(deviceId, characteristicId, value),
|
||||
pairStateChange: (String deviceId, bool isPaired, String? error) =>
|
||||
onPairingStateChange?.call(deviceId, isPaired, error),
|
||||
),
|
||||
);
|
||||
UniversalBleCallbackChannel.setUp(_UniversalBleCallbackHandler(
|
||||
scanResult: (BleDevice bleDevice) => updateScanResult(bleDevice),
|
||||
availabilityChange: (AvailabilityState state) =>
|
||||
onAvailabilityChange?.call(state),
|
||||
connectionChanged: (String deviceId, BleConnectionState state) =>
|
||||
onConnectionChanged?.call(deviceId, state),
|
||||
valueChanged:
|
||||
(String deviceId, String characteristicId, Uint8List value) =>
|
||||
onValueChanged?.call(deviceId, characteristicId, value),
|
||||
pairStateChange: (String deviceId, bool isPaired, String? error) =>
|
||||
onPairingStateChange?.call(deviceId, isPaired, error),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +178,7 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
|
||||
@override
|
||||
void onScanResult(UniversalBleScanResult result) =>
|
||||
scanResult(result.toBleScanResult());
|
||||
scanResult(result.toBleDevice());
|
||||
|
||||
@override
|
||||
void onValueChanged(
|
||||
@@ -188,16 +191,19 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
}
|
||||
|
||||
extension _UniversalBleScanResultExtension on UniversalBleScanResult {
|
||||
BleScanResult toBleScanResult() {
|
||||
BleDevice toBleDevice({
|
||||
bool? isSystemDevice,
|
||||
}) {
|
||||
var mnfDataHead = manufacturerDataHead ?? Uint8List.fromList([]);
|
||||
var mnfData = manufacturerData ?? mnfDataHead;
|
||||
return BleScanResult(
|
||||
return BleDevice(
|
||||
name: name,
|
||||
deviceId: deviceId,
|
||||
isPaired: isPaired,
|
||||
manufacturerData: mnfData,
|
||||
manufacturerDataHead: mnfDataHead,
|
||||
rssi: rssi,
|
||||
isPaired: isPaired,
|
||||
isSystemDevice: isSystemDevice,
|
||||
services: services
|
||||
?.where((e) => e != null)
|
||||
.map((e) => UUID(e!).toString())
|
||||
|
||||
@@ -44,19 +44,21 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
Future<void> unPair(String deviceId);
|
||||
|
||||
Future<List<BleScanResult>> getConnectedDevices(
|
||||
Future<bool> isConnected(String deviceId);
|
||||
|
||||
Future<List<BleDevice>> getSystemDevices(
|
||||
List<String>? withServices,
|
||||
);
|
||||
|
||||
void updateScanResult(BleScanResult scanResult) {
|
||||
void updateScanResult(BleDevice bleDevice) {
|
||||
// Filter by name
|
||||
ScanFilter? scanFilter = _scanFilter;
|
||||
if (scanFilter != null && scanFilter.withNamePrefix.isNotEmpty) {
|
||||
if (scanResult.name == null ||
|
||||
if (bleDevice.name == null ||
|
||||
!scanFilter.withNamePrefix
|
||||
.any((e) => scanResult.name?.startsWith(e) == true)) return;
|
||||
.any((e) => bleDevice.name?.startsWith(e) == true)) return;
|
||||
}
|
||||
onScanResult?.call(scanResult);
|
||||
onScanResult?.call(bleDevice);
|
||||
}
|
||||
|
||||
OnAvailabilityChange? onAvailabilityChange;
|
||||
@@ -78,7 +80,7 @@ typedef OnConnectionChanged = void Function(
|
||||
typedef OnValueChanged = void Function(
|
||||
String deviceId, String characteristicId, Uint8List value);
|
||||
|
||||
typedef OnScanResult = void Function(BleScanResult scanResult);
|
||||
typedef OnScanResult = void Function(BleDevice scanResult);
|
||||
|
||||
typedef OnAvailabilityChange = void Function(AvailabilityState state);
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
final Map<String, StreamSubscription> _connectedDeviceStreamList = {};
|
||||
final Map<String, StreamSubscription> _characteristicStreamList = {};
|
||||
|
||||
@override
|
||||
Future<bool> isConnected(String deviceId) async {
|
||||
// TODO: Test this on Web (All platforms)
|
||||
BluetoothDevice? device = _getDeviceById(deviceId);
|
||||
return await device?.connected.first ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(
|
||||
String deviceId, {
|
||||
@@ -289,7 +296,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleScanResult>> getConnectedDevices(
|
||||
Future<List<BleDevice>> getSystemDevices(
|
||||
List<String>? withServices,
|
||||
) {
|
||||
throw UnimplementedError();
|
||||
@@ -351,12 +358,12 @@ class UniversalBleWeb extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
extension _BluetoothDeviceExtension on BluetoothDevice {
|
||||
BleScanResult toBleScanResult({
|
||||
BleDevice toBleScanResult({
|
||||
int? rssi,
|
||||
UnmodifiableMapView<int, ByteData>? manufacturerDataMap,
|
||||
List<String> services = const [],
|
||||
}) {
|
||||
return BleScanResult(
|
||||
return BleDevice(
|
||||
name: name,
|
||||
deviceId: id,
|
||||
manufacturerData: manufacturerDataMap?.toUint8List(),
|
||||
|
||||
@@ -73,9 +73,11 @@ abstract class UniversalBlePlatformChannel {
|
||||
void unPair(String deviceId);
|
||||
|
||||
@async
|
||||
List<UniversalBleScanResult> getConnectedDevices(
|
||||
List<UniversalBleScanResult> getSystemDevices(
|
||||
List<String> withServices,
|
||||
);
|
||||
|
||||
bool isConnected(String deviceId);
|
||||
}
|
||||
|
||||
/// Native -> Flutter
|
||||
|
||||
@@ -897,7 +897,7 @@ void UniversalBlePlatformChannel::SetUp(
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices" + prepended_suffix, &GetCodec());
|
||||
BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices" + prepended_suffix, &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
@@ -908,7 +908,7 @@ void UniversalBlePlatformChannel::SetUp(
|
||||
return;
|
||||
}
|
||||
const auto& with_services_arg = std::get<EncodableList>(encodable_with_services_arg);
|
||||
api->GetConnectedDevices(with_services_arg, [reply](ErrorOr<EncodableList>&& output) {
|
||||
api->GetSystemDevices(with_services_arg, [reply](ErrorOr<EncodableList>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
@@ -925,6 +925,34 @@ void UniversalBlePlatformChannel::SetUp(
|
||||
channel.SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isConnected" + prepended_suffix, &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
ErrorOr<bool> output = api->IsConnected(device_id_arg);
|
||||
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()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel.SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EncodableValue UniversalBlePlatformChannel::WrapError(std::string_view error_message) {
|
||||
|
||||
@@ -310,9 +310,10 @@ class UniversalBlePlatformChannel {
|
||||
std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
virtual std::optional<FlutterError> Pair(const std::string& device_id) = 0;
|
||||
virtual std::optional<FlutterError> UnPair(const std::string& device_id) = 0;
|
||||
virtual void GetConnectedDevices(
|
||||
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;
|
||||
|
||||
// The codec used by UniversalBlePlatformChannel.
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
|
||||
@@ -164,6 +164,15 @@ namespace universal_ble
|
||||
}
|
||||
};
|
||||
|
||||
ErrorOr<bool> UniversalBlePlugin::IsConnected(const std::string &device_id)
|
||||
{
|
||||
auto it = connectedDevices.find(_str_to_mac_address(device_id));
|
||||
if (it == connectedDevices.end())
|
||||
return false;
|
||||
auto deviceAgent = *it->second;
|
||||
return deviceAgent.device.ConnectionStatus() == BluetoothConnectionStatus::Connected;
|
||||
}
|
||||
|
||||
std::optional<FlutterError> UniversalBlePlugin::Connect(const std::string &device_id)
|
||||
{
|
||||
ConnectAsync(_str_to_mac_address(device_id));
|
||||
@@ -463,7 +472,7 @@ namespace universal_ble
|
||||
}
|
||||
};
|
||||
|
||||
void UniversalBlePlugin::GetConnectedDevices(
|
||||
void UniversalBlePlugin::GetSystemDevices(
|
||||
const flutter::EncodableList &with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result)
|
||||
{
|
||||
@@ -473,7 +482,7 @@ namespace universal_ble
|
||||
auto serviceId = std::get<std::string>(item);
|
||||
with_services_str.push_back(serviceId);
|
||||
}
|
||||
GetConnectedDevicesAsync(with_services_str, result);
|
||||
GetSystemDevicesAsync(with_services_str, result);
|
||||
}
|
||||
|
||||
/// Helper Methods
|
||||
@@ -1088,7 +1097,7 @@ namespace universal_ble
|
||||
}
|
||||
}
|
||||
|
||||
winrt::fire_and_forget UniversalBlePlugin::GetConnectedDevicesAsync(
|
||||
winrt::fire_and_forget UniversalBlePlugin::GetSystemDevicesAsync(
|
||||
std::vector<std::string> with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result)
|
||||
{
|
||||
@@ -1143,7 +1152,7 @@ namespace universal_ble
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown error GetConnectedDevicesAsync" << std::endl;
|
||||
std::cout << "Unknown error GetSystemDevicesAsyncAsync" << std::endl;
|
||||
result(FlutterError("Unknown error"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace universal_ble
|
||||
void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
|
||||
AvailabilityState getAvailabilityStateFromRadio(RadioState radioState);
|
||||
std::string parsePairingFailError(Enumeration::DevicePairingResult result);
|
||||
winrt::fire_and_forget GetConnectedDevicesAsync(std::vector<std::string> with_services,
|
||||
winrt::fire_and_forget GetSystemDevicesAsync(std::vector<std::string> with_services,
|
||||
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,
|
||||
@@ -132,6 +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;
|
||||
std::optional<FlutterError> StartScan(const UniversalScanFilter *filter) override;
|
||||
std::optional<FlutterError> StopScan() override;
|
||||
std::optional<FlutterError> Connect(const std::string &device_id) override;
|
||||
@@ -166,7 +167,7 @@ namespace universal_ble
|
||||
std::function<void(ErrorOr<bool> reply)> result) override;
|
||||
std::optional<FlutterError> Pair(const std::string &device_id) override;
|
||||
std::optional<FlutterError> UnPair(const std::string &device_id) override;
|
||||
void GetConnectedDevices(
|
||||
void GetSystemDevices(
|
||||
const flutter::EncodableList &with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user