389 lines
16 KiB
Dart
389 lines
16 KiB
Dart
|
||
import 'dart:async';
|
||
|
||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||
import 'package:star_lock/blue/sender_manage.dart';
|
||
|
||
import '../tools/toast.dart';
|
||
import 'io_tool/io_model.dart';
|
||
import 'io_tool/io_tool.dart';
|
||
import 'io_tool/manager_event_bus.dart';
|
||
import 'reciver_data.dart';
|
||
|
||
typedef ScanResultCallBack = void Function(List<DiscoveredDevice> devices);
|
||
//连接状态回调
|
||
typedef ConnectStateCallBack = Function(DeviceConnectionState connectionState);
|
||
|
||
class BlueManage{
|
||
FlutterReactiveBle? _flutterReactiveBle;
|
||
final List<DiscoveredDevice> _scanDevices = [];
|
||
|
||
Uuid serviceId = Uuid.parse('0000FFF0-0000-1000-8000-00805F9B34FB');
|
||
Uuid characteristicIdSubscription = Uuid.parse("fff1");//用来订阅的特征id
|
||
Uuid characteristicIdWrite = Uuid.parse("fff2");// 用来写入的特征id
|
||
String connectDeviceMacAddress = "";
|
||
String connectDeviceName = "";
|
||
|
||
// final int _limitLen = 20;
|
||
|
||
// 监听发送事件
|
||
StreamSubscription<EventSendModel>? _sendStreamSubscription;
|
||
StreamSubscription? _scanSubscription;
|
||
|
||
// 监听蓝牙连接状态
|
||
DeviceConnectionState? deviceConnectionState = DeviceConnectionState.disconnected;
|
||
|
||
static BlueManage? _manager;
|
||
BlueManage._init();
|
||
|
||
static BlueManage? shareManager(){
|
||
_manager ??= BlueManage._init();
|
||
_manager!._initBlue();
|
||
return _manager;
|
||
}
|
||
|
||
factory BlueManage() => shareManager()!;
|
||
BlueManage? get manager => shareManager();
|
||
|
||
void _initBlue(){
|
||
_flutterReactiveBle = FlutterReactiveBle();
|
||
print("蓝牙功能初始化了");
|
||
_initSendStreamSubscription();
|
||
}
|
||
|
||
void _initSendStreamSubscription() {
|
||
_sendStreamSubscription ??= EventBusManager().eventBus!.on<EventSendModel>().listen((
|
||
EventSendModel model) {
|
||
if (model.sendChannel == DataChannel.ble) {
|
||
// managerAppWriteData(model.data);
|
||
writeCharacteristicWithResponse(model.data);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// 开始扫描蓝牙设备
|
||
void startScan(bool isScanAll, ScanResultCallBack scanResultCallBack) {
|
||
_scanDevices.clear();
|
||
_scanSubscription = _flutterReactiveBle!.scanForDevices(withServices: []).listen((device) {
|
||
// 判断名字为空的直接剔除
|
||
if(device.name.isEmpty){
|
||
return;
|
||
}
|
||
// print("startScanDevice:${device}");
|
||
// 判断是否
|
||
if(isScanAll == true){
|
||
if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824"))&& (device.rssi >= -100)) {
|
||
// 查询id相同的元素
|
||
final knownDeviceIndex = _scanDevices.indexWhere((d) => d.id == device.id);
|
||
// 不存在的时候返回-1
|
||
if (knownDeviceIndex >= 0) {
|
||
_scanDevices[knownDeviceIndex] = device;
|
||
} else {
|
||
_scanDevices.add(device);
|
||
}
|
||
|
||
scanResultCallBack(_scanDevices);
|
||
}
|
||
}else{
|
||
if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824")) && ((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString()[31] != "1") && (device.rssi >= -100)) {
|
||
// 查询id相同的元素
|
||
final knownDeviceIndex = _scanDevices.indexWhere((d) => d.id == device.id);
|
||
// 不存在的时候返回-1
|
||
if (knownDeviceIndex >= 0) {
|
||
_scanDevices[knownDeviceIndex] = device;
|
||
} else {
|
||
_scanDevices.add(device);
|
||
}
|
||
// print("_scanDevices:$_scanDevices");
|
||
scanResultCallBack(_scanDevices);
|
||
}
|
||
}
|
||
|
||
}, onError: (Object e) {
|
||
print('Device scan fails with error: $e');
|
||
});
|
||
}
|
||
|
||
/// 连接监听状态
|
||
Future<void> connect(String deviceMAC, String deviceName, {ConnectStateCallBack? connectStateCallBack, bool? isFrist = false ,bool isShowLoading = true}) async {
|
||
connectDeviceMacAddress = deviceMAC;
|
||
connectDeviceName = deviceName;
|
||
print("connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName");
|
||
|
||
if(isShowLoading){
|
||
EasyLoading.show();
|
||
Future.delayed(const Duration(seconds: 10), () { //asynchronous delay
|
||
print("10s之后 菊花没有隐藏的话,强制隐藏菊花");
|
||
if(EasyLoading.isShow){
|
||
EasyLoading.dismiss();
|
||
}
|
||
});
|
||
}
|
||
_flutterReactiveBle!.connectToDevice(id: connectDeviceMacAddress, connectionTimeout: const Duration(seconds: 100000)).listen((connectionStateUpdate) async {
|
||
// 获取状态
|
||
deviceConnectionState = connectionStateUpdate.connectionState;
|
||
print('ConnectionState for device $deviceMAC : ${connectionStateUpdate.connectionState}');
|
||
|
||
// if(connectionStateUpdate.connectionState != DeviceConnectionState.connected){
|
||
// EasyLoading.dismiss();
|
||
// }
|
||
|
||
if(connectionStateUpdate.connectionState == DeviceConnectionState.connected){
|
||
// 如果状态是连接的开始发现服务
|
||
// await discoverServices(connectDeviceId, connectDeviceName);
|
||
try {
|
||
// print('Start discovering services for: $deviceId');
|
||
List<DiscoveredService> result = await _flutterReactiveBle!.discoverServices(deviceMAC);
|
||
// print("mmmmmmmmm$result");
|
||
if(result.isNotEmpty){
|
||
for (var i = 0; i < result.length; i++) {
|
||
DiscoveredService discoveredService = result[i];
|
||
if (discoveredService.serviceId.toString() == "fff0"){
|
||
// getDiscoveredService = discoveredService;
|
||
for (var j = 0; j < discoveredService.characteristics.length; j++) {
|
||
DiscoveredCharacteristic discoveredCharacteristic = discoveredService.characteristics[j];
|
||
if (discoveredCharacteristic.characteristicId.toString() == "fff1") {
|
||
// 订阅用
|
||
characteristicIdSubscription = discoveredCharacteristic.characteristicId;
|
||
// print("Subscription characteristicId:${result[i].characteristicIds[j].toString()} serviceId:${result[i].serviceId} deviceId:$deviceMAC");
|
||
}
|
||
if (discoveredCharacteristic.characteristicId.toString() == "fff2") {
|
||
// 用来写入
|
||
characteristicIdWrite= discoveredCharacteristic.characteristicId;
|
||
// print("1111111111111111characteristicId:${discoveredCharacteristic.characteristicId} serviceId:${serviceId} deviceId:$deviceId");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}else{
|
||
EasyLoading.dismiss();
|
||
}
|
||
_subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: characteristicIdSubscription, serviceId: Uuid.parse("fff0"), deviceId: deviceMAC));
|
||
print('Discovering services finished');
|
||
|
||
if(isFrist == true){
|
||
// var publicKey = await Storage.getStringList(saveBluePublicKey);
|
||
// List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
|
||
// if(publicKeyDataList.isNotEmpty ){
|
||
// IoSenderManage.getPrivateKey(
|
||
// lockId:BlueManage().connectDeviceName,
|
||
// keyID:"1",
|
||
// authUserID:"1",
|
||
// nowTime:1,
|
||
// publicKeyData:publicKeyDataList,
|
||
// needAuthor:1);
|
||
// }else{
|
||
// 第一次添加锁的时候需要先获取公钥
|
||
IoSenderManage.getPublicKey(lockId: deviceName);
|
||
// }
|
||
}
|
||
connectStateCallBack!(connectionStateUpdate.connectionState);
|
||
} on Exception catch (e) {
|
||
EasyLoading.dismiss();
|
||
print('Error occurred when discovering services: $e');
|
||
rethrow;
|
||
}
|
||
}
|
||
}, onError: (Object e){
|
||
EasyLoading.dismiss();
|
||
print('Connecting to device $deviceMAC resulted in error $e');
|
||
}
|
||
);
|
||
}
|
||
|
||
/// 停止扫描蓝牙设备
|
||
Future<void> stopScan() async {
|
||
await _scanSubscription?.cancel();
|
||
_scanSubscription = null;
|
||
}
|
||
|
||
// 断开连接
|
||
Future<void> disconnect(String deviceMAC) async {
|
||
try {
|
||
print('disconnecting to device: $deviceMAC');
|
||
} on Exception catch (e, _) {
|
||
print("Error disconnecting from a device: $e");
|
||
} finally {
|
||
// EventBusManager().eventBusFir(ConnectionStateUpdate(
|
||
// deviceId: deviceMAC,
|
||
// connectionState: DeviceConnectionState.disconnected,
|
||
// failure: null,
|
||
// ));
|
||
}
|
||
}
|
||
|
||
// 重新连接
|
||
Future<void> judgeReconnect(String deviceMAC, String deviceName, ConnectStateCallBack? connectStateCallBack, {bool isShowLoading = true}) async {
|
||
// print("11111111$deviceConnectionState");
|
||
if(deviceMAC.isEmpty){
|
||
Toast.show(msg: "未连接到设备,请确保在设备附近,设备未被连接,设备已打开");
|
||
// return;
|
||
}
|
||
if(deviceConnectionState == DeviceConnectionState.connected){
|
||
// print("2222222:$deviceConnectionState");
|
||
if(isShowLoading){
|
||
EasyLoading.show();
|
||
Future.delayed(const Duration(seconds: 10), () { //asynchronous delay
|
||
print("10s之后 菊花没有隐藏的话,强制隐藏菊花");
|
||
if(EasyLoading.isShow){
|
||
EasyLoading.dismiss();
|
||
}
|
||
});
|
||
}
|
||
connectStateCallBack!(deviceConnectionState!);
|
||
}else{
|
||
// print("333333333:${deviceConnectionState}");
|
||
connect(deviceMAC, deviceName, isShowLoading: false, connectStateCallBack: (state){
|
||
// print("44444444:${state}");
|
||
// if(deviceConnectionState == DeviceConnectionState.connected){
|
||
connectStateCallBack!(state);
|
||
// }else {
|
||
// Toast.show(msg: "连接设备失败,请确保在设备附近,设备未被连接,设备已打开");
|
||
// }
|
||
});
|
||
}
|
||
}
|
||
|
||
// 扫描服务,并过滤服务
|
||
// Future<List<DiscoveredService>> discoverServices(String deviceMAC, String deviceName, {bool? isFrist = false}) async {
|
||
// try {
|
||
// // print('Start discovering services for: $deviceId');
|
||
// List<DiscoveredService> result = await _flutterReactiveBle!.discoverServices(deviceMAC);
|
||
// // 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()}");
|
||
// if (discoveredService.serviceId.toString() == "fff0"){
|
||
// // getDiscoveredService = discoveredService;
|
||
// for (var j = 0; j < discoveredService.characteristics.length; j++) {
|
||
// DiscoveredCharacteristic discoveredCharacteristic = discoveredService.characteristics[j];
|
||
//
|
||
// // print("hhhhhhhhhh${result[i].characteristicIds[j].toString()}");
|
||
// if (discoveredCharacteristic.characteristicId.toString() == "fff1") {
|
||
// // 订阅用
|
||
// characteristicIdSubscription = discoveredCharacteristic.characteristicId;
|
||
// // getDiscoveredCharacteristic = discoveredCharacteristic;
|
||
// print("1111111111111111characteristicId:${result[i].characteristicIds[j].toString()} serviceId:${result[i].serviceId} deviceId:$deviceMAC");
|
||
// }
|
||
// if (discoveredCharacteristic.characteristicId.toString() == "fff2") {
|
||
// // 用来写入
|
||
// characteristicIdWrite= discoveredCharacteristic.characteristicId;
|
||
// // print("1111111111111111characteristicId:${discoveredCharacteristic.characteristicId} serviceId:${serviceId} deviceId:$deviceId");
|
||
// // qualifiedCharacteristic = QualifiedCharacteristic(characteristicId: discoveredCharacteristic.characteristicId, serviceId:serviceId , deviceId: deviceId);
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
// _subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: characteristicIdSubscription, serviceId: Uuid.parse("fff0"), deviceId: deviceMAC));
|
||
// print('Discovering services finished');
|
||
//
|
||
// if(isFrist == true){
|
||
// // 第一次添加锁的时候需要先获取公钥
|
||
// IoSenderManage.getPublicKey(lockId: deviceName);
|
||
// }
|
||
// return result;
|
||
// } on Exception catch (e) {
|
||
// print('Error occurred when discovering services: $e');
|
||
// rethrow;
|
||
// }
|
||
// }
|
||
|
||
// 听上报来的数据,参数来自前面扫描到的结果
|
||
var allData = <int>[];
|
||
_subScribeToCharacteristic(QualifiedCharacteristic characteristic) {
|
||
_flutterReactiveBle!.subscribeToCharacteristic(characteristic).listen((data) {
|
||
// code to handle incoming data
|
||
print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
||
var dataLen = 0;// 高16位用来指示后面数据块内容的长度
|
||
|
||
if((data[0] == 0xEF)&&(data[1] == 0x01)&&(data[2] == 0xEE)&&(data[3] == 0x02)){
|
||
// 当包有头时
|
||
// 判断是否需要分包
|
||
dataLen = data[8] * 256 + data[9];
|
||
print("dataLen1111:$dataLen getDataLength:${data.length}");
|
||
if(dataLen + 12 > data.length){
|
||
// 当前包的长度小于实际的包时 分包添加 不解析
|
||
allData.addAll(data);
|
||
}else{
|
||
// 当前包的长度小于实际的包时 不分包 解析
|
||
allData.addAll(data);
|
||
CommandReciverManager.appDataReceive(allData);
|
||
// 发送完解析初始化数组
|
||
allData = <int>[];
|
||
}
|
||
}else{
|
||
// 当包没有头时 是分包的包 直接添加
|
||
allData.addAll(data);
|
||
// var len = allData[8] * 256 + allData[9];
|
||
print("dataLen222:$dataLen");
|
||
if(dataLen <= (allData.length - 14)){
|
||
// 当长度小于等于当前包的数据时 直接解析数据
|
||
CommandReciverManager.appDataReceive(allData);
|
||
// 发送完解析初始化数组
|
||
allData = <int>[];
|
||
}
|
||
}
|
||
}, onError: (dynamic error) {
|
||
EasyLoading.dismiss();
|
||
print("subscribeToCharacteristic error:$error");
|
||
});
|
||
}
|
||
|
||
// 写入
|
||
Future<void> writeCharacteristicWithResponse(List<int> value) async {
|
||
QualifiedCharacteristic characteristic = QualifiedCharacteristic(characteristicId: characteristicIdWrite, serviceId: serviceId, deviceId: connectDeviceMacAddress);
|
||
print('Write with characteristicId:${characteristic.characteristicId} serviceId:${characteristic.serviceId} deviceId:${characteristic.deviceId} value : $value \nhexStr:${radixHex16String(value)}');
|
||
int mtuLength = await _flutterReactiveBle!.requestMtu(deviceId: characteristic.deviceId, mtu: 250);
|
||
print("mtuLength:$mtuLength");
|
||
try {
|
||
List<int> valueList = value;
|
||
List subData = splitList(valueList, mtuLength);
|
||
print('得到的分割数据:$subData');
|
||
|
||
for (int i = 0; i < subData.length; i++) {
|
||
await _flutterReactiveBle!.writeCharacteristicWithResponse(characteristic, value: subData[i]).then((value) async {
|
||
await Future.delayed(const Duration(milliseconds: 1))
|
||
.then((value) async {
|
||
print('分包发送成功了');
|
||
});
|
||
});
|
||
}
|
||
} on Exception catch (e, s) {
|
||
print('Error occurred when writing: $e');
|
||
// ignore: avoid_print
|
||
print(s);
|
||
rethrow;
|
||
}
|
||
}
|
||
|
||
// 读取
|
||
Future<List<int>> readCharacteristic(QualifiedCharacteristic characteristic) async {
|
||
try {
|
||
final result = await _flutterReactiveBle!.readCharacteristic(characteristic);
|
||
print("readListresult$result");
|
||
return result;
|
||
} on Exception catch (e, s) {
|
||
print('Error occurred when reading ${characteristic.characteristicId} : $e',);
|
||
rethrow;
|
||
}
|
||
}
|
||
|
||
Future<void> writeCharacteristicWithoutResponse(
|
||
QualifiedCharacteristic characteristic, List<int> value) async {
|
||
try {
|
||
await _flutterReactiveBle!.writeCharacteristicWithoutResponse(characteristic,
|
||
value: value);
|
||
} on Exception catch (e, s) {
|
||
// ignore: avoid_print
|
||
print(s);
|
||
rethrow;
|
||
}
|
||
}
|
||
|
||
disposed(){
|
||
_sendStreamSubscription?.cancel();
|
||
}
|
||
} |