跳转到内容

Node-RED触发流程

Node-RED触发流程

本节介绍接收和处理 IoT 按钮按键消息的 Node-RED 流程。学习完本节后,您将能够:

  • 创建 MQTT In 节点以接收按钮消息
  • 实现用于开/关操作的切换开关逻辑
  • 集成 Shelly 继电器或其他智能设备
  • 部署并测试完整的按钮到操作流程

开始本节前,请确保:

  • Node-RED 已安装并运行(参见第 09 章)
  • MQTT Broker 已配置(Mosquitto)
  • 已完成 04-08. MQTT消息传输
  • 基本熟悉 Node-RED 流程

按钮触发流程遵循一个简单的链条:

[MQTT In] → [函数:解析] → [切换节点] → [MQTT Out:Shelly]
│ │
└─────────────┴──→ [调试](监控)
节点类型用途
MQTT Inmqtt in订阅按钮主题
解析 JSONfunction从 JSON 负载中提取按钮数据
Togglenode-red-contrib-toggle切换开/关状态
MQTT Outmqtt out发送命令到 Shelly/设备
Debugdebug监控传入消息
Terminal window
# 在 Node-RED 容器或安装目录中
cd ~/.node-red
npm install node-red-contrib-toggle
npm install node-red-contrib-shelly # 可选,用于 Shelly 集成

然后重启 Node-RED。

配置

  • 节点:MQTT In
  • 主题factory/button/#
  • 输出一个解析后的 JSON 对象
  • 名称按键按下
  • 服务器:您的 Mosquitto Broker(选择或添加 MQTT Broker 配置)
╔══════════════════════════════════════════════════╗
║ [MQTT In] ║
║ ║
║ 服务器: Mosquitto(localhost:1883) ║
║ 主题: factory/button/# ║
║ QoS: 1 ║
║ 输出: 自动检测(JSON 字符串) ║
║ ║
║ 名称: 按键按下 ║
╚══════════════════════════════════════════════════╝

# 通配符订阅所有按钮主题,允许多个按钮使用同一流程。

// 解析传入的按钮消息
// 输入:msg.payload = JSON 字符串
// 输出:msg.payload = 解析后的对象
// 按钮发送:{"button_id":"BTN-001","action":"toggle","battery_voltage":3.85}
try {
// 解析 JSON 负载(如果还不是对象)
let data = typeof msg.payload === 'string'
? JSON.parse(msg.payload)
: msg.payload;
// 提取按钮信息
msg.buttonId = data.button_id;
msg.batteryVoltage = data.battery_voltage;
msg.batteryPercent = data.battery_percent;
// 记录电池状态
if (data.battery_percent < 20) {
node.warn(`低电量:${data.button_id} 剩余 ${data.battery_percent}%`);
}
// 设置负载以触发切换
msg.payload = {
action: data.action || "toggle",
source: data.button_id
};
return msg;
} catch (error) {
node.error("解析错误:" + error.message, msg);
return null;
}

节点配置

  • 节点:Function
  • 名称解析按钮数据
  • 输出:1

node-red-contrib-toggle 维护一个状态,并在每次收到消息时切换该状态。

配置

  • 节点:Toggle
  • 主题toggle(或留空)
  • 输出值
    • 开值{"state": "ON", "source": "button"}
    • 关值{"state": "OFF", "source": "button"}
  • 初始状态off
  • 随机:false
  • 名称切换继电器
╔══════════════════════════════════════════════════╗
║ [Toggle] ║
║ ║
║ 起始状态: off ║
║ 开负载: {"state":"ON"} ║
║ 关负载: {"state":"OFF"} ║
║ ║
║ 名称: 切换继电器 ║
╚══════════════════════════════════════════════════╝

步骤 5:创建用于 Shelly 的 MQTT Out 节点

Section titled “步骤 5:创建用于 Shelly 的 MQTT Out 节点”

配置

  • 节点:MQTT Out
  • 主题shellies/shelly1-ABC123/relay/0/command
  • QoS:1
  • 保留:false
  • 名称Shelly 命令
  • 服务器:同一 Mosquitto Broker

注意:将 Shelly 主题替换为您实际的 Shelly 设备主题。

为方便导入,以下是完整的流程:

