iNeuOS工業互聯平臺,iNeuKernel(物聯網核心組件)遠程控制標準化設計與實現。發佈v2.3版本。

目       錄php

1.      概述... 2html

2.      平臺演示... 2瀏覽器

3.      控制端與iNeuKernel的交互協議... 3安全

4.      設備驅動實現控制業務... 4服務器

5.      應用效果... 9微信

5.1           CS客戶端... 9app

5.2           BS瀏覽器... 9運維

5.3           Linux環境測試... 10機器學習

5.4           視頻應用效果... 10異步


 >>iNeuKernel v2.3版本下載:https://pan.baidu.com/s/1nxpnC7FazBBVyK9zUFgjyg


 1.   概述

        2019年6月,iNeuOS發佈第一個版本以來,實際合做的客戶和在談合做的客戶,對於雲端控制或雲端修改參數的需求比較多,基本上是共識。未來5G的發展和應用,雲端控制將是一個常態,在iNeuOS的規劃中已經做爲一項重要工做。之因此沒有早期開發雲端控制部分,是由於咱們所在的工業領域(煤炭、鋼鐵、化工、電力等)是重工業,與互聯網傳輸數據都有嚴格的限制,更不可能讓雲端控制,另外涉及到安全問題。

        大部分雲端控制的需求涉及行業通常爲環保、農業、電工裝備等,業務需求通常是遠程修改參數和控制一些開關狀態,可是這些操做不會帶來致命事故,更多的是從遠程運維角度考慮的需求。

        如今iNeuKernel(設備容器)物聯網核心組件,已經具有了遠程控制服務功能,支持終端設備或軟件以Socket或WebSocket通道協議,經過標準的文本協議與硬件或傳感進行交互,實現遠程修改參數和控制的目的。後續會把這項功能集成到iNeuView(Web組態)視圖建模,能夠經過組態頁面操做實現遠程控制。

        參見之前的文章:

      《終端控制傳感器或設備,造成迴路控制

      《4種通信模式機制

2.   平臺演示

在線演示:http://demo.ineuos.net  (注:服務器比較慢,請耐心等待。自已註冊用戶,體驗系統功能)

視頻演示:http://www.ineuos.net/video/iNeuOS%20and%20app.mp4

驅動開發:http://www.ineuos.net/index.php/products/ineukernel-15.html (v2.1版本)

手機APP:http://demo.ineuos.net/app/ineuos_app.apk

3.   控制端與iNeuKernel的交互協議

      控制端能夠理解爲iNeuView組態,控制操做經過交互協議與後臺的iNeuKernel進行交互,進一步與設備驅動交互,對設備進行控制操做,固然其餘終端的操做鏈路也是這樣的。示意,以下圖:

     交互協議充分考慮了系統命令和設備命令兩種狀況,一個是對後臺服務進行遠程控制,一個是對設備進行控制,綜合完成遠程運維業務需求。示意,以下圖:

4.   設備驅動實現控制業務

       以Modbus RTU通信協議爲例,實現遠程控制業務需求。IRunDevice接口有一個RunServiceConnector函數接口接收控制端發來的交互信息,交互信息是一個DevicePacket協議包。

      注:具體代碼事例,能夠加物聯網&大數據技術羣:54256083,找羣主

    (1)DevicePacket設備協議包轉換成JSON格式

"DevicePacket": {
    "OperationCode": "20200206202127025",
    "DeviceId": "92b2306385f749d494a9b24f469cac87",
    "DeviceName": "Modbus",
    "Desc": "",
    "DeviceFrames": [
      {
        "TagId": "79be2b1e790f4c06873a8446bca755ea",
        "TagName": "tag1",
        "DataType": "int",
        "Value": "true",
        "FrameId": "20200206202127032",
        "OperationType": "setack",
        "Code": "200",
        "Desc": "淇敼鎴愬姛",
        "Time": "2020-02-06T20:21:27.0322772+08:00"
      }
    ]
  }

  (2)RunServiceConnector函數接口接收設備協議包

       /// <summary>
        /// 與服務(Service)交互使用的接口,與service.OnServiceConnector配合使用。
        /// </summary>
        /// <param name="fromService"></param>
        /// <param name="toDevice"></param>
        /// <param name="asyncService"></param>
        /// <returns></returns>
        public override IServiceConnectorCallbackResult RunServiceConnector(IFromService fromService, IServiceToDevice toDevice, AsyncServiceConnectorCallback asyncService)
        {
            if(!(toDevice.Object is DevicePacket))
            {
                OnDeviceRuningLog("RunServiceConnector 接收到的爲非 DevicePacket 對象");
                return null;
            }
            //設置優先調用此設備驅動
            this.DevicePriority = DevicePriority.Priority;
            //接收過來的設備協議包
            this._devicePacket = (DevicePacket)toDevice.Object;
            //異步返回操做結果,把操做最終的結果反饋給代理服務,最終通知操做端
            this._asyncServiceConnectorCallback = asyncService;
            //設置爲當前爲接收狀態
            this._sendCommandState = SendCommandState.Received;
            OnDeviceRuningLog("已經接收到命令交換信息,正在準備下發命令......");
            return new ServiceConnectorCallbackResult(true, null);
        }

  (3)GetConstantCommand()函數接口得到下發控制命令

 if (_sendCommandState == SendCommandState.Received)   //發送命令
            {
                #region 構建發送命令
                if (_devicePacket != null)
                {
                    #region
                    _sendCommandState = SendCommandState.ReadySending;
                    foreach (DeviceFrame df in _devicePacket.DeviceFrames)
                    {
                        ITag tag = tags.Where(t => t.TagId == df.TagId && t.TagName == df.TagName).FirstOrDefault();
                        if (tag != null)
                        {
                            IModbusMessage requestMsg = null;
                            byte[] reqeustBytes = null;
                            switch (tag.Function)
                            {
                                case 0x01:   //線圈,bool值
                                    reqeustBytes = _modbusRtuMaster.BuildWriteSingleCoilCommand(byte.Parse(tag.SlaveId), ushort.Parse(tag.Address), bool.Parse(df.Value), out requestMsg);
                                    break;
                                case 0x03:   //保持寄存器,數值
                                    reqeustBytes = _modbusRtuMaster.BuildWriteSingleRegisterCommand(byte.Parse(tag.SlaveId), ushort.Parse(tag.Address), ushort.Parse(df.Value), out requestMsg);
                                    break;
                                default:
                                    OnDeviceRuningLog("沒有找到可寫入命令的標籤配置");
                                    break;
                            }

                            if (reqeustBytes != null)
                            {
                                requestList.Add(new RequestInfo(reqeustBytes, new SendObject(requestMsg, tag)));
                            }
                        }
                    }
                    _sendCommandState = SendCommandState.Sending;
                    #endregion
                }
                else
                {
                    _sendCommandState = SendCommandState.None;
                }
                #endregion
 }

  (4)Communicate接收控制命令返回結果

 byte[] revData = info.Data;
            IModbusMessage requestMessage = _sendObject.ModbusMessage;
            ITag tag = _sendObject.Tag;
