恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Web能源管理系统实战:从电表接入到城市热力图全流程
首页
资讯中心
/
Web能源管理系统实战:从电表接入到城市热力图全流程
Web能源管理系统实战:从电表接入到城市热力图全流程
发布时间:2026/10/17 8:14:44
简介这是一套面向城市能源管理场景的Web系统源码适合计算机、物联网及能源相关专业学生做课程设计或毕业设计也可供开发者参考前后端整合与可视化实现。系统围绕能源监测、响应预警与设备管理展开涵盖登录验证、实时能耗仪表盘、异常预警以及设备入库、检修与查询等模块并借助Bootstrap实现响应式布局兼顾桌面与移动端访问。资源包共170个文件约3MB包含18个html页面、18个js脚本、13个css样式及14个less、14个scss预编译文件另有64张png与14张jpg界面截图、字体图标文件和一个db数据库文件结构完整、便于二次开发。目前已有899人学习下载。读者可据此获得一套可直接运行的能源管理系统原型理解监测数据采集、预警触发与设备台账管理的实现思路并参考其目录组织与前端组件用法快速搭建自己的管理后台。1. 从一块电表到一张城市热力图这套 Web 能源管理系统到底能干什么去年帮某园区做能耗盘点物业经理甩给我一个 Excel里面是 37 栋楼、两百多块电表的手抄数据时间戳对不齐、单位混着 kW 和 kWh光清洗就花了两天。那次之后我就一直在找一套能直接跑起来的 Web 能源管理系统——不是那种演示用的静态大屏而是真能接表、真能算分项、真能出趋势的完整源码。这套基于 Web 的城市能源管理系统核心就是干这件事把分散的电、水、气计量点统一接入做实时监测、分项统计和趋势分析最后落到浏览器里一张可交互的看板上。它适合三类人做智慧园区/楼宇自控的集成商、需要给甲方交付能耗平台的开发者、以及想拿一套完整前后端练手的技术人。技术栈是典型的前后端分离后端管数据采集与聚合前端管可视化中间靠接口打通下面我按实际拆包的顺序讲。2. 系统架构与数据流先搞清楚数据从哪来到哪去2.1 三层结构采集层、服务层、展示层这套系统的骨架是三层。采集层负责和现场设备打交道常见做法是通过 Modbus TCP 或 MQTT 把电表、水表的数据拉上来落到时序库或者关系库里服务层是后端应用做数据清洗、分项聚合、告警判断对外暴露 REST 接口展示层就是浏览器里的看板用图表库把数据画出来。三层之间是松耦合的采集层挂了不影响看板读历史数据这点在真实项目里很关键——现场网络抖动是常态不能让整条链路一起崩。我一般会把采集频率和展示频率分开设计。采集可以 15 秒一次保证原始粒度展示按分钟或小时聚合减少前端压力。这个分离如果一开始不做后期数据量上来会非常难受查询慢到你以为数据库坏了。2.2 数据表设计计量点、读数、分项三张核心表数据模型不用搞太复杂抓住三张表基本够用。计量点表存设备元信息读数表存时序数据分项表存能耗分类映射。下面是我根据这套系统整理的核心建表语句字段名做了通用化处理-- 计量点表每块表/每个回路一条记录 CREATE TABLE meter_point ( id BIGINT PRIMARY KEY AUTO_INCREMENT, point_code VARCHAR(64) NOT NULL UNIQUE COMMENT 计量点编码现场唯一, point_name VARCHAR(128) NOT NULL COMMENT 点位名称如1号楼照明, energy_type TINYINT NOT NULL COMMENT 1电 2水 3气, parent_id BIGINT DEFAULT 0 COMMENT 所属分区0为根, collect_proto VARCHAR(32) DEFAULT modbus COMMENT 采集协议, status TINYINT DEFAULT 1 COMMENT 1启用 0停用 ); -- 读数表时序数据量大必须建联合索引 CREATE TABLE meter_reading ( id BIGINT PRIMARY KEY AUTO_INCREMENT, point_code VARCHAR(64) NOT NULL, read_time DATETIME NOT NULL COMMENT 采集时间, value DECIMAL(12,3) NOT NULL COMMENT 读数电为kWh, quality TINYINT DEFAULT 1 COMMENT 1正常 0异常, INDEX idx_point_time (point_code, read_time) ); -- 分项映射表把计量点归到照明/空调/动力等分项 CREATE TABLE energy_category ( id BIGINT PRIMARY KEY AUTO_INCREMENT, point_code VARCHAR(64) NOT NULL, category VARCHAR(32) NOT NULL COMMENT 照明/空调/动力/特殊, ratio DECIMAL(5,2) DEFAULT 100.00 COMMENT 分摊比例% );逻辑说明meter_reading的联合索引idx_point_time是必须的能耗查询几乎都是「某点位某时间段」没有这个索引几十万行就开始明显卡顿。quality字段别省现场采集经常出现跳变和负值标记异常比直接丢弃更利于排查。energy_category里的ratio是为分项分摊准备的比如一个总表下面挂多个子项按比例拆分能耗这在没有独立子表的老楼里特别常见。参数上value用DECIMAL而不是FLOAT因为能耗是要对账的浮点误差累积起来会让月度报表对不上这个坑我踩过。read_time用DATETIME而非时间戳方便直接写 SQL 做按天按小时分组。2.3 后端接口分层聚合逻辑放服务层别塞进 SQL后端我习惯分三层Controller 收请求、Service 做业务聚合、Mapper 只管取数。能耗统计最容易犯的错是把所有分组、环比、同比全写进一条大 SQL后期改一个口径就要动 SQL牵一发动全身。正确做法是 Mapper 只按点位和时间范围取原始读数Service 里做分项汇总和周期对比。# 服务层聚合示例按分项统计某时间段能耗 def stat_by_category(point_codes, start_time, end_time): # 1. 取原始读数Mapper只做最简单的范围查询 readings reading_mapper.select_range(point_codes, start_time, end_time) # 2. 取分项映射缓存起来避免每次查库 category_map category_cache.get_map(point_codes) result {} for r in readings: cat category_map.get(r.point_code, 未分类) # 3. 按分项累加注意单位统一 result[cat] result.get(cat, 0) float(r.value) return result逻辑说明把聚合放在 Python 层好处是口径调整只改代码不改表结构测试也好写。category_cache用本地缓存或 Redis 都行分项映射变动频率极低没必要每次查库。单位统一这一步别偷懒电表有的返回 kWh 有的返回 MWh混在一起算出来的数能差一千倍这种翻车现场我见过不止一次。3. 前端看板与实时刷新把数据画成人能看懂的东西3.1 图表选型趋势用折线分项用堆叠柱占比用环形看板上最常出现的三类图能耗趋势、分项对比、占比分布。趋势用折线图X 轴时间、Y 轴能耗多条线区分不同点位分项对比用堆叠柱状图一眼看出哪个分项占大头占比用环形图适合给领导看。图表库选 ECharts 或 Chart.js 都行ECharts 对中文和复杂配置更友好Chart.js 更轻。这套系统前端用的是 ECharts配置项多但可控性强。一个实际经验趋势图的 X 轴时间间隔要按查询范围动态调整。查一天按小时查一月按天查一年按月。如果固定按小时查一年会返回八千多个点浏览器直接卡死。这个逻辑放在前端做还是后端做都行我一般放后端接口直接返回聚合好的粒度前端只管画。3.2 实时刷新轮询够用别一上来就上 WebSocket很多人一听「实时监测」就想上 WebSocket觉得轮询 low。但真实场景里能耗数据的变化频率是分钟级甚至小时级15 秒轮询一次完全够用实现简单、断线重连逻辑现成、后端压力可控。WebSocket 适合秒级变化的数据用在能耗上属于杀鸡用牛刀还容易因为心跳和重连写出玄学 bug。// 前端轮询刷新示例带页面隐藏暂停 let timer null; const POLL_INTERVAL 15000; // 15秒 function startPolling() { stopPolling(); // 防止重复启动 timer setInterval(async () { // 页面切到后台时跳过请求省资源 if (document.hidden) return; try { const data await fetch(/api/energy/realtime).then(r r.json()); updateDashboard(data); // 更新图表 } catch (e) { console.warn(刷新失败下轮重试, e); } }, POLL_INTERVAL); } function stopPolling() { if (timer) { clearInterval(timer); timer null; } } // 页面可见性变化时恢复刷新 document.addEventListener(visibilitychange, () { if (!document.hidden) startPolling(); });逻辑说明document.hidden判断是省资源的关键用户切走标签页时没必要继续请求。stopPolling在启动前先调一次避免多次绑定导致定时器叠加这个 bug 表现为「刷新越来越快」本质是多个 timer 同时在跑。失败不弹窗只打日志能耗看板不是支付系统偶发失败下轮补上就行弹窗反而打扰。参数上POLL_INTERVAL设 15000 是折中值。设 5000 后端压力大设 60000 用户觉得「怎么不动」。如果点位特别多可以按看板区域分批轮询别一次全量拉。3.3 大屏适配rem 加媒体查询别写死像素看板经常要投到大屏上写死 px 的布局一放大就散架。常见做法是用 rem 做基准缩放配合媒体查询处理断点。根字号根据屏幕宽度动态设置图表容器用百分比宽度ECharts 的resize方法在窗口变化时调用。// 动态根字号基准1920宽 function setRootFontSize() { const w document.documentElement.clientWidth; const base 1920; // 限制缩放范围避免超宽屏字太大 const scale Math.min(Math.max(w / base, 0.7), 1.5); document.documentElement.style.fontSize (16 * scale) px; } window.addEventListener(resize, () { setRootFontSize(); // 通知所有图表重绘 window.dispatchEvent(new Event(chart-resize)); }); setRootFontSize();逻辑说明Math.min(Math.max(...))把缩放限制在 0.7 到 1.5 之间防止在超宽屏上字大到溢出、在小屏上小到看不清。图表重绘用自定义事件解耦各图表组件自己监听chart-resize调resize()不用在窗口事件里挨个引用。这套适配方案不复杂但能省掉大量「在我屏幕上好好的到现场就乱了」的返工。4. 避坑与排查这几个问题我替你踩过了4.1 读数跳变导致能耗为负现象月度报表里某个点位能耗是负数或者某天突然飙高十倍。原因通常是采集时读到了异常值比如电表通信中断返回 0 或 65535或者抄表程序把上一轮的值重复写入。解决在入库前做合理性校验相邻两次读数差值超过阈值就标记quality0统计时排除异常点。阈值按点位额定功率估算别用统一值。4.2 分项之和大于总表现象照明加空调加动力比总表读数还大。原因是分项映射里同一个点位被归到了多个分项或者总表本身也被算进了某个分项。解决建映射时保证一个点位只属于一个分项总表单独标记不参与分项累加。上线前跑一次「分项和 vs 总表」的对账脚本差值超过 5% 就拦下来查。4.3 时间戳时区不统一现象看板上白天的能耗跑到凌晨去了或者跨天统计对不上。原因是采集端用本地时间、数据库存 UTC、前端又按浏览器时区渲染三处不一致。解决全链路统一存 UTC只在展示层转本地时区。数据库连接串里明确时区参数别依赖默认值不同环境默认值可能不一样。4.4 大数据量查询拖垮数据库现象查一年数据时接口超时数据库 CPU 打满。原因是直接对原始读数表做范围扫描没走聚合。解决建按小时或按天的汇总表定时任务预聚合查询走汇总表。原始表只保留最近三个月更早的归档。这个改造越早做越好等数据上亿行再补迁移成本高得让人想删库。4.5 前端图表内存泄漏现象看板开久了浏览器越来越卡最后崩掉。原因是每次刷新都新建图表实例旧的没销毁。解决图表实例只创建一次刷新时用setOption更新数据页面销毁时调dispose。这个坑在单页应用里尤其常见路由切来切去实例越积越多。5. 进阶玩法把能耗数据用出花来的三个技巧第一个技巧是负荷预测的轻量实现。不用上复杂的机器学习用「同类型日」的历史均值就能做出可用的短期预测取过去四周同一星期几同一时段的能耗均值作为明天的预测值。这个方法在园区场景里准确度意外地高因为用能规律性强。实现上就是一条按WEEKDAY和HOUR分组的 SQL配合缓存成本极低。-- 同时段历史均值预测过去4周同一星期几同一小时 SELECT AVG(value) AS predict_value FROM meter_reading WHERE point_code ? AND HOUR(read_time) ? AND WEEKDAY(read_time) ? AND read_time DATE_SUB(NOW(), INTERVAL 28 DAY) AND quality 1;逻辑说明WEEKDAY返回 0 到 6HOUR返回 0 到 23两个条件锁定「星期几的几点」。quality 1排除异常点否则一个跳变值能把预测拉偏。这个查询走idx_point_time索引28 天数据量可控。预测值只做参考展示别直接拿去控制设备误差还是有的。第二个技巧是告警的静默与升级。能耗告警最怕狼来了阈值设低了天天响设高了真出事不响。我的做法是分两级一级告警只记录不推送连续 N 个周期都超阈值才升级为二级推送。这样偶发波动被过滤持续异常才打扰人。N 一般取 3对应 45 分钟按 15 秒采集、分钟聚合算。第三个技巧是数据导出与对账。甲方永远会要 Excel与其每次手动导不如做个异步导出请求后生成文件放临时目录返回下载链接前端轮询状态。导出内容除了原始数据附上分项汇总和与总表的对账差值让甲方自己就能核对。这个功能看着不起眼但能省掉大量「你这个数不对」的扯皮。从那以后我每次交付能耗系统上线前都强制走一遍「异常值校验、分项对账、时区核对」这三步宁可多花半天也不想在验收会上被问得下不来台。希望帮到你。本文还有配套的精品资源点击获取