找回密码
 立即注册

微信扫码登录

搜索
查看: 139|回复: 2

[流程系列] 【教程】Node-Red-创建第二个流程(S7-200PLC数据采集、JSON格式转换、MQTT协议上云)

[复制链接]

2

主题

1

回帖

29

积分

新手上路

积分
29
金钱
26
HASS币
0
QQ
发表于 前天 17:23 | 显示全部楼层 |阅读模式
本帖最后由 iotrouter 于 2025-8-18 17:27 编辑

需求概述
本章节主要实现一个流程:EG8200采集西门子S7-200 Smart的数据,并组装成JSON格式,通过MQTT上报应用平台;同时能够接收应用平台下发的控制命令,实现远程开关。要实现此流程,需要提前准备好以下材料:
1. PLC的IP/端口/点位表
PLC
S7-200 Smart
IP
192.168.0.24/102
点表(DB1)
地址
数据类型
属性
名称
V0.0
Boolean
只读
1号电机启停状态
V0.1
Boolean
只读
2号电机启停状态
V0.2
Boolean
只读
3号电机启停状态
V0.3
Boolean
只读
4号电机启停状态
V0.4
Boolean
读写
1号电机启停控制
V0.5
Boolean
读写
2号电机启停控制
V0.6
Boolean
读写
3号电机启停控制
V0.7
Boolean
读写
4号电机启停控制
VD100
Unsigned16
只读
电压(V)
VD200
Unsigned16
只读
电流(A)
2. MQTT通信相关参数Broker:1883.dtuip.com:1883ClientID:820000003058164FUsername:19381903226Password:ZHZK19381903226订阅Topic:820000003058164F/+发布Topic:820000003058164F3. JSON数据数据JSON格式:{        "sensorDatas":        [                {                        "flag":"em1Status",                        "switcher":1                },                {                        "flag":"em2Status",                        "switcher":1                },                {                        "flag":"em3Status",                        "switcher":1                },                {                        "flag":"em4Status",                        "switcher":1                },                {                        "flag":"em1Control",                        "switcher":0                },                {                        "flag":"em2Control",                        "switcher":0                },                {                        "flag":"em3Control",                        "switcher":0                },                {                        "flag":"em4Control",                        "switcher":0                },                {                        "flag":"voltage",                        "value":220.0                },                {                        "flag":"current",                        "value":10.2                }        ]}

需求分析

在制作流程时,基础的逻辑是根据数据走向来制作流程该需求经过分析可以得出,主要分为数据上行和数据下行两个部分。其中,数据上行主要工作有:



    • 通过S7协议读取PLC的数据,得到的数据存储在内存中(S7节点)
    • 将数据按照JSON格式进行格式化(函数节点)
    • 建立MQTT连接,发布到指定主题(MQTT发布节点)

数据下行主要工作有:




    • 订阅MQTT主题,接收平台下发数据(MQTT订阅节点)
    • 将收到的JSON数据解析后存储在内存中(函数节点)
    • 按照S7要求的格式写入PLC中(S7节点)


                               
登录/注册后可看大图
需求实现1. 采集PLC数据



    • 从节点库拖入一个S7读数据节点,以及一个调试节点,调试节点用于查看读取到的PLC的数据,方便定位问题


                               
登录/注册后可看大图



    • 双击S7读数据节点,根据需求概述的内容填写对应的设置参数,如下图所示:

IPLC的IP端口:102(S7协议通信默认端口102)模式:TASP(S7-200 Smart选择TASP,其余型号选择Rack/Slot)本地TSAP:1002(固定值)远端TSAP:0301(固定值)采集周期:1000ms(默认1000ms,可自定义)超时周期:2000ms(默认2000ms,可自定义)数据点配置(根据帮助文档可以找到对应关系)V0.0-->DB1,X0.0V0.1-->DB1,X0.1V0.2-->DB1,X0.2V0.3-->DB1,X0.3V0.4-->DB1,X0.4V0.5-->DB1,X0.5V0.6-->DB1,X0.6V0.7-->DB1,X0.7VD100 -->DB1,W100VD200 -->DB1,W200输出模式可以根据需求选择,这里选择所有变量输出一条

如果设置正确,调试窗口会有日志打印,显示的是读取到的数据内容


                               
登录/注册后可看大图



    • 有的时候PLC数据点比较多,手动依次录入比较繁琐。节点支持数据点的导入导出:


                               
登录/注册后可看大图

