using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Common; using Dao; using Domain; using RCUHost.Protocols; namespace RCUHost.Implement { public class ServiceReceiver : GenericReceiverBase, IServiceReceiver { private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(ServiceReceiver)); private ConcurrentDictionary> roomsServices = new ConcurrentDictionary>(); public IHostRepository HostRepository { get; set; } public IAlarmSettingRepository AlarmSettingRepository { get; set; } public IRoomServiceRepository RoomServiceRepository { get; set; } public IRoomServiceRecordRepository RoomServiceRecordRepository { get; set; } public void SetService(Host host, int serviceCode, int status) { byte[] data = CreateServiceControlDataPacket(serviceCode, status); SendAndPushCommandQueue(data, host.HostNumber, host.MAC);// host.IP, host.Port); } public override void Process(ReceiverContext context) { bool bkb = GenericReceiverBase.DealWwith(context); if (bkb == false) { return; } Reply(context); Host host = HostRepository.GetByHostNumber(context.SystemHeader.Value.HostNumber.ToString());//.RemoteEndPoint.Address.ToString()); if (host != null) { try { int offset = StructConverter.SizeOf(context.SystemHeader); int length = context.Data.Length - offset - 2; using (MemoryStream stream = new MemoryStream(context.Data, offset, length)) { var services = DecodeServices(host.IP, stream); foreach (var service in services) { if (service.Value.Status != 2) { //处理服务 ProcessServices(host, service.Value); //设置Host表的保险箱状态 if (service.Value.Code == 12) { HostRepository.SetSafeBoxStatus(host, service.Value.Status); } //处理异常 ProcessAbnormities(host, service.Value); } } } } catch (Exception ex) { if (logger.IsErrorEnabled) { logger.Error(context.RemoteEndPoint.Address.ToString() + ":" + context.RemoteEndPoint.Port.ToString() + ":" + Tools.ByteToString(context.Data)); logger.Error("解析【" + host.HostNumber + "】客房服务数据出错。", ex); } } } } /// /// 处理服务 /// /// /// private void ProcessServices(Host host, ServiceStatus status) { var serviceSetting = AlarmSettingRepository.Get(host.SysHotel.ID, 'B', status.Code); if (serviceSetting != null && status.Status != 2) { //更新客房服务状态 var roomService = RoomServiceRepository.Get(host.ID, serviceSetting.Code); if (roomService != null && roomService.Status != Convert.ToBoolean(status.Status)) { roomService.Status = Convert.ToBoolean(status.Status); roomService.StartTime = DateTime.Now; RoomServiceRepository.Update(roomService); } if (status.Status == 0) { //更新清除服务记录状态和时间 var serviceRecord = RoomServiceRecordRepository.Get(host.ID, serviceSetting.Code, true); if (serviceRecord != null) { serviceRecord.Status = false; serviceRecord.EndTime = DateTime.Now; RoomServiceRecordRepository.Update(serviceRecord); } } else if (status.Status == 1) { //判断数据库中是否存在服务开启记录,不存在才去记录服务 var existServiceRecord = RoomServiceRecordRepository.Get(host.ID, serviceSetting.Code, true); if (existServiceRecord == null) { var serviceRecord = new RoomServiceRecord(); serviceRecord.HostID = host.ID; serviceRecord.RoomNumber = host.RoomNumber; serviceRecord.AlarmCode = serviceSetting.Code; serviceRecord.Name = serviceSetting.Name; serviceRecord.Status = true; serviceRecord.StartTime = DateTime.Now; RoomServiceRecordRepository.Save(serviceRecord); } } //给FreeGo(福瑞狗)上报服务状态 //FreeGoOperation.UploadService(host.SysHotel.Code, host.RoomNumber, serviceSetting.Name, status.Status.ToString()); } } /// /// 处理异常 /// /// /// private void ProcessAbnormities(Host host, ServiceStatus status) { #region 处理“非客人在保险箱开”异常 var abnormitySetting = AlarmSettingRepository.Get(host.SysHotel.ID, 'C', "C03", status.Code); if (abnormitySetting != null) { var abnormity = RoomServiceRepository.Get(host.ID, abnormitySetting.Code); bool isUpdated = false; if (status.Status == 1) { //保险箱开 如果非客人卡且出租房态,则报警 if (host.RoomCard != null && host.RoomCard.RoomCardType != null && host.RoomCard.RoomCardType.ID != 0x20 && host.RoomStatus != null && host.RoomStatus.ID == 0x02) { isUpdated = true; if (abnormity != null && !abnormity.Status) { abnormity.Status = true; abnormity.StartTime = DateTime.Now; RoomServiceRepository.Update(abnormity); //插入保险箱开的记录 var abnormityRecord = RoomServiceRecordRepository.Get(host.ID, abnormitySetting.Code, true); if (abnormityRecord == null) { abnormityRecord = RoomServiceRecordRepository.CreateServiceRecord(host, abnormitySetting); RoomServiceRecordRepository.Save(abnormityRecord); } } } } //保险箱关或未接保险箱(关掉报警) if (!isUpdated) { if (abnormity != null && abnormity.Status) { abnormity.Status = false;//取消报警 abnormity.StartTime = DateTime.Now; RoomServiceRepository.Update(abnormity); //更新保险箱关的记录 var abnormityRecord = RoomServiceRecordRepository.Get(host.ID, abnormitySetting.Code, true); if (abnormityRecord != null) { abnormityRecord.Status = false; abnormityRecord.EndTime = DateTime.Now; RoomServiceRecordRepository.Update(abnormityRecord); } } } } #endregion #region 处理“退房保险箱关”异常 abnormitySetting = AlarmSettingRepository.Get(host.SysHotel.ID, 'C', "C04", status.Code); var abnormity1 = RoomServiceRepository.Get(host.ID, "C04"); if (abnormitySetting != null && abnormity1 != null) { bool isUpdated = false; if (status.Status == 0) { //保险箱关 如果是“退房”状态,则报警 if (host.RoomStatus != null && host.RoomStatus.ID == 0x08) { isUpdated = true; if (!abnormity1.Status) { abnormity1.Status = true; abnormity1.StartTime = DateTime.Now; RoomServiceRepository.Update(abnormity1); //异常记录 var abnormityRecord = RoomServiceRecordRepository.Get(host.ID, abnormitySetting.Code, true); if (abnormityRecord == null) { abnormityRecord = RoomServiceRecordRepository.CreateServiceRecord(host, abnormitySetting); RoomServiceRecordRepository.Save(abnormityRecord); } } } } if (!isUpdated) { //保险箱开或未接保险箱(关掉报警) if (abnormity1.Status) { abnormity1.Status = false; abnormity1.StartTime = DateTime.Now; RoomServiceRepository.Update(abnormity1); //异常记录 var abnormityRecord = RoomServiceRecordRepository.Get(host.ID, abnormitySetting.Code, true); if (abnormityRecord != null) { abnormityRecord.Status = false; abnormityRecord.EndTime = DateTime.Now; RoomServiceRecordRepository.Update(abnormityRecord); } } } } #endregion } /// /// 创建服务控制数据包 /// /// /// public byte[] CreateServiceControlDataPacket(int serviceCode, int status) { using (MemoryStream buffer = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(buffer)) { var headerLen = StructConverter.SizeOf(typeof(SystemHeader)); buffer.Seek(headerLen, SeekOrigin.Begin); writer.Write((byte)1); //写入服务数量 writer.Write((byte)serviceCode); //写入服务代码 writer.Write((byte)status); //写入服务状态 writer.Write(new byte[] { 0, 0 }, 0, 2);//预留两字节CRC16校验码 buffer.Seek(0, SeekOrigin.Begin); var header = CreateSystemHeader((int)buffer.Length - headerLen); var headerData = StructConverter.StructToBytes(header); writer.Write(headerData, 0, headerData.Length); return buffer.ToArray(); } } } public override CommandType CommandType { get { return CommandType.Service; } } /// /// 解析服务状态 /// /// /// private ConcurrentDictionary DecodeServices(string hostIP, Stream stream) { ConcurrentDictionary services = null; if (roomsServices.ContainsKey(hostIP)) { services = roomsServices[hostIP]; } else { services = new ConcurrentDictionary(); roomsServices[hostIP] = services; } using (BinaryReader reader = new BinaryReader(stream)) { try { int count = reader.ReadByte();//读取服务数量 for (int i = 0; i < count; i++) { ServiceStatus serviceStatus = null; int serviceCode = reader.ReadByte();//读取服务代码 if (services.ContainsKey(serviceCode)) { serviceStatus = services[serviceCode]; } else { serviceStatus = new ServiceStatus(); services[serviceCode] = serviceStatus; } serviceStatus.Code = serviceCode; serviceStatus.Status = reader.ReadByte();//读取服务状态 } } catch (Exception) { } return services; } } } internal class ServiceStatus { private int code; private int status = 2; public int Code { get { return this.code; } set { this.code = value; } } public int Status { get { return this.status; } set { this.status = value; } } } internal delegate void ServiceChangedDelegate(string hostIP, ServiceStatus serviceStatus); internal class RoomServiceCache { private Hashtable services = new Hashtable(); public string HostIP { get; set; } public event ServiceChangedDelegate ServiceChanged; public void AddOrUpdate(int code, int status) { ServiceStatus service = services[code] as ServiceStatus; if (service != null) { if (service.Status != status) { service.Status = status; RasieServiceChanged(service); } } else { service = new ServiceStatus(); service.Code = code; service.Status = status; services[code] = service; RasieServiceChanged(service); } } public IList Services { get { IList values = new List(); foreach (var service in services.Values) { values.Add((ServiceStatus)service); } return values; } } private void RasieServiceChanged(ServiceStatus serviceStatus) { if (ServiceChanged != null) { ServiceChanged(HostIP, serviceStatus); } } } }