《連載 | 物聯網框架ServerSuperIO教程》- 6.併發通訊模式開發及注意事項
目 錄
6. 併發通訊模式開發及注意事項... 2
6.1 概述... 2
6.2 通訊機制說明... 2
6.3 裝置驅動開發注意事項... 3
6.3.1 實時傳送資料... 3
6.3.2 優先發送其他資料... 3
6.3.3 如何選擇IO通道傳送資料... 4
6.3.4 如何以DeviceCode分配資料... 4
6.4 宿主程式服務例項配置注意事項... 5
6.5 併發模式執行效果... 6
6. 併發通訊模式開發及注意事項
6.1 概述
併發通訊模式只能用於網路通訊裝置,主要是加強通訊的併發能力,集中傳送請求資料,非同步接收返回資料。集中傳送請求資料的間隔時間可以設定;非同步接收返回資料涉及到如何分配資料到相應的裝置驅動的問題,主要是通過兩種方式:IP地址的方式和裝置Code的方式,前者適用於裝置終端是固定IP地址的情況,後者適用於裝置終端是動態IP的情況,例如:DTU、GPRS、3G/4G等無線通訊方式。
併發通訊模式本質上還是呼叫應答的通訊方式,與輪詢通訊模式類似,但是比輪詢通訊模式的採集資料更高效。
6.2 通訊機制說明
網路通訊的情況下,輪詢模式顯然效率比較低,那麼可以採用併發模式。併發通訊模式是集中傳送給所有裝置請求指令,框架是採用迴圈同步方式傳送請求命令給每個IO通道對應的裝置,當然也可以採用並行非同步方式集中傳送請求命令。硬體裝置接收到指令後進行校驗,校驗成功後返回對應指令的資料,通訊平臺非同步監聽到資料資訊後,進行接收操作,然後再進行資料的分發、處理等。
那麼這裡就涉及到IO通道接收到的資料是非同步接收的,如何才能和裝置驅動匹配上(把資料分發到裝置驅動上),這是能過DeviceCode和DeviceIP兩種方式來實現的。DeviceCode可以是裝置地址或是裝置編碼,DeviceIP是預先設定好的引數,要求終端裝置的IP地址是固定的。
通訊結構如下圖:
`
6.3 裝置驅動開發注意事項
6.3.1 實時傳送資料
ServerSuperIO框架會輪詢排程所有裝置,以呼叫應答的方式向裝置傳送請求實時資料命令,對於同一個裝置的請求實時資料命令一般相對固定。在排程某一具體裝置驅動的時候,會呼叫固定的呼叫IRunDevice驅動介面的GetConstantCommand函式,以獲得請求實時資料的命令。程式碼如下:
public override byte[] GetConstantCommand() { byte[] data = this.Protocol.DriverPackage<String>("0", "61", null); string hexs = BinaryUtil.ByteToHex(data); OnDeviceRuningLog("傳送>>"+hexs); return data; }
this.Protocol.DriverPackage驅動呼叫61命令獲得要傳送的命令,並返回byte[]陣列,ServerSuperIO獲得資料後會自動通過IO介面下發命令資料。如果返回null型別,系統不進行下發操作。
6.3.2 優先發送其他資料
對於一個裝置不可能只有一個讀實時資料的命令,可能還存在其他命令進行互動,例如:讀引數、實時校準等,這時就需要進行優先順序排程傳送資料資訊。可以通過兩種方式讓ServerSuperIO框架優先排程該裝置驅動。
- 把命令增加發送資料快取中,框架從快取中獲得資料後會自動刪除,程式碼如下:
this.Protocol.SendCache.Add("讀引數",readParaBytes);
2.設定裝置的優先級別屬性,程式碼如下:
this.DevicePriority=DevicePriority.Priority;
6.3.3 如何選擇IO通道傳送資料
集中傳送資料時,涉及到如何關聯裝置驅動與IO通道,框架會以DeviceParameter.NET.RemoteIP設定的終端IP引數進行選擇IO通道傳送資料。但是如果終端裝置是動態IP地址的話,那麼RemoteIP引數也應該是變動的。這時就需要設定服務例項是以DeviceCode的方式分佈資料到裝置驅動,終端裝置先發送簡單的驗證資料,保證傳送的DeviceCode與裝置驅動的相對應,裝置驅動接收到驗證資料後需要儲存臨時的RemoteIP資訊,這樣保證在傳送資料的時候引數準確找到要請求資料的IO通道到終端裝置。
例如下面程式碼:
public override void Communicate(ServerSuperIO.Communicate.IRequestInfo info) { this.DeviceParameter.NET.RemoteIP = info.Channel.Key; this.DeviceParameter.Save(this.DeviceParameter); …… }
6.3.4 如何以DeviceCode分配資料
如果服務例項設定以DeliveryMode.DeviceCode模式分配資料,那麼就需要在通訊協議接口裡實現過濾DeviceCode編碼的介面。
例如下面的程式碼:
internal class DeviceProtocol:ProtocolDriver { public override string GetCode(byte[] data) { byte[] head = new byte[] {0x55, 0xaa}; int codeIndex = data.Mark(0, data.Length, head); if (codeIndex == -1) { return String.Empty; } else { return data[codeIndex + head.Length].ToString(); } } }
6.4 宿主程式服務例項配置注意事項
在宿主程式中建立服務例項的時候,需要把服務例項的配置引數設定為併發通訊模式,並啟動服務例項,把例項化的裝置驅動增加到該服務例項中。程式碼如下:
static void Main(string[] args) { IServer server = new ServerFactory().CreateServer(new ServerConfig() { ServerName = "服務1", ComReadTimeout = 1000, ComWriteTimeout = 1000, NetReceiveTimeout = 1000, NetSendTimeout = 1000, ControlMode = ControlMode.Parallel, SocketMode = SocketMode.Tcp, StartReceiveDataFliter = false, ClearSocketSession = false, StartCheckPackageLength = false, CheckSameSocketSession = false, DeliveryMode = DeliveryMode.DeviceCode, ParallelInterval = 1000 }); server.AddDeviceCompleted += server_AddDeviceCompleted; server.DeleteDeviceCompleted += server_DeleteDeviceCompleted; server.Start(); string devCode = "0"; DeviceDriver dev1 = new DeviceDriver(); dev1.DeviceParameter.DeviceName = "裝置驅動"+ devCode.ToString(); dev1.DeviceParameter.DeviceAddr = int.Parse(devCode); dev1.DeviceParameter.DeviceCode = devCode.ToString(); dev1.DeviceParameter.DeviceID = devCode.ToString(); dev1.DeviceDynamic.DeviceID = devCode.ToString(); dev1.DeviceParameter.NET.RemoteIP = "127.0.0.1"; dev1.DeviceParameter.NET.RemotePort = 9600; dev1.CommunicateType = CommunicateType.NET; dev1.Initialize(devCode.ToString()); server.AddDevice(dev1); devCode = "1"; DeviceDriver dev2 = new DeviceDriver(); dev2.DeviceParameter.DeviceName = "裝置驅動" + devCode.ToString(); dev2.DeviceParameter.DeviceAddr = int.Parse(devCode); dev2.DeviceParameter.DeviceCode = devCode.ToString(); dev2.DeviceParameter.DeviceID = devCode.ToString(); dev2.DeviceDynamic.DeviceID = devCode.ToString(); dev2.DeviceParameter.NET.RemoteIP = "192.168.1.102"; dev2.DeviceParameter.NET.RemotePort = 9600; dev2.CommunicateType = CommunicateType.NET; dev2.Initialize(devCode.ToString()); server.AddDevice(dev2); while ("exit" == Console.ReadLine()) { server.Stop(); } }
ControlMode = ControlMode. Parallel程式碼是設定服務例項排程裝置為併發控制模式;以DeliveryMode = DeliveryMode.DeviceCode方式進行資料分發,當然我現在模擬的是因定的終端IP。
6.5 併發模式執行效果
1.圖片
2.視訊
物聯網&整合技術(.NET) QQ群:54256083