diff --git a/android/version.properties b/android/version.properties index d209e3e..cdeab51 100644 --- a/android/version.properties +++ b/android/version.properties @@ -1,2 +1,7 @@ -flutter.android.versionName=2.0.7 -flutter.android.versionCode=11 \ No newline at end of file +# 太和版本信息 +# flutter.android.versionName=2.0.5 +# flutter.android.versionCode=11 + +# 智慧眠花糖版本信息 +flutter.android.versionName=2.0.8 +flutter.android.versionCode=12 \ No newline at end of file diff --git a/assets/mhlangs/en_US.json b/assets/mhlangs/en_US.json index bf1acee..6b8124b 100644 --- a/assets/mhlangs/en_US.json +++ b/assets/mhlangs/en_US.json @@ -627,5 +627,6 @@ "取消升级": "Cancel Upgrade", "通知设置": "Notification Setting", "睡眠报告通知":"Sleep Report Notification", - "糖管家":"SweetyKeeper" + "糖管家":"SweetyKeeper", + "蓝牙已断开,请点击下方刷新按钮重试": "Bluetooth disconnected, please click the refresh button below to retry" } \ No newline at end of file diff --git a/assets/mhlangs/zh_CN.json b/assets/mhlangs/zh_CN.json index 4104747..c7f480e 100644 --- a/assets/mhlangs/zh_CN.json +++ b/assets/mhlangs/zh_CN.json @@ -228,7 +228,7 @@ "生日": "生日", "yyyy年MM月dd日": "yyyy年MM月dd日", "请输入联系方式": "请输入联系方式", - "未配置网络提示": "未配置网络提示", + "未配置网络提示": "当前设备未进行网络配置,是否确认跳过网络配置", "wifi配置": "wifi配置", "可用WLAN": "可用WLAN", "输入wifi密码": "输入wifi密码", @@ -627,5 +627,7 @@ "取消升级": "取消升级", "通知设置": "通知设置", "睡眠报告通知":"睡眠报告通知", - "糖管家": "糖管家" + "糖管家": "糖管家", + "蓝牙连接成功": "蓝牙连接成功", + "蓝牙已断开,请点击下方刷新按钮重试": "蓝牙已断开,请点击下方刷新按钮重试" } \ No newline at end of file diff --git a/assets/mhlangs/zh_TW.json b/assets/mhlangs/zh_TW.json index 2108e49..fb2911f 100644 --- a/assets/mhlangs/zh_TW.json +++ b/assets/mhlangs/zh_TW.json @@ -626,5 +626,7 @@ "取消升级": "取消升級", "通知设置": "通知設置", "睡眠报告通知":"睡眠報告通知", - "糖管家":"糖管家" + "糖管家":"糖管家", + "蓝牙连接成功":"糖管家", + "蓝牙已断开,请点击下方刷新按钮重试": "蓝牙已斷開,請點擊下方刷新按鈕重試" } \ No newline at end of file diff --git a/lib/common/util/BluetoothFirmwareUpdater.dart b/lib/common/util/BluetoothFirmwareUpdater.dart index 11f557c..5da0f91 100644 --- a/lib/common/util/BluetoothFirmwareUpdater.dart +++ b/lib/common/util/BluetoothFirmwareUpdater.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/component/tool/cmd.dart'; import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart'; import 'package:ef/ef.dart'; // THapp 所在的包 @@ -86,7 +87,7 @@ class MultiDeviceFirmwareUpdater { throw Exception("[蓝牙指令执行日志] 设备 $mac 正在升级中".tr); } } - + // await sendBlogAndDlogCommands(thapp); final completer = Completer(); final task = UpgradeTask( mac: mac, @@ -98,25 +99,24 @@ class MultiDeviceFirmwareUpdater { _upgradeTasks[mac] = task; _updateUiProgress(mac, 0, 'waiting'); - _processUpgradeQueue(); + _processUpgradeQueue(thapp); return completer.future; } - void _processUpgradeQueue() { + void _processUpgradeQueue(THapp thapp) { final waitingTasks = _upgradeTasks.values.where((task) => task.status == 'waiting').toList(); for (final task in waitingTasks) { if (_currentConcurrentUpgrades < _maxConcurrentUpgrades) { _currentConcurrentUpgrades++; - _startSingleUpgrade(task); + _startSingleUpgrade(task, thapp); } - //screen shots } } - Future _startSingleUpgrade(UpgradeTask task) async { + Future _startSingleUpgrade(UpgradeTask task, THapp thapp) async { try { task.status = 'downloading'; @@ -129,7 +129,8 @@ class MultiDeviceFirmwareUpdater { } // await _sendCommand(task.thapp, "blog disable"); - _sendCommand(task.thapp, "blog disable"); + // _sendCommand(task.thapp, "blog disable"); + await Future.delayed(Duration(milliseconds: 200)); task.status = 'upgrading'; @@ -137,9 +138,8 @@ class MultiDeviceFirmwareUpdater { await _sendFirmwareFrames(task); - await _sendCommand(task.thapp, "blog enable"); + // await _sendCommand(task.thapp, "blog enable"); await _verifyFirmware(task); - task.status = 'completed'; task.endTime = DateTime.now(); _updateUiProgress(task.mac, 100, 'completed'); @@ -162,13 +162,7 @@ class MultiDeviceFirmwareUpdater { } finally { _currentConcurrentUpgrades--; _cleanupTask(task.mac); - _processUpgradeQueue(); - - try { - await _sendCommand(task.thapp, "blog enable"); - } catch (e, stack) { - ef.log("[蓝牙指令执行日志] 重新开启日志失败: $e\n$stack"); - } + _processUpgradeQueue(thapp); } } @@ -192,88 +186,141 @@ class MultiDeviceFirmwareUpdater { } } + // Future _sendFirmwareFrames(UpgradeTask task) async { + // final firmwareData = _firmwareDataCache[task.mac]; + // if (firmwareData == null) { + // throw Exception("[蓝牙指令执行日志] 固件数据为空".tr); + // } + + // final totalFrames = + // (firmwareData.length / UpgradeConfig.maxFrameSize).ceil(); + // ef.log("[蓝牙指令执行日志] 固件总帧数:$totalFrames"); + // final stopwatch = Stopwatch()..start(); + // DateTime lastFrameTime = DateTime.now(); + + // for (int sentFrames = 0; sentFrames < totalFrames; sentFrames++) { + // if (task.status == 'cancelled') { + // throw Exception("[蓝牙指令执行日志] 升级已取消".tr); + // } + + // final elapsed = stopwatch.elapsed; + // final frameInterval = UpgradeConfig.getFrameInterval(elapsed); + // final now = DateTime.now(); + + // if (now.difference(lastFrameTime) < frameInterval) { + // await Future.delayed(Duration(milliseconds: 10)); + // continue; + // } + + // final offset = sentFrames * UpgradeConfig.maxFrameSize; + // final end = offset + UpgradeConfig.maxFrameSize; + // final frameData = firmwareData.sublist( + // offset, + // end > firmwareData.length ? firmwareData.length : end, + // ); + + // final base64Data = base64Encode(frameData); + // final mmxCommand = + // '''mmx path="/root/mtd/update" write base64 len=${frameData.length} offset=$offset data="$base64Data"'''; + + // try { + // await _sendCommand(task.thapp, mmxCommand); + // await Future.delayed(Duration(milliseconds: sentFrames<500?100:10)); + // } catch (e, stack) { + // ef.log("[蓝牙指令执行日志] 发送固件帧失败: $e\n$stack"); + // rethrow; + // } + + // final waitTime = frameInterval - now.difference(lastFrameTime); + // if (waitTime > Duration.zero) await Future.delayed(waitTime); + + // final progress = ((sentFrames + 1) / totalFrames * 100).round(); + // _updateUiProgress(task.mac, progress, 'upgrading'); + + // lastFrameTime = now; + // } + + // stopwatch.stop(); + // } + Future _sendFirmwareFrames(UpgradeTask task) async { final firmwareData = _firmwareDataCache[task.mac]; if (firmwareData == null) { throw Exception("[蓝牙指令执行日志] 固件数据为空".tr); } - final totalFrames = - (firmwareData.length / UpgradeConfig.maxFrameSize).ceil(); - final stopwatch = Stopwatch()..start(); - DateTime lastFrameTime = DateTime.now(); + try { + ef.log("[蓝牙指令执行日志] 开始执行 OTA 升级流程"); - for (int sentFrames = 0; sentFrames < totalFrames; sentFrames++) { - if (task.status == 'cancelled') { - throw Exception("[蓝牙指令执行日志] 升级已取消".tr); - } - - final elapsed = stopwatch.elapsed; - final frameInterval = UpgradeConfig.getFrameInterval(elapsed); - final now = DateTime.now(); - - if (now.difference(lastFrameTime) < frameInterval) { - await Future.delayed(Duration(milliseconds: 10)); - continue; - } - - final offset = sentFrames * UpgradeConfig.maxFrameSize; - final end = offset + UpgradeConfig.maxFrameSize; - final frameData = firmwareData.sublist( - offset, - end > firmwareData.length ? firmwareData.length : end, + // 调用 THapp 封装的 otaStart 方法 + int result = await task.thapp.otaStart( + firmwareData, + chunkSize: UpgradeConfig.maxFrameSize, // 单帧大小 + retryPerChunk: 2, // 每帧重试次数 + timeoutMs: 3000, // 每帧超时时间 + firststepsframes: 300, // 前300帧延时发送,防止过载 + firststepdelayms: 30, // 前300帧延迟 30ms + onceDelayms: 10, // 之后帧间延迟 + disableBlog: true, // 升级时关闭日志 + withResponse: false, // 一般OTA不需要响应确认 + binmode: false, // 使用文本命令模式发送(mmx命令) + onProgress: (double progress) { + // 更新 UI 进度 + final percent = (progress * 100).clamp(0, 100).round(); + _updateUiProgress(task.mac, percent, 'upgrading'); + }, ); - final base64Data = base64Encode(frameData); - final mmxCommand = - '''mmx path="/root/mtd/update" write base64 len=${frameData.length} offset=$offset data="$base64Data"'''; - - try { - await _sendCommand(task.thapp, mmxCommand); - } catch (e, stack) { - ef.log("[蓝牙指令执行日志] 发送固件帧失败: $e\n$stack"); - rethrow; + // 根据返回码判断状态 + switch (result) { + case 0: + ef.log("[蓝牙指令执行日志] OTA 升级完成 ✅"); + _updateUiProgress(task.mac, 100, 'completed'); + break; + case -1: + throw Exception("固件为空或格式错误"); + case -2: + throw Exception("数据发送失败"); + case -3: + throw Exception("日志操作失败"); + case -4: + throw Exception("vota 命令执行失败"); + default: + throw Exception("未知错误: $result"); } - - final waitTime = frameInterval - now.difference(lastFrameTime); - if (waitTime > Duration.zero) await Future.delayed(waitTime); - - final progress = ((sentFrames + 1) / totalFrames * 100).round(); - _updateUiProgress(task.mac, progress, 'upgrading'); - - lastFrameTime = now; + } catch (e, stack) { + ef.log("[蓝牙指令执行日志] OTA 升级失败: $e\n$stack"); + rethrow; } - - stopwatch.stop(); } Future _verifyFirmware(UpgradeTask task) async { - try { - final success = await _sendVotaCommand(task.thapp); - - if (!success) { - throw Exception("[蓝牙指令执行日志] 固件验证失败".tr); - } + try { + final success = await _sendVotaCommand(task.thapp); - await Future.delayed(Duration(seconds: 10)); - - bool deviceRestarted = false; - for (int i = 0; i < 10; i++) { - if (!task.thapp.isConnected) { - deviceRestarted = true; - break; + if (!success) { + throw Exception("[蓝牙指令执行日志] 固件验证失败".tr); } - await Future.delayed(Duration(seconds: 1)); - } - if (!deviceRestarted) { - throw Exception("[蓝牙指令执行日志] 设备未重启,可能升级失败".tr); + await Future.delayed(Duration(seconds: 10)); + + bool deviceRestarted = false; + for (int i = 0; i < 10; i++) { + if (!task.thapp.isConnected) { + deviceRestarted = true; + break; + } + await Future.delayed(Duration(seconds: 1)); + } + + if (!deviceRestarted) { + throw Exception("[蓝牙指令执行日志] 设备未重启,可能升级失败".tr); + } + } catch (e, stack) { + ef.log("[蓝牙指令执行日志] 固件校验失败: $e\n$stack"); + throw Exception("[蓝牙指令执行日志] 固件校验失败".tr); } - } catch (e, stack) { - ef.log("[蓝牙指令执行日志] 固件校验失败: $e\n$stack"); - throw Exception("[蓝牙指令执行日志] 固件校验失败".tr); } -} Future _sendCommand(THapp thapp, String command, {bool needResponse = false}) async { @@ -337,6 +384,7 @@ class MultiDeviceFirmwareUpdater { "status": status, "updateTime": DateTime.now().millisecondsSinceEpoch, }; + // ef.log("[蓝牙指令执行日志] 更新进度: $progress, 状态: $status"); controller.update(); } } @@ -429,7 +477,7 @@ class MultiDeviceFirmwareUpdater { } return false; - }, 0, 20000 // vota 命令可能需要更长时间 + }, 3, 20000 // vota 命令可能需要更长时间 ); return result == true; diff --git a/lib/component/tool/cmd.dart b/lib/component/tool/cmd.dart index c454452..0cfac73 100644 --- a/lib/component/tool/cmd.dart +++ b/lib/component/tool/cmd.dart @@ -100,7 +100,7 @@ Future sendWifiSetting(wifiItem, String password, THapp tHapp) async { return true; } return false; - }, 1); + }, 10, 3000); if (!success) { edm.EasyDartModule.logger.error("WiFi配置超时或失败"); @@ -119,69 +119,85 @@ getDeviceWifiStatus( int times, { bool link = false, }) async { - edm.EasyDartModule.logger.info("发送请求设备已配置网络状态指令"); DailyLogUtils.writeLog("发送请求设备已配置网络状态指令"); - print("at+system info"); bool success = false; + final now = DateTime.now(); + final currenttIme = + "${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} " + "${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}"; + edm.EasyDartModule.logger.info("[aaa:配置开始]发送请求设备已配置网络状态指令:${currenttIme}"); + ef.log("[aaa:配置开始]:${currenttIme}"); + var stream = tHapp.logingStream.listen((data) { + ef.log("[设备日志]:${data}"); + }); try { - var result = await tHapp.send( - "at+system info", - true, - (ss) { - var log = ss.log; - // 匹配设备状态 - final statusMatch = RegExp(r'Status=([^\s]+)').firstMatch(log); - final status = statusMatch?.group(1); - if (status != null) { - print('提取到的 status: $status'); + var result = await tHapp.send("at+system info", true, (ss) { + var log = ss.log; + // ef.log("[设备WiFi配置信息]:${log}"); + edm.EasyDartModule.logger.info("设备WiFi配置信息->log:$log"); + // 匹配设备状态 + final statusMatch = RegExp(r'Status=([^\s]+)').firstMatch(log); + final status = statusMatch?.group(1); + print('提取到的 status: 为空'); + if (status != null) { + // print('提取到的 status: $status'); + final now = DateTime.now(); + final formattedTime = + "${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} " + "${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}"; - // 如果设备连接状态是 "connect",继续检测 - if (status.contains('connect')) { - // 匹配 Wi-Fi 连接信息 - final wifiInfoMatch = RegExp( - r'WIFI CONNECTED INFO:SSID=([^\s]+),RSSI=([-0-9]+),AUTH=([0-9]+),CH=([0-9]+),BSSID=([A-F0-9]+)') - .firstMatch(log); - if (wifiInfoMatch != null) { - final ssid = wifiInfoMatch.group(1); - final rssi = wifiInfoMatch.group(2); - final auth = wifiInfoMatch.group(3); - final ch = wifiInfoMatch.group(4); - final bssid = wifiInfoMatch.group(5); + // 如果设备连接状态是 "connect",继续检测 + if (status.contains('connect')) { + // 匹配 Wi-Fi 连接信息 + final wifiInfoMatch = RegExp( + r'WIFI CONNECTED INFO:SSID=([^\s]+),RSSI=([-0-9]+),AUTH=([0-9]+),CH=([0-9]+),BSSID=([A-F0-9]+)') + .firstMatch(log); + if (wifiInfoMatch != null) { + final ssid = wifiInfoMatch.group(1); + final rssi = wifiInfoMatch.group(2); + final auth = wifiInfoMatch.group(3); + final ch = wifiInfoMatch.group(4); + final bssid = wifiInfoMatch.group(5); - // 打印并返回 Wi-Fi 信息 - print( - 'Wi-Fi 信息: SSID=$ssid, RSSI=$rssi, AUTH=$auth, CH=$ch, BSSID=$bssid'); - - // 停止监听并返回信息 - ss.result = { - 'ssid': ssid, - 'rssi': rssi, - 'auth': auth, - 'ch': ch, - 'bssid': bssid, - }; - ss.over = true; - success = true; - return true; - } - } else { - if (!link) { - ss.over = true; - return true; - } + // 打印并返回 Wi-Fi 信息 + print( + 'Wi-Fi 信息: SSID=$ssid, RSSI=$rssi, AUTH=$auth, CH=$ch, BSSID=$bssid'); + final currenttIme = + "${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} " + "${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}"; + ef.log("[aaa:配置结束]:${currenttIme}"); + // 停止监听并返回信息 + ss.result = { + 'ssid': ssid, + 'rssi': rssi, + 'auth': auth, + 'ch': ch, + 'bssid': bssid, + }; + ss.over = true; + success = true; + return true; + } + } else { + if (!link) { + ss.over = true; + return true; } } - // 继续监听 - return false; - }, - times, - ); - if(!success){ + } + // 继续监听 + return false; + }, times, 3000); + if (!success) { return success; } return result; } catch (e) { print(e); + } finally { + if (stream != null) { + stream.cancel(); + } } } @@ -221,3 +237,207 @@ Future getDeviceNetVersion(THapp tHapp, int times) async { return netType; } } + +/// 发送关闭blog日志与开启业务日志的指令 +Future sendBlogAndDlogCommands(THapp tHapp) async { + edm.EasyDartModule.logger.info("发送 blog disable 与 dlog on business 指令"); + DailyLogUtils.writeLog("发送 blog disable 与 dlog on business 指令"); + try { + // 第一步:发送 blog disable + await Future.delayed(const Duration(seconds: 20)); + ef.log("[发送指令] blog disable"); + var blogResult = await tHapp.send("blog disable", true, (ss) { + var log = ss.log; + if (log.contains("disable") || + log.contains("ok") || + log.contains("success")) { + ef.log("[blog disable 响应] ${log}"); + ss.result = true; + ss.over = true; + return true; + } + return true; + }, 0, 1000); + + // 第二步:发送 dlog on business + ef.log("[发送指令] dlog on business"); + var dlogResult = await tHapp.send("dlog on hal", true, (ss) { + var log = ss.log; + if (log.contains("on business") || + log.contains("ok") || + log.contains("success")) { + ef.log("[dlog on business 响应] ${log}"); + ss.result = true; + ss.over = true; + return true; + } + + return true; + }, 0, 1000); + + if (!dlogResult) { + edm.EasyDartModule.logger.error("dlog on business 指令执行失败或超时"); + DailyLogUtils.writeLog("dlog on business 指令执行失败或超时"); + return false; + } + + edm.EasyDartModule.logger.info("blog disable 与 dlog on business 指令发送完成"); + DailyLogUtils.writeLog("blog disable 与 dlog on business 指令发送完成"); + return true; + } catch (e) { + edm.EasyDartModule.logger.error("发送 blog/dlog 指令异常: ${e.toString()}"); + DailyLogUtils.writeLog("发送 blog/dlog 指令异常 -> ${e.toString()}"); + return false; + } +} + +/// 执行 wscan close -> 延迟 1s -> wscan open +Future sendCloseAndOpenWscanCommand(THapp tHapp) async { + edm.EasyDartModule.logger.info("执行 wscan close -> wscan open 指令"); + DailyLogUtils.writeLog("执行 wscan close -> wscan open 指令开始"); + + try { + // 第一步:关闭 wscan + ef.log("[发送指令] wscan close"); + edm.EasyDartModule.logger.info("发送 wscan close 指令"); + DailyLogUtils.writeLog("发送 wscan close 指令"); + + await tHapp.send("wscan close", true, (ss) { + // 不判断是否成功,直接结束 + ss.over = true; + return true; + }, 0, 1000); + + // 等待 1 秒再执行下一个指令 + await Future.delayed(const Duration(seconds: 1)); + + // 第二步:开启 wscan + ef.log("[发送指令] wscan open"); + edm.EasyDartModule.logger.info("发送 wscan open 指令"); + DailyLogUtils.writeLog("发送 wscan open 指令"); + + await tHapp.send("wscan open", true, (ss) { + // 不判断是否成功,直接结束 + ss.over = true; + return true; + }, 0, 1000); + + edm.EasyDartModule.logger.info("wscan close -> wscan open 指令执行完成"); + DailyLogUtils.writeLog("wscan close -> wscan open 指令执行完成"); + ef.log("[执行完成] wscan close -> wscan open"); + await Future.delayed(const Duration(seconds: 3)); + return true; + } catch (e) { + edm.EasyDartModule.logger + .error("执行 wscan close/open 指令异常: ${e.toString()}"); + DailyLogUtils.writeLog("执行 wscan close/open 指令异常 -> ${e.toString()}"); + ef.log("[异常] 执行 wscan close/open 失败: ${e.toString()}"); + return false; + } +} + + +/// 查询设备内存状态(指令: free all) +/// +/// 示例返回: +/// 2025-10-27 11:47:22 当前系统内存剩余:895643 字节 +/// 2025-10-27 11:47:22 关键内存剩余:27111 字节 , jiffies = 164029 +/// +/// 若匹配到“关键内存剩余:xxxx 字节”,其中 xxxx < 20000 返回 false, +/// 否则返回 true。 +Future queryMemory(THapp tHapp, {int times = 1}) async { + edm.EasyDartModule.logger.info("发送查询内存状态指令 (free all)"); + DailyLogUtils.writeLog("发送查询内存状态指令 (free all)"); + + try { + final result = await tHapp.send("free all", true, (ss) { + final log = ss.log; + ef.log("[内存查询日志]:$log"); + + // 匹配关键内存剩余:xxxxx 字节 + final match = RegExp(r'关键内存剩余:(\d+)\s*字节').firstMatch(log); + if (match != null) { + final freeValue = int.tryParse(match.group(1) ?? "0") ?? 0; + edm.EasyDartModule.logger + .info("提取到关键内存剩余: $freeValue 字节"); + DailyLogUtils.writeLog("提取到关键内存剩余: $freeValue 字节"); + + // 判断内存是否充足 + final bool isEnough = freeValue > 20000; + + ss.result = isEnough; + ss.over = true; + return true; + } + + return false; // 未匹配到继续监听 + }, times, 3000); + + // result 就是 send 内部设置的 ss.result + if (result is bool) { + edm.EasyDartModule.logger + .info("内存检测结果 -> ${result ? "充足" : "不足"}"); + DailyLogUtils.writeLog("内存检测结果 -> ${result ? "充足" : "不足"}"); + return result; + } + + edm.EasyDartModule.logger.error("未检测到有效内存信息"); + DailyLogUtils.writeLog("未检测到有效内存信息"); + return false; + } catch (e) { + edm.EasyDartModule.logger.error("查询内存状态异常: ${e.toString()}"); + DailyLogUtils.writeLog("查询内存状态异常 -> ${e.toString()}"); + return false; + } +} + + +/// 重启设备指令 +/// +/// 发送 "reboot" 命令,若响应中包含 reboot / restart / ok / success 等关键字 +/// 视为执行成功,返回 true;否则返回 false。 +Future rebootDevice(THapp tHapp) async { + edm.EasyDartModule.logger.info("发送设备重启指令 (reboot)"); + DailyLogUtils.writeLog("发送设备重启指令 (reboot)"); + + try { + ef.log("[发送指令] reboot"); + final result = await tHapp.send("reboot", true, (ss) { + final log = ss.log; + ef.log("[设备重启响应]:$log"); + + // 匹配常见的重启反馈 + if (log.contains("reboot") || + log.contains("restart") || + log.contains("ok") || + log.contains("success")) { + edm.EasyDartModule.logger.info("设备重启命令执行成功"); + DailyLogUtils.writeLog("设备重启命令执行成功"); + ss.result = true; + ss.over = true; + return true; + } + + // 继续监听 + return false; + }, 1, 3000); + + // 如果 tHapp.send 没返回 true,记录失败 + if (result != true) { + edm.EasyDartModule.logger.error("设备重启指令执行失败或超时"); + DailyLogUtils.writeLog("设备重启指令执行失败或超时"); + return false; + } + + edm.EasyDartModule.logger.info("设备重启指令执行完成"); + DailyLogUtils.writeLog("设备重启指令执行完成"); + return true; + } catch (e) { + edm.EasyDartModule.logger.error("发送设备重启指令异常: ${e.toString()}"); + DailyLogUtils.writeLog("发送设备重启指令异常 -> ${e.toString()}"); + ef.log("[异常] 执行 reboot 失败: ${e.toString()}"); + return false; + } +} + + diff --git a/lib/controller/mh_controller/device_list_controller.dart b/lib/controller/mh_controller/device_list_controller.dart index c5aea4f..37bcb2e 100644 --- a/lib/controller/mh_controller/device_list_controller.dart +++ b/lib/controller/mh_controller/device_list_controller.dart @@ -1,8 +1,6 @@ import 'dart:convert'; -import 'dart:ui'; import 'package:EasyDartModule/EasyDartModule.dart'; -import 'package:ef/base/http/dio.dart'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -12,8 +10,6 @@ import 'package:vbvs_app/common/util/DailyLogUtils.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/common/util/requestWithLog.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; - -import 'package:vbvs_app/controller/mh_controller/device.dart'; import 'package:vbvs_app/model/api_response.dart'; part 'device_list_controller.g.dart'; diff --git a/lib/pages/mh_page/Vital_signs_sensor.dart b/lib/pages/mh_page/Vital_signs_sensor.dart index bd1a371..e16752b 100644 --- a/lib/pages/mh_page/Vital_signs_sensor.dart +++ b/lib/pages/mh_page/Vital_signs_sensor.dart @@ -106,53 +106,53 @@ class _VitalSignsSensorState extends State { left: 0.rpx, child: returnIconButtomNew(), ), - Positioned( - right: 0.rpx, - child: ClickableContainer( - backgroundColor: Colors.transparent, - highlightColor: Colors.transparent, - padding: EdgeInsets.symmetric( - horizontal: 30.rpx, vertical: 30.rpx), - onTap: () { - // TopSlideNotification.show(context); - //检测蓝牙是否开启,没有开启提示开启蓝牙 - //如果已经开启,则进行x秒的蓝牙扫描 - BluetoothHelper.listenBluetoothState((isOn) { - mhtBlueToothController.model.bluetooth = isOn; - mhtBlueToothController.updateAll(); - if (!isOn) { - mhtBlueToothController.model.blueRawData = []; - mhtBlueToothController - .model.deviceDataStatus = []; - mhtBlueToothController.updateAll(); - _showBluetoothNotEnabledDialog(); - } - }); - _checkBluetoothPermission(); - }, - child: Obx(() { - return SizedBox( - width: 34.rpx, - height: mhtBlueToothController.isScanning.value - ? 34.rpx - : 24.rpx, - child: mhtBlueToothController.isScanning.value - ? CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation( - themeController.currentColor.sc3, - ), - ) - : SvgPicture.asset( - 'assets/img/icon/upgrade.svg', - fit: BoxFit.cover, - color: Colors.white, - ), - ); - }), - ), - ), + // Positioned( + // right: 0.rpx, + // child: ClickableContainer( + // backgroundColor: Colors.transparent, + // highlightColor: Colors.transparent, + // padding: EdgeInsets.symmetric( + // horizontal: 30.rpx, vertical: 30.rpx), + // onTap: () { + // // TopSlideNotification.show(context); + // //检测蓝牙是否开启,没有开启提示开启蓝牙 + // //如果已经开启,则进行x秒的蓝牙扫描 + // BluetoothHelper.listenBluetoothState((isOn) { + // mhtBlueToothController.model.bluetooth = isOn; + // mhtBlueToothController.updateAll(); + // if (!isOn) { + // mhtBlueToothController.model.blueRawData = []; + // mhtBlueToothController + // .model.deviceDataStatus = []; + // mhtBlueToothController.updateAll(); + // _showBluetoothNotEnabledDialog(); + // } + // }); + // _checkBluetoothPermission(); + // }, + // child: Obx(() { + // return SizedBox( + // width: 34.rpx, + // height: mhtBlueToothController.isScanning.value + // ? 34.rpx + // : 24.rpx, + // child: mhtBlueToothController.isScanning.value + // ? CircularProgressIndicator( + // strokeWidth: 2, + // valueColor: + // AlwaysStoppedAnimation( + // themeController.currentColor.sc3, + // ), + // ) + // : SvgPicture.asset( + // 'assets/img/icon/upgrade.svg', + // fit: BoxFit.cover, + // color: Colors.white, + // ), + // ); + // }), + // ), + // ), ], ), ), @@ -279,12 +279,16 @@ class _VitalSignsSensorState extends State { .toList(); //todo 过滤,跟远程的版本信息比对 // return macList.contains(d.mac) && d.version != null; - if (formatString(d.mac) == "48CA43B2E0B4") { - ef.log(""); + if (macList.contains(formatString(d.mac))) { + ef.log("[待升级设备]:${d.mac}, 版本:${d.version}"); } - return macList.contains(formatString(d.mac)); + // return macList.contains(formatString(d.mac)) && + // d.version != null && + // judgeNeedUpgrade(d.version); + return macList.contains(formatString(d.mac)) && + judgeNeedUpgrade(d.version); }).toList(); - print("$filteredResults"); + for (var item in filteredResults) { // 如果不存在才加入,初始进度设为-1,代表未开始升级 mhtBlueToothController.localUpgradeMac.putIfAbsent( @@ -436,6 +440,42 @@ class _VitalSignsSensorState extends State { /// 格式化字符串:移除所有空格和冒号,并将小写字母转换为大写 return input.replaceAll(' ', '').replaceAll(':', '').toUpperCase(); } + + bool judgeNeedUpgrade(int? version) { + return true; + try { + if (version == null) { + ef.log("[升级判断] 本地版本为空,不需要升级"); + return false; + } + + String? newestVersionStr = mhtBlueToothController.currentUpgradeVersion; + if (newestVersionStr == null || newestVersionStr.isEmpty) { + ef.log("[升级判断] 远程最新版本为空,不需要升级"); + return false; + } + + // 转为整数比较 + int? newestVersion = int.tryParse(newestVersionStr); + if (newestVersion == null) { + ef.log("[升级判断] 远程版本格式错误: $newestVersionStr"); + return false; + } + + ef.log("[升级判断] 当前版本: $version,远程版本: $newestVersion"); + + if (newestVersion > version) { + ef.log("[升级判断] 检测到新版本,需要升级"); + return true; + } else { + ef.log("[升级判断] 已是最新版本,无需升级"); + return false; + } + } catch (e) { + ef.log("[升级判断] 异常: $e"); + return false; + } + } } class VitalWidget extends StatelessWidget { @@ -843,6 +883,7 @@ class VitalWidget extends StatelessWidget { mac: data['mac'], firmwareUrl: firmwareUrl, ); + } catch (e) { print("升级失败: $e"); TopSlideNotification.show(context, @@ -960,520 +1001,6 @@ class VitalWidget extends StatelessWidget { } } -// class VitalWidget extends StatelessWidget { -// final String title; -// final Map data; - -// const VitalWidget({ -// super.key, -// required this.title, -// required this.data, -// }); - -// @override -// Widget build(BuildContext context) { -// MHTBlueToothController mhtBlueToothController = Get.find(); -// final String id = data['mac'.tr] ?? '--'; -// final int? timestamp = data['status']['updateTime']; -// final String time = (timestamp != null) -// ? DateFormat('yyyy-MM-dd HH:mm') -// .format(DateTime.fromMillisecondsSinceEpoch(timestamp)) -// : '--'; - -// return ClickableContainer( -// backgroundColor: Color(0xFF003058), -// highlightColor: Color(0xFF055466), -// borderRadius: 20.rpx, -// padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 30.rpx, 30.rpx, 40.rpx), -// onTap: () {}, -// child: Column( -// mainAxisSize: MainAxisSize.max, -// children: [ -// Container( -// width: double.infinity, -// child: Align( -// alignment: AlignmentDirectional(-1, 0), -// child: Text( -// title, -// style: TextStyle( -// fontFamily: 'Inter', -// fontSize: 30.rpx, -// letterSpacing: 0.0, -// color: themeController.currentColor.sc3, -// ), -// ), -// ), -// ), -// Row( -// mainAxisAlignment: MainAxisAlignment.start, -// children: [ -// Container( -// width: MediaQuery.sizeOf(context).width * 0.14, -// constraints: BoxConstraints(minWidth: 110.rpx), -// child: Text( -// "设备ID".tr, -// style: TextStyle( -// color: stringToColor("#929699"), -// fontSize: 26.rpx, -// ), -// maxLines: 2, -// overflow: TextOverflow.ellipsis, -// ), -// ), -// Text( -// id, -// style: TextStyle(fontSize: 26.rpx, color: Color(0xFFFFFFFF)), -// ), -// ].divide(SizedBox(width: 33.rpx)), -// ), -// Row( -// mainAxisAlignment: MainAxisAlignment.start, -// children: [ -// Container( -// width: MediaQuery.sizeOf(context).width * 0.14, -// constraints: BoxConstraints(minWidth: 110.rpx), -// child: Text( -// "更新时间".tr, -// style: TextStyle( -// color: stringToColor("#929699"), -// fontSize: 26.rpx, -// ), -// maxLines: 2, -// overflow: TextOverflow.ellipsis, -// ), -// ), -// Text( -// time, -// style: TextStyle(fontSize: 26.rpx, color: Color(0xFFFFFFFF)), -// ), -// ].divide(SizedBox(width: 33.rpx)), -// ), -// Row( -// mainAxisSize: MainAxisSize.max, -// children: [ -// Container( -// width: MediaQuery.sizeOf(context).width * 0.14, -// constraints: BoxConstraints(minWidth: 110.rpx), -// child: Text( -// "设备状态".tr, -// style: TextStyle( -// color: stringToColor("#929699"), -// fontSize: 26.rpx, -// ), -// maxLines: 2, -// overflow: TextOverflow.ellipsis, -// ), -// ), -// Expanded( -// child: Row( -// mainAxisSize: MainAxisSize.max, -// children: [ -// if (data['status']['signal'] != null && -// data['status']['signal'] != -1 && -// data['status']['status'] != null && -// data['status']['status'] == 1) -// ClickableContainer( -// backgroundColor: Colors.transparent, -// highlightColor: Colors.grey, -// padding: EdgeInsets.zero, -// borderRadius: 0, -// onTap: () { -// showTipDialog( -// context, -// Container( -// child: RichText( -// text: TextSpan( -// text: "信号强度".tr, -// style: TextStyle( -// color: Colors.black, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// children: [ -// TextSpan( -// text: getBedSignal( -// data['status']['signal']), -// style: TextStyle( -// color: themeController.currentColor.sc2, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// ), -// ], -// ), -// ), -// ), -// backgroundColor: Color(0xFFFFFFFF), -// colors: [ -// Color(0XFF1592AA), -// Color(0xFF0C83A7), -// Color(0xFF006FA3) -// ], -// ); -// }, -// child: Container( -// width: 30.rpx, -// height: 24.rpx, -// child: Image.asset( -// 'assets/img/signal${_getSignalLevel(data['status']['signal'])}.png'), -// ), -// ), -// if (data['status']['inBed'] != null && -// data['status']['status'] != null && -// data['status']['status'] == 1) -// ClickableContainer( -// backgroundColor: Colors.transparent, -// highlightColor: Colors.grey, -// padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), -// borderRadius: 0, -// onTap: () { -// showTipDialog( -// context, -// Container( -// child: RichText( -// text: TextSpan( -// text: "是否在床".tr, -// style: TextStyle( -// color: Colors.black, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// children: [ -// TextSpan( -// text: -// getBedStatus(data['status']['inBed']), -// style: TextStyle( -// color: themeController.currentColor.sc2, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// ), -// ], -// ), -// ), -// ), -// backgroundColor: Color(0xFFFFFFFF), -// colors: [ -// Color(0XFF1592AA), -// Color(0xFF0C83A7), -// Color(0xFF006FA3) -// ], -// ); -// }, -// child: SizedBox( -// width: 16.rpx, -// height: 36.rpx, -// child: SvgPicture.asset( -// data['status']['inBed'] == 0 -// ? 'assets/img/icon/not_bed.svg' -// : 'assets/img/icon/in_bed.svg', -// fit: BoxFit.fill, -// ), -// ), -// ), -// if (data['status']['failure'] != 0 && -// data['status']['status'] != null && -// data['status']['status'] == 1) -// ClickableContainer( -// backgroundColor: Colors.transparent, -// highlightColor: Colors.grey, -// padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), -// borderRadius: 0, -// onTap: () { -// showTipDialog( -// context, -// Container( -// child: RichText( -// text: TextSpan( -// text: "设备故障".tr, -// style: TextStyle( -// color: Colors.black, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// children: const [], -// ), -// ), -// ), -// backgroundColor: Color(0xFFFFFFFF), -// colors: [ -// Color(0XFF1592AA), -// Color(0xFF0C83A7), -// Color(0xFF006FA3) -// ], -// ); -// }, -// child: SizedBox( -// width: 27.rpx, -// height: 27.rpx, -// child: SvgPicture.asset( -// 'assets/img/icon/device_issue.svg', -// fit: BoxFit.cover, -// ), -// ), -// ), -// if (data['status']['status'] != null && -// data['status']['status'] == 0) -// ClickableContainer( -// backgroundColor: Colors.transparent, -// highlightColor: Colors.grey, -// padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), -// borderRadius: 0, -// onTap: () { -// showTipDialog( -// context, -// Container( -// child: RichText( -// text: TextSpan( -// text: "网络状态".tr, -// style: TextStyle( -// color: Colors.black, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// children: [ -// TextSpan( -// text: data['status']['status'] == 1 -// ? "在线".tr -// : "离线".tr, -// style: TextStyle( -// color: themeController.currentColor.sc2, -// fontSize: -// AppConstants().title_text_fontSize, -// ), -// ), -// ], -// ), -// ), -// ), -// backgroundColor: Color(0xFFFFFFFF), -// colors: [ -// Color(0XFF1592AA), -// Color(0xFF0C83A7), -// Color(0xFF006FA3) -// ], -// ); -// }, -// child: SizedBox( -// width: 27.rpx, -// height: 27.rpx, -// child: SvgPicture.asset( -// 'assets/img/icon/device_issue.svg', -// fit: BoxFit.cover, -// ), -// ), -// ), -// Obx(() { -// final upgradeInfo = -// mhtBlueToothController.localUpgradeMac[data['mac']]; -// if (upgradeInfo == null) { -// return Container(); -// } -// final int progress = upgradeInfo?['progress'] ?? -1; -// final String status = upgradeInfo?['status'] ?? ''; -// // 只有在有升级信息时才显示 -// if (mhtBlueToothController.localUpgradeMac -// .containsKey(data['mac'])) { -// return ClickableContainer( -// backgroundColor: Colors.transparent, -// highlightColor: Colors.grey, -// padding: -// EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), -// borderRadius: 0, -// onTap: () { -// if (progress == -1) { -// _showUpgradeDialog(context, data['mac']); -// } else { -// _showCancelDialog(context, data['mac']); -// } -// }, -// child: Row( -// children: [ -// // 升级图标 -// SizedBox( -// width: 34.rpx, -// height: 24.rpx, -// child: SvgPicture.asset( -// 'assets/img/icon/upgrade.svg', -// fit: BoxFit.cover, -// color: _getUpgradeIconColor(status), -// ), -// ), -// SizedBox(width: 10.rpx), -// // 进度数字和状态指示 -// Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// mainAxisSize: MainAxisSize.min, -// children: [ -// // 进度百分比 -// if (progress >= 0 && progress <= 100) -// Text( -// "$progress%", -// style: TextStyle( -// color: _getProgressTextColor(progress), -// fontSize: 26.rpx, -// fontWeight: FontWeight.bold, -// ), -// ), -// ], -// ), -// ], -// ), -// ); -// } -// return Container(); -// }), -// ].divide(SizedBox(width: 50.rpx)), // 减少图标间距 -// ), -// ), -// ].divide(SizedBox(width: 34.rpx)), -// ), -// ].divide(SizedBox(height: 20.rpx)), -// ), -// ); -// } - -// // 获取状态文本 -// String _getStatusText(String status) { -// switch (status) { -// case 'waiting': -// return '等待'.tr; -// case 'downloading': -// return '下载'.tr; -// case 'upgrading': -// return '升级'.tr; -// case 'completed': -// return '完成'.tr; -// case 'failed': -// return '失败'.tr; -// case 'cancelled': -// return '取消'.tr; -// default: -// return status; -// } -// } - -// // 获取状态文字颜色 -// Color _getStatusTextColor(String status) { -// switch (status) { -// case 'completed': -// return Colors.green; -// case 'failed': -// return Colors.red; -// case 'cancelled': -// return Colors.orange; -// default: -// return Colors.blue; -// } -// } - -// // 获取进度文字颜色 -// Color _getProgressTextColor(int progress) { -// if (progress == 100) return Colors.green; -// if (progress < 0) return Colors.red; -// return Colors.white; -// } - -// // 获取升级图标颜色 -// Color _getUpgradeIconColor(String status) { -// switch (status) { -// case 'completed': -// return Colors.green; -// case 'failed': -// return Colors.red; -// case 'cancelled': -// return Colors.orange; -// default: -// return themeController.currentColor.sc3; -// } -// } - -// // 显示升级对话框 -// void _showUpgradeDialog(BuildContext context, String mac) { -// MHTBlueToothController mhtBlueToothController = Get.find(); -// showConfirmUpDialog( -// context, -// Column( -// children: [ -// SizedBox( -// width: 94.rpx, -// height: 70.rpx, -// child: SvgPicture.asset( -// 'assets/img/icon/upgrade.svg', -// fit: BoxFit.cover, -// ), -// ), -// Text( -// "设备升级".tr, -// style: TextStyle( -// color: stringToColor("#333333"), -// fontSize: AppConstants().title_text_fontSize, -// ), -// ), -// ].divide(SizedBox(height: 37.rpx)), -// ), -// "", onConfirm: () async { -// final deviceData = mhtBlueToothController.localUpgradeMac[mac]!; -// final firmwareUrl = mhtBlueToothController.currentUpgradeUrl; -// if (firmwareUrl == null) { -// TopSlideNotification.show(context, text: "未获取到固件下载地址".tr); -// return; -// } -// try { -// final scanResult = deviceData['device'].scanResult; -// final thapp = THapp(device: scanResult.device); -// if (!thapp.isConnected) { -// await thapp.device.connect(); -// } -// await MultiDeviceFirmwareUpdater().startUpgrade( -// thapp: thapp, -// mac: mac, -// firmwareUrl: firmwareUrl, -// ); -// } catch (e) { -// TopSlideNotification.show(context, -// text: "升级失败: ${e.toString()}".tr, textColor: Colors.red); -// } -// }, -// onCancel: () {}, -// backgroundColor: Colors.white, -// confirmText: "立即升级".tr, -// cancelText: "下次再说".tr); -// } - -// // 显示取消对话框 -// void _showCancelDialog(BuildContext context, String mac) { -// showConfirmCancelDialog( -// context, -// Column( -// children: [ -// Text( -// "确认取消升级".tr, -// style: TextStyle( -// color: stringToColor("#333333"), -// fontSize: AppConstants().title_text_fontSize, -// ), -// ), -// Text( -// "确定要取消设备 $mac 的升级吗?".tr, -// style: TextStyle( -// color: stringToColor("#333333"), -// fontSize: AppConstants().normal_text_fontSize, -// ), -// ), -// ], -// ), -// "", onConfirm: () { -// MultiDeviceFirmwareUpdater().cancelUpgrade(mac); -// }, -// onCancel: () {}, -// backgroundColor: Colors.white, -// confirmText: "确认取消".tr, -// cancelText: "继续升级".tr, -// confirmButtonColor: Colors.red); -// } -// } - getBedSignal(signal) { if (signal <= 1) { return "较弱".tr; diff --git a/lib/pages/mh_page/device/controller/mht_bluetooth_controller.dart b/lib/pages/mh_page/device/controller/mht_bluetooth_controller.dart index ff78abe..97d14c5 100644 --- a/lib/pages/mh_page/device/controller/mht_bluetooth_controller.dart +++ b/lib/pages/mh_page/device/controller/mht_bluetooth_controller.dart @@ -229,7 +229,7 @@ class MHTBlueToothController extends GetControllerEx { 'name': bleDevice.name, }, }; - + EasyDartModule.logger.info("绑定传感器数据: $data"); var response = await EasyDartModule.dio.post(queryUrl, data: jsonEncode(data)); if (response != null) { diff --git a/lib/pages/mh_page/device/mht_device_calibration.dart b/lib/pages/mh_page/device/mht_device_calibration.dart index e1f7698..bca23ec 100644 --- a/lib/pages/mh_page/device/mht_device_calibration.dart +++ b/lib/pages/mh_page/device/mht_device_calibration.dart @@ -12,14 +12,16 @@ import 'package:vbvs_app/common/util/requestWithLog.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/CustomCard.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; import 'package:vbvs_app/pages/device_bind/componnet/CalibrationProgressWidget.dart'; import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart'; import 'package:vbvs_app/pages/mh_page/device/component/mht_device_calibration_controller.dart'; import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart'; +import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart'; class MHTCalibrationPage extends StatefulWidget { - const MHTCalibrationPage({super.key}); - + BlueToothDataModel deviceInfo; + MHTCalibrationPage({super.key, required this.deviceInfo}); @override State createState() => _MHTCalibrationPageState(); } @@ -114,6 +116,10 @@ class _MHTCalibrationPageState extends State { onConfirm: () async { exit = true; _resetCalibrationState(); + // Get.back(); + initWifiData(); + // Get.toNamed('/mHTwifiPage', + // arguments: widget.deviceInfo); Get.back(); }, onCancel: () { exit = false; @@ -125,6 +131,9 @@ class _MHTCalibrationPageState extends State { exit = true; } if (exit) { + initWifiData(); + // Get.toNamed('/mHTwifiPage', + // arguments: widget.deviceInfo); Get.back(); } }, enableBack: exit), @@ -741,7 +750,7 @@ class _MHTCalibrationPageState extends State { } void _requestProgress( - String serviceAddress, String progressApi, bool isSecondStep) { + String serviceAddress, String progressApi, bool isSecondStep) { String cid = blueteethBindController.cid!.value; String progressUrl = "$serviceAddress$progressApi?id=$cid"; @@ -1006,4 +1015,19 @@ class _MHTCalibrationPageState extends State { onFailure: (res) {}, ); } + + void initWifiData() { + BlueteethBindController blueteethBindController = Get.find(); + blueteethBindController.shareDevice = widget.deviceInfo; + blueteethBindController.netType.value = 0; + blueteethBindController.connectStatus.value = 0; + blueteethBindController.wifiList = [].obs; + blueteethBindController.wifiStatus = 0.obs; + blueteethBindController.connect_wifi.value = {}; + blueteethBindController.selectWifi.value = {}; + blueteethBindController.wifiStatus.value = 0; + blueteethBindController.blueConnectFlag.value = 0; + blueteethBindController.wifiConnectStatus.value = 1; + blueteethBindController.updateAll(); + } } diff --git a/lib/pages/mh_page/device/mht_wifi_page.dart b/lib/pages/mh_page/device/mht_wifi_page.dart index fbce998..64cc8e8 100644 --- a/lib/pages/mh_page/device/mht_wifi_page.dart +++ b/lib/pages/mh_page/device/mht_wifi_page.dart @@ -45,17 +45,23 @@ class _MHTWifiPageState extends State { Timer? _timeoutTimer; StreamSubscription>? _scanSubscription; bool _isDisposed = false; + bool dealing = false; //是否正在刷新 + DateTime _lastTapTime = DateTime.now(); + bool haveSuccess = false; @override void initState() { super.initState(); - _initController(); - dealWifi(widget.deviceInfo.macA).then((aa) { + + WidgetsBinding.instance.addPostFrameCallback((_) async { + // _initController(); + await dealWifi(widget.deviceInfo.macA); print("object"); }); } void _initController() { + dealing = false; blueteethBindController.shareDevice = widget.deviceInfo; blueteethBindController.netType.value = 0; blueteethBindController.connectStatus.value = 0; @@ -73,11 +79,11 @@ class _MHTWifiPageState extends State { void dispose() { _isDisposed = true; _cleanupResources(); - _disconnectDevice(); + // _disconnectDevice(); super.dispose(); } - void _cleanupResources() { + Future _cleanupResources({bool needTip = true}) async { // 取消监听器 lisObj?.cancel(); lisObj = null; @@ -91,10 +97,11 @@ class _MHTWifiPageState extends State { _scanSubscription = null; // 断开蓝牙连接 - if (blueteethBindController.currentDevice != null) { - blueteethBindController.currentDevice!.disconnect(); - blueteethBindController.currentDevice = null; - } + // if (blueteethBindController.currentDevice != null) { + // blueteethBindController.currentDevice!.disconnect(); + // blueteethBindController.currentDevice = null; + // } + await _disconnectDevice(); // 停止扫描 FlutterBluePlus.stopScan(); @@ -105,24 +112,30 @@ class _MHTWifiPageState extends State { _cleanupResources(); if (_isDisposed) return; - // 导航到下一页 if (blueteethBindController.wifiStatus.value != 1) { showConfirmDialog(context, Container(), "未配置网络提示".tr, onConfirm: () async { _cleanupResources(); await _disconnectDevice(); - Get.toNamed("/calibrationPage"); + Get.toNamed("/calibrationPage", arguments: widget.deviceInfo)! + .then((value) { + dealWifi(widget.deviceInfo.macA); + }); }, onCancel: () {}); } else { _cleanupResources(); await _disconnectDevice(); - Get.toNamed("/calibrationPage"); + Get.toNamed("/calibrationPage", arguments: widget.deviceInfo)! + .then((value) { + dealWifi(widget.deviceInfo.macA); + }); } } @override Widget build(BuildContext context) { + // _initController(); return LayoutBuilder( builder: (context, bodySize) => GestureDetector( // onTap: () => FocusScope.of(context).unfocus(),, @@ -209,7 +222,13 @@ class _MHTWifiPageState extends State { ), Positioned( left: 0, - child: returnIconButtom, + child: returnIconButtomNew( + onBack: () { + // Get.offAllNamed('/mHTBlueteethDevicePage', + // arguments: widget.deviceInfo.type); + Get.back(); + }, + ), ), Positioned( right: 20.rpx, @@ -279,6 +298,9 @@ class _MHTWifiPageState extends State { ), ), Obx(() { + var cc = blueteethBindController + .wifiStatus.value; + print("${cc}"); return Text( blueteethBindController .wifiStatus.value == @@ -552,6 +574,7 @@ class _MHTWifiPageState extends State { wifiItem['ssid'] ?? '未命名'.tr, onConfirm: () async { + haveSuccess = false; blueteethBindController .selectWifi .value = wifiItem; @@ -561,14 +584,55 @@ class _MHTWifiPageState extends State { .model.wifiPass!, blueteethBindController .currentDevice!); + bool memoryFlag = + await queryMemory( + blueteethBindController + .currentDevice!); + if (!memoryFlag) { + await rebootDevice( + blueteethBindController + .currentDevice!); + await dealWifi( + widget + .deviceInfo.macA, + needSuccess: true); + // return; + } + if (!flag) { + blueteethBindController + .selectWifi + .value = {}; + // TopSlideNotification.show( + // context, + // textColor: + // themeController + // .currentColor + // .sc9, + // text: + // '蓝牙已断开,请点击下方刷新按钮重试' + // .tr); + return; + } if (flag) { var aa = await getDeviceWifiStatus( blueteethBindController .currentDevice!, - 1); + 4, + link: true); + aa = await restoreWifi( + blueteethBindController + .currentDevice!, + aa); + if (!memoryFlag) { + aa = await rebootDeviceCurrent( + blueteethBindController + .currentDevice!, + aa); + } blueteethBindController .selectWifi .value = {}; + if (aa != null && aa is Map) { blueteethBindController @@ -578,30 +642,46 @@ class _MHTWifiPageState extends State { blueteethBindController .connect_wifi .value = {}; + blueteethBindController + .wifiStatus + .value == + 0; + blueteethBindController + .updateAll(); } blueteethBindController .wifiStatus .value = aa != null ? 1 : 0; - if (aa != null&& + if (aa != null && aa != false) { updateDeviceBindStatus( blueteethBindController .currentDeviceMac! .value); - TopSlideNotification - .show( - context, - text: "配网成功".tr, - textColor: - themeController - .currentColor - .sc2, - ); + if (!haveSuccess) { + TopSlideNotification + .show( + context, + text: "配网成功".tr, + textColor: + themeController + .currentColor + .sc2, + ); + } } else { - blueteethBindController + blueteethBindController .connect_wifi .value = {}; + blueteethBindController + .selectWifi + .value = {}; + blueteethBindController + .wifiStatus + .value = 0; + blueteethBindController + .updateAll(); TopSlideNotification .show( context, @@ -613,9 +693,16 @@ class _MHTWifiPageState extends State { ); } } else { - blueteethBindController - .connect_wifi - .value = {}; + blueteethBindController + .selectWifi + .value = {}; + blueteethBindController + .connect_wifi + .value = {}; + blueteethBindController + .wifiStatus.value = 0; + blueteethBindController + .updateAll(); TopSlideNotification.show( context, text: "配网失败".tr, @@ -626,7 +713,6 @@ class _MHTWifiPageState extends State { ); } }); - }, child: Row( mainAxisSize: @@ -678,6 +764,17 @@ class _MHTWifiPageState extends State { horizontal: 20.rpx, vertical: 10.rpx), borderRadius: 20.rpx, onTap: () async { + if (DateTime.now() + .difference(_lastTapTime) < + Duration(seconds: 2)) { + return; // 防止快速重复点击 + } + _lastTapTime = DateTime.now(); + blueteethBindController.netType.value = 0; + blueteethBindController + .blueConnectFlag.value = 0; + blueteethBindController.wifiList.value = + []; var bluetoothState = await FlutterBluePlus.isOn; blueteethBindController.bluetoothStatus @@ -694,13 +791,13 @@ class _MHTWifiPageState extends State { 1) { blueteethBindController .blueConnectFlag.value = 0; - dealWifi(widget.deviceInfo.macA) + await dealWifi(widget.deviceInfo.macA, + needTip: false) .then((aa) { print("object"); }); return; } - if (blueteethBindController .netType.value == 0) { @@ -712,6 +809,7 @@ class _MHTWifiPageState extends State { blueteethBindController .currentDevice!, 1); + if (aa == "4g") { updateDeviceBindStatus( blueteethBindController @@ -731,7 +829,10 @@ class _MHTWifiPageState extends State { const Duration(seconds: 1), () { _cleanupResources(); Get.toNamed("/calibrationPage", - arguments: 1); + arguments: 1)! + .then((value) { + dealWifi(widget.deviceInfo.macA); + }); }); } else if (aa == 'unknown') { blueteethBindController.netType.value = @@ -746,6 +847,7 @@ class _MHTWifiPageState extends State { .currentColor.sc9, ); }); + await initWifiStatusAndWifiList(); } else { blueteethBindController.netType.value = 1; @@ -798,24 +900,40 @@ class _MHTWifiPageState extends State { ); } - Future initWifiStatusAndWifiList() async { + Future initWifiStatusAndWifiList( + {int retryCount = 0, bool needSuccess = false}) async { if (_isDisposed) return; if (lisObj != null) { lisObj!.cancel(); + lisObj = null; } bool wifiStatus = false; - var aa = - await getDeviceWifiStatus(blueteethBindController.currentDevice!, 0); - if (aa != null && aa is Map) { - updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); - wifiStatus = true; - blueteethBindController.connect_wifi.value = aa; - } else { - wifiStatus = false; + try { + // 获取WiFi状态 + var aa = + await getDeviceWifiStatus(blueteethBindController.currentDevice!, 0); + if (aa != null && aa is Map) { + updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); + wifiStatus = true; + blueteethBindController.connect_wifi.value = aa; + if (needSuccess) { + haveSuccess = true; + TopSlideNotification.show( + context, + text: "配网成功".tr, + textColor: themeController.currentColor.sc2, + ); + } + } else { + wifiStatus = false; + } + blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0; + } catch (e) { + print("获取WiFi状态异常: $e"); + blueteethBindController.wifiStatus.value = 0; } - blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0; List wifiList = []; try { @@ -836,19 +954,52 @@ class _MHTWifiPageState extends State { if (wifiList.isNotEmpty) { blueteethBindController.connectStatus.value = 1; blueteethBindController.updateAll(); - TopSlideNotification.show( - context, - text: "获取wifi列表成功".tr, - textColor: themeController.currentColor.sc2, - ); + // TopSlideNotification.show( + // context, + // text: "获取wifi列表成功".tr, + // textColor: themeController.currentColor.sc2, + // ); blueteethBindController.wifiList.value = wifiList; blueteethBindController.updateAll(); } else { + // 获取WiFi列表失败,尝试重新扫描 + if (retryCount < 2) { + // 最多重试2次 + print("第${retryCount + 1}次获取WiFi列表失败,尝试重新扫描..."); + + // TopSlideNotification.show( + // context, + // text: "正在重新扫描WiFi...".tr, + // textColor: themeController.currentColor.sc2, + // ); + + try { + // 发送关闭并重新打开WiFi扫描命令 + await sendCloseAndOpenWscanCommand( + blueteethBindController.currentDevice!); + + // 等待一段时间让设备重新扫描 + await Future.delayed(Duration(seconds: 3)); + + // 递归调用自身进行重试 + await initWifiStatusAndWifiList(retryCount: retryCount + 1); + return; // 重试后直接返回,避免执行后面的代码 + } catch (e) { + print("重新扫描WiFi失败: $e"); + // 继续执行下面的失败处理 + } + } + + // 重试次数用尽或重试失败,显示最终失败提示 TopSlideNotification.show( context, text: "获取wifi列表失败".tr, textColor: themeController.currentColor.sc9, ); + + // 可选:重置WiFi连接状态 + blueteethBindController.connectStatus.value = 0; + blueteethBindController.updateAll(); } lisObj = blueteethBindController.currentDevice!.statusStream @@ -859,6 +1010,21 @@ class _MHTWifiPageState extends State { edm.EasyDartModule.logger.info("[bleee]:" + line); DailyLogUtils.writeLog("[bleee]:" + line); } + if (onData.status == BleEventType.disconnected) { + print("蓝牙连接已断开"); + blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.updateAll(); + + // 显示断开提示 + // if (!_isDisposed) { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接已断开,请重新连接".tr, + // textColor: themeController.currentColor.sc9, + // ); + // } + _autoReconnect(); + } }); } @@ -910,16 +1076,21 @@ class _MHTWifiPageState extends State { } } - Future dealWifi(String mac) async { - if (_isDisposed) return; - - final blueteethBindController = Get.find(); - final themeController = Get.find(); - - // 清理之前的资源 - _cleanupResources(); + Future dealWifi(String mac, + {bool needTip = true, bool needSuccess = false}) async { + if (dealing) { + return; + } try { + dealing = true; + if (_isDisposed) return; + + final blueteethBindController = Get.find(); + final themeController = Get.find(); + + // 清理之前的资源 + _cleanupResources(needTip: needTip); // 检查蓝牙状态 var bluetoothState = await FlutterBluePlus.isOn; blueteethBindController.bluetoothStatus.value = bluetoothState; @@ -938,6 +1109,7 @@ class _MHTWifiPageState extends State { _timeoutTimer = Timer(Duration(seconds: 20), () { if (!isConnected && !_isDisposed) { blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.netType.value = 3; blueteethBindController.updateAll(); TopSlideNotification.show( context, @@ -945,6 +1117,7 @@ class _MHTWifiPageState extends State { textColor: themeController.currentColor.sc9, ); FlutterBluePlus.stopScan(); + blueteethBindController.updateAll(); } }); @@ -971,34 +1144,76 @@ class _MHTWifiPageState extends State { isConnected = true; _timeoutTimer?.cancel(); _scanSubscription?.cancel(); - + var streamlog; try { - THapp bledevice = THapp(device: targetDevice.device); - await bledevice.device.connect(); - var res2 = bledevice.isConnected; + THapp bledevice = THapp(device: targetDevice!.device); - if (res2 && !_isDisposed) { + blueteethBindController.currentDevice = bledevice; + streamlog = blueteethBindController.currentDevice!.logingStream + .listen((log) { + ef.log("[传感器设备日志]: $log"); + edm.EasyDartModule.logger.info("[传感器设备日志]: $log"); + }); + bledevice.autoConnect = true; + const int maxRetry = 3; + int retryCount = 0; + bool connected = false; + + while (retryCount < maxRetry && !_isDisposed) { + try { + await bledevice.device.connect(); + connected = bledevice.isConnected; + if (connected) break; + } catch (e) { + retryCount++; + print("[蓝牙连接错误] 第${retryCount}次重试: $e"); + edm.EasyDartModule.logger + .info("[蓝牙连接错误] 第${retryCount}次重试: $e"); + DailyLogUtils.writeLog("[蓝牙连接错误] 第${retryCount}次重试: $e"); + + // 延迟重试 + await Future.delayed(const Duration(seconds: 2)); + } + } + + if (connected && !_isDisposed) { blueteethBindController.blueConnectFlag.value = 2; - TopSlideNotification.show( - context, - text: "连接成功".tr, - textColor: themeController.currentColor.sc2, - ); - blueteethBindController.currentDevice = bledevice; - lisObj = blueteethBindController.currentDevice!.statusStream - .listen((onData) async { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接成功".tr, + // textColor: themeController.currentColor.sc2, + // ); + + lisObj = bledevice.statusStream.listen((onData) async { if (_isDisposed) return; if (onData.status == BleEventType.recvLineLog) { final line = onData.val; - print("[bleee]:" + line); - edm.EasyDartModule.logger.info("[bleee]:" + line); - DailyLogUtils.writeLog("[bleee]:" + line); + print("[bleee]: $line"); + edm.EasyDartModule.logger.info("[bleee]: $line"); + DailyLogUtils.writeLog("[bleee]: $line"); } + + // 添加连接状态监听 + if (onData.status == BleEventType.disconnected) { + print("蓝牙连接已断开"); + blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.updateAll(); + + // 显示断开提示 + // if (!_isDisposed) { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接已断开,请重新连接".tr, + // textColor: themeController.currentColor.sc9, + // ); + // } + _autoReconnect(); + } + if (onData.status == BleEventType.ready) { - var aa = await getDeviceNetVersion( - blueteethBindController.currentDevice!, 0); + var aa = await getDeviceNetVersion(bledevice, 0); if (aa == "4g") { blueteethBindController.netType.value = 2; blueteethBindController.updateAll(); @@ -1025,23 +1240,27 @@ class _MHTWifiPageState extends State { blueteethBindController.updateAll(); blueteethBindController.wifiConnectStatus.value = 0; blueteethBindController.updateAll(); - await initWifiStatusAndWifiList(); + await initWifiStatusAndWifiList(needSuccess: needSuccess); } + dealing = false; } }); } else { TopSlideNotification.show( context, - text: "蓝牙绑定.连接失败".tr, + text: "设备连接失败,请点击刷新重试".tr, textColor: themeController.currentColor.sc9, ); } } catch (e) { + blueteethBindController.blueConnectFlag.value = 1; TopSlideNotification.show( context, - text: "设备连接失败".tr, + text: "设备连接失败,请点击刷新重试".tr, textColor: themeController.currentColor.sc9, ); + } finally { + streamlog.close(); } } }); @@ -1054,10 +1273,12 @@ class _MHTWifiPageState extends State { text: "扫描过程中发生错误".tr, textColor: themeController.currentColor.sc9, ); + dealing = false; } } finally { _timeoutTimer?.cancel(); await FlutterBluePlus.stopScan(); + dealing = false; } } @@ -1123,11 +1344,73 @@ class _MHTWifiPageState extends State { Future _disconnectDevice() async { try { - THapp bledevice = THapp(device: widget.deviceInfo.scanResult.device); - await bledevice.disconnect(); + if (blueteethBindController.currentDevice != null) { + await blueteethBindController.currentDevice!.disconnect(); + // blueteethBindController.currentDevice = null; + } DailyLogUtils.writeLog("关闭蓝牙连接成功".tr); } catch (e) { DailyLogUtils.writeError("关闭蓝牙连接失败: $e"); + } finally { + // dealing = false; + } + } + + Future restoreWifi(THapp tHapp, aa) async { + if (aa != null && aa is Map) { + return aa; + } + await sendCloseAndOpenWscanCommand(tHapp); + return await getDeviceWifiStatus(blueteethBindController.currentDevice!, 4, + link: true); + } + + Future rebootDeviceCurrent(THapp tHapp, aa) async { + if (aa != null && aa is Map) { + return aa; + } + await rebootDevice( + blueteethBindController.currentDevice!, + ); + await dealWifi( + widget.deviceInfo.macA, + ); + return await getDeviceWifiStatus(blueteethBindController.currentDevice!, 1, + link: true); + } + + int _retryCount = 0; + final int _maxRetry = 3; + Future _autoReconnect() async { + if (blueteethBindController.currentDevice == null) return; + + while (_retryCount < _maxRetry) { + try { + print("[蓝牙重连] 第${_retryCount + 1}次尝试连接..."); + await blueteethBindController.currentDevice!.connect(); + + // 检查是否连接成功 + var isConnected = + await blueteethBindController.currentDevice!.isConnected; + if (isConnected) { + print("[蓝牙重连] 连接成功 ✅"); + _retryCount = 0; // 重置重试次数 + return; + } else { + throw Exception("连接失败"); + } + } catch (e) { + _retryCount++; + print("[蓝牙重连] 第$_retryCount次连接失败:$e"); + + if (_retryCount >= _maxRetry) { + print("[蓝牙重连] 已达到最大重试次数($_maxRetry),停止重连 ❌"); + break; + } + + // 等待 2 秒后重试 + await Future.delayed(Duration(seconds: 2)); + } } } } diff --git a/lib/pages/mh_page/device/mht_wifi_page_after.dart b/lib/pages/mh_page/device/mht_wifi_page_after.dart index c6a32c2..07200f7 100644 --- a/lib/pages/mh_page/device/mht_wifi_page_after.dart +++ b/lib/pages/mh_page/device/mht_wifi_page_after.dart @@ -44,6 +44,9 @@ class _MHTWifiAfterPageState extends State { StreamSubscription>? _scanSubscription; bool _isDisposed = false; ScanResult? targetDevice; + bool dealing = false; //是否正在刷新 + DateTime _lastTapTime = DateTime.now(); + bool haveSuccess = false; @override void initState() { @@ -55,6 +58,7 @@ class _MHTWifiAfterPageState extends State { } void _initController() { + dealing = false; blueteethBindController.netType.value = 0; blueteethBindController.connectStatus.value = 0; blueteethBindController.wifiList = [].obs; @@ -71,11 +75,11 @@ class _MHTWifiAfterPageState extends State { void dispose() { _isDisposed = true; _cleanupResources(); - _disconnectDevice(); + // _disconnectDevice(); super.dispose(); } - void _cleanupResources() { + Future _cleanupResources() async { // 取消监听器 lisObj?.cancel(); lisObj = null; @@ -88,12 +92,7 @@ class _MHTWifiAfterPageState extends State { _scanSubscription?.cancel(); _scanSubscription = null; - // 断开蓝牙连接 - if (blueteethBindController.currentDevice != null) { - blueteethBindController.currentDevice!.disconnect(); - blueteethBindController.currentDevice = null; - } - + await _disconnectDevice(); // 停止扫描 FlutterBluePlus.stopScan(); } @@ -183,7 +182,7 @@ class _MHTWifiAfterPageState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - themeController.currentColor.sc1, + Colors.white, ), ), ); @@ -196,7 +195,7 @@ class _MHTWifiAfterPageState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - themeController.currentColor.sc1, + Colors.white, ), ), ); @@ -526,12 +525,13 @@ class _MHTWifiAfterPageState extends State { wifiItem['ssid'] ?? '未命名'.tr, onConfirm: () async { - blueteethBindController - .currentDevice! - .logingStream - .listen((event) { - ef.log("[命令日志]:$event"); - }); + // blueteethBindController + // .currentDevice! + // .logingStream + // .listen((event) { + // ef.log("[命令日志]:$event"); + // }); + haveSuccess = false; blueteethBindController .selectWifi .value = wifiItem; @@ -541,11 +541,53 @@ class _MHTWifiAfterPageState extends State { .model.wifiPass!, blueteethBindController .currentDevice!); + //todo 查询内存,如果关键内存小于20000k,重启设备 + bool memoryFlag = + await queryMemory( + blueteethBindController + .currentDevice!); + if (!memoryFlag) { + await rebootDevice( + blueteethBindController + .currentDevice!); + await dealWifi( + widget.deviceInfo + .value[ + 'bind_mac_a'], + needSuccess: true); + // return; + } + if (!flag) { + blueteethBindController + .selectWifi + .value = {}; + // TopSlideNotification.show( + // context, + // textColor: + // themeController + // .currentColor + // .sc9, + // text: + // '蓝牙已断开,请点击下方刷新按钮重试' + // .tr); + return; + } if (flag) { var aa = await getDeviceWifiStatus( blueteethBindController .currentDevice!, - 1,link: true); + 1, + link: true); + aa = await restoreWifi( + blueteethBindController + .currentDevice!, + aa); + if (!memoryFlag) { + aa = await rebootDeviceCurrent( + blueteethBindController + .currentDevice!, + aa); + } blueteethBindController .selectWifi .value = {}; @@ -558,6 +600,10 @@ class _MHTWifiAfterPageState extends State { blueteethBindController .connect_wifi .value = {}; + blueteethBindController + .wifiStatus + .value == + 0; } blueteethBindController .wifiStatus @@ -572,19 +618,28 @@ class _MHTWifiAfterPageState extends State { blueteethBindController .currentDeviceMac! .value); - TopSlideNotification - .show( - context, - text: "配网成功".tr, - textColor: - themeController - .currentColor - .sc2, - ); + if (!haveSuccess) { + TopSlideNotification + .show( + context, + text: "配网成功".tr, + textColor: + themeController + .currentColor + .sc2, + ); + } } else { + //读取不到wifi信息 blueteethBindController .connect_wifi .value = {}; + blueteethBindController + .selectWifi + .value = {}; + blueteethBindController + .wifiStatus + .value = 0; TopSlideNotification .show( context, @@ -599,6 +654,11 @@ class _MHTWifiAfterPageState extends State { blueteethBindController .connect_wifi .value = {}; + blueteethBindController + .selectWifi + .value = {}; + blueteethBindController + .wifiStatus.value = 0; TopSlideNotification.show( context, text: "配网失败".tr, @@ -639,9 +699,7 @@ class _MHTWifiAfterPageState extends State { valueColor: AlwaysStoppedAnimation< Color>( - themeController - .currentColor - .sc1, + Colors.white, ), ), ) @@ -662,6 +720,20 @@ class _MHTWifiAfterPageState extends State { horizontal: 20.rpx, vertical: 10.rpx), borderRadius: 20.rpx, onTap: () async { + // if (dealing) { + // return; + // } + if (DateTime.now() + .difference(_lastTapTime) < + Duration(seconds: 2)) { + return; // 防止快速重复点击 + } + _lastTapTime = DateTime.now(); + blueteethBindController.netType.value = 0; + blueteethBindController + .blueConnectFlag.value = 0; + blueteethBindController.wifiList.value = + []; var bluetoothState = await FlutterBluePlus.isOn; blueteethBindController.bluetoothStatus @@ -678,10 +750,17 @@ class _MHTWifiAfterPageState extends State { 1) { blueteethBindController .blueConnectFlag.value = 0; - dealWifi(widget.deviceInfo.macA) - .then((aa) { - print("object"); - }); + try { + await dealWifi( + widget + .deviceInfo['bind_mac_a'], + needTip: false) + .then((aa) { + print("object"); + }); + } catch (e) { + ef.log("$e"); + } return; } @@ -730,6 +809,7 @@ class _MHTWifiAfterPageState extends State { .currentColor.sc9, ); }); + await initWifiStatusAndWifiList(); } else { blueteethBindController.netType.value = 1; @@ -782,35 +862,54 @@ class _MHTWifiAfterPageState extends State { ); } - Future initWifiStatusAndWifiList() async { + Future initWifiStatusAndWifiList( + {int retryCount = 0, bool needSuccess = false}) async { if (_isDisposed) return; + // 取消之前的监听器 if (lisObj != null) { lisObj!.cancel(); + lisObj = null; } bool wifiStatus = false; - var aa = - await getDeviceWifiStatus(blueteethBindController.currentDevice!, 0); - if (aa != null && aa is Map) { - updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); - wifiStatus = true; - blueteethBindController.connect_wifi.value = aa; - } else { - wifiStatus = false; + try { + // 获取WiFi状态 + var aa = + await getDeviceWifiStatus(blueteethBindController.currentDevice!, 0); + if (aa != null && aa is Map) { + updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); + wifiStatus = true; + blueteethBindController.connect_wifi.value = aa; + if (needSuccess) { + haveSuccess = true; + TopSlideNotification.show( + context, + text: "配网成功".tr, + textColor: themeController.currentColor.sc2, + ); + } + } else { + wifiStatus = false; + } + blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0; + } catch (e) { + print("获取WiFi状态异常: $e"); + blueteethBindController.wifiStatus.value = 0; } - blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0; List wifiList = []; try { + // 获取WiFi列表 final result = await getWifiList(blueteethBindController.currentDevice!); blueteethBindController.wifiConnectStatus.value = 1; blueteethBindController.updateAll(); + if (result is List) { wifiList = result; } } catch (e) { - print("异常: $e"); + print("获取WiFi列表异常: $e"); blueteethBindController.wifiConnectStatus.value = 0; blueteethBindController.updateAll(); } @@ -818,32 +917,87 @@ class _MHTWifiAfterPageState extends State { if (_isDisposed) return; if (wifiList.isNotEmpty) { + // 成功获取WiFi列表 blueteethBindController.connectStatus.value = 1; blueteethBindController.updateAll(); - TopSlideNotification.show( - context, - text: "获取wifi列表成功".tr, - textColor: themeController.currentColor.sc2, - ); + // TopSlideNotification.show( + // context, + // text: "获取wifi列表成功".tr, + // textColor: themeController.currentColor.sc2, + // ); blueteethBindController.wifiList.value = wifiList; blueteethBindController.updateAll(); } else { + // 获取WiFi列表失败,尝试重新扫描 + if (retryCount < 2) { + // 最多重试2次 + print("第${retryCount + 1}次获取WiFi列表失败,尝试重新扫描..."); + + // TopSlideNotification.show( + // context, + // text: "正在重新扫描WiFi...".tr, + // textColor: themeController.currentColor.sc2, + // ); + + try { + // 发送关闭并重新打开WiFi扫描命令 + await sendCloseAndOpenWscanCommand( + blueteethBindController.currentDevice!); + + // 等待一段时间让设备重新扫描 + await Future.delayed(Duration(seconds: 3)); + + // 递归调用自身进行重试 + await initWifiStatusAndWifiList(retryCount: retryCount + 1); + return; // 重试后直接返回,避免执行后面的代码 + } catch (e) { + print("重新扫描WiFi失败: $e"); + // 继续执行下面的失败处理 + } + } + + // 重试次数用尽或重试失败,显示最终失败提示 TopSlideNotification.show( context, text: "获取wifi列表失败".tr, textColor: themeController.currentColor.sc9, ); + + // 可选:重置WiFi连接状态 + blueteethBindController.connectStatus.value = 0; + blueteethBindController.updateAll(); } - lisObj = blueteethBindController.currentDevice!.statusStream - .listen((onData) async { - if (onData.status == BleEventType.recvLineLog) { - final line = onData.val; - print("[bleee]:" + line); - edm.EasyDartModule.logger.info("[bleee]:" + line); - DailyLogUtils.writeLog("[bleee]:" + line); - } - }); + // 设置日志监听器 + if (!_isDisposed && blueteethBindController.currentDevice != null) { + lisObj = blueteethBindController.currentDevice!.statusStream + .listen((onData) async { + if (_isDisposed) return; + + if (onData.status == BleEventType.recvLineLog) { + final line = onData.val; + print("[bleee]: $line"); + edm.EasyDartModule.logger.info("[bleee]: $line"); + DailyLogUtils.writeLog("[bleee]: $line"); + } + // 添加连接状态监听 + if (onData.status == BleEventType.disconnected) { + print("蓝牙连接已断开"); + blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.updateAll(); + + // 显示断开提示 + // if (!_isDisposed) { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接已断开,请重新连接".tr, + // textColor: themeController.currentColor.sc9, + // ); + // } + _autoReconnect(); + } + }); + } } Widget getWifiIconByRsso(wifiItem) { @@ -894,16 +1048,20 @@ class _MHTWifiAfterPageState extends State { } } - Future dealWifi(String mac) async { - if (_isDisposed) return; - - final blueteethBindController = Get.find(); - final themeController = Get.find(); - - // 清理之前的资源 - _cleanupResources(); - + Future dealWifi(String mac, + {bool needTip = true, bool needSuccess = false}) async { + if (dealing) { + return; + } try { + dealing = true; + if (_isDisposed) return; + + final blueteethBindController = Get.find(); + final themeController = Get.find(); + + // 清理之前的资源 + await _cleanupResources(); // 检查蓝牙状态 var bluetoothState = await FlutterBluePlus.isOn; blueteethBindController.bluetoothStatus.value = bluetoothState; @@ -922,13 +1080,14 @@ class _MHTWifiAfterPageState extends State { _timeoutTimer = Timer(Duration(seconds: 20), () { if (!isConnected && !_isDisposed) { blueteethBindController.blueConnectFlag.value = 1; - blueteethBindController.updateAll(); + blueteethBindController.netType.value = 3; TopSlideNotification.show( context, - text: "设备连接超时,请重试".tr, + text: "设备连接超时,请点击刷新重试".tr, textColor: themeController.currentColor.sc9, ); FlutterBluePlus.stopScan(); + blueteethBindController.updateAll(); } }); @@ -954,33 +1113,76 @@ class _MHTWifiAfterPageState extends State { _timeoutTimer?.cancel(); _scanSubscription?.cancel(); + var streamlog; try { THapp bledevice = THapp(device: targetDevice!.device); - await bledevice.device.connect(); - var res2 = bledevice.isConnected; + blueteethBindController.currentDevice = bledevice; + streamlog = blueteethBindController.currentDevice!.logingStream + .listen((log) { + ef.log("[传感器设备日志]: $log"); + edm.EasyDartModule.logger.info("[传感器设备日志]: $log"); + }); + bledevice.autoConnect = true; - if (res2 && !_isDisposed) { + const int maxRetry = 3; + int retryCount = 0; + bool connected = false; + + while (retryCount < maxRetry && !_isDisposed) { + try { + await bledevice.device.connect(); + connected = bledevice.isConnected; + if (connected) break; + } catch (e) { + retryCount++; + print("[蓝牙连接错误] 第${retryCount}次重试: $e"); + edm.EasyDartModule.logger + .info("[蓝牙连接错误] 第${retryCount}次重试: $e"); + DailyLogUtils.writeLog("[蓝牙连接错误] 第${retryCount}次重试: $e"); + + // 延迟重试 + await Future.delayed(const Duration(seconds: 2)); + } + } + + if (connected && !_isDisposed) { blueteethBindController.blueConnectFlag.value = 2; - TopSlideNotification.show( - context, - text: "连接成功".tr, - textColor: themeController.currentColor.sc2, - ); - blueteethBindController.currentDevice = bledevice; - lisObj = blueteethBindController.currentDevice!.statusStream - .listen((onData) async { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接成功".tr, + // textColor: themeController.currentColor.sc2, + // ); + + lisObj = bledevice.statusStream.listen((onData) async { if (_isDisposed) return; if (onData.status == BleEventType.recvLineLog) { final line = onData.val; - print("[bleee]:" + line); - edm.EasyDartModule.logger.info("[bleee]:" + line); - DailyLogUtils.writeLog("[bleee]:" + line); + print("[bleee]: $line"); + edm.EasyDartModule.logger.info("[bleee]: $line"); + DailyLogUtils.writeLog("[bleee]: $line"); } + + // 添加连接状态监听 + if (onData.status == BleEventType.disconnected) { + print("蓝牙连接已断开"); + blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.updateAll(); + + // 显示断开提示 + // if (!_isDisposed) { + // TopSlideNotification.show( + // context, + // text: "蓝牙连接已断开,请重新连接".tr, + // textColor: themeController.currentColor.sc9, + // ); + // } + _autoReconnect(); + } + if (onData.status == BleEventType.ready) { - var aa = await getDeviceNetVersion( - blueteethBindController.currentDevice!, 0); + var aa = await getDeviceNetVersion(bledevice, 0); if (aa == "4g") { blueteethBindController.netType.value = 2; blueteethBindController.updateAll(); @@ -1007,27 +1209,30 @@ class _MHTWifiAfterPageState extends State { blueteethBindController.updateAll(); blueteethBindController.wifiConnectStatus.value = 0; blueteethBindController.updateAll(); - await initWifiStatusAndWifiList(); + await initWifiStatusAndWifiList(needSuccess: needSuccess); } + dealing = false; } }); } else { TopSlideNotification.show( context, - text: "蓝牙绑定.连接失败".tr, + text: "设备连接失败,请点击刷新重试".tr, textColor: themeController.currentColor.sc9, ); } } catch (e) { + blueteethBindController.blueConnectFlag.value = 1; TopSlideNotification.show( context, - text: "设备连接失败".tr, + text: "设备连接失败,请点击刷新重试".tr, textColor: themeController.currentColor.sc9, ); + } finally { + streamlog.close(); } } }); - await Future.delayed(Duration(seconds: 20)); } catch (e) { if (!_isDisposed) { @@ -1036,10 +1241,12 @@ class _MHTWifiAfterPageState extends State { text: "扫描过程中发生错误".tr, textColor: themeController.currentColor.sc9, ); + dealing = false; } } finally { _timeoutTimer?.cancel(); await FlutterBluePlus.stopScan(); + dealing = false; } } @@ -1105,12 +1312,74 @@ class _MHTWifiAfterPageState extends State { Future _disconnectDevice() async { try { - // THapp bledevice = THapp(device: widget.deviceInfo.scanResult.device); - THapp bledevice = THapp(device: targetDevice!.device); - await bledevice.disconnect(); + if (blueteethBindController.currentDevice != null) { + await blueteethBindController.currentDevice!.disconnect(); + // blueteethBindController.currentDevice = null; + } DailyLogUtils.writeLog("关闭蓝牙连接成功".tr); } catch (e) { DailyLogUtils.writeError("关闭蓝牙连接失败: $e"); + } finally { + // dealing = false; + } + } + + Future restoreWifi(THapp tHapp, aa) async { + if (aa != null && aa is Map) { + return aa; + } + await sendCloseAndOpenWscanCommand(tHapp); + return await getDeviceWifiStatus(blueteethBindController.currentDevice!, 4, + link: true); + } + + Future rebootDeviceCurrent(THapp tHapp, aa) async { + if (aa != null && aa is Map) { + return aa; + } + blueteethBindController.connect_wifi.value = {}; + await rebootDevice( + blueteethBindController.currentDevice!, + ); + await dealWifi( + widget.deviceInfo['bind_mac_a'], + ); + return await getDeviceWifiStatus(blueteethBindController.currentDevice!, 1, + link: true); + } + + int _retryCount = 0; + final int _maxRetry = 3; + Future _autoReconnect() async { + if (blueteethBindController.currentDevice == null) return; + + while (_retryCount < _maxRetry) { + try { + print("[蓝牙重连] 第${_retryCount + 1}次尝试连接..."); + await blueteethBindController.currentDevice!.connect(); + + // 检查是否连接成功 + var isConnected = + await blueteethBindController.currentDevice!.isConnected; + if (isConnected) { + print("[蓝牙重连] 连接成功 ✅"); + _retryCount = 0; // 重置重试次数 + return; + } else { + throw Exception("连接失败"); + } + } catch (e) { + _retryCount++; + print("[蓝牙重连] 第$_retryCount次连接失败:$e"); + + if (_retryCount >= _maxRetry) { + print("[蓝牙重连] 已达到最大重试次数($_maxRetry),停止重连 ❌"); + break; + } + + // 等待 2 秒后重试 + await Future.delayed(Duration(seconds: 2)); + } } } } diff --git a/lib/pages/mh_page/new_settingPage.dart b/lib/pages/mh_page/new_settingPage.dart index 3ff855f..c4ea039 100644 --- a/lib/pages/mh_page/new_settingPage.dart +++ b/lib/pages/mh_page/new_settingPage.dart @@ -253,7 +253,7 @@ class _SettingPageState extends State { ), ].divide(SizedBox(width: 22.rpx)), ), - Text('SWES2025.9.8', + Text('SWES2025.10.28', style: TextStyle( color: Colors.white, fontSize: 26.rpx, diff --git a/lib/routers/mh_routers.dart b/lib/routers/mh_routers.dart index ede8986..bc5ae58 100644 --- a/lib/routers/mh_routers.dart +++ b/lib/routers/mh_routers.dart @@ -106,7 +106,7 @@ var mhroutes = { "/mHTBlueteethDevicePage": (context, {arguments}) => MHTBlueteethDevicePage(deviceType: arguments), "/mHTwifiPage": (contxt, {arguments}) => MHTWifiPage(deviceInfo: arguments), - "/calibrationPage": (contxt) => MHTCalibrationPage(), + "/calibrationPage": (contxt,{arguments}) => MHTCalibrationPage(deviceInfo: arguments), "/mhtCalibrationAfterPage": (contxt, {arguments}) => MHTCalibrationAfterPage(deviceInfo: arguments), "/bindDeviceSuccess": (contxt) => MHTBindDeviceSuccess(),