news 2026/11/4 11:11:16

总用电下降了,为什么家庭能源看板仍然提示异常

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
总用电下降了,为什么家庭能源看板仍然提示异常

看板左上角的总功率是 3.8 kW,比昨天同一时刻低了 8%,绿色的趋势线看着很舒服。可往下看,厨房区域的卡片是黄的,上面标着"洗碗机运行中"。

用户的疑问很合理:总量都下降了,还有什么好提示的?

把采样翻出来才看明白。昨天这个点是 4.1 kW,其中客厅空调占了 1.5 kW;今天空调没开,客厅掉到 1.2 kW。省下来的电被厨房吃掉了——洗碗机今天在同一时段启动了,功率 0.8 kW。总量因为这个此消彼长下降了,但厨房确实出现了一台平时不该出现在这个时段的大功率设备。

所以"总量下降"和"每个区域正常"是两件事。看板的异常提示盯的是区域和设备的偏离,跟总量没什么关系。

功率要按来源拆开,不能只记一个总数

第一版的采样只存了一个总功率。这个数据结构没法回答"今天的下降是真的省电,还是光伏出力变大了"。

光伏和储能接进来之后,同一时刻家里有三路能量在动:电网取电、光伏自用、电池放电或充电。总负荷是三者叠加的结果:

