# 8. IoT数据通讯
# 8.1 MQTT
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
# 8.1.1 配置说明
在寂山IDE工程中使用mqtt协议步骤如下:
- 在通讯协议栈上面右击,点击添加MQTT Server选项,即可添加MQTT配置界面
- 点击刚才添加的MQTTServer,打开当前的mqtt通讯协议配置
- 常规配置,设置客户端名称,ID,broker地址和端口号,变量采样间隔,以及mqtt broker的登录用户名和密码
- 发布消息配置,设置需要发布的变量的topic,以及对应的Qos级别
- 高级配置, 设置mqtt连接超时时间,keep alive时间以及是否重连和重连间隔时间
- 连接时发送消息,配置mqtt连接上后向broker是否发布消息(即程序开始后连接上mqtt发布的消息),以及发布的主题等信息
- 断开连接时发送的消息,程序停止或者意外断开(遗愿消息)等信息
- 在应用上右击,选择MQTT变量,添加需要发布的MQTT变量
- 打开3中添加的MQTTVariables, 勾选需要发布的变量,即可通过mqtt协议发布对应的变量
# 8.1.2 变量发布消息格式
mqtt通讯协议栈,以MQTT Server中配置的主题向mqtt broker中发布变量内容, 变量内容以json字符串的形式,其json字符串的形式如下:
{
"header": {
"token": "",
"projectId": "",
"applicationId": ""
},
"body": {
"errorCode": 0, // 错误码
"message": "Get online variables successfully!", // 结果的简单描述
"data": {
"vars": [LogicVar]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
上述消息json报文中,主要关注body中的字段值,其中各字段说明如下
字段 | 数据类型 | 说明 | 是否可选 |
---|---|---|---|
header | 工程的相关描述,暂时可以为空 | ||
body | |||
errorCode | 整型 | 0为执行成功,非0为失败 | 必选 |
message | 字符串 | 结果简单描述 | 必选 |
相应数据(data) | |||
locationX | Object | 代表具体实例名所在位置(实际值为config.resource.instanceName...) | 必选 |
varX | 字符串 | 变量名,实例对应的POU下的变量名 | 必选 |
valueX | 字符串 | 变量值,以字符串的形式处理,具体参见下面描述 | 必选 |
子类型 LogicVar
{
"location": "string", // 变量的位置,格式"config.resource.instance", 例如:"CONFIG.RES2.R2_INST_1"
"pou": "string", // 变量所处的POU名称
"varName": "string", // 变量名
"type": int, // 变量类型
"value": "string" // 变量值(字符串化)
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 8.1.3 变量值说明
变量值的字符串化按照下表的方式处理
类型分类 | IEC类型 | 说明示例 |
---|---|---|
布尔型 | BOOL | "TRUE"或"FALSE" |
整形 | BYTE WORD DWORD LWORD SINT USINT INT UINT DINT UDINT LINT ULINT | 转为对应字符串,例如 "123" |
浮点型 | REAL LREAL | 转为对应字符串,例如 "3.14" |
字串 | STRING | 直接字,例如"ABCD" |
时间和日期 | TIME DATE TOD DT | 转化为对应字符串,格式分别为:TIME : "T#2d0h8m6s"DATE : "D#2023-08-23"TOD : "TOD#12:34:56"DT : "DT#2023-08-23-12:34:56" |
枚举 | DUT 枚举类型 | 使用LINT强转为字符串 |
数组 | DUT 数组类型 | json字符串,格式参考下例 |
结构体 | DUT 结构体类型 | json字符串,格式为参考下例 |
# 8.1.4 变量值类型说明
变量的类型为整型变量,其值代表的含义如下
IEC数据类型 | 对应字段中type的值 | IEC数据类型 | 对应字段中type的值 | IEC数据类型 | 对应字段中type的值 |
---|---|---|---|---|---|
无效数据类型 | 0 | DINT | 10 | DT | 20 |
BOOL | 1 | UDINT | 11 | ENUM | 21 |
BYTE | 2 | LINT | 12 | ARRAY | 22 |
WORD | 3 | ULINT | 13 | STRUCT | 23 |
DWORD | 4 | REAL | 14 | FB | 24 |
LWORD | 5 | LREAL | 15 | 预留 | 25 |
SINT | 6 | STRING | 16 | 预留 | 26 |
USINT | 7 | TIME | 17 | 预留 | 27 |
INT | 8 | DATE | 18 | 预留 | 28 |
UINT | 9 | TOD | 19 | 预留 | 29 |
# 8.1.5 报文格式样例
下面是mqtt报文格式具体的json报文,供参考:
{
"header": {},
"body": {
"errorCode": 0,
"message": "Get online variables successfully!",
"progress": 100,
"data": {
"vars": [{
"type": 1,
"location": "CONFIG.RESOURCE1.MAINTASK_3230_PRG2_1",
"pou": "PRG2",
"varName": "LOCALVAR0",
"value": "FALSE"
}, {
"type": 8,
"location": "CONFIG.RESOURCE1.MAINTASK_3230_PRG2_1",
"pou": "PRG2",
"varName": "VAR1",
"value": "4"
}, {
"type": 9,
"location": "CONFIG.RESOURCE1.MAINTASK_3230_PRG1_1",
"pou": "PRG1",
"varName": "LOCALVAR0",
"value": "4"
}, {
"type": 22,
"location": "CONFIG.RESOURCE1.MAINTASK_3230_PRG1_1",
"pou": "PRG1",
"varName": "ARRVAR",
"value": "{\"dimension\":[{\"lower\":\"1\",\"upper\":\"3\"},{\"lower\":\"2\",\"upper\":\"5\"}],\"values\":[\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"4\",\"0\",\"0\",\"0\",\"0\",\"0\"]}"
}, {
"type": 23,
"location": "CONFIG.RESOURCE1.MAINTASK_3230_PRG2_1",
"pou": "PRG2",
"varName": "STRVAR1",
"value": "{\"NAME\":\"wisdon\",\"AGE\":\"12\"}"
}, {
"type": 1,
"location": "CONFIG.GVL1",
"pou": "config",
"varName": "GLOBALVAR0",
"value": "FALSE"
}]
}
}
}
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
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
# 8.1.6 在IoT工程中使用mqtt发布的变量
在设置完MQTT通信协议之后,可以通过Python程序,获取mqtt通信协议栈发布的变量,具体使用方式如下:
from iec_mqtt import * # 导入iec mqtt协议栈库
jsmq = IecMqtt(broker='192.168.10.238', port=1883, topic="variables") # 连接mqtt broker
gVar = jsmq.GetIECVars("gvl1.GLOBALVAR0") # 获取全局变量gvl1.GLOBALVAR0
print("GetIECVars: gVar=", gVar, "type(gVar)=", type(gVar), flush=True)
# 获取POU实例变量 MAINTASK_3230_PRG1_1.ARRVAR 和 MAINTASK_3230_PRG2_1.strVar1
(arrVar, strVar) = jsmq.GetIECVars(["MAINTASK_3230_PRG1_1.ARRVAR", "MAINTASK_3230_PRG2_1.strVar1"])
print("GetIECVars: arrVar=", arrVar, "type(arrVar)=", type(arrVar), ",strVar=", strVar, "type(bVar)=", type(strVar), flush=True)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
关于iec_mqtt
库有以下几点说明:
iec_mqtt
中有一个名为IecMqtt
的类,其包含三个参数,broker为对应的mqtt broker地址,port为对应端口号,默认为1883,topic对应IEC程序通过MQTT发布变量的topic。IecMqtt
类提供一个方法:获取MQTT发布变量的值GetIECVars()
,GetIECVars()
只有一个参数,只能是字符串、字符串列表、或字符串元组。字符串不区分大小写。
- 当参数为字符串时,代表只获取一个变量的值,返回当前获取的变量值。例如
gVar = jsmq.GetIECVars("gvl1.GLOBALVAR0")
- 当参数为字符串列表或者字符串元组时,代表只获取一组变量的值,返回当前获取的变量值列表。例如
(arrVar, strVar) = jsmq.GetIECVars(["MAINTASK_3230_PRG1_1.ARRVAR", "MAINTASK_3230_PRG2_1.strVar1"])
可以同时获取"MAINTASK_3230_PRG1_1.ARRVAR"和"MAINTASK_3230_PRG2_1.strVar1"两个全局变量的值,分别赋值给 arrVar 和 strVar 变量。- 获取全局变量必须以全局变量以"[GVLName].[globalVarName]"方式访问,获取POU变量以"[instanceName].[VarName]"方式访问。
- MQTT发布的IEC变量与Python数据类型的对应关系,如下
IEC数据类型 | Python数据类型 | 说明 |
---|---|---|
BOOL | bool | True或者False |
SINT, INT, INT, LINT, USINT, UINT, UDINT, ULINT, REAL, LREAL | Number | 数值类型 |
STRING | String | 字符串类型 |
自定义数组 | 列表 | 所有自定义数组都被存放在Python一维列表中,Python列表下表从0开始,元素个数与IEC数组总元素个数相同, 注意:数组元素的值都是字符串表示形式,使用时需要根据实际数据类型做转换,因为Python拿不到数组实际数据类型 |
自定义结构体 | 字典 | 所有自定义结构体存放在Python字典中,字典中的key为IEC结构体元素名,且必须全部大写,字典中value对应IEC结构体元素的值。 注意:结构体元素的值都是字符串表示形式,使用时需要根据实际数据类型做转换,因为Python拿不到结构体元素的实际数据类型 |
TIME | String | "T#%dd%dh%dm%ds%gms"格式 |
DATE | String | "D#%d-%2.2d-%2.2d" |
TOD | String | "TOD#%2.2d:%2.2d:%2.2d" 或者 "TOD#%2.2d:%2.2d:%09.6f" 格式 |
DT | String | "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d" 或者 "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%09.6f"格式 |
iec_mqtt
库中使用了库paho.mqtt
,用户必须以root权限手动安装。参考安装命令:sudo pip3 install paho-mqtt -i https://pypi.tuna.tsinghua.edu.cn/simple
- 其他Python使用相关手册,请参考《IoT数据通讯》对应章节。