# 操作手册

# 通用物模型

# 1.概述

物模型是产品数字化的描述,定义了产品的功能,物模型将不同品牌不同品类的产品功能抽象归纳,形成“标准物模型”,便于各方用统一的语言描述、控制、理解产品功能。 物模型由若干条“参数”组成,参数按描述的功能类型不同,又分为属性、功能和事件。

# 2.功能说明

物模型是物理空间中的实体(如传感器设备、消防装置、园区、工厂等)在云端的数字化表示,属性、功能、事件三个维度,分别描述了该实体是什么、能做什么、可以对外提供哪些信息、可以自定义补充哪些信息。定义了物模型的这三个维度,即完成了产品功能的定义。

类型 说明
属性 用于描述设备运行时具体信息和状态。例如,环境监测设备所读取的当前环境温度、智能灯开关状态、电风扇风力等级等。属性可分为读、写和上报三种类型,即支持读取、设置属性、设备上报属性。 当属性数据来源为“规则”时,则称该属性为规则属性。
功能 指设备可供外部调用的指令或方法。服务调用中可设置输入和输出参数。输入参数是服务执行时的参数,输出参数是服务执行后的结果。相比于属性,服务可通过一条指令实现更复杂的业务逻辑,例如执行某项特定的任务。
事件 设备运行时,主动上报给云端的信息,一般包含需要被外部感知和处理的信息、告警和故障。事件中可包含多个输出参数。例如,某项任务完成后的通知信息;设备发生故障时的温度、时间信息;设备告警时的运行状态等。事件可以被订阅和推送。

# 3.物模型支持的数据类型

参数 说明 示例
int 整型 100
double 小数型 100.45
boolean 布尔型。采用0(false)或1(true)来定义布尔值 1表示是、0表示否
enum 枚举型。定义枚举项的参数值和参数描述。 [{key:1,value:1}]
string 字符串 你好!中科智电物联网平台
array 数组。需声明数组内的元素类型、数组元素个数和元素标识。需确保同一个数组元素类型相同。 [1, 2, 3, 4, 5, 6]
Object 对象型 [{id:"Object",name:"对象",datatype:{type:"object",params:[{key1:value1}]}}]

# 4.操作步骤

1.登陆中科智电物联网物联网平台。  
2.左侧导航栏,选择设备管理>通用物模型 
3.点击  "新增" 按钮,根据设备实际情况,合理设计物模型  
1
2
3

# 4.1.物模型定义

在接入一个设备时,首先根据设备以及设备接入文档(报文说明), 将设备物模型的属性、功能以及事件设计好。  
属性用于定义一些指标数据,如:电压,温度等。 属性都应该是简单的数据类型  
功能用于定义设备具有的一些可执行动作  
事件用于定义设备在特定条件时,发生的动作  
1
2
3
4

# 4.2.物模型新增

配置项 说明
模型名称 必填,物模型名称
模型标识 必填,后端识别的标识符
模型排序 必填,物模型展示顺序
模型类别 必选,属性、功能、事件
模型特性 勾选,属性:图表展示,实时监测,是否只读数据,历史存储,分享权限(注意:图表展示、实时监测仅支持整数和小数)。 功能:是否只读数据,是否进行历史存储,分享权限。 事件:默认只读,是否进行历史存储,分享权限
数据类型 单选下拉框,整数、小数、布尔、枚举、字符串、数组、对象
取值范围 仅整数和小数显示,取值区间,最小值和最大值
单位 仅整数和小数显示,如:元,℃
步长 仅整数和小数显示,取值间隔,步长是指设备上报或下发数值时,递增或递减的间隔。
计算公式 仅整数和小数显示,加减乘除计算
布尔值 布尔类型显示,0、1对应文本(打开或关闭)
展示方式 仅枚举类型显示,单选下拉框
枚举项 [{key:1,value:1}]
最大长度 仅字符串类型显示,字符串的最大长度
数组类型 仅数组类型显示,单选,整数、小数、字符串、对象
元素个数 仅数组类型显示,数组元素个数
元素标识 仅数组类型显示,每个元素的序号标识,可根据具体情况配置,比如:子设备 1、3、5
对象参数 仅 数组--对象 类型显示,在数组中添加具体的对象参数

# 5.配置物模型

配置设备模型分为: 属性properties,功能functions,事件events。
设备模型使用场景:
1. 前端通过模型定义动态展示设备运行状态或者设备操作界面
2. 服务端可通过统一的API获取设备模型并进行相关操作,如:在发送设备消息时进行参数校验, 在收到设备消息进行类型转换处理。
数据结构:
1
2
3
4
5
    {
    "properties":[...属性],
    "functions":[...功能],
    "events":[...事件],
    "tags":[...标签]
    }
1
2
3
4
5
6

# 属性

用于定义设备属性,描述设备运行时的具体信息和状态。
例如: 设备温度,co2等。 平台可主动下发指令获取设备属性,设备也可以通过消息上报属性。
1
2

