You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
8.9 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:path/path.dart';
import 'dart:async';
import '../../../data/services/network/api.dart';
import '../model/ota_upgrade_model.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:jl_ota/jl_ota.dart';
import '../../../data/services/ble_manager.dart';
class OtaUpgradeController extends GetxController {
final RxString errorMessage = ''.obs;
final RxBool isFetchingDeviceInfo = false.obs;
final Dio _dio = Dio();
final RxString latestVersion = ''.obs;
final RxString currentVersion = ''.obs;
String updatepackageaddress = '';
final RxDouble downloadProgress = 0.0.obs;
final RxBool isUpdating = false.obs;
final isUpdateAvailable = true.obs;
final RxDouble progress = 0.0.obs;
// 蓝牙服务
final _bleManager = Get.find<BleManager>();
@override
void onInit() {
super.onInit();
_getCurrentVersion();
}
// 添加重试方法
void retryConnection() {
errorMessage.value = '';
_getCurrentVersion();
}
// 添加更新方法
Future<void> startUpdate() async {
try {
isUpdating.value = true;
checkUpdate();
// 实现更新逻辑...
} catch (e) {
errorMessage.value = e.toString();
Get.snackbar('更新失败', e.toString());
} finally {
isUpdating.value = false;
}
}
Future<void> _getCurrentVersion() async {
JlOta().getPlatformVersion();
//try {
// // 添加获取设备信息的重试机制
// DeviceInfo? deviceInfo = _bleManager.deviceInfo.value;
// // 第一次检查设备信息
// if (deviceInfo == null) {
// // 显示加载提示
// isFetchingDeviceInfo.value = true;
// // 尝试重新获取设备信息
// await _bleManager.fetchDeviceInfo();
// // 等待后再次获取设备信息
// deviceInfo = _bleManager.deviceInfo.value;
// isFetchingDeviceInfo.value = false;
// // 仍然为空则抛出异常
// if (deviceInfo == null) {
// throw const FormatException('无法获取设备信息,请检查设备连接');
// }
// }
// // 检查固件信息有效性
// if (deviceInfo.firmwareVersion.isEmpty
// // ||
// // deviceInfo.firmwareProductId.isEmpty
// ) {
// throw const FormatException('设备固件信息不完整');
// }
// // 正常流程
// currentVersion.value = "0"; //deviceInfo.firmwareVersion;
// // API请求
// final response = await Api.getequipmentinfo({
// "id": "s3",
// });
// // 处理API响应
// if (response['info'] == null) {
// throw const FormatException('API 响应格式错误');
// }
// final resp = OtaConfigResp.fromJson(response);
// latestVersion.value = resp.systemversion!;
// updatepackageaddress = resp.updatepackageaddress!;
// // 版本检查
// isUpdateAvailable.value = _isNewVersionAvailable(resp.systemversion!);
// } catch (e) {
// // 统一错误处理
// errorMessage.value = e.toString();
// Get.snackbar('错误', e.toString(),
// snackPosition: SnackPosition.BOTTOM,
// backgroundColor: Colors.red,
// colorText: Colors.white);
// // 重要:重新抛出异常以便上层处理(可选)
// } finally {
// isFetchingDeviceInfo.value = false;
// }
}
// 版本比较方法优化
bool _isNewVersionAvailable(String latest) {
try {
List<int> currentParts = currentVersion.value
.split('.')
.map((e) => int.parse(e.trim()))
.toList();
List<int> latestParts =
latest.split('.').map((e) => int.parse(e.trim())).toList();
for (int i = 0; i < latestParts.length; i++) {
int current = (i < currentParts.length) ? currentParts[i] : 0;
if (latestParts[i] > current) return true;
if (latestParts[i] < current) return false;
}
return false;
} catch (e) {
print('版本比较错误: $e');
return false;
}
}
// 版本更新
Future<void> checkUpdate() async {
try {
if (latestVersion.value != "")
_showUpdateDialog(latestVersion.value);
else {
Get.snackbar('错误', '获取最新版本信息失败');
}
} catch (e) {
Get.snackbar('错误', '获取版本信息失败');
}
}
// 显示更新对话框
void _showUpdateDialog(String latest) {
Get.dialog(
AlertDialog(
title: Text('发现新版本 $latest'),
content: Text('是否立即更新?'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('取消'),
),
TextButton(
onPressed: () {
Get.back();
startDownload();
},
child: Text('更新'),
),
],
),
);
}
// 修改后的startDownload方法
Future<void> startDownload() async {
isUpdating.value = true;
int lastIndex = updatepackageaddress.lastIndexOf('/');
String fileName = updatepackageaddress.substring(lastIndex + 1);
String directoryName = "ota_upgrades";
final dio = Dio(BaseOptions(
connectTimeout: const Duration(seconds: 5),
receiveTimeout: Duration.zero,
sendTimeout: const Duration(seconds: 5),
headers: {'Accept-Encoding': 'gzip'},
));
Get.snackbar('升级命令已发送', '开始下载...');
try {
final Directory? downloadsDir = await getDownloadsDirectory();
if (downloadsDir == null) {
throw FileSystemException('无法访问下载目录');
}
final targetDir = Directory('${downloadsDir.path}/$directoryName');
if (!await targetDir.exists()) {
await targetDir.create(recursive: true);
}
final savePath = '${targetDir.path}/$fileName';
// 新增:检查同名文件逻辑
bool existingSameFile = false;
try {
var files = await targetDir.list().toList();
for (var entity in files) {
if (await FileSystemEntity.isFile(entity.path)) {
String name = basename(entity.path); // 使用path包中的basename
if (name == fileName) {
existingSameFile = true;
break;
}
}
}
} catch (e) {
Get.snackbar('错误', '检查本地文件失败: $e');
isUpdating.value = false;
return;
}
if (existingSameFile) {
Get.snackbar('文件已存在', '跳过下载,直接更新');
isUpdating.value = false;
_installApp(savePath);
return;
}
// 新增:删除其他文件逻辑
try {
var files = await targetDir.list().toList();
for (var entity in files) {
if (await FileSystemEntity.isFile(entity.path)) {
await entity.delete();
}
}
} catch (e) {
Get.snackbar('错误', '删除旧文件失败: $e');
isUpdating.value = false;
return;
}
print('文件保存路径: $savePath');
final options = Options(
receiveTimeout: Duration.zero,
followRedirects: true,
maxRedirects: 5,
);
DateTime lastUpdate = DateTime.now();
await dio.download(
updatepackageaddress,
savePath,
options: options,
onReceiveProgress: (received, total) {
final now = DateTime.now();
if (now.difference(lastUpdate).inMilliseconds > 1000) {
lastUpdate = now;
String progressMsg = total != -1
? '${(received / total * 100).toStringAsFixed(1)}%'
: '已下载:${(received / 1024 / 1024).toStringAsFixed(1)}MB';
Get.snackbar(
'升级进度',
progressMsg,
duration: const Duration(seconds: 1),
);
}
},
);
File file = File(savePath);
if (await file.exists()) {
Get.snackbar('下载完成', '文件已保存至: $savePath');
} else {
Get.snackbar('错误', '文件未找到,请检查写入权限');
}
isUpdating.value = false;
_installApp(savePath);
} on DioException catch (e) {
Get.snackbar('下载失败', '错误: ${e.message}');
isUpdating.value = false;
} on FileSystemException catch (e) {
Get.snackbar('存储失败', '无法写入文件: ${e.message}');
isUpdating.value = false;
} catch (e) {
Get.snackbar('未知错误', e.toString());
isUpdating.value = false;
}
}
// 开始升级
void _installApp(String path) async {
// JlOtaPlugin()
// final File file = File(path);
// if (await file.exists()) {
// // OpenResult result = await OpenFile.open(path);
// // if (result.type != ResultType.done) {
// // Get.snackbar('错误', '安装失败: ${result.message}');
// // }
// }
}
}