feat: 5.0.0 (#35)
* draft: 临时提交 * feat: 实现扫描功能 * fix: 优化广播逻辑 * feat: 添加协程方法 * fix: 修改宏定义 * draft: 临时提交 * feat: 调整接口 * fix: 修改版本号 * feat: 4.1.1 * draft: 临时提交 * feat: 5.0.0-dev.2 * fix: 修复版本号错误 * draft: 临时提交 * fix: 修复连接断开异常 * fix: 修复问题 * fix: 优化代码 * fix: 优化 short UUID 格式化逻辑 * fix: 尝试实现 read_rssi 接口,当前此接口不可用,会报异常 * feat: 删除 getMaximumWriteLength 方法 * fix: 更新 CHANGELOG.md * feat: 5.0.0-dev.1 * fix: 更新依赖项 * feat: linux-5.0.0-dev.1 * fix: 更新 CHANGELOG.md * fix: 开始搜索设备时清空设备列表 * fix: 开始扫描时清空设备列表 * feat: 5.0.0-dev.2 * fix: 优化 MyGattService 和 MyGattCharacteristic * feat: 更新 interface 版本 -> 5.0.0-dev.4 * feat: 更新 interface 版本 -> 5.0.0-dev.4 * feat: 实现 flutter 部分 5.0.0 * fix: 移除 maximumWriteLength * fix: 移除 rssi * feat: 5.0.0-dev.1 * feat: 5.0.0-dev.2 * fix: 更新依赖项 * fix: 5.0.0-dev.4 * fix: 更新依赖项 * draft: 临时提交 * feat: 5.0.0-dev.5 * draft: 删除 MyCentralManager 和 MyPeripheralManager * fix: 更新依赖项 * fix: 更新依赖项 * feat: 适配新接口 * feat: 5.0.0-dev.6 * draft: 临时提交 * feat: 5.0.0-dev.7 * fix: 修改版本号 * feat: 5.0.0-dev.8 * feat: 5.0.0-dev.9 * fix: 修复 trimGATT 错误 * feat: 5.0.0-dev.6 * feat: 5.0.0-dev.3 * feat: 5.0.0-dev.4 * fix: 更新 pubspec.lock * feat: 5.0.0-dev.7 * feat: 5.0.0-dev.3 * fix: balabala * fix: balabala * draft: 5.0.0-dev.1 * fix: trim GATT when call the `writeCharacteristic` method. * fix: make difference of `trim` and `fragment`. * feat: 5.0.0-dev.1 * feat: 5.0.0-dev.1 * feat: 优化示例程序 * fix: 更新 README.md * fix: 修复插件引用 * draft: XXXX * feat: 增加调试信息 * fix: 更新 pubspec.lock * feat: 5.0.0-dev.4 * feat: 5.0.0-dev.3 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'src/my_central_manager_2.dart';
|
||||
import 'src/my_peripheral_manager_2.dart';
|
||||
import 'src/my_central_manager.dart';
|
||||
import 'src/my_peripheral_manager.dart';
|
||||
|
||||
abstract class BluetoothLowEnergyDarwin {
|
||||
static void registerWith() {
|
||||
MyCentralManager.instance = MyCentralManager2();
|
||||
MyPeripheralManager.instance = MyPeripheralManager2();
|
||||
CentralManager.instance = MyCentralManager();
|
||||
PeripheralManager.instance = MyPeripheralManager();
|
||||
}
|
||||
}
|
||||
|
@ -9,22 +9,51 @@ import 'my_gatt_service2.dart';
|
||||
|
||||
export 'my_api.g.dart';
|
||||
|
||||
// ToObject
|
||||
extension MyBluetoothLowEnergyStateArgsX on MyBluetoothLowEnergyStateArgs {
|
||||
BluetoothLowEnergyState toState() {
|
||||
return BluetoothLowEnergyState.values[index];
|
||||
switch (this) {
|
||||
case MyBluetoothLowEnergyStateArgs.unknown:
|
||||
case MyBluetoothLowEnergyStateArgs.resetting:
|
||||
return BluetoothLowEnergyState.unknown;
|
||||
case MyBluetoothLowEnergyStateArgs.unsupported:
|
||||
return BluetoothLowEnergyState.unsupported;
|
||||
case MyBluetoothLowEnergyStateArgs.unauthorized:
|
||||
return BluetoothLowEnergyState.unauthorized;
|
||||
case MyBluetoothLowEnergyStateArgs.poweredOff:
|
||||
return BluetoothLowEnergyState.poweredOff;
|
||||
case MyBluetoothLowEnergyStateArgs.poweredOn:
|
||||
return BluetoothLowEnergyState.poweredOn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicPropertyArgsX
|
||||
on MyGattCharacteristicPropertyArgs {
|
||||
GattCharacteristicProperty toProperty() {
|
||||
return GattCharacteristicProperty.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension MyManufacturerSpecificDataArgsX on MyManufacturerSpecificDataArgs {
|
||||
ManufacturerSpecificData toManufacturerSpecificData() {
|
||||
final id = idArgs;
|
||||
final data = dataArgs;
|
||||
return ManufacturerSpecificData(
|
||||
id: id,
|
||||
data: data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyAdvertisementArgsX on MyAdvertisementArgs {
|
||||
Advertisement toAdvertisement() {
|
||||
final name = nameArgs;
|
||||
final serviceUUIDs = serviceUUIDsArgs
|
||||
.cast<String>()
|
||||
.map((args) => UUID.fromString(args))
|
||||
.toList();
|
||||
final serviceUUIDs =
|
||||
serviceUUIDsArgs.cast<String>().map((args) => args.toUUID()).toList();
|
||||
final serviceData = serviceDataArgs.cast<String, Uint8List>().map(
|
||||
(uuidArgs, dataArgs) {
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final data = dataArgs;
|
||||
return MapEntry(uuid, data);
|
||||
},
|
||||
@ -40,61 +69,40 @@ extension MyAdvertisementArgsX on MyAdvertisementArgs {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyManufacturerSpecificDataArgsX on MyManufacturerSpecificDataArgs {
|
||||
ManufacturerSpecificData toManufacturerSpecificData() {
|
||||
final id = idArgs;
|
||||
final data = dataArgs;
|
||||
return ManufacturerSpecificData(
|
||||
id: id,
|
||||
data: data,
|
||||
extension MyCentralArgsX on MyCentralArgs {
|
||||
MyCentral toCentral() {
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyCentral(
|
||||
uuid: uuid,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicPropertyArgsX
|
||||
on MyGattCharacteristicPropertyArgs {
|
||||
GattCharacteristicProperty toProperty() {
|
||||
return GattCharacteristicProperty.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicWriteTypeX on GattCharacteristicWriteType {
|
||||
MyGattCharacteristicWriteTypeArgs toArgs() {
|
||||
return MyGattCharacteristicWriteTypeArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension MyPeripheralArgsX on MyPeripheralArgs {
|
||||
Peripheral toPeripheral() {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
MyPeripheral toPeripheral() {
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyPeripheral(
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattServiceArgsX on MyGattServiceArgs {
|
||||
MyGattService2 toService2() {
|
||||
extension MyGattDescriptorArgsX on MyGattDescriptorArgs {
|
||||
MyGattDescriptor2 toDescriptor2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final characteristics = characteristicsArgs
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map((args) => args.toCharacteristic2())
|
||||
.toList();
|
||||
return MyGattService2(
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyGattDescriptor2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
characteristics: characteristics,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
MyGattCharacteristic2 toCharacteristic2() {
|
||||
MyGattCharacteristic2 toCharacteristic2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final properties = propertyNumbersArgs.cast<int>().map(
|
||||
(args) {
|
||||
final propertyArgs = MyGattCharacteristicPropertyArgs.values[args];
|
||||
@ -103,9 +111,10 @@ extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
).toList();
|
||||
final descriptors = descriptorsArgs
|
||||
.cast<MyGattDescriptorArgs>()
|
||||
.map((args) => args.toDescriptor2())
|
||||
.map((args) => args.toDescriptor2(peripheral))
|
||||
.toList();
|
||||
return MyGattCharacteristic2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
properties: properties,
|
||||
@ -114,45 +123,39 @@ extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorArgsX on MyGattDescriptorArgs {
|
||||
MyGattDescriptor2 toDescriptor2() {
|
||||
extension MyGattServiceArgsX on MyGattServiceArgs {
|
||||
MyGattService2 toService2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
return MyGattDescriptor2(
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final characteristics = characteristicsArgs
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map((args) => args.toCharacteristic2(peripheral))
|
||||
.toList();
|
||||
return MyGattService2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
characteristics: characteristics,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyCentralArgsX on MyCentralArgs {
|
||||
MyCentral toCentral() {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
return MyCentral(
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
);
|
||||
extension MyUuidArgsX on String {
|
||||
UUID toUUID() {
|
||||
return UUID.fromString(this);
|
||||
}
|
||||
}
|
||||
|
||||
extension AdvertisementX on Advertisement {
|
||||
MyAdvertisementArgs toArgs() {
|
||||
final nameArgs = name;
|
||||
final serviceUUIDsArgs =
|
||||
serviceUUIDs.map((uuid) => uuid.toString()).toList();
|
||||
final serviceDataArgs = serviceData.map((uuid, data) {
|
||||
final uuidArgs = uuid.toString();
|
||||
final dataArgs = data;
|
||||
return MapEntry(uuidArgs, dataArgs);
|
||||
});
|
||||
final manufacturerSpecificDataArgs = manufacturerSpecificData?.toArgs();
|
||||
return MyAdvertisementArgs(
|
||||
nameArgs: nameArgs,
|
||||
serviceUUIDsArgs: serviceUUIDsArgs,
|
||||
serviceDataArgs: serviceDataArgs,
|
||||
manufacturerSpecificDataArgs: manufacturerSpecificDataArgs,
|
||||
);
|
||||
// ToArgs
|
||||
extension GattCharacteristicPropertyX on GattCharacteristicProperty {
|
||||
MyGattCharacteristicPropertyArgs toArgs() {
|
||||
return MyGattCharacteristicPropertyArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicWriteTypeX on GattCharacteristicWriteType {
|
||||
MyGattCharacteristicWriteTypeArgs toArgs() {
|
||||
return MyGattCharacteristicWriteTypeArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,18 +170,34 @@ extension ManufacturerSpecificDataX on ManufacturerSpecificData {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattServiceX on MyGattService {
|
||||
MyGattServiceArgs toArgs() {
|
||||
extension AdvertisementX on Advertisement {
|
||||
MyAdvertisementArgs toArgs() {
|
||||
final nameArgs = name;
|
||||
final serviceUUIDsArgs = serviceUUIDs.map((uuid) => uuid.toArgs()).toList();
|
||||
final serviceDataArgs = serviceData.map((uuid, data) {
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final dataArgs = data;
|
||||
return MapEntry(uuidArgs, dataArgs);
|
||||
});
|
||||
final manufacturerSpecificDataArgs = manufacturerSpecificData?.toArgs();
|
||||
return MyAdvertisementArgs(
|
||||
nameArgs: nameArgs,
|
||||
serviceUUIDsArgs: serviceUUIDsArgs,
|
||||
serviceDataArgs: serviceDataArgs,
|
||||
manufacturerSpecificDataArgs: manufacturerSpecificDataArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorX on MyGattDescriptor {
|
||||
MyGattDescriptorArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final characteristicsArgs = characteristics
|
||||
.cast<MyGattCharacteristic>()
|
||||
.map((characteristic) => characteristic.toArgs())
|
||||
.toList();
|
||||
return MyGattServiceArgs(
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final valueArgs = value;
|
||||
return MyGattDescriptorArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
characteristicsArgs: characteristicsArgs,
|
||||
valueArgs: valueArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -186,7 +205,7 @@ extension MyGattServiceX on MyGattService {
|
||||
extension MyGattCharacteristicX on MyGattCharacteristic {
|
||||
MyGattCharacteristicArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final propertyNumbersArgs = properties.map((property) {
|
||||
final propertyArgs = property.toArgs();
|
||||
return propertyArgs.index;
|
||||
@ -204,21 +223,24 @@ extension MyGattCharacteristicX on MyGattCharacteristic {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorX on MyGattDescriptor {
|
||||
MyGattDescriptorArgs toArgs() {
|
||||
extension MyGattServiceX on MyGattService {
|
||||
MyGattServiceArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final valueArgs = value;
|
||||
return MyGattDescriptorArgs(
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final characteristicsArgs = characteristics
|
||||
.cast<MyGattCharacteristic>()
|
||||
.map((characteristic) => characteristic.toArgs())
|
||||
.toList();
|
||||
return MyGattServiceArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
valueArgs: valueArgs,
|
||||
characteristicsArgs: characteristicsArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicPropertyX on GattCharacteristicProperty {
|
||||
MyGattCharacteristicPropertyArgs toArgs() {
|
||||
return MyGattCharacteristicPropertyArgs.values[index];
|
||||
extension UuidX on UUID {
|
||||
String toArgs() {
|
||||
return toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
331
bluetooth_low_energy_darwin/lib/src/my_central_manager.dart
Normal file
331
bluetooth_low_energy_darwin/lib/src/my_central_manager.dart
Normal file
@ -0,0 +1,331 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
|
||||
class MyCentralManager extends CentralManager
|
||||
implements MyCentralManagerFlutterApi {
|
||||
final MyCentralManagerHostApi _api;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<DiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<ConnectionStateChangedEventArgs>
|
||||
_connectionStateChangedController;
|
||||
final StreamController<GattCharacteristicNotifiedEventArgs>
|
||||
_characteristicNotifiedController;
|
||||
final Map<String, MyPeripheral> _peripherals;
|
||||
final Map<String, Map<int, MyGattCharacteristic2>> _characteristics;
|
||||
|
||||
BluetoothLowEnergyState _state;
|
||||
|
||||
MyCentralManager()
|
||||
: _api = MyCentralManagerHostApi(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_connectionStateChangedController = StreamController.broadcast(),
|
||||
_characteristicNotifiedController = StreamController.broadcast(),
|
||||
_peripherals = {},
|
||||
_characteristics = {},
|
||||
_state = BluetoothLowEnergyState.unknown;
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<DiscoveredEventArgs> get discovered => _discoveredController.stream;
|
||||
@override
|
||||
Stream<ConnectionStateChangedEventArgs> get connectionStateChanged =>
|
||||
_connectionStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicNotifiedEventArgs> get characteristicNotified =>
|
||||
_characteristicNotifiedController.stream;
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
logger.info('setUp');
|
||||
await _api.setUp();
|
||||
MyCentralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BluetoothLowEnergyState> getState() {
|
||||
logger.info('getState');
|
||||
return Future.value(_state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
logger.info('startDiscovery');
|
||||
await _api.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
logger.info('stopDiscovery');
|
||||
await _api.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('connect: $uuidArgs');
|
||||
await _api.connect(uuidArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('disconnect: $uuidArgs');
|
||||
await _api.disconnect(uuidArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> readRSSI(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('readRSSI: $uuidArgs');
|
||||
final rssi = await _api.readRSSI(uuidArgs);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> discoverGATT(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
// 发现 GATT 服务
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('discoverServices: $uuidArgs');
|
||||
final servicesArgs = await _api
|
||||
.discoverServices(uuidArgs)
|
||||
.then((args) => args.cast<MyGattServiceArgs>());
|
||||
for (var serviceArgs in servicesArgs) {
|
||||
// 发现 GATT 特征值
|
||||
final hashCodeArgs = serviceArgs.hashCodeArgs;
|
||||
logger.info('discoverCharacteristics: $uuidArgs.$hashCodeArgs');
|
||||
final characteristicsArgs = await _api
|
||||
.discoverCharacteristics(uuidArgs, hashCodeArgs)
|
||||
.then((args) => args.cast<MyGattCharacteristicArgs>());
|
||||
for (var characteristicArgs in characteristicsArgs) {
|
||||
// 发现 GATT 描述值
|
||||
final hashCodeArgs = characteristicArgs.hashCodeArgs;
|
||||
logger.info('discoverDescriptors: $uuidArgs.$hashCodeArgs');
|
||||
final descriptorsArgs = await _api
|
||||
.discoverDescriptors(uuidArgs, hashCodeArgs)
|
||||
.then((args) => args.cast<MyGattDescriptorArgs>());
|
||||
characteristicArgs.descriptorsArgs = descriptorsArgs;
|
||||
}
|
||||
serviceArgs.characteristicsArgs = characteristicsArgs;
|
||||
}
|
||||
final services =
|
||||
servicesArgs.map((args) => args.toService2(peripheral)).toList();
|
||||
final characteristics =
|
||||
services.expand((service) => service.characteristics).toList();
|
||||
_characteristics[uuidArgs] = {
|
||||
for (var characteristic in characteristics)
|
||||
characteristic.hashCode: characteristic
|
||||
};
|
||||
return services;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
logger.info('readCharacteristic: $uuidArgs.$hashCodeArgs');
|
||||
final value = await _api.readCharacteristic(uuidArgs, hashCodeArgs);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final trimmedValueArgs = value.trimGATT();
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
final fragmentSize = await _api.getMaximumWriteValueLength(
|
||||
uuidArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
var start = 0;
|
||||
while (start < trimmedValueArgs.length) {
|
||||
final end = start + fragmentSize;
|
||||
final fragmentedValueArgs = end < trimmedValueArgs.length
|
||||
? trimmedValueArgs.sublist(start, end)
|
||||
: trimmedValueArgs.sublist(start);
|
||||
logger.info(
|
||||
'writeCharacteristic: $uuidArgs.$hashCodeArgs - $fragmentedValueArgs, $typeArgs');
|
||||
await _api.writeCharacteristic(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
fragmentedValueArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setCharacteristicNotifyState(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final stateArgs = state;
|
||||
logger.info(
|
||||
'setCharacteristicNotifyState: $uuidArgs.$hashCodeArgs - $stateArgs');
|
||||
await _api.setCharacteristicNotifyState(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
stateArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = descriptor.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = descriptor.hashCode;
|
||||
logger.info('readDescriptor: $uuidArgs.$hashCodeArgs');
|
||||
final value = await _api.readDescriptor(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = descriptor.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = descriptor.hashCode;
|
||||
final trimmedValueArgs = value.trimGATT();
|
||||
logger.info('writeDescriptor: $uuidArgs.$hashCodeArgs - $trimmedValueArgs');
|
||||
await _api.writeDescriptor(uuidArgs, hashCodeArgs, trimmedValueArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
logger.info('onStateChanged: $stateArgs');
|
||||
final state = stateArgs.toState();
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
) {
|
||||
final uuidArgs = peripheralArgs.uuidArgs;
|
||||
logger.info('onDiscovered: $uuidArgs - $rssiArgs, $advertisementArgs');
|
||||
final peripheral = _peripherals.putIfAbsent(
|
||||
peripheralArgs.uuidArgs,
|
||||
() => peripheralArgs.toPeripheral(),
|
||||
);
|
||||
final rssi = rssiArgs;
|
||||
final advertisement = advertisementArgs.toAdvertisement();
|
||||
final eventArgs = DiscoveredEventArgs(
|
||||
peripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onConnectionStateChanged(
|
||||
String uuidArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
logger.info('onConnectionStateChanged: $uuidArgs - $stateArgs');
|
||||
final peripheral = _peripherals[uuidArgs];
|
||||
if (peripheral == null) {
|
||||
return;
|
||||
}
|
||||
final state = stateArgs;
|
||||
final eventArgs = ConnectionStateChangedEventArgs(peripheral, state);
|
||||
_connectionStateChangedController.add(eventArgs);
|
||||
if (!state) {
|
||||
_characteristics.remove(uuidArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicNotified(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
logger
|
||||
.info('onCharacteristicNotified: $uuidArgs.$hashCodeArgs - $valueArgs');
|
||||
final characteristic = _retrieveCharacteristic(uuidArgs, hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
final value = valueArgs;
|
||||
final eventArgs = GattCharacteristicNotifiedEventArgs(
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicNotifiedController.add(eventArgs);
|
||||
}
|
||||
|
||||
MyGattCharacteristic2? _retrieveCharacteristic(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
) {
|
||||
final characteristics = _characteristics[uuidArgs];
|
||||
if (characteristics == null) {
|
||||
return null;
|
||||
}
|
||||
return characteristics[hashCodeArgs];
|
||||
}
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
|
||||
class MyCentralManager2 extends MyCentralManager
|
||||
implements MyCentralManagerFlutterApi {
|
||||
final MyCentralManagerHostApi _api;
|
||||
BluetoothLowEnergyState _state;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<DiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<PeripheralStateChangedEventArgs>
|
||||
_peripheralStateChangedController;
|
||||
final StreamController<GattCharacteristicValueChangedEventArgs>
|
||||
_characteristicValueChangedController;
|
||||
|
||||
MyCentralManager2()
|
||||
: _api = MyCentralManagerHostApi(),
|
||||
_state = BluetoothLowEnergyState.unknown,
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_peripheralStateChangedController = StreamController.broadcast(),
|
||||
_characteristicValueChangedController = StreamController.broadcast();
|
||||
|
||||
@override
|
||||
BluetoothLowEnergyState get state => _state;
|
||||
@protected
|
||||
set state(BluetoothLowEnergyState value) {
|
||||
if (_state == value) {
|
||||
return;
|
||||
}
|
||||
_state = value;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<DiscoveredEventArgs> get discovered => _discoveredController.stream;
|
||||
@override
|
||||
Stream<PeripheralStateChangedEventArgs> get peripheralStateChanged =>
|
||||
_peripheralStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged =>
|
||||
_characteristicValueChangedController.stream;
|
||||
|
||||
Future<void> _throwWithoutState(BluetoothLowEnergyState state) async {
|
||||
if (this.state != state) {
|
||||
throw StateError(
|
||||
'$state is expected, but current state is ${this.state}.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
final args = await _api.setUp();
|
||||
final stateArgs =
|
||||
MyBluetoothLowEnergyStateArgs.values[args.stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
MyCentralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
await _api.connect(peripheralHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
await _api.disconnect(peripheralHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getMaximumWriteLength(
|
||||
Peripheral peripheral, {
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
final maximumWriteLength = await _api.getMaximumWriteLength(
|
||||
peripheralHashCodeArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
return maximumWriteLength;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> readRSSI(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final rssi = await _api.readRSSI(peripheralHashCodeArgs);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> discoverGATT(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final servicesArgs = await _api.discoverGATT(peripheralHashCodeArgs);
|
||||
final services = servicesArgs
|
||||
.cast<MyGattServiceArgs>()
|
||||
.map((args) => args.toService2())
|
||||
.toList();
|
||||
for (var service in services) {
|
||||
for (var charactersitic in service.characteristics) {
|
||||
for (var descriptor in charactersitic.descriptors) {
|
||||
descriptor.characteristic = charactersitic;
|
||||
}
|
||||
charactersitic.service = service;
|
||||
}
|
||||
service.peripheral = peripheral;
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final value = await _api.readCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final valueArgs = value;
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
await _api.writeCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
valueArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final stateArgs = state;
|
||||
await _api.notifyCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
stateArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final characteristic = descriptor.characteristic;
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final descriptorHashCodeArgs = descriptor.hashCode;
|
||||
final value = await _api.readDescriptor(
|
||||
peripheralHashCodeArgs,
|
||||
descriptorHashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final characteristic = descriptor.characteristic;
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final descriptorHashCodeArgs = descriptor.hashCode;
|
||||
final valueArgs = value;
|
||||
await _api.writeDescriptor(
|
||||
peripheralHashCodeArgs,
|
||||
descriptorHashCodeArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
}
|
||||
|
||||
@override
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
) {
|
||||
final peripheral = peripheralArgs.toPeripheral();
|
||||
final rssi = rssiArgs;
|
||||
final advertisement = advertisementArgs.toAdvertisement();
|
||||
final eventArgs = DiscoveredEventArgs(
|
||||
peripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onPeripheralStateChanged(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final peripheral = peripheralArgs.toPeripheral();
|
||||
final state = stateArgs;
|
||||
final eventArgs = PeripheralStateChangedEventArgs(peripheral, state);
|
||||
_peripheralStateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicValueChanged(
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final value = valueArgs;
|
||||
final eventArgs = GattCharacteristicValueChangedEventArgs(
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicValueChangedController.add(eventArgs);
|
||||
}
|
||||
}
|
@ -1,13 +1,15 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
import 'my_gatt_service2.dart';
|
||||
|
||||
class MyGattCharacteristic2 extends MyGattCharacteristic {
|
||||
late final MyGattService2 service;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattCharacteristic2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
required super.properties,
|
||||
required List<MyGattDescriptor2> descriptors,
|
||||
@ -16,4 +18,11 @@ class MyGattCharacteristic2 extends MyGattCharacteristic {
|
||||
@override
|
||||
List<MyGattDescriptor2> get descriptors =>
|
||||
super.descriptors.cast<MyGattDescriptor2>();
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattCharacteristic2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,20 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
|
||||
class MyGattDescriptor2 extends MyGattDescriptor {
|
||||
late final MyGattCharacteristic2 characteristic;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattDescriptor2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattDescriptor2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,13 @@ import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_pla
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
|
||||
class MyGattService2 extends MyGattService {
|
||||
late final MyPeripheral peripheral;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattService2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
required List<MyGattCharacteristic2> characteristics,
|
||||
}) : super(characteristics: characteristics);
|
||||
@ -14,4 +17,11 @@ class MyGattService2 extends MyGattService {
|
||||
@override
|
||||
List<MyGattCharacteristic2> get characteristics =>
|
||||
super.characteristics.cast<MyGattCharacteristic2>();
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattService2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
315
bluetooth_low_energy_darwin/lib/src/my_peripheral_manager.dart
Normal file
315
bluetooth_low_energy_darwin/lib/src/my_peripheral_manager.dart
Normal file
@ -0,0 +1,315 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
|
||||
class MyPeripheralManager extends PeripheralManager
|
||||
implements MyPeripheralManagerFlutterApi {
|
||||
final MyPeripheralManagerHostApi _api;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<GattCharacteristicReadEventArgs>
|
||||
_characteristicReadController;
|
||||
final StreamController<GattCharacteristicWrittenEventArgs>
|
||||
_characteristicWrittenController;
|
||||
final StreamController<GattCharacteristicNotifyStateChangedEventArgs>
|
||||
_characteristicNotifyStateChangedController;
|
||||
|
||||
final Map<int, Map<int, MyGattCharacteristic>> _characteristics;
|
||||
final Map<String, Map<int, bool>> _listeners;
|
||||
|
||||
BluetoothLowEnergyState _state;
|
||||
|
||||
MyPeripheralManager()
|
||||
: _api = MyPeripheralManagerHostApi(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_characteristicReadController = StreamController.broadcast(),
|
||||
_characteristicWrittenController = StreamController.broadcast(),
|
||||
_characteristicNotifyStateChangedController =
|
||||
StreamController.broadcast(),
|
||||
_characteristics = {},
|
||||
_listeners = {},
|
||||
_state = BluetoothLowEnergyState.unknown;
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicReadEventArgs> get characteristicRead =>
|
||||
_characteristicReadController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicWrittenEventArgs> get characteristicWritten =>
|
||||
_characteristicWrittenController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicNotifyStateChangedEventArgs>
|
||||
get characteristicNotifyStateChanged =>
|
||||
_characteristicNotifyStateChangedController.stream;
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
logger.info('setUp');
|
||||
await _api.setUp();
|
||||
MyPeripheralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BluetoothLowEnergyState> getState() {
|
||||
logger.info('getState');
|
||||
return Future.value(_state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addService(GattService service) async {
|
||||
if (service is! MyGattService) {
|
||||
throw TypeError();
|
||||
}
|
||||
final serviceArgs = service.toArgs();
|
||||
final hashCodeArgs = serviceArgs.hashCodeArgs;
|
||||
logger.info('addService: $hashCodeArgs');
|
||||
await _api.addService(serviceArgs);
|
||||
_characteristics[hashCodeArgs] = {
|
||||
for (var characteristics in service.characteristics)
|
||||
characteristics.hashCode: characteristics
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeService(GattService service) async {
|
||||
final hashCodeArgs = service.hashCode;
|
||||
logger.info('removeService: $hashCodeArgs');
|
||||
await _api.removeService(hashCodeArgs);
|
||||
_characteristics.remove(hashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearServices() async {
|
||||
logger.info('clearServices');
|
||||
await _api.clearServices();
|
||||
_characteristics.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startAdvertising(Advertisement advertisement) async {
|
||||
final advertisementArgs = advertisement.toArgs();
|
||||
logger.info('startAdvertising: $advertisementArgs');
|
||||
await _api.startAdvertising(advertisementArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopAdvertising() async {
|
||||
logger.info('stopAdvertising');
|
||||
await _api.stopAdvertising();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(GattCharacteristic characteristic) {
|
||||
if (characteristic is! MyGattCharacteristic) {
|
||||
throw TypeError();
|
||||
}
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
logger.info('readCharacteristic: $hashCodeArgs');
|
||||
final value = characteristic.value;
|
||||
return Future.value(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
Central? central,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic) {
|
||||
throw TypeError();
|
||||
}
|
||||
characteristic.value = value;
|
||||
if (central == null) {
|
||||
return;
|
||||
}
|
||||
if (central is! MyCentral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = central.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final listener = _retrieveListener(uuidArgs, hashCodeArgs);
|
||||
if (listener == null) {
|
||||
logger.warning('The central is not listening.');
|
||||
return;
|
||||
}
|
||||
final uuidsArgs = [uuidArgs];
|
||||
final trimmedValueArgs = characteristic.value;
|
||||
final fragmentSize = await _api.getMaximumUpdateValueLength(uuidArgs);
|
||||
var start = 0;
|
||||
while (start < trimmedValueArgs.length) {
|
||||
final end = start + fragmentSize;
|
||||
final fragmentedValueArgs = end < trimmedValueArgs.length
|
||||
? trimmedValueArgs.sublist(start, end)
|
||||
: trimmedValueArgs.sublist(start);
|
||||
logger.info(
|
||||
'notifyCharacteristicChanged: $hashCodeArgs - $fragmentedValueArgs, $uuidsArgs');
|
||||
await _api.updateCharacteristic(
|
||||
hashCodeArgs,
|
||||
fragmentedValueArgs,
|
||||
uuidsArgs,
|
||||
);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
logger.info('onStateChanged: $stateArgs');
|
||||
final state = stateArgs.toState();
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicReadRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
) async {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicReadRequest: $uuidArgs.$hashCodeArgs - $idArgs, $offsetArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
const errorArgs = MyGattErrorArgs.success;
|
||||
final offset = offsetArgs;
|
||||
final valueArgs = _onCharacteristicRead(central, characteristic, offset);
|
||||
await _tryRespond(
|
||||
idArgs,
|
||||
errorArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicWriteRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
) async {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicWriteRequest: $uuidArgs.$hashCodeArgs - $idArgs, $offsetArgs, $valueArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
const errorArgs = MyGattErrorArgs.success;
|
||||
final value = valueArgs;
|
||||
_onCharacteristicWritten(central, characteristic, value);
|
||||
await _tryRespond(
|
||||
idArgs,
|
||||
errorArgs,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicNotifyStateChanged(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicNotifyStateChanged: $uuidArgs.$hashCodeArgs - $stateArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
final state = stateArgs;
|
||||
final listeners = _listeners.putIfAbsent(uuidArgs, () => {});
|
||||
if (state) {
|
||||
listeners[hashCodeArgs] = true;
|
||||
} else {
|
||||
listeners.remove(hashCodeArgs);
|
||||
}
|
||||
final eventArgs = GattCharacteristicNotifyStateChangedEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
state,
|
||||
);
|
||||
_characteristicNotifyStateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
MyGattCharacteristic? _retrieveCharacteristic(int hashCodeArgs) {
|
||||
final characteristics = _characteristics.values
|
||||
.reduce((value, element) => value..addAll(element));
|
||||
return characteristics[hashCodeArgs];
|
||||
}
|
||||
|
||||
bool? _retrieveListener(String uuidArgs, int hashCodeArgs) {
|
||||
final listeners = _listeners[uuidArgs];
|
||||
if (listeners == null) {
|
||||
return null;
|
||||
}
|
||||
return listeners[hashCodeArgs];
|
||||
}
|
||||
|
||||
Future<void> _tryRespond(
|
||||
int idArgs,
|
||||
MyGattErrorArgs errorArgs,
|
||||
Uint8List? valueArgs,
|
||||
) async {
|
||||
final errorNumberArgs = errorArgs.index;
|
||||
try {
|
||||
_api.respond(
|
||||
idArgs,
|
||||
errorNumberArgs,
|
||||
valueArgs,
|
||||
);
|
||||
} catch (e, stack) {
|
||||
logger.shout('Respond failed.', e, stack);
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List _onCharacteristicRead(
|
||||
MyCentral central,
|
||||
MyGattCharacteristic characteristic,
|
||||
int offset,
|
||||
) {
|
||||
final value = characteristic.value;
|
||||
final trimmedValue = value.sublist(offset);
|
||||
if (offset == 0) {
|
||||
final eventArgs = GattCharacteristicReadEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicReadController.add(eventArgs);
|
||||
}
|
||||
return trimmedValue;
|
||||
}
|
||||
|
||||
void _onCharacteristicWritten(
|
||||
MyCentral central,
|
||||
MyGattCharacteristic characteristic,
|
||||
Uint8List value,
|
||||
) async {
|
||||
final trimmedValue = value.trimGATT();
|
||||
final eventArgs = GattCharacteristicWrittenEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
trimmedValue,
|
||||
);
|
||||
_characteristicWrittenController.add(eventArgs);
|
||||
}
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
|
||||
class MyPeripheralManager2 extends MyPeripheralManager
|
||||
implements MyPeripheralManagerFlutterApi {
|
||||
final MyPeripheralManagerHostApi _api;
|
||||
BluetoothLowEnergyState _state;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<ReadGattCharacteristicCommandEventArgs>
|
||||
_readCharacteristicCommandReceivedController;
|
||||
final StreamController<WriteGattCharacteristicCommandEventArgs>
|
||||
_writeCharacteristicCommandReceivedController;
|
||||
final StreamController<NotifyGattCharacteristicCommandEventArgs>
|
||||
_notifyCharacteristicCommandReceivedController;
|
||||
|
||||
MyPeripheralManager2()
|
||||
: _api = MyPeripheralManagerHostApi(),
|
||||
_state = BluetoothLowEnergyState.unknown,
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_readCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast(),
|
||||
_writeCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast(),
|
||||
_notifyCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast();
|
||||
|
||||
@override
|
||||
BluetoothLowEnergyState get state => _state;
|
||||
@protected
|
||||
set state(BluetoothLowEnergyState value) {
|
||||
if (_state == value) {
|
||||
return;
|
||||
}
|
||||
_state = value;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<ReadGattCharacteristicCommandEventArgs>
|
||||
get readCharacteristicCommandReceived =>
|
||||
_readCharacteristicCommandReceivedController.stream;
|
||||
@override
|
||||
Stream<WriteGattCharacteristicCommandEventArgs>
|
||||
get writeCharacteristicCommandReceived =>
|
||||
_writeCharacteristicCommandReceivedController.stream;
|
||||
@override
|
||||
Stream<NotifyGattCharacteristicCommandEventArgs>
|
||||
get notifyCharacteristicCommandReceived =>
|
||||
_notifyCharacteristicCommandReceivedController.stream;
|
||||
|
||||
Future<void> _throwWithoutState(BluetoothLowEnergyState state) async {
|
||||
if (this.state != state) {
|
||||
throw StateError(
|
||||
'$state is expected, but current state is ${this.state}.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
final args = await _api.setUp();
|
||||
final stateArgs =
|
||||
MyBluetoothLowEnergyStateArgs.values[args.stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
MyPeripheralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addService(GattService service) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (service is! MyGattService) {
|
||||
throw TypeError();
|
||||
}
|
||||
final serviceArgs = service.toArgs();
|
||||
await _api.addService(serviceArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeService(GattService service) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final serviceHashCodeArgs = service.hashCode;
|
||||
await _api.removeService(serviceHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearServices() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.clearServices();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startAdvertising(Advertisement advertisement) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final advertisementArgs = advertisement.toArgs();
|
||||
await _api.startAdvertising(advertisementArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopAdvertising() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.stopAdvertising();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getMaximumWriteLength(Central central) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final maximumWriteLength =
|
||||
await _api.getMaximumWriteLength(centralHashCodeArgs);
|
||||
return maximumWriteLength;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendReadCharacteristicReply(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required int id,
|
||||
required int offset,
|
||||
required bool status,
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final idArgs = id;
|
||||
final offsetArgs = offset;
|
||||
final statusArgs = status;
|
||||
final valueArgs = value;
|
||||
await _api.sendReadCharacteristicReply(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
idArgs,
|
||||
offsetArgs,
|
||||
statusArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendWriteCharacteristicReply(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required int id,
|
||||
required int offset,
|
||||
required bool status,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final idArgs = id;
|
||||
final offsetArgs = offset;
|
||||
final statusArgs = status;
|
||||
await _api.sendWriteCharacteristicReply(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
idArgs,
|
||||
offsetArgs,
|
||||
statusArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristicValueChanged(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final valueArgs = value;
|
||||
await _api.notifyCharacteristicValueChanged(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReadCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final id = idArgs;
|
||||
final offset = offsetArgs;
|
||||
final eventArgs = ReadGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
id,
|
||||
offset,
|
||||
);
|
||||
_readCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onWriteCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final id = idArgs;
|
||||
final offset = offsetArgs;
|
||||
final value = valueArgs;
|
||||
final eventArgs = WriteGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
id,
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
_writeCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onNotifyCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final state = stateArgs;
|
||||
final eventArgs = NotifyGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
state,
|
||||
);
|
||||
_notifyCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user