exportinterfaceRoomLoad{roomId:stringwatts:number}exportinterfacePowerSample{capturedAt:numbergridW:number// 从电网取电,正数表示消耗solarW:number// 光伏自用部分,恒为正batteryW:number// 正数为充电,负数为放电rooms:RoomLoad[]}exportfunctionhomeLoad(sample:PowerSample):number{// 电池充电时这部分不算家庭负荷,所以取负号把它还原成负荷口径returnsample.gridW+sample.solarW-sample.batteryW}

batteryW的符号约定必须在项目里统一。电池充电时它记正数,家庭负荷要减掉这部分,因为它没有真正被用掉;放电时记负数,减掉负数等于加回来,正好把电池供给的那部分算进负荷。这个符号在早期版本里被两个模块用了不同的约定,界面上出现过"总负荷比电网取电还低"的显示。

界面上的"光伏供给 62%"来自另一组计算:

exportfunctionsolarShare(sample:PowerSample):number{constload:number=homeLoad(sample)if(load<=0){return0}constshare:number=(sample.solarW/load)*100// 光伏可能向电网反送,这里只表示自用占比,上限取 100returnMath.min(100,share)}

基线不能用昨天,要用同一时段的长期分布

最早的异常判定很直觉:拿今天和昨天比,差得多了就报。这个做法在住家里几乎不可用。洗衣服、做饭、洗澡都有星期规律,工作日和周末的差异能到两三倍。用昨天当基线,周二的用电在周一面前永远是异常。

改成按"星期几 + 小时"建槽位,一周 168 个槽:

exportinterfaceBaselineSlot{slotIndex:number// 0 到 167,等于 星期数 * 24 + 小时meanW:number// 该槽位的历史均值stdW:number// 标准差samples:number// 参与统计的样本数}exportinterfaceAnomalyVerdict{abnormal:booleanreason:stringdeviationW:number}constMIN_SAMPLES:number=4constZ_THRESHOLD:number=2.5constMIN_ABSOLUTE_W:number=300exportfunctiondetectAnomaly(slot:BaselineSlot,actualW:number):AnomalyVerdict{constdeviation:number=actualW-slot.meanW// 样本太少就不判定,避免刚装上的设备天天被标异常if(slot.samples<MIN_SAMPLES){return{abnormal:false,reason:'基线样本不足',deviationW:deviation}}// 绝对偏离太小就不报,小功率设备的相对波动没有意义if(Math.abs(deviation)<MIN_ABSOLUTE_W){return{abnormal:false,reason:'偏离在正常范围内',deviationW:deviation}}constsafeStd:number=slot.stdW<1?1:slot.stdWconstz:number=Math.abs(deviation)/safeStdif(z<Z_THRESHOLD){return{abnormal:false,reason:'波动未超过历史范围',deviationW:deviation}}return{abnormal:true,reason:deviation>0?'高于同时段基线':'低于同时段基线',deviationW:deviation}}

三个条件必须同时满足才算异常,缺一个都会产生误报。

样本量门槛来自实际体验。新设备接入后的头两天,基线里只有两三个样本,某个样本恰好是待机状态,均值被拉得很低,之后设备正常工作就被一直判定为"高于基线 400%"。加了这个门槛,头两天安静地学习,第三天开始才给出提示。

绝对偏离门槛解决的是小功率设备的问题。路由器平时 8 W,某天因为固件升级跑到 12 W,相对变化 50%,但图上看不出任何意义。300 W 这个值是根据家里几个主要电器的实际波动定的。

标准差取了下限 1 W。历史样本全都一样的时候标准差会算出 0,除法直接炸掉。

Z_THRESHOLD定在 2.5 而不是常见的 1.96,是有意调松的。1.96 对应 95% 置信,家用场景下一天下来会报出五到八条提示,用户很快就学会无视它们。2.5 大约对应 99%,实测一周只会报出两三条真正值得看的。

分区判定要独立跑一遍

有了区域和设备的功率,就能解释为什么总量下降还会报异常。判定是逐个区域独立做的,不看总量:

exportinterfaceRoomVerdict{roomId:stringabnormal:booleanreason:stringdeviationW:number}exportfunctionjudgeRooms(rooms:RoomLoad[],baselines:Map<string,BaselineSlot>,now:number):RoomVerdict[]{constslotIndex:number=slotOf(now)returnrooms.map((room:RoomLoad)=>{constslot:BaselineSlot|undefined=baselines.get(room.roomId)if(slot===undefined){return{roomId:room.roomId,abnormal:false,reason:'暂无基线',deviationW:0}}constshifted:BaselineSlot={...slot,slotIndex}constverdict:AnomalyVerdict=detectAnomaly(shifted,room.watts)return{roomId:room.roomId,abnormal:verdict.abnormal,reason:verdict.reason,deviationW:verdict.deviationW}})}

一个区域大幅下降、另一个区域大幅上升,两者的偏离在总量里互相抵消,可分区判定各自都能看出来。这正是"总用电下降了却还在提示异常"的成因。

界面上客厅卡片显示"较昨日下降 8%",用的是环比;它的异常判定用的是同时段基线。两个数字不一样是正常的,缺一个都会让用户困惑:只给环比,解释不了为什么降了还报警;只给基线偏离,用户又不知道跟自己印象里的昨天差多少。

目录结构

EnergyHub/ ├─ entry/src/main/ets/ │ ├─ pages/Index.ets # 能源流向与区域负荷卡片 │ ├─ features/ │ │ ├─ PowerModel.ets # 采样、负荷与基线结构 │ │ ├─ BaselineLearner.ets # 168 槽位基线的累积 │ │ └─ AnomalyJudge.ets # 偏离判定与分区归因 │ ├─ entryability/EntryAbility.ets │ └─ adapters/ │ ├─ MeterAdapter.ets # 电表与光伏逆变器读数 │ └─ BatteryAdapter.ets # 储能状态 ├─ entry/src/main/resources/ └─ build-profile.json5

BaselineLearner每天凌晨用前一天的数据更新一次槽位,白天只读。基线如果在白天滚动更新,异常判定会被自己刚才的判定结果带偏——判定为异常的高功率采样如果也进了基线,这条基线会慢慢爬高,之后同样的用电就不报警了。

界面上的"今日节省 ¥8.40"也是估算值。它用当日自用光伏量乘以当地电价得到,在分时电价地区这个数字只能算个大概。真要准确结算,得引入分时电价表和上网电价,那是另一套逻辑,不该混在实时看板里算。

数据只在本机处理,不上传云端,历史采样按天滚动保留最近 90 天。这些设置都放在系统设置页,用户可以单独关掉某个区域的异常提示。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/25 10:34:56

用Vulkan从零实现N-Body模拟:计算着色器与GPU并行优化指南

前阵子我把一套自写的Vulkan N-Body demo重新整理了一遍&#xff0c;第一版跑通时帧数并不高——一万六千颗粒子&#xff0c;在中端显卡上只有三十出头&#xff0c;但这并不妨碍我高兴了好一阵。从创建实例、挑选物理设备、分配显存&#xff0c;到写计算着色器累积引力&#xf…

作者头像 李华
网站建设 2026/10/25 6:38:49

CentOS 8上部署Ceph Octopus:从环境初始化到性能调优实战

在这个全民上云、云原生泛滥的年代&#xff0c;反而有一批服务器被留在机房里&#xff0c;跑着并不算新的系统。我接手过一个类似运维环境&#xff0c;一水的CentOS 8服务器&#xff0c;业务侧明确要求自建分布式存储&#xff0c;给出的选型是Ceph&#xff0c;版本锁定Octopus&…

作者头像 李华
网站建设 2026/10/26 15:11:00

培养孩子心理健康的6大类35项核心能力

1. 引言&#xff1a;重新定义孩子的心理健康在育儿这条路上&#xff0c;我见过太多家长陷入一个误区——认为孩子只要不哭不闹、性格开朗就是心理健康。直到我自己在儿童心理咨询领域深耕十年后才发现&#xff0c;真正的心理健康远比表面现象复杂得多。它更像是一套完整的操作系…

作者头像 李华
网站建设 2026/10/28 7:11:10

工业仿真自动化实战:AI Agent与MCP协议全解析

我接过不少这种需求&#xff1a;“帮我大概看一下这段管路压降合不合理&#xff0c;流量按5万吨/天来算&#xff0c;介质就是水&#xff0c;常温&#xff0c;出口背压别低于3公斤&#xff0c;结果最好直接能放进报告里。” 一句话的事&#xff0c;但真要把这句话变成一场能跑、…

作者头像 李华
网站建设 2026/10/28 9:27:24

多维信号传输:突破带宽效率瓶颈的工程实践指南

1. 项目概述&#xff1a;为什么“多维信号传输”是数字通信的分水岭“数字通信第三章——多维信号传输”这个标题&#xff0c;乍看像教科书里一个平平无奇的章节名&#xff0c;但如果你在通信系统设计、无线链路优化或高速数据接口开发一线干过几年&#xff0c;就会明白——这一…

作者头像 李华
网站建设 2026/10/28 5:35:49

操作系统经典同步问题:从信号量到工程实践的并发控制指南

如果你的工作里写过任何多线程程序&#xff0c;那你大概率遇到过这种情况&#xff1a;数据莫名其妙错乱、程序偶尔卡死、压测一上来日志就乱套。我在某公司做服务端开发的那几年&#xff0c;代码评审里最常见的争议&#xff0c;就是“这个共享变量加锁没有”“这两个锁的顺序对…

作者头像 李华