2. 数据格式化

根据步骤2的引导,在调试窗口可以看到读到的PLC数据如下:


                               
登录/注册后可看大图

因为应用平台已经规定了数据必须按照JSON格式上报。接下来使用函数节点Javascrip代码将数据进行格式化,代码如下:

let jsonArray = []jsonArray.push({ "flag": "em1Status", "switcher": msg.payload.em1Status == true ? 1 : 0 })jsonArray.push({ "flag": "em2Status", "switcher": msg.payload.em2Status == true ? 1 : 0 })jsonArray.push({ "flag": "em3Status", "switcher": msg.payload.em3Status == true ? 1 : 0 })jsonArray.push({ "flag": "em4Status", "switcher": msg.payload.em4Status == true ? 1 : 0 })jsonArray.push({ "flag": "em1Control", "switcher": msg.payload.em1Control == true ? 1 : 0 })jsonArray.push({ "flag": "em2Control", "switcher": msg.payload.em2Control == true ? 1 : 0 })jsonArray.push({ "flag": "em3Control", "switcher": msg.payload.em3Control == true ? 1 : 0 })jsonArray.push({ "flag": "em4Control", "switcher": msg.payload.em4Control == true ? 1 : 0 })jsonArray.push({ "flag": "voltage", "value": msg.payload.voltage / 100 })/*两位小数*/jsonArray.push({ "flag": "current", "value": msg.payload.current / 100 })/*两位小数*/let data = {}data.sensorDatas = jsonArraymsg.payload = JSON.stringify(data)return msg

复制以上代码,粘贴到函数节点内,部署后即可看到效果:


                               
登录/注册后可看大图

可以看到,已经将读到的PLC数据,按照需求要求转换成了最终的JSON格式,且对数据进行了一定程度的计算(两位小数)。此处只是函数节点的冰山一角,因为支持Javascrip语言编程,几乎你能想到的任何功能都可以在这里实现


                               
登录/注册后可看大图
3. 通过MQTT上报数据

拖入一个MQTT发布节点,根据提示进行配置,填入MQTT连接相关信息及MQTT发布主题后(详情见需求概述),即可实现数据上报。可以看到,数据上报成功后,应用平台显示绿色表明设备上线且数据正常:


                               
登录/注册后可看大图

至此,数据上报已经完成,很简单几步即可实现:采集PLC数据并按照自定义JSON格式上报。

4. 通过MQTT接收数据

拖入一个MQTT订阅节点,注意:MQTT发布节点和MQTT订阅节点可以共用一个MQTT连接,如果使用的是同一个连接,只是不同的Topic,拖入节点后选择已经配置好的连接即可。如果选择添加新的mqtt-broker节点,则代表的是新建一个MQTT连接


                               
登录/注册后可看大图

选择一个调试节点,在平台点击控制按钮后,调试窗口可以看到下发的指令:


                               
登录/注册后可看大图
5. 数据解析

根据S7写数据节点的帮助文档,可以知道,要想实现向PLC写入数据,需要传递的数据携带两个参数,如下:


                               
登录/注册后可看大图

因此,数据解析时,需要将应用平台下发的数据转换为携带payload和variable两个变量的消息,传递给S7写数据节点,函数节点的代码如下:

let cmdDate = msg.payloadmsg.variable = cmdDate.sensorDatas[0].flagmsg.payload = cmdDate.sensorDatas[0].switcher == 1 ? true : falsereturn msg

复制以上代码,粘贴到函数节点内,将调试节点设置为输出原始消息,可以看到打印内容如下:


                               
登录/注册后可看大图

可以看到数据已经转换为S7写数据节点要求的格式


                               
登录/注册后可看大图
6. 写入PLC

