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:
@ -0,0 +1,12 @@
|
||||
export 'src/errors.dart';
|
||||
export 'src/event_args.dart';
|
||||
export 'src/central_controller.dart';
|
||||
export 'src/central_state.dart';
|
||||
export 'src/peripheral.dart';
|
||||
export 'src/uuid.dart';
|
||||
export 'src/advertisement.dart';
|
||||
export 'src/gatt_service.dart';
|
||||
export 'src/gatt_characteristic.dart';
|
||||
export 'src/gatt_characteristic_property.dart';
|
||||
export 'src/gatt_characteristic_write_type.dart';
|
||||
export 'src/gatt_descriptor.dart';
|
@ -0,0 +1,17 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'uuid.dart';
|
||||
|
||||
class Advertisement {
|
||||
final String? name;
|
||||
final Map<int, Uint8List> manufacturerSpecificData;
|
||||
final List<UUID> serviceUUIDs;
|
||||
final Map<UUID, Uint8List> serviceData;
|
||||
|
||||
Advertisement({
|
||||
this.name,
|
||||
this.manufacturerSpecificData = const {},
|
||||
this.serviceUUIDs = const [],
|
||||
this.serviceData = const {},
|
||||
});
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
import 'central_state.dart';
|
||||
import 'event_args.dart';
|
||||
import 'gatt_characteristic.dart';
|
||||
import 'gatt_characteristic_write_type.dart';
|
||||
import 'gatt_descriptor.dart';
|
||||
import 'gatt_service.dart';
|
||||
import 'peripheral.dart';
|
||||
|
||||
abstract class CentralController extends PlatformInterface {
|
||||
/// Constructs a [CentralController].
|
||||
CentralController() : super(token: _token);
|
||||
|
||||
static final Object _token = Object();
|
||||
|
||||
static CentralController? _instance;
|
||||
|
||||
/// The default instance of [CentralController] to use.
|
||||
static CentralController get instance {
|
||||
final instance = _instance;
|
||||
if (instance == null) {
|
||||
const message =
|
||||
'`BluetoothLowEnergy` is not implemented on this platform.';
|
||||
throw UnimplementedError(message);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// Platform-specific implementations should set this with their own
|
||||
/// platform-specific class that extends [CentralController] when
|
||||
/// they register themselves.
|
||||
static set instance(CentralController instance) {
|
||||
PlatformInterface.verifyToken(instance, _token);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
CentralState get state;
|
||||
Stream<CentralStateChangedEventArgs> get stateChanged;
|
||||
Stream<CentralDiscoveredEventArgs> get discovered;
|
||||
Stream<PeripheralStateChangedEventArgs> get peripheralStateChanged;
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged;
|
||||
|
||||
Future<void> setUp();
|
||||
Future<void> tearDown();
|
||||
Future<void> startDiscovery();
|
||||
Future<void> stopDiscovery();
|
||||
Future<void> connect(Peripheral peripheral);
|
||||
Future<void> disconnect(Peripheral peripheral);
|
||||
Future<void> discoverGATT(Peripheral peripheral);
|
||||
Future<List<GattService>> getServices(Peripheral peripheral);
|
||||
Future<List<GattCharacteristic>> getCharacteristics(GattService service);
|
||||
Future<List<GattDescriptor>> getDescriptors(
|
||||
GattCharacteristic characteristic,
|
||||
);
|
||||
Future<Uint8List> readCharacteristic(GattCharacteristic characteristic);
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
});
|
||||
Future<void> notifyCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
});
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor);
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
});
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
enum CentralState {
|
||||
unknown,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn,
|
||||
}
|
10
bluetooth_low_energy_platform_interface/lib/src/errors.dart
Normal file
10
bluetooth_low_energy_platform_interface/lib/src/errors.dart
Normal file
@ -0,0 +1,10 @@
|
||||
class BluetoothLowEnergyError extends Error {
|
||||
final String message;
|
||||
|
||||
BluetoothLowEnergyError(this.message);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BluetoothLowEnergyError: $message';
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'advertisement.dart';
|
||||
import 'central_state.dart';
|
||||
import 'gatt_characteristic.dart';
|
||||
import 'peripheral.dart';
|
||||
|
||||
abstract class EventArgs {}
|
||||
|
||||
class CentralStateChangedEventArgs extends EventArgs {
|
||||
final CentralState state;
|
||||
|
||||
CentralStateChangedEventArgs(this.state);
|
||||
}
|
||||
|
||||
class CentralDiscoveredEventArgs extends EventArgs {
|
||||
final Peripheral peripheral;
|
||||
final int rssi;
|
||||
final Advertisement advertisement;
|
||||
|
||||
CentralDiscoveredEventArgs(this.peripheral, this.rssi, this.advertisement);
|
||||
}
|
||||
|
||||
class PeripheralStateChangedEventArgs extends EventArgs {
|
||||
final Peripheral peripheral;
|
||||
final bool state;
|
||||
|
||||
PeripheralStateChangedEventArgs(this.peripheral, this.state);
|
||||
}
|
||||
|
||||
class GattCharacteristicValueChangedEventArgs extends EventArgs {
|
||||
final GattCharacteristic characteristic;
|
||||
final Uint8List value;
|
||||
|
||||
GattCharacteristicValueChangedEventArgs(this.characteristic, this.value);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import 'gatt_characteristic_property.dart';
|
||||
import 'uuid.dart';
|
||||
|
||||
class GattCharacteristic {
|
||||
final UUID uuid;
|
||||
final List<GattCharacteristicProperty> properties;
|
||||
|
||||
GattCharacteristic({
|
||||
required this.uuid,
|
||||
required this.properties,
|
||||
});
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
enum GattCharacteristicProperty {
|
||||
read,
|
||||
write,
|
||||
writeWithoutResponse,
|
||||
notify,
|
||||
indicate,
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
enum GattCharacteristicWriteType {
|
||||
// Write with response
|
||||
withResponse,
|
||||
// Write without response
|
||||
withoutResponse,
|
||||
// Write with response and waiting for confirmation
|
||||
// reliable,
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import 'uuid.dart';
|
||||
|
||||
class GattDescriptor {
|
||||
final UUID uuid;
|
||||
|
||||
GattDescriptor({
|
||||
required this.uuid,
|
||||
});
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import 'uuid.dart';
|
||||
|
||||
class GattService {
|
||||
final UUID uuid;
|
||||
|
||||
GattService({
|
||||
required this.uuid,
|
||||
});
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import 'uuid.dart';
|
||||
|
||||
abstract class Peripheral {
|
||||
UUID get uuid;
|
||||
}
|
141
bluetooth_low_energy_platform_interface/lib/src/uuid.dart
Normal file
141
bluetooth_low_energy_platform_interface/lib/src/uuid.dart
Normal file
@ -0,0 +1,141 @@
|
||||
/// 128 bit universally unique identifier used in Bluetooth.
|
||||
class UUID {
|
||||
/// The value of the UUID in 16 bytes.
|
||||
final List<int> value;
|
||||
|
||||
/// True if the UUID is a short (16 or 32 bit) encoded UUID.
|
||||
bool get isShort =>
|
||||
value[4] == 0x00 &&
|
||||
value[5] == 0x00 &&
|
||||
value[6] == 0x10 &&
|
||||
value[7] == 0x00 &&
|
||||
value[8] == 0x80 &&
|
||||
value[9] == 0x00 &&
|
||||
value[10] == 0x00 &&
|
||||
value[11] == 0x80 &&
|
||||
value[12] == 0x5f &&
|
||||
value[13] == 0x9b &&
|
||||
value[14] == 0x34 &&
|
||||
value[15] == 0xfb;
|
||||
|
||||
/// Creates a new UUID from 16 bytes.
|
||||
UUID(Iterable<int> value) : value = value.toList() {
|
||||
if (value.length != 16) {
|
||||
throw const FormatException('Invalid length UUID');
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new Bluetooth UUID from the short (16 or 32 bit) encoding.
|
||||
UUID.short(int shortValue)
|
||||
: value = [
|
||||
(shortValue >> 24) & 0xff,
|
||||
(shortValue >> 16) & 0xff,
|
||||
(shortValue >> 8) & 0xff,
|
||||
(shortValue >> 0) & 0xff,
|
||||
0x00,
|
||||
0x00,
|
||||
0x10,
|
||||
0x00,
|
||||
0x80,
|
||||
0x00,
|
||||
0x00,
|
||||
0x80,
|
||||
0x5f,
|
||||
0x9b,
|
||||
0x34,
|
||||
0xfb
|
||||
];
|
||||
|
||||
/// Creates a new UUID from the string format encoding (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx where xx is a hexadecimal number).
|
||||
factory UUID.fromString(String value) {
|
||||
if (value.length == 4) {
|
||||
try {
|
||||
final shortValue = int.parse(value, radix: 16);
|
||||
return UUID.short(shortValue);
|
||||
} catch (e) {
|
||||
throw const FormatException('Invalid UUID string');
|
||||
}
|
||||
}
|
||||
var groups = value.split('-');
|
||||
if (groups.length != 5 ||
|
||||
groups[0].length != 8 ||
|
||||
groups[1].length != 4 ||
|
||||
groups[2].length != 4 ||
|
||||
groups[3].length != 4 ||
|
||||
groups[4].length != 12) {
|
||||
throw const FormatException('Invalid UUID string');
|
||||
}
|
||||
int group0, group1, group2, group3, group4;
|
||||
try {
|
||||
group0 = int.parse(groups[0], radix: 16);
|
||||
group1 = int.parse(groups[1], radix: 16);
|
||||
group2 = int.parse(groups[2], radix: 16);
|
||||
group3 = int.parse(groups[3], radix: 16);
|
||||
group4 = int.parse(groups[4], radix: 16);
|
||||
} catch (e) {
|
||||
throw const FormatException('Invalid UUID string');
|
||||
}
|
||||
return UUID([
|
||||
(group0 >> 24) & 0xff,
|
||||
(group0 >> 16) & 0xff,
|
||||
(group0 >> 8) & 0xff,
|
||||
(group0 >> 0) & 0xff,
|
||||
(group1 >> 8) & 0xff,
|
||||
(group1 >> 0) & 0xff,
|
||||
(group2 >> 8) & 0xff,
|
||||
(group2 >> 0) & 0xff,
|
||||
(group3 >> 8) & 0xff,
|
||||
(group3 >> 0) & 0xff,
|
||||
(group4 >> 40) & 0xff,
|
||||
(group4 >> 32) & 0xff,
|
||||
(group4 >> 24) & 0xff,
|
||||
(group4 >> 16) & 0xff,
|
||||
(group4 >> 8) & 0xff,
|
||||
(group4 >> 0) & 0xff
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var v0 = value[0].toRadixString(16).padLeft(2, '0');
|
||||
var v1 = value[1].toRadixString(16).padLeft(2, '0');
|
||||
var v2 = value[2].toRadixString(16).padLeft(2, '0');
|
||||
var v3 = value[3].toRadixString(16).padLeft(2, '0');
|
||||
var v4 = value[4].toRadixString(16).padLeft(2, '0');
|
||||
var v5 = value[5].toRadixString(16).padLeft(2, '0');
|
||||
var v6 = value[6].toRadixString(16).padLeft(2, '0');
|
||||
var v7 = value[7].toRadixString(16).padLeft(2, '0');
|
||||
var v8 = value[8].toRadixString(16).padLeft(2, '0');
|
||||
var v9 = value[9].toRadixString(16).padLeft(2, '0');
|
||||
var v10 = value[10].toRadixString(16).padLeft(2, '0');
|
||||
var v11 = value[11].toRadixString(16).padLeft(2, '0');
|
||||
var v12 = value[12].toRadixString(16).padLeft(2, '0');
|
||||
var v13 = value[13].toRadixString(16).padLeft(2, '0');
|
||||
var v14 = value[14].toRadixString(16).padLeft(2, '0');
|
||||
var v15 = value[15].toRadixString(16).padLeft(2, '0');
|
||||
return '$v0$v1$v2$v3-$v4$v5-$v6$v7-$v8$v9-$v10$v11$v12$v13$v14$v15';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is UUID &&
|
||||
other.value[0] == value[0] &&
|
||||
other.value[1] == value[1] &&
|
||||
other.value[2] == value[2] &&
|
||||
other.value[3] == value[3] &&
|
||||
other.value[4] == value[4] &&
|
||||
other.value[5] == value[5] &&
|
||||
other.value[6] == value[6] &&
|
||||
other.value[7] == value[7] &&
|
||||
other.value[8] == value[8] &&
|
||||
other.value[9] == value[9] &&
|
||||
other.value[10] == value[10] &&
|
||||
other.value[11] == value[11] &&
|
||||
other.value[12] == value[12] &&
|
||||
other.value[13] == value[13] &&
|
||||
other.value[14] == value[14] &&
|
||||
other.value[15] == value[15];
|
||||
|
||||
@override
|
||||
int get hashCode => value.fold(17, (prev, value) => 37 * prev + value);
|
||||
}
|
Reference in New Issue
Block a user