经过与大华技术支持的沟通,门禁服务程序已经开发好了,可以正常接收门禁开关事件,可以发送开门命令。基于项目实时性要求,这里使用SignalR实现门禁状态、控制命令的实时传送。
根据SignalR的设计规则,Client端可以主动调用服务端Hub的多个方法,但是客户端被动接收消息的方法只能有一个。
根据门禁功能需求,我们将Client分为两组:
这样便于服务端区分Web客户端和门禁服务端这两类client。
项目中主要实现以下几个场景:
//web客户端
chat.server.sendMessageByBrowser();
// 定义AddMessage供服务器调用
chat.client.AddMessage = function (result) {
for (var i = 0; i < result.length; i++) {
try {
//前端响应门禁状态变化
} catch (error) {
}
}
};
//web服务端
/// <summary>
/// 浏览器发送消息,向doorServer请求所有门禁状态,用于初始化门禁状态
/// </summary>
/// <param name="name"></param>
public void SendMessageByBrowser()
{
var messageList = new List<DoorStateInfo>();
var dc = new DoorStateInfo {ConnectId = Context.ConnectionId};
messageList.Add(dc);
Clients.Group("doorserver").AddMessage(messageList);
}
/// <summary>
/// 门禁服务发送多条开关门消息给某个浏览器,hubserver转发给浏览器
/// 浏览器id放在messagelist[0].ConnectId
/// </summary>
/// <param name="name"></param>
/// <param name="messageList"></param>
public void SendManyMessageByDoorServer(string name, List<DoorStateInfo> messageList)
{
Clients.Client(messageList[0].ConnectId).AddMessage(messageList);
}
//门禁服务端
// 创建一个集线器代理对象
HubProxy = Connection.CreateHubProxy("DoorAlarmHub");
// 供服务端调用,将消息输出到消息列表框中
HubProxy.On<string, List<DoorStateInfo>>("AddMessage", (message) =>
{
var alarmMsg = new AlarmMsg
{
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
AlarmInfo = message,
AlarmType = EM_ALARM_TYPE.ALARM_SIGNALR_QUERY
};
if (message != null && message.Count > 0)
{
//无门禁状态,为门禁查询命令
if (message[0].DoorState == EM_NET_DOOR_STATUS_TYPE.EM_NET_DOOR_STATUS_UNKNOWN)
{
alarmMsg.AlarmType = EM_ALARM_TYPE.ALARM_SIGNALR_QUERY;
}
//有门禁状态,为门禁控制命令
else
{
alarmMsg.AlarmType = EM_ALARM_TYPE.ALARM_SIGNALR_CONTROL;
}
m_AlarmMsgQueue.Enqueue(alarmMsg);
}
});
//web服务端
/// <summary>
/// 浏览器端调用,请求开门
/// </summary>
public void SendOpenDoorByBrowser(/*业务参数用于标识门禁*/)
{
var messageList = new List<DoorStateInfo>();
//业务处理
...
Clients.Group("doorserver").AddMessage("doorserver", messageList);
}
/// <summary>
/// 门禁服务发送开关门消息,hubserver转发给浏览器
/// </summary>
/// <param name="name"></param>
/// <param name="message"></param>
public void SendOneMessageByDoorServer(string name, DoorStateInfo message)
{
//业务处理
Clients.Group("doorclient").AddMessage(message);
}
客户端使用AddMessage
接收server转发来的消息,由于client监听接收消息只能有一个方法,但是存在单个门禁状态变化消息和多个两种情况。因此AddMessage
的消息参数统一使用List<Message>
,然后在server端转发时相应加入业务标记,便于client端处理。
门禁服务程序采用事件机制
原文:https://www.cnblogs.com/zhangdk/p/SignalR.html