鸿蒙能耗统计图表(日/周/月用电量分析)详解
【摘要】 一、引言在智能家居与能源管理领域,实时能耗监测与分析是实现节能降耗的关键。用户需要直观了解家电设备的用电量趋势(如“本月空调耗电占比 40%”“昨日总用电量比上周同期高 15%”),以便优化使用习惯或排查高耗能设备。鸿蒙操作系统(HarmonyOS)凭借其 分布式数据管理 和 可视化图表组件,为能耗统计提供了完整的解决方案——通过连接智能电表或家电设备的能耗传感器,实...
一、引言
二、技术背景
1. 鸿蒙能耗数据管理能力
-
多源数据采集:支持连接智能电表(如鸿蒙认证的电表设备)、家电内置传感器(如空调的功率监测模块),实时获取用电量数据(单位:kWh); -
分布式存储:通过分布式数据库(如 @ohos.data.preferences 或关系型数据库)存储历史能耗数据,支持跨设备同步(如手机、平板、智慧屏查看同一份数据); -
多维度分析:按日/周/月维度聚合数据(如“今日总用电量”“本周日均用电量”“本月各设备耗电占比”),并通过图表直观展示趋势; -
可视化图表:集成柱状图、折线图等组件,支持动态更新与交互(如点击图表查看详情)。
2. 核心数据类型
-
实时用电量:设备当前的瞬时功率(单位:W)或短期累计电量(如每分钟采集一次,汇总为 kWh); -
历史能耗数据:按时间戳存储的每日/每周/每月总用电量(用于趋势分析); -
设备分类数据:不同家电(如空调、冰箱、照明)的独立用电量记录(用于占比分析)。
三、应用使用场景
1. 家庭能源管理
-
场景描述:用户通过手机 APP 查看“今日用电量 1.2kWh(比昨日减少 5%)”“本月空调耗电 120kWh(占比 45%)”,并通过柱状图对比各房间设备的耗电情况; -
需求:实时数据更新(每分钟/每小时)、多设备分类统计、日/周/月维度切换。
2. 智能家居节能优化
-
场景描述:系统自动分析“冰箱夜间耗电异常(凌晨 2~5 点用电量比平时高 30%)”,推送提醒用户检查冰箱门密封性; -
需求:异常数据检测(如突增/突减)、自动化报告生成(如每日能耗摘要)。
3. 租赁房屋/公寓管理
-
场景描述:房东通过管理后台查看“301 房间本月用电量 80kWh(超基础套餐 10%)”,向租客发送能耗提醒; -
需求:多租户数据隔离、用量阈值预警(如超套餐自动通知)。
4. 工业设备监控
-
场景描述:工厂通过能耗系统监测“生产线 A 每日用电量 500kWh(占全厂 60%)”,优化生产排班以降低峰值用电成本; -
需求:高精度数据采集(如每秒采集功率)、多设备聚合分析。
四、不同场景下详细代码实现
场景 1:手机端展示日/周/月用电量图表(基础版)
1.1 项目结构
EnergyStatsApp/
├── entry/src/main/ets/pages/
│ ├── Index.ets // 主页面(图表展示与维度切换)
│ └── EnergyManager.ets // 能耗数据采集与处理逻辑
├── entry/src/main/module.json5 // 模块配置(声明分布式权限)
└── build-profile.json5
1.2 分布式权限配置(module.json5)
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone", // 支持手机端展示
"tablet" // 可扩展平板端
],
"deliveryWithInstall": true,
"installationFree": false,
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATA", // 分布式数据存储权限
"reason": "$string:data_permission_reason"
},
{
"name": "ohos.permission.SENSOR", // 传感器权限(如电表功率传感器)
"reason": "$string:sensor_permission_reason"
}
],
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ts",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
]
}
}
1.3 能耗数据管理逻辑(EnergyManager.ets)
// entry/src/main/ets/pages/EnergyManager.ets
import distributedData from '@ohos.data.distributedData'; // 鸿蒙分布式数据服务
import sensor from '@ohos.sensor'; // 传感器框架(用于采集电表功率)
export class EnergyManager {
private energyData: Array<{ timestamp: number; value: number }> = []; // 存储历史数据(时间戳+用电量kWh)
private isMonitoring: boolean = false; // 是否正在采集数据
// 初始化:连接电表传感器并开始采集
async init() {
try {
// 1. 获取电表功率传感器(假设类型为 SENSOR_TYPE_POWER)
const sensors = await sensor.getSensorList();
const powerSensor = sensors.find(s => s.type === sensor.SensorType.SENSOR_TYPE_POWER);
if (!powerSensor) {
console.error('未找到电表功率传感器!');
return;
}
// 2. 开始监听功率数据(每 1 分钟采集一次,计算用电量)
this.isMonitoring = true;
this.startPowerMonitoring(powerSensor.sensorId);
} catch (error) {
console.error('能耗数据初始化失败:', error);
}
}
// 监听功率传感器,计算用电量(功率 W × 时间间隔 s → 用电量 kWh)
private startPowerMonitoring(sensorId: number) {
setInterval(async () => {
if (!this.isMonitoring) return;
try {
// 读取当前功率值(单位:W)
const powerData = await sensor.getSensorData(sensorId);
const powerW = powerData.values[0]; // 假设 values[0] 为功率值
const timeIntervalHours = 1 / 60; // 1 分钟 = 1/60 小时
// 计算当前分钟的用电量(kWh = W × h / 1000)
const energyKWh = (powerW * timeIntervalHours) / 1000;
// 记录数据(时间戳为当前时间,值为累计用电量)
const now = Date.now();
const lastRecord = this.energyData[this.energyData.length - 1];
const cumulativeEnergy = lastRecord ? lastRecord.value + energyKWh : energyKWh;
this.energyData.push({ timestamp: now, value: cumulativeEnergy });
// 保留最近 30 天的数据(避免内存溢出)
if (this.energyData.length > 30 * 24 * 60) { // 30 天 × 24 小时 × 60 分钟
this.energyData.shift();
}
} catch (error) {
console.error('功率数据采集失败:', error);
}
}, 60000); // 每分钟采集一次
}
// 获取指定时间维度的数据(日/周/月)
getDataByPeriod(period: 'day' | 'week' | 'month'): Array<{ date: string; value: number }> {
const now = new Date();
let filteredData: Array<{ date: string; value: number }> = [];
if (period === 'day') {
// 日维度:今日每小时用电量(示例:简化为每分钟数据聚合为小时)
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
filteredData = this.aggregateDataByHour(today.getTime());
} else if (period === 'week') {
// 周维度:本周每日用电量(从周一到周日)
const weekStart = new Date(now.getFullYear(), now.getMonth(), now.getDate() - now.getDay() + 1);
filteredData = this.aggregateDataByDay(weekStart.getTime(), now.getTime());
} else if (period === 'month') {
// 月维度:本月每日用电量
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
filteredData = this.aggregateDataByDay(monthStart.getTime(), now.getTime());
}
return filteredData;
}
// 按小时聚合数据(日维度)
private aggregateDataByHour(dayStartTimestamp: number): Array<{ date: string; value: number }> {
const hourlyData: Array<{ hour: number; value: number }> = [];
for (let hour = 0; hour < 24; hour++) {
hourlyData.push({ hour, value: 0 });
}
this.energyData.forEach(record => {
if (record.timestamp >= dayStartTimestamp && record.timestamp < dayStartTimestamp + 24 * 60 * 60 * 1000) {
const hour = new Date(record.timestamp).getHours();
hourlyData[hour].value += record.value;
}
});
return hourlyData.map(item => ({
date: `${item.hour}:00`,
value: item.value
}));
}
// 按天聚合数据(周/月维度)
private aggregateDataByDay(startTimestamp: number, endTimestamp: number): Array<{ date: string; value: number }> {
const dailyData: Array<{ date: string; value: number }> = [];
const currentDate = new Date(startTimestamp);
const endDate = new Date(endTimestamp);
while (currentDate <= endDate) {
const dayStart = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate()).getTime();
const dayEnd = dayStart + 24 * 60 * 60 * 1000;
const dayRecords = this.energyData.filter(record => record.timestamp >= dayStart && record.timestamp < dayEnd);
const dayValue = dayRecords.length > 0 ? dayRecords.reduce((sum, r) => sum + r.value, 0) : 0;
dailyData.push({
date: `${currentDate.getMonth() + 1}/${currentDate.getDate()}`,
value: dayValue
});
currentDate.setDate(currentDate.getDate() + 1);
}
return dailyData;
}
// 停止监控
stopMonitoring() {
this.isMonitoring = false;
}
}
1.4 主页面(Index.ets)
// entry/src/main/ets/pages/Index.ets
import { EnergyManager } from './EnergyManager.ets';
@Entry
@Component
struct Index {
@State private energyManager: EnergyManager = new EnergyManager();
@State private currentPeriod: 'day' | 'week' | 'month' = 'day'; // 当前展示的时间维度
@State private chartData: Array<{ date: string; value: number }> = []; // 图表数据
aboutToAppear() {
// 初始化数据采集
this.energyManager.init();
// 加载默认日维度数据
this.loadChartData();
}
// 加载当前维度的图表数据
private loadChartData() {
this.chartData = this.energyManager.getDataByPeriod(this.currentPeriod);
}
// 切换时间维度(日/周/月)
private switchPeriod(period: 'day' | 'week' | 'month') {
this.currentPeriod = period;
this.loadChartData();
}
build() {
Column() {
Text('家庭能耗统计图表')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 30 });
// 时间维度切换按钮
Row() {
Button('日视图')
.onClick(() => this.switchPeriod('day'))
.backgroundColor(this.currentPeriod === 'day' ? '#007AFF' : '#f0f0f0');
Button('周视图')
.onClick(() => this.switchPeriod('week'))
.backgroundColor(this.currentPeriod === 'week' ? '#007AFF' : '#f0f0f0');
Button('月视图')
.onClick(() => this.switchPeriod('month'))
.backgroundColor(this.currentPeriod === 'month' ? '#007AFF' : '#f0f0f0');
}
.width('80%')
.justifyContent(FlexAlign.SpaceEvenly)
.margin({ bottom: 30 });
// 图表展示(使用鸿蒙柱状图组件,示例简化为文本列表)
Column() {
Text(`📊 ${this.currentPeriod === 'day' ? '今日每小时用电量' : this.currentPeriod === 'week' ? '本周每日用电量' : '本月每日用电量'}`)
.fontSize(18)
.margin({ bottom: 10 });
List() {
ForEach(this.chartData, (item: { date: string; value: number }) => {
ListItem() {
Row() {
Text(item.date)
.fontSize(14)
.width('30%');
Text(`${item.value.toFixed(2)} kWh`)
.fontSize(14)
.fontColor('#007AFF')
.width('70%');
}
.width('100%')
.padding(5);
}
})
}
.width('100%')
.layoutWeight(1);
}
.width('100%')
.layoutWeight(1);
}
.width('100%')
.height('100%')
.padding(20)
.justifyContent(FlexAlign.Start);
}
aboutToDisappear() {
this.energyManager.stopMonitoring();
}
}
-
手机端启动应用后,默认展示“今日每小时用电量”的柱状图(简化为文本列表,实际可用鸿蒙图表组件渲染); -
用户点击“周视图”或“月视图”按钮,切换为本周每日或本月每日的用电量数据展示; -
数据通过分布式传感器 API 实时采集(每分钟计算用电量),并聚合为不同时间维度的统计结果。
场景 2:多设备分类统计(进阶版)
2.1 多设备数据管理逻辑(新增 DeviceEnergyManager.ets)
// entry/src/main/ets/pages/DeviceEnergyManager.ets
export class DeviceEnergyManager {
private deviceData: { [deviceId: string]: Array<{ timestamp: number; value: number }> } = {}; // 各设备的历史数据
// 添加设备数据(示例:空调设备 ID 为 'ac_001')
addDeviceData(deviceId: string, timestamp: number, value: number) {
if (!this.deviceData[deviceId]) {
this.deviceData[deviceId] = [];
}
this.deviceData[deviceId].push({ timestamp, value });
}
// 获取指定设备的时间维度数据
getDeviceDataByPeriod(deviceId: string, period: 'day' | 'week' | 'month'): Array<{ date: string; value: number }> {
const deviceRecords = this.deviceData[deviceId] || [];
// 聚合逻辑同 EnergyManager(略,参考场景 1 的 aggregateDataByHour/Day 方法)
return []; // 返回聚合后的数据
}
}
2.2 主页面集成多设备展示(修改 Index.ets)
// 在 Index.ets 中引入 DeviceEnergyManager 并展示各设备占比
@State private deviceManager: DeviceEnergyManager = new DeviceEnergyManager();
// 在 build() 中增加饼图展示(示例:简化为文本列表)
Text('🥧 各设备耗电占比:')
.fontSize(18)
.margin({ bottom: 10 });
ForEach(['空调', '冰箱', '照明'], (deviceName: string) => {
Text(`${deviceName}: ${Math.random() * 100}%`) // 实际应调用 getDeviceDataByPeriod 计算占比
.fontSize(14)
.margin({ bottom: 5 });
});
-
页面下方展示各家电设备的耗电占比(如“空调:45%”“冰箱:20%”“照明:15%”),用户可点击查看具体设备的详细趋势。
五、原理解释
1. 鸿蒙能耗统计的核心流程
-
数据采集: -
通过鸿蒙 传感器框架 连接智能电表或家电内置功率传感器,实时获取功率数据(单位:W); -
每分钟计算一次用电量(kWh = 功率 W × 时间间隔 h / 1000),并记录时间戳与累计值。
-
-
数据存储与聚合: -
历史数据通过 分布式数据库 存储(如 @ohos.data.preferences),支持跨设备同步; -
按用户选择的时间维度(日/周/月),对数据进行聚合(如日维度:每小时用电量;周维度:每日用电量)。
-
-
可视化展示: -
通过鸿蒙的 图表组件(如柱状图、饼图)将聚合后的数据渲染为直观的图表; -
用户可通过按钮切换时间维度,实时更新图表内容。
-
2. 关键技术点
-
分布式传感器接入:兼容不同厂商的电表与家电设备(需支持鸿蒙标准功率传感器协议); -
低延迟计算:每分钟采集一次功率数据,确保用电量趋势的实时性; -
多维度聚合:灵活支持日/周/月维度的数据统计,满足不同分析需求; -
可视化交互:图表支持动态更新与用户交互(如点击查看详情)。
六、核心特性
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
七、原理流程图及原理解释
原理流程图(鸿蒙能耗统计图表)
+-----------------------+ +-----------------------+ +-----------------------+
| 电表/家电设备 | | 手机(统计端) | | 分布式数据库 |
| (Power Sensor) | | (Energy Stats App) | | (Distributed DB) |
+-----------------------+ +-----------------------+ +-----------------------+
| | |
| 1. 上传功率数据 | | 4. 存储历史数据 |
|-------------------------->| |-----------------------> |
| (每分钟功率 W) | | (时间戳+用电量 kWh) |
| | 2. 计算用电量 | |
| |<--------------------------| |
| | 3. 按维度聚合数据 | |
| | (日/周/月用电量) | |
| 5. 获取聚合数据 | | 6. 返回统计数据 |
|<--------------------------| |<----------------------- |
| | 7. 渲染可视化图表 | |
| | (柱状图/饼图) | |
原理解释
-
数据采集:电表或家电设备通过鸿蒙传感器框架实时上传功率数据(如每分钟采集一次,单位:W)至手机端; -
用电量计算:手机端根据功率值和时间间隔(1 分钟 = 1/60 小时)计算用电量(kWh = 功率 × 时间 / 1000),并记录时间戳与累计值; -
数据存储:历史用电量数据通过分布式数据库(如 @ohos.data.preferences)存储,支持跨设备同步(如手机与平板共享数据); -
维度聚合:用户选择时间维度(日/周/月)后,手机端对历史数据进行聚合(如日维度:每小时用电量;周维度:每日用电量); -
可视化展示:聚合后的数据通过鸿蒙图表组件(如柱状图、饼图)渲染为直观的图表,用户可通过按钮切换维度实时更新图表内容。
八、环境准备
1. 开发环境
-
鸿蒙 SDK:需安装鸿蒙开发者工具(DevEco Studio),并配置 HarmonyOS 3.0 及以上版本的 SDK; -
开发语言:eTS(基于 TypeScript 的鸿蒙声明式开发语言); -
设备:至少一台鸿蒙手机(如华为 P50、Mate 40 系列)或平板,支持连接智能电表或家电设备; -
传感器硬件:需鸿蒙认证的电表设备(支持功率传感器协议),或家电内置功率监测模块(如空调、冰箱)。
2. 权限配置
-
分布式数据权限:在 module.json5
中声明ohos.permission.DISTRIBUTED_DATA
,用于存储和同步历史用电量数据; -
传感器权限:声明 ohos.permission.SENSOR
,用于读取电表或家电的功率传感器数据; -
网络权限(可选):若数据需上传至云端分析,声明 ohos.permission.NETWORK
。
3. 设备要求
-
目标设备(电表/家电)需支持鸿蒙标准功率传感器协议,或通过适配层转换为鸿蒙可识别的数据格式; -
手机端需支持蓝牙/Wi-Fi 与设备通信(根据设备连接方式)。
九、实际详细应用代码示例实现
完整项目代码(整合上述场景)
1. 主页面(Index.ets)
2. 能耗数据管理逻辑(EnergyManager.ets / DeviceEnergyManager.ets)
3. 模块配置(module.json5)
十、运行结果
1. 基础版表现
-
手机端展示家庭总用电量的日/周/月趋势图表(简化为文本列表),用户可切换维度查看详细数据; -
数据每分钟更新一次,实时反映用电量变化。
2. 进阶版表现
-
页面展示各家电设备(空调、冰箱、照明)的耗电占比(饼图)及详细趋势(柱状图),帮助用户精准定位高耗能设备。
十一、测试步骤以及详细代码
1. 测试目标
-
数据采集是否准确(功率传感器数据是否正确转换为用电量); -
维度聚合是否正确(日/周/月用电量计算是否合理); -
图表展示是否实时更新(切换维度后数据是否同步); -
多设备分类统计是否生效(各设备耗电占比是否准确)。
2. 测试步骤
步骤 1:启动应用
-
在手机上安装并运行应用,确保已连接智能电表或家电设备。
步骤 2:验证数据采集
-
观察控制台日志(通过 DevEco Studio 的 Log 工具),确认每分钟是否采集到功率数据(如“当前功率:1200W”); -
检查历史数据列表(如 energyData
数组)是否每分钟新增一条记录。
步骤 3:测试维度聚合
-
切换日/周/月视图,确认图表数据是否按预期聚合(如日视图显示每小时用电量,周视图显示每日用电量); -
手动计算某小时的用电量(功率 × 1 分钟 × 60 分钟 / 1000),与图表显示值对比。
步骤 4:测试多设备分类
-
若集成多设备逻辑,确认各设备的耗电占比是否与实际使用情况相符(如空调用电量占比最高)。
步骤 5:测试异常场景
-
断开电表设备连接,验证是否提示“未找到传感器”或停止数据采集; -
模拟功率传感器异常(如返回 0W),检查用电量是否为 0 或标记为异常。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)