《連載 | 物聯網框架ServerSuperIO教程》- 3.設備驅動介紹


1.C#跨平台物聯網通訊框架ServerSuperIO(SSIO)介紹

《連載 | 物聯網框架ServerSuperIO教程》1.4種通訊模式機制。

《連載 | 物聯網框架ServerSuperIO教程》2.服務實例的配置參數說明

 

3.1    概述

     定位ServerSuperIO(SSIO)為物聯網通訊框架,就是因為這個框架是以“設備”(驅動)為核心構建,“設備”是泛指傳感器、下位機、PC機等各類數據源,數據源有自己的通訊協議或數據傳輸格式;ServerSuperIO並不是以IO通道為核心構建的框架,但是ServerSuperIO有很好的通訊能力,完全可以部署在服務端,並且支持多個服務實例,以及可以在Linux下運行。

3.2    接口定義

   ServerSuperIO的“設備”統一接口定義為IRunDevice,這是在框架內部運行、調度、與IO通道協作的唯一接口。代碼定義如下:

public interface IRunDevice: IServerProvider,IVirtualDevice
    {
        #region 函數接口

        /// <summary>
        /// 初始化設備,加載設備驅動的頭一件事就是初始化設備
        /// </summary>
        /// <param name="devid"></param>
        void Initialize(string devid);

        /// <summary>
        /// 保存原始的byte數據
        /// </summary>
        /// <param name="data"></param>
        void SaveBytes(byte[] data, string desc);
        
        /// <summary>
        /// 獲得發送數據的命令,如果命令緩存中沒有命令,則調用獲得實時數據函數
        /// </summary>
        /// <returns></returns>
        byte[] GetSendBytes();

        /// <summary>
        /// 如果當前命令緩存沒有命令,則調用該函數,一般返回獲得設備的實時數據命令,
        /// </summary>
        /// <returns></returns>
        byte[] GetConstantCommand();

        /// <summary>
        /// 發送IO數據接口
        /// </summary>
        /// <param name="io"></param>
        /// <param name="senddata"></param>
        int Send(IChannel io, byte[] senddata);

        /// <summary>
        /// 讀取IO數據接口
        /// </summary>
        /// <param name="io"></param>
        /// <returns></returns>
        byte[] Receive(IChannel io);

        /// <summary>
        /// 接收數據信息,帶過濾器
        /// </summary>
        /// <param name="io"></param>
        /// <param name="receiveFilter"></param>
        /// <returns></returns>
        IList<byte[]> Receive(IChannel io, IReceiveFilter receiveFilter);

        /// <summary>
        /// 同步運行設備(IO)
        /// </summary>
        /// <param name="io">io實例對象</param>
        void Run(IChannel io);

        /// <summary>
        /// 同步運行設備(byte[])
        /// </summary>
        /// <param name="key"></param>
        /// <param name="channel"></param>
        /// <param name="revData">接收到的數據</param>
        void Run(string key, IChannel channel, IRequestInfo ri);

        /// <summary>
        /// 如果通訊正常,這個函數負責處理數據
        /// </summary>
        /// <param name="info"></param>
        void Communicate(IRequestInfo info);

        /// <summary>
        /// 通訊中斷,未接收到數據
        /// </summary>
        void CommunicateInterrupt(IRequestInfo info);

        /// <summary>
        /// 通訊的數據錯誤或受到干擾
        /// </summary>
        void CommunicateError(IRequestInfo info);

        /// <summary>
        /// 通訊未知,默認狀態(一般不用)
        /// </summary>
        void CommunicateNone();

        /// <summary>
        /// 檢測通訊狀態
        /// </summary>
        /// <param name="revdata"></param>
        /// <returns></returns>
        CommunicateState CheckCommunicateState(byte[] revdata);

        /// <summary>
        /// 報警接口函數
        /// </summary>
        void Alert();

        /// <summary>
        /// 保存解析后的數據
        /// </summary>
        void Save();

        /// <summary>
        /// 展示
        /// </summary>
        void Show();

        /// <summary>
        /// 當通訊實例為NULL的時候,調用該函數
        /// </summary>
        void UnknownIO();

        /// <summary>
        /// 通訊狀態改變
        /// </summary>
        /// <param name="comState">改變后的狀態</param>
        void CommunicateStateChanged(CommunicateState comState);

        /// <summary>
        /// 通道狀態改變
        /// </summary>
        /// <param name="channelState"></param>
        void ChannelStateChanged(ChannelState channelState);


        /// <summary>
        /// 當軟件關閉的時間,響應設備退出操作
        /// </summary>
        void Exit();

        /// <summary>
        /// 刪除設備的響應接口函數
        /// </summary>
        void Delete();

        /// <summary>
        /// 可以自定義返數據對象,用於與其他組件交互
        /// </summary>
        /// <returns></returns>
        object GetObject();

        /// <summary>
        /// 設備定時器,響應定時任務
        /// </summary>
        void OnRunTimer();

        /// <summary>
        /// 顯示上下文菜單
        /// </summary>
        void ShowContextMenu();

        /// <summary>
        /// 顯示IO監視器的窗體
        /// </summary>
        void ShowMonitorDialog();

        /// <summary>
        /// 在IO監視器上顯示byte[]數據
        /// </summary>
        /// <param name="data"></param>
        /// <param name="desc"></param>
        void ShowMonitorData(byte[] data, string desc);
        #endregion

        #region 屬性接口
        /// <summary>
        /// 默認程序集ID,用於存儲臨時對象
        /// </summary>
        object Tag { set; get; }

        /// <summary>
        /// 同步對象,用於IO互拆
        /// </summary>
        object SyncLock { get; }

        /// <summary>
        /// 實時數據持久接口
        /// </summary>
        IDeviceDynamic DeviceDynamic { get; }

        /// <summary>
        /// 設備參數持久接口
        /// </summary>
        IDeviceParameter DeviceParameter { get; }

        /// <summary>
        /// 協議驅動
        /// </summary>
        IProtocolDriver Protocol { get; }

        /// <summary>
        /// 是否開啟時鍾,標識是否調用OnRunTimer接口函數。
        /// </summary>
        bool IsRunTimer { set; get;}

        /// <summary>
        /// 時鍾間隔值,標識定時調用DeviceTimer接口函數的周期
        /// </summary>
        int RunTimerInterval { set; get; }

        /// <summary>
        /// 設備的類型
        /// </summary>
        DeviceType DeviceType { get;  }

        /// <summary>
        /// 設備編號
        /// </summary>
        string ModelNumber { get;}

        /// <summary>
        /// 設備運行權限級別,如果運行級別高的話,則優先發送和接收數據。
        /// </summary>
        DevicePriority DevicePriority { get;set;}

        /// <summary>
        /// 設備的通訊類型
        /// </summary>
        CommunicateType CommunicateType { get;set;}

        /// <summary>
        /// 標識是否運行設備,如果為false,調用運行設備接口時直接返回
        /// </summary>
        bool IsRunDevice{ get;set;}

        /// <summary>
        /// 是否釋放資源
        /// </summary>
        bool IsDisposed { get; }

        /// <summary>
        /// 顯示視圖
        /// </summary>
        Control DeviceGraphics { get;}
        #endregion

        #region 事件接口

        /// <summary>
        /// 發送數據事件
        /// </summary>
        event SendDataHandler SendData;

        /// <summary>
        /// 發送數據事件,對SendDataHandler事件的封裝
        /// </summary>
        /// <param name="senddata"></param>
        void OnSendData(byte[] senddata);

        /// <summary>
        /// 設備日志輸出事件
        /// </summary>
        event DeviceRuningLogHandler DeviceRuningLog;

        /// <summary>
        /// 運行監視器顯示日志事件,對DeviceRuningLogHandler事件的封裝
        /// </summary>
        void OnDeviceRuningLog(string statetext);

        /// <summary>
        /// 串口參數改變事件
        /// </summary>
        event ComParameterExchangeHandler ComParameterExchange;

        /// <summary>
        /// 串口參數改變事件,對COMParameterExchangeHandler事件的封裝
        /// </summary>
        void OnComParameterExchange(int oldcom, int oldbaud, int newcom, int newbaud);

        /// <summary>
        /// 設備數據對象改變事件
        /// </summary>
        event DeviceObjectChangedHandler DeviceObjectChanged;
        /// <summary>
        /// 數據驅動事件,對DeviceObjectChangedHandler事件的封裝
        /// </summary>
        void OnDeviceObjectChanged(object obj);

        ///// <summary>
        ///// 刪除設備事件
        ///// </summary>
        //event DeleteDeviceCompletedHandler DeleteDeviceCompleted;
        ///// <summary>
        ///// 刪除設備事件,對DeleteDeviceHandler事件的封裝
        ///// </summary>
        //void OnDeleteDeviceCompleted();
        #endregion
}

