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; /// /// 当前搜索主机用户 /// 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 = ""; } /// /// 修改协议:原来的搜索改成注册,当mac地址已存在时,更新数据,否则插入新主机 /// /// 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(() => 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); } /// /// 获取主机设备密钥 /// /// /// 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; } /// /// 下发设备密钥 /// /// private void PublishDeviceSecret(Host host) { if (!host.IsPublish && !string.IsNullOrEmpty(host.DeviceSecret)) { DeviceSecretReceiver.Send(host); HostRepository.SetPublish(host, true); } } /// /// 创建新回路 /// /// /// 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; } /// /// 解码 SearchHostPacketReply /// /// /// /// 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 } }