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 '../../../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(); @override void onInit() { super.onInit(); _getCurrentVersion(); } // 添加重试方法 void retryConnection() { errorMessage.value = ''; _getCurrentVersion(); } // 添加更新方法 Future startUpdate() async { try { isUpdating.value = true; // 实现更新逻辑... } catch (e) { errorMessage.value = e.toString(); Get.snackbar('更新失败', e.toString()); } finally { isUpdating.value = false; } } Future _getCurrentVersion() async { 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 = deviceInfo.firmwareVersion; // API请求 final response = await Api.getequipmentinfo({ "id": "a2", }); // 处理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 currentParts = currentVersion.value .split('.') .map((e) => int.parse(e.trim())) .toList(); List 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 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 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 { // final File file = File(path); // if (await file.exists()) { // // OpenResult result = await OpenFile.open(path); // // if (result.type != ResultType.done) { // // Get.snackbar('错误', '安装失败: ${result.message}'); // // } // } } }