killapp/Assets/Scripts/UI/Pages/DeviceInfoPage/FirmwareUpdatePage.cs

271 lines
10 KiB
C#
Raw Normal View History

2026-06-08 08:55:10 +08:00
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Kill.Bluetooth;
using Kill.Core;
using Kill.Managers;
using Kill.Network;
using Kill.UI.Components;
using UnityEngine;
using UnityEngine.UI;
namespace Kill.UI.Pages
{
public class FirmwareUpdatePage : MonoBehaviour
{
public GameObject latestTip;
public GameObject getNewVersionTip;
public Text versionText;
public Text changeLogText;
public Button backButton;
public Button updateButton;
OTAData otaData;
void Start()
{
UIManager.Instance.RegisterBackAction(Back);
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(Back);
updateButton.onClick.RemoveAllListeners();
updateButton.onClick.AddListener(OnUpdateButtonClick);
updateButton.gameObject.SetActive(false);
GetOtaInfo();
}
public async void GetOtaInfo()
{
LoadingUI.Show();
var response = await NetworkCtrl.Instance.Get<OTAResponse>("/api/v1/ota/latest");
LoadingUI.Hide();
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
otaData = data.data;
Debug.Log($"加载OTA信息成功版本: {otaData.version}");
InitOtaUI();
},
onError:(code,message)=>
{
Debug.LogError($"加载OTA信息失败: {message}");
}
);
}
public void InitOtaUI()
{
string nowVersion = DataManager.Instance.selectedDevice.firmware_version;
string[] versionParts = otaData.version.Split('.');
string[] nowVersionParts = nowVersion.Split('.');
int nowversionNum = 0;
int versionNum = 0;
int index=1;
2026-06-08 08:55:10 +08:00
for(int i=nowVersionParts.Length-1;i>=0;i--)
{
nowversionNum += int.Parse(nowVersionParts[i]) * 10*index++;
}
index = 1;
2026-06-08 08:55:10 +08:00
for (int i = versionParts.Length - 1; i >= 0; i--)
{
versionNum += int.Parse(versionParts[i]) * 10 * index++;
}
Debug.Log($"当前版本: {nowVersion} ({nowversionNum}), 最新版本: {otaData.version} ({versionNum})");
bool hasNewVersion = versionNum > nowversionNum;
if(hasNewVersion)
{
latestTip.SetActive(false);
getNewVersionTip.SetActive(true);
changeLogText.gameObject.SetActive(true);
versionText=getNewVersionTip.transform.Find("value").GetComponent<Text>();
versionText.text = otaData.version;
changeLogText.text = otaData.release_notes;
updateButton.gameObject.SetActive(true);
}
else
{
latestTip.SetActive(true);
getNewVersionTip.SetActive(false);
updateButton.gameObject.SetActive(false);
changeLogText.gameObject.SetActive(false);
versionText = latestTip.transform.Find("value").GetComponent<Text>();
versionText.text = otaData.version;
}
}
public void Back()
{
UIManager.Instance.RegisterBackAction(GetComponentInParent<DeviceInfoPage>().Back);
Destroy(gameObject);
2026-06-22 14:57:16 +08:00
Screen.sleepTimeout = SleepTimeout.SystemSetting;
2026-06-08 08:55:10 +08:00
}
private bool isUpdating; // OTA升级进行中(防连点重入)
2026-06-08 08:55:10 +08:00
public async void OnUpdateButtonClick()
{
// 防连点升级流程进行中忽略重复触发避免并发启动两个OTA
if (isUpdating) return;
isUpdating = true;
2026-06-22 14:57:16 +08:00
Screen.sleepTimeout = SleepTimeout.NeverSleep;
// WiFi 模式:直接 push OTA 指令,设备自行下载固件
if (DataManager.Instance.hasWifi)
{
try
{
var pushRequest = new OTAPushRequest
{
ble_mac = DataManager.Instance.selectedDevice.ble_mac,
version = otaData.version
};
var pushResponse = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/ota/push", pushRequest);
ResponseCodeHandler.HandleResponse(pushResponse,
onSuccess: (data) =>
{
ToastUI.Show("100308");
DataManager.Instance.selectedDevice.firmware_version = otaData.version;
},
onError: (code, message) =>
{
ToastUI.Show("100227");
Debug.LogError($"WiFi OTA push 失败: {message}");
}
);
}
catch (System.Exception ex)
{
Debug.LogError($"WiFi OTA push 异常: {ex.Message}");
}
finally
{
isUpdating = false;
}
UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
return;
}
// BLE 模式:下载固件 → 校验 → 蓝牙传输
2026-06-22 14:57:16 +08:00
ToastUI.Show("100294");
UpdateLoadingUI.Instance.Show();
2026-06-08 08:55:10 +08:00
string savePath = Application.persistentDataPath + "/ota.bin";
var downloadResult = await NetworkCtrl.Instance.DownloadFile(otaData.download_url, savePath, UpdateLoadingUI.Instance.GetDownloadProcess);
2026-06-22 14:57:16 +08:00
UpdateLoadingUI.Instance.Hide();
if (!downloadResult.IsSuccess)
2026-06-08 08:55:10 +08:00
{
ToastUI.Show("100224");
isUpdating = false;
2026-06-08 08:55:10 +08:00
return;
}
string md5 = NetworkCtrl.Instance.CalculateMD5(savePath);
if (md5 != otaData.md5)
2026-06-08 08:55:10 +08:00
{
ToastUI.Show("100223");
Debug.LogError("下载的文件MD5校验失败");
File.Delete(savePath);
isUpdating = false;
2026-06-08 08:55:10 +08:00
return;
}
LoadFirmwareFile(savePath);
if (_selectedFirmwareData == null)
{
isUpdating = false;
return;
}
2026-06-08 08:55:10 +08:00
ToastUI.Show("100225");
2026-06-22 14:57:16 +08:00
UpdateLoadingUI.Instance.SetPrecent(0);
UpdateLoadingUI.Instance.Show();
uint firmwareVersion = ParseFirmwareVersion(otaData.version);
OTAManager.Instance.OnTransferProgress += OnOTATransferProgress;
// OTA 传输期间清空返回事件,防止用户触发返回中断升级;传输结束恢复
var otaBackAction = UIManager.Instance.GetBackAction();
UIManager.Instance.ClearBackAction();
2026-06-08 08:55:10 +08:00
StartCoroutine(OTAManager.Instance.PerformFullUpgrade(_selectedFirmwareData, firmwareVersion, (success) =>
{
Loom.QueueOnMainThread(() =>
{
isUpdating = false;
// 恢复返回事件
if (otaBackAction != null)
UIManager.Instance.RegisterBackAction(otaBackAction);
2026-06-08 08:55:10 +08:00
if (success)
{
ToastUI.Show("100226");
DataManager.Instance.selectedDevice.firmware_version = otaData.version;
2026-06-08 08:55:10 +08:00
}
else
{
ToastUI.Show("100227");
}
2026-06-22 14:57:16 +08:00
UpdateLoadingUI.Instance.Hide();
UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
2026-06-08 08:55:10 +08:00
});
}));
}
// 选中的固件文件数据
private byte[] _selectedFirmwareData;
private string _selectedFirmwarePath;
/// <summary>
/// 加载固件文件
/// </summary>
private void LoadFirmwareFile(string filePath)
{
try
{
// 获取文件大小
FileInfo fileInfo = new FileInfo(filePath);
long fileSize = fileInfo.Length;
// 读取文件
_selectedFirmwareData = File.ReadAllBytes(filePath);
_selectedFirmwarePath = filePath;
string fileName = Path.GetFileName(filePath);
}
catch (System.Exception)
{
ToastUI.Show("100224");
LoadingUI.Hide();
}
}
/// <summary>
/// 解析固件版本号
/// </summary>
private uint ParseFirmwareVersion(string version)
{
try
{
string[] parts = version.Split('.');
if (parts.Length >= 3 &&
uint.TryParse(parts[0], out uint v0) &&
uint.TryParse(parts[1], out uint v1) &&
uint.TryParse(parts[2], out uint v2))
2026-06-08 08:55:10 +08:00
{
// 版本号格式:主版本.次版本.修订号(可含第4段)
// 按每段2位十进制压缩与设备端编码一致如 00.00.01.05 -> 105
uint v3 = 0;
if (parts.Length >= 4)
uint.TryParse(parts[3], out v3);
return v0 * 1000000 + v1 * 10000 + v2 * 100 + v3;
2026-06-08 08:55:10 +08:00
}
}
catch { }
// 默认返回版本号 1
return 1;
}
2026-06-22 14:57:16 +08:00
/// <summary>
/// OTA传输进度回调
/// </summary>
private void OnOTATransferProgress(int current, int total, int retryCount, int maxRetries)
{
UpdateLoadingUI.Instance.SetPrecent((float)current/ total);
}
2026-06-08 08:55:10 +08:00
}
}