Files

510 lines
23 KiB
C#
Raw Permalink Normal View History

2025-12-11 09:17:16 +08:00
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
}
}