using System;
|
using System.Collections.Generic;
|
using System.Text;
|
using ZigBee.Device;
|
|
namespace Shared.Phone
|
{
|
/// <summary>
|
/// 中央空调的升级逻辑
|
/// </summary>
|
public class HdlACZbGatewayUpdateLogic : DeviceUpdateCommon
|
{
|
#region ■ 变量声明___________________________
|
|
/// <summary>
|
/// <para>更新状态变化的事件</para>
|
/// <para>第一个参数为:</para>
|
/// <para>-1:更新异常,后面的值为异常信息的翻译文本</para>
|
/// <para> 0:更新状态正常变化,后面的值为状态变更的文本翻译</para>
|
/// <para> 1:升级成功</para>
|
/// <para> 2:主动终止升级(中央空调木允许终止)</para>
|
/// <para> 3:从等待中取消(目前还没有用)</para>
|
/// </summary>
|
public Action<int, string> UpdateStatuChangedEvent = null;
|
/// <summary>
|
/// 进度值事件
|
/// </summary>
|
public Action<decimal> ProgressEvent = null;
|
/// <summary>
|
/// 设备新版本的固件信息(多个设备升级时,应该会需要公开这个对象)
|
/// </summary>
|
public FirmwareVersionInfo deviceFirmware = null;
|
/// <summary>
|
/// 网关
|
/// </summary>
|
private ZbGateway zbGateway = null;
|
/// <summary>
|
/// 升级的设备
|
/// </summary>
|
private OTADevice otaDevice = null;
|
/// <summary>
|
/// 设备对象
|
/// </summary>
|
private CommonDevice deviceAc = null;
|
/// <summary>
|
/// 前一次的最终状态
|
/// </summary>
|
private UpdateStatuMode oldUpdateStatu = UpdateStatuMode.None;
|
/// <summary>
|
/// 固件的byte数组
|
/// </summary>
|
private byte[] deviceFirmwareByte = null;
|
|
#endregion
|
|
#region ■ 初始化_____________________________
|
|
/// <summary>
|
/// <para>HDL设备升级,以下为两个重要事件</para>
|
/// <para>UpdateStatuChangedEvent:更新状态变化的事件</para>
|
/// <para>ProgressEvent:进度值事件</para>
|
/// <para>StartUpdateReady():设备开始执行升级的函数,在调用这个之前,请先实现上面两个方法</para>
|
/// </summary>
|
/// <param name="i_deviceAc">设备</param>
|
/// <param name="i_deviceFirmware">设备的固件信息</param>
|
public HdlACZbGatewayUpdateLogic(CommonDevice i_deviceAc, FirmwareVersionInfo i_deviceFirmware)
|
{
|
this.ClassDiv = 2;
|
this.deviceAc = i_deviceAc;
|
this.otaDevice = HdlDeviceCommonLogic.Current.GetOTADevice(i_deviceAc.DeviceAddr);
|
this.deviceFirmware = i_deviceFirmware;
|
this.zbGateway = i_deviceAc.Gateway;
|
}
|
|
#endregion
|
|
#region ■ 开始更新___________________________
|
|
/// <summary>
|
/// 进入执行更新操作准备阶段
|
/// </summary>
|
public void StartUpdateReady()
|
{
|
if (this.UpdateStatu == UpdateStatuMode.Wait)
|
{
|
//如果是等待模式,再次点击时,移除列表
|
if (HdlFirmwareUpdateResourse.dicUpdateList.ContainsKey(otaDevice.DeviceAddr) == true)
|
{
|
HdlFirmwareUpdateResourse.dicUpdateList.Remove(otaDevice.DeviceAddr);
|
}
|
//取消
|
this.UpdateStatu = UpdateStatuMode.None;
|
this.UpdateStatuChangedEvent?.Invoke(3, "");
|
return;
|
}
|
//如果它有状态,则表示之前它被什么错误中断了
|
if (this.UpdateStatu != UpdateStatuMode.None)
|
{
|
//保存起来,后面有用处
|
this.oldUpdateStatu = this.UpdateStatu;
|
}
|
|
//进入等待模式
|
this.UpdateStatu = UpdateStatuMode.Wait;
|
HdlFirmwareUpdateResourse.dicUpdateList[otaDevice.DeviceAddr] = this;
|
|
//等待中…
|
this.UpdateStatuChangedEvent?.Invoke(0, Language.StringByID(R.MyInternationalizationString.uWaitting));
|
|
//执行下一个可更新的固件的更新操作
|
HdlFirmwareUpdateLogic.Current.DoUpdateNextFirmware();
|
}
|
|
/// <summary>
|
/// 开始执行更新操作
|
/// </summary>
|
public override void DoStartUpdate()
|
{
|
//状态变更
|
this.IsFinishUpdate = false;
|
this.UpdateStatu = UpdateStatuMode.Action;
|
//根据状态执行操作
|
this.DoAdjustByStatuMode();
|
}
|
|
/// <summary>
|
/// 根据状态执行操作
|
/// </summary>
|
private void DoAdjustByStatuMode()
|
{
|
//先这样写吧,有可能以后会分情况
|
//首发时,从开始执行
|
if (this.oldUpdateStatu == UpdateStatuMode.None)
|
{
|
//执行校验版本
|
this.DoCheckVersion();
|
}
|
//设备下载失败
|
else if (this.oldUpdateStatu == UpdateStatuMode.DeviceDownLoadFail)
|
{
|
//执行校验版本
|
this.DoCheckVersion();
|
}
|
//设备升级失败
|
else if (this.oldUpdateStatu == UpdateStatuMode.DeviceUpdateFail)
|
{
|
//执行校验版本
|
this.DoCheckVersion();
|
}
|
else
|
{
|
//重新再来
|
this.DoCheckVersion();
|
}
|
}
|
|
#endregion
|
|
#region ■ 校验版本___________________________
|
|
/// <summary>
|
/// 校验版本
|
/// </summary>
|
private async void DoCheckVersion()
|
{
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateReady;
|
//检测设备版本
|
this.UpdateStatuChangedEvent?.Invoke(0, Language.StringByID(R.MyInternationalizationString.uCheckDeviceVersion));
|
//设置初始值
|
this.SetProgressValue(0, 100);
|
|
await System.Threading.Tasks.Task.Delay(1000);
|
|
//下载固件资源
|
if (this.deviceFirmware.ImagType != "-100")
|
{
|
this.deviceFirmwareByte = HdlFirmwareUpdateLogic.Current.DowLoadFirmware(FirmwareLevelType.A设备, this.deviceFirmware.DistributedMark);
|
}
|
else
|
{
|
//取本地模板
|
this.deviceFirmwareByte = HdlFileLogic.Current.ReadFileByteContent(this.deviceFirmware.Name);
|
}
|
if (this.deviceFirmwareByte == null)
|
{
|
//设备固件资源下载失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uDeviceFirmwareDownLoadFail));
|
|
//显示重新下载模式
|
this.ShowReDownLoadMode();
|
|
this.UpdateStatu = UpdateStatuMode.DeviceDownLoadFail;
|
return;
|
}
|
|
//数据偏移量,每个分包偏移量+(1-43)
|
string offset = string.Empty;
|
//一次发送的数据长度
|
int dataLength = -1;
|
//接收网关的透传数据
|
Action<string, object> receiveAction = (comand, pushData) =>
|
{
|
string receiveData = ((CommonDevice.ClientDataPassthroughResponseData)pushData).PassData;
|
if (receiveData.Length < 6)
|
{
|
return;
|
}
|
try
|
{
|
var command = receiveData[4].ToString() + receiveData[5].ToString() + receiveData[2].ToString() + receiveData[3].ToString();
|
if (command == "025c")
|
{
|
offset = receiveData.Substring(10, 8);
|
dataLength = Convert.ToInt32(receiveData.Substring(18, 2), 16);
|
}
|
}
|
catch { }
|
};
|
this.zbGateway.ReportAction += receiveAction;
|
|
//读取空调模块版本
|
var result = await HdlDeviceAirConditionerLogic.Current.ReadACFirewareVersionAsync(deviceAc);
|
if (result == null || result.readACFirewareVersionResponData == null || result.readACFirewareVersionResponData.Status != 0)
|
{
|
//获取空调模块版本失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uGetAirConditionerModelVersionFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
//发送升级通知
|
var result2 = await HdlDeviceAirConditionerLogic.Current.UpggradeACNotificationAsync(deviceAc, result.readACFirewareVersionResponData.FirewareVersion, this.deviceFirmwareByte.Length);
|
if (result2.responseData == null)
|
{
|
//发送升级命令失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uSendUpdateComandFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
else if (result2.responseData.status == 1)
|
{
|
//版本号相同,升级失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uVersionIsEqualAndUpdateFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
else if (result2.responseData.status != 0)
|
{
|
//校验版本号失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uCheckVersionFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
|
int timeOut = 0;
|
//等待接收偏移量
|
while (dataLength == -1)
|
{
|
timeOut++;
|
if (timeOut >= 30)
|
{
|
//响应超时,检测设备版本失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uResponseTimeoutsAndCheckDeviceVersionFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
await System.Threading.Tasks.Task.Delay(1000);
|
//设置进度值
|
this.SetProgressValue(timeOut, 30);
|
}
|
this.zbGateway.ReportAction -= receiveAction;
|
|
//执行设备升级操作
|
this.DoSetUpdateDevice(offset, dataLength);
|
}
|
|
#endregion
|
|
#region ■ 设备升级___________________________
|
|
/// <summary>
|
/// 执行设备升级操作
|
/// </summary>
|
private async void DoSetUpdateDevice(string i_offset, int i_dataLength)
|
{
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateReady;
|
//设备正在升级…
|
this.UpdateStatuChangedEvent?.Invoke(0, Language.StringByID(R.MyInternationalizationString.uDeviceUpdating));
|
//设置初始值
|
this.SetProgressValue(0, 100);
|
|
await System.Threading.Tasks.Task.Delay(1000);
|
|
//发送数据的索引
|
int startIndex = 0;
|
int allDataLength = this.deviceFirmwareByte.Length;
|
int timeOut = 0;
|
//是否接收到成功命令
|
bool receiveSuccess = false;
|
|
//接收网关的透传数据
|
bool hadReceive = true;
|
Action<string, object> receiveAction = (comand, pushData) =>
|
{
|
if (comand != "DeviceRequestAcUpdateData")
|
{
|
return;
|
}
|
string receiveData = ((CommonDevice.ClientDataPassthroughResponseData)pushData).PassData;
|
if (receiveData.Length < 6)
|
{
|
return;
|
}
|
try
|
{
|
var command = receiveData[4].ToString() + receiveData[5].ToString() + receiveData[2].ToString() + receiveData[3].ToString();
|
if (command == "025c")
|
{
|
i_offset = receiveData.Substring(10, 8);
|
i_dataLength = Convert.ToInt32(receiveData.Substring(18, 2), 16);
|
hadReceive = true;
|
timeOut = 0;
|
//设置进度值
|
this.SetProgressValue(startIndex, allDataLength);
|
}
|
else if (command == "025e")
|
{
|
//成功 设置进度值直接100%
|
this.SetProgressValue(allDataLength, allDataLength);
|
receiveSuccess = true;
|
timeOut = 0;
|
}
|
}
|
catch { }
|
};
|
this.zbGateway.ReportAction += receiveAction;
|
|
//最后一次需要等待回复结果才往下走
|
while (startIndex < allDataLength)
|
{
|
if (receiveSuccess == true)
|
{
|
//已经接收到成功的命令
|
break;
|
}
|
if (hadReceive == false)
|
{
|
timeOut++;
|
if (timeOut >= 1500)
|
{
|
//响应超时,升级失败
|
this.ShowErrorMsg(Language.StringByID(R.MyInternationalizationString.uResponseTimeoutsAndUpdateFail));
|
//显示重新安装
|
this.ShowReSetupMsg();
|
this.UpdateStatu = UpdateStatuMode.DeviceUpdateFail;
|
this.zbGateway.ReportAction -= receiveAction;
|
//发送失败给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 1);
|
return;
|
}
|
await System.Threading.Tasks.Task.Delay(50);
|
continue;
|
}
|
hadReceive = false;
|
//因为偏移量是高位在前,所以倒过来
|
string Myoffset = string.Empty;
|
for (int i = 6; i >= 0; i = i - 2)
|
{
|
Myoffset += i_offset.Substring(i, 2);
|
}
|
startIndex = Convert.ToInt32(Myoffset, 16) - i_dataLength;
|
|
//获取一次能够发送的byte
|
var listData = new List<byte>();
|
for (; startIndex < allDataLength; startIndex++)
|
{
|
listData.Add(this.deviceFirmwareByte[startIndex]);
|
if (listData.Count == i_dataLength)
|
{
|
break;
|
}
|
}
|
//发送透传数据
|
var sendData = new HdlDeviceAirConditionerLogic.SendUpgradeData() { dataLength = i_dataLength, offset = i_offset };
|
sendData.databytes = listData.ToArray();
|
HdlDeviceAirConditionerLogic.Current.UpgradeAsync(deviceAc, sendData);
|
}
|
this.zbGateway.ReportAction -= receiveAction;
|
|
//发送结束命令
|
this.DoSendFinishComand();
|
}
|
|
#endregion
|
|
#region ■ 分包结束___________________________
|
|
/// <summary>
|
/// 发送结束命令
|
/// </summary>
|
private async void DoSendFinishComand()
|
{
|
//正在发送升级完成的命令
|
this.UpdateStatuChangedEvent?.Invoke(0, Language.StringByID(R.MyInternationalizationString.uSendingFinishUpdateComand));
|
|
//发送成功命令给设备
|
HdlDeviceAirConditionerLogic.Current.SendFinishAsync(deviceAc, 0);
|
|
//等个两秒钟吧
|
await System.Threading.Tasks.Task.Delay(2000);
|
|
//显示升级完成的信息
|
this.ShowFinishMsg();
|
}
|
|
#endregion
|
|
#region ■ 设置进度___________________________
|
|
/// <summary>
|
/// 设定进度值
|
/// </summary>
|
/// <param name="value">进度值</param>
|
/// <param name="maxValue">maxValue</param>
|
private void SetProgressValue(decimal value, decimal maxValue)
|
{
|
this.ProgressEvent?.Invoke(value / maxValue);
|
}
|
|
/// <summary>
|
/// 设置错误信息
|
/// </summary>
|
/// <param name="value"></param>
|
private void ShowErrorMsg(string value)
|
{
|
this.UpdateStatuChangedEvent?.Invoke(-1, value);
|
}
|
|
#endregion
|
|
#region ■ 升级完成提示_______________________
|
|
/// <summary>
|
/// 显示升级完成的信息
|
/// </summary>
|
private void ShowFinishMsg()
|
{
|
//状态变更
|
this.IsFinishUpdate = true;
|
//升级完成
|
this.UpdateStatu = UpdateStatuMode.UpdateFinish;
|
|
HdlFirmwareUpdateLogic.Current.DoUpdateNextFirmware();
|
|
//设备升级成功!
|
this.UpdateStatuChangedEvent?.Invoke(1, Language.StringByID(R.MyInternationalizationString.uDeviceUpdateSuccess));
|
}
|
|
#endregion
|
|
#region ■ 处理结果提示_______________________
|
|
/// <summary>
|
/// 显示重新安装的信息
|
/// </summary>
|
private void ShowReSetupMsg()
|
{
|
//状态变更
|
this.IsFinishUpdate = true;
|
//执行下一个升级
|
HdlFirmwareUpdateLogic.Current.DoUpdateNextFirmware();
|
}
|
|
/// <summary>
|
/// 显示重新下载模式
|
/// </summary>
|
private void ShowReDownLoadMode()
|
{
|
//状态变更
|
this.IsFinishUpdate = true;
|
//执行下一个升级
|
HdlFirmwareUpdateLogic.Current.DoUpdateNextFirmware();
|
}
|
|
#endregion
|
|
#region ■ 释放缓存___________________________
|
|
/// <summary>
|
/// 释放缓存
|
/// </summary>
|
public override void Dispose()
|
{
|
this.ProgressEvent = null;
|
this.UpdateStatuChangedEvent = null;
|
}
|
|
#endregion
|
}
|
}
|