【边缘计算网关教程】7.Modbus协议转MQTT协议
a.从节点库拖出一个MQTT发布节点,函数节点,调试节点,状态监测节点和条件判断节点,MQTT发布用于消息发布,函数节点用于注册信息封装,状态检测节点用于检测MQTT的连接状态,调试节点用于打印发布的报文。a.从节点库拿出一个MQTT订阅节点,MQTT发布节点,函数节点和DO节点,MQTT订阅节点和MQTT发布节点用于接收云端发来的数据和控制响应,函数节点用于解析下发的报文和控制的响应报文封装。注
前景回顾:【边缘计算网关教程】6.松下 Mewtocol TCP 协议-CSDN博客--成都纵横智控
需求概述
本章节主要实现一个流程:
1.采集Modbus电表数据上传到MQTT指定topic
2.如果传感器未响应需要发送报警信息到指定topic
3.MQTT连接成功时发送注册信息
4.周期推送心跳到指定topic
5.云端下发控制EG8200继电器并回复
对接资料
1.南向接口 RS485对接协议(标准modbus)
点位 |
字段 |
寄存器地址 |
解析方式 |
A相电压 |
voltageA |
40001~40002 |
float32 ABCD |
B相电压 |
voltageB |
40003~40004 |
float32 ABCD |
C相电压 |
voltageC |
40005~40006 |
float32 ABCD |
A相电压 |
currentA |
40007~40008 |
float32 ABCD |
B相电压 |
currentB |
40009~40010 |
float32 ABCD |
C相电压 |
currentC |
40011~40012 |
float32 ABCD |
2.北向接口协议说明:
MQTT连接信息 |
|||
Broker |
139.129.229.113 |
||
Clientid |
TestClient |
||
Username |
82000000305E144F |
||
Password |
EG12345678 |
||
Topic报文格式 |
|||
功能 |
Topic |
数据流向 |
报文示例 |
信息注册 |
data/sg/${sn}/info |
网关->平台 |
{ "sn":"82000000305E144F", "time":"2023-01-01 12:00:00" } |
数据上报 |
data/sg/${sn}/report |
网关->平台 |
{ "sn":"82000000305E144F", "data":{ "voltageA":0, "voltageB":0, "voltageC":0, "currentA":0, "currentB":0, "currentC":0 }, time:"2023-01-01 12:00:00" } |
心跳 |
data/sg/${sn}/heart |
网关->平台 |
{ "sn":"82000000305E144F", "data":{}, "message":"heart", "time":"2023-01-01 12:00:00" } |
报警 |
data/sg/${sn}/warn |
网关->平台 |
{ "sn":"82000000305E144F", "data":{}, "message":"offline", "time":"2023-01-01 12:00:00" } |
平台控制 |
/data/sg/${sn}/request |
平台->网关 |
{ "event_id":"HsUCigC4Jk", "data": { "parameter": "DO1", "value": 0 } } |
控制回复 |
data/sg/${sn}/response |
网关->平台 |
{ "event_id":"HsUCigC4Jk", "message":"OK", "data":{}, "time":"2023-01-01 12:00:00" } |
需求分析
注册与连接工作
a.建立MQTT连接,发布到注册主题(MQTT发布节点)注:MQTT订阅发布节点连接信息共享,其他MQTT无需在配置连接参数,选择第一次配置的连接参数即可
b.监听MQTT连接状态(状态变化节点)
c.封装注册信息(函数节点)
数据上报
a.modbus读取电表数据(modbus读节点)
b.判断传感器是否有回复并封装上报报文(函数节点)
c.配置对应的发布主题(MQTT发布节点)
心跳推送
a.注入节点周期触发(注入节点)
b.封装心跳报文(函数节点)
c.MQTT发布数据(MQTT发布节点)
下发控制
a.MQTT订阅云端下发主题(MQTT订阅节点)
b.解析云端数据,并控制对应DO(函数节点)
c.响应MQTT控制情况(函数节点)
d.上报响应报文(MQTT发布)
实现流程框架
需求实现
1. 监听MQTT状态并发布注册信息
a.从节点库拖出一个MQTT发布节点,函数节点,调试节点,状态监测节点和条件判断节点,MQTT发布用于消息发布,函数节点用于注册信息封装,状态检测节点用于检测MQTT的连接状态,调试节点用于打印发布的报文
b.从上可以看见日志打印了注册报文,以及MQTTx端以及接收到了注册信息
c.注册流程使用的代码块:
const fmt = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
let obj = {
"sn": "82000000305E144F",
"time": fmt
}
function dateFormat(fmt, timestamp) {
let ret;
const opt = {
"Y+": timestamp.getFullYear().toString(), // 年
"m+": (timestamp.getMonth() + 1).toString(), // 月
"d+": timestamp.getDate().toString(), // 日
"H+": timestamp.getHours().toString(), // 时
"M+": timestamp.getMinutes().toString(), // 分
"S+": timestamp.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
msg.payload = JSON.stringify(obj)
return msg
2. 数据上报
a.从节点库拖出一个注入节点,函数节点和一个MQTT发布节点,注入节点用于周期触发,函数节点用于封装心跳报文,MQTT发布节点用于心跳发布
b.从上面可以看到日志窗口打印了数据报文,MQTTx也接收到了上报数据
c.数据上报流程使用的代码块:
function dateFormat(fmt, timestamp) {
let ret;
const opt = {
"Y+": timestamp.getFullYear().toString(), // 年
"m+": (timestamp.getMonth() + 1).toString(), // 月
"d+": timestamp.getDate().toString(), // 日
"H+": timestamp.getHours().toString(), // 时
"M+": timestamp.getMinutes().toString(), // 分
"S+": timestamp.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
var flag = msg.status
var data = msg.payload
var payload
const fmt = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
if (flag == "TIMEOUT") {
payload = {
"sn": "82000000305E144F",
"data": {},
"message": "offline",
"time": fmt
}
msg.payload = JSON.stringify(payload)
return [msg, null]
}
else if (flag == "OK") {
payload = {
sn: "02C00081275A574E",
data,
time: fmt
}
msg.payload = JSON.stringify(payload)
return [null, msg]
}
3. 心跳推送
a.从节点库拿出一个注入节点,函数节点,MQTT发布节点。注入节点用于周期发发送心跳,函数节点用于封装心跳报文,MQTT发布节点用于发布到MQTT
b.从上面可以看到日志窗口打印了心跳报文,MQTTx也接收到了心跳报
心跳上报流程使用的代码块:
const fmt = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
function dateFormat(fmt, timestamp) {
let ret;
const opt = {
"Y+": timestamp.getFullYear().toString(), // 年
"m+": (timestamp.getMonth() + 1).toString(), // 月
"d+": timestamp.getDate().toString(), // 日
"H+": timestamp.getHours().toString(), // 时
"M+": timestamp.getMinutes().toString(), // 分
"S+": timestamp.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
let obj = {
"sn": "82000000305E144F",
"data": {},
"message": "heart",
"time": fmt
}
msg.payload = JSON.stringify(obj)
return msg;
4. 下发控制及响应
a.从节点库拿出一个MQTT订阅节点,MQTT发布节点,函数节点和DO节点,MQTT订阅节点和MQTT发布节点用于接收云端发来的数据和控制响应,函数节点用于解析下发的报文和控制的响应报文封装
b.从上面可以看到日志窗口打印了报文,MQTTx也接收到了控制响应
c.控制流程使用的代码块//云端下发解析
//############################
if (msg.payload.length < 10) { return }
if (typeof (msg.payload) == "object") {
var obj = msg.payload
//信息获取
let event_id = obj.event_id;
global.set("event_id", event_id)
let parameter = obj.data.parameter
let value = obj.data.value
let arr = []
switch (parameter) {
case "DO1":
arr = value
break
case "DO2":
arr = value
break
}
msg.payload = arr
return msg;
}
//############################
//反馈响应封装
//############################
let event_id = global.get("event_id")
const fmt = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
function dateFormat(fmt, timestamp) {
let ret;
const opt = {
"Y+": timestamp.getFullYear().toString(), // 年
"m+": (timestamp.getMonth() + 1).toString(), // 月
"d+": timestamp.getDate().toString(), // 日
"H+": timestamp.getHours().toString(), // 时
"M+": timestamp.getMinutes().toString(), // 分
"S+": timestamp.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
let obj = {
"event_id": event_id,
"message": "OK",
"data": {},
"time": fmt
}
msg.payload = JSON.stringify(obj);
return msg;
//############################
以上来源于官方授权公众号-mp.weixin.qq.com/s/qeZwrOFaIzn2QqoboHicRg

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)