人机交互接口(HMI)是自动控制与物联网不可或缺的重要部分。在一个基于模型的物联网或者自动控制平台上如何构建HMI是一个富有挑战的课题。本文讨论如何使用图模型构建HMI模型,系统模型与HMI模型之间的相互操作。
实现HMI 组态化的主要方法是建立HMI 的模型。有了模型就能够通过配置模型的属性来实现组态。HMI建模的方法可以有许多种,例如面向对象的类,自动控制中的功能块,OPC UA 模型等等。在我们的显示系统中,尝试采用与系统模型一样的建模方式-图模型。这样做的好处在于组态方法,概念,术语都系统组态方式相同。软件模块实现公用,学习曲线平坦。我们的尝试表明这是可行的。
HMI 单元的特点
HMI 的图模型
从HMI 的上述特点可以看出,它们与系统中的图模型非常相似。我们完全可以使用系统的图模型来构建HMI 的模型。
例如下面是我们建立的一个HMI 的图模型。
模型中包括:
在三个带有按键的节点,还有一个Function 子节点,定义了按键Click 时调用的方法。
HMI 模型的优点
使用系统信息模型构建HMI 模型的优点:
-能够自动生成HMI页面
-与系统模型设计使用同一个工具。软件实现的工作量减少了,使用更容易。
-便于HMI 和系统之间的交互。
HMI 最终需要通过HTML5 来呈现,它们就是UI 组件(也有人称为widget 小部件)。每一个 HMI 节点对应一个UI 组件。UI 组件是HTML5,SVG 图形,CSS和javascript 类组成的。
SVG
SVG 称之为可伸缩的矢量图(Scalable Vector Graphics),它使用XML来描述图型。
在HTML5 网页中实现动画,绘图主要有两种方法,一种是利用canvas ,另一种就是使用SVG。
SVG 可以内嵌JavaScript 脚本实现动画图标。
相比其它的图像格式,SVG具有如下的特点:
• SVG文件是纯粹的XML, 可被非常多的工具读取和修改(比如记事本)。
• SVG 与JPEG 和GIF图像比起来,尺寸更小,且可压缩性更强。
• SVG 是可伸缩的,可在图像质量不下降的情况下被放大,可在任何的分辨率下被高质量地打印。
• SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)。
• SVG 可以与 Javascript 技术一起运行。
• SVG 是开放的标准。
下图是使用SVG 构建的SCADA 界面
java script 类封装
在javascript 中很少使用类,不过在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。
在构建HMI 中, HMI页面上可能会使用多个相同类型的UI组件。所以进一步将UI组件封装成类。
一个文本框CLASS的例子:
class TextBox{
constructor(WidgetInfor) {
Option =WidgetInfor;
this.Option = Option;
$("#hmi").append(""+Option.Text+"")
$("#"+Option.Name).css({
"top":this.Option.Position.y+"px",
"left":this.Option.Position.x+"px",
"font-size":this.Option.FontSize,
"align":this.Option.Align,
"background-color":Option.BackgroundColor,
"width":this.Option.Size.width+"px",
"height":this.Option.Size.height+"px",
"color":this.Option.Color
})
}
PutAttribute(Name,Value){
if (Name=="Text")
$("#"+this.Option.Name).text(Value);
}
},
HMI 界面的图形化编辑工具
使用图形化编译软件来编辑HMI界面,可以导入HMI 模板,填入各种属性参数,确定UI 图形在页面的位置,大小等等。这个HMI编辑程序也是基于HTML5 技术实现。
一旦建立了HMI 界面之后,前端页面打开时,读取HMI 模型的属性。自动地构建HMI页面。HMI页面是由各个UI 组件构成。它们是通过HMI 类的实例化来实现的。
对应的HMI 界面是这样的,有点丑,但是可以优化。
信息模型几乎都是静止的数据结构。要通过信息读取,订阅/发布,事件通知等方式实现HMI 组件与系统模型的交互。
组件通过后台访问系统模型。浏览器前端与后台服务器之间可以采用HTTP,websocket,socket.io等多种协议实现信息交换。在我们的实验系统中,使用socket .io实现双向消息通信,它是建立在web socket 之上的消息系统(HMI Message)。
被动型HMI组件和主动型HMI 组件
只接收外部发生的信息的组件称为被动型组件,比如标题(Title),输出文本框(textbox),数据表格,图形曲线显示,仪表盘是被动型组件。
向其它模型主动发送数据,调用其它节点的方法的组件都是主动型节点。例如按键,输入文本框,滑杆等组件都是主动型HMI组件。
HMI Message 消息格式
被动型组件接收消息
被动型组件通过下面几种方式接收外部的数据:
订阅数据(subscribe)
订阅某个节点的属性,当该属性更新时,系统向该组件发送数据。
在上面的例子中,一个TextBox和电表的电流建立订阅关系。订阅和事件通知需要HMI 控件的属性与目标节点建立订阅或者事件通知关系。这样在实现多变量HMI控件时,能够明确属性的映射关系。
例如下面的图中,一个曲线显示控件订阅了两个节点的属性。
订阅事件(Notify Event)
与某个事件建立订阅关系,当事件发生时,系统向该组件发送数据。
方法的结果(Function Result)
由主动型组件调用方法的结果调度到被动型组件中。
主动型组件的消息发送
主动型组件将主动向系统发送调用方法(Call Function) 调用的方法有两类:
第一类是调用系统API的方法,比如读取某一个节点的属性(getAttribute),读取历史数据等等。
常用的系统API
读取某个或者某一类节点的某个属性当前值
读取某个或者某一类节点的某个属性某一时间段的历史数据
设置某个或者某一类节点的某个属性。
等待某个或者某一类节点产生的事件。
向某个或者某一类节点发送的事件。
发布数据。
订阅数据。
另一类是调用某个节点的方法,比如调用motor 节点的 start 方法。
例如, 我们要在HMI 面板上输入电机的速度。于是我们建立一个inputValue 的HMI控件,它内部包含了一个文本框TextBox 和一个按键(button)。当按键click时,调用putAttribute 方法。发送textbox的值到motor节点的Speed 属性。
getAttribute 方法
getAttribute 方法要相对复杂一点。涉及到如何返回,返回给HMI 控件的哪一个属性?所以在Message 中要确定属性的名称。
HMI和后端的消息格式(sendHMessage):
$("#"+this.Option.Name+"_btn").click(()=>{
SendHMIMessage({
Name:this.Option.Name,
ID:this.Option.ID,
Method:this.Option.Method,
Arguments:[this.Option.Argument,"Text"]
})
});
由于篇幅有限,我们只是粗略地讨论了如何采用系统统一建模方式来构建HMI模型的若干问题。这个演示系统目前可以Work 了。主要是用来检验图模型数据库的物联网系统的可行性,以及各种模型,模板,协议的设计与选择。感兴趣的朋友可以交流。
要真正实现产品化还有许多事情要做。