app-starlock/star_lock/lib/blue/blue_manage.dart
2024-05-07 16:47:56 +08:00

708 lines
26 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'io_tool/io_model.dart';
import 'io_tool/io_tool.dart';
import 'io_tool/manager_event_bus.dart';
import 'reciver_data.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
//连接状态回调
typedef ConnectStateCallBack = Function(
BluetoothConnectionState connectionState);
typedef ScanDevicesCallBack = Function(List<ScanResult>);
class BlueManage {
final List<ScanResult> scanDevices = [];
// 用来写入的服务id
final Guid _serviceIdConnect = Guid("fff0");
// 用来写入的服务id
final Guid _serviceIdWrite = Guid('0000FFF0-0000-1000-8000-00805F9B34FB');
// 用来订阅的特征id
final Guid _characteristicIdSubscription = Guid("fff1");
// 用来写入的特征id
final Guid _characteristicIdWrite = Guid("fff2");
// 监听发送事件
StreamSubscription<EventSendModel>? _sendStreamSubscription;
// 监听蓝牙扫描的事件
// StreamSubscription? _scanSubscription;
// 监听蓝牙连接的事件
// StreamSubscription<dynamic>? _currentConnectionStream;
// StreamSubscription<List<ScanResult>>? _scanResultsSubscription;
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
StreamSubscription<int>? _mtuSubscription;
int? _mtuSize = 20;
// 当前连接设备的名字
String connectDeviceName = "";
// 当前连接设备的mac地址
String connectDeviceMacAddress = "";
// 当前连接的设备
BluetoothDevice? bluetoothConnectDevice;
// 当前扫描到结果要连接设备
ScanResult? scanResult;
// 监听蓝牙连接状态
BluetoothConnectionState? bluetoothConnectionState =
BluetoothConnectionState.disconnected;
BluetoothAdapterState? _adapterState = BluetoothAdapterState.unknown;
StreamSubscription<BluetoothAdapterState>? _adapterStateStateSubscription;
static BlueManage? _manager;
BlueManage._init() {
_initBlue();
}
static BlueManage? shareManager() {
_manager ??= BlueManage._init();
// _manager!._initBlue();
return _manager;
}
factory BlueManage() => shareManager()!;
BlueManage? get manager => shareManager();
void _initBlue() {
FlutterBluePlus.setLogLevel(LogLevel.error, color: true);
_initSendStreamSubscription();
_initAdapterStateStateSubscription();
// _initListenscanResults();
// _initListenConnectionState();
}
void _initGetMtuSubscription() {
_mtuSubscription ??= bluetoothConnectDevice!.mtu.listen((value) {
_mtuSize = value - 3;
AppLog.log('_mtuSizeValue:$value mtuSize:$_mtuSize');
});
}
void _initAdapterStateStateSubscription() {
_adapterStateStateSubscription ??=
FlutterBluePlus.adapterState.listen((state) {
_adapterState = state;
});
}
// void _initListenscanResults() {
// var subscription = FlutterBluePlus.scanResults.listen((results) {
// scanDevices.clear();
// for (var scanResult in results) {
// // 判断名字为空的直接剔除
// // if (scanResult.device.advName.isEmpty) {
// // return;
// // }
// AppLog.log("scanResult.device.advName:${scanResult.device.advName}"
// " scanResult.advertisementData.serviceUuids:${scanResult.advertisementData.serviceUuids}"
// " rssi:${scanResult.rssi}");
// if (((scanResult.advertisementData.serviceUuids.isNotEmpty ? scanResult.advertisementData.serviceUuids[0] : "").toString().contains("758824")) && (scanResult.rssi >= -100)) {
// // 查询id相同的元素
// final knownDeviceIndex = scanDevices.indexWhere((d) => d.advertisementData.advName == scanResult.advertisementData.advName);
// // 不存在的时候返回-1
// if (knownDeviceIndex >= 0) {
// scanDevices[knownDeviceIndex] = scanResult;
// } else {
// scanDevices.add(scanResult);
// }
// }
// }
// EventBusManager().eventBusFir(scanDevices);
// // FlutterBluePlus.stopScan();
// }, onError: (e) {
// AppLog.log("Scan Error:$e", );
// });
//
// FlutterBluePlus.cancelWhenScanComplete(subscription);
// FlutterBluePlus.isScanning.listen((state) {
// if (state) {
// prAppLog.logint('Scanning');
// } else {
// AppLog.log('Not scanning');
// }
// });
// }
void _initListenConnectionState() {
_connectionStateSubscription?.cancel();
_connectionStateSubscription = null;
_connectionStateSubscription =
bluetoothConnectDevice!.connectionState.listen((state) async {
bluetoothConnectionState = state;
// AppLog.log("蓝牙连接状态:$state");
});
}
void _initSendStreamSubscription() {
_sendStreamSubscription ??= EventBusManager()
.eventBus!
.on<EventSendModel>()
.listen((EventSendModel model) {
if (model.sendChannel == DataChannel.ble) {
FlutterBluePlus.isSupported.then((isAvailable) async {
if (isAvailable) {
if (_adapterState == BluetoothAdapterState.on) {
// 蓝牙已开启,可以进行蓝牙操作
writeCharacteristicWithResponse(model.data);
} else {
try {} catch (e) {
AppLog.log("蓝牙打开失败");
}
}
} else {
AppLog.log("写入数据 蓝牙不可用,不能进行蓝牙操作");
}
});
}
});
}
/// 开始指定设备名称的扫描蓝牙设备
Future<void> startScanSingle(String deviceName, int timeout,
ScanDevicesCallBack scanDevicesCallBack) async {
FlutterBluePlus.isSupported.then((isAvailable) async {
if (isAvailable) {
if (_adapterState == BluetoothAdapterState.on) {
try {
FlutterBluePlus.startScan(timeout: Duration(seconds: timeout));
Completer<dynamic> completer = Completer<dynamic>();
var subscription = FlutterBluePlus.scanResults.listen((results) {
// AppLog.log("startScanSingle扫描到的设备:$results");
bool isExit = results.any((element) =>
(element.device.platformName == deviceName) ||
(element.advertisementData.advName == deviceName));
if (isExit) {
for (var scanResult in results) {
if (((scanResult.advertisementData.serviceUuids.isNotEmpty
? scanResult.advertisementData.serviceUuids[0]
: "")
.toString()
.contains("758824")) &&
(scanResult.rssi >= -100)) {
// 查询id相同的元素
final knownDeviceIndex = scanDevices.indexWhere((d) =>
(d.device.platformName ==
scanResult.device.platformName) ||
(d.advertisementData.advName ==
scanResult.advertisementData.advName));
// 不存在的时候返回-1
if (knownDeviceIndex >= 0) {
scanDevices[knownDeviceIndex] = scanResult;
} else {
scanDevices.add(scanResult);
}
}
}
completer.complete();
}
}, onError: (e) {
AppLog.log(
"扫描失败:$e",
);
});
FlutterBluePlus.cancelWhenScanComplete(subscription);
await completer.future;
scanDevicesCallBack(scanDevices);
subscription.cancel();
} catch (e) {
AppLog.log("扫描失败");
}
} else {
try {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
} catch (e) {
AppLog.log("蓝牙打开失败");
}
}
} else {
AppLog.log("开始扫描 蓝牙不可用,不能进行蓝牙操作");
}
});
}
/// 开始扫描蓝牙设备
Future<void> startScan(int timeout, ScanDevicesCallBack scanDevicesCallBack,
{List<Guid>? idList}) async {
FlutterBluePlus.isSupported.then((isAvailable) async {
if (isAvailable) {
if (_adapterState == BluetoothAdapterState.on) {
try {
FlutterBluePlus.startScan(timeout: Duration(seconds: timeout));
var subscription = FlutterBluePlus.scanResults.listen((results) {
scanDevices.clear();
for (var scanResult in results) {
// 判断名字为空的直接剔除
// if (scanResult.device.advName.isEmpty) {
// return;
// }
// AppLog.log("scanResult.device.advName:${scanResult.device.advName}"
// " scanResult.advertisementData.serviceUuids:${scanResult.advertisementData.serviceUuids}"
// " rssi:${scanResult.rssi}");
if (((scanResult.advertisementData.serviceUuids.isNotEmpty
? scanResult.advertisementData.serviceUuids[0]
: "")
.toString()
.contains("758824")) &&
(scanResult.rssi >= -100)) {
// 查询id相同的元素
final knownDeviceIndex = scanDevices.indexWhere((d) =>
(d.device.platformName ==
scanResult.device.platformName) ||
(d.advertisementData.advName ==
scanResult.advertisementData.advName));
// 不存在的时候返回-1
if (knownDeviceIndex >= 0) {
scanDevices[knownDeviceIndex] = scanResult;
} else {
scanDevices.add(scanResult);
}
}
}
scanDevicesCallBack(scanDevices);
// EventBusManager().eventBusFir(scanDevices);
// FlutterBluePlus.stopScan();
}, onError: (e) {
AppLog.log(
"扫描失败:$e",
);
});
FlutterBluePlus.cancelWhenScanComplete(subscription);
} catch (e) {
AppLog.log("扫描失败");
}
} else {
try {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
} catch (e) {
AppLog.log("蓝牙打开失败");
}
}
} else {
AppLog.log("开始扫描 蓝牙不可用,不能进行蓝牙操作");
}
});
}
/// 调用发送数据 List senderData,
Future<void> bludSendData(
String deviceName, ConnectStateCallBack stateCallBack,
{bool isAddEquipment = false}) async {
FlutterBluePlus.isSupported.then((isAvailable) async {
if (isAvailable) {
if (_adapterState == BluetoothAdapterState.on) {
// 蓝牙已开启,可以进行蓝牙操作
if (bluetoothConnectionState != BluetoothConnectionState.connected) {
_connect(deviceName, (state) {
stateCallBack(bluetoothConnectionState!);
}, isAddEquipment: isAddEquipment);
} else {
stateCallBack(bluetoothConnectionState!);
}
} else {
try {
stateCallBack(BluetoothConnectionState.disconnected);
openBlue();
} catch (e) {
AppLog.log("蓝牙打开失败");
}
}
} else {
AppLog.log("开始扫描 蓝牙不可用,不能进行蓝牙操作");
}
});
}
/// 连接
Future<void> _connect(
String deviceName, ConnectStateCallBack connectStateCallBack,
{bool isAddEquipment = false}) async {
connectDeviceName = deviceName;
List<ScanResult> devicesList = scanDevices;
if (isAddEquipment == false) {
//取消缓存直接使用,存在配对场景设备信息会更变
startScan(10, (List<ScanResult> scanDevices) {
_connectDevice(devicesList, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
});
} else {
_connectDevice(devicesList, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
}
}
Future<void> _connectDevice(List<ScanResult> devicesList, String deviceName,
ConnectStateCallBack connectStateCallBack,
{bool isAddEquipment = false}) async {
// 判断数组列表里面是否有这个设备
// AppLog.log("devicesList:$devicesList");
final knownDeviceIndex = devicesList.indexWhere((d) =>
(d.device.platformName == deviceName) ||
(d.advertisementData.advName == deviceName));
if (knownDeviceIndex >= 0) {
// 存在的时候赋值
connectDeviceMacAddress =
devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty
? devicesList[knownDeviceIndex].advertisementData.advName
: devicesList[knownDeviceIndex].device.platformName;
bluetoothConnectDevice = devicesList[knownDeviceIndex].device;
// AppLog.log('bluetoothConnectDevice: $bluetoothConnectDevice');
scanResult = devicesList[knownDeviceIndex];
_initGetMtuSubscription();
_initListenConnectionState();
}
// AppLog.log("1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName");
// stopScan();
if (connectDeviceMacAddress.isEmpty) {
// connectStateCallBack(BluetoothConnectionState.disconnected!);
return;
}
// AppLog.log("调用了停止扫描的方法");
await stopScan();
if ((scanResult!.advertisementData.serviceUuids[0].toString()[31] == "0") &&
isAddEquipment == false) {
connectStateCallBack(BluetoothConnectionState.disconnected);
EasyLoading.showToast("该锁已被重置".tr, duration: 2000.milliseconds);
return;
}
// 重连三次
int maxAttempts = 3;
int attempt = 0;
while (attempt < maxAttempts) {
try {
await bluetoothConnectDevice!.connect(timeout: 5.seconds);
break; // If the connection is successful, break the loop
} catch (e) {
AppLog.log('连接失败 重连了: $e');
attempt++; // Increase the attempt count
if (attempt < maxAttempts) {
AppLog.log('重新尝试连接...');
}
}
}
if (attempt >= maxAttempts) {
AppLog.log('$maxAttempts次后尝试连接失败');
connectStateCallBack(BluetoothConnectionState.disconnected);
}
// await bluetoothConnectDevice!.connect();
if (bluetoothConnectionState == BluetoothConnectionState.connected) {
try {
bluetoothConnectDevice!.discoverServices().then((services) {
for (BluetoothService service in services) {
// AppLog.log("11111service.remoteId:${service.remoteId}"
// " service.uuid:${service.uuid}"
// " service.characteristics:${service.characteristics}"
// " service.includedServices:${service.includedServices}");
if (service.uuid == _serviceIdConnect) {
for (BluetoothCharacteristic characteristic
in service.characteristics) {
// Get.log("22222characteristic.remoteId:${characteristic.remoteId}"
// " characteristic.uuid:${characteristic.uuid}"
// " characteristic.secondaryServiceUuid:${characteristic.secondaryServiceUuid}"
// " characteristic.characteristicUuid:${characteristic.characteristicUuid}");
if (characteristic.characteristicUuid ==
_characteristicIdSubscription) {
_subScribeToCharacteristic(characteristic);
// AppLog.log('Discovering services finished');
bluetoothConnectionState = BluetoothConnectionState.connected;
connectStateCallBack(bluetoothConnectionState!);
}
}
}
}
});
} on Exception catch (e) {
bluetoothConnectionState = BluetoothConnectionState.disconnected;
connectStateCallBack(bluetoothConnectionState!);
AppLog.log(
'发现设备时失败 e:$e bluetoothConnectionState:$bluetoothConnectionState');
rethrow;
}
}
}
// 听上报来的数据,参数来自前面扫描到的结果
var allData = <int>[];
// 保存上一次的数据,用来判断是否收到重复的数据
var lastTimeData = <int>[];
int? dataLen;
_subScribeToCharacteristic(BluetoothCharacteristic characteristic) async {
final subscription = characteristic.onValueReceived.listen((data) {
AppLog.log("订阅获取的数据:$data");
if (data == lastTimeData || data.isEmpty) {
return;
} else {
lastTimeData = data;
}
// code to handle incoming data
// AppLog.log("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
if ((data[0] == 0xEF) &&
(data[1] == 0x01) &&
(data[2] == 0xEE) &&
(data[3] == 0x02)) {
// 当包有头时
// 判断是否需要分包
dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
// AppLog.log("dataLen1111:$dataLen getDataLength:${data.length} data:$data");
if (dataLen! + 14 > data.length) {
// 当前包的长度小于实际的包时 分包添加 不解析
allData.addAll(data);
} else {
// 当前包的长度小于实际的包时 不分包 解析
allData.addAll(data);
// AppLog.log("dataLen2222:$dataLen getDataLength:${data.length}");
CommandReciverManager.appDataReceive(allData);
// 发送完解析初始化数组
allData = <int>[];
}
} else {
// 当包没有头时 是分包的包 直接添加
allData.addAll(data);
// var len = allData[8] * 256 + allData[9];
AppLog.log("dataLen3333:$dataLen allData.length:${allData.length} allData:$allData");
if ((dataLen! + 14) <= allData.length) {
// 当长度小于等于当前包的数据时 直接解析数据
CommandReciverManager.appDataReceive(allData);
// 发送完解析初始化数组
allData = <int>[];
}
}
});
// cleanup: cancel subscription when disconnected
bluetoothConnectDevice!.cancelWhenDisconnected(subscription);
// enable notifications
await characteristic.setNotifyValue(true);
// characteristic.setNotifyValue(true).then((_) {
// AppLog.log("启动对特性的通知。当特性的值发生变化时,设备会发送一个通知");
// characteristic.lastValueStream.listen((data) {
// AppLog.log("订阅获取的数据:$data");
// // do something with new value
// if(data == lastTimeData || data.isEmpty){
// return;
// }else{
// lastTimeData = data;
// }
// // code to handle incoming data
// // AppLog.log("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
// if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && (data[3] == 0x02)) {
// // 当包有头时
// // 判断是否需要分包
// dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
// // AppLog.log("dataLen1111:$dataLen getDataLength:${data.length}");
// if (dataLen! + 12 > data.length) {
// // 当前包的长度小于实际的包时 分包添加 不解析
// allData.addAll(data);
// } else {
// // 当前包的长度小于实际的包时 不分包 解析
// allData.addAll(data);
// // AppLog.log("dataLen2222:$dataLen getDataLength:${data.length}");
// CommandReciverManager.appDataReceive(allData);
// // 发送完解析初始化数组
// allData = <int>[];
// }
// } else {
// // 当包没有头时 是分包的包 直接添加
// allData.addAll(data);
// // var len = allData[8] * 256 + allData[9];
// // AppLog.log("dataLen3333:$dataLen");
// if ((dataLen! + 14) <= allData.length) {
// // AppLog.log("44444数据被解析了");
// // 当长度小于等于当前包的数据时 直接解析数据
// CommandReciverManager.appDataReceive(allData);
// // 发送完解析初始化数组
// allData = <int>[];
// }
// }
// });
// });
}
// 写入
Future<void> writeCharacteristicWithResponse(List<int> value) async {
List<BluetoothService> services =
await bluetoothConnectDevice!.discoverServices();
for (BluetoothService service in services) {
// AppLog.log("33333 service.remoteId:${service.remoteId}"
// " service.uuid:${service.uuid}\n\n"
// " service.characteristics:${service.characteristics}\n\n"
// " service.includedServices:${service.includedServices}");
if (service.uuid == _serviceIdConnect) {
for (BluetoothCharacteristic characteristic
in service.characteristics) {
// AppLog.log("44444 characteristic.remoteId:${characteristic.remoteId}"
// " characteristic.uuid:${characteristic.uuid}\n\n"
// " characteristic.secondaryServiceUuid:${characteristic
// .secondaryServiceUuid}\n\n"
// " characteristic.characteristicUuid:${characteristic
// .characteristicUuid}");
if (characteristic.characteristicUuid == _characteristicIdWrite) {
try {
List<int> valueList = value;
List subData = splitList(valueList, _mtuSize!);
// AppLog.log('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData');
for (int i = 0; i < subData.length; i++) {
if (characteristic.properties.writeWithoutResponse) {
// 使用WRITE_NO_RESPONSE属性写入值
await characteristic
.write(subData[i], withoutResponse: true)
.then((value) async {
// await Future.delayed(const Duration(milliseconds: 1)).then((
// value) async {
// AppLog.log('分包发送成功了');
// });
});
} else if (characteristic.properties.write) {
// 使用WRITE属性写入值
await characteristic.write(subData[i]).then((value) async {
// await Future.delayed(const Duration(milliseconds: 1)).then((
// value) async {
// AppLog.log('分包发送成功了');
// });
});
} else {
// 特性不支持写入
throw Exception(
'This characteristic does not support writing.');
}
}
} on Exception catch (e, s) {
AppLog.log('APP写入失败: $e');
rethrow;
}
}
}
}
}
// List<BluetoothService> services = await bluetoothConnectDevice!.discoverServices();
// BluetoothCharacteristic characteristic = services
// .firstWhere((service) => service.uuid == _serviceIdWrite)
// .characteristics
// .firstWhere((char) => char.uuid == _characteristicIdWrite);
// try {
// List<int> valueList = value;
// List subData = splitList(valueList, _mtuSize!);
// AppLog.log('writeCharacteristicWithResponse 得到的分割数据:$subData');
//
// for (int i = 0; i < subData.length; i++) {
// await characteristic.write(subData[i]).then((value) async {
// await Future.delayed(const Duration(milliseconds: 1)).then((value) async {
// AppLog.log('分包发送成功了');
// });
// });
// }
// } on Exception catch (e, s) {
// AppLog.log('Error occurred when writing: $e');
// AppLog.log(s);
// rethrow;
// }
}
// 读取
// Future<List<int>> _readCharacteristic(QualifiedCharacteristic characteristic) async {
// try {
// final result =
// await _flutterReactiveBle!.readCharacteristic(characteristic);
// AppLog.log("readListresult$result");
// return result;
// } on Exception catch (e, s) {
// AppLog.log(
// '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
// AppLog.log(s);
// rethrow;
// }
// }
// 停止扫描蓝牙设备
Future<void> stopScan() async {
try {
await FlutterBluePlus.stopScan();
} catch (e) {
AppLog.log("停止扫描失败");
}
}
// 断开连接
Future<void> disconnect() async {
try {
// if(bluetoothConnectDevice != null && bluetoothConnectDevice!.connectionState == BluetoothConnectionState.connected){
connectDeviceMacAddress = "";
if (bluetoothConnectionState == BluetoothConnectionState.connected) {
await bluetoothConnectDevice!.disconnect();
AppLog.log("断开连接成功");
}
// }
} on Exception catch (e, _) {
AppLog.log("断开连接失败: $e");
} finally {
bluetoothConnectionState = BluetoothConnectionState.disconnected;
}
}
openBlue() async {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
if (Platform.isIOS) {
EasyLoading.showToast("请开启蓝牙", duration: 2000.milliseconds);
}
}
disposed() {
_sendStreamSubscription?.cancel();
_mtuSubscription!.cancel();
// _scanResultsSubscription!.cancel();
_adapterStateStateSubscription!.cancel();
_connectionStateSubscription!.cancel();
}
}