3.3    二次開發,常用接口

    RunDevice抽象類繼承自IRunDevice接口,本質上來講,二次開發只需要繼承RunDevice抽象類就可以了。RunDevice已經完成了設備驅動在ServerSuperIO框架下基本的條件。那么在繼承RunDevice抽象類的時候,所需要二次開發的工作很小,只需要關注協議和處理數據業務本身,對於框架的內部運行機制可以配置、調度機制內部自動處理。

    二次開發常用的接口,項目示意如下圖:

     這是一個按協議規則完成實時接收文件數據的設備驅動,ReceiveFileDriver繼承自RunDevice抽象類,是設備驅動的核心接口;Protocol是自定義協議接口,包括發送數據協議和接收數據協議,實例化后在ReceiveFileDriver接口的IProtocolDriver屬性中返回;不光要有協議接口,在協議里邊還要有命令,那么Command就是協議中的自定義命令,這個協議命令規定了發送數據和接收解析數據,協議命令不僅僅包括一個,根據業務需要,設備驅動可以包含多個協議命令,以完成與實體硬件的交互;Parameter自定義參數接口,每個設備對象本身的參數不一樣,實例化后在ReceiveFileDriver接口的IDeviceParameter屬性中返回;Dynamic是自定義實時數據臨時緩存接口,可以把解析后的實時數據臨時存儲在這個對象里,,實例化后在ReceiveFileDriver接口的IDeviceDynamic屬性中返回,這個對象不是必須要實現的,ServerSuperIO內部並沒有直接引用。

     以上是從項目角度大體闡述了需要寫哪幾類代碼,ReceiveFileDriver設備驅動需要二次開發寫的代碼,如下示意圖:

