205 lines
6.8 KiB
C#
205 lines
6.8 KiB
C#
|
|
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=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<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);
|
|||
|
|
}
|
|||
|
|
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;
|
|||
|
|
|
|||
|
|
/// <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 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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|