变量是一个非数字符号,代表某个数据。它提供了数据定义、运算、传递功能,支持用于下发数据、数据源等配置中。
1. 创建变量
步骤一:点击左侧变量按钮,然后选择一个分组,点击加号。
步骤二:配置
按照规则填入配置变量的名称、描述,引用方式(静态、动态)。
快速创建设备点变量
1.创建组件后,点击rightPanel中样式tab的选择数据源,点击快速创建设备点变
2.出现快捷创建设备点弹框后选择属性-设备-属性组,点击属性组之后对应属性展示在表格中3.选中任意一项属性或者全选属性后,点击在组态中创建,出现创建变量弹框
4.选择后点击确定,变量创建成功
2. 编辑变量
在变量卡片中双击或者点击编辑按钮,弹出变量编辑框。在弹窗中可以修改变量的名称、描述、值等配置,也可查看变量code等信息。
3. 删除变量
选中某个变量后,点击“删除”选项。
4. 变量引用方式
4.1. 引用方式1——静态变量
静态变量数据来源是固定的不变的。
配置静态变量数据源类型:
HTTP接口:数据源从HTTP接口中获取;
设备数据点:从设备点位中获取数据源;
固定值:手动输入一些静态的数据;
数据库:从数据库中获取变量类型;
MQTT:通过网络连接发送的信息数据包;
告警变量:设备告警类数据;
文件:.csv / .json / .xlsx后缀的文件内容作为变量
虚拟变量:几个变量通过过滤器进行加减乘除等操作后返回得到一个虚拟变量。
1)设备属性点示例
配合数采一体机使用时,组态系统默认集成了设备属性列表,在变量类型中选择设备属性点,在选择属性栏可以根据设备模板选择具体的设备实例,再选择设备属性,即可将设备属性值匹配到变量上。
选择设备属性后,可以继续填写数据过滤脚本,对已获取到的设备属性值进行二次加工。
2)数据库示例
1.配置变量为静态引用方式下的数据库类型,其中数据库类型分为PgSQL(功能强大的开源对象系统管理系统)、MySQL(关系类型数据库管理系统)、SqlServer(微软推出的关系数据库管理系统)
2.配置数据库类型以及数据库的地址、端口数据库名称用户名和地址,点击配置栏右上方按钮可以检查连接配置是否有效。
3.设置数据源默认值:勾选设置数据源默认值,未接收到有效数据返回时预置的默认值,用于保证初始显示效果。收到首次返回即失效。
4.配置完成点击确定,即创建了一个数据库类型的变量
注:版本限制
MySQL 5.6及以上
PostgreSQL 11 及以上
SQL Server 2005 及以上
3)MQTT变量示例
1.配置引用变量
数据来源选择MQTT变量,配置MQTT协议的host(接入地址)、port(端口)、topic(主题)、用户名及密码。
4)告警变量示例
告警变量需选择监听告警的设备模板、设备、告警级别、告警类型。常用于告警类组件。
5)文件变量示例
1.在左侧变量中,选中某个分组,点击加号按钮,点击“添加变量”
2.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择文件, 选择文件后会展示文件变量的面板
3.点击上传文件按钮, 文件类型支持 csv / json / xlsx 格式, 上传之后会展示文件解析结果
4.确认解析内容无误之后,点击确定按钮创建变量, 显示创建变量成功的提示则表示创建成功。
文件类变量可以用在柱状图等图表组件的数据源中。
6)虚拟变量示例
1.配置引用变量
数据来源选择虚拟变量,选择需要的引用变量(不能少于一个),默认为两个,可添加或删除引用变量,点击刷新按钮返回结果为由几个引用变量组合成的虚拟变量。
2.配置数据过滤脚本
勾选数据过滤脚本,在编码框过滤函数中对引用变量操作,如下:
3.刷新返回结果
点击刷新按钮,最终返回结果即为创建的虚拟变量。
7)Nats变量
NATS是一个开源的消息传递系统,用于在云中或者在数据中心内部传递数据。
1.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择nats, 选择nats后会展示nats变量的面板。
2.填写nats表单中的必填项,非必填项可不填写。
3.填写完表单数据之后,确认表单中的必填项填写完成。
4.点击下一步确认后显示创建变量成功消息则表示创建成功,变量将会展示在左侧变量面板中。
8)Kafka 变量
Apache Kafka是一种高吞吐量的分布式发布订阅消息系统,用于在云中或者在数据中心内部传递数据
1.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择kafka, 选择nats后会展示kafka变量的面板。
2.填写kafka表单中的必填项,非必填项可不填写。
3.填写完表单数据之后,确认表单中的必填项填写完成。
4.点击下一步确认后显示创建变量成功消息则表示创建成功,变量将会展示在左侧变量面板中。
4.2 引用方式2——动态变量
动态变量数据来源是可变的,通过通配符可实现来源路径的变化。
配置动态变量数据源类型:
设备数据点:从设备点位中获取数据源。
实例:
步骤一:变量类型选择设备数据点;
步骤二:设置属性点动态路径,使用“{{}}”设置通配符,在数据源引用本变量时,可动态指定通配符,从而实现动态路径引用,对设备属性点,标准引用格式是“{{AssetCode}}/{{AttributeCode}}”可类似“Device_{{Num}}/Temperature”方式实现部分动态路径。
配置动态路径参数:
点击刷新按钮获取返回结果。
5. 使用变量
可在数据配置中做为数据源使用,详见配置数据源变量部分:
按钮类组件“下发变量通道”。在按钮类组件的“通道”中选择变量,即可将按钮数据下发到变量对应的数据点位:
6. 变量数据主动投递
在很多工业应用场景中都需要实时显示设备的监测数据,工业组态提供了实时数据投递能力,允许用户提前进行数据点配置,通过数据主动投递方式,将实时数据同步至组态变量中,以便于在可视化界面中展示设备实时数据。
6.1 创建变量
您可以将数据投递至除虚拟变量
外的任何变量上。
点击+
按钮,弹出创建窗口。
示例中创建固定值变量用于演示,首先定义变量名,每个变量名都不允许重复,建议用户用英文+数字来表示,如果需要分段,可以用”下划线(_)“来拼接,如 ”device_01_status“,变量描述可以是中文,主要是便于区分和管理。
选择变量类型可以选择 ”固定值“,可以指定该变量的值,如示例中指定该变量值为 ”1“,则该变量在实时数据投递前值都为 ”1“,后续可以同步设备属性值至该变量上。
当然该值可以是任意字符串,比如设备数据,该变量”device_01“ 即为设备消息数据,后续实时数据同步也可以按照设备维度进行数据投递。
变量创建成功后,可在变量详情中查看变量Code,变量Code将作为后续实时数据同步的变量唯一标识。
6.2 实时数据同步
工业组态提供了两种方式完成实时数据投递,
HTTP POST方式,适合数据更新频率较低
Nats 消息推送方式,适合数据更新频率较高
HTTP POST 方式
工业组态提供了Restful API 接口,可用于第三方程序通过API方式向工业组态投递数据,以下使用Postman工具进行测试。
curl --location --request POST 'http://127.0.0.1:7001/open/v1/tag/hub/push' \
--header 'Content-Type: application/json' \
--data-raw '[
{
"code": "tag_20n7QQ7CONEcFm2Ishmk",
"value": {
"status": 0,
"temperature": "38摄氏度"
}
},
{
"code": "tag_20YEVwpwrkmR75V7Wvv6",
"value": 1
}
]'
如上图,变量数据可以统一投递至接口 /open/v1/tag/hub/push
, 请求参数为变量数据数组,允许一次性投递多个变量数据。但是存在以下限制:
单次请求至多投递100条数据
单条投递数据大小需在10KB以下
每秒最多请求200次
Nats 消息推送方式
针对数据量大,数据更新频率高的应用场景,工业组态还提供了Nats 消息中间件方式进行实时消息同步。
Nats是一个开源的,云原生的消息系统。Apcera,百度,西门子,VMware,HTC和爱立信等公司都有在使用。
核心基于EventMachine开发,原理是基于消息发布订阅机制,每台服务器上的每个模块会根据自己的消息类别向MessageBus发布多个消息主题,而同时也向自己需要交互的模块,按照需要的主题订阅消息。能够达到每秒8-11百万个消息,整个程序很小只有3M Docker image,它不支持持久化消息,如果你离线,你就不能获得消息。使用nats streaming可以做到持久化,缓存等功能。
Nats的核心原则是性能,可伸缩和易用性。由于可伸缩性的复杂性,nats旨在容易使用和实现,且能提供多种质量的服务。一些适用nats的场景有:
高吞吐量的消息分散 —— 少数的生产者需要将数据发送给很多的消费者。
寻址和发现 —— 将数据发送给特定的应用实例,设备或者用户,也可用于发现并连接到基础架构中的实例,设备或用户。
命令和控制(控制面板)—— 向程序或设备发送指令,并从程序/设备中接收状态,如SCADA,卫星遥感,物联网等。
负载均衡 —— 主要应用于程序会生成大量的请求,且可动态伸缩程序实例。
N路可扩展性 —— 通信基础架构能够充分利用go的高效并发/调度机制,以增强水平和垂直的扩展性。
位置透明 —— 程序在各个地理位置上分布着大量实例,且你无法了解到程序之间的端点配置详情,及他们所生产或消费的数据。
容错
工业组态作为Nats的消息订阅者,用户的第三方平台只需要向指定的topic队列推送实时数据即可。
Topic有以下两种:通用Topic和变量独立Topic
通用Topic
tag/data/push
工业组态支持统一将投递数据推送至通用的Topic中,数据格式同HTTP方式,示例如下
[
{
"code": "tag_20n7QQ7CONEcFm2Ishmk",
"value": {
"status": 0,
"temperature": "38摄氏度"
}
},
{
"code": "tag_20YEVwpwrkmR75V7Wvv6",
"value": 1
}
]
所有变量实时数据都会通过这个Topic进行推送和接收。
变量独立Topic
tag/data/push/${tagCode}
对于单个变量数据更新频率非常大的应用场景,工业组态也提供了变量维度的Topic队列来推送数据至指定变量上。该模式下投递的数据必须为字符串,无需进行额外数据格式包装。
"1"
比如需要投递数据至变量 ”device_01_status“,其变量Code为 ”tag_20YEVwpwrkmR75V7Wvv6“, 则投递Topic地址则为 tag/data/push/tag_20YEVwpwrkmR75V7Wvv6
代码示例
Golang 示例如下
package main
import (
"encoding/json"
"time"
nats "github.com/nats-io/nats.go"
)
type TagPushData struct {
Code string `json:"code"`
Value interface{} `json:"value"`
Timestamp int64 `json:"timestamp"`
}
type NatsDriver struct {
conn *nats.Conn
subMap map[string]*nats.Subscription
}
func (n *NatsDriver) NewClient(host string, option ...nats.Option) (nc *nats.Conn, err error) {
nc, err = nats.Connect(host, option...)
n.conn = nc
return
}
func (n *NatsDriver) Subscribe(topic string, cb func(m *nats.Msg)) (err error) {
sub, err := n.conn.Subscribe(topic, cb)
n.subMap[topic] = sub
return
}
func (n *NatsDriver) Unsubscribe(topic string) (err error) {
if n.subMap[topic] != nil {
err = n.subMap[topic].Unsubscribe()
}
return
}
func (n *NatsDriver) Publish(topic string, data []byte) (err error) {
err = n.conn.Publish(topic, data)
return
}
func main() {
n := &NatsDriver{}
// 创建nats连接,提供用户名密码进行鉴权
n.NewClient("nats://127.0.0.1:4222", nats.UserInfo("iadc", "iadc@nats"))
// 方案一: 投递到通用Topic
// 按要求构建投递数据
datas := []TagPushData{
{
Code: "tag_20n7QQ7CONEcFm2Ishmk",
Value: map[string]interface{}{
"status": 1,
"temperature": "40摄氏度",
},
},
{
Code: "tag_20YEVwpwrkmR75V7Wvv6",
Value: 0,
},
}
strDatas, _ := json.Marshal(datas)
n.Publish("tag/data/push", strDatas)
time.Sleep(3 * time.Second)
// 方案二: 投递到变量指定Topic
// 原始数据即为投递数据,投递值为字符串
val := "11"
n.Publish("tag/data/push/tag_20YEVwpwrkmR75V7Wvv6", []byte(val))
time.Sleep(3 * time.Second)
}
Java代码示例
<dependencies>
<dependency>
<groupId>io.nats</groupId>
<artifactId>jnats</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.14.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
import com.fasterxml.jackson.databind.ObjectMapper;
import io.nats.client.Connection;
import io.nats.client.Nats;
import io.nats.client.Options;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class NatsDemo {
private Connection conn;
public void newClient() throws IOException {
// 建连,使用默认用户名密码
Options o = new Options.Builder().userInfo("iadc", "iadc@nats").build();
// 连接地址从组态变量控制台中获取
Connection nc = Nats.connect("nats://11.238.108.198:4222", o);
conn = nc;
}
public void publish() throws IOException, InterruptedException {
// 方案一: 投递到通用Topic
// 按要求构建投递数据
List<LinkedHashMap<String, Object>> list = new ArrayList<>();
LinkedHashMap<String, Object> map1 = new LinkedHashMap<>();
map1.put("code", "tag_20GHAEW9KGgRpS2iVkqK");
Map value = new HashMap(16);
value.put("status", 4);
value.put("temperature", "41摄氏度");
map1.put("value", value);
list.add(map1);
LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
map2.put("code", "tag_20nhGvqeRLv3ykoCNPph");
map2.put("value", 0);
list.add(map2);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(list);
System.out.println(json);
conn.publish("tag/data/push", json.getBytes(StandardCharsets.UTF_8));
//延时3秒
Thread.sleep(3000);
// 方案二: 投递到变量指定Topic
// 原始数据即为投递数据,投递值为字符串
String value2 = "14";
conn.publish("tag/data/push/tag_20nhGvqeRLv3ykoCNPph", value2.getBytes(StandardCharsets.UTF_8));
//延时3秒
Thread.sleep(3000);
}
public static void main(String[] args) throws IOException, InterruptedException {
NatsDemo natsDemo = new NatsDemo();
natsDemo.newClient();
natsDemo.publish();
System.exit(0);
}
}
投递地址查看
在变量详情中,可查看数据主动投递的投递地址
6.3 组态画面预览查看投递数据
将变量绑定至文本组件,打开 ”页面预览“ 即可查看到实时推送过来的设备数据