1)        Initialize:初始化設備驅動接口,在這里可以初始化協議驅動、設備參數和設備的實時數據等對象,以及完成一些其他的操作。

2)        DeviceDynamic:實時數據對象接口屬性,不是必須實現。

3)        DeviceParameter:參數數據對象接口屬性,必須實現。

4)        Protocol:協議驅動接口,很關鍵,必須實現。

5)        DeviceType:設備類型,一般指普通設備,虛擬設備適用於特殊情況,必須實現。

6)        ModelNumber:設備驅動的唯一編號,一般必須實現。

7)        GetConstantCommand:固定返回發送數據的接口,一般返回讀實時數據命令,在SendCache里沒有命令的時候,會調用該接口,必須實現。

8)        Communicate:通訊正常,會把數據返回到這個接口,影響通訊狀態為Protocol接口中的CheckData函數,校驗接收到數據的完整性。

9)        CommunicateInterrupt:通訊中斷代表沒有接收到任何數據,會調用這個接口,影響通訊狀態為Protocol接口中的CheckData函數,校驗接收到數據的完整性。

10)    CommunicateError:通訊干擾代表接收到數據,但是沒有校驗正確,會調用這個接口,影響通訊狀態為Protocol接口中的CheckData函數,校驗接收到數據的完整性。

11)    CommunicateNone:通訊未知,代表該設備驅動對應的IO通道COM沒有打開或NET沒有有效連接。

12)    UnknownIO:未知IO通道,COM沒有打開或NET沒有有效連接。

13)    CommunicateStateChanged:每次通訊狀態改變后會調用這個接口函數。

14)    ChannelStateChanged:IO通道狀態改變后會調用這個接口函數,COM是打開或關閉,NET是連接或斷開。

15)    Save:保存數據函數接口,設備驅動執行到生命周期最后會調用這個接口,以完成對數據的保存。

16)    Alert:報警函數接口,數據處理完成后,對數據進行判斷,以完成報警功能。

17)    Show:顯示數據函數接口,數據處理完成后,對數據進行顯示,是SIO保留下來的接口函數,以后擴展使用。

18)    Exit:當設備驅動退出時調用該函數接口,例如:宿主程序退出時。

19)    Delete:刪除設備驅動調用該函數接口,是SIO保留下來的接口函數,適用於有界面UI的應用場景,以后擴展使用。

20)    DeviceGraphics:視圖接口,是SIO保留下來的接口函數,以后擴展使用。

21)    GetObject:獲得數據對象,以后打算為服務接口供數據支持,現在沒有實際用處。

22)    ShowContextMenu:顯示上下文菜單,是SIO保留下來的接口函數,以后擴展使用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM