初始化CRICS
This commit is contained in:
283
RCUHost/Implement/UpdateHostReceiver.cs
Normal file
283
RCUHost/Implement/UpdateHostReceiver.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Common;
|
||||
using Dao;
|
||||
using Domain;
|
||||
using RCUHost.Protocols;
|
||||
|
||||
namespace RCUHost.Implement
|
||||
{
|
||||
public class UpdateHostReceiver : GenericReceiverBase, IUpdateHostReceiver
|
||||
{
|
||||
private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(UpdateHostReceiver));
|
||||
private readonly int TFTP_PORT = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["TFTPPort"]);//TFTP通信端口
|
||||
private const int BLOCK_SIZE = 512;//TFTP块大小512字节
|
||||
public IHostRepository HostRepository { get; set; }
|
||||
public IHostUpdateStatusRepository HostUpdateStatusRepository { get; set; }
|
||||
private IList<UpdateHostWorker> updateHostList = new List<UpdateHostWorker>();
|
||||
/// <summary>
|
||||
/// 升级
|
||||
/// </summary>
|
||||
/// <param name="hostUpdate"></param>
|
||||
/// <param name="fileType"></param>
|
||||
/// <param name="fileHref"></param>
|
||||
/// <param name="fileMd5"></param>
|
||||
/// <param name="hosts"></param>
|
||||
public void Update(HostUpdate hostUpdate, FileType fileType, string fileHref, string fileMd5, IList<Host> hosts)
|
||||
{
|
||||
if (hosts == null || hosts.Count == 0)
|
||||
{
|
||||
throw new ApplicationException("升级失败,没有找到需要升级的主机。");
|
||||
}
|
||||
if (String.IsNullOrEmpty(fileHref))
|
||||
{
|
||||
throw new ApplicationException("升级失败,无效的升级文件。");
|
||||
}
|
||||
string updateFile = Tools.GetApplicationPath() + fileHref;
|
||||
if (!File.Exists(updateFile))
|
||||
{
|
||||
throw new ApplicationException("升级失败,【" + updateFile + "】文件不存在。");
|
||||
}
|
||||
|
||||
//添加升级功能标志,告诉缓存,不能被拦截
|
||||
foreach (var item in hosts)
|
||||
{
|
||||
string Key="Upgrade_UpdateSQL_"+ item.HostNumber;
|
||||
MemoryCacheHelper.Set(Key,item.ID,DateTimeOffset.Now.AddMinutes(3));
|
||||
}
|
||||
|
||||
FileInfo fileInfo = new FileInfo(updateFile);
|
||||
ushort blockNum = (ushort)Math.Ceiling((double)fileInfo.Length / BLOCK_SIZE);
|
||||
this.updateHostList.Clear();
|
||||
foreach (var host in hosts)
|
||||
{
|
||||
SendUpdateRequest(host, fileMd5, blockNum, (byte)fileType, fileHref.Substring(fileHref.IndexOf("/")));//发送升级通知
|
||||
this.updateHostList.Add(new UpdateHostWorker(host, hostUpdate, MessageIP, fileHref, updateFile));
|
||||
if (hostUpdate == null)//从api获取升级文件方式为null,保存主机表升级状态信息
|
||||
{
|
||||
HostRepository.SetUpgradeStatus(host, 0, true);//重置升级状态
|
||||
}
|
||||
else
|
||||
{
|
||||
HostUpdateStatus hostUpdateStatus = HostUpdateStatusRepository.Get(host, hostUpdate);
|
||||
if (hostUpdateStatus == null)
|
||||
{
|
||||
hostUpdateStatus = new HostUpdateStatus();
|
||||
hostUpdateStatus.Host = host;
|
||||
hostUpdateStatus.HostUpdate = hostUpdate;
|
||||
hostUpdateStatus.PublishTime = DateTime.Now;
|
||||
}
|
||||
hostUpdateStatus.Status = 0;
|
||||
hostUpdateStatus.UpdatedTime = DateTime.Now;
|
||||
HostUpdateStatusRepository.SaveOrUpdate(hostUpdateStatus);
|
||||
}
|
||||
//logger.Error(string.Format("酒店{0}客房{1}开始升级:{2}", host.SysHotel.Code, host.RoomNumber, fileHref));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Process(ReceiverContext context1)
|
||||
{
|
||||
int startIndex = StructConverter.SizeOf(context1.SystemHeader);
|
||||
UpdateHostPacketReply? reply1 = DecodeUpdateHostPacketReply(context1.Data, startIndex);
|
||||
var TTT = new Tuple<ReceiverContext, UpdateHostPacketReply?>(context1,reply1);
|
||||
//logger.Error(string.Format("收到tftp升级回复命令({0}:{1}):{2},解析结果:{3}", context.RemoteEndPoint.Address.ToString(), context.RemoteEndPoint.Port, Tools.ByteToString(context.Data), reply.HasValue));
|
||||
if (reply1.HasValue)
|
||||
{
|
||||
Task.Factory.StartNew((State) =>
|
||||
{
|
||||
var NNN = State as Tuple<ReceiverContext, UpdateHostPacketReply?>;
|
||||
var context = NNN.Item1;
|
||||
var reply = NNN.Item2;
|
||||
var updateHostWorker = this.updateHostList.FirstOrDefault(r => r.Host.HostNumber == context.SystemHeader.Value.HostNumber.ToString());
|
||||
//logger.Error(string.Format("酒店{0}客房{1}升级({2}),状态{3}", updateHostWorker.Host.SysHotel.Code, updateHostWorker.Host.RoomNumber, updateHostWorker.RemoteFile, reply.Value.Status));
|
||||
SaveSystemLog(30, "升级主机", string.Format("收到主机({0})升级回复命令,状态:{1}", updateHostWorker.Host.RoomNumber, reply.Value.Status), "收到命令", "RCU", context.RemoteEndPoint.Address.ToString(), updateHostWorker.Host.SysHotel.ID);
|
||||
if (updateHostWorker.HostUpdate == null)
|
||||
{
|
||||
BarData bbb = new BarData();
|
||||
bbb.HostID = updateHostWorker.Host.ID;
|
||||
|
||||
switch (reply.Value.Status)
|
||||
{
|
||||
case UpdateHostPacketReply.Ready:
|
||||
HostRepository.SetUpgradeStatus(updateHostWorker.Host, 0);//升级就绪
|
||||
//updateHostWorker.Update();
|
||||
bbb.Upgrade_status = "升级就绪";
|
||||
break;
|
||||
case UpdateHostPacketReply.Completed:
|
||||
Reply(context);//升级完成回复主机
|
||||
HostRepository.SetUpgradeStatus(updateHostWorker.Host, 1);//升级完成
|
||||
bbb.Upgrade_status = "升级完成";
|
||||
break;
|
||||
default:
|
||||
HostRepository.SetUpgradeStatus(updateHostWorker.Host, 2);//升级失败
|
||||
bbb.Upgrade_status = "升级失败";
|
||||
break;
|
||||
}
|
||||
UploadCurrentVersionReceiver.UP_Grade_Json(updateHostWorker.Host, bbb);
|
||||
}
|
||||
else
|
||||
{
|
||||
HostUpdateStatus hostUpdateStatus = HostUpdateStatusRepository.Get(updateHostWorker.Host, updateHostWorker.HostUpdate);
|
||||
if (hostUpdateStatus == null)
|
||||
{
|
||||
hostUpdateStatus = new HostUpdateStatus();
|
||||
hostUpdateStatus.Host = updateHostWorker.Host;
|
||||
hostUpdateStatus.HostUpdate = updateHostWorker.HostUpdate;
|
||||
hostUpdateStatus.PublishTime = DateTime.Now;
|
||||
hostUpdateStatus.Status = 0;
|
||||
}
|
||||
BarData bbb = new BarData();
|
||||
bbb.HostID = updateHostWorker.Host.ID;
|
||||
switch (reply.Value.Status)
|
||||
{
|
||||
case UpdateHostPacketReply.Ready:
|
||||
//updateHostWorker.Update();
|
||||
hostUpdateStatus.Status = 0;//升级就绪
|
||||
bbb.Upgrade_status = "升级就绪";
|
||||
break;
|
||||
case UpdateHostPacketReply.Completed:
|
||||
bbb.Upgrade_status = "升级完成";
|
||||
Reply(context);//升级完成回复主机
|
||||
hostUpdateStatus.Status = 1;//升级完成
|
||||
updateHostList.Remove(updateHostWorker);
|
||||
break;
|
||||
default:
|
||||
bbb.Upgrade_status = "升级失败";
|
||||
hostUpdateStatus.Status = 2;//升级失败
|
||||
updateHostList.Remove(updateHostWorker);
|
||||
break;
|
||||
}
|
||||
bbb.Upgrade_DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
UploadCurrentVersionReceiver.UP_Grade_Json(updateHostWorker.Host, bbb);
|
||||
hostUpdateStatus.UpdatedTime = DateTime.Now;
|
||||
HostUpdateStatusRepository.SaveOrUpdate(hostUpdateStatus);
|
||||
}
|
||||
},TTT);
|
||||
}
|
||||
}
|
||||
public override CommandType CommandType
|
||||
{
|
||||
get { return CommandType.TFTPUpdate; }
|
||||
}
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// 发送升级指令到RCU主机
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
/// <param name="updateFileMd5">升级文件MD5值</param>
|
||||
private void SendUpdateRequest(Host host, string updateFileMd5, ushort blockNum, byte fileType, string fileName)
|
||||
{
|
||||
byte[] data = CreateUpdateRequestPacket(updateFileMd5, blockNum, fileType, fileName);
|
||||
Send(data, host.HostNumber, host.MAC);// host.IP, host.Port);
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建主机升级请求数据包
|
||||
/// </summary>
|
||||
/// <param name="updateFileMd5">升级文件MD5值</param>
|
||||
/// <param name="blockNum">块数量</param>
|
||||
/// <param name="fileType">文件类型</param>
|
||||
/// <param name="fileName">文件名(含酒店编码)</param>
|
||||
/// <returns></returns>
|
||||
private byte[] CreateUpdateRequestPacket(string updateFileMd5, ushort blockNum, byte fileType, string fileName)
|
||||
{
|
||||
SystemHeader systemHeader = CreateSystemHeader();
|
||||
int headerSize = StructConverter.SizeOf(systemHeader);
|
||||
|
||||
byte[] ipArr = IPAddress.Parse(MessageIP).GetAddressBytes();
|
||||
byte[] portArr = BitConverter.GetBytes((ushort)TFTP_PORT);//tftp通讯端口
|
||||
uint[] md5Arr = Tools.MD5StringToUIntArray(updateFileMd5);
|
||||
byte[] bFileName = System.Text.Encoding.Default.GetBytes(fileName); //Tools.GetBytes(fileName, 20);
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
stream.Seek(headerSize, SeekOrigin.Begin);
|
||||
|
||||
stream.Write(ipArr, 0, ipArr.Length);
|
||||
stream.Write(portArr, 0, portArr.Length);
|
||||
stream.Write(BitConverter.GetBytes(md5Arr[0]), 0, 4);
|
||||
stream.Write(BitConverter.GetBytes(md5Arr[1]), 0, 4);
|
||||
stream.Write(BitConverter.GetBytes(md5Arr[2]), 0, 4);
|
||||
stream.Write(BitConverter.GetBytes(md5Arr[3]), 0, 4);
|
||||
stream.Write(BitConverter.GetBytes(blockNum), 0, 2);
|
||||
stream.Write(new byte[] { fileType }, 0, 1);//文件类型,0是bin,1是cfg,2是bat
|
||||
stream.Write(bFileName, 0, bFileName.Length);//文件名
|
||||
stream.Write(new byte[] { 0, 0 }, 0, 2);//补两个长度
|
||||
|
||||
//填充 SystemHeader
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
systemHeader.FrameLength = (ushort)stream.Length;
|
||||
systemHeader.FrameNo = 0xFFFF;
|
||||
byte[] headerData = StructConverter.StructToBytes(systemHeader);
|
||||
stream.Write(headerData, 0, headerData.Length);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 解码 UpdateHostPacketReply
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <returns></returns>
|
||||
private UpdateHostPacketReply? DecodeUpdateHostPacketReply(byte[] data, int startIndex)
|
||||
{
|
||||
return StructConverter.BytesToStruct(data, startIndex, typeof(UpdateHostPacketReply)) as UpdateHostPacketReply?;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class UpdateHostWorker
|
||||
{
|
||||
private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(UpdateHostWorker));
|
||||
|
||||
private readonly int TFTP_PORT = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["TFTPPort"]);//TFTP通信端口
|
||||
//private Comzept.Genesis.NetworkTools.TFTPClient tftpClient;
|
||||
public Host Host { get; private set; }
|
||||
public int Progress { get; private set; }
|
||||
public HostUpdate HostUpdate;
|
||||
//private Task task;
|
||||
public string RemoteFile;
|
||||
public string LocalFile;
|
||||
|
||||
public UpdateHostWorker(Host host, HostUpdate hostUpdate, string tftpServer, string remoteFile, string localFile)
|
||||
{
|
||||
this.Host = host;
|
||||
this.HostUpdate = hostUpdate;
|
||||
this.RemoteFile = remoteFile;
|
||||
this.LocalFile = localFile;
|
||||
//this.tftpClient = new Comzept.Genesis.NetworkTools.TFTPClient(tftpServer, TFTP_PORT);
|
||||
//this.tftpClient.ReportCompletedProgress += new Comzept.Genesis.NetworkTools.TFTPClient.ReportCompletedProgressEventDelegate(tftpClient_ReportCompletedProgress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Puts the specified remote file.
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
logger.Error(string.Format("酒店({0})客房({1})主机升级:RemoteFile:{2},LocalFile:{3}", this.Host.SysHotel.Code, this.Host.RoomNumber, this.RemoteFile, this.LocalFile));
|
||||
//this.tftpClient.Put(this.RemoteFile, this.LocalFile);
|
||||
}
|
||||
|
||||
private void tftpClient_ReportCompletedProgress(string remoteIP, int completedBlock, int totalBlock)
|
||||
{
|
||||
this.Progress = completedBlock;
|
||||
logger.Error(string.Format("收到酒店({0})客房({1})主机升级总块数({2})", this.Host.SysHotel.Code, this.Host.RoomNumber, totalBlock));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//if (task != null)
|
||||
//{
|
||||
// task.Dispose();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user