|
|
|
@ -1,4 +1,6 @@ |
|
|
|
import 'package:classic_bluetooth/classic_bluetooth.dart'; |
|
|
|
import '/routes/app_routes.dart'; |
|
|
|
import 'package:logger/web.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:path/path.dart'; |
|
|
|
@ -121,7 +123,17 @@ class OtaUpgradeController extends GetxController { |
|
|
|
// 实现更新逻辑... |
|
|
|
} catch (e) { |
|
|
|
errorMessage.value = e.toString(); |
|
|
|
Get.snackbar('更新失败', e.toString()); |
|
|
|
Get.snackbar( |
|
|
|
'更新失败', |
|
|
|
e.toString(), |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: const Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -166,7 +178,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
// 从第三个 `.` 开始分割 |
|
|
|
final firstPart = firmwareParts.sublist(0, 3).join('.'); |
|
|
|
final secondPart = firmwareParts.sublist(3).join('.'); |
|
|
|
print("firstPart${firstPart},secondPart=${secondPart}"); |
|
|
|
Logger().d("firstPart${firstPart},secondPart=${secondPart}"); |
|
|
|
// 判断两部分是否一致 |
|
|
|
if (firstPart != secondPart) { |
|
|
|
throw "固件版本格式错误:${deviceInfo.firmwareVersion}"; |
|
|
|
@ -174,7 +186,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
|
|
|
|
// 正常流程 |
|
|
|
currentVersion.value = firstPart; |
|
|
|
print('getequipmentinfo,id: ${deviceInfo.firmwareProductId}'); |
|
|
|
Logger().d('getequipmentinfo,id: ${deviceInfo.firmwareProductId}'); |
|
|
|
|
|
|
|
final connectedDevices = await ClassicBluetooth.getConnectedDevices(); |
|
|
|
if (connectedDevices.isNotEmpty) { |
|
|
|
@ -192,7 +204,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
} |
|
|
|
|
|
|
|
final resp = OtaConfigResp.fromJson(response); |
|
|
|
print('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); |
|
|
|
Logger().d('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); |
|
|
|
latestVersion.value = resp.systemversion!; |
|
|
|
updatedescription.value = resp.updatedescription!; |
|
|
|
updatepackageaddress = resp.updatepackageaddress!; |
|
|
|
@ -210,10 +222,17 @@ class OtaUpgradeController extends GetxController { |
|
|
|
} catch (e) { |
|
|
|
// 统一错误处理 |
|
|
|
errorMessage.value = e.toString(); |
|
|
|
Get.snackbar('错误', e.toString(), |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red, |
|
|
|
colorText: Colors.white); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
e.toString(), |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: const Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
// 重要:重新抛出异常以便上层处理(可选) |
|
|
|
} finally { |
|
|
|
isFetchingDeviceInfo.value = false; |
|
|
|
@ -237,7 +256,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
} |
|
|
|
return false; |
|
|
|
} catch (e) { |
|
|
|
print('版本比较错误: $e'); |
|
|
|
Logger().d('版本比较错误: $e'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -248,15 +267,35 @@ class OtaUpgradeController extends GetxController { |
|
|
|
if (latestVersion.value != "") { |
|
|
|
_showUpdateDialog(latestVersion.value); |
|
|
|
} else { |
|
|
|
Get.snackbar('错误', '获取最新版本信息失败'); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
'获取最新版本信息失败', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[800], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: const Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
Get.snackbar('错误', '获取版本信息失败'); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
'获取版本信息失败', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[800], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: const Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void _showUpdateDialog(String latest) async { |
|
|
|
print('显示更新对话框'); |
|
|
|
Logger().d('显示更新对话框'); |
|
|
|
Get.dialog( |
|
|
|
AlertDialog( |
|
|
|
title: Text('发现新版本 $latest'), |
|
|
|
@ -264,7 +303,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
actions: [ |
|
|
|
TextButton( |
|
|
|
onPressed: () async { |
|
|
|
print('取消按钮被点击'); |
|
|
|
Logger().d('取消按钮被点击'); |
|
|
|
|
|
|
|
Get.back(); |
|
|
|
Future.delayed(Duration(milliseconds: 300)); |
|
|
|
@ -273,7 +312,7 @@ class OtaUpgradeController extends GetxController { |
|
|
|
), |
|
|
|
TextButton( |
|
|
|
onPressed: () async { |
|
|
|
print('更新按钮被点击'); |
|
|
|
Logger().d('更新按钮被点击'); |
|
|
|
|
|
|
|
Get.back(); |
|
|
|
Future.delayed(Duration(milliseconds: 300)); |
|
|
|
@ -341,7 +380,17 @@ class OtaUpgradeController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
Get.snackbar('错误', '检查本地文件失败: $e'); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
'检查本地文件失败: $e', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
@ -363,12 +412,22 @@ class OtaUpgradeController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
Get.snackbar('错误', '删除旧文件失败: $e'); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
'删除旧文件失败: $e', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
//isUpgrade.value = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
print('文件保存路径: $savePath'); |
|
|
|
Logger().d('文件保存路径: $savePath'); |
|
|
|
|
|
|
|
detailedStatus.value = '开始下载固件包...'; |
|
|
|
final options = Options( |
|
|
|
@ -394,7 +453,17 @@ class OtaUpgradeController extends GetxController { |
|
|
|
// Get.snackbar('下载完成', '文件已保存至: $savePath'); |
|
|
|
detailedStatus.value = '下载完成,准备升级...'; |
|
|
|
} else { |
|
|
|
Get.snackbar('错误', '文件未找到,请检查写入权限'); |
|
|
|
Get.snackbar( |
|
|
|
'错误', |
|
|
|
'文件未找到,请检查写入权限', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
detailedStatus.value = '下载失败'; |
|
|
|
showDetailedStatus.value = false; |
|
|
|
return; |
|
|
|
@ -403,15 +472,45 @@ class OtaUpgradeController extends GetxController { |
|
|
|
startUpgrading(savePath); |
|
|
|
return; |
|
|
|
} on DioException catch (e) { |
|
|
|
Get.snackbar('下载失败', '错误: ${e.message}'); |
|
|
|
Get.snackbar( |
|
|
|
'下载失败', |
|
|
|
'错误: ${e.message}', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} on FileSystemException catch (e) { |
|
|
|
Get.snackbar('存储失败', '无法写入文件: ${e.message}'); |
|
|
|
Get.snackbar( |
|
|
|
'存储失败', |
|
|
|
'无法写入文件: ${e.message}', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} catch (e) { |
|
|
|
isDownloading.value = false; |
|
|
|
detailedStatus.value = '下载失败,请检查网络连接'; |
|
|
|
showDetailedStatus.value = false; |
|
|
|
Get.snackbar('下载失败', '请检查网络连接: $e'); |
|
|
|
print('下载失败: $e'); |
|
|
|
Get.snackbar( |
|
|
|
'下载失败', |
|
|
|
'请检查网络连接: $e', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
Logger().d('下载失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -442,8 +541,12 @@ class OtaUpgradeController extends GetxController { |
|
|
|
'电量检查失败', |
|
|
|
'无法获取设备信息,请检查设备连接', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.orange, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.warning_amber, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
return false; |
|
|
|
} |
|
|
|
@ -460,14 +563,36 @@ class OtaUpgradeController extends GetxController { |
|
|
|
|
|
|
|
Get.dialog( |
|
|
|
AlertDialog( |
|
|
|
title: Text('电量不足'), |
|
|
|
content: Text(message), |
|
|
|
title: Text( |
|
|
|
'电量不足', |
|
|
|
style: TextStyle( |
|
|
|
color: Colors.orange[700], |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
), |
|
|
|
), |
|
|
|
content: Text( |
|
|
|
message, |
|
|
|
style: TextStyle( |
|
|
|
color: Colors.orange[600], |
|
|
|
), |
|
|
|
), |
|
|
|
actions: [ |
|
|
|
TextButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
child: Text('确定'), |
|
|
|
style: TextButton.styleFrom( |
|
|
|
foregroundColor: Colors.orange[700], |
|
|
|
), |
|
|
|
child: const Text('确定'), |
|
|
|
), |
|
|
|
], |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
side: BorderSide( |
|
|
|
color: Colors.orange.withValues(alpha: 0.3), |
|
|
|
width: 1, |
|
|
|
), |
|
|
|
), |
|
|
|
backgroundColor: Colors.orange[50], |
|
|
|
), |
|
|
|
); |
|
|
|
return false; |
|
|
|
@ -479,8 +604,12 @@ class OtaUpgradeController extends GetxController { |
|
|
|
'电量检查失败', |
|
|
|
'检查设备电量时发生错误:$e', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red, |
|
|
|
backgroundColor: Colors.orange[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: const Icon( |
|
|
|
Icons.warning_amber, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
return false; |
|
|
|
} |
|
|
|
@ -507,15 +636,83 @@ class OtaUpgradeController extends GetxController { |
|
|
|
isUpgrade.value = false; |
|
|
|
detailedStatus.value = '升级成功完成'; |
|
|
|
showDetailedStatus.value = false; |
|
|
|
Get.snackbar('升级成功', '请退出重新连接设备'); |
|
|
|
_getCurrentVersion(); |
|
|
|
|
|
|
|
// 升级成功,更新版本信息显示 |
|
|
|
currentVersion.value = latestVersion.value; |
|
|
|
isUpdateAvailable.value = false; |
|
|
|
|
|
|
|
// 显示升级成功对话框,引导用户重新配对 |
|
|
|
Get.dialog( |
|
|
|
AlertDialog( |
|
|
|
title: Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
Icons.check_circle, |
|
|
|
color: Colors.green[600], |
|
|
|
size: 28, |
|
|
|
), |
|
|
|
SizedBox(width: 12), |
|
|
|
Text( |
|
|
|
'升级成功', |
|
|
|
style: TextStyle( |
|
|
|
color: Colors.green[700], |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
content: Text( |
|
|
|
'固件升级已完成!\n\n设备需要重新配对才能正常使用,现在跳转到配对页面吗?', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
height: 1.4, |
|
|
|
), |
|
|
|
), |
|
|
|
actions: [ |
|
|
|
TextButton( |
|
|
|
onPressed: () { |
|
|
|
Get.back(); // 关闭对话框 |
|
|
|
}, |
|
|
|
child: Text( |
|
|
|
'稍后配对', |
|
|
|
style: TextStyle(color: Colors.grey[600]), |
|
|
|
), |
|
|
|
), |
|
|
|
ElevatedButton( |
|
|
|
onPressed: () { |
|
|
|
Get.back(); // 关闭对话框 |
|
|
|
Get.toNamed(Routes.pairing); |
|
|
|
}, |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: Colors.green[600], |
|
|
|
foregroundColor: Colors.white, |
|
|
|
), |
|
|
|
child: Text('立即配对'), |
|
|
|
), |
|
|
|
], |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
), |
|
|
|
), |
|
|
|
barrierDismissible: false, // 防止用户意外关闭 |
|
|
|
); |
|
|
|
} |
|
|
|
if (event.event == 'onError') { |
|
|
|
type.value = UPGRADE_FAILED; |
|
|
|
isUpgrade.value = false; |
|
|
|
detailedStatus.value = '升级失败,错误码:${event.code}'; |
|
|
|
showDetailedStatus.value = false; |
|
|
|
Get.snackbar('升级失败', '请检查设备连接或升级包,错误码:${event.code}'); |
|
|
|
Get.snackbar( |
|
|
|
'升级失败', |
|
|
|
'请检查设备连接或升级包,错误码:${event.code}', |
|
|
|
snackPosition: SnackPosition.BOTTOM, |
|
|
|
backgroundColor: Colors.red[600], |
|
|
|
colorText: Colors.white, |
|
|
|
icon: Icon( |
|
|
|
Icons.error_outline, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
if (event.event == 'NOCONNECTION') { |
|
|
|
type.value = CONNECTION_DISCONNECTION; |
|
|
|
|