//用於驗證修改值返回數據
            bool modiftyData = false;  //是否修改返回數據
            bool validate = true;      //驗證是否經過
if(requestMessage.FunctionCode == Modbus.Modbus.WriteSingleCoil)
            {
                modiftyData = true;
                try
                {
_modbusRtuMaster.ValidateWriteSingleCoilResponse(revData, requestMessage);
                }
                catch(Exception ex)
                {
                    validate = false;
                    OnDeviceRuningLog(ex.Message);
                }
            }
            else if(requestMessage.FunctionCode==Modbus.Modbus.WriteSingleRegister)
            {
                modiftyData = true;
                try
                {
_modbusRtuMaster.ValidateWriteSingleRegisterResponse(revData, requestMessage);
                }
                catch (Exception ex)
                {
                    validate = false;
                    OnDeviceRuningLog(ex.Message);
                }
            }

          if(modiftyData)
            {
                if (_devicePacket != null)
                {
                    DeviceFrame df = _devicePacket.DeviceFrames.Where(t => t.TagId == tag.TagId).FirstOrDefault();
                    if (df != null)
                    {
                        if (validate)  //正常
                        {
                            df.OperationType = "setack";
                            df.Code = "200";
                            df.Desc = "修改爲功";
                            _modifyConfirm.Add(df.TagId, true);
                        }
                        else
                        {
                            df.OperationType = "setack";
                            df.Code = "-1";
                            df.Desc = "修改失敗";
                        }
 
                        OnDeviceRuningLog(String.Format("{0},{1}!!!", tag.TagName, df.Desc));
 
                        if (_asyncServiceConnectorCallback != null)
                        {
_asyncServiceConnectorCallback.Invoke(_devicePacket);
                        }
                    }
                    else
                    {
                        OnDeviceRuningLog("得到修改設備幀數據爲空");
                    }
                    bool modifyComplete = true;
                    foreach(DeviceFrame d in _devicePacket.DeviceFrames)
                    {
   modifyComplete=_modifyConfirm.ContainsKey(d.TagId);
                        if(!modifyComplete)
                        {
                            break;
                        }
                    }

                    if(modifyComplete)
                    {
                        _devicePacket = null;
                        _asyncServiceConnectorCallback = null;
                        _modifyConfirm.Clear();
                        _sendCommandState = SendCommandState.Complete;
                        OnDeviceRuningLog("修改參數已所有完成!!!");
                    }
                }
            }

5.   應用效果

5.1    CS客戶端

5.2    BS瀏覽器

5.3    Linux環境測試

5.4    視頻應用效果


文章:

 .NET Core開發的iNeuOS工業互聯網平臺,發佈 iNeuDA 數據分析展現組件,快捷開發圖形報表和數據大屏

 [視頻演示].NET Core開發的iNeuOS物聯網平臺,實現從設備&PLC、雲平臺、移動APP數據鏈路閉環

 .NET Core開發的iNeuOS物聯網平臺部署樹黴派(raspbian),從網關到雲端總體解決方案

 .NET Core開發的iNeuOS物聯網平臺部署在Ubuntu操做系統,無縫跨平臺

 iNeuOS 物聯網雲操做系統2.0發佈,集成設備容器、視圖建模、機器學習三大模塊

 iNeuOS雲操做系統,.NET Core全系打造


 物聯網&大數據技術 QQ羣:54256083 

 物聯網&大數據合做 QQ羣:727664080

 網站:http://www.ineuos.net

 聯繫QQ:504547114

 合做微信:wxzz0151

相關文章
相關標籤/搜索