
鸿蒙能耗监测仪表盘开发指南(基于Hi3516) 原创
鸿蒙能耗监测仪表盘开发指南(基于Hi3516)
一、系统架构设计
基于HarmonyOS的能耗监测系统,通过Hi3516开发板采集用电数据,实现以下功能:
实时监测:采集插座电压、电流、功率等数据
可视化展示:多维度展示能耗数据
跨设备同步:通过分布式能力实现多设备数据共享
异常预警:检测异常用电情况
!https://example.com/harmony-energy-monitor-arch.png
二、核心代码实现
数据采集服务
// EnergyDataService.ets
import driver from ‘@ohos.driver’;
import distributedData from ‘@ohos.distributedData’;
class EnergyDataService {
private static instance: EnergyDataService = null;
private hi3516Driver: driver.Driver | null = null;
private dataManager: distributedData.DataManager;
private listeners: DataListener[] = [];
private constructor() {
this.initDriver();
this.initDataManager();
public static getInstance(): EnergyDataService {
if (!EnergyDataService.instance) {
EnergyDataService.instance = new EnergyDataService();
return EnergyDataService.instance;
private async initDriver(): Promise<void> {
try {
this.hi3516Driver = await driver.createDriver('hi3516');
await this.hi3516Driver.init();
// 启动定时数据采集
setInterval(() => {
this.collectEnergyData();
}, 5000); // 每5秒采集一次
catch (err) {
console.error('初始化驱动失败:', JSON.stringify(err));
}
private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
bundleName: ‘com.example.energymonitor’,
area: distributedData.Area.GLOBAL,
isEncrypted: true
});
this.dataManager.registerDataListener('energy_sync', (data) => {
this.handleSyncData(data);
});
private async collectEnergyData(): Promise<void> {
if (!this.hi3516Driver) return;
try {
// 从Hi3516读取传感器数据
const voltage = await this.hi3516Driver.read('voltage');
const current = await this.hi3516Driver.read('current');
const power = voltage * current;
const energy = power * (5 / 3600); // 5秒的能耗(kWh)
const energyData: EnergyData = {
timestamp: Date.now(),
voltage: parseFloat(voltage.toFixed(2)),
current: parseFloat(current.toFixed(3)),
power: parseFloat(power.toFixed(1)),
energy: parseFloat(energy.toFixed(5)),
deviceId: this.dataManager.getDeviceId()
};
// 通知监听器
this.listeners.forEach(listener => {
listener.onDataUpdate(energyData);
});
// 同步到其他设备
this.syncEnergyData(energyData);
catch (err) {
console.error('采集能耗数据失败:', JSON.stringify(err));
}
private syncEnergyData(data: EnergyData): void {
this.dataManager.syncData(‘energy_sync’, {
type: ‘energy_data’,
data: data,
timestamp: Date.now()
});
private handleSyncData(data: any): void {
if (!data || data.type !== 'energy_data') return;
this.listeners.forEach(listener => {
listener.onDataUpdate(data.data);
});
public addListener(listener: DataListener): void {
if (!this.listeners.includes(listener)) {
this.listeners.push(listener);
}
public removeListener(listener: DataListener): void {
this.listeners = this.listeners.filter(l => l !== listener);
public async release(): Promise<void> {
if (this.hi3516Driver) {
await this.hi3516Driver.release();
this.hi3516Driver = null;
}
interface DataListener {
onDataUpdate(data: EnergyData): void;
interface EnergyData {
timestamp: number;
voltage: number; // 电压(V)
current: number; // 电流(A)
power: number; // 功率(W)
energy: number; // 能耗(kWh)
deviceId: string;
export const energyService = EnergyDataService.getInstance();
仪表盘界面
// DashboardScreen.ets
import { energyService } from ‘./EnergyDataService’;
@Component
export struct DashboardScreen {
@State currentData: EnergyData | null = null;
@State historyData: EnergyData[] = [];
@State connectedDevices: string[] = [];
@State isAlert: boolean = false;
private timer: number = 0;
build() {
Column() {
// 标题栏
Row() {
Text(‘能耗监测仪表盘’)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Button('设备')
.width(80)
.onClick(() => {
this.showDeviceDialog();
})
.padding(10)
.width('100%')
// 报警提示
if (this.isAlert) {
Row() {
Image($r('app.media.ic_alert'))
.width(24)
.height(24)
.margin({ right: 8 })
Text('检测到异常用电!')
.fontSize(16)
.fontColor(Color.Red)
.padding(10)
.width('90%')
.backgroundColor('#FFF0F0')
.borderRadius(8)
.margin({ bottom: 10 })
// 实时数据卡片
if (this.currentData) {
Grid() {
GridItem() {
EnergyCard({
title: '电压',
value: this.currentData.voltage,
unit: 'V',
icon: $r('app.media.ic_voltage')
})
GridItem() {
EnergyCard({
title: '电流',
value: this.currentData.current,
unit: 'A',
icon: $r('app.media.ic_current')
})
GridItem() {
EnergyCard({
title: '功率',
value: this.currentData.power,
unit: 'W',
icon: $r('app.media.ic_power')
})
GridItem() {
EnergyCard({
title: '能耗',
value: this.currentData.energy * 1000, // 转换为Wh
unit: 'Wh',
icon: $r('app.media.ic_energy')
})
}
.columnsTemplate('1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.height(300)
.margin({ bottom: 20 })
// 历史数据图表
EnergyChart({
data: this.historyData,
width: '100%',
height: 200
})
.margin({ bottom: 20 })
// 设备状态
if (this.connectedDevices.length > 0) {
Column() {
Text('已连接设备:')
.fontSize(16)
.margin({ bottom: 8 })
ForEach(this.connectedDevices, (deviceId) => {
Text(设备 ${deviceId})
.fontSize(14)
.margin({ bottom: 4 })
})
.width(‘90%’)
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
.margin({ bottom: 20 })
}
.width('100%')
.height('100%')
.padding(20)
.onAppear(() => {
energyService.addListener({
onDataUpdate: (data) => {
this.updateEnergyData(data);
});
// 每5分钟清理一次历史数据
this.timer = setInterval(() => {
if (this.historyData.length > 100) {
this.historyData = this.historyData.slice(-100);
}, 300000);
})
.onDisappear(() => {
energyService.removeListener({
onDataUpdate: () => {}
});
if (this.timer) {
clearInterval(this.timer);
})
private updateEnergyData(data: EnergyData): void {
this.currentData = data;
this.historyData.push(data);
// 异常检测
this.isAlert = data.power > 2000 || data.current > 10; // 功率>2000W或电流>10A视为异常
// 如果是其他设备的数据,添加到连接设备列表
if (data.deviceId !== energyService.getDeviceId() &&
!this.connectedDevices.includes(data.deviceId)) {
this.connectedDevices.push(data.deviceId);
}
private showDeviceDialog(): void {
const dialog = new AlertDialog({
title: ‘选择设备’,
customComponent: DeviceSelector({
onDeviceSelect: (deviceId) => {
this.connectToDevice(deviceId);
}),
buttons: [
text: ‘取消’,
action: () => {}
]
});
dialog.show();
private connectToDevice(deviceId: string): void {
if (!this.connectedDevices.includes(deviceId)) {
this.connectedDevices.push(deviceId);
prompt.showToast({ message: 已连接设备 ${deviceId} });
}
@Component
struct EnergyCard {
private title: string;
private value: number;
private unit: string;
private icon: Resource;
build() {
Column() {
Row() {
Image(this.icon)
.width(24)
.height(24)
.margin({ right: 8 })
Text(this.title)
.fontSize(16)
.margin({ bottom: 8 })
Row(Align.Center) {
Text(this.value.toFixed(this.unit === 'A' ? 3 : 1))
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ right: 4 })
Text(this.unit)
.fontSize(16)
.fontColor('#666666')
}
.padding(15)
.width('100%')
.backgroundColor(Color.White)
.borderRadius(8)
}
@Component
struct EnergyChart {
private data: EnergyData[];
private width: string | number;
private height: string | number;
build() {
Canvas()
.width(this.width)
.height(this.height)
.onReady((context: CanvasRenderingContext2D) => {
this.drawChart(context);
})
private drawChart(ctx: CanvasRenderingContext2D): void {
if (this.data.length === 0) return;
const width = ctx.width;
const height = ctx.height;
const padding = 20;
const chartWidth = width - padding * 2;
const chartHeight = height - padding * 2;
// 清空画布
ctx.clearRect(0, 0, width, height);
// 绘制坐标轴
ctx.beginPath();
ctx.strokeStyle = '#CCCCCC';
ctx.lineWidth = 1;
// X轴
ctx.moveTo(padding, height - padding);
ctx.lineTo(width - padding, height - padding);
// Y轴
ctx.moveTo(padding, height - padding);
ctx.lineTo(padding, padding);
// Y轴刻度
const maxPower = Math.max(...this.data.map(d => d.power), 1000);
const yStep = chartHeight / 5;
for (let i = 0; i <= 5; i++) {
const y = height - padding - i * yStep;
ctx.moveTo(padding, y);
ctx.lineTo(padding - 5, y);
ctx.textAlign = 'right';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#666666';
ctx.font = '12px sans-serif';
ctx.fillText((maxPower * i / 5).toFixed(0), padding - 10, y);
ctx.stroke();
// 绘制功率曲线
ctx.beginPath();
ctx.strokeStyle = '#4285F4';
ctx.lineWidth = 2;
const xStep = chartWidth / (this.data.length - 1);
const startX = padding;
const startY = height - padding - (this.data[0].power / maxPower) * chartHeight;
ctx.moveTo(startX, startY);
for (let i = 1; i < this.data.length; i++) {
const x = padding + i * xStep;
const y = height - padding - (this.data[i].power / maxPower) * chartHeight;
ctx.lineTo(x, y);
ctx.stroke();
// 绘制数据点
ctx.fillStyle = '#4285F4';
for (let i = 0; i < this.data.length; i += Math.floor(this.data.length / 10)) {
const x = padding + i * xStep;
const y = height - padding - (this.data[i].power / maxPower) * chartHeight;
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2);
ctx.fill();
}
设备管理组件
// DeviceManager.ets
import distributedDeviceManager from ‘@ohos.distributedDeviceManager’;
@Component
export struct DeviceManager {
@State availableDevices: distributedDeviceManager.DeviceInfo[] = [];
private deviceManager: distributedDeviceManager.DeviceManager;
aboutToAppear() {
this.initDeviceManager();
private async initDeviceManager(): Promise<void> {
try {
this.deviceManager = await distributedDeviceManager.createDeviceManager('com.example.energymonitor');
// 监听设备状态变化
this.deviceManager.on('deviceStateChange', (data) => {
this.handleDeviceStateChange(data);
});
// 初始发现设备
this.discoverDevices();
catch (err) {
console.error('初始化设备管理器失败:', JSON.stringify(err));
}
private async discoverDevices(): Promise<void> {
try {
const devices = await this.deviceManager.getAvailableDeviceList();
this.availableDevices = devices;
catch (err) {
console.error('发现设备失败:', JSON.stringify(err));
}
private handleDeviceStateChange(data: any): void {
switch (data.action) {
case ‘add’:
this.availableDevices.push(data.device);
break;
case ‘remove’:
this.availableDevices = this.availableDevices.filter(d => d.deviceId !== data.device.deviceId);
break;
case ‘update’:
const index = this.availableDevices.findIndex(d => d.deviceId === data.device.deviceId);
if (index >= 0) {
this.availableDevices[index] = data.device;
break;
}
build() {
Column() {
Text(‘可用设备’)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
if (this.availableDevices.length === 0) {
Text('未发现可用设备')
.fontSize(16)
.margin({ top: 20 })
else {
ForEach(this.availableDevices, (device) => {
Row() {
Image(this.getDeviceIcon(device.deviceType))
.width(40)
.height(40)
.margin({ right: 10 })
Column() {
Text(device.deviceName)
.fontSize(16)
Text(this.getDeviceTypeName(device.deviceType))
.fontSize(12)
.fontColor('#666666')
.layoutWeight(1)
Button('连接')
.width(80)
.onClick(() => {
this.connectToDevice(device.deviceId);
})
.padding(10)
.width('100%')
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ bottom: 10 })
})
Button(‘刷新设备列表’)
.width('80%')
.height(40)
.margin({ top: 20 })
.onClick(() => {
this.discoverDevices();
})
.width(‘100%’)
.height('100%')
.padding(20)
private getDeviceIcon(deviceType: string): Resource {
switch (deviceType) {
case 'smartPlug': return $r('app.media.ic_smartplug');
case 'energyMonitor': return $r('app.media.ic_energymonitor');
default: return $r('app.media.ic_device');
}
private getDeviceTypeName(deviceType: string): string {
switch (deviceType) {
case ‘smartPlug’: return ‘智能插座’;
case ‘energyMonitor’: return ‘能耗监测仪’;
default: return ‘其他设备’;
}
private connectToDevice(deviceId: string): void {
// 实际实现应使用设备管理服务
prompt.showToast({ message: 已连接设备 ${deviceId} });
router.back();
}
三、项目配置与权限
权限配置
// module.json5
“module”: {
"requestPermissions": [
“name”: “ohos.permission.ACCESS_DRIVER”,
"reason": "访问Hi3516驱动"
},
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,
"reason": "同步能耗数据"
},
“name”: “ohos.permission.ACCESS_DISTRIBUTED_DEVICE_MANAGER”,
"reason": "发现和连接其他设备"
},
“name”: “ohos.permission.READ_MEDIA”,
"reason": "读取媒体文件"
},
“name”: “ohos.permission.WRITE_MEDIA”,
"reason": "保存报表"
],
"abilities": [
“name”: “MainAbility”,
"type": "page",
"visible": true
},
“name”: “DeviceAbility”,
"type": "page",
"visible": true
]
}
资源文件
// resources/base/media/media.json
“media”: [
“name”: “ic_voltage”,
"type": "svg",
"src": "media/voltage.svg"
},
“name”: “ic_current”,
"type": "svg",
"src": "media/current.svg"
},
“name”: “ic_power”,
"type": "svg",
"src": "media/power.svg"
},
“name”: “ic_energy”,
"type": "svg",
"src": "media/energy.svg"
},
“name”: “ic_alert”,
"type": "svg",
"src": "media/alert.svg"
},
“name”: “ic_smartplug”,
"type": "svg",
"src": "media/smartplug.svg"
},
“name”: “ic_energymonitor”,
"type": "svg",
"src": "media/energymonitor.svg"
]
四、总结与扩展
本能耗监测仪表盘实现了以下核心功能:
实时采集:通过Hi3516精确采集用电数据
可视化展示:多维度展示电压、电流、功率等数据
跨设备同步:多设备实时共享能耗数据
异常预警:检测异常用电情况
扩展方向:
能耗分析:提供能耗趋势分析和节能建议
远程控制:支持远程控制智能插座开关
报表导出:生成日/周/月能耗报表
场景联动:与其他智能设备联动控制
云存储:安全存储历史能耗数据
通过HarmonyOS的分布式能力和Hi3516的硬件能力,我们构建了一个高效、可靠的能耗监测系统,帮助用户更好地管理和优化能源使用。
