門禁服務程式已經調試完成,基於項目實時性要求,使用SignalR實現門禁狀態實時獲取和控制。 ...
經過與大華技術支持的溝通,門禁服務程式已經開發好了,可以正常接收門禁開關事件,可以發送開門命令。基於項目實時性要求,這裡使用SignalR實現門禁狀態、控制命令的實時傳送。
幾種場景需求
根據SignalR的設計規則,Client端可以主動調用服務端Hub的多個方法,但是客戶端被動接收消息的方法只能有一個。
根據門禁功能需求,我們將Client分為兩組:
- doorclient:指Web客戶端
- doorserver:指門禁服務端
這樣便於服務端區分Web客戶端和門禁服務端這兩類client。
項目中主要實現以下幾個場景:
Web客戶端初始載入,刷新全部門禁狀態
- A. 瀏覽器主動請求初始化門禁狀態;
- B. web服務端接收信息,並轉發到doorserver組;
- C. 門禁服務查詢門禁狀態,主動發送門禁狀態列表;
- D. web服務端接收消息,並根據connectId轉發給指定瀏覽器。
//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端請求打開某個門
- A. 瀏覽器主動請求開門;
- B. web服務端接收信息,並轉發到doorserver組;
- C. 門禁服務發送開門命令,接收到門禁狀態變化消息後,主動發送門禁狀態變化信息;
- D. web服務端接收信息,並轉發到doorclient組。
//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);
}
門禁服務發送門禁狀態變化
- A.這種情況主要發生在門禁刷卡等開門操作,引起的門禁狀態變化,門禁服務接收到消息後,主動發送門禁狀態變化信息;
- B.web服務端接收信息,並轉發到doorclient組。
幾個問題說明
AddMessage方法
客戶端使用AddMessage
接收server轉發來的消息,由於client監聽接收消息只能有一個方法,但是存在單個門禁狀態變化消息和多個兩種情況。因此AddMessage
的消息參數統一使用List<Message>
,然後在server端轉發時相應加入業務標記,便於client端處理。
門禁服務程式的事件機制
門禁服務程式採用事件機制
- 刷卡等開發事件接收到後,門禁服務會主動進行消息發送,通知所有瀏覽器更新相應門禁狀態;
- 瀏覽器初始化請求所有門禁狀態時,由於消息通信是不能直接返回的,因此信息傳遞時攜帶connectId,用於下一條消息確認發送對象;
- 與初始化請求一樣,瀏覽器發送開門命令後,門禁服務接收到開門命令發送給大華門禁伺服器後,會在收到門禁狀態變化事件時,向doorclient組發送消息。兩條消息是相對獨立的。