1.C#跨平台物聯網通訊框架ServerSuperIO(SSIO)介紹
《連載 | 物聯網框架ServerSuperIO教程》1.4種通訊模式機制。
《連載 | 物聯網框架ServerSuperIO教程》2.服務實例的配置參數說明
《連載 | 物聯網框架ServerSuperIO教程》- 3.設備驅動介紹
《連載 | 物聯網框架ServerSuperIO教程》-4.如開發一套設備驅動,同時支持串口和網絡通訊。
《連載 | 物聯網框架ServerSuperIO教程》- 5.輪詢通訊模式開發及注意事項。
《連載 | 物聯網框架ServerSuperIO教程》- 6.並發通訊模式開發及注意事項
《連載 | 物聯網框架ServerSuperIO教程》- 7.自控通訊模式開發及注意事項
《連載 | 物聯網框架ServerSuperIO教程》- 8.單例通訊模式開發及注意事項
《連載 | 物聯網框架ServerSuperIO教程》- 9. 協議過濾器,解決一包多發、粘包、冗余數據
《連載 | 物聯網框架ServerSuperIO教程》- 10.持續傳輸大塊數據流的兩種方式(如:文件)
《連載 | 物聯網框架ServerSuperIO教程》- 11.實現設備(驅動)與設備(驅動)交互和級聯控制。
目 錄
12.服務接口的開發,以及與雲端雙向交互... 2
12.1 概述... 2
12.2 設備鏈接器... 2
12.3 服務鏈接器... 3
12.4 場景假設... 3
12.5 設備驅動開發及注意事項... 4
12.6 服務實例開發及注意事項... 4
12.7 宿主程序服務實例配置注意事項... 8
12.8 運行效果... 9
服務接口IService是除設備驅動接口IRunDevice外的特殊應用場景,例如:短信報警、LED輸出、模擬量的采集、OPC服務端/客戶端、數據的級聯轉發、以及其他的特殊應用。是基於設備驅動接口IRunDevice的有力擴展,讓框架的功能更豐富和強大。
這篇文章主要介紹數據的轉發和控制服務,其他的服務開發與此類似。如果基於ServerSuperIO服務接口的開發具備數據轉發和控制能力,那麼在物聯網建設中將具備數據的無限級聯傳遞與控制能力,使用一套框架形成一套解決方案。示意圖如下:
IRunDevice設備驅動接口繼承了服務的IServiceConnectorDevice接口,設備驅動會實現RunServiceConnector接口函數,代表可以接收或運行來自服務實例傳遞過來的數據信息。代碼定義如下:
public interface IServiceConnectorDevice { /// <summary> /// 支行設備連接器 /// </summary> /// <param name="fromService"></param> /// <param name="toDevice"></param> /// <returns></returns> object RunServiceConnector(IFromService fromService, IServiceToDevice toDevice); }
IService接口繼承自IServiceConnector服務鏈接器,代表服務具備兩大職能:1、向設備驅動發送命令或信息。2、接收設備驅動處理命令或信息的結果。代碼如下:
public interface IServiceConnector { /// <summary> /// 設備連接器回調函數,在這裡寫回調的處理結果 /// </summary> /// <param name="obj"></param> void ServiceConnectorCallback(object obj); /// <summary> /// 如果執行方出現異常,則返回給這個函數結果 /// </summary> /// <param name="ex"></param> void ServiceConnectorCallbackError(Exception ex); /// <summary> /// 連接器事件,發起端 /// </summary> event ServiceConnectorHandler ServiceConnector; /// <summary> /// 確發事件接口 /// </summary> /// <param name="fromService"></param> /// <param name="toDevice"></param> void OnServiceConnector(IFromService fromService, IServiceToDevice toDevice); }
設備驅動實時采集傳感器的數據信息,然後通過OnDeviceObjectChanged事件接口把數據信息傳遞給服務實例UpdateDevice接口函數,然後進行數據的緩存。開啟服務線程,連接雲端服務並且定時上傳傳感器的數據信息。雲端服務下發控制指令command:control:1(注:命令控制1號編碼設備),然後設備驅動把命令下發給傳感器,最終把結果返回給服務實例。
1.給服務實例傳遞數據信息,通過OnDeviceObjectChanged事件。代碼如下:
List<string> list = new List<string>(); list.Add(_devicePara.DeviceCode); list.Add(_devicePara.DeviceName); list.Add(_deviceDyn.Dyn.Flow.ToString()); list.Add(_deviceDyn.Dyn.Signal.ToString()); OnDeviceObjectChanged(list.ToArray());
2.接收服務實例傳遞的命令和信息。代碼如下:
public override object RunServiceConnector(IFromService fromService, IServiceToDevice toDevice) { Console.WriteLine(this.DeviceParameter.DeviceName+",接收到雲端指令:"+toDevice.Text); return this.DeviceParameter.DeviceName+",執行完成"; }
服務實例主要的職能是:緩存數據、連接雲端服務並定時發送數據、接收雲端命令信息並傳遞給設備驅動、接收驅動執行命令信息的結果。
public override void UpdateDevice(string devCode, object obj) { lock (_SyncObject) { if (obj != null) { if (obj is string[]) { string[] arr = (string[])obj; //OnServiceLog(String.Format("服務:{0} 接收到'{1}'的數據>>{2},{3}", ServiceName, arr[1], arr[2], arr[3])); if (arr.Length >= 2) { if (this._Cache.ContainsKey(devCode)) //判斷ID { this._Cache[devCode] = arr; } else { this._Cache.Add(devCode, arr); } } } } } }
2.連接雲端服務並定時發送數據,代碼如下:
private void Target_Service() { while (_IsRun) { try { if (_tcpClient != null) { lock (_SyncObject) { string content = String.Empty; foreach (KeyValuePair<string, string[]> kv in _Cache) { content += String.Join(",", kv.Value) + Environment.NewLine; } if (!String.IsNullOrEmpty(content)) { byte[] data = System.Text.Encoding.ASCII.GetBytes(content); this.OnSend(data); } } } else { this.ConnectServer(); } } catch (SocketException ex) { this.CloseSocket(); OnServiceLog(ex.Message); } catch (Exception ex) { OnServiceLog(ex.Message); } finally { System.Threading.Thread.Sleep(2000); } } }
3.接收雲端命令信息並傳遞給設備驅動
private void ReceiveCallback(IAsyncResult ar) { TcpClient socket = (TcpClient)ar.AsyncState; try { if (socket != null) { int read = socket.Client.EndReceive(ar); if (read > 0) { //處理數據.....................通知設備 string text = System.Text.Encoding.ASCII.GetString(_Buffer, 0, read); OnServiceConnector(new FromService(this.ServiceName,this.ServiceKey),new ServiceToDevice("1",text,null,null) ); OnReceive(); } else { this.CloseSocket(); } } } catch (SocketException ex) { this.CloseSocket(); this.OnServiceLog(ex.Message); } catch (Exception ex) { this.OnServiceLog(ex.Message); } }
4.接收驅動執行命令信息的結果
public override void ServiceConnectorCallback(object obj) { OnServiceLog(obj.ToString()); OnServiceLog("設備已經處理完成指令"); }
static void Main(string[] args) { DeviceSelfDriver dev2 = new DeviceSelfDriver(); dev2.DeviceParameter.DeviceName = "網絡設備"; dev2.DeviceParameter.DeviceAddr = 1; dev2.DeviceParameter.DeviceID = "1"; dev2.DeviceDynamic.DeviceID = "1"; dev2.DeviceParameter.DeviceCode = "1"; dev2.DeviceParameter.NET.RemoteIP = "127.0.0.1"; dev2.DeviceParameter.NET.RemotePort = 9600; dev2.CommunicateType = CommunicateType.NET; dev2.Initialize("1"); IServer server = new ServerManager().CreateServer(new ServerConfig() { ServerName = "服務1", ComReadTimeout = 1000, ComWriteTimeout = 1000, NetReceiveTimeout = 1000, NetSendTimeout = 1000, ControlMode = ControlMode.Self, SocketMode = SocketMode.Tcp, StartReceiveDataFliter = true, ClearSocketSession = false, StartCheckPackageLength = true, CheckSameSocketSession = false, DeliveryMode = DeliveryMode.DeviceCode, }); server.AddDeviceCompleted += server_AddDeviceCompleted; server.DeleteDeviceCompleted+=server_DeleteDeviceCompleted; server.Start(); server.AddDevice(dev2); TestService.Service service=new TestService.Service(); service.IsAutoStart = true; server.AddService(service); while ("exit" == Console.ReadLine()) { server.Stop(); } }
1.圖片