基於abp的小小設備控制系統設計
- 2020 年 9 月 16 日
- 筆記
- Asp.Net Core, IoT
客戶有一堆小設備,需要通過小程式來控制它們,主要是設備門的開關、電源開關、狀態查詢、壓力控制等。下面主要紀錄下設計思路。源碼地址://gitee.com/bxjg1987/abp
最初的設計是這樣的
核心流程有3個,分別用綠、藍、黑這3種顏色來標識。
流程1:小程式端發送指令控制設備(開關、艙壓調整等)
以開關電源控制為例
- 小程式向wei服務端發起請求,說我想關閉設備id為1的那個設備
- wei服務端準備一條消息(說我要關閉id為1的那個設備),發送給RabbitMQ消息隊列
- RabbitMQ消息隊列將消息推送給硬體伺服器
- 硬體伺服器解析消息,根據設備id和按協議約定準備byte[]指令下發給具體設備
- 設備回復消息給硬體伺服器
- 硬體伺服器組織一條回復消息(所id為1的設備已經關閉成功)發送給RabbitMQ消息隊列
- 消息隊列將回復消息推送給web服務端
- web服務端通過abp提供的通知功能(默認基於a’s’p.net core signalr)通知小程式端,
此時小程式端開源認為操作成功,但是不是太準確,另一種辦法是小程式再查一次設備狀態確認下。所以上面的步驟5可以向設備觸發一個請求,讓設備立即上報一次數據。默認情況下設備是輪詢的比如30秒上報一次數據。
流程2:設備輪詢30秒上報一次數據
- 設備上報狀態數據
- 硬體伺服器將設備狀態數據存儲到資料庫
- 硬體伺服器向RabbitMQ消息隊列發送一條消息,說設備id為x的設備上報了狀態數據
- RabbitMQ消息隊列將消息推送給web服務端
- web服務端通過abp提供的通知機制通知小程式端
步驟3沒必要直接將狀態數據推送給消息隊列,因為此消息的接收方未必關係具體的數據,目前設計只是說有設備狀態上報了,這個消息通知到接收方,由接收方決定是否主動來查設備狀態
流程3:小程式主動查詢設備狀態
這個就比較簡單了
- 小程式端向web服務端發起查詢請求
- web伺服器直接從資料庫查詢設備狀態返回就可以了
有點問題,這樣查詢不是設備的當前狀態,我們可以再定義介面直接去查一次當前設備的狀態,但是這樣編碼比較大,也不利於我們復用現有流程。最簡單的辦法是定義一個介面,向設備發送一條指令說請你立即上報一次數據,小程式原有的查詢設備狀態查到就是最新的了。
設備服務端SuperSocket
開源地址://github.com/kerryjiang/SuperSocket,這是個設計得比較好的,基於.net core的socket的通訊框架。官方有文檔學起來比較簡單。
它負責與設備通訊,可以單獨部署在一台伺服器上。
基於Abp的Web服務端
這就不多說了,因為它已經為我們提供了很好的web服務端基礎設施,免得從頭做起。此服務端也可以單獨部署一台伺服器
消息隊列RabbitMQ
其它mq沒用過,就用它咯。它主要是解耦設備服務端和web服務端的,主要是它可以主動推送消息給接收方,也可以考慮使用redis的推送來實現。消息隊列也可以單獨部署一台伺服器
簡化後的設計
如果設備比較少,請求量不大可以用下面這種簡化的設計
既然是簡化,流程就不說了。主要是省略了消息隊列,並且省略了指令回復的處理,而是使用輪詢的方式,比如每過10秒查一次當前設備狀態,控制設備時,只是下髮指令,而不等結果,因為我們的輪詢會查到下一次的設備狀態。
這裡有些注意:
- 設備上報狀態存入資料庫時可以使用一個全局的資料庫連接
- web伺服器向設備伺服器發送指令時也可以考慮使用全局的tcp連接
- web伺服器向設備伺服器發送指令時可以使用supersocket提供的客戶端庫
結束
簡化後的方案最low,但是也最容易實現,目前源碼中就是採用的這種方式。前一種方式稍微好點,3台伺服器可以分開部署,如果並發再大點可以考慮下分散式了,再不行就放棄這個上思路,直接上個阿里雲IOT啥的。