更新眠花糖兼容wifi配置
This commit is contained in:
@@ -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<void>();
|
||||
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<void> _startSingleUpgrade(UpgradeTask task) async {
|
||||
Future<void> _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<void> _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<void> _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<void> _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<dynamic> _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;
|
||||
|
||||
Reference in New Issue
Block a user