feat: 重构项目 2.0.0 (#6)
* feat: 重构项目 * feat: 添加 bluez_central_manager * feat: 联合插件 * feat: 拆分项目 * feat: 实现 linux 部分接口 * feat: 重新创建项目 * feat: 定义接口 * feat: 实现接入插件 * feat: 清空接入插件示例代码 * feat: 开发 linux 插件 * feat: 调整接口 * 临时提交 * feat: 实现 Android 接口 * fix: 修复 Android 问题 * fix: 移除多余文件 * feat: 重构项目 (#5) * fix: 移除多余的状态判断 * fix: 外围设备断开时检查是否存在未完成的操作 * feat: 尝试使用 win32 实现接口 * fix: 修复大小写问题 * feat: 实现 macOS 接口 * feat: 实现 macOS 接口 * fix:支持使用16位短字符串生成UUID * fix: 修复未清理已完成操作的问题 * fix: 规范命名 * 添加蓝牙使用描述 * fix: 更新 README.md
This commit is contained in:
30
bluetooth_low_energy_linux/.gitignore
vendored
Normal file
30
bluetooth_low_energy_linux/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
30
bluetooth_low_energy_linux/.metadata
Normal file
30
bluetooth_low_energy_linux/.metadata
Normal file
@ -0,0 +1,30 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
channel: stable
|
||||
|
||||
project_type: plugin
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
- platform: linux
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
4
bluetooth_low_energy_linux/CHANGELOG.md
Normal file
4
bluetooth_low_energy_linux/CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
- Support macOS and Linux.
|
21
bluetooth_low_energy_linux/LICENSE
Normal file
21
bluetooth_low_energy_linux/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 yanshouwang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
15
bluetooth_low_energy_linux/README.md
Normal file
15
bluetooth_low_energy_linux/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# bluetooth_low_energy_linux
|
||||
|
||||
The Linux implementation of [`bluetooth_low_energy`][1].
|
||||
|
||||
## Usage
|
||||
|
||||
This package is [endorsed][2], which means you can simply use `bluetooth_low_energy`
|
||||
normally. This package will be automatically included in your app when you do,
|
||||
so you do not need to add it to your `pubspec.yaml`.
|
||||
|
||||
However, if you `import` this package to use any of its APIs directly, you
|
||||
should add it to your `pubspec.yaml` as usual.
|
||||
|
||||
[1]: https://pub.dev/packages/bluetooth_low_energy
|
||||
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
|
4
bluetooth_low_energy_linux/analysis_options.yaml
Normal file
4
bluetooth_low_energy_linux/analysis_options.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
@ -0,0 +1,9 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'src/my_central_controller.dart';
|
||||
|
||||
abstract class BluetoothLowEnergyLinux {
|
||||
static void registerWith() {
|
||||
CentralController.instance = MyCentralController();
|
||||
}
|
||||
}
|
81
bluetooth_low_energy_linux/lib/src/my_bluez.dart
Normal file
81
bluetooth_low_energy_linux/lib/src/my_bluez.dart
Normal file
@ -0,0 +1,81 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
extension MyBlueZAdapter on BlueZAdapter {
|
||||
CentralState get state {
|
||||
return powered ? CentralState.poweredOn : CentralState.poweredOff;
|
||||
}
|
||||
}
|
||||
|
||||
extension MyBlueZDevice on BlueZDevice {
|
||||
BlueZUUID get uuid {
|
||||
final node = address.replaceAll(':', '');
|
||||
// We don't know the timestamp of the bluetooth device, use nil UUID as prefix.
|
||||
return BlueZUUID.fromString("00000000-0000-0000-$node");
|
||||
}
|
||||
|
||||
Advertisement get advertisement {
|
||||
final manufacturerSpecificData = manufacturerData.map((key, value) {
|
||||
final id = key.id;
|
||||
final data = Uint8List.fromList(value);
|
||||
return MapEntry(id, data);
|
||||
});
|
||||
final serviceUUIDs = uuids.map((uuid) => uuid.toUUID()).toList();
|
||||
final serviceData = this.serviceData.map((uuid, data) {
|
||||
final key = uuid.toUUID();
|
||||
final value = Uint8List.fromList(data);
|
||||
return MapEntry(key, value);
|
||||
});
|
||||
return Advertisement(
|
||||
name: name,
|
||||
manufacturerSpecificData: manufacturerSpecificData,
|
||||
serviceUUIDs: serviceUUIDs,
|
||||
serviceData: serviceData,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyBlueZUUID on BlueZUUID {
|
||||
UUID toUUID() => UUID(value);
|
||||
}
|
||||
|
||||
extension MyBlueZGattCharacteristic on BlueZGattCharacteristic {
|
||||
List<GattCharacteristicProperty> get properties => flags
|
||||
.map((e) => e.toProperty())
|
||||
.whereType<GattCharacteristicProperty>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
extension MyBlueZGattCharacteristicFlag on BlueZGattCharacteristicFlag {
|
||||
GattCharacteristicProperty? toProperty() {
|
||||
switch (this) {
|
||||
case BlueZGattCharacteristicFlag.read:
|
||||
return GattCharacteristicProperty.read;
|
||||
case BlueZGattCharacteristicFlag.write:
|
||||
return GattCharacteristicProperty.write;
|
||||
case BlueZGattCharacteristicFlag.writeWithoutResponse:
|
||||
return GattCharacteristicProperty.writeWithoutResponse;
|
||||
case BlueZGattCharacteristicFlag.notify:
|
||||
return GattCharacteristicProperty.notify;
|
||||
case BlueZGattCharacteristicFlag.indicate:
|
||||
return GattCharacteristicProperty.indicate;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicWriteType on GattCharacteristicWriteType {
|
||||
BlueZGattCharacteristicWriteType toBlueZ() {
|
||||
switch (this) {
|
||||
case GattCharacteristicWriteType.withResponse:
|
||||
return BlueZGattCharacteristicWriteType.request;
|
||||
case GattCharacteristicWriteType.withoutResponse:
|
||||
return BlueZGattCharacteristicWriteType.command;
|
||||
default:
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
}
|
426
bluetooth_low_energy_linux/lib/src/my_central_controller.dart
Normal file
426
bluetooth_low_energy_linux/lib/src/my_central_controller.dart
Normal file
@ -0,0 +1,426 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
import 'my_bluez.dart';
|
||||
import 'my_gatt_characteristic.dart';
|
||||
import 'my_gatt_descriptor.dart';
|
||||
import 'my_gatt_service.dart';
|
||||
import 'my_peripheral.dart';
|
||||
|
||||
class MyCentralController extends CentralController {
|
||||
MyCentralController()
|
||||
: _client = BlueZClient(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_peripheralStateChangedController = StreamController.broadcast(),
|
||||
_characteristicValueChangedController = StreamController.broadcast(),
|
||||
_servicesResolvedController = StreamController.broadcast(),
|
||||
_devicePropertiesChangedSubscriptions = {},
|
||||
_characteristicPropertiesChangedSubscriptions = {},
|
||||
_myPeripherals = {},
|
||||
_myServices = {},
|
||||
_myCharacteristics = {},
|
||||
_myDescriptors = {},
|
||||
_state = CentralState.unknown;
|
||||
|
||||
final BlueZClient _client;
|
||||
final StreamController<CentralStateChangedEventArgs> _stateChangedController;
|
||||
final StreamController<CentralDiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<PeripheralStateChangedEventArgs>
|
||||
_peripheralStateChangedController;
|
||||
final StreamController<GattCharacteristicValueChangedEventArgs>
|
||||
_characteristicValueChangedController;
|
||||
final StreamController<int> _servicesResolvedController;
|
||||
final Map<int, StreamSubscription<List<String>>>
|
||||
_devicePropertiesChangedSubscriptions;
|
||||
final Map<int, StreamSubscription<List<String>>>
|
||||
_characteristicPropertiesChangedSubscriptions;
|
||||
final Map<int, MyPeripheral> _myPeripherals;
|
||||
final Map<int, MyGattService> _myServices;
|
||||
final Map<int, MyGattCharacteristic> _myCharacteristics;
|
||||
final Map<int, MyGattDescriptor> _myDescriptors;
|
||||
|
||||
BlueZAdapter get _adapter => _client.adapters.first;
|
||||
CentralState _state;
|
||||
@override
|
||||
CentralState get state => _state;
|
||||
|
||||
@override
|
||||
Stream<CentralStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<CentralDiscoveredEventArgs> get discovered =>
|
||||
_discoveredController.stream;
|
||||
@override
|
||||
Stream<PeripheralStateChangedEventArgs> get peripheralStateChanged =>
|
||||
_peripheralStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged =>
|
||||
_characteristicValueChangedController.stream;
|
||||
Stream<int> get _servicesResolved => _servicesResolvedController.stream;
|
||||
|
||||
late StreamSubscription<List<String>> _adapterPropertiesChangedSubscription;
|
||||
late StreamSubscription<BlueZDevice> _deviceAddedSubscription;
|
||||
late StreamSubscription<BlueZDevice> _deviceRemovedSubscription;
|
||||
|
||||
Future<void> _throwWithState(CentralState state) async {
|
||||
if (this.state == state) {
|
||||
throw BluetoothLowEnergyError('$state is unexpected.');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _throwWithoutState(CentralState state) async {
|
||||
if (this.state != state) {
|
||||
throw BluetoothLowEnergyError(
|
||||
'$state is expected, but current state is ${this.state}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
await _throwWithoutState(CentralState.unknown);
|
||||
await _client.connect();
|
||||
_state =
|
||||
_client.adapters.isEmpty ? CentralState.unsupported : _adapter.state;
|
||||
if (_state == CentralState.unsupported) {
|
||||
return;
|
||||
}
|
||||
for (var device in _client.devices) {
|
||||
if (device.adapter != _adapter) {
|
||||
continue;
|
||||
}
|
||||
_beginDevicePropertiesChangedListener(device);
|
||||
}
|
||||
_adapterPropertiesChangedSubscription = _adapter.propertiesChanged.listen(
|
||||
_onAdapterPropertiesChanged,
|
||||
);
|
||||
_deviceAddedSubscription = _client.deviceAdded.listen(_onDeviceAdded);
|
||||
_deviceRemovedSubscription = _client.deviceRemoved.listen(_onDeviceRemoved);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> tearDown() async {
|
||||
await _throwWithState(CentralState.unknown);
|
||||
if (_state != CentralState.unsupported && _adapter.discovering) {
|
||||
await _adapter.stopDiscovery();
|
||||
}
|
||||
for (var myPeripheral in _myPeripherals.values) {
|
||||
final device = myPeripheral.device;
|
||||
if (device.connected) {
|
||||
await device.disconnect();
|
||||
}
|
||||
}
|
||||
_myPeripherals.clear();
|
||||
_myServices.clear();
|
||||
_myCharacteristics.clear();
|
||||
_myDescriptors.clear();
|
||||
for (var device in _client.devices) {
|
||||
if (device.adapter != _adapter) {
|
||||
continue;
|
||||
}
|
||||
_endDevicePropertiesChangedListener(device);
|
||||
}
|
||||
_adapterPropertiesChangedSubscription.cancel();
|
||||
_deviceAddedSubscription.cancel();
|
||||
_deviceRemovedSubscription.cancel();
|
||||
await _client.close();
|
||||
_state = CentralState.unknown;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
await _adapter.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
await _adapter.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final device = myPeripheral.device;
|
||||
await device.connect();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final device = myPeripheral.device;
|
||||
await device.disconnect();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> discoverGATT(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final device = myPeripheral.device;
|
||||
if (!device.connected) {
|
||||
throw BluetoothLowEnergyError('Peripheral is disconnected.');
|
||||
}
|
||||
if (device.servicesResolved) {
|
||||
return;
|
||||
}
|
||||
await _servicesResolved.firstWhere(
|
||||
(hashCode) => hashCode == peripheral.hashCode,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> getServices(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final blueZDevice = myPeripheral.device;
|
||||
return blueZDevice.gattServices
|
||||
.map(
|
||||
(service) => _myServices.putIfAbsent(
|
||||
service.hashCode,
|
||||
() => MyGattService(service),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattCharacteristic>> getCharacteristics(
|
||||
GattService service,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myService = service as MyGattService;
|
||||
final blueZService = myService.service;
|
||||
return blueZService.characteristics
|
||||
.map(
|
||||
(characteristic) => _myCharacteristics.putIfAbsent(
|
||||
characteristic.hashCode,
|
||||
() => MyGattCharacteristic(characteristic),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattDescriptor>> getDescriptors(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final blueZCharacteristic = myCharacteristic.characteristic;
|
||||
return blueZCharacteristic.descriptors
|
||||
.map(
|
||||
(descriptor) => _myDescriptors.putIfAbsent(
|
||||
descriptor.hashCode,
|
||||
() => MyGattDescriptor(descriptor),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final blueZCharacteristic = myCharacteristic.characteristic;
|
||||
final blueZValue = await blueZCharacteristic.readValue();
|
||||
return Uint8List.fromList(blueZValue);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final blueZCharacteristic = myCharacteristic.characteristic;
|
||||
await blueZCharacteristic.writeValue(
|
||||
value,
|
||||
type: type.toBlueZ(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final blueZCharacteristic = myCharacteristic.characteristic;
|
||||
if (state) {
|
||||
await blueZCharacteristic.startNotify();
|
||||
} else {
|
||||
await blueZCharacteristic.stopNotify();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myDescriptor = descriptor as MyGattDescriptor;
|
||||
final blueZDescriptor = myDescriptor.descriptor;
|
||||
final blueZValue = await blueZDescriptor.readValue();
|
||||
return Uint8List.fromList(blueZValue);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myDescriptor = descriptor as MyGattDescriptor;
|
||||
final blueZDescriptor = myDescriptor.descriptor;
|
||||
await blueZDescriptor.writeValue(value);
|
||||
}
|
||||
|
||||
void _onAdapterPropertiesChanged(List<String> properties) {
|
||||
for (var property in properties) {
|
||||
switch (property) {
|
||||
case 'Powered':
|
||||
final state = _adapter.state;
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = CentralStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _onDeviceAdded(BlueZDevice device) {
|
||||
if (device.adapter != _adapter) {
|
||||
return;
|
||||
}
|
||||
_onDiscovered(device);
|
||||
_beginDevicePropertiesChangedListener(device);
|
||||
}
|
||||
|
||||
void _onDeviceRemoved(BlueZDevice device) {
|
||||
if (device.adapter != _adapter) {
|
||||
return;
|
||||
}
|
||||
_endDevicePropertiesChangedListener(device);
|
||||
}
|
||||
|
||||
void _onDiscovered(BlueZDevice device) {
|
||||
final myPeripheral = _myPeripherals.putIfAbsent(
|
||||
device.hashCode,
|
||||
() => MyPeripheral(device),
|
||||
);
|
||||
final rssi = device.rssi;
|
||||
final advertisement = device.advertisement;
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
myPeripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
void _beginDevicePropertiesChangedListener(BlueZDevice device) {
|
||||
for (var service in device.gattServices) {
|
||||
for (var characteristic in service.characteristics) {
|
||||
_beginCharacteristicPropertiesChangedListener(characteristic);
|
||||
}
|
||||
}
|
||||
final subscription = device.propertiesChanged.listen((properties) {
|
||||
for (var property in properties) {
|
||||
switch (property) {
|
||||
case 'RSSI':
|
||||
_onDiscovered(device);
|
||||
break;
|
||||
case 'Connected':
|
||||
final myPeripheral =
|
||||
_myPeripherals[device.hashCode] as MyPeripheral;
|
||||
final state = device.connected;
|
||||
final eventArgs = PeripheralStateChangedEventArgs(
|
||||
myPeripheral,
|
||||
state,
|
||||
);
|
||||
_peripheralStateChangedController.add(eventArgs);
|
||||
break;
|
||||
case 'UUIDs':
|
||||
break;
|
||||
case 'ServicesResolved':
|
||||
if (device.servicesResolved) {
|
||||
for (var service in device.gattServices) {
|
||||
for (var characteristic in service.characteristics) {
|
||||
_beginCharacteristicPropertiesChangedListener(characteristic);
|
||||
}
|
||||
}
|
||||
_servicesResolvedController.add(device.hashCode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
_devicePropertiesChangedSubscriptions[device.hashCode] = subscription;
|
||||
}
|
||||
|
||||
void _endDevicePropertiesChangedListener(BlueZDevice device) {
|
||||
for (var service in device.gattServices) {
|
||||
for (var characteristic in service.characteristics) {
|
||||
_endCharacteristicPropertiesChangedListener(characteristic);
|
||||
}
|
||||
}
|
||||
final subscription = _devicePropertiesChangedSubscriptions.remove(
|
||||
device.address,
|
||||
);
|
||||
subscription?.cancel();
|
||||
}
|
||||
|
||||
void _beginCharacteristicPropertiesChangedListener(
|
||||
BlueZGattCharacteristic characteristic,
|
||||
) {
|
||||
final subscription = characteristic.propertiesChanged.listen((properties) {
|
||||
for (var property in properties) {
|
||||
switch (property) {
|
||||
case 'Value':
|
||||
final instance = _myCharacteristics[characteristic.hashCode];
|
||||
final myCharacteristic = instance is MyGattCharacteristic
|
||||
? instance
|
||||
: MyGattCharacteristic(characteristic);
|
||||
final value = Uint8List.fromList(characteristic.value);
|
||||
final eventArgs = GattCharacteristicValueChangedEventArgs(
|
||||
myCharacteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicValueChangedController.add(eventArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
_characteristicPropertiesChangedSubscriptions[characteristic.hashCode] =
|
||||
subscription;
|
||||
}
|
||||
|
||||
void _endCharacteristicPropertiesChangedListener(
|
||||
BlueZGattCharacteristic characteristic,
|
||||
) {
|
||||
final subscription = _characteristicPropertiesChangedSubscriptions.remove(
|
||||
characteristic.hashCode,
|
||||
);
|
||||
subscription?.cancel();
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
import 'my_bluez.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyGattCharacteristic extends MyObject implements GattCharacteristic {
|
||||
final BlueZGattCharacteristic characteristic;
|
||||
|
||||
MyGattCharacteristic(this.characteristic) : super(characteristic);
|
||||
|
||||
@override
|
||||
UUID get uuid => characteristic.uuid.toUUID();
|
||||
|
||||
@override
|
||||
List<GattCharacteristicProperty> get properties => characteristic.properties;
|
||||
}
|
14
bluetooth_low_energy_linux/lib/src/my_gatt_descriptor.dart
Normal file
14
bluetooth_low_energy_linux/lib/src/my_gatt_descriptor.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
import 'my_bluez.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyGattDescriptor extends MyObject implements GattDescriptor {
|
||||
final BlueZGattDescriptor descriptor;
|
||||
|
||||
MyGattDescriptor(this.descriptor) : super(descriptor);
|
||||
|
||||
@override
|
||||
UUID get uuid => descriptor.uuid.toUUID();
|
||||
}
|
14
bluetooth_low_energy_linux/lib/src/my_gatt_service.dart
Normal file
14
bluetooth_low_energy_linux/lib/src/my_gatt_service.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
import 'my_bluez.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyGattService extends MyObject implements GattService {
|
||||
final BlueZGattService service;
|
||||
|
||||
MyGattService(this.service) : super(service);
|
||||
|
||||
@override
|
||||
UUID get uuid => service.uuid.toUUID();
|
||||
}
|
11
bluetooth_low_energy_linux/lib/src/my_object.dart
Normal file
11
bluetooth_low_energy_linux/lib/src/my_object.dart
Normal file
@ -0,0 +1,11 @@
|
||||
abstract class MyObject {
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyObject(Object instance) : hashCode = instance.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyObject && other.hashCode == hashCode;
|
||||
}
|
||||
}
|
14
bluetooth_low_energy_linux/lib/src/my_peripheral.dart
Normal file
14
bluetooth_low_energy_linux/lib/src/my_peripheral.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
import 'my_bluez.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyPeripheral extends MyObject implements Peripheral {
|
||||
final BlueZDevice device;
|
||||
|
||||
MyPeripheral(this.device) : super(device);
|
||||
|
||||
@override
|
||||
UUID get uuid => device.uuid.toUUID();
|
||||
}
|
27
bluetooth_low_energy_linux/pubspec.yaml
Normal file
27
bluetooth_low_energy_linux/pubspec.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
name: bluetooth_low_energy_linux
|
||||
description: Linux implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface:
|
||||
path: ../bluetooth_low_energy_platform_interface
|
||||
bluez: ^0.8.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
flutter:
|
||||
plugin:
|
||||
implements: bluetooth_low_energy
|
||||
platforms:
|
||||
linux:
|
||||
dartPluginClass: BluetoothLowEnergyLinux
|
Reference in New Issue
Block a user