[
{
"id": "btn_mqtt_in",
"type": "mqtt in",
"topic": "factory/button/#",
"qos": "1",
"datatype": "auto",
"broker": "your_broker_id",
"name": "按键按下",
"x": 100,
"y": 100,
"wires": [["btn_parse"]]
},
{
"id": "btn_parse",
"type": "function",
"func": "try {\n let data = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;\n msg.buttonId = data.button_id;\n msg.batteryVoltage = data.battery_voltage;\n if (data.battery_percent < 20) {\n node.warn(`低电量:${data.button_id} 剩余 ${data.battery_percent}%`);\n }\n msg.payload = {action: data.action || 'toggle', source: data.button_id};\n return msg;\n} catch (error) {\n node.error('解析错误:' + error.message, msg);\n return null;\n}",
"outputs": 1,
"name": "解析按钮数据",
"x": 300,
"y": 100,
"wires": [["btn_toggle"]]
},
{
"id": "btn_toggle",
"type": "toggle",
"name": "切换继电器",
"topic": "",
"onvalue": "{\"state\":\"ON\"}",
"onvalueType": "json",
"offvalue": "{\"state\":\"OFF\"}",
"offvalueType": "json",
"onstartup": false,
"startstate": "off",
"random": false,
"x": 500,
"y": 100,
"wires": [["btn_mqtt_out"]]
},
{
"id": "btn_mqtt_out",
"type": "mqtt out",
"topic": "shellies/shelly1-ABC123/relay/0/command",
"qos": "1",
"retain": "false",
"broker": "your_broker_id",
"name": "Shelly 命令",
"x": 700,
"y": 100,
"wires": []
},
{
"id": "btn_debug",
"type": "debug",
"name": "按钮监控",
"active": true,
"tosidebar": true,
"console": false,
"x": 500,
"y": 200,
"wires": []
}
]

使用 导入 菜单(汉堡菜单 → 导入 → 剪贴板)将此 JSON 导入 Node-RED。

  1. 部署 Node-RED 中的流程
  2. 按下 IoT 按钮(或使用 MQTT Explorer 模拟)
  3. 观察调试面板中的传入消息
  4. 验证Shelly 设备是否随每次按压切换开/关

使用 MQTT CLI 手动测试

Terminal window
# 模拟按钮按下
mosquitto_pub -h localhost -t "factory/button/01/press" \
-m '{"button_id":"BTN-001","action":"toggle","battery_voltage":3.85,"battery_percent":85}'

为演示目的,添加一个模拟按钮按下的注入节点:

[注入节点]
按钮:点击模拟按压
负载:{"button_id":"BTN-DEMO","action":"toggle","battery_voltage":3.85,"battery_percent":85}
重复:无
名称:模拟按钮

要支持多个按钮,添加一个带通配符主题的 MQTT In 节点,并通过按钮 ID 进行路由:

// 函数节点:按按钮路由
let buttonId = msg.buttonId || "unknown";
switch(buttonId) {
case "BTN-001":
msg.topic = "shellies/shelly1-ABC123/relay/0/command";
break;
case "BTN-002":
msg.topic = "shellies/shelly1-DEF456/relay/0/command";
break;
default:
node.warn("未知按钮:" + buttonId);
return null;
}
return msg;
  • MQTT In 节点接收按钮消息
  • 切换节点在每次按压时切换状态
  • Shelly(或目标设备)正确响应
  • 调试面板显示解析后的数据
  • 多次按压一致地交替开/关

症状:按下按钮时调试面板不显示任何内容

可能原因

  • MQTT Broker 连接问题
  • 主题不匹配
  • MQTT In 节点未连接到正确的 Broker

解决方案

Terminal window
# 直接用 mosquitto_sub 测试
mosquitto_sub -h localhost -t "factory/button/#" -v
# 如果这里没有输出,说明按钮没有发布消息
# 检查 ESP32 上的 WiFi 凭据和 MQTT Broker

症状:消息到达但 Shelly 不切换

可能原因

  • 切换输出值与 Shelly 期望值不匹配
  • MQTT Out 节点主题错误
  • Shelly 未连接到 MQTT

解决方案:绕过切换节点直接发送命令进行验证:

Terminal window
# 直接测试 Shelly
mosquitto_pub -h localhost -t "shellies/shelly1-ABC123/relay/0/command" -m "on"
mosquitto_pub -h localhost -t "shellies/shelly1-ABC123/relay/0/command" -m "off"
  • 对多按钮安装使用通配符主题#
  • 在流程中包含电池监测以发送低电量告警
  • 添加通知节点(邮件、短信)用于重要的按钮事件
  • 在流程上下文中存储切换状态以在 Node-RED 重启后持久保持
  • 不要为按钮事件使用保留消息
  • 避免在流程中放置复杂逻辑——保持简单可靠
  1. Node-RED 通过带通配符主题的 MQTT In 节点接收按钮按下消息
  2. 切换节点提供开/关状态切换,每次按压切换一次
  3. MQTT Out 节点发送命令到 Shelly 或其他智能设备
  4. 电池监测可集成用于主动维护
  5. 多按钮支持通过在函数节点中进行主题路由轻松实现