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("/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=0; for(int i=nowVersionParts.Length-1;i>=0;i--) { nowversionNum += int.Parse(nowVersionParts[i]) * 10*index++; } index = 0; 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(); 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(); versionText.text = otaData.version; } } public void Back() { UIManager.Instance.RegisterBackAction(GetComponentInParent().Back); Destroy(gameObject); } public async void OnUpdateButtonClick() { LoadingUI.Show(); string savePath = Application.persistentDataPath + "/ota.bin"; var success= await NetworkCtrl.Instance.DownloadFile(otaData.download_url, savePath, GetDownloadProcess); if(!success.IsSuccess) { LoadingUI.Hide(); ToastUI.Show("100224"); return; } string md5=NetworkCtrl.Instance.CalculateMD5(savePath); if(md5!=otaData.md5) { LoadingUI.Hide(); ToastUI.Show("100223"); Debug.LogError("下载的文件MD5校验失败"); File.Delete(savePath); return; } // TODO: continue OTA update via BLE LoadFirmwareFile(savePath); ToastUI.Show("100225"); uint firmwareVersion = ParseFirmwareVersion(otaData.version); StartCoroutine(OTAManager.Instance.PerformFullUpgrade(_selectedFirmwareData, firmwareVersion, (success) => { Loom.QueueOnMainThread(() => { if (success) { ToastUI.Show("100226"); } else { ToastUI.Show("100227"); } LoadingUI.Hide(); Back(); }); })); } private void GetDownloadProcess(DownloadProgress progress) { Debug.Log($"下载进度: {progress.ProgressPercentage}%"); } // 选中的固件文件数据 private byte[] _selectedFirmwareData; private string _selectedFirmwarePath; /// /// 加载固件文件 /// 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(); } } /// /// 解析固件版本号 /// private uint ParseFirmwareVersion(string version) { try { string[] parts = version.Split('.'); if (parts.Length >= 3 && uint.TryParse(parts[0], out uint major) && uint.TryParse(parts[1], out uint minor) && uint.TryParse(parts[2], out uint patch)) { // 版本号格式:主版本.次版本.修订号 -> 32位整数 return (major << 16) | (minor << 8) | patch; } } catch { } // 默认返回版本号 1 return 1; } } }