1.C#跨平台物聯網通訊框架ServerSuperIO(SSIO)介紹
《連載 | 物聯網框架ServerSuperIO教程》1.4種通訊模式機制。
《連載 | 物聯網框架ServerSuperIO教程》2.服務實例的配置參數說明
《連載 | 物聯網框架ServerSuperIO教程》- 3.設備驅動介紹
《連載 | 物聯網框架ServerSuperIO教程》-4.如開發一套設備驅動,同時支持串口和網絡通訊。
《連載 | 物聯網框架ServerSuperIO教程》- 5.輪詢通訊模式開發及注意事項。
目 錄
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
並發通訊模式只能用於網絡通訊設備,主要是加強通訊的並發能力,集中發送請求數據,異步接收返回數據。集中發送請求數據的間隔時間可以設置;異步接收返回數據涉及到如何分配數據到相應的設備驅動的問題,主要是通過兩種方式:IP地址的方式和設備Code的方式,前者適用於設備終端是固定IP地址的情況,後者適用於設備終端是動態IP的情況,例如:DTU、GPRS、3G/4G等無線通訊方式。
並發通訊模式本質上還是呼叫應答的通訊方式,與輪詢通訊模式類似,但是比輪詢通訊模式的采集數據更高效。
網絡通訊的情況下,輪詢模式顯然效率比較低,那麼可以采用並發模式。並發通訊模式是集中發送給所有設備請求指令,框架是采用循環同步方式發送請求命令給每個IO通道對應的設備,當然也可以采用並行異步方式集中發送請求命令。硬件設備接收到指令後進行校驗,校驗成功後返回對應指令的數據,通訊平台異步監聽到數據信息後,進行接收操作,然後再進行數據的分發、處理等。
那麼這裡就涉及到IO通道接收到的數據是異步接收的,如何才能和設備驅動匹配上(把數據分發到設備驅動上),這是能過DeviceCode和DeviceIP兩種方式來實現的。DeviceCode可以是設備地址或是設備編碼,DeviceIP是預先設置好的參數,要求終端設備的IP地址是固定的。
通訊結構如下圖:
`
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類型,系統不進行下發操作。
對於一個設備不可能只有一個讀實時數據的命令,可能還存在其他命令進行交互,例如:讀參數、實時校准等,這時就需要進行優先級調度發送數據信息。可以通過兩種方式讓ServerSuperIO框架優先調度該設備驅動。
this.Protocol.SendCache.Add("讀參數",readParaBytes);
2.設置設備的優先級別屬性,代碼如下:
this.DevicePriority=DevicePriority.Priority;
集中發送數據時,涉及到如何關聯設備驅動與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); …… }
如果服務實例設置以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(); } } }
在宿主程序中創建服務實例的時候,需要把服務實例的配置參數設置為並發通訊模式,並啟動服務實例,把實例化的設備驅動增加到該服務實例中。代碼如下:
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。
1.圖片
2.視頻