630 lines
18 KiB
C#
630 lines
18 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using BLEProtocol;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// OTA版本信息
|
|||
|
|
/// </summary>
|
|||
|
|
[Serializable]
|
|||
|
|
public class OTAVersionInfo
|
|||
|
|
{
|
|||
|
|
public uint FirmwareVersion; // 固件版本 (4字节)
|
|||
|
|
public uint HardwareVersion; // 硬件版本 (4字节)
|
|||
|
|
public uint OTAVersion; // OTA版本 (4字节)
|
|||
|
|
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
return $"固件版本: {FirmwareVersion}, 硬件版本: {HardwareVersion}, OTA版本: {OTAVersion}";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// OTA升级状态
|
|||
|
|
/// </summary>
|
|||
|
|
public enum OTAState
|
|||
|
|
{
|
|||
|
|
Idle, // 空闲
|
|||
|
|
QueryingVersion, // 查询版本中
|
|||
|
|
Starting, // 开始升级中
|
|||
|
|
Transferring, // 传输数据中
|
|||
|
|
Ending, // 结束传输中
|
|||
|
|
Cancelling, // 取消升级中
|
|||
|
|
Completed, // 完成
|
|||
|
|
Error // 错误
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// OTA升级管理器 - 处理固件OTA升级
|
|||
|
|
/// </summary>
|
|||
|
|
public class OTAManager : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public static OTAManager Instance { get; private set; }
|
|||
|
|
|
|||
|
|
// 事件定义
|
|||
|
|
public event Action<OTAVersionInfo> OnVersionInfoReceived; // 收到版本信息
|
|||
|
|
public event Action<bool> OnStartUpgradeResult; // 开始升级结果
|
|||
|
|
public event Action<int, int, int, int> OnTransferProgress; // 传输进度 (当前包, 总包数, 重试次数, 最大重试次数)
|
|||
|
|
public event Action<bool> OnTransferComplete; // 传输完成
|
|||
|
|
public event Action<bool> OnCancelResult; // 取消结果
|
|||
|
|
public event Action<string> OnError; // 错误事件
|
|||
|
|
public event Action<OTAState> OnStateChanged; // 状态变化
|
|||
|
|
|
|||
|
|
// 状态
|
|||
|
|
public OTAState CurrentState { get; private set; } = OTAState.Idle;
|
|||
|
|
|
|||
|
|
// 升级参数
|
|||
|
|
private byte[] _firmwareData; // 固件数据
|
|||
|
|
private uint _firmwareVersion; // 固件版本
|
|||
|
|
private int _currentPacketIndex; // 当前包序号
|
|||
|
|
private int _totalPackets; // 总包数
|
|||
|
|
private const int PACKET_SIZE = 512; // 每包数据大小(根据设备MTU调整)
|
|||
|
|
|
|||
|
|
private void Awake()
|
|||
|
|
{
|
|||
|
|
if (Instance == null)
|
|||
|
|
{
|
|||
|
|
Instance = this;
|
|||
|
|
DontDestroyOnLoad(gameObject);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Destroy(gameObject);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnDestroy()
|
|||
|
|
{
|
|||
|
|
if (Instance == this)
|
|||
|
|
{
|
|||
|
|
Instance = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region OTA命令接口
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 查询OTA版本信息 (命令 0x80)
|
|||
|
|
/// </summary>
|
|||
|
|
public void QueryVersionInfo(Action<OTAVersionInfo> callback = null)
|
|||
|
|
{
|
|||
|
|
if (!CheckConnection()) return;
|
|||
|
|
|
|||
|
|
SetState(OTAState.QueryingVersion);
|
|||
|
|
|
|||
|
|
var frame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_QUERY_VERSION,
|
|||
|
|
ReadWrite = BLEConstants.RW_READ,
|
|||
|
|
Length = 0,
|
|||
|
|
Data = null
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SendFrame(frame, (response) =>
|
|||
|
|
{
|
|||
|
|
if (response.IsSuccess && response.Data != null && response.Data.Length >= 12)
|
|||
|
|
{
|
|||
|
|
var info = new OTAVersionInfo
|
|||
|
|
{
|
|||
|
|
FirmwareVersion = BitConverter.ToUInt32(response.Data, 0),
|
|||
|
|
HardwareVersion = BitConverter.ToUInt32(response.Data, 4),
|
|||
|
|
OTAVersion = BitConverter.ToUInt32(response.Data, 8)
|
|||
|
|
};
|
|||
|
|
SetState(OTAState.Idle);
|
|||
|
|
OnVersionInfoReceived?.Invoke(info);
|
|||
|
|
callback?.Invoke(info);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnError?.Invoke("查询OTA版本信息失败");
|
|||
|
|
callback?.Invoke(null);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 开始OTA升级 (命令 0x81)
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="firmwareData">固件数据</param>
|
|||
|
|
/// <param name="firmwareVersion">固件版本</param>
|
|||
|
|
/// <param name="callback">回调</param>
|
|||
|
|
public void StartUpgrade(byte[] firmwareData, uint firmwareVersion, Action<bool> callback = null)
|
|||
|
|
{
|
|||
|
|
if (!CheckConnection())
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (firmwareData == null || firmwareData.Length == 0)
|
|||
|
|
{
|
|||
|
|
LogError("固件数据为空");
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_firmwareData = firmwareData;
|
|||
|
|
_firmwareVersion = firmwareVersion;
|
|||
|
|
_currentPacketIndex = 0;
|
|||
|
|
_totalPackets = (int)Math.Ceiling((double)firmwareData.Length / PACKET_SIZE);
|
|||
|
|
|
|||
|
|
SetState(OTAState.Starting);
|
|||
|
|
|
|||
|
|
// 计算CRC16
|
|||
|
|
ushort crc16 = CalculateCRC16(firmwareData);
|
|||
|
|
|
|||
|
|
// 构建数据: 版本号(4) + 大小(4) + CRC16(2)
|
|||
|
|
byte[] data = new byte[10];
|
|||
|
|
BitConverter.GetBytes(firmwareVersion).CopyTo(data, 0);
|
|||
|
|
BitConverter.GetBytes((uint)firmwareData.Length).CopyTo(data, 4);
|
|||
|
|
BitConverter.GetBytes(crc16).CopyTo(data, 8);
|
|||
|
|
|
|||
|
|
var frame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_START,
|
|||
|
|
ReadWrite = BLEConstants.RW_WRITE,
|
|||
|
|
Length = (byte)data.Length,
|
|||
|
|
Data = data
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 使用协程来处理响应和延迟
|
|||
|
|
StartCoroutine(StartUpgradeCoroutineInternal(frame, callback));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator StartUpgradeCoroutineInternal(BLEFrame frame, Action<bool> callback)
|
|||
|
|
{
|
|||
|
|
BLEResponse response = new BLEResponse { Status = BLEConstants.STATUS_DEVICE_ERROR };
|
|||
|
|
bool completed = false;
|
|||
|
|
|
|||
|
|
SendFrame(frame, (resp) =>
|
|||
|
|
{
|
|||
|
|
response = resp;
|
|||
|
|
completed = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
yield return new WaitUntil(() => completed);
|
|||
|
|
|
|||
|
|
bool success = response.IsSuccess;
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
// 检查连接状态,如果断开则等待重连
|
|||
|
|
int retryCount = 0;
|
|||
|
|
const int maxRetries = 10;
|
|||
|
|
while (BluetoothManager.Instance != null && !BluetoothManager.Instance.IsConnected && retryCount < maxRetries)
|
|||
|
|
{
|
|||
|
|
yield return new WaitForSeconds(0.5f);
|
|||
|
|
retryCount++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (BluetoothManager.Instance == null || !BluetoothManager.Instance.IsConnected)
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnStartUpgradeResult?.Invoke(false);
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 实际测试连接是否可用 - 发送一个查询版本命令
|
|||
|
|
bool testCompleted = false;
|
|||
|
|
bool testSuccess = false;
|
|||
|
|
|
|||
|
|
var testFrame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_QUERY_VERSION,
|
|||
|
|
ReadWrite = BLEConstants.RW_READ,
|
|||
|
|
Length = 0,
|
|||
|
|
Data = null
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SendFrame(testFrame, (testResponse) =>
|
|||
|
|
{
|
|||
|
|
testSuccess = testResponse.IsSuccess;
|
|||
|
|
testCompleted = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 等待最多3秒
|
|||
|
|
float testStartTime = Time.time;
|
|||
|
|
while (!testCompleted && Time.time - testStartTime < 3f)
|
|||
|
|
{
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!testCompleted)
|
|||
|
|
{
|
|||
|
|
LogError("[OTA-DEBUG] 连接测试超时,BLE连接可能已断开");
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnStartUpgradeResult?.Invoke(false);
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!testSuccess)
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnStartUpgradeResult?.Invoke(false);
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetState(OTAState.Transferring);
|
|||
|
|
OnStartUpgradeResult?.Invoke(true);
|
|||
|
|
callback?.Invoke(true);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnStartUpgradeResult?.Invoke(false);
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 传输固件数据包 (命令 0x82)
|
|||
|
|
/// </summary>
|
|||
|
|
public IEnumerator TransferFirmware(Action<bool> callback = null)
|
|||
|
|
{
|
|||
|
|
if (_firmwareData == null)
|
|||
|
|
{
|
|||
|
|
LogError("没有固件数据");
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetState(OTAState.Transferring);
|
|||
|
|
|
|||
|
|
// 每包实际数据长度(不包括包序号)
|
|||
|
|
const int DATA_PER_PACKET = 253; // 255 - 2 (包序号)
|
|||
|
|
|
|||
|
|
// 重新计算总包数
|
|||
|
|
_totalPackets = (_firmwareData.Length + DATA_PER_PACKET - 1) / DATA_PER_PACKET;
|
|||
|
|
|
|||
|
|
for (int i = 0; i < _totalPackets; i++)
|
|||
|
|
{
|
|||
|
|
_currentPacketIndex = i;
|
|||
|
|
int offset = i * DATA_PER_PACKET; // 使用实际数据长度计算偏移
|
|||
|
|
int length = Mathf.Min(DATA_PER_PACKET, _firmwareData.Length - offset);
|
|||
|
|
|
|||
|
|
// 构建数据包: 包序号(2) + 数据(N)
|
|||
|
|
byte[] packetData = new byte[2 + length];
|
|||
|
|
BitConverter.GetBytes((ushort)i).CopyTo(packetData, 0);
|
|||
|
|
Buffer.BlockCopy(_firmwareData, offset, packetData, 2, length);
|
|||
|
|
|
|||
|
|
var frame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_TRANSFER_DATA,
|
|||
|
|
ReadWrite = BLEConstants.RW_WRITE,
|
|||
|
|
Length = (byte)packetData.Length,
|
|||
|
|
Data = packetData
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 发送数据包,带重试机制
|
|||
|
|
bool packetSuccess = false;
|
|||
|
|
int retryCount = 0;
|
|||
|
|
const int maxRetries = 5;
|
|||
|
|
|
|||
|
|
while (!packetSuccess && retryCount < maxRetries)
|
|||
|
|
{
|
|||
|
|
if (retryCount > 0)
|
|||
|
|
{
|
|||
|
|
OnTransferProgress?.Invoke(i + 1, _totalPackets, retryCount, maxRetries);
|
|||
|
|
yield return new WaitForSeconds(0.5f);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yield return SendFrameCoroutine(frame, (response) =>
|
|||
|
|
{
|
|||
|
|
packetSuccess = response.IsSuccess;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (!packetSuccess)
|
|||
|
|
{
|
|||
|
|
retryCount++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!packetSuccess)
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
OnError?.Invoke($"传输包 {_currentPacketIndex} 失败");
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 报告进度(无重试)
|
|||
|
|
OnTransferProgress?.Invoke(i + 1, _totalPackets, 0, 0);
|
|||
|
|
|
|||
|
|
// 每包之间添加小延迟,避免设备处理不过来
|
|||
|
|
if (i < _totalPackets - 1)
|
|||
|
|
{
|
|||
|
|
yield return new WaitForSeconds(0.01f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetState(OTAState.Ending);
|
|||
|
|
OnTransferComplete?.Invoke(true);
|
|||
|
|
callback?.Invoke(true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 结束传输 (命令 0x83)
|
|||
|
|
/// </summary>
|
|||
|
|
public void EndTransfer(Action<bool> callback = null)
|
|||
|
|
{
|
|||
|
|
if (!CheckConnection())
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetState(OTAState.Ending);
|
|||
|
|
|
|||
|
|
// 数据: 总大小(4) + CRC16(2)
|
|||
|
|
byte[] data = new byte[6];
|
|||
|
|
BitConverter.GetBytes((uint)_firmwareData.Length).CopyTo(data, 0);
|
|||
|
|
ushort crc16 = CalculateCRC16(_firmwareData);
|
|||
|
|
BitConverter.GetBytes(crc16).CopyTo(data, 4);
|
|||
|
|
|
|||
|
|
var frame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_END_TRANSFER,
|
|||
|
|
ReadWrite = BLEConstants.RW_WRITE,
|
|||
|
|
Length = (byte)data.Length,
|
|||
|
|
Data = data
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SendFrame(frame, (response) =>
|
|||
|
|
{
|
|||
|
|
bool success = response.IsSuccess;
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Completed);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
}
|
|||
|
|
callback?.Invoke(success);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 取消升级 (命令 0x85)
|
|||
|
|
/// </summary>
|
|||
|
|
public void CancelUpgrade(Action<bool> callback = null)
|
|||
|
|
{
|
|||
|
|
if (!CheckConnection())
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetState(OTAState.Cancelling);
|
|||
|
|
|
|||
|
|
// 数据: 取消标志(1)
|
|||
|
|
byte[] data = new byte[] { 0x01 };
|
|||
|
|
|
|||
|
|
var frame = new BLEFrame
|
|||
|
|
{
|
|||
|
|
Header1 = BLEConstants.FRAME_HEADER_1,
|
|||
|
|
Header2 = BLEConstants.FRAME_HEADER_2,
|
|||
|
|
Command = BLEConstants.CMD_OTA_CANCEL,
|
|||
|
|
ReadWrite = BLEConstants.RW_WRITE,
|
|||
|
|
Length = (byte)data.Length,
|
|||
|
|
Data = data
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SendFrame(frame, (response) =>
|
|||
|
|
{
|
|||
|
|
bool success = response.IsSuccess;
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Idle);
|
|||
|
|
_firmwareData = null;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SetState(OTAState.Error);
|
|||
|
|
}
|
|||
|
|
OnCancelResult?.Invoke(success);
|
|||
|
|
callback?.Invoke(success);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 完整升级流程
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 执行完整OTA升级流程
|
|||
|
|
/// </summary>
|
|||
|
|
public IEnumerator PerformFullUpgrade(byte[] firmwareData, uint firmwareVersion, Action<bool> callback = null)
|
|||
|
|
{
|
|||
|
|
// 0. 先取消可能存在的未完成升级
|
|||
|
|
bool cancelSuccess = false;
|
|||
|
|
yield return CancelUpgradeCoroutine((success) => cancelSuccess = success);
|
|||
|
|
if (cancelSuccess)
|
|||
|
|
{
|
|||
|
|
yield return new WaitForSeconds(1f);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 查询版本信息
|
|||
|
|
OTAVersionInfo versionInfo = null;
|
|||
|
|
yield return QueryVersionInfoCoroutine((info) => versionInfo = info);
|
|||
|
|
|
|||
|
|
if (versionInfo == null)
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 开始升级
|
|||
|
|
bool startSuccess = false;
|
|||
|
|
yield return StartUpgradeCoroutine(firmwareData, firmwareVersion, (success) => startSuccess = success);
|
|||
|
|
|
|||
|
|
if (!startSuccess)
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 传输数据
|
|||
|
|
bool transferSuccess = false;
|
|||
|
|
yield return TransferFirmware((success) => transferSuccess = success);
|
|||
|
|
|
|||
|
|
if (!transferSuccess)
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 结束传输
|
|||
|
|
bool endSuccess = false;
|
|||
|
|
yield return EndTransferCoroutine((success) => endSuccess = success);
|
|||
|
|
|
|||
|
|
if (!endSuccess)
|
|||
|
|
{
|
|||
|
|
callback?.Invoke(false);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
callback?.Invoke(true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 辅助方法
|
|||
|
|
|
|||
|
|
private bool CheckConnection()
|
|||
|
|
{
|
|||
|
|
if (BLECommunicationManager.Instance == null) return false;
|
|||
|
|
if (BluetoothManager.Instance == null || !BluetoothManager.Instance.IsConnected) return false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SetState(OTAState newState)
|
|||
|
|
{
|
|||
|
|
if (CurrentState != newState)
|
|||
|
|
{
|
|||
|
|
CurrentState = newState;
|
|||
|
|
OnStateChanged?.Invoke(newState);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SendFrame(BLEFrame frame, Action<BLEResponse> callback)
|
|||
|
|
{
|
|||
|
|
BLECommunicationManager.Instance.SendFrameInternal(frame, callback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator SendFrameCoroutine(BLEFrame frame, Action<BLEResponse> callback)
|
|||
|
|
{
|
|||
|
|
bool completed = false;
|
|||
|
|
BLEResponse response = new BLEResponse { Status = BLEConstants.STATUS_DEVICE_ERROR };
|
|||
|
|
|
|||
|
|
SendFrame(frame, (resp) =>
|
|||
|
|
{
|
|||
|
|
response = resp;
|
|||
|
|
completed = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
yield return new WaitUntil(() => completed);
|
|||
|
|
callback?.Invoke(response);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator QueryVersionInfoCoroutine(Action<OTAVersionInfo> callback)
|
|||
|
|
{
|
|||
|
|
OTAVersionInfo info = null;
|
|||
|
|
QueryVersionInfo((result) => info = result);
|
|||
|
|
yield return new WaitUntil(() => CurrentState != OTAState.QueryingVersion || info != null);
|
|||
|
|
callback?.Invoke(info);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator StartUpgradeCoroutine(byte[] firmwareData, uint firmwareVersion, Action<bool> callback)
|
|||
|
|
{
|
|||
|
|
bool completed = false;
|
|||
|
|
bool success = false;
|
|||
|
|
|
|||
|
|
StartUpgrade(firmwareData, firmwareVersion, (result) =>
|
|||
|
|
{
|
|||
|
|
success = result;
|
|||
|
|
completed = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
yield return new WaitUntil(() => completed);
|
|||
|
|
callback?.Invoke(success);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator CancelUpgradeCoroutine(Action<bool> callback)
|
|||
|
|
{
|
|||
|
|
bool completed = false;
|
|||
|
|
bool success = false;
|
|||
|
|
|
|||
|
|
CancelUpgrade((result) =>
|
|||
|
|
{
|
|||
|
|
success = result;
|
|||
|
|
completed = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
yield return new WaitUntil(() => completed);
|
|||
|
|
callback?.Invoke(success);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator EndTransferCoroutine(Action<bool> callback)
|
|||
|
|
{
|
|||
|
|
bool completed = false;
|
|||
|
|
bool success = false;
|
|||
|
|
|
|||
|
|
EndTransfer((result) =>
|
|||
|
|
{
|
|||
|
|
success = result;
|
|||
|
|
completed = true;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
yield return new WaitUntil(() => completed);
|
|||
|
|
callback?.Invoke(success);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 计算CRC16校验
|
|||
|
|
/// </summary>
|
|||
|
|
private ushort CalculateCRC16(byte[] data)
|
|||
|
|
{
|
|||
|
|
ushort crc = 0xFFFF;
|
|||
|
|
for (int i = 0; i < data.Length; i++)
|
|||
|
|
{
|
|||
|
|
crc ^= (ushort)(data[i] << 8);
|
|||
|
|
for (int j = 0; j < 8; j++)
|
|||
|
|
{
|
|||
|
|
if ((crc & 0x8000) != 0)
|
|||
|
|
crc = (ushort)((crc << 1) ^ 0x1021);
|
|||
|
|
else
|
|||
|
|
crc <<= 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return crc;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void Log(string message)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[OTAManager] {message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void LogError(string message)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[OTAManager] {message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|