import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:ef/ef.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/pages/common/selectDialog.dart'; String findInput = ""; double rssichange = -90; Function? findCall; int mcuMax = 500; String myuuid = "00000001-0000-1000-8000-00805F9B34FB"; int closeTime = 20000; Map devices = Map(); StreamSubscription? subscription_adapterState; Map connectList = Map(); bool isBleStart = false; StreamSubscription>? onScanResultsListen; StreamSubscription? streamSubscription_onConnectionStateChangedEvent; Timer? showToastTimer; List permissionInfo = [ ["位置权限说明", "获得位置信息,连接附近的蓝牙设备与推荐附近门店"], ["蓝牙权限说明", "搜索链接附近的蓝牙设备"], ["附近设备权限说明", "搜索链接附近的蓝牙设备"] ]; bool isQuanShiDevice(name) { return "$name".contains("S4-ZM-M94-4") || "$name".contains("S4-ZM-N94-4") || "$name".contains("MHT-SWES-D"); } bool isMHTSWES(name) { return "$name".contains("MHT-SWES-H") || "$name".contains("MHT-SWES-M") || "$name".contains("MHT-SWES-S"); } bleParse() { findCall = null; print("bleParse 执行了"); showToastTimer?.cancel(); if (FlutterBluePlus.isScanningNow) { FlutterBluePlus.stopScan(); } } start(Function fun, {Function? bleOnCall}) async { if (isBleStart) { var isOk = await requestBluetoothPermission(); if (isOk == true) { findCall = fun; bleOnCall?.call(); bleOnCall = null; } print("ble start again"); return; } print("ble start"); FlutterBluePlus.setLogLevel(LogLevel.info, color: false); streamSubscription_onConnectionStateChangedEvent?.cancel(); streamSubscription_onConnectionStateChangedEvent = FlutterBluePlus.events.onConnectionStateChanged.listen((event) { print('${event.device} ${event.connectionState}'); }); if (await FlutterBluePlus.isSupported == false) { print("Bluetooth not supported by this device"); return; } // handle bluetooth on & off // note: for iOS the initial state is typically BluetoothAdapterState.unknown // note: if you have permissions issues you will get stuck at BluetoothAdapterState.unauthorized subscription_adapterState?.cancel(); int callIndex = 0; subscription_adapterState = FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) async { print(state); print("蓝牙状态 $state"); if (state == BluetoothAdapterState.on) { showToastTimer?.cancel(); // usually start scanning, connecting, etc findCall = fun; var isOk = await requestBluetoothPermission(); if (isOk == true) { bleOnCall?.call(); bleOnCall = null; } } else { // show an error to the user, etc if (Platform.isIOS && callIndex == 0 && state == BluetoothAdapterState.unknown) { callIndex++; return; } if (Platform.isAndroid) { showToast("请打开蓝牙开关"); } if (Platform.isIOS) { showToast("请打开蓝牙开关且开启蓝牙权限"); await showCustomConfirmAndCancelDialog( Get.context!, "请在“设置-蓝牙”中打开蓝牙开关或者在“设置-APP”中找到对应APP开启蓝牙权限", confirmName: "去设置") .then((msg) async { if (msg == "confirm") { openAppSettings(); } }); } isBleStart = false; showToastTimer?.cancel(); showToastTimer = Timer.periodic(const Duration(seconds: 5), (t) { if (t.tick > 3) { t.cancel(); } if (Platform.isAndroid) { showToast("请打开蓝牙开关"); } if (Platform.isIOS) { showToast("请打开蓝牙开关且开启蓝牙权限"); } }); } callIndex++; }); // turn on bluetooth ourself if we can // for iOS, the user controls bluetooth enable/disable if (Platform.isAndroid && FlutterBluePlus.adapterStateNow != BluetoothAdapterState.on) { showPermissionInfoDialog(Get.context!, permissionInfo); FlutterBluePlus.turnOn().then((e) { Get.back(); }).catchError((e) { Get.back(); }); } var timer = null; onScanResultsListen?.cancel(); onScanResultsListen = FlutterBluePlus.onScanResults.listen( (List results) { // print(results.length); for (ScanResult result in results) { // if (result.device.id.toString().contains("A3:76")) { // print("$result"); // } Map d = { "updateTime": DateTime.now().millisecondsSinceEpoch, "name": result.device.advName, "id": result.device.remoteId.str, "rssi": result.rssi, "device": result.device, "connectable": result.advertisementData.connectable }; Map> m_d = result.advertisementData.manufacturerData; m_d.keys.toList().forEach((v) { if (v == 65517 && m_d[65517]?.length != 0) { List a = [0, 0, ...?m_d[65517]]; advertisDataFormatter(a, d); } else if (v == 11125 && m_d[11125]?.length == 8) { List a = [...?m_d[11125]]; d['adData'] = {'deviceId': ab2str(a.sublist(2, 8)).toUpperCase()}; } else if (m_d[v]?.length == 8 && isQuanShiDevice(d["name"])) { List a = [...?m_d[v]]; d['adData'] = {'deviceId': ab2str(a.sublist(2, 8)).toUpperCase()}; } else if (m_d[v]?.length == 4 && isMHTSWES(d["name"])) { ByteData bd = ByteData(2); bd.setUint16(0, v, Endian.little); List a = [bd.getUint8(0), bd.getUint8(1), ...?m_d[v]]; d['adData'] = {'deviceId': ab2str(a).toUpperCase()}; } else if (m_d[v]?.length == 6 && isMHTSWES(d["name"])) { List a = [...?m_d[v]]; d['adData'] = {'deviceId': ab2str(a).toUpperCase()}; } }); devices[d['id']] = d; // print('Device found: ${result.device.name}, ${result.device.id}'); if (timer == null) { timer = 1; timer = Future.delayed(const Duration(microseconds: 300), () { timer = null; find(); }); } } }, onError: (e) => print(e), ); } // Future locationCheck({bool isGetLocation = true}) async { // // 先查看定位服务是否开启 // bool b = await Geolocator.isLocationServiceEnabled(); // if (b == false) { // if (Platform.isAndroid) { // showToast("请开启系统位置开关", closeTime: 5); // await showCustomConfirmAndCancelDialog(Get.context!, "请开启系统位置开关", // confirmName: "去设置") // .then((msg) async { // if (msg == "confirm") { // // await Geolocator.openLocationSettings(); // await openGeolocatorLocationSettingsAndWait(); // b = await Geolocator.isLocationServiceEnabled(); // } // }); // } // if (Platform.isIOS) { // showToast("请开启系统定位服务与定位权限", closeTime: 5); // await showCustomConfirmAndCancelDialog(Get.context!, // "请在“设置-隐私与安全性-定位服务”中开启定位服务开关或者在“设置-APP”中找到对应APP开启定位服务权限", // confirmName: "去设置") // .then((msg) async { // if (msg == "confirm") { // // await Geolocator.openAppSettings(); // await openGeolocatorAppSettingsAndWait(); // b = await Geolocator.isLocationServiceEnabled(); // } // }); // } // } // var permission = await Geolocator.checkPermission(); // if (permission == LocationPermission.denied || // permission == LocationPermission.deniedForever) { // showPermissionInfoDialog(Get.context!, [permissionInfo[0]]); // permission = await Geolocator.requestPermission().catchError((e) { // Get.back(); // }); // Get.back(); // if (permission == LocationPermission.deniedForever) { // if (Platform.isAndroid) { // await showCustomConfirmAndCancelDialog(Get.context!, "请开启位置权限(打开精确位置)", // confirmName: "去设置") // .then((msg) async { // if (msg == "confirm") { // // await Geolocator.openAppSettings(); // await openGeolocatorAppSettingsAndWait(); // } // }); // } // if (Platform.isIOS) { // await showCustomConfirmAndCancelDialog(Get.context!, // "请在“设置-隐私与安全性-定位服务”中开启定位服务开关或者在“设置-APP”中找到对应APP开启定位服务权限", // confirmName: "去设置") // .then((msg) async { // if (msg == "confirm") { // // await Geolocator.openAppSettings(); // await openGeolocatorAppSettingsAndWait(); // } // }); // } // } // } // Position? position; // if (isGetLocation) { // if (b && // permission != LocationPermission.denied && // permission != LocationPermission.deniedForever) { // try { // position = await Geolocator.getCurrentPosition( // locationSettings: // const LocationSettings(timeLimit: Duration(seconds: 5))); // print("$position"); // } catch (e) { // print("error $e"); // } // } // } // return position; // } /// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态, /// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回 /// ------开始----- Future openGeolocatorAppSettingsAndWait() async { final geolocatorAppSettingsLifecycleState = GeolocatorAppSettingsLifecycleEventHandler(); WidgetsBinding.instance.addObserver(geolocatorAppSettingsLifecycleState); // await Geolocator.openAppSettings(); await geolocatorAppSettingsLifecycleState.waitForResume(); WidgetsBinding.instance.removeObserver(geolocatorAppSettingsLifecycleState); print('AppSettings have been opened and user has returned'); } class GeolocatorAppSettingsLifecycleEventHandler extends WidgetsBindingObserver { final Completer _completer = Completer(); @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed && !_completer.isCompleted) { _completer.complete(); } } Future waitForResume() => _completer.future; } /// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态, /// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回 /// ------结束----- /// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态, /// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回 /// ------开始----- Future openGeolocatorLocationSettingsAndWait() async { final geolocatorLocationSettingsLifecycleState = GeolocatorLocationSettingsLifecycleEventHandler(); WidgetsBinding.instance.addObserver(geolocatorLocationSettingsLifecycleState); // await Geolocator.openLocationSettings(); await geolocatorLocationSettingsLifecycleState.waitForResume(); WidgetsBinding.instance .removeObserver(geolocatorLocationSettingsLifecycleState); print('LocationSettings have been opened and user has returned'); } class GeolocatorLocationSettingsLifecycleEventHandler extends WidgetsBindingObserver { final Completer _completer = Completer(); @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed && !_completer.isCompleted) { _completer.complete(); } } Future waitForResume() => _completer.future; } /// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态, /// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回 /// ------结束----- Future requestBluetoothPermission() async { if (Platform.isIOS) { PermissionStatus isBleGranted = await Permission.bluetooth.request(); print('checkBlePermissions-ios, isBleGranted=$isBleGranted'); if (isBleGranted.isGranted) { startBluetoothScanning(); return true; } else { showToast("蓝牙开关或蓝牙权限未开启,请开启蓝牙开关与蓝牙权限", closeTime: 7); await showCustomConfirmAndCancelDialog( Get.context!, "请“设置-蓝牙”中打开蓝牙开关或者在“设置-APP”中找到对应APP开启蓝牙权限", confirmName: "去设置") .then((msg) async { if (msg == "confirm") { openAppSettings(); } }); return false; } } else if (Platform.isAndroid) { // 检查蓝牙扫描权限 String error = ""; bool isShowDialog = false; if (!await Permission.bluetoothScan.isGranted) { if (!isShowDialog) { isShowDialog = true; showPermissionInfoDialog(Get.context!, permissionInfo); } PermissionStatus status = await Permission.bluetoothScan.request(); if (!status.isGranted) { error += "蓝牙扫描权限未开启,请开启附近设备权限"; } print("蓝牙扫描 $status"); } // 检查蓝牙连接权限 if (!await Permission.bluetoothConnect.isGranted) { if (!isShowDialog) { isShowDialog = true; showPermissionInfoDialog(Get.context!, permissionInfo); } PermissionStatus status = await Permission.bluetoothConnect.request(); if (!status.isGranted) { if (error.isNotEmpty) { error += "\n"; } error += "蓝牙连接权限未开启,请开启蓝牙权限"; } print("蓝牙连接 $status"); } // 检查位置权限 if (!await Permission.location.isGranted) { if (!isShowDialog) { isShowDialog = true; showPermissionInfoDialog(Get.context!, permissionInfo); } //检查 PermissionStatus status = await Permission.location.request(); print("位置权限 $status"); if (!status.isGranted) { await showCustomConfirmAndCancelDialog(Get.context!, "请开启位置权限(打开精确位置)", confirmName: "去设置") .then((msg) async { if (msg == "confirm") { await openGeolocatorAppSettingsAndWait(); // await Future.delayed(const Duration(seconds: 2)); print('Proceeding with other operations'); status = await Permission.location.request(); } }); } if (!status.isGranted) { if (error.isNotEmpty) { error += "\n"; } error += "位置权限未开启,请开启位置权限"; } } if (isShowDialog) { Get.back(); } if (await Permission.bluetoothScan.isGranted && await Permission.bluetoothConnect.isGranted && await Permission.location.isGranted) { // bool b = await Geolocator.isLocationServiceEnabled(); bool b =false; if (b == false) { await showCustomConfirmAndCancelDialog(Get.context!, "请开启系统位置开关", confirmName: "去设置") .then((msg) async { if (msg == "confirm") { // bool isOpen = await Geolocator.openLocationSettings(); await openGeolocatorLocationSettingsAndWait(); // await Future.delayed(const Duration(seconds: 2)); print('Proceeding with other operations'); // b = await Geolocator.isLocationServiceEnabled(); } }); } if (b) { isBleStart = true; startBluetoothScanning(); return true; } else { showToast("系统位置开关未开启,请开启系统位置开关", closeTime: 7); return false; } } else { Timer(Duration.zero, () async { showToast(error, closeTime: 7); }); return false; } } else { showToast("当前系统不支持蓝牙,无法使用此功能", closeTime: 7); return false; } } void find() { int len = devices.length; String reg = findInput.toLowerCase().replaceAll(RegExp("[::]"), ""); List list = devices.values.toList(); for (int i = 0; i < len; i++) { Map d = list[i]; bool flag = d['rssi'] >= rssichange; if (flag) { bool a = d['name'].toString().toLowerCase().contains(reg); a = a || d['id'] .toString() .toLowerCase() .replaceAll(RegExp("[::]"), "") .contains(reg); // if(d.adData && d.adData.deviceId) { // a = a || d.adData.deviceId.toLowerCase().replace(/[::]/g, "").indexOf(reg) > -1 // } // if(d.adData && d.adData.version && reg) { // a = a || (d.adData.version + "").indexOf(reg) > -1 // } flag = flag && a; } if (flag) { flag = flag && DateTime.now().millisecondsSinceEpoch - d['updateTime'] < closeTime; } if (!flag) { d['isClose'] = true; } else { d['isClose'] = false; } } var result = list.where((item) => item['isClose'] == false).toList(); if (result == null) { findCall?.call([]); } else { // print(result); result.sort((a, b) { // print("${a['rssi']},${b['rssi']}"); return b['rssi'] - a['rssi']; }); if (result.length > 0) { findCall?.call(result.where((d) => d?['adData'] != null).toList()); } else { findCall?.call(result); } } } String ab2str(List buffer) { return buffer.map((x) => x.toRadixString(16).padLeft(2, '0')).join(''); } void advertisDataFormatter(var a, item) { Map obj = {}; try { if (a[2] == 1) { obj['sn'] = a[3]; obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase(); obj['b'] = a[10]; obj['h'] = a[11]; obj['t'] = a[12]; item['adData'] = obj; } else if (a[2] == 2) { obj['sn'] = a[3]; obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase(); obj['b'] = a[10]; obj['h'] = a[11]; obj['t'] = a[12]; obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线'; obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常'; ByteData byteData = ByteData.sublistView( Uint8List.fromList(a.sublist(14, 18).reversed.toList())); obj['version'] = byteData.getUint32(0); item['adData'] = obj; } else if (a[2] == 3) { List otherstr = []; obj['sn'] = a[3]; obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase(); obj['b'] = a[10]; obj['h'] = a[11]; obj['t'] = a[12]; obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线'; obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常'; if ((a[13] & 4) == 4) { otherstr.add('呼吸暂停'); } if ((a[13] & 8) == 8 && (a[13] & 1) == 1) { obj['isbed'] = '在床'; } else { obj['isbed'] = '离床'; } if ((a[13] & 16) == 16) { otherstr.add('授权过期'); } if ((a[13] & 64) == 64) { otherstr.add('设备休眠'); } obj['other'] = otherstr.join('、'); ByteData byteData = ByteData.sublistView( Uint8List.fromList(a.sublist(14, 18).reversed.toList())); obj['version'] = byteData.getUint32(0); ByteData qsnData = ByteData.sublistView(Uint8List.fromList(a.sublist(17, 19))); obj['qsn'] = qsnData.getUint16(0) * 256 + obj['sn']; item['adData'] = obj; } else if (a.length > 17) { obj['sn'] = a[3]; obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase(); obj['b'] = a[10]; obj['h'] = a[11]; obj['t'] = a[12]; obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线'; obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常'; ByteData byteData = ByteData.sublistView( Uint8List.fromList(a.sublist(14, 18).reversed.toList())); obj['version'] = byteData.getUint32(0); item['adData'] = obj; } } catch (e) { print(e); } } void startBluetoothScanning() async { // 开始扫描附近的蓝牙设备 if (FlutterBluePlus.isScanningNow) { await FlutterBluePlus.stopScan(); } FlutterBluePlus.startScan(timeout: const Duration(seconds: 15)); } getOneConnectedDeviceProp(id) { return connectList[id]; } void setOther(device, connectedDeviceProp, fun) async { try { List services = await device.discoverServices(); print(services); bool isNotify = false; bool isWrite = false; for (var service in services) { if (connectedDeviceProp.connectedDevicePropType == ConnectedDevicePropType.JunHe) { if (service.uuid.str128.toUpperCase() != myuuid) { continue; } } // print("serviece $service"); for (BluetoothCharacteristic element in service.characteristics) { if (isNotify == false && element.properties.notify) { await element.setNotifyValue(true); print("setNotifyValue 完成"); connectedDeviceProp.createLisetenReceive(element); isNotify = true; if (connectedDeviceProp.connectedDevicePropType == ConnectedDevicePropType.JunHe) { continue; } if (connectedDeviceProp.connectedDevicePropType == ConnectedDevicePropType.MHT) { continue; } } if (isWrite == false && element.properties.write) { connectedDeviceProp?.writeCharacteristic = element; isWrite = true; print("$element"); } } } if (!isWrite || !isNotify) { if (connectedDeviceProp != null) { disconnect(connectedDeviceProp!); } print("service 订阅失败 isWrite $isWrite isNotify $isNotify"); fun['fail']?.call("service 订阅失败 isWrite $isWrite isNotify $isNotify"); return; } print("service 注册完成"); connectList[connectedDeviceProp.id] = connectedDeviceProp; connectedDeviceProp.createListenState(); if (connectedDeviceProp.connectedDevicePropType == ConnectedDevicePropType.JunHe) { connectedDeviceProp.heartbeat(); } print("回调成功"); fun['success']?.call(connectedDeviceProp); } catch (e) { print("连接失败 执行失败回调 错误: $e"); if (connectedDeviceProp != null) { disconnect(connectedDeviceProp!); } print("连接失败 执行失败回调"); fun['fail']?.call(e); } } // 连接设备 void connectToDevice(fun) async { if (fun != null) { return; } BluetoothDevice device = fun.device; ConnectedDeviceProp? connectedDeviceProp = getOneConnectedDeviceProp(device.remoteId.str); if (connectedDeviceProp != null) { disconnect(connectedDeviceProp); Future.delayed(const Duration(seconds: 1), () { connectToDevice(fun); }); return; } try { print("connecting"); await device.connect(timeout: const Duration(seconds: 8)); print("device.connect success"); ConnectedDevicePropType connectedDevicePropType = ConnectedDevicePropType.JunHe; connectedDeviceProp = ConnectedDeviceProp( connectDevice: device, fun: fun, connectedDevicePropType: connectedDevicePropType); if (Platform.isAndroid) { await device.requestMtu(mcuMax); } Timer(const Duration(milliseconds: 1000), () { setOther(device, connectedDeviceProp, fun); }); } catch (e) { print("连接失败 执行失败回调 错误: $e"); if (connectedDeviceProp != null) { disconnect(connectedDeviceProp!); } print("连接失败 执行失败回调"); fun['fail']?.call(e); } } bool jsJunHe(String name) { return "$name".contains("AITH-V2") || "$name".contains("AITH-V2") || "$name".contains("AITH-V2"); } void disconnect(ConnectedDeviceProp connectedDeviceProp) { connectedDeviceProp.closeHeartBeat(); connectList.remove(connectedDeviceProp.id); connectedDeviceProp.closeConnectedDeviceProp(); } void closeAll() { findCall = null; connectList.values.toList().forEach((element) { disconnect(element); }); } enum ConnectedDevicePropType { JunHe, QuanShi, MHT } class ConnectedDeviceProp { ConnectedDevicePropType connectedDevicePropType; Timer? heartbeatTimer = null; int _seq = 0; var connectDevice; var writeCharacteristic; var listenState; StreamSubscription>? lisetenReceive; Map fun; List receiveMethods = []; List logList = []; Function? logChange; ConnectedDeviceProp( {required this.connectDevice, required Map this.fun, this.connectedDevicePropType = ConnectedDevicePropType.JunHe}); List receiveLogArr = []; int deviceType = 2; int encodeType = 2; List sendArr = []; double sendExecAverage = 100; bool isClose = false; String get id { return connectDevice.remoteId.str; } int sum_ab(dv) { ByteData sum = ByteData(1); for (int i = 0; i < dv.buffer.lengthInBytes; i++) { sum.setUint8(0, dv.getUint8(i) + sum.getUint8(0)); } return sum.getUint8(0); } void heartbeat() { closeHeartBeat(); heartbeatTimer = Timer.periodic(const Duration(seconds: 8), (timer) { ByteData dv = ByteData(4); dv.setUint8(0, 4); dv.setUint8(2, seq); dv.setUint8(3, 5); dv.setUint8(1, sum_ab(dv)); writeBle(dv); }); } closeHeartBeat() { if (heartbeatTimer != null) { heartbeatTimer!.cancel(); heartbeatTimer = null; } } ByteData str2ab_oneByte(String str, {int startLength = 0}) { Uint8List utf8str = utf8.encode(str); int len = utf8str.length + startLength; ByteData buf2 = ByteData.sublistView(utf8str); ByteData buf = ByteData(len); for (int i = startLength; i < len; i++) { buf.setUint8(i, buf2.getUint8(i - startLength)); } return buf; } void write3OfString(sendDate, {Function? success, Function? fail}) { ByteData dv = str2ab_oneByte(sendDate, startLength: 4); int len = dv.buffer.lengthInBytes; dv.setUint8(0, len); dv.setUint8(2, seq); dv.setUint8(3, 8 * 16 + 3); dv.setUint8(1, sum_ab(dv)); writeBle(dv, success: success, fail: fail); } void writeBle(ByteData d, {Function? success, Function? fail}) { Uint8List d_ = Uint8List.view(d.buffer); if (sendArr.length == 0) { write(d_, success, fail); } sendArr.insert(0, {"d": d_, "success": success, "fail": fail}); } void write(Uint8List d, Function? success, Function? fail, {int exec = 100}) { if (writeCharacteristic != null) { // try { // if (d[3] == 8 * 16 + 3) { // print( // "blewrite s = $sendExecAverage d = ${utf8.decode(d.sublist(4))}"); // } else { // print("ble last write d = ${d[3]}"); // } // } catch (e) { // print("write logprint error $e"); // } writeCharacteristic.write(d, withoutResponse: true).then((e) { // print("write success $e"); if (connectedDevicePropType != ConnectedDevicePropType.JunHe) { print("发送 $d"); } if (exec > 95) { sendExecAverage = sendExecAverage + 0.5; } if (sendExecAverage > 99) { sendExecAverage = 99; } if (sendArr.length > 0) { sendArr.removeLast(); Map last = sendArr.last; write(last["d"], last["success"], last["fail"]); } success?.call(); }).catchError((e) { // print("exec = $exec , $e"); if (exec < 0) { print("$e"); fail?.call(); } if (exec > -1 && isClose == false) { int time = ((100.0 - sendExecAverage) * 5.0).toInt(); if (exec < 80) { time = (100 - exec) * 5; sendExecAverage = exec * 1.0; } else { sendExecAverage = sendExecAverage - (100 - exec) * 0.1; } Timer(Duration(milliseconds: time), () { write(d, success, fail, exec: exec - 1); }); } }); } } void read6() { ByteData dv = ByteData(4); dv.setUint8(0, 4); dv.setUint8(2, seq); dv.setUint8(3, 6); dv.setUint8(1, sum_ab(dv)); writeBle(dv); } addLog(String log) { if (logList.length > 500) { logList.removeRange(0, 50); } DateTime date = DateTime.now(); String h = date.hour > 10 ? "${date.hour}" : "0${date.hour}"; String m = date.minute > 10 ? "${date.minute}" : "0${date.minute}"; String s = date.second > 10 ? "${date.second}" : "0${date.second}"; logList.add({"time": "$h:$m:$s", "value": log}); print("ble $id log: $log"); if (logChange != null) { logChange?.call(logList, log); } } createListenState() { listenState = connectDevice.connectionState.listen((state) { print('ble Device state $id $state'); if (state == BluetoothConnectionState.disconnected) { print('ble Device state $id disconnected'); isClose = true; disconnect(this); fun['stateChange']?.call(state, this); } }); } createLisetenReceive(BluetoothCharacteristic element) { lisetenReceive = element.onValueReceived.listen((List value) { if (connectedDevicePropType == ConnectedDevicePropType.JunHe) { if (value.isEmpty) { return; } bool isOk = sumCheck(value); if (isOk) { receiveMethods.forEach((m) { m?.call(); }); yewuSwitch(value[3], value.sublist(4)); } } else { print("onValueReceived $value"); receiveLogArr.forEach((m) { m(value); }); } }); } closeConnectedDeviceProp() { isClose = true; if (listenState != null) { listenState?.cancel(); } if (lisetenReceive != null) { lisetenReceive?.cancel(); } connectDevice?.disconnect(); } int get seq { int r = _seq % 256; _seq++; return r; } bool sumCheck(List ab) { ByteData dv = ByteData.sublistView(Uint8List.fromList(ab)); if (dv.getUint8(0) != ab.length) { print("和校验失败:长度不对"); return false; } //和校验失败 if (sumList(ab) != dv.getUint8(1)) { print("和校验失败: 校验失败"); return false; } return true; } int sumList(List ab) { ByteData dv = ByteData.sublistView(Uint8List.fromList(ab)); ByteData sum = ByteData.sublistView(Uint8List(1)); sum.setUint8(0, dv.getUint8(0)); for (int i = 2; i < ab.length; i++) { sum.setUint8(0, dv.getUint8(i) + sum.getUint8(0)); } return sum.getUint8(0); } List endLogValue = []; Timer? endLogTimer; void yewuSwitch(int yewu, List abData) { switch (yewu) { case 7: String error = ab2StrByType(abData); print(error); break; case 131: List? logData; if (abData.last != 10) { int index = abData.lastIndexOf(10); if (index == -1) { index = abData.length; endLogValue = [...endLogValue, ...abData.sublist(0, index)]; } else { logData = [...endLogValue, ...abData.sublist(0, index)]; endLogValue = abData.sublist(index); } // if (index == -1) { // index = abData.length; // } // if(endLogValue.isNotEmpty) { // logData = [...endLogValue, ...abData.sublist(0, index)]; // endLogValue = []; // } else { // logData = [...abData.sublist(0, index)]; // } // if(index != abData.length) { // endLogValue = abData.sublist(index); // } } else { int index = abData.length; if (endLogValue.isNotEmpty) { logData = [...endLogValue, ...abData]; } else { logData = abData; } endLogValue = []; } if (endLogTimer != null) { endLogTimer!.cancel(); endLogTimer = null; } if (endLogValue != null && endLogValue!.isNotEmpty) { endLogTimer = Timer(Duration(milliseconds: 400), () { String log = ab2StrByType(endLogValue!); endLogValue = []; addLog(log); try { receiveLogArr.forEach((m) { m(log); }); } catch (e) { print(e); } }); } if (logData != null && logData.isNotEmpty) { if (logData.length != 1 || logData[0] != 13) { String log = ab2StrByType(logData!); addLog(log); try { receiveLogArr.forEach((m) { m(log); }); } catch (e) { print(e); } } } // 处理逻辑 break; case 132: ByteData dv = ByteData.sublistView(Uint8List.fromList(abData)); for (int i = 0; i < abData.length;) { int len = dv.getUint8(i); yewuSwitch(dv.getUint8(i + 1), abData.sublist(i + 2, i + 1 + len)); i = i + 1 + len; } break; default: break; } } String ab2StrByType(List abData) { // Implement your logic for converting abData to String String str = ""; if (abData.isNotEmpty) { try { str = utf8.decode(abData); } catch (e) { str = "解析错误"; } } return str; } }