拖入一个S7写数据节点,连接函数计算节点,在应用平台操作开关,看演示效果:


                               
登录/注册后可看大图
总结
本章节介绍了一个相对复杂的流程,旨在表述网关所具备的能力,因此并未对程序的安全性、稳定性、灵活性等方面做优化。通过理解本流程,相信你已经对网关的可视化编程有了一定的熟悉。接下来,深入学习每个节点的功能用法吧,掌握它们将会为你制作更复杂的流程提供更多的选择和可能!
源码
所有的流程支持以json格式导入导出,方便与其他人分享做好的流程。本章节的流程json文件如下,复制后在菜单栏右上角选择导入粘贴即可,导出同理
[{"id":"c8d138cd30e452fc","type":"s7 in","z":"2ff624305b8cb30b","endpoint":"374f5d9e3d2741c0","mode":"all","variable":"","diff":false,"name":"读PLC数据","x":180,"y":180,"wires":[["03f0b9014af25c1d"]]},{"id":"4abb25e7e75b3447","type":"mqtt out","z":"2ff624305b8cb30b","name":"发布数据","topic":"820000003058164F","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"8d85be060cbc6545","x":520,"y":180,"wires":[]},{"id":"63f2816a781192d5","type":"mqtt in","z":"2ff624305b8cb30b","name":"订阅数据","topic":"820000003058164F/+","qos":"0","datatype":"auto-detect","broker":"8d85be060cbc6545","nl":false,"rap":true,"rh":0,"inputs":0,"x":180,"y":260,"wires":[["1b6776e208355720"]]},{"id":"03f0b9014af25c1d","type":"function","z":"2ff624305b8cb30b","name":"数据格式化","func":"let jsonArray = []\n\njsonArray.push({ \"flag\": \"em1Status\", \"switcher\": msg.payload.em1Status == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em2Status\", \"switcher\": msg.payload.em2Status == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em3Status\", \"switcher\": msg.payload.em3Status == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em4Status\", \"switcher\": msg.payload.em4Status == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em1Control\", \"switcher\": msg.payload.em1Control == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em2Control\", \"switcher\": msg.payload.em2Control == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em3Control\", \"switcher\": msg.payload.em3Control == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"em4Control\", \"switcher\": msg.payload.em4Control == true ? 1 : 0 })\njsonArray.push({ \"flag\": \"voltage\", \"value\": msg.payload.voltage / 100 })/*两位小数*/\njsonArray.push({ \"flag\": \"current\", \"value\": msg.payload.current / 100 })/*两位小数*/\n\nlet data = {}\ndata.sensorDatas = jsonArray\n\nmsg.payload = JSON.stringify(data)\n\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":180,"wires":[["4abb25e7e75b3447"]]},{"id":"1b6776e208355720","type":"function","z":"2ff624305b8cb30b","name":"函数计算 1","func":"let cmdDate = msg.payload\n\nmsg.variable = cmdDate.sensorDatas[0].flag\nmsg.payload = cmdDate.sensorDatas[0].switcher == 1 ? true : false\n\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":260,"wires":[["140b525dd4d0608b"]]},{"id":"140b525dd4d0608b","type":"s7 out","z":"2ff624305b8cb30b","endpoint":"374f5d9e3d2741c0","variable":"","name":"","x":510,"y":260,"wires":[]},{"id":"374f5d9e3d2741c0","type":"s7 endpoint","transport":"iso-on-tcp","address":"192.168.0.24","port":"102","rack":"0","slot":"2","localtsaphi":"10","localtsaplo":"02","remotetsaphi":"03","remotetsaplo":"01","connmode":"tsap","adapter":"","busaddr":"2","cycletime":"2000","timeout":"2000","name":"LC","vartable":[{"addr":"DB1,X0.0","name":"em1Status"},{"addr":"DB1,X0.1","name":"em2Status"},{"addr":"DB1,X0.2","name":"em3Status"},{"addr":"DB1,X0.3","name":"em4Status"},{"addr":"DB1,X0.4","name":"em1Control"},{"addr":"DB1,X0.5","name":"em2Control"},{"addr":"DB1,X0.6","name":"em3Control"},{"addr":"DB1,X0.7","name":"em4Control"},{"addr":"DB1,W100","name":"voltage"},{"addr":"DB1,DW200","name":"current"}]},{"id":"8d85be060cbc6545","type":"mqtt-broker","name":"","broker":"1883.dtuip.com:1883","port":"1883","clientid":"820000003058164F","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]注意
MQTT配置节点导出时,不会携带用户名和密码。因此导入时需要重新录入用户名和密码





回复

使用道具 举报

1

主题

141

回帖

469

积分

中级会员

积分
469
金钱
327
HASS币
0
发表于 前天 22:59 | 显示全部楼层
666,不明觉厉
回复

使用道具 举报

26

主题

304

回帖

2342

积分

金牌会员

积分
2342
金钱
2012
HASS币
0
发表于 昨天 08:18 | 显示全部楼层
老司机开车
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian ( 晋ICP备17001384号-1 )

GMT+8, 2025-8-20 21:22 , Processed in 0.064734 second(s), 7 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表