1. 程式人生 > >大華門禁SDK二次開發(二)

大華門禁SDK二次開發(二)

經過與大華技術支援的溝通,門禁服務程式已經開發好了,可以正常接收門禁開關事件,可以傳送開門命令。基於專案實時性要求,這裡使用SignalR實現門禁狀態、控制命令的實時傳送。

幾種場景需求

根據SignalR的設計規則,Client端可以主動呼叫服務端Hub的多個方法,但是客戶端被動接收訊息的方法只能有一個
根據門禁功能需求,我們將Client分為兩組:

  • doorclient:指Web客戶端
  • doorserver:指門禁服務端

這樣便於服務端區分Web客戶端和門禁服務端這兩類client。

image

專案中主要實現以下幾個場景:

Web客戶端初始載入,重新整理全部門禁狀態

image

  • 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端請求開啟某個門

image

  • 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);            
}

門禁服務傳送門禁狀態變化

image

  • A.這種情況主要發生在門禁刷卡等開門操作,引起的門禁狀態變化,門禁服務接收到訊息後,主動傳送門禁狀態變化資訊;
  • B.web服務端接收資訊,並轉發到doorclient組。

幾個問題說明

AddMessage方法

客戶端使用AddMessage接收server轉發來的訊息,由於client監聽接收訊息只能有一個方法,但是存在單個門禁狀態變化訊息和多個兩種情況。因此AddMessage的訊息引數統一使用List<Message>,然後在server端轉發時相應加入業務標記,便於client端處理。

門禁服務程式的事件機制

門禁服務程式採用事件機制

  • 刷卡等開發事件接收到後,門禁服務會主動進行訊息傳送,通知所有瀏覽器更新相應門禁狀態;
  • 瀏覽器初始化請求所有門禁狀態時,由於訊息通訊是不能直接返回的,因此資訊傳遞時攜帶connectId,用於下一條訊息確認傳送物件;
  • 與初始化請求一樣,瀏覽器傳送開門命令後,門禁服務接收到開門命令傳送給大華門禁伺服器後,會在收到門禁狀態變化事件時,向doorclient組傳送訊息。兩條訊息是相對獨立的。