Files
Web_CRICS_Server_VS2010_Prod/RCUHost/Implement/HostSearchReceiver.cs
2025-12-11 09:17:16 +08:00

510 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Common;
using Dao;
using Domain;
using RCUHost.Protocols;
using System.Threading.Tasks;
using System.Threading;
using CommonEntity;
namespace RCUHost.Implement
{
public class HostSearchReceiver : GenericReceiverBase, IHostSearchReceiver
{
public static object objlock = new object();
private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(HostSearchReceiver));
public IHostRepository HostRepository { get; set; }
public IHostModalRepository HostModalRepository { get; set; }
public IRoomTypeModalRepository RoomTypeModalRepository { get; set; }
public ISysHotelRepository SysHotelRepository { get; set; }
public IGroupRepository GroupRepository { get; set; }
public IRoomTypeRepository RoomTypeRepository { get; set; }
public IDeviceSecretReceiver DeviceSecretReceiver { get; set; }
public IHostRegisterReceiver HostRegisterReceiver { get; set; }//注册时通知同步主机信息
private static bool searching = false;
/// <summary>
/// 当前搜索主机用户
/// </summary>
private static String user = "";
private SearchHostResultHandler searchHostResultHandler;
public void Start(SearchHostResultHandler handler)
{
searchHostResultHandler = handler;
searching = true;
HostServer.AddReceiver(this);
Start();
}
public void Start()
{
//byte[] data = CreateSearchHostRequestPacket();
//Send(data, MulticastIP, MulticastPort);
}
public bool Searching
{
get { return searching; }
}
public string User
{
get { return user; }
set { user = value ?? String.Empty; }
}
public void Stop()
{
HostServer.RemoveReceiver(this);
searchHostResultHandler = null;
searching = false;
user = "";
}
/// <summary>
/// 修改协议原来的搜索改成注册当mac地址已存在时更新数据否则插入新主机
/// </summary>
/// <param name="context"></param>
public override void Process(ReceiverContext context)
{
StepTongJi.SendInfo(4, "注册命令Task内部开始执行", context.MessageID, context.IsMonitor);
//Reply(context);
var OriginalByte = context.Data;
int lll = OriginalByte.Length;
var A1 = OriginalByte.Skip(15).Take(lll - 15 - 2).ToArray();
int startIndex = StructConverter.SizeOf(context.SystemHeader);
SearchHostPacketReply? reply = DecodeSearchHostPacketReply(context.Data, startIndex);
SearchHostPacketReplyV2? reply2 = null;
if (context.Data.Length > 100)//V2版本新补充的内容
{
reply2 = DecodeSearchHostPacketReplyV2(context.Data, 58);
}
if (reply.HasValue)
{
try
{
string hhostnumber = context.SystemHeader.Value.HostNumber.ToString();
string hotelCode = context.SystemHeader.Value.HostNumber.ToHotelCode().ToString();//获取酒店编码
string mac = BitConverter.ToString(reply.Value.MAC);
string version = reply.Value.Version;
string ip = context.RemoteEndPoint.Address.ToString();
int port = context.RemoteEndPoint.Port;
Host exitEntity = null;
StringBuilder sbSQL = new StringBuilder();
sbSQL.Append("UPDATE tb_Hosts SET ");
if (reply2.HasValue)//C系列主机处理只能靠后台手工添加
{
#region C系列主要
if (string.IsNullOrEmpty(context.SystemHeader.Value.HostNumber.ToString()))
{
//logger.Error(string.Format("C主机注册主机编号不能为空。HotelCode:{0},MAC:{1}", hotelCode, mac));
return;
}
Host EEE = null;
lock (objlock)
{
EEE = HostRepository.LoadByMac(mac).OrderByDescending(r => r.ID).FirstOrDefault();
}
if (EEE == null)
{
//logger.Error(string.Format("C主机注册通过MAC和版本号C开头找不到记录。HotelCode:{0},MAC:{1}", hotelCode, mac));
return;//通过mac地址找不到C系列主机则不新增
}
if (string.IsNullOrEmpty(EEE.RoomNumber))
{
//logger.Error(string.Format("C主机注册通过MAC和版本号C开头找到记录的房号为空。HotelCode:{0},MAC:{1}", hotelCode, mac));
return;//如果房号是空,则不更新
}
string KKK1 = CacheKey.HostInfo_Key_MAC + "_" + hotelCode + "_" + mac;
string KKK2 = CacheKey.HostInfo_Key_HostNumber + "_" + hhostnumber;
object ooo = MemoryCacheHelper.Get(KKK1);
if (ooo != null)
{
exitEntity = (Host)ooo;
}
else
{
exitEntity = EEE;
MemoryCacheHelper.Set(KKK1, EEE);
MemoryCacheHelper.SlideSet(KKK2, EEE);
}
exitEntity.DNS = string.Join(".", reply2.Value.DNS);
sbSQL.Append("DNS='" + exitEntity.DNS + "'");
if (!version.ToUpper().StartsWith("C"))
{
version = "C" + version;//如果命令里的版本号不是C开头则补上C
}
//if (exitEntity.RoomNumber != reply2.Value.RoomNumber)
//{
// //如果房号不匹配则给rcu发命令同步房号
//}
#endregion
}
else
{
#region
string Key = CacheKey.HotelInfo_Key_Code + "_" + hotelCode; ;
object ooo = MemoryCacheHelper.Get(Key);
SysHotel sysHotel = null;
if (ooo != null)
{
sysHotel = (SysHotel)ooo;
}
else
{
sysHotel = SysHotelRepository.GetByCode(hotelCode);//获取酒店记录
MemoryCacheHelper.SlideSet(hotelCode, sysHotel);
}
if (sysHotel == null)//如果无酒店记录,则设置默认酒店
{
sysHotel = new SysHotel { ID = 1 };
}
exitEntity = HostRepository.GetByMAC(mac, sysHotel.ID);//根据mac地址获取指定酒店下主机
if (exitEntity == null)//老主机新增
{
var entity = new Host();
entity.HostNumber = context.SystemHeader.Value.HostNumber.ToString();
entity.RoomNumber = context.SystemHeader.Value.HostNumber.ToRoomNumber();
entity.MAC = mac;
entity.SysHotel = sysHotel;
Group group = GroupRepository.GetGroupList(sysHotel.ID).OrderBy(r => r.ID).FirstOrDefault();
entity.Group = group != null ? group : new Group { ID = 1 };
RoomType roomType = RoomTypeRepository.LoadAll().Where(r => r.HotelID == sysHotel.ID && r.Default == true).OrderBy(r => r.ID).FirstOrDefault();
entity.RoomType = roomType != null ? roomType : new RoomType { ID = 1 };
entity.IP = ip;
entity.Port = port;
entity.Version = reply.Value.Version;
entity.ConfigVersion = String.Join(".", reply.Value.ConfigVersion);
entity.SubnetMask = String.Join(".", reply.Value.SubnetMask);
entity.Gateway = String.Join(".", reply.Value.Gateway);
entity.Remark = hotelCode;
entity.RoomStatus = new RoomStatus { ID = 16 };//默认房态“空房”
entity.SafeStatus = 2;//默认未接保险箱
entity.RegisterDate = DateTime.Now;
entity.IsSyncRoomNumber = false;
entity.IsAutoUpdate = false;
entity.Last_Modified_Time = DateTime.Now;//标识有更新
entity = GetDeviceSecret(entity, ref sbSQL);//获取密钥
HostRepository.Save(entity);//保存主机
PublishDeviceSecret(entity);//下发密钥
Task.Factory.StartNew<bool>(() => UpdateHostModals(entity));//创建新回路
return;
}
else
{
sbSQL.Append("MAC='" + mac + "'");
}
#endregion
}
bool isChanged = false;
string hostNumber = context.SystemHeader.Value.HostNumber.ToString();
string configVersion = String.Join(".", reply.Value.ConfigVersion);
string subnetMask = String.Join(".", reply.Value.SubnetMask);
string gateway = String.Join(".", reply.Value.Gateway);
if (true)
//if (exitEntity.HostNumber != hostNumber)
{
exitEntity.HostNumber = hostNumber;
isChanged = true;
sbSQL.Append(",HostNumber='" + exitEntity.HostNumber + "'");
}
//if (exitEntity.Version != version)
if (true)
{
exitEntity.Version = version;
isChanged = true;
sbSQL.Append(",Version='" + exitEntity.Version + "'");
}
if (true)
//if (exitEntity.ConfigVersion != configVersion)
{
exitEntity.ConfigVersion = configVersion;
isChanged = true;
BarData bbb = new BarData();
bbb.HostID = exitEntity.ID;
string output = NormalizeVersion(exitEntity.ConfigVersion); // 输出 "15.0.0"
bbb.ConfiguraVersion = output;
UploadCurrentVersionReceiver.UP_Grade_Json(exitEntity, bbb);
sbSQL.Append(",ConfigVersion='" + exitEntity.ConfigVersion + "'");
}
//if (exitEntity.SubnetMask != subnetMask)
if (true)
{
exitEntity.SubnetMask = subnetMask;
isChanged = true;
sbSQL.Append(",SubnetMask='" + exitEntity.SubnetMask + "'");
}
//if (exitEntity.Gateway != gateway)
if (true)
{
exitEntity.Gateway = gateway;
isChanged = true;
sbSQL.Append(",Gateway='" + exitEntity.Gateway + "'");
}
//if (exitEntity.Remark != hotelCode)
if (true)
{
exitEntity.Remark = hotelCode;
isChanged = true;
sbSQL.Append(",Remark='" + exitEntity.Remark + "'");
}
if (isChanged)
{
exitEntity.Last_Modified_Time = DateTime.Now;//标识有更新
sbSQL.Append(",Last_Modified_Time=GETDATE()");
}
//if (exitEntity.IP != ip)
if (true)
{
exitEntity.IP = ip;
isChanged = true;
sbSQL.Append(",IP='" + exitEntity.IP + "'");
}
if (true)
//if (exitEntity.Port != port)
{
exitEntity.Port = port;
isChanged = true;
sbSQL.Append(",Port=" + exitEntity.Port);
}
//Host hostTemp = HostRepository.Get(exitEntity.ID);//重新获取主机最新升级更新状态数据
//exitEntity.UpgradeStatus = hostTemp.UpgradeStatus;
//exitEntity.UpgradeTime = hostTemp.UpgradeTime;
if (isChanged)
{
exitEntity = GetDeviceSecret(exitEntity, ref sbSQL);//获取密钥
sbSQL.Append(" WHERE ID=" + exitEntity.ID);
//string RegisterKey1 = "SearchHostPass";
//string RegisterKey2 = "SearchHostFilter";
//暂时的取消
if (hotelCode.Equals("1197"))
{
HostRepository.Update(sbSQL.ToString());//更新主机用sql语句更新更高效
}
else
{
//string KKK = "RegisterKey_" + hhostnumber;
//object OOO = MemoryCacheHelper.Get(KKK);
//if (OOO != null)
//{
// RCUHost.RCUHostCommon.tools.LanJieData(RegisterKey2, hotelCode);
//}
//else
//{
// string ti = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// MemoryCacheHelper.Set(KKK, ti, DateTimeOffset.Now.AddMinutes(5));
// HostRepository.Update(sbSQL.ToString());//更新主机用sql语句更新更高效
// RCUHost.RCUHostCommon.tools.LanJieData(RegisterKey1, hotelCode);
//}
HostRepository.Update(sbSQL.ToString());//更新主机用sql语句更新更高效
//有升级的时候,不能被跳过
string Key = "Upgrade_UpdateSQL_" + exitEntity.HostNumber;
object OOO1 = MemoryCacheHelper.Get(Key);
if (OOO1 != null)
{
HostRepository.Update(sbSQL.ToString());//更新主机用sql语句更新更高效
MemoryCacheHelper.Delete(Key);
}
}
PublishDeviceSecret(exitEntity);//下发密钥
}
if (exitEntity.Version.StartsWith("C"))
{
CSRedisCacheHelper.Set(mac, exitEntity.IP + ":" + exitEntity.Port);//心跳包更新
string RegisterKey1 = "HostSearchReceiveDrop";
RCUHost.RCUHostCommon.tools.LanJieData(RegisterKey1, hotelCode);
//这里的功能暂时去掉
//这里会发送 B1 数据 一定 要注意
//B1不能被去掉
HostRegisterReceiver.Send(exitEntity);//通知同步工具
//logger.Error(string.Format("通知酒店({0})客房({1})同步主机信息。", exitEntity.SysHotel.Code, exitEntity.RoomNumber));
}
string HKey1 = CacheKey.HostInfo_Key_MAC + hotelCode + "_" + mac;
string HKey = CacheKey.HostInfo_Key_HostNumber + "_" + hostNumber;
object takeout_obj = MemoryCacheHelper.Get(HKey);
if (takeout_obj == null)
{
MemoryCacheHelper.SlideSet(HKey, exitEntity);
MemoryCacheHelper.SlideSet(HKey1, exitEntity);
}
string YiJingChuLiGuo = CacheKey.AllReadyDealWith01_Prefix + "_" + hostNumber;
MemoryCacheHelper.Set(YiJingChuLiGuo, A1, DateTimeOffset.Now.AddMinutes(5));
StepTongJi.SendInfo(5, "注册命令Task内部执行完毕", context.MessageID, context.IsMonitor);
}
catch (Exception ex)
{
logger.Error(string.Format("终端注册失败,来自:{0},原因:{1},数据:{2}", context.RemoteEndPoint.Address.ToString(), ex.ToString(), Tools.ByteToString(context.Data)));
}
}
}
public static string NormalizeVersion(string version, int desiredParts = 3)
{
// 移除末尾的冗余点并分割
var parts = version.TrimEnd('.').Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
// 补零到目标位数
while (parts.Length < desiredParts)
{
parts = parts.Concat(new[] { "0" }).ToArray();
}
return string.Join(".", parts);
}
/// <summary>
/// 获取主机设备密钥
/// </summary>
/// <param name="host"></param>
/// <returns></returns>
private Host GetDeviceSecret(Host host, ref StringBuilder sbSQL)
{
//如果所属酒店需要自动获取密钥,且目前密钥是空,则自动获取
if (host.SysHotel.IsAutoGetKey && string.IsNullOrEmpty(host.DeviceSecret))
{
DeviceRegisterResult resultData = FreeGoOperation.DeviceRegister(host.MAC);
if (resultData.errcode == "0")
{
host.DeviceName = resultData.device_name;
sbSQL.Append(",DeviceName='" + host.DeviceName + "'");
host.DeviceSecret = resultData.device_secret;
sbSQL.Append(",DeviceSecret='" + host.DeviceSecret + "'");
host.IotId = resultData.iot_id;
sbSQL.Append(",IotId='" + host.IotId + "'");
host.ProductKey = resultData.product_key;
sbSQL.Append(",ProductKey='" + host.ProductKey + "'");
host.IsPublish = false;
sbSQL.Append(",IsPublish=0");
}
else
{
logger.Error(string.Format("调用FreeGo接口返回错误RoomNumber:{0},ErrorCode:{1},ErrorMessage:{2}", host.RoomNumber, resultData.errcode, resultData.msg));
}
}
return host;
}
/// <summary>
/// 下发设备密钥
/// </summary>
/// <param name="host"></param>
private void PublishDeviceSecret(Host host)
{
if (!host.IsPublish && !string.IsNullOrEmpty(host.DeviceSecret))
{
DeviceSecretReceiver.Send(host);
HostRepository.SetPublish(host, true);
}
}
/// <summary>
/// 创建新回路
/// </summary>
/// <param name="host"></param>
/// <returns></returns>
private bool UpdateHostModals(Host host)
{
if (host == null)
{
return false;
}
HostModalRepository.DeteleByHostID(host.ID);
var list = RoomTypeModalRepository.LoadAll().Where(r => r.RoomType == host.RoomType);
DateTime now = DateTime.Now;
foreach (var modal in list)
{
HostModalRepository.Save(new HostModal { HostID = host.ID, Modal = modal, Status = 2, Time = 0, UpdateTime = now });
}
return true;
}
public override CommandType CommandType
{
get { return CommandType.SearchHost; }
}
#region Private Methods
private byte[] CreateSearchHostRequestPacket()
{
SystemHeader systemHeader = CreateSystemHeader();
SearchHostPacket searchHostPacket = CreateSearchHostPacket();
int size = StructConverter.SizeOf(systemHeader) + StructConverter.SizeOf(searchHostPacket);
systemHeader.FrameLength = (ushort)size;
byte[] buffer = new byte[size];
byte[] src1 = StructConverter.StructToBytes(systemHeader);
Array.Copy(src1, 0, buffer, 0, src1.Length);
byte[] src3 = StructConverter.StructToBytes(searchHostPacket);
Array.Copy(src3, 0, buffer, src1.Length, src3.Length);
return buffer;
}
private SearchHostPacket CreateSearchHostPacket()
{
#if DEBUG
var ip = Tools.GetLocalIP();
#else
var ip = MessageIP;
#endif
SearchHostPacket packet = new SearchHostPacket
{
IsSave = 1,
IP = IPAddress.Parse(ip).GetAddressBytes(),
Port = Convert.ToUInt16(MessagePort)
};
return packet;
}
/// <summary>
/// 解码 SearchHostPacketReply
/// </summary>
/// <param name="data"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
private SearchHostPacketReply? DecodeSearchHostPacketReply(byte[] data, int startIndex)
{
return StructConverter.BytesToStruct(data, startIndex, typeof(SearchHostPacketReply)) as SearchHostPacketReply?;
}
private SearchHostPacketReplyV2? DecodeSearchHostPacketReplyV2(byte[] data, int startIndex)
{
return StructConverter.BytesToStruct(data, startIndex, typeof(SearchHostPacketReplyV2)) as SearchHostPacketReplyV2?;
}
#endregion
}
}