import 'dart:async'; import 'dart:io'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/commonDataManage.dart'; import 'io_tool/io_model.dart'; import 'io_tool/io_tool.dart'; import 'io_tool/manager_event_bus.dart'; import 'io_type.dart'; import 'reciver_data.dart'; //连接状态回调 typedef ConnectStateCallBack = Function( BluetoothConnectionState connectionState); typedef ScanDevicesCallBack = Function(List); class BlueManage { factory BlueManage() => shareManager()!; BlueManage._init() { _initBlue(); } final List 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? _sendStreamSubscription; StreamSubscription? _connectionStateSubscription; StreamSubscription? _mtuSubscription; int? _mtuSize = 20; // 当前连接设备的名字 String connectDeviceName = ''; // 当前连接设备的mac地址 String connectDeviceMacAddress = ''; // 当前连接的设备 BluetoothDevice? bluetoothConnectDevice; // 当前扫描到结果要连接设备 ScanResult? scanResult; // 监听蓝牙连接状态 BluetoothConnectionState? bluetoothConnectionState = BluetoothConnectionState.disconnected; BluetoothAdapterState? _adapterState = BluetoothAdapterState.on; StreamSubscription? _adapterStateStateSubscription; // 听上报来的数据,参数来自前面扫描到的结果 List allData = []; // 保存上一次的数据,用来判断是否收到重复的数据 List lastTimeData = []; int? dataLen; Timer? scanSingleTimer; bool needScanSingle = false; static BlueManage? _manager; static BlueManage? shareManager() { _manager ??= BlueManage._init(); // _manager!._initBlue(); return _manager; } BlueManage? get manager => shareManager(); void _initBlue() { FlutterBluePlus.setLogLevel(LogLevel.error, color: true); _initSendStreamSubscription(); _initAdapterStateStateSubscription(); } void _initGetMtuSubscription() { _mtuSubscription ??= bluetoothConnectDevice!.mtu.listen((int value) { _mtuSize = value - 3; AppLog.log('_mtuSizeValue:$value mtuSize:$_mtuSize'); }); } void _initAdapterStateStateSubscription() { _adapterStateStateSubscription ??= FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) { AppLog.log('蓝牙状态:$state'); _adapterState = state; }); } void _initListenConnectionState() { _connectionStateSubscription?.cancel(); _connectionStateSubscription = null; _connectionStateSubscription = bluetoothConnectDevice!.connectionState .listen((BluetoothConnectionState state) async { bluetoothConnectionState = state; AppLog.log('蓝牙连接回调状态:$state'); }); } void _initSendStreamSubscription() { _sendStreamSubscription ??= EventBusManager() .eventBus! .on() .listen((EventSendModel model) { if (model.sendChannel == DataChannel.ble) { FlutterBluePlus.isSupported.then((bool isAvailable) async { if (isAvailable) { if (_adapterState == BluetoothAdapterState.on) { // 蓝牙已开启,可以进行蓝牙操作 writeCharacteristicWithResponse(model.data); } else { try {} catch (e) { AppLog.log('蓝牙打开失败'); } } } else { AppLog.log('写入数据 蓝牙不可用,不能进行蓝牙操作'); } }); } }); } /// 开始指定设备名称的扫描蓝牙设备 Future startScanSingle(String deviceName, int timeout, ScanDevicesCallBack scanDevicesCallBack) async { final DateTime start = DateTime.now(); FlutterBluePlus.isSupported.then((bool isAvailable) async { if (isAvailable) { // AppLog.log('startScanSingle 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState'); if (_adapterState == BluetoothAdapterState.on) { try { BuglyTool.uploadException( message: '开始指定设备名称的扫描蓝牙设备', detail: '调用方法是:startScanSingle 指定设备名称是:$deviceName', upload: false); //android 扫描比较慢,取样只要 3 分之一 final int divisor = Platform.isAndroid ? 3 : 1; FlutterBluePlus.startScan( continuousDivisor: divisor, continuousUpdates: true, withKeywords: [deviceName], timeout: Duration(seconds: timeout)); final Completer completer = Completer(); final StreamSubscription> subscription = FlutterBluePlus.scanResults.listen((List results) { final bool isExit = results.any((ScanResult element) => (element.device.platformName == deviceName) || (element.advertisementData.advName == deviceName)); final int milliseconds = DateTime.now().millisecondsSinceEpoch - start.millisecondsSinceEpoch; AppLog.log( '扫描到的设备数:${results.length} 是否查找到 $isExit 以查找$milliseconds毫秒'); BuglyTool.uploadException( message: '指定设备名称的扫描蓝牙设备 监听扫描结果', detail: 'startScanSingle$deviceName 监听扫描结果 是否查找到 $isExit 以查找$milliseconds毫秒 扫描到的设备数:${results.length} results:$results', upload: false); if (isExit) { for (final ScanResult scanResult in results) { if (((scanResult.advertisementData.serviceUuids.isNotEmpty ? scanResult.advertisementData.serviceUuids[0] : '') .toString() .contains('758824')) && (scanResult.rssi >= -100)) { // 查询id相同的元素 final int knownDeviceIndex = scanDevices.indexWhere( (ScanResult d) => (d.device.platformName == scanResult.device.platformName) || (d.advertisementData.advName == scanResult.advertisementData.advName)); // 不存在的时候返回-1 if (knownDeviceIndex >= 0) { scanDevices[knownDeviceIndex] = scanResult; } else { scanDevices.add(scanResult); } BuglyTool.uploadException( message: '遍历扫描到的结果跟缓存的结果对比,如果有最新的就更新缓存', detail: 'startScanSingle deviceName:$deviceName 查询到的结果scanResult:$scanResult', upload: false); } } completer.complete(); } }, onError: (e) { BuglyTool.uploadException( message: '指定设备名称的扫描蓝牙设备 监听扫描结果失败', detail: '打印失败问题 e:${e.toString()}', upload: false); AppLog.log('扫描失败:$e'); }); FlutterBluePlus.cancelWhenScanComplete(subscription); await completer.future; scanDevicesCallBack(scanDevices); subscription.cancel(); } catch (e) { BuglyTool.uploadException( message: '指定设备名称的扫描蓝牙设备 内部逻辑整形失败', detail: 'tartScanSingle内部逻辑整形失败 e:${e.toString()}', upload: false); AppLog.log('扫描失败'); } } else { try { openBlue(); } catch (e) { AppLog.log('蓝牙打开失败'); } } } else { AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作'); } }); } /// 开始扫描蓝牙设备 Future startScan(int timeout, DeviceType deviceType, ScanDevicesCallBack scanDevicesCallBack, {List? idList}) async { FlutterBluePlus.isSupported.then((bool isAvailable) async { if (isAvailable) { // AppLog.log('startScan 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState'); if (_adapterState == BluetoothAdapterState.on) { try { FlutterBluePlus.startScan(timeout: Duration(seconds: timeout)); final StreamSubscription> subscription = FlutterBluePlus.scanResults.listen((List results) { scanDevices.clear(); for (final ScanResult scanResult in results) { // AppLog.log('扫描到的设备:${scanResult.device.platformName} ${scanResult.advertisementData.advName} ${scanResult.rssi}'); // 判断名字为空的直接剔除 if (((scanResult.advertisementData.serviceUuids.isNotEmpty ? scanResult.advertisementData.serviceUuids[0] : '') .toString() .contains(getDeviceType(deviceType))) && (scanResult.rssi >= -100)) { // 查询id相同的元素 final int knownDeviceIndex = scanDevices.indexWhere( (ScanResult 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); }, onError: (e) { AppLog.log( '扫描失败:$e', ); }); FlutterBluePlus.cancelWhenScanComplete(subscription); } catch (e) { AppLog.log('扫描失败'); } } else { try { openBlue(); } catch (e) { AppLog.log('蓝牙打开失败'); } } } else { AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作'); } }); } /// 调用发送数据 List senderData, Future blueSendData( String deviceName, ConnectStateCallBack stateCallBack, {bool isAddEquipment = false}) async { FlutterBluePlus.isSupported.then((bool isAvailable) async { if (isAvailable) { // AppLog.log('蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState'); if (_adapterState == BluetoothAdapterState.on) { // 蓝牙已开启,可以进行蓝牙操作 if (bluetoothConnectionState != BluetoothConnectionState.connected) { BuglyTool.uploadException( message: '点击按钮 蓝牙未连接 下一步扫描连接蓝牙', detail: 'blueSendData 蓝牙连接状态 bluetoothConnectionState:$bluetoothConnectionState deviceName:$deviceName', upload: false); _connect(deviceName, (BluetoothConnectionState state) { stateCallBack(bluetoothConnectionState!); }, isAddEquipment: isAddEquipment); } else { BuglyTool.uploadException( message: '点击按钮 蓝牙已经连接 下一步扫描连接蓝牙', detail: 'blueSendData 直接回调状态 蓝牙连接状态bluetoothConnectionState:$bluetoothConnectionState deviceName:$deviceName', upload: false); stateCallBack(bluetoothConnectionState!); } } else { BuglyTool.uploadException( message: '点击按钮 蓝牙未打开', detail: 'blueSendData 蓝牙未打开--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName', upload: false); try { stateCallBack(BluetoothConnectionState.disconnected); openBlue(); } catch (e) { AppLog.log('蓝牙打开失败'); BuglyTool.uploadException( message: '点击按钮 蓝牙未打开 然后蓝牙打开失败', detail: 'blueSendData 蓝牙打开失败--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName', upload: false); } } } else { BuglyTool.uploadException( message: '点击按钮 蓝牙状态不可用', detail: 'blueSendData 蓝牙状态不可用--isAvailable:$isAvailable', upload: false); stateCallBack(BluetoothConnectionState.disconnected); AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作'); } }); } /// 连接 Future _connect( String deviceName, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async { connectDeviceName = deviceName; // 当前已扫描到的缓存设备 final List devicesList = scanDevices; // 是否有缓存设备 true是有缓存设备 final bool isExistDevice = isExistScanDevices(connectDeviceName); // 是否是当前设备 final bool isCurrentDevice = CommonDataManage().currentKeyInfo.lockName == deviceName; // mac地址 final String? mac = CommonDataManage().currentKeyInfo.mac; AppLog.log('开始连接 是否存在缓存:$isExistDevice 是否是当前设备:$isCurrentDevice mac:$mac'); if (GetPlatform.isAndroid && !isExistDevice && isCurrentDevice && mac != null) { // 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 BuglyTool.uploadException( message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是:_connect', detail: '调用方法_connect deviceName:$deviceName GetPlatform.isAndroid:${GetPlatform.isAndroid} isExistDevice:$isExistDevice mac:$mac needScanSingle:$needScanSingle', upload: false); // scanSingleTimer?.cancel(); // 兼容android 的低配手机 try { if (!needScanSingle) { BuglyTool.uploadException( message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是:_connect', detail: '调用方法doNotSearchBLE,直接连接,needScanSingle:$needScanSingle', upload: false); await doNotSearchBLE(mac, connectStateCallBack, isAddEquipment: isAddEquipment); } else { BuglyTool.uploadException( message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是:_connect', detail: '调用方法startScanSingle,执行扫描函数,needScanSingle:$needScanSingle', upload: false); startScanSingle(deviceName, 15, (List scanDevices) { _connectDevice(scanDevices, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); }); } } catch (e) { BuglyTool.uploadException( message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是:_connect', detail: '调用方法doNotSearchBLE发生异常,执行扫描函数 startScanSingle,异常信息:$e', upload: false); startScanSingle(deviceName, 15, (List scanDevices) { _connectDevice(scanDevices, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); }); } // // scanSingleTimer = Timer(3.seconds, () { // scanSingleTimer?.cancel(); // BuglyTool.uploadException( // message: // '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 3秒以后调用startScanSingle 上传记录当前方法是:_connect', // detail: // '_connect deviceName:$deviceName scanSingleTimer调用startScanSingle', // upload: false); // startScanSingle(deviceName, 15, (List scanDevices) => null); // });ƒ } else if (isAddEquipment == false && isExistDevice == false) { // 取消缓存直接使用,存在配对场景设备信息会更变 BuglyTool.uploadException( message: '取消缓存直接使用,存在配对场景设备信息会更变 然后开始指定设备名称的扫描蓝牙设备 上传记录当前方法是:_connect', detail: '符合条件(isAddEquipment == false && isExistDevice == false) 下一步调用startScanSingle', upload: false); // AppLog.log('无存在设备需要扫描 deviceName:$deviceName isAddEquipment:$isAddEquipment'); startScanSingle(deviceName, 15, (List scanDevices) { _connectDevice(scanDevices, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); }); } else { BuglyTool.uploadException( message: '没有扫描直接调用连接设备 上传记录当前方法是:_connect', detail: '走这个方法是有缓存或者添加设备的时候以及不符合(GetPlatform.isAndroid && !isExistDevice && isCurrentDevice && mac != null) deviceName:$deviceName 直接调用_connectDevice', upload: false); // AppLog.log('安卓或者iOS 存在设备不需要扫描 deviceName:$deviceName isAddEquipment:$isAddEquipment'); _connectDevice(devicesList, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); } } //查找缓存里面是否有设备 bool isExistScanDevices(String connectDeviceName) { final bool isExistDevice = scanDevices.any((ScanResult element) => element.device.platformName == connectDeviceName || element.advertisementData.advName == connectDeviceName); return isExistDevice; } Future _connectDevice( List devicesList, String deviceName, ConnectStateCallBack connectStateCallBack, { bool isAddEquipment = false, // 是否是添加设备之前 bool isReconnect = true, // 是否是重连 }) async { // 判断数组列表里面是否有这个设备 // AppLog.log("devicesList:$devicesList"); final int knownDeviceIndex = devicesList.indexWhere((ScanResult d) => (d.device.platformName == deviceName) || (d.advertisementData.advName == deviceName)); ScanResult? scanResult; //使用局部变量防止出现缓存 if (knownDeviceIndex >= 0) { // 存在的时候赋值 connectDeviceMacAddress = devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty ? devicesList[knownDeviceIndex].advertisementData.advName : devicesList[knownDeviceIndex].device.platformName; bluetoothConnectDevice = devicesList[knownDeviceIndex].device; scanResult = devicesList[knownDeviceIndex]; // AppLog.log('bluetoothConnectDevice: $bluetoothConnectDevice scanResult:$scanResult'); _initGetMtuSubscription(); _initListenConnectionState(); } if (scanResult == null || connectDeviceMacAddress.isEmpty) { BuglyTool.uploadException( message: '扫描结果scanResult == null || connectDeviceMacAddress.isEmpty不往下执行 return 上传记录当前方法是:_connectDevice', detail: 'scanResult:$scanResult connectDeviceMacAddress:$connectDeviceMacAddress', upload: false); return; } AppLog.log('调用了停止扫描的方法'); await stopScan(); if ((scanResult.advertisementData.serviceUuids[0].toString()[31] == '0') && isAddEquipment == false) { // 添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接 if (isReconnect == true) { AppLog.log('该锁已被重置, 重新发送扫描命令'); BuglyTool.uploadException( message: '该锁已被重置, 重新发送扫描命令startScanSingle 上传记录当前方法是:_connectDevice', detail: '添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接 该锁已被重置, 重新发送扫描命令 serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}', upload: false); scanDevices.clear(); startScanSingle(deviceName, 15, (List scanDevices) { _connectDevice(scanDevices, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment, isReconnect: false); }); } else { connectStateCallBack(BluetoothConnectionState.disconnected); EasyLoading.showToast('该锁已被重置'.tr, duration: 2000.milliseconds); scanDevices.clear(); BuglyTool.uploadException( message: '提示该锁已被重置, 回调断开连接, 清除缓存,上传记录当前方法是:_connectDevice', detail: 'isReconnect:$isReconnect serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}', upload: false); } return; } BuglyTool.uploadException( message: '从devicesList里面查到了设备 下一步连接设备 上传记录当前方法是:_connectDevice', detail: 'devicesList:$devicesList scanResult:${scanResult.toString()} bluetoothConnectDevice:${bluetoothConnectDevice.toString()} connectDeviceMacAddress:$connectDeviceMacAddress', upload: false); //连接设备 await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack); } //直接给蓝牙设备写入 Future doNotSearchBLE( String masAdds, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async { await FlutterBluePlus.stopScan(); if (bluetoothConnectDevice == null || bluetoothConnectDevice?.remoteId.str != masAdds) { bluetoothConnectDevice = BluetoothDevice.fromId(masAdds); _initGetMtuSubscription(); _initListenConnectionState(); BuglyTool.uploadException( message: '直接给蓝牙设备写入 上传记录当前方法是:doNotSearchBLE', detail: '直接给蓝牙设备写入 通过fromId方法创建一个BluetoothDevice masAdds:$masAdds', upload: false); } else { BuglyTool.uploadException( message: '直接给蓝牙设备写入 上传记录当前方法是:doNotSearchBLE', detail: '直接给蓝牙设备写入 用传入的bluetoothConnectDevice:${bluetoothConnectDevice.toString()}连接 masAdds:$masAdds', upload: false); } //尝试连接设备 await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack, isAddEquipment: isAddEquipment); } //设备连接 Future bluetoothDeviceConnect(BluetoothDevice bluetoothConnectDevice, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async { // 重连三次 const 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次后尝试连接失败'); BuglyTool.uploadException( message: '连接三次超时断开连接 回调断开连接 上传记录当前方法是:bluetoothDeviceConnect', detail: 'bluetoothDeviceConnect:${bluetoothConnectDevice.toString()} $maxAttempts次后尝试连接失败', upload: false); needScanSingle = true; connectStateCallBack(BluetoothConnectionState.disconnected); } if (bluetoothConnectionState == BluetoothConnectionState.connected) { try { needScanSingle = false; final List services = await bluetoothConnectDevice.discoverServices(); //循环判断服务 for (final BluetoothService service in services) { if (service.uuid == _serviceIdConnect) { for (final BluetoothCharacteristic characteristic in service.characteristics) { if (characteristic.characteristicUuid == _characteristicIdSubscription) { _subScribeToCharacteristic(characteristic); bluetoothConnectionState = BluetoothConnectionState.connected; connectStateCallBack(bluetoothConnectionState!); BuglyTool.uploadException( message: '订阅成功 上传记录当前方法是:bluetoothDeviceConnect', detail: '发现服务,连接成功,订阅数据 bluetoothDeviceConnect:${bluetoothConnectDevice.toString()} ', upload: false); } else { BuglyTool.uploadException( message: '订阅失败 上传记录当前方法是:bluetoothDeviceConnect', detail: '失败原因: characteristic.characteristicUuid:${characteristic.characteristicUuid} != _characteristicIdSubscription:$_characteristicIdSubscription bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}', upload: false); } } } else { BuglyTool.uploadException( message: '订阅失败 上传记录当前方法是:bluetoothDeviceConnect', detail: '失败原因: service.uuid:${service.uuid} != _serviceIdConnect:$_serviceIdConnect bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}', upload: false); } } } on Exception catch (e) { needScanSingle = true; bluetoothConnectionState = BluetoothConnectionState.disconnected; connectStateCallBack(bluetoothConnectionState!); AppLog.log( '发现设备时失败 e:$e bluetoothConnectionState:$bluetoothConnectionState'); BuglyTool.uploadException( message: '发现服务时失败', detail: '发现服务时报错原因e:$e bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}', upload: false); rethrow; } } } Future _subScribeToCharacteristic( BluetoothCharacteristic characteristic) async { final StreamSubscription> subscription = characteristic.onValueReceived.listen((List data) { AppLog.log('订阅获取的数据: $data '); if (data == lastTimeData || data.isEmpty) { return; } else { lastTimeData = data; } final bool dataHeadCorrect = isDataHeadCorrect(data); final bool allDataHeadCorrect = isDataHeadCorrect(allData); if (dataHeadCorrect && allDataHeadCorrect) { //缓存数据和新数据都有包头,直接放弃缓存数据 allData = []; } if (dataHeadCorrect) { // 当包有头时 // 判断是否需要分包 dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度 if (dataLen! + 14 > data.length) { // 当前包的长度小于实际的包时 分包添加 不解析 allData.addAll(data); } else { // 当前包的长度小于实际的包时 不分包 解析 allData.addAll(data); CommandReciverManager.appDataReceive(allData); // 发送完解析初始化数组 allData = []; } } else if (allDataHeadCorrect) { // 当包没有头时 是分包的包 直接添加 allData.addAll(data); if (((dataLen ?? 0) + 14) <= allData.length) { // 当长度小于等于当前包的数据时 直接解析数据 CommandReciverManager.appDataReceive(allData); // 发送完解析初始化数组 allData = []; } } }); bluetoothConnectDevice!.cancelWhenDisconnected(subscription); await characteristic.setNotifyValue(true); } //判断数据头是否正确 bool isDataHeadCorrect(List data) { if (data.length < 4) { return false; } //239, 1, 238, 2, 是数据包头 if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && (data[3] == 0x02)) { return true; } else { return false; } } // 写入 Future writeCharacteristicWithResponse(List value) async { final List services = await bluetoothConnectDevice!.discoverServices(); for (final BluetoothService service in services) { if (service.uuid == _serviceIdConnect) { for (final BluetoothCharacteristic characteristic in service.characteristics) { if (characteristic.characteristicUuid == _characteristicIdWrite) { try { final List valueList = value; final 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); } else if (characteristic.properties.write) { // 使用WRITE属性写入值 await characteristic.write(subData[i]); } else { // 特性不支持写入 throw Exception( 'This characteristic does not support writing.'); } } } on Exception catch (e, s) { AppLog.log('APP写入失败: $e $s'); rethrow; } } } } } } // 停止扫描蓝牙设备 Future stopScan() async { try { await FlutterBluePlus.stopScan(); AppLog.log('调用停止扫描成功'); } catch (e) { AppLog.log('停止扫描失败'); } } // 断开连接 Future disconnect() async { try { connectDeviceMacAddress = ''; if (bluetoothConnectionState == BluetoothConnectionState.connected) { //加快蓝牙断连 await bluetoothConnectDevice!.disconnect(timeout: 3); AppLog.log('断开连接成功'); } } on Exception catch (e, _) { AppLog.log('断开连接失败: $e'); } finally { bluetoothConnectionState = BluetoothConnectionState.disconnected; } } Future openBlue() async { if (Platform.isAndroid) { await FlutterBluePlus.turnOn(); } if (Platform.isIOS) { EasyLoading.showToast('请开启蓝牙'.tr, duration: 2000.milliseconds); } } void disposed() { _sendStreamSubscription?.cancel(); _mtuSubscription!.cancel(); _adapterStateStateSubscription!.cancel(); _connectionStateSubscription!.cancel(); } }