万维组态绑点示例文档

   演示地址:http://121.40.16.189:12000

  1. 万维组态本地部署文档
  2. 万维组态线上部署文档
  3. 万维组态操作说明文档
  4. 万维组态接入文档
  5. 万维组态绑点示例文档
  6. 万维组态接入源代码说明
  7. 万维组态扩展图元示例文档
  8. 万维组态大屏图元示例文档

万维组态架构图

万维组态数据通讯架构图

1、创建模版及点位

绑点操作1

(1)点击左侧菜单数据模版管理菜单 ;(2)点击新增按钮;(3)输入模版名称,添加数据点位;

注意: 添加数据点位时,【点位属性】这个字段是我们在数据通信的时候的键,举例如下: 如上图中,我们添加了4个点位,那我们在数据通信的时候,消息体如下,

{
    'wd': 0,
        'sd': 0.5,
        'fg': 1,
        'sw': 1.2
}

2、创建组态及关联模版

绑点操作2

(1)点击左侧菜单组态管理管理菜单 ;(2)点击新增按钮;(3)输入组态名称;(4)选择数据模版;

新增一个组态,绑定刚刚添加的模版

3、设置数据源

3.1、MQTT数据源

绑点操作3

(1)点击左侧菜单组态管理管理菜单打开组态列表 ;(2)找到刚刚添加的组态;(3)点击列表最后一栏[【操作】栏目中的数据源配置;(4)选择【MQTT】;

连接地址:地址中可以设置动态参数占位符,如:ws://localhost:8083/mqtt/{{a1}}/{{a2}}/point, 我们在代码中解析到这个地址时, 会从编辑器组件的对象参数【initOptions】中取键为 【a1】和【a2】的值进行替换,initOptions的设置请参考【src/views/editor.vue】 或【src/views/preview.vue】中;而在【src/views/home.vue】中,我们会把路由参数全部合并到initOptions中去,从而达到参数动态的效果;

客户端id:MQTT连接的clientId,这里不设置源码中会默认生成;

用户名:MQTT连接的认证账号用户名;

密码:MQTT连接的认证账号密码;

3.2、websocket数据源

绑点操作4

(1)点击左侧菜单组态管理管理菜单打开组态列表 ;(2)找到刚刚添加的组态;(3)点击列表最后一栏[【操作】栏目中的数据源配置;(4)选择【WebSocket】;

连接地址和[3.1]中的地址一样可以设置动态参数, 我们管理后端java服务中就开启了一个websocket服务,在【com.rcscada.common.utils.websocket.WebSocketServer类中, 服务地址: ws://localhost:8089/app/ws/{{deviceId}}, {{deviceId}} 是组态id,所以我们编辑器在连接这个服务时,就会把{{deviceId}}替换成组态id去连接;

协议:WebSocket的protocols参数,多个请用英文;分割.

3.3、http数据源

绑点操作5

(1)点击左侧菜单组态管理管理菜单打开组态列表 ;(2)找到刚刚添加的组态;(3)点击列表最后一栏[【操作】栏目中的数据源配置;(4)选择【HTTP】;

数据源域名:http数据源的请求域名 它是轮询请求和事件请求两个接口的域名部分,如:http://127.0.0.1:8080或http://www.xxx.com;格式:[协议://域名:端口]();

轮询请求接口:和MQTT/websocket不同,http源需要我们的组态主动请求点位数据,所以我们这里就要设置域名和接口等信息; 这部分需要我们在业务系统中自己开发,将点位数据通过接口的形式返回给编辑器;支持动态参数{{}}

轮询周期:轮询请求接口的请求周期,如上图我们设置了 5000毫秒,也就是5秒,这个频率可以根据实际情况来做调节;

轮询请求头:轮询请求接口如果有需要传递的请求头部信息,就在这里定义,如上我们定义了token和ContentType两个参数,其中token是动态的,ContentType为静态的 ${token={{token}}}${ContentType=application/json},格式:${key=value},其中key为属性名,value为属性值, value如果是动态的就使用我们的动态参数替换,如:${key={{value}}}

轮询请求参数:轮询请求接口如果有需要传递的请求参数,就在这里定义,如上我们定义了params1、params2和deviceId三个参数,params1和deviceId为动态参数,params2为静态的 ${params1={{params1}}}${params2=100}${deviceId={{deviceId}}},格式和轮询请求头的格式一样

【轮询请求接口】响应体固定如下

{
    code: 0, //成功 非0 就是失败
        msg: 'success',
        data: JSON.stringify({
        'wd': 0,
        'sd': 0.5,
        'fg': 1,
        'sw': 1.2
    })// 点位数据的json字符串 一定为字符串,否则没效果
}

注意 点位数据一定要是 JSON string

事件请求接口:格式和轮询请求接口一样,区别在于编辑器中绑定了反向控制事件时,触发事件后调用此接口; 事件请求头:与轮询请求头一样; 事件请求参数:格式和轮询请求参数一样;自定义请求参数 + message

【事件请求接口】请求参数固定如下

// 发送反向修改点位值
{
    params1: {{params1}},//事件请求参数中设置的
    params2: 100,//事件请求参数中设置的
    deviceId={{deviceId}},//事件请求参数中设置的
    message: JSON.stringify({
        deviceId: '组态id',
        type: 'changePointValue',
        data: {
            key: '点位属性',
            value: '需要修改的新值'
        }
    })// message 是固定的 所以定义事件请求参数时不要定义成'message'
}
// 发送反向控制指令
{
    params1: {{params1}},//事件请求参数中设置的
    params2: 100,//事件请求参数中设置的
    deviceId={{deviceId}},//事件请求参数中设置的
    message: JSON.stringify({
        deviceId: '组态id',
        type: 'ctrlCommand',
        data: {
            command: '绑定时设置的指令值',
        }
    })// message 是固定的 所以定义事件请求参数时不要定义成'message'
}

点位数据 json字符串数据】:

// 点位数据 json字符串数据 下面会用到这个
JSON.stringify({
    'wd': 0,
    'sd': 0.5,
    'fg': 1,
    'sw': 1.2
})

【事件请求接口】响应体固定如下

{
    code: 0, //成功 非0 就是失败
        msg: 'success'
}

从【轮询请求接口】和【事件请求接口】响应体可以看到是固定的

{
    code: 0,
        msg: 'success',
        data: JSON.stringify({
        'wd': 0,
        'sd': 0.5,
        'fg': 1,
        'sw': 1.2
    })
}

我们编辑器判断响应体的code === 0才是成功,点位数据是存放在【data】字段中的所以为了让编辑器能够识别, 如果【轮询请求接口】和【事件请求接口】返回的响应体内容不是以上格式, 就需要我们在上图的右边代码区配置转换方法, 默认已写入:

const response = arguments[0];
return response.data;

以上 response是我们将axios的response注入到这个转换方法体的, response的键值如下:

{
    "data": {
        "resCode": 200,
            "resMsg": '成功',
            "resData": Object
    },
    "status": 200,
        "statusText": "OK",
        "headers": {
        "connection": "close",
            "content-type": "application/json",
            "date": "Fri, 29 Dec 2023 07:50:31 GMT",
            "transfer-encoding": "chunked",
            "vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
            "x-content-type-options": "nosniff",
            "x-powered-by": "Express",
            "x-xss-protection": "1; mode=block"
    },
    "config": {
        "transitional": {
            "silentJSONParsing": true,
                "forcedJSONParsing": true,
                "clarifyTimeoutError": false
        },
        "transformRequest": [
            null
        ],
            "transformResponse": [
            null
        ],
            "timeout": 10000,
            "xsrfCookieName": "XSRF-TOKEN",
            "xsrfHeaderName": "X-XSRF-TOKEN",
            "maxContentLength": -1,
            "maxBodyLength": -1,
            "headers": {
            "Accept": "application/json, text/plain, */*",
                "Authorization": "Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjQ1N2Y3NDJkLWQ1NzktNGY0Ni04YTI1LTZhMjY4MjYwY2ZiMSJ9.ULxPQnH1yYOUE9MR0YtTQ9mJb2S32XUqY64NnsS2zfkQRxv_qKZtXcoqpNy_J3FAa-eP6um0KXPnRLvMwnU0Zg"
        },
        "baseURL": "/dev-api",
            "url": "/system/dict/data/type/data_source_type",
            "method": "get"
    },
    "request": {}
}

从如上返回信息中我们可以看到 data 不是我们想要格式{code, msg, data},而是{resCode, resMsg, resData} 这个时候转换区的代码就该如下:

const response = arguments[0];
if(response.status === 200 && response.data){
    // http 状态正常
    const oldData = response.data;
    // 你自己业务系统的状态码 resCode == 200 为成功,转换到我们这边就是
    const data = {
        code: oldData.resCode == 200 ? 0 : -1,// 0成功,非0失败
        msg: oldData.resMsg,
        data: oldData.resData,
        // 注意 轮询请求接口 这个地方需要【点位数据】json string,如果oldData.resData不是上面的 【点位数据json字符串数据】 时
        // 就可以在这里做转换 把它转换成我们想要的格式
        // 如何判断是不是 【轮询请求接口】可以用response.config.url来和我们填写的【轮询请求接口】进行对比;
    }
}

return response.data;

注意 轮询请求接口 这个地方需要【点位数据】json string,如果oldData.resData不是上面的 【点位数据json字符串数据】 时, 就可以在这里做转换 把它转换成我们想要的格式。 如何判断是不是 【轮询请求接口】可以用response.config.urlji就是我们填写的【轮询请求接口】或【事件请求接口】;

4、变量的创建与使用

首先在组态列表中我们刚添加的组态后面点击【组态设计】进入编辑器编辑组态内容;点击右边【配置虚拟变量】;可以看到我们生成了4个变量; 这是我们编辑器自动生成的,如果不想使用可以不用管;我们重点看看新增变量;如下图: 

绑点操作6

4.1、变量的属性介绍

变量:我们这里的变量不是通常意义上的变量,是有本质区别的,我们这里的变量是虚拟的,是我们自己构造出来的,它的变量值是由我们的自定义算法计算出来的;

随便点击一个系统生成的变量后边的设置【按钮】,右边的表单区域就会显示对应的变量信息;变量的属性主要有5个属性:

4.1.1、变量名称

变量名称:变量的名称,每个变量都有属于自己的名称,便于区别记录;

4.1.2、变量类型

变量类型:和点位值类型是一样的,也是有三种类型,整型、浮点型和字符串,这个属性就是下面的自定义算法的返回值类型;

4.1.3、默认值

默认值:就是算法默认值,如果算法中出现异常或者没有返回值,变量的值就是这个值;

4.1.4、数据点位

数据点位:这里的左边显示的点位列表就是我们在创建模版时添加的数据点位,这里是多选,意味着可以选择n个点位,那么这n个点位的实时值 就会被我们注入到自定义算法的第一个形参里面,第二个形参就是【4.1.3】中的默认值;比如我们在调用的时候就是如下

自定义算法名([点位值1,点位值2,点位值3,...], 默认值);

我们会把所有点位值按选择的顺序放到数组中,然后在作为自定义算法的第一个形参中;

4.1.5、自定义算法

自定义算法: 算法是我们变量的核心,一切皆变量;在自定义算法中, 我们可以像在普通js方法中一样写我们想要的结果的代码,它的参数就是我们选择 的点位值,也就是说,可以用n个点位值,通过这个方法得到我们想要的结果,然后把这个值给到我们绑定的图元上,达到我们的就控制显示效果;

4.2、变量应用场景举例
4.2.1、返回一个点位实时值的变量

只选择一个数据点位参与计算,变量值的类型就是点位值的类型,直接返回改点位值的变量。其实,我们系统生成的这 四个变量就是这种变量,就是点位值原值输出,什么换算都不做;如果我们像直接取某个点位的值就用这种变量;

4.2.2、将一个点位值缩小1000倍的变量

(1)首先在【数据模版管理】中添加一个数据点位,叫‘测点电压’,它的点位值类型为浮点型; 

绑点操作8

(2) 在编辑器的配置虚拟变量面板中点击【新增】按钮添加一个变量;如下图所示:

绑点操作7

设置:

变量名称:测点电压(kv),顾名思义这个变量返回一个单位为 kv的值;

变量类型:浮点型 ,【测点电压】点位的类型为浮点型,缩小1000倍还是浮点型;

默认值:0;

数据点位:只选择 【测点电压】;

自定义算法:算法内容如下

const params = arguments[0];
const defaultValue = arguments[1];
try{
    if(!params || params.length <= 0) return defaultValue;
    let dyValue = params[0];
    // dyValue数量级单位是 V 缩小1000倍 数量级单位为 KV
    dyValue = parseFloat(dyValue) / 1000
    return dyValue;
} catch (e) {
    return defaultValue;
}

从参数arguments 中取出 arguments[0], 里面存放的就是点位值的数组也就是: [测点电压值],所以我们要获取 测点电压值电压值的话就是这样获取:arguments[0][0],对应到我们的算法中的代码就是

const params = arguments[0];
let dyValue = params[0];

dyValue就是arguments[0][0],就是【测点电压值】; 这个电压值的单位是 v(伏),我们要转化为 kv(千伏),dyValue就要缩小1000倍;对应的代码就是:

dyValue = parseFloat(dyValue) / 1000;

然后 return dyValue; 返回了这个缩小了1000倍的电压值;

注意自定义算法为了规范一定要有返回值;

4.2.3、三个开关的状态决定电灯是否开关的变量

我们规定 开关状态有两种:开为1 关为0;电灯状态有两种:1点亮,2熄灭; 这里有个三个开关控制的电灯,是一个三控开关系统,其中一个开关开,电灯就会点亮,所有开关关,电灯就熄灭;

(1)首先在【数据模版管理】中添加三个数据点位,叫‘开关1、开关2、开关3’,这三个点位的值类型类整型,并且取值为只有 0或1; 定义0为关,1为开, 

绑点操作9

 (2) 在编辑器的配置虚拟变量面板中点击【新增】按钮添加一个变量;如下图所示:

绑点操作10

设置:

变量名称:电灯状态控制变量;

变量类型:整型; 1点亮,2熄灭;

默认值:0;默认关闭;

数据点位:选择3个点位, 开关1、开关2、开关3;

自定义算法:算法内容如下

const params = arguments[0];
const defaultValue = arguments[1];
try{
    if(!params || params.length <= 0) return defaultValue;
    let kg1Value = params[0];
    let kg2Value = params[1];
    let kg3Value = params[2];
    let status = kg1Value == 1 || kg2Value == 1 || kg3Value == 1;
    return status ? 1 : 0;
} catch (e) {
    return defaultValue;
}

从参数arguments 中取出 arguments[0], 里面存放的就是点位值的数组也就是: [开关1值,开关2值,开关3值],所以我们要获取 开关1、开关2、开关3的状态值的话就是这样获取:arguments[0][0]、arguments[0][1]、arguments[0][2],对应到我们的算法中的代码就是

const params = arguments[0];
let kg1Value = params[0];// 开关1状态
let kg2Value = params[1];// 开关2状态
let kg3Value = params[2];// 开关3状态

电灯状态值计算如下

let status = kg1Value == 1 || kg2Value == 1 || kg3Value == 1;
return status ? 1 : 0;

然后 return status ? 1 : 0; 返回了电灯要么开1, 要么关0;

5、图元绑定变量

5.1、变量控制图元状态

5.1.1、创建变量控制图元

4.2.3中【电灯状态控制变量】到图元 在编辑器图元菜单的【控制组件】栏目中拖拽一个【状态图片】图元到画布中, 

绑点操作11

5.1.2、绑定变量

根据上图操作后,电灯状态控制变量就和电灯图元绑定上了;

注意最后一定要点击右上角保存按钮同步到服务器; ctrl + S 只会保存到本地;

5.1.3、模拟发布三个开关点位值切换图元状态

点击右上角预览;这时我们可以去 emqx websocket客户端模拟发送点位数据;

(1)topic为: topic/preview/subscribe/device/{deviceId} 发送数据为:{'kg1':0,'kg2':0,'kg3':0}

绑点操作12

预览界面收到消息:点位数据是 {'kg1':0,'kg2':0,'kg3':0} 

绑点操作13

 此时电灯显示的是关状态的图片;

(2)再次发送点位数据 {'kg1':1,'kg2':0,'kg3':0}

预览界面收到消息:点位数据是 {'kg1':0,'kg2':0,'kg3':0} 

绑点操作14

 此时电灯显示的是开状态的图片;

5.2、将变量值显示到图元上

5.2.1、创建图元;

将变量值显示到图元上在编辑器图元菜单的【控制组件】栏目中拖拽一个【变量文本】图元到画布中, 

绑点操作15

5.2.2、绑定变量

根据上图操作后,我们把在【4.2.2】步骤中创建的 测点电压(kv)变量就和显示电压的变量文本图元绑定了,我们给这个图元取名为 【测点电压文本】,它由两部分组成,数值区和单位区,单位区显示固定文本 ‘千伏’;

5.2.3、模拟发布测点电压点位值切换图元显示的电压

点击右上角预览;这时我们可以去 emqx websocket客户端模拟发送点位数据;

(1)topic为: topic/preview/subscribe/device/{deviceId} 发送数据为:{"dy":1500,"kg1":1,"kg2":0,"kg3":0}

绑点操作16

如需了解更多关于万维组态,请添加微信:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值