目录
-
- 一、项目目标
- 二、S7节点配置
- 三、变量分流
- 四、边沿检测
- 五、本篇小结
玩转Node-Red
一、项目目标
需要通过 Node-RED 读取 PLC 状态,并根据设备运行状态推送企业微信消息。整体架构不是把所有逻辑堆在一个 Function 节点里,而是拆成几个清晰模块:
S7读取PLC变量
↓
按变量名分流
├── 模式变量 -> 存储到flow上下文
└── 状态变量 -> 边沿检测
这样后续无论是文本报警,还是 PDF 报告推送,都可以复用同一个状态判断结果。

二、S7节点配置
安装节点:
node-red-contrib-s7
PLC 连接参数示例:
Address:<PLC设备IP>
Port:102
Rack:<机架号>
Slot:<机槽号>
Cycle time:1000 ms
Timeout:2000 ms
变量表示例:
Mode2_R <PLC模式变量地址>
EndingFlag <PLC结束标志变量地址>
建议:
- 变量数量较少时,可以直接在 S7 节点里配置变量表。
- 变量较多时,建议拆多个 S7 节点,或读取整个 DB 块后在 Node-RED 中解析。
- diff 建议打开,只在变量变化时输出,减少后续节点压力。
PLC端:
- CPU属性-防护安全(完全访问)、连接机制(勾选允许Put/Get)

三、变量分流
S7 节点输出后,接一个 switch 节点,根据 msg.topic 分流:
msg.topic == Mode2_R -> 存储Mode
msg.topic == EndingFlag -> 边沿检测
Mode2_R 用来表示当前工作模式,进入 存储Mode 节点:
flow.set('mode', msg.payload);
return null;
这里使用 flow 上下文,是因为后续构造企业微信消息时,需要拿到当前模式。


四、边沿检测
EndingFlag 进入边沿检测节点。核心思路:
- 保存上一次状态。
- 当前值从 false -> true,判断为上升沿。
- 当前值从 true -> false,判断为下降沿。
- 上升沿记录开始时间。
- 下降沿计算运行时长。
关键状态结构:
const pointName = msg.topic;
let storage = context.get(pointName) || {
lastValue: false,
initialized: false,
risingTime: null
};
上升沿:
if (currentValue === true && storage.lastValue === false) {
newMsg.edgeType = "rising";
storage.lastValue = true;
storage.risingTime = Date.now();
context.set(pointName, storage);
return newMsg;
}
下降沿:
if (currentValue === false && storage.lastValue === true) {
newMsg.edgeType = "falling";
storage.lastValue = false;
if (storage.risingTime !== null) {
const durationMs = Date.now() – storage.risingTime;
newMsg.durationMs = durationMs;
newMsg.duration = formatDuration(durationMs);
} else {
newMsg.duration = "无上升沿记录";
}
storage.risingTime = null;
context.set(pointName, storage);
return newMsg;
}
运行时长格式化可以单独封装:
function formatDuration(durationMs) {
const minutes = Math.floor(durationMs / 60000);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const remainingHours = hours % 24;
const remainingMinutes = minutes % 60;
let text = "";
if (days > 0) text += `${days}天`;
if (remainingHours > 0) text += `${remainingHours}小时`;
if (remainingMinutes > 0 || text === "") text += `${remainingMinutes}分钟`;
return text;
}
五、本篇小结
这一篇完成了 PLC 状态采集和状态判断:
PLC变量
↓
S7节点
↓
switch分流
├── 模式保存
└── 上升沿/下降沿判断
这个架构的关键是:先把状态判断做干净,后面的报警、PDF推送都只消费 edgeType。



