前言 随着工业物联网和互联网技术的普及和发展,人工投料逐渐被机械设备所取代。减少误操作、提高设备安全性、追求高效率等制造特性对设备提出了越来越高的标准和严格的要求。同时,机械化生产后,需要对整个工程流程进行规范化管理。如何实施管理和交接也是一个严峻的挑战。因此,在整个生产过程中也应该开发一套关于管理过程的可视化界面。 在工业过程控制中,根据被控对象实时数据采集的信息与给定值进行比较所产生的误差的比例、积分、微分对控制系统进行控制,简称PID控制系统。PID控制生产环境具有适应性强、鲁棒性强、使用方便等特点。供料系统涉及超高压技术,广泛应用于流水线系统。可实现设备半自动或自动上料作业,解决传统上料方式计量不准确、工作环境污染、工人劳动强度大等问题,实现高效生产。流水线加工。结合PID和自动化调配,可为电力、机械、冶金、化工、食品、纺织等工业或民用行业供需。Hightopo的HTforWeb产品(以下简称HT)提供了丰富的二维配置。本文通过搭建危废投料系统的二维场景,展示数据界面,帮助我们理解如何使用HT实现可视化PID控制。饲料系统。效果预览项目地址预览:http://www.hightopo.com/demo/PID-feed-system/整体协作场景抓取操作场景feed场景代码构建构建场景本文主要实现2D场景,我们需要使用到拓扑组件相关api构建基础场景://数据容器,用于访问数据节点NodedataModel=newht.DataModel();//拓扑组件graphView=newht.graph.GraphView(dataModel);//将组件添加到主体graphView.addToDOM(); 上面的代码使用addToDOM()方法将组件添加到主体中。HT组件一般嵌入在BorderPane、SplitView、TabView等容器中,最外层的HT组件需要用户手动将getView()返回的底层div元素添加到页面的DOM元素中。这里需要注意的是,当父容器的尺寸变化时,如果父容器是BorderPane、SplitView等HT预定义的容器组件,那么HT容器会自动递归调用子组件的invalidate函数来通知更新.但是如果父容器是原生的html元素,HT组件无法知道它需要更新,所以最外层的HT组件一般需要监听窗口的窗口大小变化事件,调用其invalidate()函数要更新的最外层组件。 为了方便加载最外层组件填满窗口,HT的所有组件都有addToDOM()函数,其实现逻辑如下,其中iv()是invalidate()的简写:addToDom=function(){varself=this,//获取组件底层divview=self.getView(),style=view.style;//将组件的底层div添加到bodydocument.body.appendChild(view);//所有组件的默认位置都设置为absolute绝对定位style.left='0';style.right='0';style.top='0';style.bottom='0';//窗口改变大小,调用刷新函数window.addEventListener('resize',function(){self.iv();},false);} 重置视图的默认方法://禁止拖动鼠标平移操作graphView.setPannable(false);//禁用拓扑上的选框操作graphView.setRectSelectable(false);//禁用移动过滤功能graphView.setMovableFunc(()=>{false}); 在二维编辑器上创建二维图会生成一个JSON文件,需要反序列化引入生成场景:ht.Default.xhrLoad('displays/industry/PID-feedingsystem.json',function(text){//解析成JSON对象varjson=ht.Default.parse(text);//反序列化到场景dataModel.deserialize(json);}) 在HT中,构造Data类型对象时,会内部会自动赋予一个id属性,可以通过data.getId()和data获取。设置编号(编号)get和set,不允许在Data对象加入DataModel后修改id值。通过dataModel.getDataById(id)可以快速找到Data对象,但一般建议id属性由HT自动赋值,用户业务意义的唯一标识可以存放在tag属性中。Data#setTag(tag)函数允许动态改变标签值,通过DataModel#getDataByTag(tag)可以找到对应的Data对象,支持DataModel#removeDataByTag(tag)删除Data对象。这里我们设置了JSON中Data对象的tag属性,代码中通过dataModel.getDataByTag(tag)函数获取Data对象:{"c":"ht.Node","i":407,"p":{"displayName":"GripKnot","parent":{"__i":403},"tag":"gripKnot","image":"symbols/symbolfactory/garbagedisposal/gripknot.json",“位置”:{“x”:-569.62125,“y”:-117.05025},“宽度”:50,“高度”:25},“s”:{“select.width”:0}}vargripRightPaw=dataModel.getDataByTag('gripRightPaw');vargirpLeftPaw=dataModel.getDataByTag('grapLeftPaw');vargripKnot=dataModel.getDataByTag('gripKnot');展开动画 HT封装了ht。Default.startAnim()函数通过设置duration获取动画时长,action函数是要执行的动画属性,动画执行后的finishFunc回调函数。本例一共设置了8个动画,包括自驱动和异步动画。下面以第八个动画(循环水流)为例来理解ht内置的动画效果://循环水流函数animation(){varlineJson={};变种名称='';varspeed=20,lastTime=Date.now();//循环获取水流标签,初始shape.dash.offset设置为0for(vari=1;i<=9;i++){if(i!=8){name='line'+我;lineJson[名称]=0;}}ht.Default.startAnim({duration:5000,action:function(){vartime=Date.now(), deltaTime=(time-lastTime)/1000;for(vartagsinlineJson){if(tags.split('e')[1]%2){lineJson[tags]+=deltaTime*speed;}else{lineJson[tags]-=deltaTime*speed;}varlines=dataModel.getDataByTag(tags);lines.setStyle('shape.dash.offset',lineJson[tags]);}lastTime=time},finishFunc:function(){动画离子();//TODO...这里也可以异步调用下一个动画}})} 本例首先根据创建的循环水流(绑定tag标签)通过for循环和dataModel.getDataByTag动态获取Data节点,通过tag名称携带的数字判断水流方向,最后使用Data.setStyle(可以简写为Data.s)设置虚线部分的偏移距离 上面的循环水flow为例,如果lineJson[tags]+=value(固定值),当用户放大view时,primitive数量减少,anim中的action函数会被调用几次,flowspeed增加,和缩小是一样的。因此采用value=speed*deltaTime的方案来解决view在不同zoom缩放条件下播放速度不一致的问题。具体原理如下://globalvarlastTime=Date.now();//距离vardistance=0;//速度varspeed=20;//actionht.Default.startAnim({duration:5000,action:function(){vartime=Date.now();vardeltaTime=(time-lastTime)/1000;distance+=speed*deltaTime;lastTime=time;},finishFunc:function(){//TODO}}) ht动画不仅可以通过startAnim来驱动,也可以通过scheduleaddScheduleTask来驱动。代码如下:dataModel.addScheleTask({//调度间隔interval,//调度开始前的ActionsbeforeAction(){},//调度任务action(){},//调度结束后的ActionsafterAction(){}}) 也可以使用callLater来实现,ht内置函数封装了很多有趣实用的关于动画的API,感兴趣的可以去官网(https://www.hightopo.com)了解学习,也可以申请框架在线试用包。如果想深入了解HT封装的动画,可以参考https://www.cnblogs.com/xhload3d/p/9222549.html等文章。可操作 当然,HT也借鉴了订阅-发布模式的天然优势。通过驱动数据改变视图,可以更直观的感受数据和视图的绑定过程。提供以下两类HT提供的可操作接口。第一种是创建面板组件。HT内部提供了一系列通用的面板组件,包括formPane、borderPane、TablePane等,这里我们以formPane为例,首先在index.html主页面引入ht-form.js,封装了formPane面板的api,相关伪代码如下://创建面板对象varfp=newht.widget.FormPane();fp.setWidth(200);fp。setHeight(100); //面板行高fp.setRowHeight(30); fp.setPadding(16); //设置节点的类名后,可以直接设置属性在样式上,说白了fp.getView()就是一个普通的DOM节点fp.getView().className='main';//通过addRow方法添加文字和进度条fp.addRow([{id:'text',element:'CurrentSpeed===20',align:'center'}],[0.1]);fp.addRow([{id:'speed',//进度条slider:{min:0,max:100,//当前进度值value:20,step:1,//触发函数onValueChanged(){varspeed=fp.v('speed');fp.v('text','当前速度==='+speed);}}}],[0.1]);document.body.appendChild(fp.getView()); 此时我们只需要将之前定义的speed指向fp.v('speed')数据视图绑定即可简单实现:functionanimation(fp){varlineJson={};变量名字='';varlastTime=Date.now();可变速度;for(vari=1;i<=9;i++){if(i!=8){name='line'+i;lineJson[名称]=0;}}ht.Default.startAnim({duration:5000,action:function(){speed=fp.v('speed');vartime=Date.now(),deltaTime=(time-lastTime)/1000;对于(lineJson中的var标签){if(tags.split('e')[1]%2){lineJson[tags]+=deltaTime*speed;}else{lineJson[tags]-=deltaTime*speed;}varlines=dataModel.getDataByTag(tags);lines.setStyle('shape.dash.offset',lineJson[tags]);}lastTime=time;},finishFunc:function(){animation(fp);}})} 另一种是通过HT的矢量图库。矢量图形使用点、线或多边形来描述图形,解决了png、jpg等格式的图片在缩放过程中出现的失真现象矢量图形的创建可以通过webstorm、webstorm等常规编辑器编写代码,也可以直接通过HT-2D编辑器编写。基本上,无需操作代码即可轻松创建图形。学过3dmax或者CAD制图的同学应该对这个不陌生。随着小编的不断完善,里面已经有很多优秀的图标和组件案例了。这里可以直接引用一些小案例。首先需要创建一个绘图,然后直接拉一个自制的图标。类似legend的效果就是画完线后,改变文字部分就可以直接看到效果了。 按键为功能组件,图标显示显示界面,功能组件支持事件的触发。首先在控件中拉动滑块图标,然后在组件栏中拉动滑块组件,并设置最大值、最小值和默认值等一系列参数。 可以知道我们要改变的值有两个,一个是滑块的值,一个是文本的值,默认是20,我们给这两个Data对象绑定唯一的标签,分别是sliderValue和textValue,先通过进度条改变text值的当前值:varsliderValue=dataModel.getDataByTag('sliderValue');vartextValue=dataModel.getDataByTag('textValue');//数值改变触发事件sliderValue.a('ht.onChange',function(){ textValue.a('textValue',sliderValue.a('ht.value'));}) 然后动画获取进度条的当前值,指向速度:functionanimation(data){varlineJson={};变种名称='';varlastTime=Date.now();可变速度;for(vari=1;i<=9;i++){if(i!=8){name='line'+i;lineJson[名称]=0;}}ht.Default.startAnim({duration:5000,action:function(){speed=data.a('ht.value');vartime=Date.now(),deltaTime=(time-lastTime)/1000;for(vartagsinlineJson){if(tags.split('e')[1]%2){lineJson[tags]+=deltaTime*speed;}else{lineJson[tags]-=deltaTime*speed;}varlines=dataModel.getDataByTag(标签);lines.setStyle('shape.dash.offset',lineJson[tags]);}lastTime=时间;},finishFunc:function(){动画(数据);}})} 当然你也可以自定义多个滑块分别控制不同的动画。如何实现它完全取决于您的需求。 不局限于2D可视化场景。3D生产环境相关的视觉场景模拟案例也很多,如下:3D水泥厂流程:http://www.hightopo.com/demo/CementFactory/3D高炉炼铁工业流程:http://www.hightopo.com/demo/CementFactory/高拓扑。com/demo/large-screen-puddling/总结 通过可视化系统的维护,大大节省了人力资源和时间成本,还可以通过丰富的2D配置流程呈现出一套完整的流程。信息网络化的发展是工业4.0的趋势,而工业控制与数据可视化的融合也是工业互联网的核心,可以通过一系列简单明了的动画和实景实现对一些复杂行业标准的反馈。时间数据。构建具有工业领域代表性行业流程标准的可视化运维体系。当然,通过自身的不断完善,HT不仅拥有方便用户使用的2D构型,在3D构型中也有很多有趣好玩的方法供用户搭建! 2019我们还更新了数百个工业互联网2D/3D可视化案例合集,在这里你可以找到很多新奇的例子,发现不一样的工业互联网:https://mp.weixin.qq。com/s/ZbhB6LO2kBRPrRIfHlKGQA 同时还可以查看更多案例及效果:https://www.hightopo.com/demos/index.html
