变量说明

变量是一个非数字符号,代表某个数据。它提供了数据定义、运算、传递功能,支持用于下发数据、数据源等配置中。

1. 创建变量

步骤一:在编辑器的资源管理中心,选择“添加资源”” ,点击“添加变量”按钮。

image..png

步骤二:配置

按照规则填入配置变量的名称、描述,引用方式(静态、动态)。

image..png

步骤三:选择文件夹

选择该变量要放置文件夹的位置

image..png

2. 编辑变量

在变量卡片中双击,弹出变量编辑框。在弹窗中可以修改变量的名称、描述、值等配置,也可查看变量code等信息。

截屏2023-01-16 下午5

可通过点击变量卡片下部的编辑按钮,编辑变量名称后按“Enter”键或者点击别处,修改变量名称。

image..pngimage..png

3. 删除变量

  1. 可以选中某个变量后,点击“删除”选项。

image..png
  1. 也可以通过选中某个变量,点击右下角的删除按钮,来删除某个变量。

  2. 若要批量删除变量,可选中多个变量后,点击“删除选中”按钮。

image..png

4. 变量引用方式

4.1. 引用方式1——静态变量

静态变量数据来源是固定的不变的。

配置静态变量数据源类型:

  1. HTTP接口:数据源从HTTP接口中获取;

  2. 设备数据点:从设备点位中获取数据源;

  3. 固定值:手动输入一些静态的数据;

  4. 数据库:从数据库中获取变量类型;

  5. MQTT:通过网络连接发送的信息数据包;

  6. 告警变量:设备告警类数据;

  7. 文件:.csv / .json / .xlsx后缀的文件内容作为变量

  8. 虚拟变量:几个变量通过过滤器进行加减乘除等操作后返回得到一个虚拟变量。

1)设备属性点示例

配合数采一体机使用时,组态系统默认集成了设备属性列表,在变量类型中选择设备属性点,在选择属性栏可以根据设备模板选择具体的设备实例,再选择设备属性,即可将设备属性值匹配到变量上。

imageimage

选择设备属性后,可以继续填写数据过滤脚本,对已获取到的设备属性值进行二次加工。

2)数据库示例

1.配置变量为静态引用方式下的数据库类型,其中数据库类型分为PgSQL(功能强大的开源对象系统管理系统)、MySQL(关系类型数据库管理系统)、SqlServer(微软推出的关系数据库管理系统)

2.配置数据库类型以及数据库的地址、端口数据库名称用户名和地址,点击配置栏右上方按钮可以检查连接配置是否有效。

配置数据库

3.设置数据源默认值:勾选设置数据源默认值,未接收到有效数据返回时预置的默认值,用于保证初始显示效果。收到首次返回即失效。

默认值

4.配置完成点击确定,即创建了一个数据库类型的变量

注:版本限制

MySQL 5.6及以上

PostgreSQL 11 及以上

SQL Server 2005 及以上

3)MQTT变量示例

1.配置引用变量

数据来源选择MQTT变量,配置MQTT协议的host(接入地址)、port(端口)、topic(主题)、用户名及密码。

mqtt

4)告警变量示例

告警变量需选择监听告警的设备模板、设备、告警级别、告警类型。常用于告警类组件。

截屏2022-08-30 下午3

5)文件变量示例

  1. 在资源管理中,选中某个文件夹,点击“添加资源”按钮,点击“添加变量”

image..png

2.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择文件, 选择文件后会展示文件变量的面板

image

3.点击上传文件按钮, 文件类型支持 csv / json / xlsx 格式, 上传之后会展示文件解析结果

image

image

4.确认解析内容无误之后,点击确认按钮创建变量, 显示创建变量成功的提示则表示创建成功。

image

文件类变量可以用在柱状图等图表组件的数据源中。

6)虚拟变量示例

1.配置引用变量

数据来源选择虚拟变量,选择需要的引用变量(不能少于一个),默认为两个,可添加或删除引用变量,点击刷新按钮返回结果为由几个引用变量组合成的虚拟变量。

变量345

2.配置数据过滤脚本

勾选数据过滤脚本,在编码框过滤函数中对引用变量操作,如下:

勾选过滤器

3.刷新返回结果

点击刷新按钮,最终返回结果即为创建的虚拟变量。

返回结果

7)Nats变量

NATS是一个开源的消息传递系统,用于在云中或者在数据中心内部传递数据。

