功率阈值逻辑
功率阈值逻辑
本节介绍如何设计和实现功率阈值逻辑,实现对设备能耗的智能监控。学习完成后,您将能够:
- 设计多级功率阈值架构
- 实现阈值触发和自动响应
- 结合时间条件优化控制策略
- 构建灵活的阈值配置管理系统
Threshold Architecture
Section titled “Threshold Architecture”功率值▲│ CRITICAL: 2000W ──┼────────────────────── 过载保护,立即断电│ ││ WARNING: 1500W ───┼──────────────── 告警通知,关注负载│ ││ NORMAL: 800W ─────┼─────────── 正常运行范围│ ││ LOW: 50W ─────────┼───── 待机/低功耗│ ││ OFF: 5W ──────────┼─ 设备关闭/断电│└──────────────────────────────────────────► 时间Multi-Level Threshold Implementation
Section titled “Multi-Level Threshold Implementation”配置式阈值管理
Section titled “配置式阈值管理”// Function: 多级阈值检测引擎// 支持灵活的阈值配置
// 阈值配置 (可从 Flow/Global Context 动态加载)var thresholds = context.get("powerThresholds") || { device: { "shellyplus1pm-LINE1": { critical: { max: 2000, action: "shutdown" }, warning: { max: 1500, action: "notify" }, normal: { min: 50, max: 1500 }, standby: { max: 50 } }, "tasmota-socket1": { critical: { max: 2500, action: "shutdown" }, warning: { max: 2000, action: "notify" }, normal: { min: 100, max: 2000 }, standby: { max: 100 } } }, default: { critical: { max: 2000, action: "shutdown" }, warning: { max: 1500, action: "notify" }, normal: { min: 10, max: 1500 }, standby: { max: 10 } }};
// 获取设备 IDvar deviceId = msg.payload.device || "unknown";
// 获取当前功率var power = msg.payload.power;if (power === undefined || power === null) { return null;}
// 获取设备阈值配置var deviceThreshold = thresholds.device[deviceId] || thresholds.default;
// 获取上次状态var lastState = context.get("powerState_" + deviceId) || "unknown";
// 判断当前状态var currentState;if (power > deviceThreshold.critical.max) { currentState = "critical";} else if (power > deviceThreshold.warning.max) { currentState = "warning";} else if (power >= deviceThreshold.normal.min) { currentState = "normal";} else if (power >= deviceThreshold.standby.max) { currentState = "standby";} else { currentState = "off";}
// 状态变化检测var stateChanged = (currentState !== lastState);
if (stateChanged) { context.set("powerState_" + deviceId, currentState); node.status({ fill: currentState === "critical" ? "red" : currentState === "warning" ? "yellow" : "green", shape: "dot", text: currentState });}
// 构建结果msg.payload = { device: deviceId, power: power, state: currentState, state_changed: stateChanged, previous_state: lastState, threshold_config: deviceThreshold, action_required: currentState === "critical" || currentState === "warning", timestamp: Date.now()};
// 触发告警的附加信息if (currentState === "critical" && deviceThreshold.critical.action === "shutdown") { msg.shutdown = true;}if (currentState === "warning") { msg.alert = true;}
return msg;Time-Aware Thresholds
Section titled “Time-Aware Thresholds”根据时间段调整阈值
Section titled “根据时间段调整阈值”// Function: 时间感知的阈值调整
var now = new Date();var hour = now.getHours();
// 按时间段调整阈值 (白天/夜晚)var timeConfig = { // 工作时间 (08:00-20:00): 正常阈值 workday: { warning: 2000, critical: 2500 }, // 非工作时间 (20:00-08:00): 更敏感的阈值 night: { warning: 500, // 夜间设备应低功耗 critical: 1000 // 超过 1000W 可能异常 }};
// 判断当前时段var isNight = (hour >= 20 || hour < 8);var config = isNight ? timeConfig.night : timeConfig.workday;
var power = msg.payload.power;
var state = "normal";if (power > config.critical) { state = "critical";} else if (power > config.warning) { state = "warning";}
// 夜间模式下异常更敏感if (isNight && state === "warning") { // 夜间告警升级 msg.severity = "high";} else { msg.severity = "normal";}
msg.payload = { power: power, state: state, period: isNight ? "night" : "workday", thresholds: config, severity: msg.severity, timestamp: Date.now()};
return msg;Cumulative Consumption Control
Section titled “Cumulative Consumption Control”基于累计电量的控制
Section titled “基于累计电量的控制”// Function: 累计电量控制// 当日用电量超过设定值时触发
var todayKwh = msg.payload.today_kwh || 0;var deviceId = msg.payload.device || "unknown";
// 每日用电量上限配置 (kWh)var DAILY_LIMIT = { "shellyplus1pm-LINE1": 10, "shellyplus1pm-LINE2": 5, "default": 8};
var limit = DAILY_LIMIT[deviceId] || DAILY_LIMIT.default;
// 检测日期变更,重置累计var today = new Date().toISOString().split('T')[0];var lastDate = context.get("lastDate_" + deviceId);
if (lastDate !== today) { context.set("lastDate_" + deviceId, today); context.set("dailyAlert_" + deviceId, false);}
if (todayKwh > limit) { var alreadyAlerted = context.get("dailyAlert_" + deviceId) || false;
if (!alreadyAlerted) { context.set("dailyAlert_" + deviceId, true);
msg.payload = { device: deviceId, type: "daily_limit", current_kwh: todayKwh, limit_kwh: limit, exceeded_by: (todayKwh - limit).toFixed(2), message: "设备 " + deviceId + " 今日用电量 " + todayKwh + "kWh 已超过限额 " + limit + "kWh", timestamp: Date.now() };
return msg; }}
return null; // 未超过限额或已告警Dynamic Threshold Configuration
Section titled “Dynamic Threshold Configuration”通过 Node-RED Dashboard 动态调整阈值
Section titled “通过 Node-RED Dashboard 动态调整阈值”// Function: 接收 Dashboard 滑条/输入组件传来的阈值更新// 输入: {"device":"shellyplus1pm-LINE1","threshold":"warning","value":1800}
var config = msg.payload;if (config.device && config.threshold && config.value) { var thresholds = context.get("powerThresholds") || {};
if (!thresholds.device) { thresholds.device = {}; } if (!thresholds.device[config.device]) { thresholds.device[config.device] = {}; }
thresholds.device[config.device][config.threshold] = { max: Number(config.value), action: config.threshold === "critical" ? "shutdown" : "notify" };
context.set("powerThresholds", thresholds);
node.log("Threshold updated: " + config.device + " " + config.threshold + " = " + config.value + "W");
msg.payload = { status: "ok", message: "阈值已更新" };
return msg;}# 1. 模拟功率过载mosquitto_pub -t "tele/tasmota/socket1/SENSOR" \ -m '{"ENERGY":{"Power":2100,"Voltage":223,"Current":9.4}}'
# 2. 检查是否触发 critical 状态和 shutdown 动作# Node-RED Debug 面板应显示 state: "critical"
# 3. 恢复模拟正常值mosquitto_pub -t "tele/tasmota/socket1/SENSOR" \ -m '{"ENERGY":{"Power":800,"Voltage":223,"Current":3.6}}'
# 4. 状态应恢复为 normalCommon Customer Questions
Section titled “Common Customer Questions”Q1: 阈值设置多大合适?
Section titled “Q1: 阈值设置多大合适?”取决于设备类型和场景:
- 照明回路: 500-1000W
- 办公设备: 1500-2000W
- 空调/电机: 2000-3500W
- 建议先采集一周数据后根据实际值调整阈值
Q2: 如何避免功率瞬态波动导致误触发?
Section titled “Q2: 如何避免功率瞬态波动导致误触发?”在 Function 中引入去抖逻辑:连续 N 次超过阈值才触发动作,或使用阈值持续时间判定(如超过阈值持续 30 秒)。
✅ 推荐做法:
- 使用多级阈值(正常/警告/严重)分级响应
- 结合时间条件调整阈值灵敏度
- 实现去抖逻辑避免瞬态误触发
- 阈值配置可从 Dashboard 动态调整
❌ 避免做法:
- 单一固定阈值不适用于所有场景
- 忽略设备启动电流(瞬时峰值)
- 无去抖逻辑导致频繁告警
- 阈值硬编码在 Function 中
Summary
Section titled “Summary”- 多级阈值提供 normal/warning/critical 分级响应
- 时间感知根据白天/夜间调整阈值灵敏度
- 累计电量控制防止单日过度用电
- 去抖逻辑避免瞬态波动误触发
- 阈值可通过 Node-RED Dashboard 动态调整