目 录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. 应用效果
文章:
《.NET Core开发的iNeuOS工业互联网平台,发布 iNeuDA 数据分析展现组件,快捷开发图形报表和数据大屏》
《[视频演示].NET Core开发的iNeuOS物联网平台,实现从设备&PLC、云平台、移动APP数据链路闭环 》
《.NET Core开发的iNeuOS物联网平台部署树霉派(raspbian),从网关到云端总体解决方案》
《.NET Core开发的iNeuOS物联网平台部署在Ubuntu操做系统,无缝跨平台》
《iNeuOS 物联网云操做系统2.0发布,集成设备容器、视图建模、机器学习三大模块 》
物联网&大数据技术 QQ群:54256083
物联网&大数据合做 QQ群:727664080
联系QQ:504547114
合做微信:wxzz0151