399 lines
15 KiB
C#
399 lines
15 KiB
C#
|
|
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<string, ConcurrentDictionary<int, ServiceStatus>> roomsServices = new ConcurrentDictionary<string, ConcurrentDictionary<int, ServiceStatus>>();
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 处理服务
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="host"></param>
|
|||
|
|
/// <param name="status"></param>
|
|||
|
|
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());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 处理异常
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="host"></param>
|
|||
|
|
/// <param name="status"></param>
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建服务控制数据包
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="devices"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 解析服务状态
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="stream"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private ConcurrentDictionary<int, ServiceStatus> DecodeServices(string hostIP, Stream stream)
|
|||
|
|
{
|
|||
|
|
ConcurrentDictionary<int, ServiceStatus> services = null;
|
|||
|
|
if (roomsServices.ContainsKey(hostIP))
|
|||
|
|
{
|
|||
|
|
services = roomsServices[hostIP];
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
services = new ConcurrentDictionary<int, ServiceStatus>();
|
|||
|
|
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<ServiceStatus> Services
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
IList<ServiceStatus> values = new List<ServiceStatus>();
|
|||
|
|
|
|||
|
|
foreach (var service in services.Values)
|
|||
|
|
{
|
|||
|
|
values.Add((ServiceStatus)service);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return values;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void RasieServiceChanged(ServiceStatus serviceStatus)
|
|||
|
|
{
|
|||
|
|
if (ServiceChanged != null)
|
|||
|
|
{
|
|||
|
|
ServiceChanged(HostIP, serviceStatus);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|