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.

363 lines
12 KiB

import 'dart:async';
import 'package:classic_bluetooth/classic_bluetooth.dart';
import 'package:device_jieli/device_jieli.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// import 'package:logger/web.dart';
import 'package:get_storage/get_storage.dart';
import '../../../data/services/ble_manager.dart';
import 'ota_core_contropller.dart';
import 'ota_download_contropller.dart';
import '../views/ota_upgrade_popup_view.dart';
import '../../../core/utils/logger.dart';
/// OTA升级主控制器 - 重构后的简化版本
/// 负责协调各个服务,管理升级流程的整体状态
class OtaUpgradeController extends GetxController {
// 服务依赖 - 使用新的合并后的服务
final _coreService = OtaCoreService();
final _downloadService = OtaDownloadService();
final _uiService = OtaUpgradePopUp();
final _bleManager = Get.find<BleManager>();
final _jlota = Jielihome.instance;
StreamSubscription<JieliEvent>? _otaEventSub;
// 状态管理
final RxString errorMessage = ''.obs;
final RxString latestVersion = ''.obs;
final RxString currentVersion = ''.obs;
final RxString detailedStatus = ''.obs;
final RxString updatedescription = ''.obs;
final RxDouble downloadProgress = 0.0.obs;
final RxDouble progress = 0.0.obs;
final RxInt type = OtaCoreService.NOT_STARTED.obs;
final RxBool isUpdateAvailable = false.obs;
final RxBool isDownloading = false.obs;
final RxBool isUpgrade = false.obs;
final RxBool isFetchingDeviceInfo = false.obs;
final RxBool showDetailedStatus = false.obs;
final RxBool isBleConnected = true.obs;
final GetStorage _storage = GetStorage();
String _address = '';
String _updatePackageAddress = '';
String? _lastConnectedDeviceImage; // 新增:存储上一次连接设备的图片链接
get lastConnectedDeviceImage => _lastConnectedDeviceImage;
@override
void onInit() {
super.onInit();
_loadLastConnectedDeviceImage(); // 加载持久化的设备图片
_initializeController();
}
@override
void onClose() {
_jlota.otaCancel();
_otaEventSub?.cancel();
_otaEventSub = null;
_bleManager.setEnterOta(false);
isUpgrade.value = false;
super.onClose();
}
/// 从本地存储加载上一次连接设备的图片链接
void _loadLastConnectedDeviceImage() {
_lastConnectedDeviceImage = _storage.read('last_connected_device_image');
Logger.d(
'OtaUpgradeController', '加载上一次连接设备的图片: $_lastConnectedDeviceImage');
}
/// 初始化控制器
/// 设置事件监听并加载版本信息
Future<void> _initializeController() async {
// 首先检查BLE设备连接状态
if (!_coreService.checkBleConnectionStatus()) {
//isFetchingDeviceInfo.value = false;
//errorMessage.value = 'unconnected'.tr;
isBleConnected.value = false;
return;
}
_listenToOtaEvents();
await _loadVersionInfo();
}
/// 加载版本信息
/// 获取当前设备版本和最新版本信息,检查是否有更新
Future<void> _loadVersionInfo() async {
try {
isFetchingDeviceInfo.value = true;
errorMessage.value = '';
// 获取当前版本信息
final currentInfo = await _coreService.getCurrentVersionInfo();
currentVersion.value = currentInfo['currentVersion'];
// 获取蓝牙地址
final connectedDevices = await ClassicBluetooth.getConnectedDevices();
if (connectedDevices.isNotEmpty) {
_address = connectedDevices.first.address;
}
// 获取最新版本信息
final latestInfo = await _coreService.getLatestVersionInfo();
latestVersion.value = latestInfo['latestVersion'];
_updatePackageAddress = latestInfo['updatePackageAddress'];
// 设置更新描述信息
updatedescription.value =
latestInfo['updateDescription'] ?? 'otaDefaultUpdateDesc'.tr;
// 检查是否有更新
isUpdateAvailable.value = _coreService.isNewVersionAvailable(
currentVersion.value,
latestVersion.value,
);
} catch (e) {
_handleError('error'.tr, _getUserFriendlyErrorMessage(e));
} finally {
isFetchingDeviceInfo.value = false;
}
}
/// 检查更新
/// 显示更新确认对话框或错误提示
Future<void> checkUpdate() async {
try {
if (latestVersion.value.isNotEmpty) {
_uiService.showUpdateDialog(latestVersion.value, _startUpdateProcess);
} else {
_uiService.showErrorSnackbar('error'.tr, 'otaGetLatestVersionFailed'.tr,
backgroundColor: Colors.orange[800]);
}
} catch (e) {
_uiService.showErrorSnackbar('error'.tr, 'otaGetVersionInfoFailed'.tr,
backgroundColor: Colors.orange[800]);
}
}
/// 开始更新流程的公共方法
/// 供视图调用的更新入口点
Future<void> startUpdate() async {
//立即给用户状态反馈
showDetailedStatus.value = true;
detailedStatus.value = 'otaCheckingDeviceStatus'.tr;
await _startUpdateProcess();
}
/// 检查设备状态后开始下载和升级
Future<void> _startUpdateProcess() async {
// 检查设备电量
if (!_coreService.checkBatteryLevel()) {
return;
}
await _startDownload();
}
/// 开始下载固件
/// 初始化OTA环境并下载固件包
Future<void> _startDownload() async {
try {
await _bleManager.setEnterOta(true);
await Future.delayed(const Duration(seconds: 2));
// device_jieli 已经在全局 InitialBinding 里 initialize 过;
// 这里无需重复 init —— 直接订阅 OTA 事件流即可。
isDownloading.value = true;
showDetailedStatus.value = true;
type.value = OtaCoreService.DOWNLOADING_UP_FILES;
final filePath = await _downloadService.downloadFirmware(
downloadUrl: _updatePackageAddress,
onProgress: (progress) {
downloadProgress.value = progress;
},
onStatusUpdate: (status) {
detailedStatus.value = status;
},
);
isDownloading.value = false;
await _startUpgrading(filePath);
} catch (e) {
isDownloading.value = false;
detailedStatus.value = 'otaDownloadFailedCheckNetwork'.tr;
showDetailedStatus.value = false;
_handleError('otaDownloadFailed'.tr, e.toString());
Logger.d('OtaUpgradeController', '下载失败: $e');
}
}
/// 开始升级
/// [filePath] 固件文件路径
/// 启动OTA升级过程
Future<void> _startUpgrading(String filePath) async {
detailedStatus.value = 'otaPreparingConnection'.tr;
await Future.delayed(const Duration(milliseconds: 500));
detailedStatus.value = 'otaConnectingDevice'.tr;
_jlota.otaStart(address: _address, firmwareFilePath: filePath);
}
/// 停止升级
/// 关闭OTA连接
void stopUpgrading() {
_jlota.otaCancel();
}
/// 重试连接
/// 清除错误信息并重新加载版本信息
void retryConnection() {
errorMessage.value = '';
_loadVersionInfo();
}
/// 获取状态描述
/// [type] 状态类型
/// 返回对应的状态描述文本
String getStatusMessage(int type) {
return OtaCoreService.getStatusMessage(type);
}
/// 监听OTA事件
/// 订阅 device_jieli 的统一事件流,过滤 OTA 相关事件并转发到分发器。
void _listenToOtaEvents() {
_otaEventSub?.cancel();
_otaEventSub = _jlota.events.listen(_handleOtaEvent);
}
/// 处理 device_jieli 抛出的 OTA / 连接事件。
/// - [OtaStateEvent]: 进度 / 状态机推进
/// - [OtaErrorEvent]: 升级失败
/// - [ConnectionStateEvent]: 设备连接 / 断开(OTA 期间用于"中断"指示)
void _handleOtaEvent(JieliEvent event) {
if (event is OtaStateEvent) {
switch (event.state) {
case OtaState.entering:
case OtaState.inquiring:
case OtaState.notifyingSize:
type.value = OtaCoreService.START_UPGRADING;
isUpgrade.value = true;
detailedStatus.value = 'otaUpgradeStarted'.tr;
break;
case OtaState.transferring:
if (event.percent >= 0) {
// device_jieli 发的是 0..100 整数;UI 这边按 0..1 浮点用。
progress.value = event.percent / 100.0;
type.value = OtaCoreService.ONUPGRADE;
isUpgrade.value = true;
detailedStatus.value = 'otaUpgradeProgressWithPercent'
.trParams({'percent': event.percent.toStringAsFixed(1)});
}
break;
case OtaState.verifying:
detailedStatus.value = 'otaUpgradeStarted'.tr;
break;
case OtaState.rebooting:
// 设备重启等待,仍在升级中
isUpgrade.value = true;
break;
case OtaState.done:
_handleUpgradeSuccess();
break;
case OtaState.failed:
_handleUpgradeError(-1);
break;
case OtaState.cancelled:
isUpgrade.value = false;
showDetailedStatus.value = false;
break;
case OtaState.idle:
break;
}
return;
}
if (event is OtaErrorEvent) {
_handleUpgradeError(event.code);
return;
}
if (event is ConnectionStateEvent) {
if (event.state == ConnectionStateEvent.connectionDisconnect &&
isUpgrade.value) {
_handleConnectionLost();
} else if (event.state == ConnectionStateEvent.connectionOk &&
isUpgrade.value) {
_handleConnectionSuccess();
}
}
}
/// 处理升级成功
/// 更新状态并显示成功对话框
void _handleUpgradeSuccess() {
type.value = OtaCoreService.UPGRADE_SUCCESS;
isUpgrade.value = false;
detailedStatus.value = 'otaUpgradeSuccessComplete'.tr;
showDetailedStatus.value = false;
// 更新版本信息
currentVersion.value = latestVersion.value;
isUpdateAvailable.value = false;
// 显示成功对话框
_uiService.showUpgradeSuccessDialog();
}
/// 处理升级错误
/// [errorCode] 错误代码
/// 更新状态并显示错误提示
void _handleUpgradeError(dynamic errorCode) {
type.value = OtaCoreService.UPGRADE_FAILED;
isUpgrade.value = false;
detailedStatus.value = 'otaUpgradeFailedWithCode'.trParams({'code': errorCode.toString()});
showDetailedStatus.value = false;
_uiService.showErrorSnackbar(
'otaUpgradeFailedTitle'.tr,
'otaUpgradeFailedDesc'.trParams({'code': errorCode.toString()}),
);
}
/// 处理连接断开
/// 更新连接状态
void _handleConnectionLost() {
type.value = OtaCoreService.CONNECTION_DISCONNECTION;
isUpgrade.value = false;
detailedStatus.value = 'otaDeviceDisconnected'.tr;
showDetailedStatus.value = false;
}
/// 处理连接成功
/// 更新连接状态
void _handleConnectionSuccess() {
type.value = OtaCoreService.CONNECTION_SUCCESS;
isUpgrade.value = true;
detailedStatus.value = 'otaDeviceConnected'.tr;
}
/// 统一错误处理
/// [title] 错误标题
/// [message] 错误信息
/// 设置错误状态并显示错误提示
void _handleError(String title, String message) {
errorMessage.value = message;
_uiService.showErrorSnackbar(title, message);
}
String _getUserFriendlyErrorMessage(Object error) {
if (error is OtaCoreException) {
switch (error.type) {
case OtaCoreErrorType.deviceInfoUnavailable:
return 'otaDeviceInfoUnavailable'.tr;
case OtaCoreErrorType.productInfoUnavailable:
return 'otaProductInfoUnavailable'.tr;
case OtaCoreErrorType.firmwareVersionFormatInvalid:
return 'otaFirmwareVersionInvalid'.tr;
}
}
return 'otaVersionInfoFailed'.tr;
}
}