# 数据结构

    {
  "properties": [
    {
      "id": "co2",
      "name": "二氧化碳",
      "isChart": 1,
      "isMonitor": 1,
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 1,
      "datatype": {
        "max": 6000,
        "min": 100,
        "step": 1,
        "type": "integer",
        "unit": "ppm"
      }
    },
    {
      "id": "temperature",
      "name": "空气温度",
      "isChart": 1,
      "isMonitor": 1,
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 1,
      "datatype": {
        "max": 120,
        "min": -20,
        "step": 0.1,
        "type": "decimal",
        "unit": "℃"
      }
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 功能

根据设备可供外部调用的指令或方法,定义设备功能。平台可主动调用设备功能。例如:设备运行档位、开关操作等。
数据结构:
1
2
    {
  "functions": [
    {
      "id": "status",
      "name": "上报状态",
      "isHistory": 0,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "enum",
        "showWay": "button",
        "enumList": [
          {
            "text": "更新状态",
            "value": "update_status"
          }
        ]
      }
    },
    {
      "id": "irc",
      "name": "射频遥控",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "enum",
        "showWay": "button",
        "enumList": [
          {
            "text": "遥控学习",
            "value": "FFXX01"
          },
          {
            "text": "遥控清码",
            "value": "FFXX02"
          },
          {
            "text": "打开开关",
            "value": "FFXX03"
          },
          {
            "text": "关闭开关",
            "value": "FFXX04"
          },
          {
            "text": "暂停",
            "value": "FFXX05"
          },
          {
            "text": "锁定",
            "value": "FFXX06"
          }
        ]
      }
    },
    {
      "id": "report_monitor",
      "name": "上报数据",
      "isHistory": 0,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "max": 10,
        "min": 1,
        "step": 1,
        "type": "integer",
        "unit": "次数"
      }
    },
    {
      "id": "switch",
      "name": "设备开关",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "bool",
        "trueText": "打开",
        "falseText": "关闭"
      }
    },
    {
      "id": "gear",
      "name": "运行档位",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "enum",
        "showWay": "select",
        "enumList": [
          {
            "text": "低速档位",
            "value": "0"
          },
          {
            "text": "中速档位",
            "value": "1"
          },
          {
            "text": "中高速档位",
            "value": "2"
          },
          {
            "text": "高速档位",
            "value": "3"
          }
        ]
      }
    },
    {
      "id": "message",
      "name": "屏显消息",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "string",
        "maxLength": 1024
      }
    },
    {
      "id": "reset",
      "name": "设备重启",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "enum",
        "showWay": "button",
        "enumList": [
          {
            "text": "重启",
            "value": "restart"
          }
        ]
      }
    },
    {
      "id": "array_01_light_color",
      "name": "灯光色值1",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "max": 100,
        "min": 0,
        "step": 1,
        "type": "integer",
      }
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

# 事件

