This commit is contained in:
Foti Dim
2026-02-28 20:45:12 +02:00
parent 4367381a56
commit 13ffda3ad7
19 changed files with 691 additions and 665 deletions
@@ -21,26 +21,12 @@ extension BleCharacteristicExtension on BleCharacteristic {
CharacteristicSubscription(this, CharacteristicProperty.indicate);
/// Unsubscribes notifications/indications from this characteristic.
Future<void> unsubscribe({
Duration? timeout,
}) =>
UniversalBle.unsubscribe(
_deviceId,
_serviceId,
uuid,
timeout: timeout,
);
Future<void> unsubscribe({Duration? timeout}) =>
UniversalBle.unsubscribe(_deviceId, _serviceId, uuid, timeout: timeout);
/// Reads the current value of the characteristic.
Future<Uint8List> read({
Duration? timeout,
}) =>
UniversalBle.read(
_deviceId,
_serviceId,
uuid,
timeout: timeout,
);
Future<Uint8List> read({Duration? timeout}) =>
UniversalBle.read(_deviceId, _serviceId, uuid, timeout: timeout);
/// Writes a value to the characteristic.
///
@@ -98,10 +84,8 @@ class CharacteristicSubscription {
/// (notifications or indications).
final bool isSupported;
CharacteristicSubscription(
this._characteristic,
this._property,
) : isSupported = _characteristic.properties.contains(_property);
CharacteristicSubscription(this._characteristic, this._property)
: isSupported = _characteristic.properties.contains(_property);
/// Registers a listener for incoming data from the characteristic.
StreamSubscription listen(
@@ -119,9 +103,7 @@ class CharacteristicSubscription {
}
/// Subscribes to this characteristic.
Future<void> subscribe({
Duration? timeout,
}) {
Future<void> subscribe({Duration? timeout}) {
if (!isSupported) throw Exception('Operation not supported');
if (_property == CharacteristicProperty.indicate) {
@@ -142,9 +124,7 @@ class CharacteristicSubscription {
}
/// Unsubscribes from this characteristic.
Future<void> unsubscribe({
Duration? timeout,
}) {
Future<void> unsubscribe({Duration? timeout}) {
if (!isSupported) throw Exception('Operation not supported');
return UniversalBle.unsubscribe(
_characteristic._deviceId,
+8 -13
View File
@@ -18,8 +18,11 @@ extension BleDeviceExtension on BleDevice {
/// Connects to the device.
/// [autoConnect] enables automatic reconnection when the device becomes available.
Future<void> connect({bool autoConnect = false, Duration? timeout}) =>
UniversalBle.connect(deviceId,
autoConnect: autoConnect, timeout: timeout);
UniversalBle.connect(
deviceId,
autoConnect: autoConnect,
timeout: timeout,
);
/// Disconnects from the device.
Future<void> disconnect() => UniversalBle.disconnect(deviceId);
@@ -40,10 +43,7 @@ extension BleDeviceExtension on BleDevice {
/// Returns true/false if it manages to execute the command.
/// Returns null when no `pairingCommand` is passed.
/// Note that it will trigger pairing if the device is not already paired.
Future<bool?> isPaired({
BleCommand? pairingCommand,
Duration? timeout,
}) {
Future<bool?> isPaired({BleCommand? pairingCommand, Duration? timeout}) {
return UniversalBle.isPaired(
deviceId,
pairingCommand: pairingCommand,
@@ -62,10 +62,7 @@ extension BleDeviceExtension on BleDevice {
///
/// On `Web/Windows` and `Web/Linux`, it does not work for devices that use `ConfirmOnly` pairing.
/// Can throw `PairingException`, `ConnectionException` or `PlatformException`.
Future<void> pair({
BleCommand? pairingCommand,
Duration? timeout,
}) {
Future<void> pair({BleCommand? pairingCommand, Duration? timeout}) {
return UniversalBle.pair(
deviceId,
pairingCommand: pairingCommand,
@@ -76,9 +73,7 @@ extension BleDeviceExtension on BleDevice {
/// Unpair a device.
///
/// It might throw an error if device is not paired.
Future<void> unpair({
Duration? timeout,
}) =>
Future<void> unpair({Duration? timeout}) =>
UniversalBle.unpair(deviceId, timeout: timeout);
/// Discovers the services offered by the device.
+3 -2
View File
@@ -22,10 +22,11 @@ class BleCapabilities {
/// but it very unreliable, therefore we return false.
static final triggersConfirmOnlyPairing =
defaultTargetPlatform != TargetPlatform.windows &&
defaultTargetPlatform != TargetPlatform.linux;
defaultTargetPlatform != TargetPlatform.linux;
/// Returns true if pair()/unpair() are supported on the platform.
static bool hasSystemPairingApi = !kIsWeb &&
static bool hasSystemPairingApi =
!kIsWeb &&
(defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.windows ||
defaultTargetPlatform == TargetPlatform.linux);
+3 -3
View File
@@ -55,9 +55,9 @@ class BleDevice {
this.manufacturerDataList = const [],
Map<String, Uint8List> serviceData = const {},
this.timestamp,
}) : serviceData = _validateServiceData(serviceData),
rawName = name,
name = name?.replaceAll(RegExp(r'[^ -~]'), '').trim();
}) : serviceData = _validateServiceData(serviceData),
rawName = name,
name = name?.replaceAll(RegExp(r'[^ -~]'), '').trim();
DateTime? get timestampDateTime => timestamp != null
? DateTime.fromMillisecondsSinceEpoch(timestamp!)
+1 -8
View File
@@ -1,8 +1 @@
enum BleLogLevel {
none,
error,
warning,
info,
debug,
verbose;
}
enum BleLogLevel { none, error, warning, info, debug, verbose }
+2 -9
View File
@@ -1,10 +1,3 @@
enum BleInputProperty {
disabled,
notification,
indication;
}
enum BleInputProperty { disabled, notification, indication }
enum BleOutputProperty {
withResponse,
withoutResponse;
}
enum BleOutputProperty { withResponse, withoutResponse }
+9 -14
View File
@@ -4,10 +4,8 @@ class BleService {
String uuid;
List<BleCharacteristic> characteristics;
BleService(
String uuid,
this.characteristics,
) : uuid = BleUuidParser.string(uuid);
BleService(String uuid, this.characteristics)
: uuid = BleUuidParser.string(uuid);
@override
String toString() {
@@ -21,11 +19,8 @@ class BleCharacteristic {
List<BleDescriptor> descriptors;
({String deviceId, String serviceId})? metaData;
BleCharacteristic(
String uuid,
this.properties,
this.descriptors,
) : uuid = BleUuidParser.string(uuid);
BleCharacteristic(String uuid, this.properties, this.descriptors)
: uuid = BleUuidParser.string(uuid);
BleCharacteristic.withMetaData({
required String deviceId,
@@ -33,11 +28,11 @@ class BleCharacteristic {
required String uuid,
required this.properties,
required this.descriptors,
}) : uuid = BleUuidParser.string(uuid),
metaData = (
deviceId: deviceId,
serviceId: BleUuidParser.string(serviceId),
);
}) : uuid = BleUuidParser.string(uuid),
metaData = (
deviceId: deviceId,
serviceId: BleUuidParser.string(serviceId),
);
@override
String toString() {
+2 -1
View File
@@ -20,7 +20,8 @@ class BleUuidParser {
if (!uuid.contains("-")) {
if (uuid.length != 32) throw const FormatException("Invalid UUID");
uuid = "${uuid.substring(0, 8)}-${uuid.substring(8, 12)}"
uuid =
"${uuid.substring(0, 8)}-${uuid.substring(8, 12)}"
"-${uuid.substring(12, 16)}-${uuid.substring(16, 20)}-${uuid.substring(20, 32)}";
}
+2 -7
View File
@@ -15,18 +15,13 @@ class ManufacturerData {
if (data.length < 2) {
throw const FormatException("Invalid Manufacturer Data");
}
return ManufacturerData(
(data[0] + (data[1] << 8)),
data.sublist(2),
);
return ManufacturerData((data[0] + (data[1] << 8)), data.sublist(2));
}
Uint8List toUint8List() {
final byteData = ByteData(2);
byteData.setInt16(0, companyId, Endian.host);
return Uint8List.fromList(
byteData.buffer.asUint8List() + payload.toList(),
);
return Uint8List.fromList(byteData.buffer.asUint8List() + payload.toList());
}
@override
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
/// Platform specific config to scan devices
///
///
/// If more than 1 platform supports a certain parameter then it should be in the high level APIs instead of platform specific options.
class PlatformConfig {
WebOptions? web;
+1 -5
View File
@@ -1,5 +1 @@
enum QueueType {
none,
perDevice,
global,
}
enum QueueType { none, perDevice, global }
+70 -73
View File
@@ -56,8 +56,9 @@ class UniversalBle {
/// Characteristic value stream
static Stream<Uint8List> characteristicValueStream(
String deviceId, String characteristicId) =>
_platform.characteristicValueStream(deviceId, characteristicId);
String deviceId,
String characteristicId,
) => _platform.characteristicValueStream(deviceId, characteristicId);
/// Pairing state stream
static Stream<bool> pairingStateStream(String deviceId) =>
@@ -125,9 +126,7 @@ class UniversalBle {
/// Check if currently scanning for devices.
/// Returns `true` if scanning is active, `false` otherwise.
static Future<bool> isScanning() async {
return await _bleCommandQueue.queueCommand(
() => _platform.isScanning(),
);
return await _bleCommandQueue.queueCommand(() => _platform.isScanning());
}
/// Connect to a device.
@@ -148,17 +147,17 @@ class UniversalBle {
bool autoConnect = false,
}) async {
timeout ??= const Duration(seconds: 60);
Completer<bool> completer =
_connectionEventCompleter(deviceId, timeout: timeout);
Completer<bool> completer = _connectionEventCompleter(
deviceId,
timeout: timeout,
);
_platform
.connect(deviceId, connectionTimeout: timeout, autoConnect: autoConnect)
.catchError(
(error) {
if (completer.isCompleted) return;
completer.completeError(ConnectionException(error));
},
);
.catchError((error) {
if (completer.isCompleted) return;
completer.completeError(ConnectionException(error));
});
if (!await completer.future.timeout(timeout)) {
throw ConnectionException("Failed to connect");
@@ -167,10 +166,7 @@ class UniversalBle {
/// Disconnect from a device.
/// Get notified of connection state changes in [onConnectionChange] listener.
static Future<void> disconnect(
String deviceId, {
Duration? timeout,
}) async {
static Future<void> disconnect(String deviceId, {Duration? timeout}) async {
timeout ??= const Duration(seconds: 60);
BleConnectionState? connectionState;
try {
@@ -180,18 +176,21 @@ class UniversalBle {
}
try {
Completer<bool> completer =
_connectionEventCompleter(deviceId, timeout: timeout);
Completer<bool> completer = _connectionEventCompleter(
deviceId,
timeout: timeout,
);
await _bleCommandQueue
.queueCommand(() => _platform.disconnect(deviceId),
timeout: timeout, deviceId: deviceId)
.catchError(
(error) {
if (completer.isCompleted) return;
completer.completeError(ConnectionException(error));
},
);
.queueCommand(
() => _platform.disconnect(deviceId),
timeout: timeout,
deviceId: deviceId,
)
.catchError((error) {
if (completer.isCompleted) return;
completer.completeError(ConnectionException(error));
});
if (connectionState == BleConnectionState.disconnected ||
connectionState == BleConnectionState.disconnecting) {
@@ -363,10 +362,7 @@ class UniversalBle {
/// Throws [UniversalBleException] if:
/// - The device is not connected
/// - Reading RSSI fails
static Future<int> readRssi(
String deviceId, {
Duration? timeout,
}) async {
static Future<int> readRssi(String deviceId, {Duration? timeout}) async {
return await _bleCommandQueue.queueCommand(
() => _platform.readRssi(deviceId),
timeout: timeout,
@@ -451,10 +447,7 @@ class UniversalBle {
/// Unpair a device.
/// It might throw an error if device is not paired.
static Future<void> unpair(
String deviceId, {
Duration? timeout,
}) async {
static Future<void> unpair(String deviceId, {Duration? timeout}) async {
return await _bleCommandQueue.queueCommand(
() => _platform.unpair(deviceId),
deviceId: deviceId,
@@ -493,9 +486,7 @@ class UniversalBle {
/// Enable Bluetooth.
/// It might throw errors if Bluetooth is not available.
/// Not supported on `Web` and `Apple`.
static Future<bool> enableBluetooth({
Duration? timeout,
}) async {
static Future<bool> enableBluetooth({Duration? timeout}) async {
return await _bleCommandQueue.queueCommand(
() => _platform.enableBluetooth(),
timeout: timeout,
@@ -505,9 +496,7 @@ class UniversalBle {
/// Disable Bluetooth.
/// It might throw errors if Bluetooth is not available.
/// Not supported on `Web` and `Apple`.
static Future<bool> disableBluetooth({
Duration? timeout,
}) async {
static Future<bool> disableBluetooth({Duration? timeout}) async {
return await _bleCommandQueue.queueCommand(
() => _platform.disableBluetooth(),
timeout: timeout,
@@ -534,14 +523,17 @@ class UniversalBle {
static set onAvailabilityChange(OnAvailabilityChange? onAvailabilityChange) {
_platform.onAvailabilityChange = onAvailabilityChange;
if (onAvailabilityChange != null) {
getBluetoothAvailabilityState().then((value) {
onAvailabilityChange(value);
}).onError((error, stackTrace) => null);
getBluetoothAvailabilityState()
.then((value) {
onAvailabilityChange(value);
})
.onError((error, stackTrace) => null);
}
}
@Deprecated(
"Use [subscribeNotifications] or [subscribeIndications] or [unsubscribe] instead")
"Use [subscribeNotifications] or [subscribeIndications] or [unsubscribe] instead",
)
static Future<void> setNotifiable(
String deviceId,
String service,
@@ -603,28 +595,32 @@ class UniversalBle {
}
connectionSubscription = _platform
.bleConnectionUpdateStreamController.stream
.bleConnectionUpdateStreamController
.stream
.where((e) => e.deviceId == deviceId)
.listen(
(e) {
cancelSubscription();
if (e.error != null) {
handleError(e.error);
} else {
if (!completer.isCompleted) {
completer.complete(e.isConnected);
}
}
},
onError: handleError,
cancelOnError: true,
);
(e) {
cancelSubscription();
if (e.error != null) {
handleError(e.error);
} else {
if (!completer.isCompleted) {
completer.complete(e.isConnected);
}
}
},
onError: handleError,
cancelOnError: true,
);
completer.future.timeout(timeout).then((_) {
cancelSubscription();
}).catchError((_) {
cancelSubscription();
});
completer.future
.timeout(timeout)
.then((_) {
cancelSubscription();
})
.catchError((_) {
cancelSubscription();
});
return completer;
}
@@ -658,10 +654,7 @@ class UniversalBle {
// Try to connect first
if (connectionState != BleConnectionState.connected) {
UniversalLogger.logInfo("Connecting to $deviceId");
await connect(
deviceId,
timeout: timeout,
);
await connect(deviceId, timeout: timeout);
}
List<BleService> services = await discoverServices(
@@ -721,7 +714,9 @@ class UniversalBle {
if (BleUuidParser.compareStrings(service.uuid, bleCommand.service)) {
for (BleCharacteristic char in service.characteristics) {
if (BleUuidParser.compareStrings(
char.uuid, bleCommand.characteristic)) {
char.uuid,
bleCommand.characteristic,
)) {
characteristic = char;
break;
}
@@ -737,11 +732,13 @@ class UniversalBle {
bool? withoutResponse;
if (characteristic.properties.contains(CharacteristicProperty.write)) {
withoutResponse = false;
} else if (characteristic.properties
.contains(CharacteristicProperty.writeWithoutResponse)) {
} else if (characteristic.properties.contains(
CharacteristicProperty.writeWithoutResponse,
)) {
withoutResponse = true;
} else if (!characteristic.properties
.contains(CharacteristicProperty.read)) {
} else if (!characteristic.properties.contains(
CharacteristicProperty.read,
)) {
throw PairingException(
"BleCommand does not support read or write operation",
);
+10 -10
View File
@@ -42,11 +42,11 @@ class ConnectionException extends UniversalBleException {
});
ConnectionException([dynamic error])
: this._(
code: UniversalBleErrorParser.getCode(error),
message: _errorParser(error),
details: error,
);
: this._(
code: UniversalBleErrorParser.getCode(error),
message: _errorParser(error),
details: error,
);
}
/// Exception thrown when pairing-related errors occur
@@ -59,11 +59,11 @@ class PairingException extends UniversalBleException {
/// Legacy constructor for backward compatibility
PairingException([dynamic error])
: this._(
code: UniversalBleErrorParser.getCode(error),
message: _errorParser(error),
details: error,
);
: this._(
code: UniversalBleErrorParser.getCode(error),
message: _errorParser(error),
details: error,
);
}
/// Exception thrown when Web Bluetooth API is globally disabled
@@ -171,22 +171,25 @@ class UniversalBleLinux extends UniversalBlePlatform {
) async {
final device = _findDeviceById(deviceId);
if (device.gattServices.isEmpty && !device.servicesResolved) {
await device.propertiesChanged.firstWhere((element) {
if (element.contains(BluezProperty.connected)) {
if (!device.connected) {
UniversalLogger.logInfo(
"DiscoverServicesFailed: Device disconnected",
);
return true;
}
}
return element.contains(BluezProperty.servicesResolved);
}).timeout(const Duration(seconds: 10), onTimeout: () {
UniversalLogger.logInfo(
"DiscoverServicesFailed: Timeout",
);
return [];
});
await device.propertiesChanged
.firstWhere((element) {
if (element.contains(BluezProperty.connected)) {
if (!device.connected) {
UniversalLogger.logInfo(
"DiscoverServicesFailed: Device disconnected",
);
return true;
}
}
return element.contains(BluezProperty.servicesResolved);
})
.timeout(
const Duration(seconds: 10),
onTimeout: () {
UniversalLogger.logInfo("DiscoverServicesFailed: Timeout");
return [];
},
);
}
// Few ble devices requires delay to perform operations after discovering services
@@ -204,10 +207,12 @@ class UniversalBleLinux extends UniversalBlePlatform {
String serviceId = service.uuid.toString();
final characteristics = service.characteristics.map((e) {
final properties = List<CharacteristicProperty>.from(e.flags
.map((e) => e.toCharacteristicProperty())
.where((element) => element != null)
.toList());
final properties = List<CharacteristicProperty>.from(
e.flags
.map((e) => e.toCharacteristicProperty())
.where((element) => element != null)
.toList(),
);
return BleCharacteristic.withMetaData(
deviceId: deviceId,
serviceId: serviceId,
@@ -215,27 +220,30 @@ class UniversalBleLinux extends UniversalBlePlatform {
properties: properties,
descriptors: withDescriptors
? e.descriptors
.map((e) => BleDescriptor(e.uuid.toString()))
.toList()
.map((e) => BleDescriptor(e.uuid.toString()))
.toList()
: [],
);
}).toList();
services.add(
BleService(serviceId, characteristics),
);
services.add(BleService(serviceId, characteristics));
}
return services;
}
BlueZGattCharacteristic _getCharacteristic(
String deviceId, String service, String characteristic) {
String deviceId,
String service,
String characteristic,
) {
final device = _findDeviceById(deviceId);
final s = device.gattServices
.cast<BlueZGattService?>()
.firstWhere((s) => s?.uuid.toString() == service, orElse: () => null);
final s = device.gattServices.cast<BlueZGattService?>().firstWhere(
(s) => s?.uuid.toString() == service,
orElse: () => null,
);
final c = s?.characteristics.cast<BlueZGattCharacteristic?>().firstWhere(
(c) => c?.uuid.toString() == characteristic,
orElse: () => null);
(c) => c?.uuid.toString() == characteristic,
orElse: () => null,
);
if (c == null) {
throw UniversalBleException(
@@ -247,8 +255,12 @@ class UniversalBleLinux extends UniversalBlePlatform {
}
@override
Future<void> setNotifiable(String deviceId, String service,
String characteristic, BleInputProperty bleInputProperty) async {
Future<void> setNotifiable(
String deviceId,
String service,
String characteristic,
BleInputProperty bleInputProperty,
) async {
UniversalLogger.logDebug(
"SET_NOTIFY -> $deviceId $service $characteristic input=${bleInputProperty.name}",
withTimestamp: true,
@@ -269,29 +281,30 @@ class UniversalBleLinux extends UniversalBlePlatform {
_characteristicPropertiesSubscriptions[characteristicKey]?.cancel();
}
_characteristicPropertiesSubscriptions[characteristicKey] =
char.propertiesChanged.listen((List<String> properties) {
for (String property in properties) {
switch (property) {
case BluezProperty.value:
UniversalLogger.logVerbose(
"NOTIFY <- $deviceId $service $characteristic len=${char.value.length} data=${char.value}",
withTimestamp: true,
);
updateCharacteristicValue(
deviceId,
characteristic,
Uint8List.fromList(char.value),
DateTime.now().millisecondsSinceEpoch,
);
break;
default:
UniversalLogger.logInfo(
"UnhandledCharValuePropertyChange: $property",
);
}
}
});
_characteristicPropertiesSubscriptions[characteristicKey] = char
.propertiesChanged
.listen((List<String> properties) {
for (String property in properties) {
switch (property) {
case BluezProperty.value:
UniversalLogger.logVerbose(
"NOTIFY <- $deviceId $service $characteristic len=${char.value.length} data=${char.value}",
withTimestamp: true,
);
updateCharacteristicValue(
deviceId,
characteristic,
Uint8List.fromList(char.value),
DateTime.now().millisecondsSinceEpoch,
);
break;
default:
UniversalLogger.logInfo(
"UnhandledCharValuePropertyChange: $property",
);
}
}
});
} else {
if (char.notifying) await char.stopNotify();
_characteristicPropertiesSubscriptions
@@ -328,11 +341,12 @@ class UniversalBleLinux extends UniversalBlePlatform {
@override
Future<void> writeValue(
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty) async {
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty,
) async {
UniversalLogger.logDebug(
"WRITE -> $deviceId $service $characteristic len=${value.length} property=${bleOutputProperty.name}",
withTimestamp: true,
@@ -419,12 +433,11 @@ class UniversalBleLinux extends UniversalBlePlatform {
}
@override
Future<List<BleDevice>> getSystemDevices(
List<String>? withServices,
) async {
Future<List<BleDevice>> getSystemDevices(List<String>? withServices) async {
await _ensureInitialized();
List<BlueZDevice> devices =
_client.devices.where((device) => device.connected).toList();
List<BlueZDevice> devices = _client.devices
.where((device) => device.connected)
.toList();
if (withServices != null && withServices.isNotEmpty) {
devices = devices.where((device) {
if (device.servicesResolved) {
@@ -467,8 +480,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
BlueZDevice? _getDeviceById(String deviceId) {
return _devices[deviceId] ??
_client.devices.cast<BlueZDevice?>().firstWhere(
(device) => device?.address == deviceId,
orElse: () => null);
(device) => device?.address == deviceId,
orElse: () => null,
);
}
Future<void> _ensureInitialized() async {
@@ -503,9 +517,7 @@ class UniversalBleLinux extends UniversalBlePlatform {
break;
case BluezProperty.propertyClass:
default:
UniversalLogger.logInfo(
"UnhandledPropertyChanged: $property",
);
UniversalLogger.logInfo("UnhandledPropertyChanged: $property");
}
}
});
@@ -554,21 +566,23 @@ class UniversalBleLinux extends UniversalBlePlatform {
_devices[device.address] = device;
// Setup advertisements Listener
_deviceAdvertisementSubscriptions[device.address] ??=
device.propertiesChanged.where((e) {
return e.contains(BluezProperty.rssi) ||
e.contains(BluezProperty.manufacturerData) ||
e.contains(BluezProperty.uuids) ||
e.contains(BluezProperty.serviceData);
}).listen((_) {
if (_bleFilter.shouldAcceptDevice(bleDevice)) {
updateScanResult(device.toBleDevice());
}
});
_deviceAdvertisementSubscriptions[device.address] ??= device
.propertiesChanged
.where((e) {
return e.contains(BluezProperty.rssi) ||
e.contains(BluezProperty.manufacturerData) ||
e.contains(BluezProperty.uuids) ||
e.contains(BluezProperty.serviceData);
})
.listen((_) {
if (_bleFilter.shouldAcceptDevice(bleDevice)) {
updateScanResult(device.toBleDevice());
}
});
// Setup update listener
_deviceUpdateStreamSubscriptions[device.address] ??=
device.propertiesChanged.listen((properties) {
_deviceUpdateStreamSubscriptions[device
.address] ??= device.propertiesChanged.listen((properties) {
for (final property in properties) {
switch (property) {
// Connection/Pair updates
@@ -685,10 +699,7 @@ extension on BlueZFailedException {
Match? match = regExp.firstMatch(message);
String? code = match?.group(0);
if (code == null) return null;
int? decimalValue = int.tryParse(
code.replaceFirst('0x', ''),
radix: 16,
);
int? decimalValue = int.tryParse(code.replaceFirst('0x', ''), radix: 16);
return decimalValue?.toString() ?? code;
} catch (e) {
return null;
@@ -698,8 +709,10 @@ extension on BlueZFailedException {
extension BlueZDeviceExtension on BlueZDevice {
List<ManufacturerData> get manufacturerDataList => manufacturerData.entries
.map((MapEntry<BlueZManufacturerId, List<int>> data) =>
ManufacturerData(data.key.id, Uint8List.fromList(data.value)))
.map(
(MapEntry<BlueZManufacturerId, List<int>> data) =>
ManufacturerData(data.key.id, Uint8List.fromList(data.value)),
)
.toList();
Map<String, Uint8List> get serviceDataMap {
+219 -179
View File
@@ -15,8 +15,11 @@ PlatformException _createConnectionError(String channelName) {
);
}
List<Object?> wrapResponse(
{Object? result, PlatformException? error, bool empty = false}) {
List<Object?> wrapResponse({
Object? result,
PlatformException? error,
bool empty = false,
}) {
if (empty) {
return <Object?>[];
}
@@ -29,34 +32,25 @@ List<Object?> wrapResponse(
bool _deepEquals(Object? a, Object? b) {
if (a is List && b is List) {
return a.length == b.length &&
a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
a.indexed.every(
((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]),
);
}
if (a is Map && b is Map) {
return a.length == b.length &&
a.entries.every((MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
a.entries.every(
(MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]),
);
}
return a == b;
}
enum UniversalBleLogLevel {
none,
error,
warning,
info,
debug,
verbose,
}
enum UniversalBleLogLevel { none, error, warning, info, debug, verbose }
/// Scan config
enum AndroidScanMode {
balanced,
lowLatency,
lowPower,
opportunistic,
}
enum AndroidScanMode { balanced, lowLatency, lowPower, opportunistic }
/// Unified error codes for all platforms
enum UniversalBleErrorCode {
@@ -175,10 +169,10 @@ class UniversalBleScanResult {
name: result[1] as String?,
isPaired: result[2] as bool?,
rssi: result[3] as int?,
manufacturerDataList:
(result[4] as List<Object?>?)?.cast<UniversalManufacturerData>(),
serviceData:
(result[5] as Map<Object?, Object?>?)?.cast<String, Uint8List>(),
manufacturerDataList: (result[4] as List<Object?>?)
?.cast<UniversalManufacturerData>(),
serviceData: (result[5] as Map<Object?, Object?>?)
?.cast<String, Uint8List>(),
services: (result[6] as List<Object?>?)?.cast<String>(),
timestamp: result[7] as int?,
);
@@ -202,20 +196,14 @@ class UniversalBleScanResult {
}
class UniversalBleService {
UniversalBleService({
required this.uuid,
this.characteristics,
});
UniversalBleService({required this.uuid, this.characteristics});
String uuid;
List<UniversalBleCharacteristic>? characteristics;
List<Object?> _toList() {
return <Object?>[
uuid,
characteristics,
];
return <Object?>[uuid, characteristics];
}
Object encode() {
@@ -226,8 +214,8 @@ class UniversalBleService {
result as List<Object?>;
return UniversalBleService(
uuid: result[0]! as String,
characteristics:
(result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic>(),
characteristics: (result[1] as List<Object?>?)
?.cast<UniversalBleCharacteristic>(),
);
}
@@ -262,11 +250,7 @@ class UniversalBleCharacteristic {
List<UniversalBleDescriptor> descriptors;
List<Object?> _toList() {
return <Object?>[
uuid,
properties,
descriptors,
];
return <Object?>[uuid, properties, descriptors];
}
Object encode() {
@@ -278,8 +262,8 @@ class UniversalBleCharacteristic {
return UniversalBleCharacteristic(
uuid: result[0]! as String,
properties: (result[1] as List<Object?>?)!.cast<int>(),
descriptors:
(result[2] as List<Object?>?)!.cast<UniversalBleDescriptor>(),
descriptors: (result[2] as List<Object?>?)!
.cast<UniversalBleDescriptor>(),
);
}
@@ -302,16 +286,12 @@ class UniversalBleCharacteristic {
}
class UniversalBleDescriptor {
UniversalBleDescriptor({
required this.uuid,
});
UniversalBleDescriptor({required this.uuid});
String uuid;
List<Object?> _toList() {
return <Object?>[
uuid,
];
return <Object?>[uuid];
}
Object encode() {
@@ -320,9 +300,7 @@ class UniversalBleDescriptor {
static UniversalBleDescriptor decode(Object result) {
result as List<Object?>;
return UniversalBleDescriptor(
uuid: result[0]! as String,
);
return UniversalBleDescriptor(uuid: result[0]! as String);
}
@override
@@ -362,11 +340,7 @@ class AndroidOptions {
int? reportDelayMillis;
List<Object?> _toList() {
return <Object?>[
requestLocationPermission,
scanMode,
reportDelayMillis,
];
return <Object?>[requestLocationPermission, scanMode, reportDelayMillis];
}
Object encode() {
@@ -400,16 +374,12 @@ class AndroidOptions {
}
class UniversalScanConfig {
UniversalScanConfig({
this.android,
});
UniversalScanConfig({this.android});
AndroidOptions? android;
List<Object?> _toList() {
return <Object?>[
android,
];
return <Object?>[android];
}
Object encode() {
@@ -418,9 +388,7 @@ class UniversalScanConfig {
static UniversalScanConfig decode(Object result) {
result as List<Object?>;
return UniversalScanConfig(
android: result[0] as AndroidOptions?,
);
return UniversalScanConfig(android: result[0] as AndroidOptions?);
}
@override
@@ -455,11 +423,7 @@ class UniversalScanFilter {
List<UniversalManufacturerDataFilter> withManufacturerData;
List<Object?> _toList() {
return <Object?>[
withServices,
withNamePrefix,
withManufacturerData,
];
return <Object?>[withServices, withNamePrefix, withManufacturerData];
}
Object encode() {
@@ -507,11 +471,7 @@ class UniversalManufacturerDataFilter {
Uint8List? mask;
List<Object?> _toList() {
return <Object?>[
companyIdentifier,
data,
mask,
];
return <Object?>[companyIdentifier, data, mask];
}
Object encode() {
@@ -556,10 +516,7 @@ class UniversalManufacturerData {
Uint8List data;
List<Object?> _toList() {
return <Object?>[
companyIdentifier,
data,
];
return <Object?>[companyIdentifier, data];
}
Object encode() {
@@ -681,11 +638,13 @@ class UniversalBlePlatformChannel {
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UniversalBlePlatformChannel(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: pigeonVar_binaryMessenger = binaryMessenger,
pigeonVar_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
UniversalBlePlatformChannel({
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) : pigeonVar_binaryMessenger = binaryMessenger,
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty
? '.$messageChannelSuffix'
: '';
final BinaryMessenger? pigeonVar_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
@@ -728,8 +687,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[withAndroidFineLocation]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[withAndroidFineLocation],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -757,8 +717,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[withAndroidFineLocation]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[withAndroidFineLocation],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -830,7 +791,9 @@ class UniversalBlePlatformChannel {
}
Future<void> startScan(
UniversalScanFilter? filter, UniversalScanConfig? config) async {
UniversalScanFilter? filter,
UniversalScanConfig? config,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -838,8 +801,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[filter, config]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[filter, config],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -913,8 +877,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId, autoConnect]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, autoConnect],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -937,8 +902,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -953,8 +919,12 @@ class UniversalBlePlatformChannel {
}
}
Future<void> setNotifiable(String deviceId, String service,
String characteristic, int bleInputProperty) async {
Future<void> setNotifiable(
String deviceId,
String service,
String characteristic,
int bleInputProperty,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -962,8 +932,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel
.send(<Object?>[deviceId, service, characteristic, bleInputProperty]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, service, characteristic, bleInputProperty],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -979,7 +950,9 @@ class UniversalBlePlatformChannel {
}
Future<List<UniversalBleService>> discoverServices(
String deviceId, bool withDescriptors) async {
String deviceId,
bool withDescriptors,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -987,8 +960,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId, withDescriptors]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, withDescriptors],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1010,7 +984,10 @@ class UniversalBlePlatformChannel {
}
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
String deviceId,
String service,
String characteristic,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -1018,8 +995,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId, service, characteristic]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, service, characteristic],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1047,8 +1025,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId, expectedMtu]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, expectedMtu],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1068,8 +1047,13 @@ class UniversalBlePlatformChannel {
}
}
Future<void> writeValue(String deviceId, String service,
String characteristic, Uint8List value, int bleOutputProperty) async {
Future<void> writeValue(
String deviceId,
String service,
String characteristic,
Uint8List value,
int bleOutputProperty,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -1078,7 +1062,8 @@ class UniversalBlePlatformChannel {
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId, service, characteristic, value, bleOutputProperty]);
<Object?>[deviceId, service, characteristic, value, bleOutputProperty],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1101,8 +1086,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1130,8 +1116,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1159,8 +1146,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1176,7 +1164,8 @@ class UniversalBlePlatformChannel {
}
Future<List<UniversalBleScanResult>> getSystemDevices(
List<String> withServices) async {
List<String> withServices,
) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -1184,8 +1173,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[withServices]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[withServices],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1214,8 +1204,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1243,8 +1234,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[deviceId]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[deviceId],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1272,8 +1264,9 @@ class UniversalBlePlatformChannel {
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[logLevel]);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[logLevel],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -1299,8 +1292,12 @@ abstract class UniversalBleCallbackChannel {
void onScanResult(UniversalBleScanResult result);
void onValueChanged(String deviceId, String characteristicId, Uint8List value,
int? timestamp);
void onValueChanged(
String deviceId,
String characteristicId,
Uint8List value,
int? timestamp,
);
void onConnectionChanged(String deviceId, bool connected, String? error);
@@ -1309,23 +1306,29 @@ abstract class UniversalBleCallbackChannel {
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
messageChannelSuffix = messageChannelSuffix.isNotEmpty
? '.$messageChannelSuffix'
: '';
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
assert(
message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_state = (args[0] as int?);
assert(arg_state != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null, expected non-null int.');
assert(
arg_state != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null, expected non-null int.',
);
try {
api.onAvailabilityChanged(arg_state!);
return wrapResponse(empty: true);
@@ -1333,29 +1336,37 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
assert(
message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null String.');
assert(
arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null String.',
);
final bool? arg_isPaired = (args[1] as bool?);
assert(arg_isPaired != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null bool.');
assert(
arg_isPaired != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null bool.',
);
final String? arg_error = (args[2] as String?);
try {
api.onPairStateChange(arg_deviceId!, arg_isPaired!, arg_error);
@@ -1364,27 +1375,33 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
assert(
message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final UniversalBleScanResult? arg_result =
(args[0] as UniversalBleScanResult?);
assert(arg_result != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
assert(
arg_result != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.',
);
try {
api.onScanResult(arg_result!);
return wrapResponse(empty: true);
@@ -1392,64 +1409,86 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
assert(
message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.');
assert(
arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.',
);
final String? arg_characteristicId = (args[1] as String?);
assert(arg_characteristicId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.');
assert(
arg_characteristicId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.',
);
final Uint8List? arg_value = (args[2] as Uint8List?);
assert(arg_value != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
assert(
arg_value != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.',
);
final int? arg_timestamp = (args[3] as int?);
try {
api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!,
arg_timestamp);
api.onValueChanged(
arg_deviceId!,
arg_characteristicId!,
arg_value!,
arg_timestamp,
);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
assert(
message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null String.');
assert(
arg_deviceId != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null String.',
);
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.');
assert(
arg_connected != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null bool.',
);
final String? arg_error = (args[2] as String?);
try {
api.onConnectionChanged(arg_deviceId!, arg_connected!, arg_error);
@@ -1458,7 +1497,8 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
@@ -65,15 +65,19 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
@override
Future<BleConnectionState> getConnectionState(String deviceId) async {
int state = await _executeWithErrorHandling(
() => _channel.getConnectionState(deviceId));
() => _channel.getConnectionState(deviceId),
);
return BleConnectionState.parse(state);
}
@override
Future<void> connect(String deviceId,
{Duration? connectionTimeout, bool autoConnect = false}) =>
_executeWithErrorHandling(
() => _channel.connect(deviceId, autoConnect: autoConnect));
Future<void> connect(
String deviceId, {
Duration? connectionTimeout,
bool autoConnect = false,
}) => _executeWithErrorHandling(
() => _channel.connect(deviceId, autoConnect: autoConnect),
);
@override
Future<void> disconnect(String deviceId) =>
@@ -86,22 +90,31 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
) async {
List<UniversalBleService?> universalBleServices =
await _executeWithErrorHandling(
() => _channel.discoverServices(deviceId, withDescriptors));
return List<BleService>.from(universalBleServices
.where((e) => e != null)
.map((e) => e!.toBleService(deviceId))
.toList());
() => _channel.discoverServices(deviceId, withDescriptors),
);
return List<BleService>.from(
universalBleServices
.where((e) => e != null)
.map((e) => e!.toBleService(deviceId))
.toList(),
);
}
@override
Future<void> setNotifiable(String deviceId, String service,
String characteristic, BleInputProperty bleInputProperty) {
return _executeWithErrorHandling(() => _channel.setNotifiable(
deviceId,
service,
characteristic,
bleInputProperty.index,
));
Future<void> setNotifiable(
String deviceId,
String service,
String characteristic,
BleInputProperty bleInputProperty,
) {
return _executeWithErrorHandling(
() => _channel.setNotifiable(
deviceId,
service,
characteristic,
bleInputProperty.index,
),
);
}
@override
@@ -112,29 +125,34 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
final Duration? timeout,
}) {
return _executeWithErrorHandling(
() => _channel.readValue(deviceId, service, characteristic));
() => _channel.readValue(deviceId, service, characteristic),
);
}
@override
Future<void> writeValue(
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty) {
return _executeWithErrorHandling(() => _channel.writeValue(
deviceId,
service,
characteristic,
value,
bleOutputProperty.index,
));
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty,
) {
return _executeWithErrorHandling(
() => _channel.writeValue(
deviceId,
service,
characteristic,
value,
bleOutputProperty.index,
),
);
}
@override
Future<int> requestMtu(String deviceId, int expectedMtu) =>
_executeWithErrorHandling(
() => _channel.requestMtu(deviceId, expectedMtu));
() => _channel.requestMtu(deviceId, expectedMtu),
);
@override
Future<int> readRssi(String deviceId) =>
@@ -160,19 +178,19 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
}
@override
Future<void> requestPermissions(
{bool withAndroidFineLocation = false}) async {
Future<void> requestPermissions({
bool withAndroidFineLocation = false,
}) async {
await _executeWithErrorHandling(
() => _channel.requestPermissions(withAndroidFineLocation),
);
}
@override
Future<List<BleDevice>> getSystemDevices(
List<String>? withServices,
) async {
Future<List<BleDevice>> getSystemDevices(List<String>? withServices) async {
var devices = await _executeWithErrorHandling(
() => _channel.getSystemDevices(withServices ?? []));
() => _channel.getSystemDevices(withServices ?? []),
);
return List<BleDevice>.from(
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
);
@@ -180,22 +198,25 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
@override
Future<void> setLogLevel(BleLogLevel logLevel) => _executeWithErrorHandling(
() => _channel.setLogLevel(logLevel.toUniversalBleLogLevel()));
() => _channel.setLogLevel(logLevel.toUniversalBleLogLevel()),
);
/// To set listeners
void _setupListeners() {
UniversalBleCallbackChannel.setUp(_UniversalBleCallbackHandler(
scanResult: (bleDevice) {
// Only check for exclusion filter here,
// scan filter handled natively on platform side
if (_bleFilter.matchesExclusionFilter(bleDevice)) return;
updateScanResult(bleDevice);
},
availabilityChange: updateAvailability,
connectionChanged: updateConnection,
valueChanged: updateCharacteristicValue,
pairStateChange: updatePairingState,
));
UniversalBleCallbackChannel.setUp(
_UniversalBleCallbackHandler(
scanResult: (bleDevice) {
// Only check for exclusion filter here,
// scan filter handled natively on platform side
if (_bleFilter.matchesExclusionFilter(bleDevice)) return;
updateScanResult(bleDevice);
},
availabilityChange: updateAvailability,
connectionChanged: updateConnection,
valueChanged: updateCharacteristicValue,
pairStateChange: updatePairingState,
),
);
}
/// Executes a platform call with error handling
@@ -230,16 +251,19 @@ extension _BleServiceExtension on UniversalBleService {
for (UniversalBleCharacteristic? characteristic in characteristics ?? []) {
if (characteristic == null) continue;
List<int?>? properties = List<int?>.from(characteristic.properties);
bleCharacteristics.add(BleCharacteristic.withMetaData(
deviceId: deviceId,
serviceId: uuid,
uuid: characteristic.uuid,
descriptors: List<BleDescriptor>.from(
characteristic.descriptors.map((e) => BleDescriptor(e.uuid))),
properties: List<CharacteristicProperty>.from(
properties.map((e) => CharacteristicProperty.parse(e ?? 1)),
bleCharacteristics.add(
BleCharacteristic.withMetaData(
deviceId: deviceId,
serviceId: uuid,
uuid: characteristic.uuid,
descriptors: List<BleDescriptor>.from(
characteristic.descriptors.map((e) => BleDescriptor(e.uuid)),
),
properties: List<CharacteristicProperty>.from(
properties.map((e) => CharacteristicProperty.parse(e ?? 1)),
),
),
));
);
}
return BleService(uuid, bleCharacteristics);
}
@@ -278,8 +302,7 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
String characteristicId,
Uint8List value,
int? timestamp,
) =>
valueChanged(deviceId, characteristicId, value, timestamp);
) => valueChanged(deviceId, characteristicId, value, timestamp);
@override
void onPairStateChange(String deviceId, bool isPaired, String? error) =>
@@ -296,7 +319,8 @@ extension _UniversalBleScanResultExtension on UniversalBleScanResult {
isSystemDevice: isSystemDevice,
services: services?.map(BleUuidParser.string).toList() ?? [],
timestamp: timestamp,
manufacturerDataList: manufacturerDataList
manufacturerDataList:
manufacturerDataList
?.map((e) => ManufacturerData(e.companyIdentifier, e.data))
.toList() ??
[],
@@ -309,11 +333,13 @@ extension _ScanFilterExtension on ScanFilter? {
UniversalScanFilter? toUniversalScanFilter() {
List<UniversalManufacturerDataFilter>? manufacturerDataFilters = this
?.withManufacturerData
.map((e) => UniversalManufacturerDataFilter(
companyIdentifier: e.companyIdentifier,
data: e.payloadPrefix,
mask: e.payloadMask,
))
.map(
(e) => UniversalManufacturerDataFilter(
companyIdentifier: e.companyIdentifier,
data: e.payloadPrefix,
mask: e.payloadMask,
),
)
.toList();
// Windows crashes if it's null, so we need to pass empty scan filter in this case
@@ -327,19 +353,17 @@ extension _ScanFilterExtension on ScanFilter? {
extension _BleLogLevelExtension on BleLogLevel {
UniversalBleLogLevel toUniversalBleLogLevel() => switch (this) {
BleLogLevel.none => UniversalBleLogLevel.none,
BleLogLevel.error => UniversalBleLogLevel.error,
BleLogLevel.warning => UniversalBleLogLevel.warning,
BleLogLevel.info => UniversalBleLogLevel.info,
BleLogLevel.debug => UniversalBleLogLevel.debug,
BleLogLevel.verbose => UniversalBleLogLevel.verbose,
};
BleLogLevel.none => UniversalBleLogLevel.none,
BleLogLevel.error => UniversalBleLogLevel.error,
BleLogLevel.warning => UniversalBleLogLevel.warning,
BleLogLevel.info => UniversalBleLogLevel.info,
BleLogLevel.debug => UniversalBleLogLevel.debug,
BleLogLevel.verbose => UniversalBleLogLevel.verbose,
};
}
extension _PlatformConfigExtension on PlatformConfig? {
UniversalScanConfig? toUniversalScanConfig() {
return UniversalScanConfig(
android: this?.android,
);
return UniversalScanConfig(android: this?.android);
}
}
+53 -39
View File
@@ -16,11 +16,15 @@ abstract class UniversalBlePlatform {
final _scanStreamController = UniversalBleStreamController<BleDevice>();
final bleConnectionUpdateStreamController = UniversalBleStreamController<
({String deviceId, bool isConnected, String? error})>();
final bleConnectionUpdateStreamController =
UniversalBleStreamController<
({String deviceId, bool isConnected, String? error})
>();
final _valueStreamController = UniversalBleStreamController<
({String deviceId, String characteristicId, Uint8List value})>();
final _valueStreamController =
UniversalBleStreamController<
({String deviceId, String characteristicId, Uint8List value})
>();
final _pairStateStreamController =
UniversalBleStreamController<({String deviceId, bool isPaired})>();
@@ -28,8 +32,8 @@ abstract class UniversalBlePlatform {
/// Send latest availability state upon subscribing
late final _availabilityStreamController =
UniversalBleStreamController<AvailabilityState>(
initialEvent: getBluetoothAvailabilityState,
);
initialEvent: getBluetoothAvailabilityState,
);
Future<AvailabilityState> getBluetoothAvailabilityState();
@@ -41,8 +45,9 @@ abstract class UniversalBlePlatform {
return true;
}
Future<void> requestPermissions(
{bool withAndroidFineLocation = false}) async {}
Future<void> requestPermissions({
bool withAndroidFineLocation = false,
}) async {}
Future<void> startScan({
ScanFilter? scanFilter,
@@ -53,16 +58,25 @@ abstract class UniversalBlePlatform {
Future<bool> isScanning();
Future<void> connect(String deviceId,
{Duration? connectionTimeout, bool autoConnect = false});
Future<void> connect(
String deviceId, {
Duration? connectionTimeout,
bool autoConnect = false,
});
Future<void> disconnect(String deviceId);
Future<List<BleService>> discoverServices(
String deviceId, bool withDescriptors);
String deviceId,
bool withDescriptors,
);
Future<void> setNotifiable(String deviceId, String service,
String characteristic, BleInputProperty bleInputProperty);
Future<void> setNotifiable(
String deviceId,
String service,
String characteristic,
BleInputProperty bleInputProperty,
);
Future<Uint8List> readValue(
String deviceId,
@@ -72,11 +86,12 @@ abstract class UniversalBlePlatform {
});
Future<void> writeValue(
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty);
String deviceId,
String service,
String characteristic,
Uint8List value,
BleOutputProperty bleOutputProperty,
);
Future<int> requestMtu(String deviceId, int expectedMtu);
@@ -90,9 +105,7 @@ abstract class UniversalBlePlatform {
Future<BleConnectionState> getConnectionState(String deviceId);
Future<List<BleDevice>> getSystemDevices(
List<String>? withServices,
);
Future<List<BleDevice>> getSystemDevices(List<String>? withServices);
Future<void> setLogLevel(BleLogLevel logLevel) async =>
UniversalLogger.setLogLevel(logLevel);
@@ -115,15 +128,18 @@ abstract class UniversalBlePlatform {
String characteristicId,
) {
characteristicId = BleUuidParser.string(characteristicId);
return _valueStreamController.stream.where((e) {
return e.deviceId == deviceId && e.characteristicId == characteristicId;
}).map((e) => e.value);
return _valueStreamController.stream
.where((e) {
return e.deviceId == deviceId &&
e.characteristicId == characteristicId;
})
.map((e) => e.value);
}
Stream<bool> pairingStateStream(String deviceId) =>
_pairStateStreamController.stream
.where((e) => e.deviceId == deviceId)
.map((e) => e.isPaired);
Stream<bool> pairingStateStream(String deviceId) => _pairStateStreamController
.stream
.where((e) => e.deviceId == deviceId)
.map((e) => e.isPaired);
/// Update Handlers
void updateScanResult(BleDevice bleDevice) {
@@ -188,18 +204,16 @@ abstract class UniversalBlePlatform {
}
// Callback types
typedef OnConnectionChange = void Function(
String deviceId,
bool isConnected,
String? error,
);
typedef OnConnectionChange =
void Function(String deviceId, bool isConnected, String? error);
typedef OnValueChange = void Function(
String deviceId,
String characteristicId,
Uint8List value,
int? timestamp,
);
typedef OnValueChange =
void Function(
String deviceId,
String characteristicId,
Uint8List value,
int? timestamp,
);
typedef OnScanResult = void Function(BleDevice scanResult);
@@ -64,7 +64,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
@override
Future<List<BleService>> discoverServices(
String deviceId, bool withDescriptors) async {
String deviceId,
bool withDescriptors,
) async {
List<BleService> services = [];
for (var service in await _getServices(deviceId)) {
services.add(await service._toBleService(deviceId, withDescriptors));
@@ -131,8 +133,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
await device.unwatchAdvertisements();
}
_deviceAdvertisementStreamList[device.id] =
device.advertisements.listen((event) {
_deviceAdvertisementStreamList[device.id] = device.advertisements.listen((
event,
) {
final serviceDataMap = event.serviceData.map(
(key, value) => MapEntry(key, value.buffer.asUint8List()),
);
@@ -192,24 +195,24 @@ class UniversalBleWeb extends UniversalBlePlatform {
_characteristicStreamList[characteristicKey]?.cancel();
}
await bleCharacteristic.startNotifications();
_characteristicStreamList[characteristicKey] =
bleCharacteristic.value.listen((ByteData event) {
final preview = event.buffer
.asUint8List()
.take(8)
.map((e) => e.toRadixString(16).padLeft(2, '0'))
.join();
UniversalLogger.logVerbose(
"NOTIFY <- $deviceId $characteristic len=${event.lengthInBytes} data=$preview",
withTimestamp: true,
);
updateCharacteristicValue(
deviceId,
characteristic,
event.buffer.asUint8List(),
DateTime.now().millisecondsSinceEpoch,
);
});
_characteristicStreamList[characteristicKey] = bleCharacteristic.value
.listen((ByteData event) {
final preview = event.buffer
.asUint8List()
.take(8)
.map((e) => e.toRadixString(16).padLeft(2, '0'))
.join();
UniversalLogger.logVerbose(
"NOTIFY <- $deviceId $characteristic len=${event.lengthInBytes} data=$preview",
withTimestamp: true,
);
updateCharacteristicValue(
deviceId,
characteristic,
event.buffer.asUint8List(),
DateTime.now().millisecondsSinceEpoch,
);
});
} else {
await bleCharacteristic.stopNotifications();
_characteristicStreamList.remove(characteristicKey)?.cancel();
@@ -245,8 +248,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
if (bleOutputProperty == BleOutputProperty.withResponse) {
await bleCharacteristic.writeValueWithResponse(Uint8List.fromList(value));
} else {
await bleCharacteristic
.writeValueWithoutResponse(Uint8List.fromList(value));
await bleCharacteristic.writeValueWithoutResponse(
Uint8List.fromList(value),
);
}
}
@@ -322,9 +326,7 @@ class UniversalBleWeb extends UniversalBlePlatform {
}
@override
Future<List<BleDevice>> getSystemDevices(
List<String>? withServices,
) {
Future<List<BleDevice>> getSystemDevices(List<String>? withServices) {
throw UniversalBleException(
code: UniversalBleErrorCode.notImplemented,
message: "getSystemDevices is not implemented on Web platform",
@@ -333,20 +335,18 @@ class UniversalBleWeb extends UniversalBlePlatform {
/// Helpers
void _setupListeners() {
FlutterWebBluetooth.instance.isAvailable.listen(
(bool isAvailable) {
AvailabilityState newState = AvailabilityState.unknown;
if (!FlutterWebBluetooth.instance.isBluetoothApiSupported) {
newState = AvailabilityState.unsupported;
} else if (FlutterWebBluetooth.instance.isBluetoothApiSupported &&
!isAvailable) {
newState = AvailabilityState.poweredOff;
} else if (isAvailable) {
newState = AvailabilityState.poweredOn;
}
updateAvailability(newState);
},
);
FlutterWebBluetooth.instance.isAvailable.listen((bool isAvailable) {
AvailabilityState newState = AvailabilityState.unknown;
if (!FlutterWebBluetooth.instance.isBluetoothApiSupported) {
newState = AvailabilityState.unsupported;
} else if (FlutterWebBluetooth.instance.isBluetoothApiSupported &&
!isAvailable) {
newState = AvailabilityState.poweredOff;
} else if (isAvailable) {
newState = AvailabilityState.poweredOn;
}
updateAvailability(newState);
});
}
void _cleanConnection(String deviceId) {
@@ -399,9 +399,9 @@ class UniversalBleWeb extends UniversalBlePlatform {
_deviceAdvertisementStreamList.removeWhere((key, value) {
if (deviceId != null && key != deviceId) return false;
value.cancel();
_getDeviceById(deviceId ?? key)
?.unwatchAdvertisements()
.onError((_, __) {});
_getDeviceById(
deviceId ?? key,
)?.unwatchAdvertisements().onError((_, __) {});
return true;
});
}
@@ -472,21 +472,23 @@ class UniversalBleWeb extends UniversalBlePlatform {
// Add exclusion filters
for (var exclusionFilter in scanFilter.exclusionFilters) {
exclusionFilters.add(RequestFilterBuilder(
services: exclusionFilter.services.isEmpty
? null
: exclusionFilter.services.toValidUUIDList(),
namePrefix: exclusionFilter.namePrefix,
manufacturerData: exclusionFilter.manufacturerDataFilter.isEmpty
? null
: exclusionFilter.manufacturerDataFilter.map((e) {
return ManufacturerDataFilterBuilder(
companyIdentifier: e.companyIdentifier,
dataPrefix: e.payloadPrefix,
mask: e.payloadMask,
);
}).toList(),
));
exclusionFilters.add(
RequestFilterBuilder(
services: exclusionFilter.services.isEmpty
? null
: exclusionFilter.services.toValidUUIDList(),
namePrefix: exclusionFilter.namePrefix,
manufacturerData: exclusionFilter.manufacturerDataFilter.isEmpty
? null
: exclusionFilter.manufacturerDataFilter.map((e) {
return ManufacturerDataFilterBuilder(
companyIdentifier: e.companyIdentifier,
dataPrefix: e.payloadPrefix,
mask: e.payloadMask,
);
}).toList(),
),
);
}
}
@@ -538,8 +540,10 @@ extension _BluetoothDeviceExtension on BluetoothDevice {
extension _UnmodifiableMapViewExtension on UnmodifiableMapView<int, ByteData> {
List<ManufacturerData>? toManufacturerDataList() => entries
.map((MapEntry<int, ByteData> data) =>
ManufacturerData(data.key, data.value.buffer.asUint8List()))
.map(
(MapEntry<int, ByteData> data) =>
ManufacturerData(data.key, data.value.buffer.asUint8List()),
)
.toList();
}
@@ -583,29 +587,32 @@ class _UniversalWebBluetoothService {
if (withDescriptors) {
try {
var bluetoothDescriptors = await characteristic.getDescriptors();
descriptors =
bluetoothDescriptors.map((e) => BleDescriptor(e.uuid)).toList();
descriptors = bluetoothDescriptors
.map((e) => BleDescriptor(e.uuid))
.toList();
} catch (_) {}
}
bleCharacteristics.add(BleCharacteristic.withMetaData(
deviceId: deviceId,
serviceId: service.uuid,
uuid: characteristic.uuid,
properties: [
if (characteristic.properties.broadcast)
CharacteristicProperty.broadcast,
if (characteristic.properties.read) CharacteristicProperty.read,
if (characteristic.properties.write) CharacteristicProperty.write,
if (characteristic.properties.writeWithoutResponse)
CharacteristicProperty.writeWithoutResponse,
if (characteristic.properties.notify) CharacteristicProperty.notify,
if (characteristic.properties.indicate)
CharacteristicProperty.indicate,
if (characteristic.properties.authenticatedSignedWrites)
CharacteristicProperty.authenticatedSignedWrites,
],
descriptors: descriptors,
));
bleCharacteristics.add(
BleCharacteristic.withMetaData(
deviceId: deviceId,
serviceId: service.uuid,
uuid: characteristic.uuid,
properties: [
if (characteristic.properties.broadcast)
CharacteristicProperty.broadcast,
if (characteristic.properties.read) CharacteristicProperty.read,
if (characteristic.properties.write) CharacteristicProperty.write,
if (characteristic.properties.writeWithoutResponse)
CharacteristicProperty.writeWithoutResponse,
if (characteristic.properties.notify) CharacteristicProperty.notify,
if (characteristic.properties.indicate)
CharacteristicProperty.indicate,
if (characteristic.properties.authenticatedSignedWrites)
CharacteristicProperty.authenticatedSignedWrites,
],
descriptors: descriptors,
),
);
}
return BleService(service.uuid, bleCharacteristics);
}
+6 -24
View File
@@ -10,19 +10,13 @@ class UniversalLogger {
_currentLogLevel = logLevel;
}
static void logError(
String message, {
bool withTimestamp = false,
}) {
static void logError(String message, {bool withTimestamp = false}) {
if (!_allows(BleLogLevel.error)) return;
if (withTimestamp) {
final ts = DateTime.now().toIso8601String();
message = "[$ts] $message";
}
log(
'\x1B[31m$message\x1B[0m',
name: 'UniversalBle:ERROR',
);
log('\x1B[31m$message\x1B[0m', name: 'UniversalBle:ERROR');
}
static void logWarning(String message, {bool withTimestamp = false}) {
@@ -31,10 +25,7 @@ class UniversalLogger {
final ts = DateTime.now().toIso8601String();
message = "[$ts] $message";
}
log(
'\x1B[33m$message\x1B[0m',
name: 'UniversalBle:WARN',
);
log('\x1B[33m$message\x1B[0m', name: 'UniversalBle:WARN');
}
static void logInfo(String message, {bool withTimestamp = false}) {
@@ -43,10 +34,7 @@ class UniversalLogger {
final ts = DateTime.now().toIso8601String();
message = "[$ts] $message";
}
log(
message.toString(),
name: 'UniversalBle:INFO',
);
log(message.toString(), name: 'UniversalBle:INFO');
}
static void logDebug(String message, {bool withTimestamp = false}) {
@@ -55,10 +43,7 @@ class UniversalLogger {
final ts = DateTime.now().toIso8601String();
message = "[$ts] $message";
}
log(
message.toString(),
name: 'UniversalBle:DEBUG',
);
log(message.toString(), name: 'UniversalBle:DEBUG');
}
static void logVerbose(String message, {bool withTimestamp = false}) {
@@ -67,10 +52,7 @@ class UniversalLogger {
final ts = DateTime.now().toIso8601String();
message = "[$ts] $message";
}
log(
message.toString(),
name: 'UniversalBle:VERBOSE',
);
log(message.toString(), name: 'UniversalBle:VERBOSE');
}
static bool _allows(BleLogLevel level) {