场景自动化与调度
场景自动化与调度
本节介绍智能家居系统的场景自动化和定时调度功能。学习完成后,您将能够:
- 设计智能家居场景模式和触发条件
- 实现 Node-RED 场景编排逻辑
- 配置定时调度和自动化规则
- 评估场景自动化方案的技术边界
在开始本节之前,请确保:
- 已完成 Node-RED 基础学习
- 已完成 MQTT 通信配置
- 了解 IF-THEN 规则引擎的基本概念
Scene Mode System
Section titled “Scene Mode System”Scene Definitions
Section titled “Scene Definitions”// Node-RED 场景配置const scenes = { // 离家模式 "away": { name: "离家", icon: "🏃", actions: [ {topic: "home/light/livingroom/set", payload: '{"state":"OFF"}'}, {topic: "home/light/bedroom/set", payload: '{"state":"OFF"}'}, {topic: "home/light/kitchen/set", payload: '{"state":"OFF"}'}, {topic: "home/climate/livingroom/mode/set", payload: '"off"'}, {topic: "home/climate/bedroom/mode/set", payload: '"off"'}, {topic: "home/curtain/livingroom/set", payload: '{"position":0}'}, {topic: "home/curtain/bedroom/set", payload: '{"position":0}'}, {topic: "home/alarm/set", payload: '{"mode":"away"}'}, {topic: "home/panel/display", payload: '{"scene":"away"}', delay: 500} ], reversed: "home" // 反向模式 },
// 回家模式 "home": { name: "回家", icon: "🏠", actions: [ {topic: "home/light/livingroom/set", payload: '{"state":"ON"}'}, {topic: "home/light/livingroom/brightness/set", payload: '50'}, {topic: "home/climate/livingroom/mode/set", payload: '"cool"'}, {topic: "home/climate/livingroom/temperature_set", payload: '26'}, {topic: "home/curtain/livingroom/set", payload: '{"position":50}'}, {topic: "home/alarm/set", payload: '{"mode":"disarm"}'}, {topic: "home/panel/display", payload: '{"scene":"home"}', delay: 500} ], reversed: "away" },
// 睡眠模式 "sleep": { name: "睡眠", icon: "🌙", actions: [ {topic: "home/light/livingroom/set", payload: '{"state":"OFF"}'}, {topic: "home/light/bedroom/set", payload: '{"state":"OFF","brightness":10}'}, {topic: "home/light/nightlight/set", payload: '{"state":"ON"}'}, {topic: "home/curtain/bedroom/set", payload: '{"position":100}'}, {topic: "home/climate/bedroom/mode/set", payload: '"sleep"'}, {topic: "home/climate/bedroom/temperature_set", payload: '24'}, {topic: "home/alarm/set", payload: '{"mode":"sleep"}'}, {topic: "home/panel/display", payload: '{"scene":"sleep"}', delay: 500} ], reversed: null },
// 阅读模式 "reading": { name: "阅读", icon: "📚", actions: [ {topic: "home/light/livingroom/set", payload: '{"state":"ON"}'}, {topic: "home/light/livingroom/brightness/set", payload: '100'}, {topic: "home/light/livingroom/color_temp/set", payload: '4000'}, // 暖白光 {topic: "home/curtain/livingroom/set", payload: '{"position":100}'}, {topic: "home/climate/livingroom/mode/set", payload: '"cool"'}, {topic: "home/panel/display", payload: '{"scene":"reading"}', delay: 500} ], reversed: null }};Scene Execution Flow
Section titled “Scene Execution Flow”Node-RED Scene Flow
Section titled “Node-RED Scene Flow”{ "id": "scene_executor", "nodes": [ // 场景触发源 {"id":"scene_trigger_mqtt","type":"mqtt in", "topic":"home/scene/+/trigger","server":"localhost"}, {"id":"scene_trigger_dashboard","type":"ui_button", "group":"scene_group","label":"场景"}, {"id":"scene_trigger_schedule","type":"inject", "crontab":"0 22 * * *","payload":"sleep","topic":"scene"},
// 场景解析 {"id":"scene_parser","type":"function","func":` var scenes = global.get("scenes") || {}; var sceneName = msg.payload;
if (typeof sceneName === 'string' && scenes[sceneName]) { var scene = scenes[sceneName]; var sequence = [];
// 生成动作序列 scene.actions.forEach(function(action, index) { var delay = action.delay || 0; sequence.push({ topic: action.topic, payload: action.payload, delay: delay + index * 200 // 每个动作间隔 200ms }); });
// 记录场景执行 node.log(`触发场景: ${scene.name} (${sceneName})`);
return { payload: { scene: sceneName, name: scene.name, icon: scene.icon, sequence: sequence, timestamp: Date.now() } }; } return null; `},
// 顺序执行 {"id":"scene_delay","type":"delay", "timeoutType":"delay","delayType":"fixed"}, {"id":"scene_mqtt_out","type":"mqtt out","qos":1} ]}Automation Rules
Section titled “Automation Rules”IF-THEN Automation
Section titled “IF-THEN Automation”// Node-RED 自动化规则引擎
// 规则定义const rules = [ // 规则 1: 温度 > 30°C → 自动开空调 { id: "rule_high_temp", name: "高温自动空调", condition: (data) => data.temperature > 30, action: { topic: "home/climate/livingroom/mode/set", payload: '"cool"' } },
// 规则 2: 温度 > 28°C 且 湿度 > 70% → 除湿模式 { id: "rule_high_humidity", name: "高湿除湿", condition: (data) => data.temperature > 28 && data.humidity > 70, action: { topic: "home/climate/livingroom/mode/set", payload: '"dry"' } },
// 规则 3: 光照 < 50 lux 且 时间 > 18:00 → 自动开灯 { id: "rule_dark_evening", name: "傍晚自动开灯", condition: (data) => { var now = new Date(); var hour = now.getHours(); return data.lux < 50 && hour >= 18; }, action: { topic: "home/light/livingroom/set", payload: '{"state":"ON","brightness":30}' } },
// 规则 4: 无人移动 30 分钟 → 自动进入节能模式 { id: "rule_no_motion", name: "无人节能", condition: (data) => { var timeSinceMotion = Date.now() - (global.get('lastMotion') || Date.now()); return timeSinceMotion > 1800000; // 30分钟 }, action: { topic: "home/scene/livingroom/trigger", payload: '"away"' } },
// 规则 5: 有人移动 + 光照不足 → 自动开夜灯 { id: "rule_motion_nightlight", name: "夜间感应灯", condition: (data) => { var now = new Date(); var hour = now.getHours(); return data.motion && (hour >= 22 || hour <= 5) && data.lux < 10; }, action: { topic: "home/light/nightlight/set", payload: '{"state":"ON","brightness":20}' } }];Timer Scheduling
Section titled “Timer Scheduling”Daily Schedule Configuration
Section titled “Daily Schedule Configuration”// Node-RED 定时调度
// 使用 inject 节点的 cron 表达式[ // 工作日 7:00 → 起床场景 {"id":"timer_wakeup","type":"inject", "crontab":"0 7 * * 1-5", "payload":"{\"scene\":\"home\",\"params\":{\"brightness\":60}}", "topic":"home/scene/livingroom/trigger"},
// 工作日 8:30 → 离家场景 {"id":"timer_leave","type":"inject", "crontab":"30 8 * * 1-5", "payload":"\"away\"", "topic":"home/scene/livingroom/trigger"},
// 工作日 17:30 → 回家场景 {"id":"timer_return","type":"inject", "crontab":"30 17 * * 1-5", "payload":"\"home\"", "topic":"home/scene/livingroom/trigger"},
// 每天 22:00 → 睡眠场景 {"id":"timer_sleep","type":"inject", "crontab":"0 22 * * *", "payload":"\"sleep\"", "topic":"home/scene/livingroom/trigger"},
// 周末 9:00 → 起床 {"id":"timer_weekend","type":"inject", "crontab":"0 9 * * 6,0", "payload":"{\"scene\":\"home\"}", "topic":"home/scene/livingroom/trigger"}]LVGL Scene UI
Section titled “LVGL Scene UI”Scene Display on Panel
Section titled “Scene Display on Panel”// ESP32 面板上的场景选择界面void create_scene_selection() { lv_obj_t* scenePage = lv_obj_create(screen); lv_obj_set_size(scenePage, LV_PCT(100), LV_PCT(100));
// 场景标题 lv_obj_t* title = lv_label_create(scenePage); lv_label_set_text(title, "选择场景模式"); lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0); lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20);
// 场景按钮网格 (2x2) const char* scenes[][2] = { {"🏃 离家", "away"}, {"🏠 回家", "home"}, {"🌙 睡眠", "sleep"}, {"📚 阅读", "reading"} };
int btnWidth = 120; int btnHeight = 80; int startX = (TFT_WIDTH - btnWidth * 2) / 3; int startY = 80; int gapX = (TFT_WIDTH - btnWidth * 2) / 3; int gapY = 30;
for (int i = 0; i < 4; i++) { int row = i / 2; int col = i % 2; int x = startX + col * (btnWidth + gapX); int y = startY + row * (btnHeight + gapY);
lv_obj_t* btn = lv_btn_create(scenePage); lv_obj_set_size(btn, btnWidth, btnHeight); lv_obj_set_pos(btn, x, y); lv_obj_set_style_radius(btn, 16, 0);
// 不同的场景颜色 lv_palette_t colors[] = {LV_PALETTE_TEAL, LV_PALETTE_GREEN, LV_PALETTE_INDIGO, LV_PALETTE_ORANGE}; lv_obj_set_style_bg_color(btn, lv_palette_main(colors[i]), 0);
lv_obj_t* label = lv_label_create(btn); lv_label_set_text(label, scenes[i][0]); lv_obj_center(label);
// 绑定场景触发 lv_obj_add_event_cb(btn, [](lv_event_t* e) { const char* scene = (const char*)lv_event_get_user_data(e); mqttClient.publish("home/scene/livingroom/trigger", scene); }, LV_EVENT_CLICKED, (void*)scenes[i][1]); }}Pre-sales Key Points
Section titled “Pre-sales Key Points”| 自动化类型 | 功能 | 买家价值 |
|---|---|---|
| 场景模式 | 一键多设备联动 | ”一键切换整个家居状态” |
| 定时调度 | 按时间自动执行 | ”每天7点自动起床场景” |
| 条件触发 | 传感器 → 自动化 | ”温度过高自动开空调” |
| 缺席检测 | 无运动自动节能 | ”离家自动关灯关空调” |
| 场景反转 | 离/回家场景互逆 | ”离家关闭的设备回家自动开启” |
Summary
Section titled “Summary”本节介绍了智能家居场景自动化和定时调度:
- 场景模式:离家、回家、睡眠、阅读等预设场景
- 场景执行流程:节点触发 → 动作序列 → MQTT 控制
- 自动化规则:IF-THEN 规则引擎基于传感器数据触发
- 定时调度:cron 表达式实现每日/工作日/周末定时触发
- 面板场景 UI:LVGL 场景选择界面,一键触发场景