用于设备的额外属性,添加拓展字段。例如:环境温度过高、设备发生异常等。
数据结构:
1
2
    {
  "functions": [],
  "events": [
    {
      "id": "height_temperature",
      "name": "环境温度过高",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "max": 100,
        "min": 0,
        "step": 0.1,
        "type": "decimal",
        "unit": "℃"
      }
    },
    {
      "id": "exception",
      "name": "设备发生异常",
      "isHistory": 1,
      "isSharePerm": 0,
      "isReadonly": 0,
      "datatype": {
        "type": "string",
        "maxLength": 1024
      }
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 6.产品与设备物模型关系

产品有物模型配置。一个产品可以添加多个设备。设备会继承产品下所有的物模型配置。  
1

# 产品管理

# 产品管理介绍

产品是设备的集合,通常是对同类型、同型号物理设备的描述。
例如,产品指同一个型号的产品,设备就是该型号下具体的某个设备。
你可以通过本文了解 产品 相关的功能。

# 1.概述

产品列表页面提供数据筛选、新增产品、数据列表三个功能模块。

# 2.新增

点击 "+ 新增" 按钮,打开新增产品窗口

配置项 说明
产品名称 必填,产品名
产品分类 必填,单选下拉框
设备类型 必填,单选下拉框
通讯协议 必填,单选下拉框
传输协议 必填,单选下拉框
联网方式 必填,单选下拉框
私有产品 开关,设置为私有后下级不能查看
启用授权 开关,设备授权功能,默认不启用
认证方式 必填,设备接入认证方式,单选下拉框
定位方式 必填,单选下拉框
产品编号 系统自动生成
Mqtt账号 可选,不填系统自动生成
Mqtt密码 可选,不填系统自动生成
产品密钥 可选,不填系统自动生成
备注信息 非必填输入框

产品创建成功弹窗,点击确定之后可以看到产品详情,可以开始定义物模型或者配置

# 3.产品详情

产品详情页面包括基本信息、设备授权、组态应用

基本信息-->可以进行一些基本信息的修改   
1

设备授权-->可选功能,用于设备认证  
1

# 4.发布产品

新建产品默认为未发布状态。完成产品定义后,点击 "发布产品" 按钮启用之后可以创建对应该产品的设备  
1

# 设备管理

创建并发布产品后,可以在当前页面为产品添加设备。
你可以通过本文了解设备的相关功能。

# 1.概述

设备列表页面提供数据筛选、新增设备、数据列表三个功能模块。

# 2.新增设备

点击 "+新增设备" 按钮,选择 "手动添加" 按钮,打开 新增设备 窗口  
1

配置项 说明
设备名称 必填,设备名
所属产品 选择按钮,选择对应产品
设备编号 可自定义(设备编号需大于9位),也可以点击 "生成" 按钮自动生成
固件版本 必填,默认为1
设备影子 开关按钮,是否启用影子模式
禁用设备 开关按钮,是否禁用设备
备注信息 可选,输入框
定位方式 单选框,单个设备定位方式修改,默认继承产品定位方式
设备经度 设备经度,定位方式为 "自定义位置" 时可手动填入,其他方式不支持填入
设备纬度 设备纬度,定位方式为 "自定义位置" 时可手动填入,其他方式不支持填入
所在地址 设备所在地址,定位方式为 "自定义位置" 时可手动填入,其他方式不支持填入
入网地址 只读,设备接入时的入网ip
激活时间 只读,设备首次接入系统时的时间
设备信号 只读,设备信号强度

# 3.设备详情

设备详情--基本信息  
1

设备详情--运行状态      
1

设备详情--设备定时   
1

设备详情--设备分享,终端用户使用分享功能,这儿查看设备被终端用户绑定和分享的关系   
1

设备详情--事件日志   
1

设备详情--告警用户,配置告警需要通知的用户   
1

设备详情--设备告警    
1

设备详情--指令日志    
1

设备详情--实时监测    
1

设备详情--监测统计    
1

# 4.分配设备

将设备分配给具体的机构
1

# 5.设备回收

将分配出去的设备进行回收  
1

# 6.批量操作

# 6.1.批量新增设备

点击  "新增设备"  按钮, 选择  "批量导入"  按钮,下载设备导入模板
1

将批量生成的设备编号填入导入模板,填写设备名称   
1

打开批量导入页面,选择对应产品,上传模板
1

导入成功界面
1

# 6.2.批量分配设备

点击  "分配设备"  按钮, "导入分配"  按钮,下载模板,将设备名称和设备编号填入模板上传
1

# 场景联动

场景联动可以通过可视化的方式定义设备之间联动的规则,配置界面如下:

配置说明:

  1. 触发条件:所有条件,任意条件,不满足。所有条件需要所有触发器都满足才会去执行动作,任意条件满足其中一个即可,不满足只能包含一个触发器。
  2. 触发方式:设备触发,产品触发,定时触发。设备触发可以指定一个或多个设备触发,产品触发时产品下面所有设备都会去匹配规则,定时触发使用cron表达式定时执行一次。
  3. 动作方式:设备执行,产品执行,告警执行。设备执行可以指定一个或多个设备执行,产品执行时产品下面所有设备都会去执行动作,告警执行时查询该场景匹配的告警配置,执行消息通知。
  4. 静默时间:指定的时间范围内只会执行一次动作,单位分钟。
  5. 执行方式:串行,并行。串行时动作按照顺序依次执行,并行时动作一起执行。
  6. 延时执行:延时执行动作,时间限制为90秒,指定时间范围内,如果服务端意外停止,重启后不会再去执行。

提示

  • 新建的场景中包含告警执行,告警配置中可以关联该场景,满足触发条件后会发送告警短信/语音/邮件,微信/钉钉通知等,具体根据告警的配置
  • 告警触发时会生成告警日志,只有当告警日志未处理条数小于等于一条时才会执行消息通知,请及时处理告警日志;或者可通过配置告警恢复处理

# 规则脚本

# 1、脚本语言

提示

规则脚本采用Groovy编写,是一种基于JVM(Java虚拟机)的敏捷开发语言,Groovy代码能够与Java代码很好的结合,也能用于扩展现有代码。 Groovy的语法与 Java 语言的语法很相似,完成同样的任务所需的代码比 Java 代码更少。可以将它想像成 Java 语言的一种更加简单、表达能力更强的变体,基本上可以直接使用Java代码编写脚本。

# 2、新建规则脚本

规则脚本列表

编辑规则脚本

配置说明:

  1. 脚本事件:设备上报(已支持)、服务下发(已支持)、设备上线、设备离线
  2. 脚本动作:消息重发(已支持)、消息通知、Http推送、mqtt桥接、数据库存储
  3. 所属产品:规则脚本跟产品绑定,只会影响产品下面的设备
  4. 脚本顺序:产品下面有多个脚本,按照顺序执行

# 3、规则脚本基础示例

重要

如果设备的Mqtt消息格式是固定的,可以通过规则引擎进行转发,适配到平台,系统目前版本只支持Mqtt传输协议的主题和内容转发

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.NumberUtil;

// 1. 获取主题/消息内容/设备编号/协议编码
String topic = msgContext.getTopic();
String payload = msgContext.getPayload();
String serialNumber = msgContext.getSerialNumber();
String protocolCode = msgContext.getProtocolCode();

// 2. 数据转换(自己处理)
msgContext.logger.info("数据转换处理")
String NewTopic = topic;
String NewPayload = payload;

// 3. 返回新的数据
msgContext.setTopic(NewTopic);
msgContext.setPayload(NewPayload);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

提示

  1. 默认仅使用hutool的Json处理和数字工具类库,hutool其他类库或者系统相关类库,需要后端开放一下;
  2. 默认禁止使用For/While循环和IO操作等,根据情况可以后端开放;
  3. 通过msgContext获取和设置主题和消息内容;
  4. 主题和消息内容如何转换需要自己编写。

规则脚本通过上下文 MsgContext 存取数据。脚本中可以通过 msgContext 获取值和重新设置新的值,系统定义的上下文如下:

public class MsgContext {

    /** 消息主题 */
    private String topic;

    /** 消息内容 */
    private String payload;

    /** 设备编号 */
    private String serialNumber;

    /** 产品ID */
    private Long productId;

    /** 协议编码 */
    private String protocolCode;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4. 设备上报示例

我们创建一个产品,产品选择JSON协议

按照平台处理上报数据的系统主题和系统数据格式分别是:

Topic: /96/D1ELV3A5TOJS/property/post

[
  {
    "id": "temperature",
    "value": "26.45"
  },
  {
    "id": "humidity",
    "value": "65.8"
  }
]
1
2
3
4
5
6
7
8
9
10
11
12

实际设备上报的数据格式和主题分别是:

Topic: D1ELV3A5TOJS/post
{
  "temperature": 26.5,
  "humidity": 65.8
}
1
2
3
4
5

此时,我们使用脚本转换主题和数据格式,我们新建一个脚本

脚本内容如下:

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.NumberUtil;

//系统主题
String sysTopic = '';
//系统数据格式
String sysPayload = '';

// 1. 获取主题和内容,topic  S&D1PGLPG58K66/post
String name = msgContext.getTopic();
Long productId = msgContext.getProductId();
String serialNumber = msgContext.getSerialNumber();
String protocolCode = msgContext.getProtocolCode();
String payload = msgContext.getPayload();
msgContext.logger.info("产品id/协议编号:" + productId + " / " + protocolCode);

// 2. 转换为系统主题 /96/D1ELV3A5TOJS/property/post
sysTopic = "/" + productId + "/" + serialNumber + "/property/post" 

if("JSON".equals(protocolCode)){   
    // 3. 内容格式转换
    JSONArray newArray = new JSONArray();
    JSONObject jsonObject = JSONUtil.parseObj(payload);
    jsonObject.keySet().forEach(key -> {
        JSONObject newObject =new JSONObject();
        newObject.put("id" , key);
        newObject.put("value" , jsonObject.getStr(key));
        newArray.add(newObject);
    });
    sysPayload = newArray.toString();
}else{
    //其他协议处理
}

// 4.打印
msgContext.logger.info("新主题:" + sysTopic);
msgContext.logger.info("新内容:" + sysPayload);

// 5. 返回新的数据(必要)
msgContext.setTopic(sysTopic)
msgContext.setPayload(sysPayload);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

脚本内容基本比较容易理解。我们编辑好脚本后,进行验证。运行一下看看效果。连接设备编号为:S&D1PGLPG58K66 的设备,按照如下格式发送:

我们看看脚本执行后的在控制台打印的结果:

16:08:55.066 [MQTT-BROKER-6-5] INFO  c.y.l.c.FlowExecutor - [info,186] - [68bc37d0dffa41a8a25b1d8c1a63a8a5]:requestId has generated
16:08:55.066 [MQTT-BROKER-6-5] INFO  c.y.l.c.FlowExecutor - [info,193] - [68bc37d0dffa41a8a25b1d8c1a63a8a5]:slot[10] offered
16:08:55.066 [MQTT-BROKER-6-5] INFO  c.y.l.f.element.Node - [info,193] - [68bc37d0dffa41a8a25b1d8c1a63a8a5]:[O]start component[D1751532166174609408(消息转发)] execution
----------------------------------------------------------------------------------------
产品id/协议编号:41 / JSON
新主题:/41/D1ELV3A5TOJS/property/post
新内容:[{"id":"temperature","value":"26.5"},{"id":"humidity","value":"65.8"}]
-----------------------------------------------------------------------------------------
16:08:55.067 [MQTT-BROKER-6-5] INFO  c.y.l.c.ScriptCommonComponent - [info,200] - [68bc37d0dffa41a8a25b1d8c1a63a8a5]:component[D1751532166174609408(消息转发)] finished in 0 milliseconds
16:08:55.067 [MQTT-BROKER-6-5] INFO  c.y.l.slot.Slot - [info,200] - [68bc37d0dffa41a8a25b1d8c1a63a8a5]:CHAIN_NAME[dataChain]
D1751532166174609408[消息转发]<0>
1
2
3
4
5
6
7
8
9
10
11

可以看到topic和数据格式已经转换为系统主题和格式

# 5. 服务下发转换示例

假设实际设备服务下发的主题和数据格式分别是:

Topic: D1PGLPG58KZ2/set
{
  "report_monitor": "4"
}
1
2
3
4

平台系统主题和数据格式:

Topic: /96/D1PGLPG58K66/property/post

[
  {
    "id": "temperature",
    "value": "26.45"
  },
  {
    "id": "humidity",
    "value": "65.8"
  }
]
1
2
3
4
5
6
7
8
9
10
11
12

新增脚本,定义如下:

我们看看脚本的定义内容:

1.将系统主题转为真实设备需要的主题

2.将系统数据格式转为真实设备需要的主题(注意:主题转换时 设备编号必须带上且长度大于9位,如果不带设备编号,需要修改后端代码)

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.NumberUtil;

//系统主题
String tranTopic = '';
//系统数据格式
String tranPayload = '';

// 1. 获取主题和内容
String topic = msgContext.getTopic();
String payload = msgContext.getPayload();
Long productId = msgContext.getProductId();
String serialNumber = msgContext.getSerialNumber();
String protocolCode = msgContext.getProtocolCode();

// 2. topic转换 将/60/DEVICE555/function/get 系统主题 转为 DEVICE555/set 
tranTopic = serialNumber+ "/set";

if("JSON".equals(protocolCode)){   
    // 3. 转发的数据  {"temperature":26.5,"humidity":65.8}
    JSONArray jsonArray = JSONUtil.parseArray(payload);
    JSONObject resultObj = new JSONObject();
    jsonArray.forEach(obj -> {
        JSONObject jsonObject = (JSONObject)obj;
        resultObj.put(jsonObject.getStr("id"),jsonObject.getStr("value"));
    });
    tranPayload = JSONUtil.toJsonStr(resultObj);  
    
}else{
    //其他协议处理
}

// 4.打印
msgContext.logger.info("转发主题:" + tranTopic);
msgContext.logger.info("转发内容:" + tranPayload);

// 5. 返回新的数据(必要)
msgContext.setTopic(tranTopic);
msgContext.setPayload(tranPayload);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

我们下发指令来测试一下转换情况,后端日志内容如下:

17:34:36.439 [functionInvokeTask2] INFO  c.y.l.c.FlowExecutor - [info,186] - [6481bf113e15499aabe550189d16f4a5]:requestId has generated
17:34:36.440 [functionInvokeTask2] INFO  c.y.l.c.FlowExecutor - [info,193] - [6481bf113e15499aabe550189d16f4a5]:slot[13] offered
17:34:36.440 [functionInvokeTask2] INFO  c.y.l.f.element.Node - [info,193] - [6481bf113e15499aabe550189d16f4a5]:[O]start component[D1753673875549458432(平台下发转发)] execution
-------------------------------------------------
转发主题:D1PGLPG58KZ2/set
转发内容:{"report_monitor":"6"}
-----------------------------------------------
17:34:36.440 [functionInvokeTask2] INFO  c.y.l.c.ScriptCommonComponent - [info,200] - [6481bf113e15499aabe550189d16f4a5]:component[D1753673875549458432(平台下发转发)] finished in 0 milliseconds
17:34:36.440 [functionInvokeTask2] INFO  c.y.l.slot.Slot - [info,200] - [6481bf113e15499aabe550189d16f4a5]:CHAIN_NAME[dataChain]
1
2
3
4
5
6
7
8
9

客户端订阅接收内容如下:

至此,将系统主题和数据格式转换为设备所需主题和格式验证成功。

# 消息通知

# 一、消息通知

# 1.概述

消息通知是单独的一个模块,包含通知渠道、通知模板、通知日志三个菜单,模板通过关联业务编码,可灵活的对接其他模块业务;

# 2.技术实现

短信、邮箱发送使用第三方开源技术首页 | SMS4J文档 (opens new window),其他渠道发送使用官方api文档。

# 3.各个平台申请流程:

# a. 阿里云短信、语音

# b. 腾讯云短信、语音

注意

腾讯云最新的通知、营销短信模版已不支持添加变量,如需自定义变量请申请阿里云短信

# c. 微信小程序订阅模板申请,参考三方登录先申请微信小程序,然后登录微信公众平台微信小程序申请订阅消息

注意

微信小程序通知必须要配置模版并启用,然后用户需要在小程序告警-待处理页面点击处理,然后订阅消息,可以自己调整订阅位置

# d. 企业微信应用信息、群机器人

注意

目前仅支持在企业内部创建使用,还未测试过第三方

注意

企业微信应用消息必须要验证URL通过后才可发送通知,在下面的代码改为自己的信息,然后部署项目验证,验证成功后再配置可信域名、可信IP就可以了

# e. 微信服务号通知

实现前提:系统已经有微信绑定功能,并且微信服务号需和微信网站应用、小程序、移动应用绑定在同一个微信开放平台账号下,不同应用端通过unionId交互;

注意

  • 请申请服务号,只有服务号支持模板消息功能
  • 在微信开放平台申请公众号,然后去微信公众平台绑定服务号;
  • 在系统三方登录配置微信公众号信息;
  • 验证url,验证通过后配置IP白名单;
  • 功能上线后已关注公众号的微信需重新关注;

# f. 钉钉消息通知、群机器人

注意

目前仅支持在企业内部创建使用,还未测试过第三方

注意

需要在机器人设置、安全设置里修改IP地址段,一般为后端服务器部署地址

# g. MQTT网页通知

注意

推送主题是/notify/alert/web/push/${用户id},此通知方式不会记录通知日志,在设备详情-告警用户配置需要通知的用户

# 二、通知渠道

# 1. 概述

通知渠道配置主要用于对接第三方渠道服务商的连接参数,一个渠道可配多个通知模版。

# 2. 定义

渠道、服务商来源于字典数据,服务商需严格按照已有字典类型格式配置:

# 3. 差异

不同渠道服务商配置参数有差异,可查看该枚举类NotifyChannelProviderEnum,可自行调整。配置参数来源方法com.fastbee.common.enums.NotifyChannelProviderEnum#getConfigContent

注意

务必保证属性(attribute)参数名和各渠道对应配置类里的属性名一致

# 三、通知模版

# 1. 概述

通知模版主要配置模版参数,模板归属于通知渠道(配置模板时需选择对应已配好的通知渠道账号),同时也要选择相应的业务编码,配好后在列表里启用;

# 2. 差异

不同渠道模版参数有差异,可查看该枚举类NotifyChannelProviderEnum,可自行调整。配置参数来源方法com.fastbee.common.enums.NotifyChannelProviderEnum#getMsgParams

注意

务必保证属性(attribute)参数名和各渠道对应配置类里的属性名一致

# 3. 发送账号

所有模版发送账号统一使用sendAccount字段保存,多个使用‘,’分隔

# 4. 内容变量

所有模版正文内容统一使用content字段保存,目前只支持content字段内容里存在变量。变量符号:微信小程序使用符号 ,腾讯云短信、语音使用符号 {},邮箱使用符号 #{},其余使用 ${} 表示

注意

需要把第三方申请的模版内容原样复制过来(方便记录完整的日志内容),例如:

  • 微信小程序订阅模板内容复制

  • 短信语音模板内容复制

# 四、通知日志

概述:记录所有通知模版发送的日志,包括发送内容、账号、返回内容;

# 五、业务对接

# 1. 概述

唯一启用模版原则:短信、语音、邮箱以业务编码+渠道保证唯一启用,微信、钉钉以业务编码+渠道+服务商保证唯一启用。

# 2. 对接

已对接设备告警,短信登录验证码业务。如需添加业务,可同时在字典数据通知业务编码和通知业务枚举类NotifyServiceCodeEnum里自行添加。

# 3. 测试

在配置好模版后,可点击测试按钮,检测是否能发送成功。

# 4. 发送服务类

主要对接不同渠道服务商的发送

# 5. 业务通知

主要对接业务发送,有新业务可写在这。

提示

  • 已统一发送方法,com.fastbee.notify.core.service.NotifySendService#notifySend,可直接调用
  • 已统一查询启用模版方法,com.fastbee.notify.core.service.NotifySendService#selectOnlyEnable,可直接调用
  • 如需加业务通知,只需自己组装一下内容变量和发送账号即可,参考统一发送方法入参类com.fastbee.notify.vo.NotifyVO

注意

  • 在对接其他业务时,务必保证模版是启用的状态,否则会发送失败。

  • 设备告警业务的通知模板,短信、语音、微信小程序会获取当前设备配置的告警用户+模板配置的发送账号通知,其余需要在模板里面配置发送账号。

  • 支持多个账号发送,微信小程序使用系统用户id(用户需要订阅模版,目前只需要配置了设备告警-微信小程序通知模板,并启用,然后在微信小程序告警页面订阅就行),企业微信应用消息使用企业通讯录成员账号名称,钉钉工作通知使用企业内部通讯录成员员工UserID,均用英文逗号‘,’分隔

  • 模版内容存在变量的,需要把变量替换为真实的参数。目前已对接的业务,模版变量是按顺序替换的,因此在申请模版内容时,变量的顺序务必和我们演示站点模版变量顺序一致。如果需要修改发送变量,可自行参考以下代码调整:

# 多租户操作

# 一、机构管理

# 1、概述

以机构维度实现多租户,分为上下级,上级机构可管理下级机构的数据,每一个机构就是一个租户、租户即是机构;

# 2、技术实现

通过在表结构添加tenant_id或user_id字段,实现租户隔离;

# 3、流程

整个系统最上层机构绑定系统管理员,可往下添加机构,其中设置的系统账号为该机构管理员:

提示

第一个机构(蜂信物联)绑定超级管理员admin,其机构dept_id必须为100,需配置系统层面的部分业务,服务于终端用户,例如:三方登录、短信登录; ​web端注册用户归属机构:其机构dept_id必须为101,机构下必须包含一个普通用户(general)角色,在web端注册的新用户绑定到该机构,后续可调整该用户所属机构。注意:如果不使用web端账号注册功能,该机构可忽略使用,正常情况下使用新版多租户web端是没有账号注册功能的,这里只是为了展示注册功能,所以把web端注册的新用户绑定到该机构。 在小程序、APP端注册的用户属于终端用户,终端用户绑定的角色是超级管理员所属机构下的普通用户(general)角色,其主键id标识必须为3,请勿删该角色,可对该角色分配相应的权限;

# 二、角色管理

# 1、概述

机构内可单独设置多个角色,也可管理下级机构的角色;

# 2、实现

创建机构时会默认创建一个管理员角色,该角色权限范围跟随当前操作者所属机构管理员的角色权限,该管理员角色绑定到机构设置的系统账号上;

# 3、流程

同一机构内管理员不可以更改自己管理员角色的权限,可更改机构内其他角色的权限;上级机构可更改下级机构的角色权限,其中下级机构管理员角色可更改范围跟随操作者所属机构管理员角色的权限范围,下级非管理员角色可更改范围为同机构内的管理员角色权限范围;

提示

每个机构只能有一个管理员角色,其权限字符为manager,不可删,请合理配置每个角色的权限范围;

# 三、用户管理

# 1、概述

机构可单独管理机构内用户,也可管理下级机构的用户;

# 2、流程

创建用户时需选择机构,其中角色为该机构下的角色;

提示

  • web端注册的新用户绑定到 (web端注册用户归属机构) 机构,其角色绑定的是该机构下的普通用户(general)角色;
  • 小程序、移动端注册的新用户不绑定任何机构,属于终端用户,其角色绑定的是admin超级管理员机构下的普通用户(general)角色;
  • 终端用户只可以登录小程序、移动端,租户用户可以登录所有平台;

# 四、设备管理

# 1、概述

机构可单独管理机构内设备,也可管理下级机构的设备;

# 2、流程

新增设备时,产品来源为该机构和上级机构的产品,该设备绑定在机构管理员账号下;

# 3、新增功能

  • 新增设备:可以批量导入,也可手动添加

  • 分配设备:可以选择机构内设备分配给其他机构,也可以批量导入设备分配给机构

  • 回收设备:可以把分配给其他机构的设备回收到自己机构下

# 四、指令权限

设备下发指令权限:租户管理员、终端用户有权限下发,租户内其他用户需分配权限才能下发,可在运维管理-指令权限下配置;

# 五、其他模块

1、通用物模型、协议管理、设备模拟、系统管理、系统监控、系统工具、Netty管理、EMQ管理、组态图库管理:整个系统通用,不做租户隔离,可在配置角色时分配权限,谨慎分配;

2、产品分类:租户隔离,可以查看上级机构的数据,但是不可以修改;

3、产品管理:租户隔离,可以查看、使用上级机构的产品,但是不可以修改;

4、设备分组:租户隔离,终端用户隔离;

5、产品固件:租户隔离,可以查看上级机构的数据;

6、通知渠道、通知模版、通知日志:租户隔离,各机构单独配置,租户用户在小程序订阅设备告警模版使用归属机构配置的模版;终端用户短信登录、三方登录、小程序内订阅告警模版使用顶级机构配置内容;

7、规则引擎:租户隔离;终端用户创建的场景、告警记录归属自己;

# 组态管理

提示

组态是指用户通过类似搭积木的方式,使用编辑器提供的工具和方法,就能通过简单直观的界面来配置和控制自动化过程和装备,而不需要编写计算机程序。在组态管理中,提供了丰富的场景素材控件,能够自由拖拽搭建监控场景,实时显示设备运行状态等信息。

# 一、组态组成

FastBee 组态可分为模版(产品)组态、场景组态和独立组态,组态的组件元素又分为图库管理、图表管理、组件管理和模型管理用于自定义组件元素。

# 二、组态中心

组态中心可对组态进行创建、编辑、设计、运行、分享和删除,组态可以是动态的平面工业图也可以制作大屏展示,用途广,直接绑定平台参数方便快捷。

# 组态列表

组态列表 是针对产品绘制的组态画面,在该产品下的所有设备都会展示该组态画面,组态画面中绑定变量来源于产品物模型,取值来源于当前设备上报的实时值。通过绘制一个模板组态画面就可以实现同产品但不同设备的可视化数据监控。避免重复编辑应用画面的麻烦。

  • 添加组态,

    点击“新增”按钮,需维护组件名称、关联产品必填信息

  • 组态运行

    直接在组态列表中点击“运行”

  • 组态设计

    直接在组态列表中点击“设计”

  • 删除组态

    选择要删除的组态,点击“删除”

# 三、图库管理

图库管理可用于上传和管理各种图片,便于在组态编辑器中使用,系统已经内置了按钮、指示灯、工业泵、储蓄罐、电机、电力符号、阀门、反应器、风机、管道、建筑物、锅炉、换热站、机械设备、交通、警示标志、人物、天气、自然、全景、3D等图。

# 组态编辑器

# 一、概述

提示

中科智电物联网平台组态编辑器主要由顶部工具栏、左侧导航栏、画布、右侧配置栏组成。

  • 工具栏:常见的执行操作,例如复制、删除、置顶、置底、旋转、组合、锁定、图库、导入、导出、撤销、恢复、缩放、保存、预览。
  • PC端:支web端网页设计,页面可设置多种分辨率。
  • 移动端:暂不支持,后期可以通过分享在移动端查看。
  • 基本组件:具备丰富的基础组件,包括基本组件、基本形态、统计图,可以更好的模拟工业场景。
  • 图库:可以通过“图库管理”上传素材,图库也提供了大量高级控件,可用于生动展现各种场景。
  • 画布:通过把组件拖拽放置于此,多个组件组合,共同完成生动的工业生产流程场景。
  • 数据:可以通过mqtt或者http的形式为组件绑定数据来源实现交互功能。
  • 样式:编辑组件位置、大小、颜色等。

# 二、组件配置

# 1. 页面配置

在画布区域中点击空白处,右侧便会出现”页面”配置栏设置。

  • 颜色:设置画布中字体颜色
  • 不透明度:设置画布的透明度
  • 背景颜色:给背景设置颜色,支持设置任何颜色。
  • 字体大小:设置画布中字体的大小

# 2. 样式设置

设置组件在页面中的样式展示,包括位置尺寸、名称、文本、外观等,不同组件配置的内容可能不同,选中组件,右侧便会出现”组件”配置栏设置。

  • 位置和尺寸:设置组件在页面画布的显示位置与尺寸,X坐标和Y坐标,分别以页面左上角为起点坐标[0,0],设置X轴和Y轴的值,调整组件在页面中的位置;宽度和宽度,就是组件的宽度和高度,用于调整组件尺寸。

  • 组件名称:支持给画布上的组件自定义设置名称,用于标记组件的作用等,同时在组态预览时不会显示设置的标题名称;

  • 旋转角度:以组件为中心,组件可以按顺时针或者逆时针旋转任意角度,在组件上方“旋转”,设置想要旋转的角度即可。

  • 基本样式:可设置组件的外观,包括不限于图层高度、背景颜色、透明度、边框圆角、阴影颜色、组件显隐等

  • 特定属性:根据组件的不同,拥有不同的特有属性,以“文本”为例,支持设置文本的文字、对齐方式、字体、大小、颜色、边框、边框颜色等

  • 组件联动:当组件发生变化时候,另一个组件样式需要执行指定动作

# 3. 动画配置

支持对组件设置出场、强调、退出动画

# 4. 事件配置

支持对组件添加变量状态、事件、交互进行配置,不同组件配置的内容不同,不同组件的配置将在下面介绍,选中组件,右侧会出现事件

  • 绑定设备:组件展示数据的来源。选择设备、选择变量,所关联的变量就是产生数据的来源。

    a.先从顶部工具栏中绑定设备

    b.绑定设备并选择需要添加的变量

  • 事件:绑定组件的单击事件,包含弹窗、跳转外部链接、和后台交互的按钮。

    a.选择指定事件

    b.根据需求自行配置动作类型(后期可扩展)

# 三、工具栏

工具栏为组件在画布中提供了一些常用操作功能,从左到右功能依次如下

  • JSON:组件的属性代码,选中组件则显示组件代码,未选中则显示画布
  • 导入:支持把导出的组态文件导入进来,导入进来组态文件的数据源与当前组态不一致时只兼容界面设计。
  • 导出:支持把组态工程导出,可用于存档或者在新组态中应用。
  • 撤销:撤销上一步操作。
  • 重做:恢复已被撤销的操作。
  • 图库:用于给画布中添加图片,图库中可以收藏一些常用的图片,若无法满足需求还可以从本地上传一些常用图片到收藏夹中。
  • 预览:对当前组态设计的效果预览查看,点击“预览”,按钮即可打开当前组态设画面;
  • 保存:对当前的组态设计进行保存,支持点击“保存”按钮手动保存。
  • 清空画布:清空画布,删除所有组件。
  • 绑定设备:选择指定设备和变量进行交互
  • 组合:将多个组件编为一个组,便于同时对多个组件进行操作,如复制、改变组件的位置等。
  • 取消组合:取消多个组件组合,恢复组件独立性。
  • 锁定:用于锁定组件。组件锁定后,该组件将不能被选中,不可改变组件显示位置等。若要对组件进行操作,需解锁。
  • 解锁:用于解锁被锁定的组件,解锁后的组件可进行操作。
  • 截图:将当前画布中的组件截图,并保存到本地。
  • 画布大小:设置画布的尺寸,支持设置画布的宽高,单位为像素。
  • 画布比例:支持页面的画布按照比例进行缩放显示。
  • 画布样式:明亮、暗黑两种模式,默认明亮模式。
  • 对齐方式:将所选中的组件(包括图片)按特定的方向对齐,包含左对齐、右对齐、上对齐、下对齐、水平等间隔和垂直等间隔等

# 四、组件库

组件作为组态的重要组成部分,是组态的核心。通过拖拽所需的组件到画布中,在配置组件的样式和数据,实现组件直接的数据交换,共同构建出各种工业场景。组件包括:基本组件、基本形状、统计图形、图库组件、图表组件和更多组件等

# 1. 基本组件

基本组件包括:文字、按钮、图片、矩形、直线、水流、圆形、星形、三角形、表格、图标、时间组件

# 1.1 文字

用来表达和展示所指定的内容,双击直接输入文本,也可以在属性->内容中输入。
组件样式中支持位置、尺寸、颜色、旋转角度、透明度、文字、对齐方式、字体粗细、字体大小、行高、字间距、组件显隐

# 1.2 按钮

通过按钮可通过对设备一些变量进行指令下发控制。
组件样式中支持位置、尺寸、颜色、旋转角度、背景颜色、边框宽度、边框颜色、边框半径、透明度、文字、对齐方式、字体粗细、字体大小、行高、字间距、组件显隐

# 1.3 图片

用来显示已设置好的图片 在组件样式中支持位置、尺寸、旋转角度、边框半径、不透明度、组件显隐

# 1.4 矩形

一个形状,在矩形内部可以输入文本,矩形、圆形、星形、三角形功能一直只是形状不同 在组件样式中支持位置、尺寸、颜色、旋转角度、背景颜色、边框宽度、边框风格、边框颜色、边框半径、透明度、文字、对齐方式、字体粗细、字体大小、行高、字间距、组件显隐

# 1.5 直线

用于连接组件的一条线
组件样式中支持位置、尺寸、背景颜色、透明度、旋转角度、组件显隐

# 1.6 水流

水流相当于直线的升级版,可以动态的显示线条是流动的效果 在组件样式中支持位置、尺寸、背景颜色、透明度、旋转角度、组件显隐、主颜色、辅颜色、分段数量、速度、流向

# 1.7 数据表格

数据表格展示实时数据或历史数据的报表,支持数据来源和表格列配置。 在组件样式中支持位置、尺寸、旋转角度、颜色、背景颜色、透明度、字体粗细、字体大小、对齐、组件显隐、添加新行新列、删除行列、斑马纹、表头加粗 表格可以配置数据源,支持配置请求参数,定时触发

# 1.8 图表

以echarts图表的方式展示数据,支持柱状、散点、折线 在组件样式中支持位置、尺寸、旋转角度、透明度、边框半径、组件显隐、显示标题、工具提示、显示图例、显示横坐标、更换图标类型、更改静态数据源

# 1.9 时间

时间组件显示当前系统时间 在组件样式中支持位置、尺寸、颜色、旋转角度、背景颜色、透明度、对齐方式、字体粗细、字体大小、行高、字间距、组件显隐

# 2. 基本形状

# 3. 统计图形

# 4. 图库组件

图库组件包括“图库管理”中所有图片
可以向画布中添加任何“图库管理”中的图片,支持组件样式和设备绑定以及使用事件