跳转到内容

Node-RED 智能家居仪表板

Node-RED 智能家居仪表板

本节介绍如何通过 Node-RED 创建智能家居系统的 Web 仪表板,作为面板的补充控制界面。学习完成后,您将能够:

  • 设计 Node-RED 智能家居仪表板的布局
  • 创建灯光、温控、场景等控制模块
  • 实现仪表板与 ESP32 面板的双向状态同步
  • 为售后和运维人员提供 Web 控制界面

在开始本节之前,请确保:

  • 已完成 Node-RED 基础学习
  • 已完成 MQTT Topic 设计
  • Node-RED 已安装 dashboard 节点(node-red-dashboard)
Terminal window
# 在 Node-RED 中安装 dashboard 节点
cd ~/.node-red
npm install node-red-dashboard
# 重启 Node-RED
Smart Home Dashboard
├── Tab: 首页概览
│ ├── Group: 环境数据
│ │ ├── 温度计 (gauge)
│ │ ├── 湿度计 (gauge)
│ │ └── 光照指示器
│ └── Group: 快捷控制
│ ├── 一键离家按钮
│ └── 一键睡眠按钮
├── Tab: 灯光控制
│ ├── Group: 客厅灯光
│ │ ├── 开关 (switch)
│ │ ├── 亮度滑块 (slider)
│ │ └── 色温选择器
│ └── Group: 卧室灯光
│ ├── 开关 (switch)
│ └── 亮度滑块 (slider)
├── Tab: 环境控制
│ ├── Group: 空调控制
│ │ ├── 温度设定 (numeric)
│ │ ├── 模式选择 (dropdown)
│ │ └── 风速选择
│ └── Group: 窗帘控制
│ └── 开合度 (slider)
└── Tab: 场景管理
├── Group: 场景触发
│ ├── 离家模式按钮
│ ├── 回家模式按钮
│ ├── 睡眠模式按钮
│ └── 阅读模式按钮
└── Group: 定时任务
└── 定时设置表
{
"id": "sensor_data_flow",
"nodes": [
{
"id": "mqtt_sensor_in",
"type": "mqtt in",
"topic": "home/panel/livingroom_01/sensors",
"qos": 1,
"server": "localhost"
},
{
"id": "parse_sensor",
"type": "function",
"func": "var data = JSON.parse(msg.payload);\nreturn [\n {payload: data.temp},\n {payload: data.hum},\n {payload: data.lux}\n];",
"outputs": 3
},
{
"id": "temp_gauge",
"type": "ui_gauge",
"group": "env_group",
"label": "温度",
"format": "{{value}}°C",
"min": 0,
"max": 50
},
{
"id": "hum_gauge",
"type": "ui_gauge",
"group": "env_group",
"label": "湿度",
"format": "{{value}}%",
"min": 0,
"max": 100
},
{
"id": "lux_text",
"type": "ui_text",
"group": "env_group",
"label": "光照"
},
{
"id": "chart_temp",
"type": "ui_chart",
"group": "env_group",
"label": "温度趋势",
"chartType": "line",
"xmax": 60
}
]
}
// 灯光控制流程
// MQTT In (状态反馈) → UI (仪表板显示) → MQTT Out (控制命令)
// 1. 读取灯光状态
// MQTT In: home/light/livingroom/status
[
{"id":"light_status_in","type":"mqtt in",
"topic":"home/light/livingroom/status","server":"localhost"},
{"id":"light_status_ui","type":"ui_switch",
"group":"light_group","label":"客厅灯"},
{"id":"status_to_ui","type":"function",
"func":"var data = JSON.parse(msg.payload);\nmsg.payload = data.state === 'ON';\nreturn msg;"}
]
// 2. 发送控制命令
// UI Switch → 函数转换 → MQTT Out
[
{"id":"light_switch_ui","type":"ui_switch",
"group":"light_group","label":"客厅灯"},
{"id":"light_control","type":"function",
"func":"var state = msg.payload ? 'ON' : 'OFF';\nmsg.payload = JSON.stringify({state: state});\nreturn msg;"},
{"id":"light_set_out","type":"mqtt out",
"topic":"home/light/livingroom/set","qos":1,"server":"localhost"}
]
// 3. 亮度控制
// UI Slider → 转换 → MQTT Out
[
{"id":"brightness_slider","type":"ui_slider",
"group":"light_group","label":"亮度",
"min":0,"max":100,"step":1},
{"id":"brightness_control","type":"function",
"func":"msg.payload = JSON.stringify({brightness: msg.payload});\nreturn msg;"},
{"id":"brightness_out","type":"mqtt out",
"topic":"home/light/livingroom/brightness/set","qos":1}
]
// 场景按钮 → MQTT 命令 → ESP32/LVGL 面板 → 执行设备动作
// Node-RED 场景按钮
[
{"id":"scene_away","type":"ui_button",
"group":"scene_group","label":"🏃 离家",
"payload":"离家","topic":"home/scene/livingroom/trigger"},
{"id":"scene_home","type":"ui_button",
"group":"scene_group","label":"🏠 回家",
"payload":"回家","topic":"home/scene/livingroom/trigger"},
{"id":"scene_sleep","type":"ui_button",
"group":"scene_group","label":"🌙 睡眠",
"payload":"睡眠","topic":"home/scene/livingroom/trigger"}
]
// 场景执行函数
function execute_scene(scene_name) {
switch(scene_name) {
case '离家':
// 关闭所有灯光
send_mqtt("home/light/livingroom/set", '{"state":"OFF"}');
send_mqtt("home/light/bedroom/set", '{"state":"OFF"}');
// 关闭空调
send_mqtt("home/climate/livingroom/mode/set", '"off"');
// 开启安防
send_mqtt("home/alarm/set", '{"mode":"away"}');
// 关闭所有窗帘
send_mqtt("home/curtain/livingroom/set", '{"position":0}');
break;
case '回家':
// 开启客厅灯光(50% 亮度)
send_mqtt("home/light/livingroom/set", '{"state":"ON"}');
send_mqtt("home/light/livingroom/brightness/set", '50');
// 开启空调(26°C)
send_mqtt("home/climate/livingroom/temperature_set", '26');
send_mqtt("home/climate/livingroom/mode/set", '"cool"');
// 关闭安防
send_mqtt("home/alarm/set", '{"mode":"disarm"}');
break;
case '睡眠':
// 关闭所有灯光
send_mqtt("home/light/livingroom/set", '{"state":"OFF"}');
// 关闭窗帘
send_mqtt("home/curtain/bedroom/set", '{"position":100}');
// 设置夜灯
send_mqtt("home/light/nightlight/set", '{"state":"ON","brightness":10}');
// 设置空调睡眠模式
send_mqtt("home/climate/bedroom/mode/set", '"sleep"');
break;
}
}
// 确保 ESP32 面板和 Web 仪表板状态同步
// 流程:任何状态变化 → 统一分发
[
{"id":"state_change_monitor","type":"function",
"func":"// 收到任何状态变化消息\n// 将状态同时推送到:\n// 1. ESP32 面板 (home/panel/display)\n// 2. Web Dashboard (自动通过 websocket)\n// 3. 日志记录\n\nvar topic = msg.topic;\nvar payload = msg.payload;\n\n// 日志记录\nnode.log(`状态变化: ${topic} = ${JSON.stringify(payload)}`);\n\n// 转发到面板显示\nvar panelMsg = {\n topic: 'home/panel/livingroom_01/display',\n payload: {\n changed_topic: topic,\n value: payload\n }\n};\nreturn panelMsg;"}
]
// 简单认证控制
const validUsers = [
{user: "admin", pass: "admin123"},
{user: "user", pass: "user123", readonly: true}
];
// HTTP 请求认证
if (msg.req && msg.req.user) {
const user = validUsers.find(u => u.user === msg.req.user.username);
if (user) {
msg.readonly = user.readonly || false;
return msg;
}
}
return null; // 拒绝访问
对比维度LVGL 本地面板Node-RED Web 仪表板
位置安装在墙面上手机/电脑浏览器
响应速度极快(本地)依赖网络延迟
展示效果定制 UI通用仪表板
远程访问需 VPN/公网任何有网络的地方
控制粒度有限屏幕空间丰富控制选项
适合用户家庭成员管理员/运维人员

本节介绍了 Node-RED 智能家居仪表板的创建:

  1. 仪表板结构:标签页 + 分组的模块化布局
  2. 控制流程:环境数据显示、灯光控制、场景触发
  3. 场景编排:一键多设备联动(离家/回家/睡眠模式)
  4. 状态同步:Web 仪表板与 ESP32 面板双向同步
  5. 访问控制:仪表板的用户权限管理