Improve scan filter api (#78)

* Improve scan filter api

* Implement Windows filters

* Add manufacturerDataList and deprecate manufacturerData

* Fix Windows

* Update Readme and changelog

* Remove import

* Fix Linux

* Update readme and changelog

* Cleanup Todo

* Improve ManufacturerData

* Rename webConfig and Manufacturer.data

* Return false for receivesAdvertisements on Linux/Web

* Add delay in discoverServices on Linux

* Remove import

* Update changelog

---------

Co-authored-by: fotidim <foti@navideck.com>
This commit is contained in:
Rohit Sangwan
2024-09-17 03:13:51 +05:30
committed by GitHub
parent 639384af30
commit 7dc22c58a5
38 changed files with 1516 additions and 850 deletions
+9 -37
View File
@@ -9,8 +9,12 @@ class BleDevice {
bool? isPaired;
List<String> services;
bool? isSystemDevice;
Uint8List? manufacturerDataHead;
Uint8List? manufacturerData;
List<ManufacturerData> manufacturerDataList;
@Deprecated("Use `manufacturerDataList` instead")
Uint8List? get manufacturerData => manufacturerDataList.isEmpty
? null
: manufacturerDataList.first.toUint8List();
/// Returns connection state of the device.
/// All platforms will return `Connected/Disconnected` states.
@@ -30,12 +34,8 @@ class BleDevice {
this.isPaired,
this.services = const [],
this.isSystemDevice,
Uint8List? manufacturerData,
Uint8List? manufacturerDataHead,
}) {
this.manufacturerDataHead = manufacturerDataHead ?? Uint8List.fromList([]);
this.manufacturerData = manufacturerData ?? manufacturerDataHead;
}
this.manufacturerDataList = const [],
});
@override
String toString() {
@@ -46,34 +46,6 @@ class BleDevice {
'isPaired: $isPaired, '
'services: $services, '
'isSystemDevice: $isSystemDevice, '
'manufacturerDataHead: $manufacturerDataHead, '
'manufacturerData: $manufacturerData';
}
}
/// Represents the manufacturer data of a BLE device.
/// Use [BleDevice.manufacturerData] with [ManufacturerData.fromData] to create an instance of this class.
class ManufacturerData {
final int? companyId;
final Uint8List? data;
String? companyIdRadix16;
ManufacturerData(this.companyId, this.data) {
if (companyId != null) {
companyIdRadix16 = "0x0${companyId!.toRadixString(16)}";
}
}
factory ManufacturerData.fromData(Uint8List data) {
if (data.length < 2) return ManufacturerData(null, data);
int manufacturerIdInt = (data[0] + (data[1] << 8));
return ManufacturerData(
manufacturerIdInt,
data.sublist(2),
);
}
@override
String toString() {
return 'ManufacturerData: companyId: $companyIdRadix16, data: $data';
'manufacturerDataList: $manufacturerDataList';
}
}
+43
View File
@@ -0,0 +1,43 @@
import 'package:flutter/foundation.dart';
/// Represents the manufacturer data of a BLE device.
class ManufacturerData {
final int companyId;
final Uint8List payload;
ManufacturerData(this.companyId, this.payload);
String get companyIdRadix16 => "0x0${companyId.toRadixString(16)}";
factory ManufacturerData.fromData(Uint8List data) {
if (data.length < 2) {
throw const FormatException("Invalid Manufacturer Data");
}
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(),
);
}
@override
int get hashCode => companyId.hashCode ^ payload.hashCode;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! ManufacturerData) return false;
return companyId == other.companyId && listEquals(payload, other.payload);
}
@override
String toString() {
return 'Manufacturer: $companyIdRadix16 - $payload';
}
}
+1
View File
@@ -1,3 +1,4 @@
export 'package:universal_ble/src/models/manufacturer_data.dart';
export 'package:universal_ble/src/models/platform_config.dart';
export 'package:universal_ble/src/models/queue_type.dart';
export 'package:universal_ble/src/models/ble_uuid_parser.dart';
+4 -4
View File
@@ -1,22 +1,22 @@
/// Platform specific config to scan devices
class PlatformConfig {
WebConfig? web;
WebOptions? web;
PlatformConfig({this.web});
}
/// Web config to scan devices
/// Web options to scan devices
/// [optionalServices] is a list of service uuid's to ensure that you can access the specified services after connecting to the device,
/// by default services from scanFilter will be used
/// [optionalManufacturerData] is list of `CompanyIdentifier's` and used to add `ManufacturerData` in advertisement results of selected device from web dialog,
/// by default manufacturerData from scanFilter will be used
/// Checkout more details on [web](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice)
/// Note: you will only get advertisements if Experimental Flag is enabled in the browser
class WebConfig {
class WebOptions {
List<String> optionalServices;
List<int> optionalManufacturerData;
WebConfig({
WebOptions({
this.optionalServices = const [],
this.optionalManufacturerData = const [],
});
+5 -5
View File
@@ -18,10 +18,10 @@ class ScanFilter {
}
class ManufacturerDataFilter {
int? companyIdentifier;
int companyIdentifier;
// Mask and data must be of same length
Uint8List? data;
Uint8List? payload;
/// For any bit in the mask, set it the 1 if it needs to match
/// the one in manufacturer data, otherwise set it to 0.
@@ -29,13 +29,13 @@ class ManufacturerDataFilter {
Uint8List? mask;
ManufacturerDataFilter({
this.companyIdentifier,
this.data,
required this.companyIdentifier,
this.payload,
this.mask,
});
@override
String toString() {
return 'ManufacturerDataFilter(companyIdentifier: $companyIdentifier, data: $data, mask: $mask)';
return 'ManufacturerDataFilter(companyIdentifier: $companyIdentifier, payload: $payload, mask: $mask)';
}
}
+98
View File
@@ -0,0 +1,98 @@
import 'dart:typed_data';
import 'package:universal_ble/universal_ble.dart';
// A default Filter on dart side
// Used on Linux only
class UniversalBleFilterUtil {
ScanFilter? scanFilter;
bool filterDevice(BleDevice device) {
final filter = scanFilter;
if (filter == null) return true;
final hasNamePrefixFilter = filter.withNamePrefix.isNotEmpty;
final hasServiceFilter = filter.withServices.isNotEmpty;
final hasManufacturerDataFilter = filter.withManufacturerData.isNotEmpty;
// If there is no filter at all, then allow device
if (!hasNamePrefixFilter &&
!hasServiceFilter &&
!hasManufacturerDataFilter) {
return true;
}
// Else check one of the filter passes
return hasNamePrefixFilter && isNameMatchingFilters(filter, device) ||
hasServiceFilter && isServicesMatchingFilters(filter, device) ||
hasManufacturerDataFilter &&
isManufacturerDataMatchingFilters(filter, device);
}
bool isNameMatchingFilters(ScanFilter scanFilter, BleDevice device) {
var namePrefixFilter = scanFilter.withNamePrefix;
if (namePrefixFilter.isEmpty) return true;
String? name = device.name;
if (name == null || name.isEmpty) return false;
return namePrefixFilter.any(name.startsWith);
}
bool isServicesMatchingFilters(ScanFilter scanFilter, BleDevice device) {
var serviceFilters = scanFilter.withServices;
if (serviceFilters.isEmpty) return true;
List<String> serviceUuids = device.services;
if (serviceUuids.isEmpty) {
return false;
}
return serviceFilters.any(serviceUuids.contains);
}
bool isManufacturerDataMatchingFilters(
ScanFilter scanFilter,
BleDevice device,
) {
final filterMfdList = scanFilter.withManufacturerData;
if (filterMfdList.isEmpty) return true;
List<ManufacturerData> manufacturerDataList = device.manufacturerDataList;
if (manufacturerDataList.isEmpty) return false;
return manufacturerDataList.any((deviceMfd) => filterMfdList.any(
(filterMfd) => _isManufacturerDataMatch(filterMfd, deviceMfd),
));
}
bool _isManufacturerDataMatch(
ManufacturerDataFilter filterMfd,
ManufacturerData deviceMfd,
) {
if (filterMfd.companyIdentifier != deviceMfd.companyId) return false;
Uint8List? filterPayload = filterMfd.payload;
Uint8List devicePayload = deviceMfd.payload;
if (filterPayload == null || filterPayload.isEmpty) return true;
if (devicePayload.isEmpty) return false;
if (filterPayload.length > devicePayload.length) return false;
Uint8List? filterMask = filterMfd.mask;
if (filterMask != null && filterMask.length == filterPayload.length) {
for (int i = 0; i < filterPayload.length; i++) {
if ((filterPayload[i] & filterMask[i]) !=
(devicePayload[i] & filterMask[i])) {
return false;
}
}
} else {
for (int i = 0; i < filterPayload.length; i++) {
if (filterPayload[i] != devicePayload[i]) {
return false;
}
}
}
return true;
}
}
@@ -1,9 +1,9 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:bluez/bluez.dart';
import 'package:flutter/services.dart';
import 'package:universal_ble/src/models/model_exports.dart';
import 'package:universal_ble/src/universal_ble_filter_util.dart';
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
class UniversalBleLinux extends UniversalBlePlatform {
@@ -14,12 +14,13 @@ class UniversalBleLinux extends UniversalBlePlatform {
bool isInitialized = false;
final BlueZClient _client = BlueZClient();
late final UniversalBleFilterUtil _bleFilter = UniversalBleFilterUtil();
BlueZAdapter? _activeAdapter;
ScanFilter? _scanFilter;
Completer<void>? _initializationCompleter;
final Map<String, BlueZDevice> _devices = {};
final Map<String, StreamSubscription> _deviceStreamSubscriptions = {};
final Map<String, StreamSubscription> _deviceUpdateStreamSubscriptions = {};
final Map<String, StreamSubscription> _deviceAdvertisementSubscriptions = {};
final Map<String, StreamSubscription> _characteristicPropertiesSubscriptions =
{};
@@ -58,15 +59,44 @@ class UniversalBleLinux extends UniversalBlePlatform {
PlatformConfig? platformConfig,
}) async {
await _ensureInitialized();
await super.startScan(scanFilter: scanFilter);
if (_activeAdapter?.discovering != true) {
// Add services filter
_activeAdapter?.setDiscoveryFilter(
uuids: scanFilter?.withServices.toValidUUIDList(),
);
_scanFilter = scanFilter;
await _activeAdapter?.startDiscovery();
_client.devices.forEach(_onDeviceAdd);
var adapter = _activeAdapter;
if (adapter == null) {
throw "Adapter not available";
}
// Stop scan and clean all old advertisement listeners
await stopScan();
bool hasCustomFilter = scanFilter?.hasCustomFilter() ?? false;
List<String> withServicesFilter = [];
if (hasCustomFilter) {
_bleFilter.scanFilter = scanFilter;
} else {
_bleFilter.scanFilter = null;
withServicesFilter = scanFilter?.withServices.toValidUUIDList() ?? [];
}
// Add services filter
await adapter.setDiscoveryFilter(
uuids: withServicesFilter,
);
await _activeAdapter?.startDiscovery();
// Apply custom Services filter to these devices
ScanFilter customServicesFilter = ScanFilter(
withServices: withServicesFilter,
);
for (var device in _client.devices) {
if (!hasCustomFilter && withServicesFilter.isNotEmpty) {
if (_bleFilter.isServicesMatchingFilters(
customServicesFilter, device.toBleDevice())) {
_onDeviceAdd(device);
}
} else {
_onDeviceAdd(device);
}
}
}
@@ -77,6 +107,11 @@ class UniversalBleLinux extends UniversalBlePlatform {
if (_activeAdapter?.discovering == true) {
await _activeAdapter?.stopDiscovery();
}
// Clean all advertiseemnt listeners
_deviceAdvertisementSubscriptions.removeWhere((e, value) {
value.cancel();
return true;
});
} catch (e) {
UniversalBlePlatform.logInfo(
"stopScan error: $e",
@@ -139,6 +174,9 @@ class UniversalBleLinux extends UniversalBlePlatform {
});
}
// Few ble devices requires delay to perform operations after discovering services
await Future.delayed(const Duration(seconds: 1));
if (device.gattServices.isEmpty && !device.servicesResolved) {
throw "Failed to resolve services";
}
@@ -413,40 +451,41 @@ class UniversalBleLinux extends UniversalBlePlatform {
}
void _onDeviceAdd(BlueZDevice device) {
if (!_isValidDevice(device)) return;
// Apply Filters
if (_scanFilter != null) {
List<ManufacturerDataFilter>? manufacturerDataFilter =
_scanFilter?.withManufacturerData;
if (manufacturerDataFilter != null &&
manufacturerDataFilter.isNotEmpty) {}
BleDevice bleDevice = device.toBleDevice();
if (!_bleFilter.filterDevice(bleDevice)) {
return;
}
// Update scan results only if rssi is available
if (device.rssi != 0) updateScanResult(device.toBleDevice());
if (device.rssi != 0) {
updateScanResult(bleDevice);
}
// Setup Cache
_devices[device.address] = device;
// Setup update listener
if (_deviceStreamSubscriptions[device.address] != null) {
_deviceStreamSubscriptions[device.address]?.cancel();
}
// Setup advertisements Listener
_deviceAdvertisementSubscriptions[device.address] ??= device
.propertiesChanged
.where((e) =>
e.contains(BluezProperty.rssi) ||
e.contains(BluezProperty.manufacturerData) ||
e.contains(BluezProperty.uuids))
.listen((_) {
if (_bleFilter.filterDevice(bleDevice)) {
updateScanResult(device.toBleDevice());
}
});
_deviceStreamSubscriptions[device.address] =
// Setup update listener
_deviceUpdateStreamSubscriptions[device.address] ??=
device.propertiesChanged.listen((properties) {
for (final property in properties) {
switch (property) {
case BluezProperty.rssi:
updateScanResult(device.toBleDevice());
break;
// Connection/Pair updates
case BluezProperty.connected:
updateConnection(device.address, device.connected);
break;
case BluezProperty.manufacturerData:
updateScanResult(device.toBleDevice());
break;
case BluezProperty.paired:
updatePairingState(device.address, device.paired);
break;
@@ -458,95 +497,37 @@ class UniversalBleLinux extends UniversalBlePlatform {
case BluezProperty.txPower:
case BluezProperty.address:
case BluezProperty.addressType:
case BluezProperty.rssi:
case BluezProperty.manufacturerData:
break;
default:
UniversalBlePlatform.logInfo(
"UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property");
"UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property",
);
break;
}
}
});
}
bool _isValidDevice(BlueZDevice device) {
ScanFilter? scanFilter = _scanFilter;
if (scanFilter == null) return true;
// Check manufacturerData filter
if (!_isValidManufacturerData(
scanFilter.withManufacturerData,
device.manufacturerDataFilter,
)) {
return false;
}
return true;
}
bool _isValidManufacturerData(
List<ManufacturerDataFilter> filterMfdList,
List<ManufacturerDataFilter> deviceMfdList,
) {
if (filterMfdList.isEmpty) return true;
if (deviceMfdList.isEmpty) return false;
// Check all filters
for (final filterMfd in filterMfdList) {
// Check if device have manufacturerData for this filter
for (final deviceMfd in deviceMfdList) {
// Check companyIdentifier
if (filterMfd.companyIdentifier != deviceMfd.companyIdentifier) {
continue;
}
// Check data
Uint8List? filterData = filterMfd.data;
Uint8List? deviceData = deviceMfd.data;
// If filter data is null and device data is not, continue to next deviceMfd
if (filterData != null && deviceData == null) continue;
if (filterData == null || deviceData == null) {
return true;
}
if (filterData.length > deviceData.length) continue;
// Apply mask
Uint8List? filterMask = filterMfd.mask;
bool dataMatched = true;
if (filterMask != null && (filterMask.length == filterData.length)) {
for (int i = 0; i < filterData.length; i++) {
if ((filterData[i] & filterMask[i]) !=
(deviceData[i] & filterMask[i])) {
dataMatched = false;
break;
}
}
}
// Compare data directly
else {
for (int i = 0; i < filterData.length; i++) {
if (filterData[i] != deviceData[i]) {
dataMatched = false;
break;
}
}
}
if (dataMatched) return true;
}
}
return false;
}
void _onDeviceRemoved(BlueZDevice device) {
_devices.remove(device.address);
// Stop listener
_deviceStreamSubscriptions[device.address]?.cancel();
_deviceStreamSubscriptions
.removeWhere((key, value) => key == device.address);
// Clean Update listeners
_deviceUpdateStreamSubscriptions.removeWhere((key, value) {
if (key == device.address) {
value.cancel();
return true;
}
return false;
});
// Clean Advertisement listeners
_deviceAdvertisementSubscriptions.removeWhere((key, value) {
if (key == device.address) {
value.cancel();
return true;
}
return false;
});
}
}
@@ -570,62 +551,6 @@ class BluezProperty {
static const String propertyClass = 'Class';
}
extension BlueZDeviceExtension on BlueZDevice {
List<ManufacturerDataFilter> get manufacturerDataFilter {
try {
if (manufacturerData.isEmpty) return [];
return manufacturerData.entries
.map((e) => ManufacturerDataFilter(
companyIdentifier: e.key.id,
data: Uint8List.fromList(e.value),
))
.toList();
} catch (e) {
UniversalBlePlatform.logInfo(
'Error parsing manufacturerData: $e',
isError: true,
);
return [];
}
}
Uint8List get manufacturerDataHead {
try {
if (manufacturerData.isEmpty) return Uint8List(0);
final sorted = manufacturerData.entries.toList()
..sort((a, b) => a.key.id - b.key.id);
int companyId = sorted.first.key.id;
List<int> manufacturerDataValue = sorted.first.value;
final byteData = ByteData(2);
// TODO: Verify that this works regardless of the endianess
byteData.setInt16(0, companyId, Endian.host);
List<int> bytes = byteData.buffer.asUint8List();
return Uint8List.fromList(bytes + manufacturerDataValue);
} catch (e) {
UniversalBlePlatform.logInfo(
'Error parsing manufacturerData: $e',
isError: true,
);
return Uint8List(0);
}
}
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(),
);
}
}
extension on BlueZGattCharacteristicFlag {
CharacteristicProperty? toCharacteristicProperty() {
return switch (this) {
@@ -664,3 +589,28 @@ extension on BlueZFailedException {
}
}
}
extension on ScanFilter {
bool hasCustomFilter() {
return withNamePrefix.isNotEmpty || withManufacturerData.isNotEmpty;
}
}
extension BlueZDeviceExtension on BlueZDevice {
List<ManufacturerData> get manufacturerDataList => manufacturerData.entries
.map((MapEntry<BlueZManufacturerId, List<int>> data) =>
ManufacturerData(data.key.id, Uint8List.fromList(data.value)))
.toList();
BleDevice toBleDevice({bool? isSystemDevice}) {
return BleDevice(
name: name,
deviceId: address,
isPaired: paired,
rssi: rssi,
isSystemDevice: isSystemDevice,
services: uuids.map((e) => e.toString()).toList(),
manufacturerDataList: manufacturerDataList,
);
}
}
+135 -176
View File
@@ -15,8 +15,7 @@ PlatformException _createConnectionError(String channelName) {
);
}
List<Object?> wrapResponse(
{Object? result, PlatformException? error, bool empty = false}) {
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
}
@@ -32,8 +31,7 @@ class UniversalBleScanResult {
this.name,
this.isPaired,
this.rssi,
this.manufacturerData,
this.manufacturerDataHead,
this.manufacturerDataList,
this.services,
});
@@ -45,9 +43,7 @@ class UniversalBleScanResult {
int? rssi;
Uint8List? manufacturerData;
Uint8List? manufacturerDataHead;
List<UniversalManufacturerData?>? manufacturerDataList;
List<String?>? services;
@@ -57,8 +53,7 @@ class UniversalBleScanResult {
name,
isPaired,
rssi,
manufacturerData,
manufacturerDataHead,
manufacturerDataList,
services,
];
}
@@ -70,9 +65,8 @@ class UniversalBleScanResult {
name: result[1] as String?,
isPaired: result[2] as bool?,
rssi: result[3] as int?,
manufacturerData: result[4] as Uint8List?,
manufacturerDataHead: result[5] as Uint8List?,
services: (result[6] as List<Object?>?)?.cast<String?>(),
manufacturerDataList: (result[4] as List<Object?>?)?.cast<UniversalManufacturerData?>(),
services: (result[5] as List<Object?>?)?.cast<String?>(),
);
}
}
@@ -98,8 +92,7 @@ class UniversalBleService {
result as List<Object?>;
return UniversalBleService(
uuid: result[0]! as String,
characteristics:
(result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
characteristics: (result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
);
}
}
@@ -134,16 +127,20 @@ class UniversalBleCharacteristic {
class UniversalScanFilter {
UniversalScanFilter({
required this.withServices,
required this.withNamePrefix,
required this.withManufacturerData,
});
List<String?> withServices;
List<String?> withNamePrefix;
List<UniversalManufacturerDataFilter?> withManufacturerData;
Object encode() {
return <Object?>[
withServices,
withNamePrefix,
withManufacturerData,
];
}
@@ -152,20 +149,20 @@ class UniversalScanFilter {
result as List<Object?>;
return UniversalScanFilter(
withServices: (result[0] as List<Object?>?)!.cast<String?>(),
withManufacturerData: (result[1] as List<Object?>?)!
.cast<UniversalManufacturerDataFilter?>(),
withNamePrefix: (result[1] as List<Object?>?)!.cast<String?>(),
withManufacturerData: (result[2] as List<Object?>?)!.cast<UniversalManufacturerDataFilter?>(),
);
}
}
class UniversalManufacturerDataFilter {
UniversalManufacturerDataFilter({
this.companyIdentifier,
required this.companyIdentifier,
this.data,
this.mask,
});
int? companyIdentifier;
int companyIdentifier;
Uint8List? data;
@@ -182,13 +179,40 @@ class UniversalManufacturerDataFilter {
static UniversalManufacturerDataFilter decode(Object result) {
result as List<Object?>;
return UniversalManufacturerDataFilter(
companyIdentifier: result[0] as int?,
companyIdentifier: result[0]! as int,
data: result[1] as Uint8List?,
mask: result[2] as Uint8List?,
);
}
}
class UniversalManufacturerData {
UniversalManufacturerData({
required this.companyIdentifier,
required this.data,
});
int companyIdentifier;
Uint8List data;
Object encode() {
return <Object?>[
companyIdentifier,
data,
];
}
static UniversalManufacturerData decode(Object result) {
result as List<Object?>;
return UniversalManufacturerData(
companyIdentifier: result[0]! as int,
data: result[1]! as Uint8List,
);
}
}
class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
@@ -196,18 +220,21 @@ class _PigeonCodec extends StandardMessageCodec {
if (value is UniversalBleScanResult) {
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is UniversalBleService) {
} else if (value is UniversalBleService) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is UniversalBleCharacteristic) {
} else if (value is UniversalBleCharacteristic) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is UniversalScanFilter) {
} else if (value is UniversalScanFilter) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerDataFilter) {
} else if (value is UniversalManufacturerDataFilter) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerData) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@@ -216,16 +243,18 @@ class _PigeonCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
case 129:
return UniversalBleScanResult.decode(readValue(buffer)!);
case 130:
case 130:
return UniversalBleService.decode(readValue(buffer)!);
case 131:
case 131:
return UniversalBleCharacteristic.decode(readValue(buffer)!);
case 132:
case 132:
return UniversalScanFilter.decode(readValue(buffer)!);
case 133:
case 133:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
case 134:
return UniversalManufacturerData.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@@ -237,11 +266,9 @@ class UniversalBlePlatformChannel {
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UniversalBlePlatformChannel(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: __pigeon_binaryMessenger = binaryMessenger,
__pigeon_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
__pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? __pigeon_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
@@ -249,10 +276,8 @@ class UniversalBlePlatformChannel {
final String __pigeon_messageChannelSuffix;
Future<int> getBluetoothAvailabilityState() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -278,10 +303,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> enableBluetooth() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -307,10 +330,8 @@ class UniversalBlePlatformChannel {
}
Future<void> startScan(UniversalScanFilter? filter) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -331,10 +352,8 @@ class UniversalBlePlatformChannel {
}
Future<void> stopScan() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -355,10 +374,8 @@ class UniversalBlePlatformChannel {
}
Future<void> connect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -379,10 +396,8 @@ class UniversalBlePlatformChannel {
}
Future<void> disconnect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -402,19 +417,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> setNotifiable(String deviceId, String service,
String characteristic, int bleInputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel.send(
<Object?>[deviceId, service, characteristic, bleInputProperty])
as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, bleInputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -429,10 +440,8 @@ class UniversalBlePlatformChannel {
}
Future<List<UniversalBleService?>> discoverServices(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -453,23 +462,19 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleService?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleService?>();
}
}
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<Uint8List> readValue(String deviceId, String service, String characteristic) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -489,16 +494,14 @@ class UniversalBlePlatformChannel {
}
Future<int> requestMtu(String deviceId, int expectedMtu) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -517,24 +520,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> writeValue(String deviceId, String service,
String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[
deviceId,
service,
characteristic,
value,
bleOutputProperty
]) as List<Object?>?;
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, value, bleOutputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
@@ -549,10 +543,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> isPaired(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -578,10 +570,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> pair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -607,10 +597,8 @@ class UniversalBlePlatformChannel {
}
Future<void> unPair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -630,12 +618,9 @@ class UniversalBlePlatformChannel {
}
}
Future<List<UniversalBleScanResult?>> getSystemDevices(
List<String?> withServices) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<List<UniversalBleScanResult?>> getSystemDevices(List<String?> withServices) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -656,16 +641,13 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleScanResult?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
}
}
Future<int> getConnectionState(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -701,30 +683,22 @@ abstract class UniversalBleCallbackChannel {
void onScanResult(UniversalBleScanResult result);
void onValueChanged(
String deviceId, String characteristicId, Uint8List value);
void onValueChanged(String deviceId, String characteristicId, Uint8List value);
void onConnectionChanged(String deviceId, bool connected);
static void setUp(
UniversalBleCallbackChannel? api, {
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
static void setUp(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_state = (args[0] as int?);
assert(arg_state != null,
@@ -734,25 +708,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -766,28 +737,24 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
final List<Object?> args = (message as List<Object?>?)!;
final UniversalBleScanResult? arg_result =
(args[0] as UniversalBleScanResult?);
final UniversalBleScanResult? arg_result = (args[0] as UniversalBleScanResult?);
assert(arg_result != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
try {
@@ -795,25 +762,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -825,30 +789,26 @@ abstract class UniversalBleCallbackChannel {
assert(arg_value != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
try {
api.onValueChanged(
arg_deviceId!, arg_characteristicId!, arg_value!);
api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -861,9 +821,8 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
@@ -32,7 +32,6 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
ScanFilter? scanFilter,
PlatformConfig? platformConfig,
}) async {
await super.startScan(scanFilter: scanFilter);
await _channel.startScan(
scanFilter.toUniversalScanFilter(),
);
@@ -194,22 +193,16 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
}
extension _UniversalBleScanResultExtension on UniversalBleScanResult {
BleDevice toBleDevice({
bool? isSystemDevice,
}) {
var mnfDataHead = manufacturerDataHead ?? Uint8List.fromList([]);
var mnfData = manufacturerData ?? mnfDataHead;
BleDevice toBleDevice({bool? isSystemDevice}) {
return BleDevice(
name: name,
deviceId: deviceId,
manufacturerData: mnfData,
manufacturerDataHead: mnfDataHead,
rssi: rssi,
isPaired: isPaired,
isSystemDevice: isSystemDevice,
services: services
?.where((e) => e != null)
.map((e) => BleUuidParser.string(e!))
services: services?.nonNulls.map(BleUuidParser.string).toList() ?? [],
manufacturerDataList: manufacturerDataList?.nonNulls
.map((e) => ManufacturerData(e.companyIdentifier, e.data))
.toList() ??
[],
);
@@ -222,7 +215,7 @@ extension _ScanFilterExtension on ScanFilter? {
?.withManufacturerData
.map((e) => UniversalManufacturerDataFilter(
companyIdentifier: e.companyIdentifier,
data: e.data,
data: e.payload,
mask: e.mask,
))
.toList();
@@ -230,6 +223,7 @@ extension _ScanFilterExtension on ScanFilter? {
// Windows crashes if it's null, so we need to pass empty scan filter in this case
return UniversalScanFilter(
withServices: this?.withServices.toValidUUIDList() ?? [],
withNamePrefix: this?.withNamePrefix ?? [],
withManufacturerData: manufacturerDataFilters ?? [],
);
}
+1 -11
View File
@@ -4,7 +4,6 @@ import 'dart:typed_data';
import 'package:universal_ble/universal_ble.dart';
abstract class UniversalBlePlatform {
ScanFilter? _scanFilter;
StreamController? _connectionStreamController;
final Map<String, bool> _pairStateMap = {};
@@ -15,9 +14,7 @@ abstract class UniversalBlePlatform {
Future<void> startScan({
ScanFilter? scanFilter,
PlatformConfig? platformConfig,
}) async {
_scanFilter = scanFilter;
}
});
Future<void> stopScan();
@@ -68,13 +65,6 @@ abstract class UniversalBlePlatform {
}
void updateScanResult(BleDevice bleDevice) {
// Filter by name
ScanFilter? scanFilter = _scanFilter;
if (scanFilter != null && scanFilter.withNamePrefix.isNotEmpty) {
if (bleDevice.name == null ||
!scanFilter.withNamePrefix
.any((e) => bleDevice.name?.startsWith(e) == true)) return;
}
onScanResult?.call(bleDevice);
}
@@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart';
import 'package:universal_ble/src/models/model_exports.dart';
import 'package:universal_ble/src/universal_ble_platform_interface.dart';
@@ -95,8 +95,14 @@ class UniversalBleWeb extends UniversalBlePlatform {
}
@override
bool receivesAdvertisements(String deviceId) =>
_getDeviceById(deviceId)?.hasWatchAdvertisements() ?? false;
bool receivesAdvertisements(String deviceId) {
// Advertisements do not work on Linux/Web even with the "Experimental Web Platform features" flag enabled. Verified with Chrome Version 128.0.6613.138
if (kIsWeb && defaultTargetPlatform == TargetPlatform.linux) {
return false;
}
return _getDeviceById(deviceId)?.hasWatchAdvertisements() ?? false;
}
/// This will work only if `chrome://flags/#enable-experimental-web-platform-features` is enabled
Future<void> _watchDeviceAdvertisements(BluetoothDevice device) async {
@@ -342,22 +348,22 @@ class UniversalBleWeb extends UniversalBlePlatform {
RequestOptionsBuilder _getRequestOptionBuilder(
ScanFilter? scanFilter,
WebConfig? webConfig,
WebOptions? webOptions,
) {
List<RequestFilterBuilder> filters = [];
List<int> optionalManufacturerData = [];
List<String> optionalServices = [];
if (webConfig != null) {
optionalServices.addAll(webConfig.optionalServices.toValidUUIDList());
optionalManufacturerData.addAll(webConfig.optionalManufacturerData);
if (webOptions != null) {
optionalServices.addAll(webOptions.optionalServices.toValidUUIDList());
optionalManufacturerData.addAll(webOptions.optionalManufacturerData);
}
if (scanFilter != null) {
// Add services filter
for (var service in scanFilter.withServices.toValidUUIDList()) {
filters.add(RequestFilterBuilder(services: [service]));
if (webConfig == null || webConfig.optionalServices.isEmpty) {
if (webOptions == null || webOptions.optionalServices.isEmpty) {
optionalServices.add(service);
}
}
@@ -369,19 +375,16 @@ class UniversalBleWeb extends UniversalBlePlatform {
manufacturerData: [
ManufacturerDataFilterBuilder(
companyIdentifier: manufacturerData.companyIdentifier,
dataPrefix: manufacturerData.data,
dataPrefix: manufacturerData.payload,
mask: manufacturerData.mask,
),
],
),
);
// Add optionalManufacturerData from scanFilter if webConfig is not provided
if (webConfig == null || webConfig.optionalManufacturerData.isEmpty) {
int? companyId = manufacturerData.companyIdentifier;
if (companyId != null) {
optionalManufacturerData.add(companyId);
}
// Add optionalManufacturerData from scanFilter if webOptions is not provided
if (webOptions == null || webOptions.optionalManufacturerData.isEmpty) {
optionalManufacturerData.add(manufacturerData.companyIdentifier);
}
}
@@ -422,8 +425,7 @@ extension _BluetoothDeviceExtension on BluetoothDevice {
return BleDevice(
name: name,
deviceId: id,
manufacturerData: manufacturerDataMap?.toUint8List(),
manufacturerDataHead: manufacturerDataMap?.toUint8List(),
manufacturerDataList: manufacturerDataMap?.toManufacturerDataList() ?? [],
rssi: rssi,
services: services,
);
@@ -431,17 +433,10 @@ extension _BluetoothDeviceExtension on BluetoothDevice {
}
extension _UnmodifiableMapViewExtension on UnmodifiableMapView<int, ByteData> {
Uint8List? toUint8List() {
List<MapEntry<int, ByteData>> sorted = entries.toList()
..sort((a, b) => a.key - b.key);
if (sorted.isEmpty) return null;
int companyId = sorted.first.key;
List<int> manufacturerDataValue = sorted.first.value.buffer.asUint8List();
final byteData = ByteData(2);
byteData.setInt16(0, companyId, Endian.host);
List<int> bytes = byteData.buffer.asUint8List();
return Uint8List.fromList(bytes + manufacturerDataValue);
}
List<ManufacturerData>? toManufacturerDataList() => entries
.map((MapEntry<int, ByteData> data) =>
ManufacturerData(data.key, data.value.buffer.asUint8List()))
.toList();
}
class _UniversalWebBluetoothService {