# 8. IoT数据通讯

# 8.1 MQTT

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

mqtt

# 8.1.1 配置说明

在寂山IDE工程中使用mqtt协议步骤如下:

  1. 在通讯协议栈上面右击,点击添加MQTT Server选项,即可添加MQTT配置界面

mqtt_server

  1. 点击刚才添加的MQTTServer,打开当前的mqtt通讯协议配置
  • 常规配置,设置客户端名称,ID,broker地址和端口号,变量采样间隔,以及mqtt broker的登录用户名和密码

mqtt_server_common_ide

  • 发布消息配置,设置需要发布的变量的topic,以及对应的Qos级别

mqtt_server_variable_ide

  • 高级配置, 设置mqtt连接超时时间,keep alive时间以及是否重连和重连间隔时间

mqtt_server_advance_ide

  • 连接时发送消息,配置mqtt连接上后向broker是否发布消息(即程序开始后连接上mqtt发布的消息),以及发布的主题等信息

mqtt_server_onconnect_ide

  • 断开连接时发送的消息,程序停止或者意外断开(遗愿消息)等信息

mqtt_server_will_ide

  1. 在应用上右击,选择MQTT变量,添加需要发布的MQTT变量

mqtt_variable

  1. 打开3中添加的MQTTVariables, 勾选需要发布的变量,即可通过mqtt协议发布对应的变量

mqtt_variable_publish

# 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

上述消息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

# 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

# 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

关于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数据通讯》对应章节。