1.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择nats, 选择nats后会展示nats变量的面板。

image

image

2.填写nats表单中的必填项,非必填项可不填写。

image

3.填写完表单数据之后,确认表单中的必填项填写完成,点击确认按钮创建变量, 显示创建变量成功toast则表示创建成功,变量将会展示在footerPanel中。

image

8)Kafka 变量

Apache Kafka是一种高吞吐量的分布式发布订阅消息系统,用于在云中或者在数据中心内部传递数据

1.点击创建变量后,出现创建变量弹窗, 在变量类型下拉框中选择kafka, 选择nats后会展示kafka变量的面板。

image

image

2.填写kafka表单中的必填项,非必填项可不填写。

image

3.填写完表单数据之后,确认表单中的必填项填写完成,点击确认按钮创建变量, 显示创建变量成功toast则表示创建成功,变量将会展示在footerPanel中。

image

4.2 引用方式2——动态变量

动态变量数据来源是可变的,通过通配符可实现来源路径的变化。

配置动态变量数据源类型:

设备数据点:从设备点位中获取数据源。

实例:

image

步骤一:变量类型选择设备数据点;

步骤二:设置属性点动态路径,使用“{{}}”设置通配符,在数据源引用本变量时,可动态指定通配符,从而实现动态路径引用,对设备属性点,标准引用格式是“{{AssetCode}}/{{AttributeCode}}”可类似“Device_{{Num}}/Temperature”方式实现部分动态路径。

image

配置动态路径参数:

动态1--4

点击刷新按钮获取返回结果。

5. 使用变量

  1. 可在数据配置中做为数据源使用,详见配置数据源变量部分:

截屏2023-01-17 上午10

  1. 按钮类组件“下发变量通道”。在按钮类组件的“通道”中选择变量,即可将按钮数据下发到变量对应的数据点位:

按钮变量

6. 变量数据主动投递

在很多工业应用场景中都需要实时显示设备的监测数据,工业组态提供了实时数据投递能力,允许用户提前进行数据点配置,通过数据主动投递方式,将实时数据同步至组态变量中,以便于在可视化界面中展示设备实时数据。

6.1 创建变量

您可以将数据投递至除虚拟变量外的任何变量上。

在指定的资源文件夹下,点击创建变量按钮。

image

示例中创建固定值变量用于演示,首先定义变量名,每个变量名都不允许重复,建议用户用英文+数字来表示,如果需要分段,可以用”下划线(_)“来拼接,如 ”device_01_status“,变量描述可以是中文,主要是便于区分和管理。

选择变量类型可以选择 ”固定值“,可以指定该变量的值,如示例中指定该变量值为 ”1“,则该变量在实时数据投递前值都为 ”1“,后续可以同步设备属性值至该变量上。

image

当然该值可以是任意字符串,比如设备数据,该变量”device_01“ 即为设备消息数据,后续实时数据同步也可以按照设备维度进行数据投递。

image

变量创建成功后,可在变量详情中查看变量Code,变量Code将作为后续实时数据同步的变量唯一标识。

6.2 实时数据同步

工业组态提供了两种方式完成实时数据投递,

  1. HTTP POST方式,适合数据更新频率较低

  2. Nats 消息推送方式,适合数据更新频率较高

HTTP POST 方式

工业组态提供了Restful API 接口,可用于第三方程序通过API方式向工业组态投递数据,以下使用Postman工具进行测试。

image
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, 请求参数为变量数据数组,允许一次性投递多个变量数据。但是存在以下限制:

  1. 单次请求至多投递100条数据

  2. 单条投递数据大小需在10KB以下

  3. 每秒最多请求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();
        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));

        Thread.sleep(3000);    //延时3秒

        // 方案二: 投递到变量指定Topic
        // 原始数据即为投递数据,投递值为字符串
        String value2 = "14";
        conn.publish("tag/data/push/tag_20nhGvqeRLv3ykoCNPph", value2.getBytes(StandardCharsets.UTF_8));

        Thread.sleep(3000);    //延时3秒
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        NatsDemo natsDemo = new NatsDemo();
        natsDemo.newClient();
        natsDemo.publish();
        System.exit(0);
    }
}

投递地址查看

在变量详情中,可查看数据主动投递的投递地址

image

6.3 组态画面预览查看投递数据

将变量绑定至文本组件,打开 ”页面预览“ 即可查看到实时推送过来的设备数据

image

阿里云首页 工业互联网平台 相关技术圈