import 'package:classic_bluetooth/classic_bluetooth.dart'; 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:ota/ota.dart'; import '../../../data/services/ble_manager.dart'; class OtaUpgradeController extends GetxController { static const int NOT_STARTED = -1; // 未开始 static const int VALIDATION_FILE = 0; // 验证文件 static const int ONUPGRADE = 1; // 升级中 static const int START_UPGRADING = 2; // 开始升级 static const int UPGRADE_SUCCESS = 3; // 升级成功 static const int UPGRADE_FAILED = 4; // 升级失败 static const int CONNECTION_DISCONNECTION = 5; // 连接断开 static const int CONNECTION_SUCCESS = 6; // 连接成功 static const int DOWNLOADING_UP_FILES = 7; // 下载升级文件 // 错误信息,用于存储错误提示 final RxString errorMessage = ''.obs; // 最新版本号 final RxString latestVersion = ''.obs; // 最新更新内容 final RxString updatedescription = ''.obs; // 当前设备固件版本号 final RxString currentVersion = ''.obs; String _address = ''; // 更新包地址,用于下载更新文件 String updatepackageaddress = ''; // 下载进度,范围为 0.0 到 1.0 final RxDouble downloadProgress = 0.0.obs; // 是否有可用更新的状态 final isUpdateAvailable = true.obs; // 当前升级进度,范围为 0.0 到 1.0 // final RxDouble progress = 0.0.obs; // OTA 单例实例,用于处理升级相关逻辑 final jlota = Ota.instance; // 是否正在下载更新包的状态 final RxBool isDownloading = false.obs; // 蓝牙管理服务,用于获取设备信息和通信 final _bleManager = Get.find(); final maxRetryAttempts = 3; // 最大重试次数 int currentRetryCount = 0; final RxBool isFetchingDeviceInfo = true.obs; final RxDouble progress = 0.0.obs; // 控制器自己的可观察属性 final RxInt type = OtaEvent.NOT_STARTED.obs; final RxBool isUpgrade = false.obs; @override void onInit() { super.onInit(); _getCurrentVersion(); } @override void onClose() { jlota.onOtaClose(); _bleManager.setEnterOta(false); isUpgrade.value = false; super.onClose(); } // 添加重试方法 void retryConnection() { errorMessage.value = ''; _getCurrentVersion(); } String getStatusMessage(int type) { switch (type) { case NOT_STARTED: // -1 return "未开始".tr; case VALIDATION_FILE: // 0 return "验证文件中".tr; case ONUPGRADE: // 1 return "升级中".tr; case START_UPGRADING: // 2 return "开始升级".tr; case UPGRADE_SUCCESS: // 3 return "升级成功".tr; case UPGRADE_FAILED: // 4 return "升级失败".tr; case CONNECTION_DISCONNECTION: // 5 return "连接断开".tr; case CONNECTION_SUCCESS: // 6 return "连接成功".tr; case DOWNLOADING_UP_FILES: // 7 (新增) return "下载升级文件".tr; default: return "未知状态".tr; // 更安全的默认值 } } // 添加更新方法 Future startUpdate() async { try { checkUpdate(); // 实现更新逻辑... } catch (e) { errorMessage.value = e.toString(); Get.snackbar('更新失败', e.toString()); } } Future _getCurrentVersion() async { _listenToEvents(); try { isFetchingDeviceInfo.value = true; errorMessage.value = ''; // 添加获取设备信息的重试机制 DeviceInfo? deviceInfo = _bleManager.deviceInfo.value; // // 第一次检查设备信息 // if (deviceInfo == null) { // // 尝试重新获取设备信息 // await _bleManager.fetchDeviceInfo(); // } while (currentRetryCount < maxRetryAttempts) { deviceInfo = _bleManager.deviceInfo.value; // 检查信息有效性 if (deviceInfo != null && deviceInfo.firmwareVersion.isNotEmpty && deviceInfo.firmwareProductId.isNotEmpty) { break; } // 获取设备信息 await _bleManager.fetchDeviceInfo(); await Future.delayed(const Duration(seconds: 5)); currentRetryCount++; } // 最终验证 if (deviceInfo == null || deviceInfo.firmwareVersion.isEmpty || deviceInfo.firmwareProductId.isEmpty) { throw "获取设备信息失败,请检查连接"; } // 拆分 firmwareVersion 并判断两边是否一致 final firmwareParts = deviceInfo.firmwareVersion.split('.'); // 从第三个 `.` 开始分割 final firstPart = firmwareParts.sublist(0, 3).join('.'); final secondPart = firmwareParts.sublist(3).join('.'); print("firstPart${firstPart},secondPart=${secondPart}"); // 判断两部分是否一致 if (firstPart != secondPart) { throw "固件版本格式错误:${deviceInfo.firmwareVersion}"; } // 正常流程 currentVersion.value = firstPart; print('getequipmentinfo,id: ${deviceInfo.firmwareProductId}'); final connectedDevices = await ClassicBluetooth.getConnectedDevices(); if (connectedDevices.isNotEmpty) { _address = connectedDevices.first.address; } await _bleManager.setEnterOta(true); await Future.delayed(const Duration(seconds: 2)); jlota.init(); // API请求 final response = await Api.getequipmentinfo({ "id": deviceInfo.firmwareProductId, }); // 处理API响应 if (response['info'] == null) { throw const FormatException('API 响应格式错误'); } final resp = OtaConfigResp.fromJson(response); print('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); latestVersion.value = resp.systemversion!; updatedescription.value = resp.updatedescription!; 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) async { print('显示更新对话框'); Get.dialog( AlertDialog( title: Text('发现新版本 $latest'), content: Text('是否立即更新?'), actions: [ TextButton( onPressed: () async { print('取消按钮被点击'); Get.back(); Future.delayed(Duration(milliseconds: 300)); }, child: Text('取消'), ), TextButton( onPressed: () async { print('更新按钮被点击'); Get.back(); Future.delayed(Duration(milliseconds: 300)); startDownload(); }, child: Text('更新'), ), ], ), ); } // 修改后的startDownload方法 Future startDownload() async { isDownloading.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'}, )); type.value = DOWNLOADING_UP_FILES; try { final Directory? downloadsDir = await getApplicationSupportDirectory(); if (downloadsDir == null) { throw FileSystemException('无法访问下载目录'); } final targetDir = Directory('${downloadsDir.path}/Download/$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'); return; } if (existingSameFile) { //Get.snackbar('文件已存在', '跳过下载,直接更新'); startUpgrading(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'); //isUpgrade.value = false; return; } print('文件保存路径: $savePath'); final options = Options( receiveTimeout: Duration.zero, followRedirects: true, maxRedirects: 5, ); // 修改下载部分 await dio.download( updatepackageaddress, savePath, options: options, onReceiveProgress: (received, total) { if (total != -1) { downloadProgress.value = received / total; } }, ); File file = File(savePath); if (await file.exists()) { // Get.snackbar('下载完成', '文件已保存至: $savePath'); } else { Get.snackbar('错误', '文件未找到,请检查写入权限'); } isDownloading.value = false; startUpgrading(savePath); return; } on DioException catch (e) { Get.snackbar('下载失败', '错误: ${e.message}'); } on FileSystemException catch (e) { Get.snackbar('存储失败', '无法写入文件: ${e.message}'); } catch (e) { Get.snackbar('未知错误', e.toString()); } } // 开始升级 void startUpgrading(String path) async { jlota.startUpgrading(address: _address, filePath: path); return; // isUpgrade.value = false; } // 停止升级 void stopUpgrading() async { jlota.onOtaClose(); return; // isUpgrade.value = false; } void _listenToEvents() { Ota.instance.eventStream.listen((event) { if (event.event == 'onProgress' && event.type != null && event.progress != null) { progress.value = event.progress!; type.value = event.type!; isUpgrade.value = true; // 开始升级 } if (event.event == 'onStartOTA') { type.value = OtaEvent.START_UPGRADING; isUpgrade.value = true; // 开始升级 } if (event.event == 'onStopOTA') { type.value = OtaEvent.UPGRADE_SUCCESS; isUpgrade.value = false; Get.snackbar('升级成功', '请退出重新连接设备'); _getCurrentVersion(); } if (event.event == 'onError') { type.value = OtaEvent.UPGRADE_FAILED; isUpgrade.value = false; Get.snackbar('升级失败', '请检查设备连接或升级包,错误码:${event.code}'); } if (event.event == 'NOCONNECTION') { type.value = OtaEvent.CONNECTION_DISCONNECTION; isUpgrade.value = false; } if (event.event == 'CONNECTION_SUCCESS') { type.value = OtaEvent.CONNECTION_SUCCESS; isUpgrade.value = true; // 开始升级 } }); } }