提交代码
This commit is contained in:
parent
721ff610a6
commit
9947d7b8b3
@ -17,7 +17,6 @@ class BlueManage{
|
||||
DiscoveredCharacteristic? getDiscoveredCharacteristic;
|
||||
Uuid serviceId = Uuid.parse('0000FFF0-0000-1000-8000-00805F9B34FB');
|
||||
final int _limitLen = 20;
|
||||
final int _sleepTimes = AppPlatform.isAndroid ? 6 : 0;
|
||||
|
||||
static BlueManage? _manager;
|
||||
BlueManage._init();
|
||||
@ -96,13 +95,13 @@ class BlueManage{
|
||||
// 扫描服务,并过滤服务
|
||||
Future<List<DiscoveredService>> discoverServices(String deviceId) async {
|
||||
try {
|
||||
print('Start discovering services for: $deviceId');
|
||||
// print('Start discovering services for: $deviceId');
|
||||
List<DiscoveredService> result = await _flutterReactiveBle!.discoverServices(deviceId);
|
||||
print("mmmmmmmmm$result");
|
||||
// print("mmmmmmmmm$result");
|
||||
if(result.isNotEmpty){
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
DiscoveredService discoveredService = result[i];
|
||||
print("objectdiscoveredService.serviceId.toString() ${discoveredService.serviceId.toString()}");
|
||||
// print("objectdiscoveredService.serviceId.toString() ${discoveredService.serviceId.toString()}");
|
||||
if (discoveredService.serviceId.toString() == "fff0"){
|
||||
// getDiscoveredService = discoveredService;
|
||||
for (var j = 0; j < discoveredService.characteristics.length; j++) {
|
||||
@ -115,8 +114,7 @@ class BlueManage{
|
||||
// print("1111111111111111characteristicId:${result[i].characteristicIds[j].toString()} serviceId:${result[i].serviceId} deviceId:$deviceId");
|
||||
}
|
||||
if (discoveredCharacteristic.characteristicId.toString() == "fff2") {
|
||||
|
||||
print("1111111111111111characteristicId:${discoveredCharacteristic.characteristicId} serviceId:${serviceId} deviceId:$deviceId");
|
||||
// print("1111111111111111characteristicId:${discoveredCharacteristic.characteristicId} serviceId:${serviceId} deviceId:$deviceId");
|
||||
qualifiedCharacteristic = QualifiedCharacteristic(characteristicId: discoveredCharacteristic.characteristicId, serviceId:serviceId , deviceId: deviceId);
|
||||
}
|
||||
}
|
||||
@ -136,7 +134,6 @@ class BlueManage{
|
||||
|
||||
// 听上报来的数据,参数来自前面扫描到的结果
|
||||
subScribeToCharacteristic(QualifiedCharacteristic characteristic) {
|
||||
print('Subscribing to characteristicId: ${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId}');
|
||||
_flutterReactiveBle!.subscribeToCharacteristic(characteristic).listen((data) {
|
||||
// code to handle incoming data
|
||||
print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
||||
@ -144,24 +141,19 @@ class BlueManage{
|
||||
}, onError: (dynamic error) {
|
||||
print("subscribeToCharacteristic error:$error");
|
||||
});
|
||||
// return _ble.subscribeToCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
// 写入
|
||||
Future<void> writeCharacteristicWithResponse(QualifiedCharacteristic characteristic, List<int> value) async {
|
||||
print(
|
||||
'Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value');
|
||||
print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value');
|
||||
|
||||
try {
|
||||
List<int> valueList = value;
|
||||
|
||||
List subData = splitList(valueList, _limitLen);
|
||||
print('得到的分割数据:$subData');
|
||||
|
||||
for (int i = 0; i < subData.length; i++) {
|
||||
await _flutterReactiveBle!
|
||||
.writeCharacteristicWithResponse(characteristic, value: subData[i])
|
||||
.then((value) async {
|
||||
await _flutterReactiveBle!.writeCharacteristicWithResponse(characteristic, value: subData[i]).then((value) async {
|
||||
await Future.delayed(const Duration(milliseconds: 1))
|
||||
.then((value) async {
|
||||
print('成功了么');
|
||||
@ -169,9 +161,7 @@ class BlueManage{
|
||||
});
|
||||
}
|
||||
} on Exception catch (e, s) {
|
||||
print(
|
||||
'Error occurred when writing: $e',
|
||||
);
|
||||
print('Error occurred when writing: $e');
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import '../io_tool/io_tool.dart';
|
||||
import 'io_reply.dart';
|
||||
import 'io_sender.dart';
|
||||
import 'io_type.dart';
|
||||
@ -8,19 +9,52 @@ import 'io_type.dart';
|
||||
class GetPrivateKeyCommand extends SenderProtocol {
|
||||
|
||||
String? lockID;
|
||||
String? keyID; // 钥匙ID
|
||||
String? authUserID; // 钥匙授权人ID
|
||||
int? nowTime;
|
||||
String? authCode;
|
||||
int? needAuthor;
|
||||
GetPrivateKeyCommand({
|
||||
this.lockID,
|
||||
}) : super(CommandType.getLockPublicKey);
|
||||
this.keyID,
|
||||
this.authUserID,
|
||||
this.nowTime,
|
||||
this.authCode,
|
||||
}) : super(CommandType.getLockPrivateKey);
|
||||
|
||||
@override
|
||||
List<int> messageDetail() {
|
||||
List<int> data = [];
|
||||
print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
||||
|
||||
// 锁id
|
||||
int lockIDLength = utf8.encode(lockID!).length;
|
||||
data.addAll(utf8.encode(lockID!));
|
||||
for(int i = 0; i<24; i++){
|
||||
data = getFixedLengthList(data, 40 - lockIDLength);
|
||||
|
||||
//KeyID 40
|
||||
int keyIDLength = utf8.encode(keyID!).length;
|
||||
data.addAll(utf8.encode(keyID!));
|
||||
data = getFixedLengthList(data, 40 - keyIDLength);
|
||||
|
||||
//authUserID 40
|
||||
int authUserIDLength = utf8.encode(authUserID!).length;
|
||||
data.addAll(utf8.encode(authUserID!));
|
||||
data = getFixedLengthList(data, 20 - authUserIDLength);
|
||||
|
||||
//NowTime 4
|
||||
DateTime now = DateTime.now();
|
||||
int timestamp = now.millisecondsSinceEpoch;
|
||||
data.add((timestamp & 0xff000000) >> 24);
|
||||
data.add((timestamp & 0xff0000) >> 16);
|
||||
data.add((timestamp & 0xff00) >> 8);
|
||||
data.add((timestamp & 0xff));
|
||||
|
||||
if(needAuthor == 0){
|
||||
data.add(0);
|
||||
}else{
|
||||
|
||||
}
|
||||
print("dataaaaaa:$data");
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import '../../tools/storage.dart';
|
||||
import '../io_tool/io_tool.dart';
|
||||
import 'io_reply.dart';
|
||||
import 'io_sender.dart';
|
||||
@ -16,10 +18,9 @@ class GetPublicKeyCommand extends SenderProtocol {
|
||||
List<int> messageDetail() {
|
||||
List<int> data = [];
|
||||
print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}");
|
||||
int length = utf8.encode(lockID!).length;
|
||||
data.addAll(utf8.encode(lockID!));
|
||||
for(int i = 0; i<24; i++){
|
||||
data.add(0);
|
||||
}
|
||||
data = getFixedLengthList(data, 40 - length);
|
||||
print("dataaaaaa:$data");
|
||||
return data;
|
||||
}
|
||||
@ -28,11 +29,16 @@ class GetPublicKeyCommand extends SenderProtocol {
|
||||
class GetPublicKeyReply extends Reply {
|
||||
GetPublicKeyReply.parseData(CommandType commandType, List<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
// print('获取公钥');
|
||||
var tokenData = dataDetail.sublist(1);
|
||||
print('获取公钥:$tokenData');
|
||||
switch(dataDetail[0]){
|
||||
case 0x00:
|
||||
//成功
|
||||
print('获取公钥');
|
||||
var stringEncoded = base64.encode(tokenData);
|
||||
print('获取公钥成功 publickey:$stringEncoded');
|
||||
// 储存公钥
|
||||
Storage.setData("bluePublicKey", stringEncoded);
|
||||
|
||||
break;
|
||||
case 0x07:
|
||||
//无权限
|
||||
|
||||
@ -22,7 +22,13 @@ import 'package:encrypt/encrypt.dart';
|
||||
// setCacheString(RKEnum.CACHE_STRING_APISTRURL, encrypt.base16);
|
||||
// }
|
||||
|
||||
|
||||
// 获取固定长度的数组
|
||||
List<int> getFixedLengthList(List<int>data, int length) {
|
||||
for(int i = 0; i<length; i++){
|
||||
data.add(0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
//int ---> 指定长度的hex (如指定长度为6的情况,0x000001 0x001234, 0xefab23)
|
||||
String intToFormatHex(int num, int length) {
|
||||
@ -38,24 +44,7 @@ String uint8ToHex(Uint8List byteArr) {
|
||||
return "";
|
||||
}
|
||||
Uint8List result = Uint8List(byteArr.length << 1);
|
||||
var hexTable = [
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F'
|
||||
]; //16进制字符表
|
||||
var hexTable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']; //16进制字符表
|
||||
for (var i = 0; i < byteArr.length; i++) {
|
||||
var bit = byteArr[i]; //取传入的byteArr的每一位
|
||||
var index = bit >> 4 & 15; //右移4位,取剩下四位
|
||||
@ -219,66 +208,54 @@ List<List<T>> splitList<T>(List<T> list, int len) {
|
||||
}
|
||||
|
||||
//TODO:获取数据包分包后包的数量
|
||||
int getPackageCount(List<int> data, {required int averageLen}) {
|
||||
int len = data.length;
|
||||
return len % averageLen > 0 ? (len ~/ averageLen + 1) : len ~/ averageLen;
|
||||
}
|
||||
// int getPackageCount(List<int> data, {required int averageLen}) {
|
||||
// int len = data.length;
|
||||
// return len % averageLen > 0 ? (len ~/ averageLen + 1) : len ~/ averageLen;
|
||||
// }
|
||||
//
|
||||
// List<int> getSubData(
|
||||
// {required int index, required int average, required List<int> data}) {
|
||||
// if (data.isEmpty) {
|
||||
// return [];
|
||||
// }
|
||||
// int totalLength = data.length;
|
||||
// if (average >= totalLength) {
|
||||
// return data;
|
||||
// }
|
||||
//
|
||||
// if (index * average > totalLength) {
|
||||
// if ((index - 1) * average > totalLength) {
|
||||
// return [];
|
||||
// } else {
|
||||
// int tempCount = average * (index - 1);
|
||||
// return data.sublist(tempCount, totalLength);
|
||||
// }
|
||||
// } else {
|
||||
// return data.sublist(average * (index - 1), average * index);
|
||||
// }
|
||||
// }
|
||||
|
||||
List<int> getSubData(
|
||||
{required int index, required int average, required List<int> data}) {
|
||||
if (data.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
int totalLength = data.length;
|
||||
if (average >= totalLength) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (index * average > totalLength) {
|
||||
if ((index - 1) * average > totalLength) {
|
||||
return [];
|
||||
} else {
|
||||
int tempCount = average * (index - 1);
|
||||
return data.sublist(tempCount, totalLength);
|
||||
}
|
||||
} else {
|
||||
return data.sublist(average * (index - 1), average * index);
|
||||
}
|
||||
}
|
||||
|
||||
List<int> reverseList(List<int> srcData) {
|
||||
print('srcData:$srcData'); //[1,3]
|
||||
int srcLen = srcData.length;
|
||||
int halfLen = srcLen ~/ 2;
|
||||
List<int> dstData = [];
|
||||
dstData.addAll(srcData);
|
||||
for (int i = 0; i < halfLen; i++) {
|
||||
int begin = i;
|
||||
int end = srcLen - i - 1;
|
||||
List<int> beginData = srcData.sublist(begin, begin + 1);
|
||||
List<int> endData = srcData.sublist(end, end + 1);
|
||||
dstData.replaceRange(begin, begin + 1, endData);
|
||||
dstData.replaceRange(end, end + 1, beginData);
|
||||
}
|
||||
print('dstData:$dstData');
|
||||
return dstData;
|
||||
}
|
||||
// List<int> reverseList(List<int> srcData) {
|
||||
// print('srcData:$srcData'); //[1,3]
|
||||
// int srcLen = srcData.length;
|
||||
// int halfLen = srcLen ~/ 2;
|
||||
// List<int> dstData = [];
|
||||
// dstData.addAll(srcData);
|
||||
// for (int i = 0; i < halfLen; i++) {
|
||||
// int begin = i;
|
||||
// int end = srcLen - i - 1;
|
||||
// List<int> beginData = srcData.sublist(begin, begin + 1);
|
||||
// List<int> endData = srcData.sublist(end, end + 1);
|
||||
// dstData.replaceRange(begin, begin + 1, endData);
|
||||
// dstData.replaceRange(end, end + 1, beginData);
|
||||
// }
|
||||
// print('dstData:$dstData');
|
||||
// return dstData;
|
||||
// }
|
||||
|
||||
//TODO:int->两个字节 List 高字节在前,低字节在后(小端存储) 本工程只有配置 WiFi用到的!!!!
|
||||
List<int> intToByte2ListLow(int value) => [value >> 8, value];
|
||||
|
||||
int dealWeekDays({
|
||||
required int mon,
|
||||
required int tue,
|
||||
required int wed,
|
||||
required int thu,
|
||||
required int fri,
|
||||
required int sat,
|
||||
required int sun,
|
||||
}) {
|
||||
return mon + tue * 2 + wed * 4 + thu * 8 + fri * 16 + sat * 32 + sun * 64;
|
||||
}
|
||||
|
||||
String radixString(List<int> codeUnits) {
|
||||
String result = '';
|
||||
codeUnits.forEach((value) {
|
||||
|
||||
@ -80,7 +80,7 @@ class CommandReciverManager {
|
||||
var cmd = data[0] * 256 + data[1];
|
||||
CommandType commandType = ExtensionCommandType.getCommandType(cmd);
|
||||
data.removeRange(0, 2);
|
||||
print("111111data:$data");
|
||||
print("111111data commandType:$commandType data:$data");
|
||||
var reply;
|
||||
switch(commandType) {
|
||||
case CommandType.getLockPublicKey:
|
||||
|
||||
@ -7,7 +7,6 @@ import 'package:star_lock/tools/app_manager.dart';
|
||||
import 'package:star_lock/tools/bindings/app_binding.dart';
|
||||
import 'package:star_lock/tools/device_info_service.dart';
|
||||
import 'package:star_lock/tools/platform_info_services.dart';
|
||||
import 'package:star_lock/tools/reactiveBlueTool/getx_ble.dart';
|
||||
// import 'package:star_lock/tools/store_service.dart';
|
||||
import 'package:star_lock/translations/app_dept.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
@ -22,8 +21,6 @@ void main() async {
|
||||
// 设置国际化信息
|
||||
await _initTranslation();
|
||||
|
||||
GetxBle();
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import 'package:star_lock/mine/mineSet/mineSet_page.dart';
|
||||
import '../../appRouters.dart';
|
||||
import '../../baseWidget.dart';
|
||||
import '../../mine/mine/starLockMine_page.dart';
|
||||
import '../../tools/reactiveBlueTool/getx_ble.dart';
|
||||
import '../../tools/titleAppBar.dart';
|
||||
import '../../translations/trans_lib.dart';
|
||||
import 'lockMain_logic.dart';
|
||||
|
||||
@ -2,14 +2,12 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
|
||||
import '../../../blue/blue_manage.dart';
|
||||
import '../../../blue/io_tool/io_model.dart';
|
||||
import '../../../blue/io_tool/manager_event_bus.dart';
|
||||
import '../../../blue/sender_manage.dart';
|
||||
import '../../../tools/reactiveBlueTool/getx_ble.dart';
|
||||
import 'nearbyLock_state.dart';
|
||||
|
||||
class NearbyLockLogic extends BaseGetXController{
|
||||
@ -76,7 +74,7 @@ class NearbyLockLogic extends BaseGetXController{
|
||||
print("onInit()");
|
||||
|
||||
// 进来第一步开始扫描
|
||||
GetxBle().scanner.startScan((v){
|
||||
BlueManage().startScan((v){
|
||||
bool isHave = state.devices.any((element) => element.id == v[0].id);
|
||||
if (isHave == false){
|
||||
state.devices.addAll(v);
|
||||
@ -88,6 +86,7 @@ class NearbyLockLogic extends BaseGetXController{
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
_streamSubscription.cancel();
|
||||
_sendStreamSubscription.cancel();
|
||||
}
|
||||
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../blue/io_tool/manager_event_bus.dart';
|
||||
|
||||
class BleDeviceConnector extends GetxController {
|
||||
BleDeviceConnector({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage {
|
||||
rxBleConnectionState.bindStream(_deviceConnectionController.stream);
|
||||
}
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
final rxBleConnectionState = Rx<ConnectionStateUpdate>(
|
||||
const ConnectionStateUpdate(
|
||||
deviceId: "",
|
||||
connectionState: DeviceConnectionState.disconnected,
|
||||
failure: null));
|
||||
|
||||
final _deviceConnectionController = StreamController<ConnectionStateUpdate>();
|
||||
|
||||
late StreamSubscription<ConnectionStateUpdate> _connection;
|
||||
|
||||
Future<void> connect(String deviceMAC) async {
|
||||
print("connect:$deviceMAC");
|
||||
_logMessage('Start connecting to $deviceMAC');
|
||||
_connection = _ble.connectToDevice(id: deviceMAC).listen(
|
||||
(update) {
|
||||
print('ConnectionState for device $deviceMAC : ${update.connectionState}');
|
||||
// _logMessage(
|
||||
// 'ConnectionState for device $deviceMAC : ${update.connectionState}');
|
||||
// _deviceConnectionController.add(update);
|
||||
EventBusManager().eventBusFir(update);
|
||||
},
|
||||
onError: (Object e) =>
|
||||
_logMessage('Connecting to device $deviceMAC resulted in error $e'),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> disconnect(String deviceMAC) async {
|
||||
try {
|
||||
_logMessage('disconnecting to device: $deviceMAC');
|
||||
await _connection.cancel();
|
||||
} on Exception catch (e, _) {
|
||||
_logMessage("Error disconnecting from a device: $e");
|
||||
} finally {
|
||||
// Since [_connection] subscription is terminated, the "disconnected" state cannot be received and propagated
|
||||
EventBusManager().eventBusFir(ConnectionStateUpdate(
|
||||
deviceId: deviceMAC,
|
||||
connectionState: DeviceConnectionState.disconnected,
|
||||
failure: null,
|
||||
));
|
||||
// _deviceConnectionController.add(
|
||||
// ConnectionStateUpdate(
|
||||
// deviceId: deviceMAC,
|
||||
// connectionState: DeviceConnectionState.disconnected,
|
||||
// failure: null,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onClose() async {
|
||||
rxBleConnectionState.close();
|
||||
await _deviceConnectionController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:core';
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../blue/io_tool/io_tool.dart';
|
||||
|
||||
class BleDeviceInteractor extends GetxController {
|
||||
BleDeviceInteractor({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage;
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
// 扫描服务,并过滤服务
|
||||
Future<List<DiscoveredService>> discoverServices(String deviceId) async {
|
||||
try {
|
||||
_logMessage('Start discovering services for: $deviceId');
|
||||
List<DiscoveredService> result = await _ble.discoverServices(deviceId);
|
||||
print("mmmmmmmmm$result");
|
||||
if(result.isNotEmpty){
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
for (var j = 0; j < result[i].characteristicIds.length; j++) {
|
||||
print("hhhhhhhhhh${result[i].characteristicIds[j].toString()}");
|
||||
if (result[i].characteristicIds[j].toString() == "fff1") {
|
||||
print("1111111111111111${result[i].characteristicIds[j].toString()}");
|
||||
_subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: result[i].characteristicIds[j], serviceId: result[i].serviceId, deviceId: deviceId));
|
||||
}
|
||||
if (result[i].characteristicIds[j].toString() == "fff2") {
|
||||
// cd02 = res.characteristics[i].uuid;
|
||||
// characteristics02 = res.characteristics[i];
|
||||
// isConnected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_logMessage('Discovering services finished');
|
||||
return result;
|
||||
} on Exception catch (e) {
|
||||
_logMessage('Error occurred when discovering services: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// 听上报来的数据,参数来自前面扫描到的结果
|
||||
_subScribeToCharacteristic(QualifiedCharacteristic characteristic) {
|
||||
_logMessage('Subscribing to: ${characteristic.characteristicId} ');
|
||||
|
||||
print("22222222222222222222${characteristic}");
|
||||
_ble.subscribeToCharacteristic(characteristic).listen((data) {
|
||||
// code to handle incoming data
|
||||
print("zzzzzzzzzzzzz subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
||||
|
||||
}, onError: (dynamic error) {
|
||||
print("xxxxxxxxxxxxx:$error");
|
||||
});
|
||||
// return _ble.subscribeToCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
// 读取
|
||||
Future<List<int>> readCharacteristic(
|
||||
QualifiedCharacteristic characteristic) async {
|
||||
try {
|
||||
final result = await _ble.readCharacteristic(characteristic);
|
||||
_logMessage('Read ${characteristic.characteristicId}: value = $result');
|
||||
return result;
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage(
|
||||
'Error occurred when reading ${characteristic.characteristicId} : $e',
|
||||
);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// 写入
|
||||
Future<void> writeCharacteristicWithResponse(
|
||||
QualifiedCharacteristic characteristic, List<int> value) async {
|
||||
try {
|
||||
// _logMessage('Write with response value : $value to ${characteristic.characteristicId}');
|
||||
print('Write with response value : $value to ${characteristic.characteristicId}');
|
||||
// await _ble.writeCharacteristicWithResponse(characteristic, value: value);
|
||||
List<int> oneList = [];
|
||||
List<int> twoList = [];
|
||||
List<int> threeList = [];
|
||||
int ctn = getPackageCount(value, averageLen: 20);
|
||||
for (int i = 1; i <= ctn; i++){
|
||||
List<int> subData = getSubData(index: i, average: 20, data: value);
|
||||
print("i:$i ctn:$ctn subData:$subData");
|
||||
print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $subData');
|
||||
|
||||
switch (i) {
|
||||
case 1:
|
||||
{
|
||||
oneList.addAll(subData);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
twoList.addAll(subData);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
threeList.addAll(subData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
// await Future.delayed(Duration(
|
||||
// milliseconds: i == ctn ? 0 : _sleepTimes,
|
||||
// ),(){
|
||||
// // i++;
|
||||
// });
|
||||
}
|
||||
|
||||
print("oneList:$oneList");
|
||||
_ble.writeCharacteristicWithResponse(characteristic, value: oneList).onError((error, stackTrace){
|
||||
// print("writeCharacteristicWithResponse:$characteristic $subData, error:$error stackTrace:$stackTrace}");
|
||||
});
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 80,),(){});
|
||||
|
||||
print("twoList:$twoList");
|
||||
_ble.writeCharacteristicWithResponse(characteristic, value: twoList).onError((error, stackTrace){
|
||||
// print("writeCharacteristicWithResponse:$characteristic $subData, error:$error stackTrace:$stackTrace}");
|
||||
});
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 80,),(){});
|
||||
|
||||
print("threeList:$threeList");
|
||||
_ble.writeCharacteristicWithResponse(characteristic, value: threeList).onError((error, stackTrace){
|
||||
// print("writeCharacteristicWithResponse:$characteristic $subData, error:$error stackTrace:$stackTrace}");
|
||||
});
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage('Error occurred when writing ${characteristic.characteristicId} : $e',);
|
||||
print('Error occurred when writing ${characteristic.characteristicId} : $e',);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristicWithoutResponse(
|
||||
QualifiedCharacteristic characteristic, List<int> value) async {
|
||||
try {
|
||||
await _ble.writeCharacteristicWithoutResponse(characteristic,
|
||||
value: value);
|
||||
_logMessage(
|
||||
'Write without response value: $value to ${characteristic.characteristicId}');
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage(
|
||||
'Error occurred when writing ${characteristic.characteristicId} : $e',
|
||||
);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleLogger extends GetxController {
|
||||
BleLogger({
|
||||
required FlutterReactiveBle ble,
|
||||
}) : _ble = ble;
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
final Rx<List<String>> rxMessages = Rx<List<String>>([]);
|
||||
final RxBool rxVerboseLogging = false.obs;
|
||||
|
||||
void addToLog(String message) {
|
||||
final now = DateTime.now();
|
||||
final formattedDate = '${now.year}-${now.month}-${now.day} ${now.hour}:${now.minute}:${now.second}';
|
||||
rxMessages.value.add('$formattedDate - $message');
|
||||
}
|
||||
|
||||
void clearLogs() => rxMessages.value.clear();
|
||||
|
||||
void verboseLoggingUpdate() {
|
||||
if (rxVerboseLogging.value) {
|
||||
_ble.logLevel = LogLevel.verbose;
|
||||
} else {
|
||||
_ble.logLevel = LogLevel.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
typedef ScanResultCallBack = void Function(List<DiscoveredDevice> devices);
|
||||
/// 这个类负责开启和关闭蓝牙扫描器并输出扫描结果
|
||||
class BleScanner extends GetxController {
|
||||
BleScanner({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage {
|
||||
rxBleScannerState.bindStream(_stateStreamController.stream);
|
||||
}
|
||||
|
||||
// static BleScanner get to => Get.find<BleScanner>();
|
||||
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
/// 输入 FlutterReactiveBle 来获取结果及功能
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
/// 输入日志函数来输出日志
|
||||
final StreamController<BleScannerState> _stateStreamController =
|
||||
StreamController();
|
||||
|
||||
StreamSubscription? _subscription;
|
||||
|
||||
/// 使用 Getx 的 Rx 来监听扫描结果
|
||||
final rxBleScannerState = Rx<BleScannerState>(
|
||||
const BleScannerState(discoveredDevices: [], scanIsInProgress: false));
|
||||
|
||||
final _devices = <DiscoveredDevice>[];
|
||||
|
||||
/// 开始扫描蓝牙设备
|
||||
void startScan(ScanResultCallBack scanResultCallBack) {
|
||||
_logMessage('Start ble discovery');
|
||||
_devices.clear();
|
||||
_subscription?.cancel();
|
||||
_subscription = _ble.scanForDevices(withServices: []).listen((device) {
|
||||
// 判断名字为空的直接剃掉
|
||||
if(device.name.isEmpty){
|
||||
return;
|
||||
}
|
||||
|
||||
if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824")) && (device.rssi >= -100)) {
|
||||
// print("11111111111111111:${device}");
|
||||
final knownDeviceIndex = _devices.indexWhere((d) => d.id == device.id);
|
||||
|
||||
if (knownDeviceIndex >= 0) {
|
||||
_devices[knownDeviceIndex] = device;
|
||||
} else {
|
||||
_devices.add(device);
|
||||
}
|
||||
scanResultCallBack(_devices);
|
||||
}
|
||||
// _pushState();
|
||||
}, onError: (Object e) => _logMessage('Device scan fails with error: $e'));
|
||||
// _pushState();
|
||||
}
|
||||
|
||||
/// 更新扫描结果
|
||||
void _pushState() {
|
||||
_stateStreamController.add(
|
||||
BleScannerState(
|
||||
discoveredDevices: _devices,
|
||||
scanIsInProgress: _subscription != null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 停止扫描蓝牙设备
|
||||
Future<void> stopScan() async {
|
||||
_logMessage('Stop ble discovery');
|
||||
|
||||
await _subscription?.cancel();
|
||||
_subscription = null;
|
||||
_pushState();
|
||||
}
|
||||
|
||||
/// GetxController 的生命周期函数,当页面关闭时,关闭扫描器
|
||||
@override
|
||||
Future<void> onClose() async {
|
||||
rxBleScannerState.close();
|
||||
await _stateStreamController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
/// 这个类用来存储扫描到的蓝牙设备以及扫描器状态
|
||||
@immutable
|
||||
class BleScannerState {
|
||||
const BleScannerState({
|
||||
required this.discoveredDevices,
|
||||
required this.scanIsInProgress,
|
||||
});
|
||||
|
||||
final List<DiscoveredDevice> discoveredDevices;
|
||||
final bool scanIsInProgress;
|
||||
}
|
||||
|
||||
/// 这个类用来存储扫描器的过滤器
|
||||
class BleScannerFilter {
|
||||
String? name;
|
||||
String? mac;
|
||||
List<Uuid>? serviceId;
|
||||
int? rssi;
|
||||
|
||||
BleScannerFilter({
|
||||
this.name,
|
||||
this.mac,
|
||||
this.serviceId,
|
||||
this.rssi,
|
||||
});
|
||||
}
|
||||
@ -1,485 +0,0 @@
|
||||
class BleSigGattUuids {
|
||||
static const Map serviceUuids = {
|
||||
"1800": "Generic Access",
|
||||
"1811": "Alert Notification Service",
|
||||
"1815": "Automation IO",
|
||||
"180F": "Battery Service",
|
||||
"1810": "Blood Pressure",
|
||||
"181B": "Body Composition",
|
||||
"181E": "Bond Management Service",
|
||||
"181F": "Continuous Glucose Monitoring",
|
||||
"1805": "Current Time Service",
|
||||
"1818": "Cycling Power",
|
||||
"1816": "Cycling Speed and Cadence",
|
||||
"180A": "Device Information",
|
||||
"181A": "Environmental Sensing",
|
||||
"1826": "Fitness Machine",
|
||||
"1801": "Generic Attribute",
|
||||
"1808": "Glucose",
|
||||
"1809": "Health Thermometer",
|
||||
"180D": "Heart Rate",
|
||||
"1823": "HTTP Proxy",
|
||||
"1812": "Human Interface Device",
|
||||
"1802": "Immediate Alert",
|
||||
"1821": "Indoor Positioning",
|
||||
"183A": "Insulin Delivery",
|
||||
"1820": "Internet Protocol Support Service",
|
||||
"1803": "Link Loss",
|
||||
"1819": "Location and Navigation",
|
||||
"1827": "Mesh Provisioning Service",
|
||||
"1828": "Mesh Proxy Service",
|
||||
"1807": "Next DST Change Service",
|
||||
"1825": "Object Transfer Service",
|
||||
"180E": "Phone Alert Status Service",
|
||||
"1822": "Pulse Oximeter Service",
|
||||
"1829": "Reconnection Configuration",
|
||||
"1806": "Reference Time Update Service",
|
||||
"1814": "Running Speed and Cadence",
|
||||
"1813": "Scan Parameters",
|
||||
"1824": "Transport Discovery",
|
||||
"1804": "Tx Power",
|
||||
"181C": "User Data",
|
||||
"181D": "Weight Scale",
|
||||
"183B": "Binary Sensor",
|
||||
"183C": "Emergency Configuration",
|
||||
"183E": "Physical Activity Monitor",
|
||||
"1843": "Audio Input Control",
|
||||
"1844": "Volume Control",
|
||||
"1845": "Volume Offset Control",
|
||||
"1846": "Coordinated Set Identification",
|
||||
"1847": "Device Time",
|
||||
"1848": "Media Control",
|
||||
"1849": "Generic Media Control",
|
||||
"184A": "Constant Tone Extension",
|
||||
"184B": "Telephone Bearer",
|
||||
"184C": "Generic Telephone Bearer",
|
||||
"184D": "Microphone Control",
|
||||
"184E": "Audio Stream Control",
|
||||
"184F": "Broadcast Audio Scan",
|
||||
"1850": "Published Audio Capabilities",
|
||||
"1851": "Published Audio Data",
|
||||
"1852": "Broadcast Audio Announcement",
|
||||
"1853": "Common Audio",
|
||||
"1854": "Hearing Access",
|
||||
"1855": "TMAS"
|
||||
};
|
||||
|
||||
static const Map characteristicUuids = {
|
||||
"2A7E": "Aerobic Heart Rate Lower Limit",
|
||||
"2A84": "Aerobic Heart Rate Upper Limit",
|
||||
"2A7F": "Aerobic Threshold",
|
||||
"2A80": "Age",
|
||||
"2A5A": "Aggregate",
|
||||
"2A43": "Alert Category ID",
|
||||
"2A42": "Alert Category ID Bit Mask",
|
||||
"2A06": "Alert Level",
|
||||
"2A44": "Alert Notification Control Point",
|
||||
"2A3F": "Alert Status",
|
||||
"2AB3": "Altitude",
|
||||
"2A81": "Anaerobic Heart Rate Lower Limit",
|
||||
"2A82": "Anaerobic Heart Rate Upper Limit",
|
||||
"2A83": "Anaerobic Threshold",
|
||||
"2A58": "Analog",
|
||||
"2A59": "Analog Output",
|
||||
"2A73": "Apparent Wind Direction",
|
||||
"2A72": "Apparent Wind Speed",
|
||||
"2A01": "Appearance",
|
||||
"2AA3": "Barometric Pressure Trend",
|
||||
"2A19": "Battery Level",
|
||||
"2A1B": "Battery Level State",
|
||||
"2A1A": "Battery Power State",
|
||||
"2A49": "Blood Pressure Feature",
|
||||
"2A35": "Blood Pressure Measurement",
|
||||
"2A9B": "Body Composition Feature",
|
||||
"2A9C": "Body Composition Measurement",
|
||||
"2A38": "Body Sensor Location",
|
||||
"2AA4": "Bond Management Control Point",
|
||||
"2AA5": "Bond Management Features",
|
||||
"2A22": "Boot Keyboard Input Report",
|
||||
"2A32": "Boot Keyboard Output Report",
|
||||
"2A33": "Boot Mouse Input Report",
|
||||
"2AA6": "Central Address Resolution",
|
||||
"2AA8": "CGM Feature",
|
||||
"2AA7": "CGM Measurement",
|
||||
"2AAB": "CGM Session Run Time",
|
||||
"2AAA": "CGM Session Start Time",
|
||||
"2AAC": "CGM Specific Ops Control Point",
|
||||
"2AA9": "CGM Status",
|
||||
"2ACE": "Cross Trainer Data",
|
||||
"2A5C": "CSC Feature",
|
||||
"2A5B": "CSC Measurement",
|
||||
"2A2B": "Current Time",
|
||||
"2A66": "Cycling Power Control Point",
|
||||
"2A65": "Cycling Power Feature",
|
||||
"2A63": "Cycling Power Measurement",
|
||||
"2A64": "Cycling Power Vector",
|
||||
"2A99": "Database Change Increment",
|
||||
"2A85": "Date of Birth",
|
||||
"2A86": "Date of Threshold Assessment",
|
||||
"2A08": "Date Time",
|
||||
"2A0A": "Day Date Time",
|
||||
"2A09": "Day of Week",
|
||||
"2A7D": "Descriptor Value Changed",
|
||||
"2A00": "Device Name",
|
||||
"2A7B": "Dew Point",
|
||||
"2A56": "Digital",
|
||||
"2A57": "Digital Output",
|
||||
"2A0D": "DST Offset",
|
||||
"2A6C": "Elevation",
|
||||
"2A87": "Email Address",
|
||||
"2A0B": "Exact Time 100",
|
||||
"2A0C": "Exact Time 256",
|
||||
"2A88": "Fat Burn Heart Rate Lower Limit",
|
||||
"2A89": "Fat Burn Heart Rate Upper Limit",
|
||||
"2A26": "Firmware Revision String",
|
||||
"2A8A": "First Name",
|
||||
"2AD9": "Fitness Machine Control Point",
|
||||
"2ACC": "Fitness Machine Feature",
|
||||
"2ADA": "Fitness Machine Status",
|
||||
"2A8B": "Five Zone Heart Rate Limits",
|
||||
"2AB2": "Floor Number",
|
||||
"2A8C": "Gender",
|
||||
"2A51": "Glucose Feature",
|
||||
"2A18": "Glucose Measurement",
|
||||
"2A34": "Glucose Measurement Context",
|
||||
"2A74": "Gust Factor",
|
||||
"2A27": "Hardware Revision String",
|
||||
"2A39": "Heart Rate Control Point",
|
||||
"2A8D": "Heart Rate Max",
|
||||
"2A37": "Heart Rate Measurement",
|
||||
"2A7A": "Heat Index",
|
||||
"2A8E": "Height",
|
||||
"2A4C": "HID Control Point",
|
||||
"2A4A": "HID Information",
|
||||
"2A8F": "Hip Circumference",
|
||||
"2ABA": "HTTP Control Point",
|
||||
"2AB9": "HTTP Entity Body",
|
||||
"2AB7": "HTTP Headers",
|
||||
"2AB8": "HTTP Status Code",
|
||||
"2ABB": "HTTPS Security",
|
||||
"2A6F": "Humidity",
|
||||
"2B22": "IDD Annunciation Status",
|
||||
"2B25": "IDD Command Control Point",
|
||||
"2B26": "IDD Command Data",
|
||||
"2B23": "IDD Features",
|
||||
"2B28": "IDD History Data",
|
||||
"2B27": "IDD Record Access Control Point",
|
||||
"2B21": "IDD Status",
|
||||
"2B20": "IDD Status Changed",
|
||||
"2B24": "IDD Status Reader Control Point",
|
||||
"2A2A": "IEEE 11073-20601 Regulatory Certification Data List",
|
||||
"2AD2": "Indoor Bike Data",
|
||||
"2AAD": "Indoor Positioning Configuration",
|
||||
"2A36": "Intermediate Cuff Pressure",
|
||||
"2A1E": "Intermediate Temperature",
|
||||
"2A77": "Irradiance",
|
||||
"2AA2": "Language",
|
||||
"2A90": "Last Name",
|
||||
"2AAE": "Latitude",
|
||||
"2A6B": "LN Control Point",
|
||||
"2A6A": "LN Feature",
|
||||
"2AB1": "Local East Coordinate",
|
||||
"2AB0": "Local North Coordinate",
|
||||
"2A0F": "Local Time Information",
|
||||
"2A67": "Location and Speed Characteristic",
|
||||
"2AB5": "Location Name",
|
||||
"2AAF": "Longitude",
|
||||
"2A2C": "Magnetic Declination",
|
||||
"2AA0": "Magnetic Flux Density - 2D",
|
||||
"2AA1": "Magnetic Flux Density - 3D",
|
||||
"2A29": "Manufacturer Name String",
|
||||
"2A91": "Maximum Recommended Heart Rate",
|
||||
"2A21": "Measurement Interval",
|
||||
"2A24": "Model Number String",
|
||||
"2A68": "Navigation",
|
||||
"2A3E": "Network Availability",
|
||||
"2A46": "New Alert",
|
||||
"2AC5": "Object Action Control Point",
|
||||
"2AC8": "Object Changed",
|
||||
"2AC1": "Object First-Created",
|
||||
"2AC3": "Object ID",
|
||||
"2AC2": "Object Last-Modified",
|
||||
"2AC6": "Object List Control Point",
|
||||
"2AC7": "Object List Filter",
|
||||
"2ABE": "Object Name",
|
||||
"2AC4": "Object Properties",
|
||||
"2AC0": "Object Size",
|
||||
"2ABF": "Object Type",
|
||||
"2ABD": "OTS Feature",
|
||||
"2A04": "Peripheral Preferred Connection Parameters",
|
||||
"2A02": "Peripheral Privacy Flag",
|
||||
"2A5F": "PLX Continuous Measurement Characteristic",
|
||||
"2A60": "PLX Features",
|
||||
"2A5E": "PLX Spot-Check Measurement",
|
||||
"2A50": "PnP ID",
|
||||
"2A75": "Pollen Concentration",
|
||||
"2A2F": "Position 2D",
|
||||
"2A30": "Position 3D",
|
||||
"2A69": "Position Quality",
|
||||
"2A6D": "Pressure",
|
||||
"2A4E": "Protocol Mode",
|
||||
"2A62": "Pulse Oximetry Control Point",
|
||||
"2A78": "Rainfall",
|
||||
"2B1D": "RC Feature",
|
||||
"2B1E": "RC Settings",
|
||||
"2A03": "Reconnection Address",
|
||||
"2B1F": "Reconnection Configuration Control Point",
|
||||
"2A52": "Record Access Control Point",
|
||||
"2A14": "Reference Time Information",
|
||||
"2A3A": "Removable",
|
||||
"2A4D": "Report",
|
||||
"2A4B": "Report Map",
|
||||
"2AC9": "Resolvable Private Address Only",
|
||||
"2A92": "Resting Heart Rate",
|
||||
"2A40": "Ringer Control point",
|
||||
"2A41": "Ringer Setting",
|
||||
"2AD1": "Rower Data",
|
||||
"2A54": "RSC Feature",
|
||||
"2A53": "RSC Measurement",
|
||||
"2A55": "SC Control Point",
|
||||
"2A4F": "Scan Interval Window",
|
||||
"2A31": "Scan Refresh",
|
||||
"2A3C": "Scientific Temperature Celsius",
|
||||
"2A10": "Secondary Time Zone",
|
||||
"2A5D": "Sensor Location",
|
||||
"2A05": "Service Changed",
|
||||
"2A0E": "Time Zone",
|
||||
"2A11": "Time with DST",
|
||||
"2A12": "Time Accuracy",
|
||||
"2A13": "Time Source",
|
||||
"2A15": "Time Broadcast",
|
||||
"2A16": "Time Update Control Point",
|
||||
"2A17": "Time Update State",
|
||||
"2A25": "Serial Number String",
|
||||
"2A3B": "Service Required",
|
||||
"2A28": "Software Revision String",
|
||||
"2A93": "Sport Type for Aerobic and Anaerobic Thresholds",
|
||||
"2AD0": "Stair Climber Data",
|
||||
"2ACF": "Step Climber Data",
|
||||
"2A3D": "String",
|
||||
"2AD7": "Supported Heart Rate Range",
|
||||
"2AD5": "Supported Inclination Range",
|
||||
"2A47": "Supported New Alert Category",
|
||||
"2AD8": "Supported Power Range",
|
||||
"2AD6": "Supported Resistance Level Range",
|
||||
"2AD4": "Supported Speed Range",
|
||||
"2A48": "Supported Unread Alert Category",
|
||||
"2A23": "System ID",
|
||||
"2ABC": "TDS Control Point",
|
||||
"2A6E": "Temperature",
|
||||
"2A1F": "Temperature Celsius",
|
||||
"2A20": "Temperature Fahrenheit",
|
||||
"2A1C": "Temperature Measurement",
|
||||
"2A1D": "Temperature Type",
|
||||
"2A94": "Three Zone Heart Rate Limits",
|
||||
"2A70": "True Wind Speed",
|
||||
"2A71": "True Wind Direction",
|
||||
"2A95": "Two Zone Heart Rate Limit",
|
||||
"2A07": "Tx Power Level",
|
||||
"2AB4": "Uncertainty",
|
||||
"2A45": "Unread Alert Status",
|
||||
"2AB6": "URI",
|
||||
"2A9F": "User Control Point",
|
||||
"2A9A": "User Index",
|
||||
"2A76": "UV Index",
|
||||
"2A79": "Wind Chill",
|
||||
"2A96": "VO2 Max",
|
||||
"2A97": "Waist Circumference",
|
||||
"2A98": "Weight",
|
||||
"2A9D": "Weight Measurement",
|
||||
"2A9E": "Weight Scale Feature",
|
||||
"2ACD": "Treadmill Data",
|
||||
"2AD3": "Training Status",
|
||||
"2AE0": "Average Current",
|
||||
"2AE1": "Average Voltage",
|
||||
"2AE2": "Boolean",
|
||||
"2AE3": "Chromatic Distance From Planckian",
|
||||
"2AE4": "Chromaticity Coordinates",
|
||||
"2AE5": "Chromaticity In CCT And Duv Values",
|
||||
"2AE6": "Chromaticity Tolerance",
|
||||
"2AE7": "CIE 13.3-1995 Color Rendering Index",
|
||||
"2AE8": "Coefficient",
|
||||
"2AE9": "Correlated Color Temperature",
|
||||
"2AEA": "Count 16",
|
||||
"2AEB": "Count 24",
|
||||
"2AEC": "Country Code",
|
||||
"2AED": "Date UTC",
|
||||
"2AEE": "Electric Current",
|
||||
"2AEF": "Electric Current Range",
|
||||
"2AF0": "Electric Current Specification",
|
||||
"2AF1": "Electric Current Statistics",
|
||||
"2AF2": "Energy",
|
||||
"2AF3": "Energy In A Period Of Day",
|
||||
"2AF4": "Event Statistics",
|
||||
"2AF5": "Fixed String 16",
|
||||
"2AF6": "Fixed String 24",
|
||||
"2AF7": "Fixed String 36",
|
||||
"2AF8": "Fixed String 8",
|
||||
"2AF9": "Generic Level",
|
||||
"2AFA": "Global Trade Item Number",
|
||||
"2AFB": "Illuminance",
|
||||
"2AFC": "Luminous Efficacy",
|
||||
"2AFD": "Luminous Energy",
|
||||
"2AFE": "Luminous Exposure",
|
||||
"2AFF": "Luminous Flux",
|
||||
"2B00": "Luminous Flux Range",
|
||||
"2B01": "Luminous Intensity",
|
||||
"2B02": "B02 Mass Flow",
|
||||
"2B03": "Perceived Lightness",
|
||||
"2B04": "Percentage 8",
|
||||
"2B05": "Power",
|
||||
"2B06": "Power Specification",
|
||||
"2B07": "Relative Runtime In A Current Range",
|
||||
"2B08": "Relative Runtime In A Generic Level Range",
|
||||
"2B09": "Relative Value In A Voltage Range",
|
||||
"2B0A": "Relative Value In An Illuminance Range",
|
||||
"2B0B": "Relative Value In A Period Of Day",
|
||||
"2B0C": "Relative Value In A Temperature Range",
|
||||
"2B0D": "Temperature 8",
|
||||
"2B0E": "Temperature 8 In A Period Of Day",
|
||||
"2B0F": "Temperature 8 Statistics",
|
||||
"2B10": "Temperature Range",
|
||||
"2B11": "Temperature Statistics",
|
||||
"2B12": "Time Decihour 8",
|
||||
"2B13": "Time Exponential 8",
|
||||
"2B14": "Time Hour 24",
|
||||
"2B15": "Time Millisecond 24",
|
||||
"2B16": "Time Second 16",
|
||||
"2B17": "Time Second 8",
|
||||
"2B18": "Voltage",
|
||||
"2B19": "Voltage Specification",
|
||||
"2B1A": "Volume Flow",
|
||||
"2B1B": "Volume Flow",
|
||||
"2B1C": "Volume Flow In A Period Of Day",
|
||||
"2B29": "Client Supported Features",
|
||||
"2B2A": "Database Hash",
|
||||
"2B2B": "BSS Control Point",
|
||||
"2B2C": "BSS Response",
|
||||
"2B2D": "Emergency ID",
|
||||
"2B2E": "Emergency Text",
|
||||
"2B34": "Enhanced Blood Pressure Measurement",
|
||||
"2B35": "Enhanced Intermediate Cuff Pressure",
|
||||
"2B36": "Blood Pressure Record",
|
||||
"2B38": "BR-EDR Handover Data",
|
||||
"2B39": "Bluetooth SIG Data",
|
||||
"2B3A": "Server Supported Features",
|
||||
"2B3B": "Physical Activity Monitor Features",
|
||||
"2B3C": "General Activity Instantaneous Data",
|
||||
"2B3D": "General Activity Summary Data",
|
||||
"2B3E": "CardioRespiratory Activity Instantaneous Data",
|
||||
"2B3F": "CardioRespiratory Activity Summary Data",
|
||||
"2B40": "Step Counter Activity Summary Data",
|
||||
"2B41": "Sleep Activity Instantaneous Data",
|
||||
"2B42": "Sleep Activity Summary Data",
|
||||
"2B43": "Physical Activity Monitor Control Point",
|
||||
"2B44": "Activity Current Session",
|
||||
"2B45": "Physical Activity Session Descriptor",
|
||||
"2B46": "Preferred Units",
|
||||
"2B47": "High Resolution Height",
|
||||
"2B48": "Middle Name",
|
||||
"2B49": "Stride Length",
|
||||
"2B4A": "Handedness",
|
||||
"2B4B": "Device Wearing Position",
|
||||
"2B4C": "Four Zone Heart Rate Limits",
|
||||
"2B4D": "High Intensity Exercise Threshold",
|
||||
"2B4E": "Activity Goal",
|
||||
"2B4F": "Sedentary Interval Notification",
|
||||
"2B50": "Caloric Intake",
|
||||
"2B51": "TMAP Role",
|
||||
"2B77": "Audio Input State",
|
||||
"2B78": "Audio Input Control Point",
|
||||
"2B79": "Audio Input Type",
|
||||
"2B7A": "Audio Input Status",
|
||||
"2B7B": "Audio Input Control Point",
|
||||
"2B7C": "Audio Input Description",
|
||||
"2B7D": "Volume State",
|
||||
"2B7E": "Volume Control Point",
|
||||
"2B7F": "Volume Flags",
|
||||
"2B80": "Volume Offset State",
|
||||
"2B81": "Audio Location",
|
||||
"2B82": "Volume Offset Control Point",
|
||||
"2B83": "Audio Output State",
|
||||
"2B84": "Set Identity Resolving Key",
|
||||
"2B85": "Coordinated Set Size",
|
||||
"2B86": "Set Member Lock",
|
||||
"2B87": "Set Member Rank",
|
||||
"2B8E": "Device Time Feature",
|
||||
"2B8F": "Device Time Parameters",
|
||||
"2B90": "Device Time",
|
||||
"2B91": "Device Time Control Point",
|
||||
"2B92": "Time Change Log Data",
|
||||
"2B93": "Media Player Name",
|
||||
"2B94": "Media Player Icon Object ID",
|
||||
"2B95": "Media Player Icon URL",
|
||||
"2B96": "Track Changed",
|
||||
"2B97": "Track Title",
|
||||
"2B98": "Track Duration",
|
||||
"2B99": "Track Position",
|
||||
"2B9A": "Playback Speed",
|
||||
"2B9B": "Seeking Speed",
|
||||
"2B9C": "Current Track Segments Object ID",
|
||||
"2B9D": "Current Track Object ID",
|
||||
"2B9E": "Next Track Object ID",
|
||||
"2B9F": "Parent Group Object ID",
|
||||
"2BA0": "Current Group Object ID",
|
||||
"2BA1": "Playing Order",
|
||||
"2BA2": "Playing Orders Supported",
|
||||
"2BA3": "Media State",
|
||||
"2BA4": "Media Control Point",
|
||||
"2BA5": "Media Control Point Opcodes Supported",
|
||||
"2BA6": "Search Results Object ID",
|
||||
"2BA7": "Search Control Point",
|
||||
"2BA9": "Media Player Icon Object Type",
|
||||
"2BAA": "Track Segments Object Type",
|
||||
"2BAB": "Track Object Type",
|
||||
"2BAC": "Group Object Type",
|
||||
"2BAD": "Constant Tone Extension Enable",
|
||||
"2BAE": "Advertising Constant Tone Extension Minimum Length",
|
||||
"2BAF": "Advertising Constant Tone Extension Minimum Transmit Count",
|
||||
"2BB0": "Advertising Constant Tone Extension Transmit Duration",
|
||||
"2BB1": "Advertising Constant Tone Extension Interval",
|
||||
"2BB2": "Advertising Constant Tone Extension PHY",
|
||||
"2BB3": "Bearer Provider Name",
|
||||
"2BB4": "Bearer UCI",
|
||||
"2BB5": "Bearer Technology",
|
||||
"2BB6": "Bearer URI Schemes Supported List",
|
||||
"2BB7": "Bearer Signal Strength",
|
||||
"2BB8": "Bearer Signal Strength Reporting Interval",
|
||||
"2BB9": "Bearer List Current Calls",
|
||||
"2BBA": "Content Control ID",
|
||||
"2BBB": "Status Flags",
|
||||
"2BBC": "Incoming Call Target Bearer URI",
|
||||
"2BBD": "Call State",
|
||||
"2BBE": "Call Control Point",
|
||||
"2BBF": "Call Control Point Optional Opcodes",
|
||||
"2BC0": "Termination Reason",
|
||||
"2BC1": "Incoming Call",
|
||||
"2BC2": "Call Friendly Name",
|
||||
"2BC3": "Mute",
|
||||
"2BC4": "Sink ASE",
|
||||
"2BC5": "Source ASE",
|
||||
"2BC6": "ASE Control Point",
|
||||
"2BC7": "Broadcast Audio Scan Control Point",
|
||||
"2BC8": "Broadcast Receive State",
|
||||
"2BC9": "Sink PAC",
|
||||
"2BCA": "Sink Audio Locations",
|
||||
"2BCB": "Source PAC",
|
||||
"2BCC": "Source Audio Locations",
|
||||
"2BCD": "Available Audio Contexts",
|
||||
"2BCE": "Supported Audio Contexts",
|
||||
"2BCF": "Ammonia Concentration",
|
||||
"2BD0": "Carbon Monoxide Concentration",
|
||||
"2BD1": "Nitrogen Dioxide Concentration",
|
||||
"2BD2": "Nitrogen Dioxide Concentration",
|
||||
"2BD3": "Non-Methane Volatile Organic Compounds Concentration",
|
||||
"2BD4": "Ozone Concentration",
|
||||
"2BD5": "Particulate Matter - PM1 Concentration",
|
||||
"2BD6": "Particulate Matter - PM2.5 Concentration",
|
||||
"2BD7": "Particulate Matter - PM10 Concentration",
|
||||
"2BD8": "Sulfur Dioxide Concentration",
|
||||
"2BD9": "Sulfur Hexafluoride Concentration",
|
||||
"2BDA": "Hearing Aid Features",
|
||||
"2BDB": "Hearing Aid Preset Control Point",
|
||||
"2BDC": "Hearing Aid Preset",
|
||||
};
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleStatusMonitor extends GetxController {
|
||||
BleStatusMonitor(this._ble) {
|
||||
rxBleStatus.bindStream(_ble.statusStream);
|
||||
}
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
final Rx<BleStatus> rxBleStatus = BleStatus.unknown.obs;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
library getx_ble;
|
||||
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'ble_device_connector.dart';
|
||||
import 'ble_device_interactor.dart';
|
||||
import 'ble_logger.dart';
|
||||
import 'ble_scanner.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'ble_status_monitor.dart';
|
||||
|
||||
export 'ble_device_connector.dart';
|
||||
export 'ble_device_interactor.dart';
|
||||
export 'ble_logger.dart';
|
||||
export 'ble_scanner.dart';
|
||||
export 'ble_status_monitor.dart';
|
||||
|
||||
class GetxBle extends GetxController {
|
||||
static GetxBle get call => Get.find<GetxBle>();
|
||||
|
||||
final ble = FlutterReactiveBle();
|
||||
late final BleLogger bleLogger;
|
||||
late final BleStatusMonitor bleStatusMonitor;
|
||||
late final BleScanner scanner;
|
||||
late final BleDeviceConnector connector;
|
||||
late final BleDeviceInteractor interactor;
|
||||
|
||||
GetxBle() {
|
||||
bleLogger = BleLogger(ble: ble);
|
||||
bleStatusMonitor = BleStatusMonitor(ble);
|
||||
scanner = BleScanner(ble: ble, logMessage: bleLogger.addToLog);
|
||||
connector = BleDeviceConnector(ble: ble, logMessage: bleLogger.addToLog);
|
||||
interactor = BleDeviceInteractor(ble: ble, logMessage: bleLogger.addToLog);
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,6 @@ class StoreService<T> extends GetxService {
|
||||
static StoreService get to => Get.find<StoreService>();
|
||||
Future<StoreService<T>> init() async {
|
||||
await GetStorage.init();
|
||||
// await resetUserInfo();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user