
鸿蒙空气质量检测仪系统开发指南 原创
鸿蒙空气质量检测仪系统开发指南
一、系统架构设计
基于HarmonyOS的空气质量检测系统采用四层架构:
感知层:多传感器数据采集(PM2.5、CO2、TVOC、温湿度等)
处理层:数据融合与异常值处理
同步层:跨设备数据同步与云端备份
展示层:多终端数据可视化
!https://example.com/harmony-airquality-arch.png
二、核心代码实现
多传感器数据融合
// SensorFusion.ets
import sensor from ‘@ohos.sensor’;
class SensorFusion {
private sensorList = {
pm25: { value: 0, timestamp: 0, accuracy: 0 },
co2: { value: 0, timestamp: 0, accuracy: 0 },
tvoc: { value: 0, timestamp: 0, accuracy: 0 },
temp: { value: 0, timestamp: 0, accuracy: 0 },
humidity: { value: 0, timestamp: 0, accuracy: 0 }
};
private weights = {
pm25: 0.35,
co2: 0.25,
tvoc: 0.2,
temp: 0.1,
humidity: 0.1
};
constructor() {
this.initSensors();
private initSensors(): void {
// PM2.5传感器
sensor.on('pm25', (data) => {
this.sensorList.pm25 = {
value: data.value,
timestamp: data.timestamp,
accuracy: data.accuracy
};
this.calculateAQI();
});
// CO2传感器
sensor.on('co2', (data) => {
this.sensorList.co2 = {
value: data.value,
timestamp: data.timestamp,
accuracy: data.accuracy
};
this.calculateAQI();
});
// 其他传感器初始化...
// 基于加权融合算法计算空气质量指数
private calculateAQI(): number {
const now = Date.now();
const validData = Object.entries(this.sensorList)
.filter(([_, data]) => now - data.timestamp < 60000); // 只使用1分钟内的数据
if (validData.length < 3) return -1; // 数据不足
let totalWeight = 0;
let weightedSum = 0;
validData.forEach(([type, data]) => {
const normalizedValue = this.normalize(data.value, type);
weightedSum += normalizedValue * this.weights[type];
totalWeight += this.weights[type];
});
return weightedSum / totalWeight;
// 传感器数据归一化
private normalize(value: number, type: string): number {
const ranges = {
pm25: [0, 500],
co2: [300, 5000],
tvoc: [0, 1000],
temp: [-10, 50],
humidity: [0, 100]
};
const [min, max] = ranges[type];
return Math.max(0, Math.min(1, (value - min) / (max - min)));
// 获取当前空气质量指数
public getCurrentAQI(): number {
return this.calculateAQI();
// 获取原始传感器数据
public getSensorData(type: string): SensorData | null {
return this.sensorList[type] || null;
}
export const sensorFusion = new SensorFusion();
异常值过滤策略
// DataFilter.ets
class DataFilter {
private historyData: Map<string, Array<number>> = new Map();
private readonly MAX_HISTORY = 10;
// 基于IQR(四分位距)的异常值检测
private isOutlierIQR(value: number, history: Array<number>): boolean {
if (history.length < 5) return false; // 数据不足时不检测
const sorted = [...history].sort((a, b) => a - b);
const q1 = this.quantile(sorted, 0.25);
const q3 = this.quantile(sorted, 0.75);
const iqr = q3 - q1;
const lowerBound = q1 - 1.5 * iqr;
const upperBound = q3 + 1.5 * iqr;
return value < lowerBound || value > upperBound;
// 计算分位数
private quantile(data: Array<number>, q: number): number {
const pos = (data.length - 1) * q;
const base = Math.floor(pos);
const rest = pos - base;
if (data[base + 1] !== undefined) {
return data[base] + rest * (data[base + 1] - data[base]);
else {
return data[base];
}
// 综合异常检测
public filter(sensorType: string, value: number): number | null {
if (!this.historyData.has(sensorType)) {
this.historyData.set(sensorType, []);
const history = this.historyData.get(sensorType);
const isOutlier = this.isOutlierIQR(value, history);
if (!isOutlier) {
history.push(value);
if (history.length > this.MAX_HISTORY) {
history.shift();
return value;
console.warn(检测到异常值: {sensorType}={value});
return null;
// 滑动平均滤波
public movingAverage(sensorType: string, value: number): number {
if (!this.historyData.has(sensorType)) {
this.historyData.set(sensorType, []);
const history = this.historyData.get(sensorType);
history.push(value);
if (history.length > this.MAX_HISTORY) {
history.shift();
const sum = history.reduce((a, b) => a + b, 0);
return sum / history.length;
}
export const dataFilter = new DataFilter();
云端同步智能节流
// CloudSync.ets
import http from ‘@ohos.net.http’;
import connection from ‘@ohos.net.connection’;
import powerManagement from ‘@ohos.powerManagement’;
class CloudSyncManager {
private syncQueue: Array<any> = [];
private isSyncing: boolean = false;
private lastSyncTime: number = 0;
private syncStrategies = {
optimal: { interval: 60000, batchSize: 10 }, // 1分钟,10条/批
normal: { interval: 120000, batchSize: 5 }, // 2分钟,5条/批
powerSave: { interval: 300000, batchSize: 3 } // 5分钟,3条/批
};
private currentStrategy = this.syncStrategies.optimal;
constructor() {
this.checkEnvironment();
// 环境检测
private checkEnvironment(): void {
const powerMode = powerManagement.getPowerMode();
const netInfo = connection.getDefaultNet();
if (powerMode === powerManagement.PowerMode.POWER_SAVE) {
this.currentStrategy = this.syncStrategies.powerSave;
else if (netInfo.type === connection.NetBearType.BEARER_CELLULAR) {
this.currentStrategy = this.syncStrategies.normal;
else {
this.currentStrategy = this.syncStrategies.optimal;
}
// 添加数据到同步队列
public addToQueue(data: any): void {
this.syncQueue.push(data);
this.checkSyncCondition();
// 检查同步条件
private checkSyncCondition(): void {
const now = Date.now();
const shouldSync =
now - this.lastSyncTime > this.currentStrategy.interval ||
this.syncQueue.length >= this.currentStrategy.batchSize;
if (shouldSync && !this.isSyncing) {
this.syncData();
}
// 执行同步
private async syncData(): Promise<void> {
if (this.syncQueue.length === 0) return;
this.isSyncing = true;
const batch = this.syncQueue.slice(0, this.currentStrategy.batchSize);
try {
const httpRequest = http.createHttp();
const response = await httpRequest.request(
'https://api.airquality.example.com/v1/data',
method: ‘POST’,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify({
deviceId: deviceInfo.deviceId,
data: batch
})
);
if (response.responseCode === 200) {
// 同步成功,移除已同步数据
this.syncQueue = this.syncQueue.slice(batch.length);
this.lastSyncTime = Date.now();
} catch (err) {
console.error('云端同步失败:', JSON.stringify(err));
finally {
this.isSyncing = false;
this.checkSyncCondition();
}
// 手动触发同步
public async forceSync(): Promise<void> {
await this.syncData();
}
export const cloudSync = new CloudSyncManager();
跨设备数据同步
// DistributedSync.ets
import distributedData from ‘@ohos.distributedData’;
class AirQualitySync {
private dataManager: distributedData.DataManager;
private localData: AirQualityData = {
aqi: 0,
pm25: 0,
co2: 0,
tvoc: 0,
timestamp: 0
};
constructor() {
this.dataManager = distributedData.createDataManager({
bundleName: ‘com.example.airquality’,
area: distributedData.Area.GLOBAL
});
this.setupListeners();
private setupListeners(): void {
this.dataManager.registerDataListener('airquality_sync', (data) => {
if (data?.type === 'data_update') {
this.handleRemoteData(data.payload);
});
// 同步本地数据到其他设备
public syncLocalData(data: AirQualityData): void {
this.localData = data;
this.dataManager.syncData(‘airquality_sync’, {
type: ‘data_update’,
payload: this.compressData(data)
});
// 数据压缩
private compressData(data: AirQualityData): Uint8Array {
const buffer = new ArrayBuffer(20); // 5个float32
const view = new DataView(buffer);
view.setFloat32(0, data.aqi);
view.setFloat32(4, data.pm25);
view.setFloat32(8, data.co2);
view.setFloat32(12, data.tvoc);
view.setFloat32(16, data.timestamp);
return new Uint8Array(buffer);
// 处理远程数据
private handleRemoteData(compressed: Uint8Array): void {
const data = this.decompressData(compressed);
// 冲突解决策略:选择时间戳最新的数据
if (data.timestamp > this.localData.timestamp) {
this.localData = data;
EventBus.emit('airQualityUpdated', this.localData);
}
// 数据解压
private decompressData(data: Uint8Array): AirQualityData {
const view = new DataView(data.buffer);
return {
aqi: view.getFloat32(0),
pm25: view.getFloat32(4),
co2: view.getFloat32(8),
tvoc: view.getFloat32(12),
timestamp: view.getFloat32(16)
};
// 获取当前数据
public getCurrentData(): AirQualityData {
return this.localData;
}
interface AirQualityData {
aqi: number;
pm25: number;
co2: number;
tvoc: number;
timestamp: number;
export const airQualitySync = new AirQualitySync();
主界面实现
// MainScreen.ets
import { sensorFusion } from ‘./SensorFusion’;
import { dataFilter } from ‘./DataFilter’;
import { cloudSync } from ‘./CloudSync’;
import { airQualitySync } from ‘./DistributedSync’;
@Component
export struct MainScreen {
@State aqi: number = 0;
@State pm25: number = 0;
@State co2: number = 0;
@State tvoc: number = 0;
@State lastUpdate: string = ‘’;
@State syncStatus: string = ‘等待同步’;
build() {
Column() {
// 空气质量指数
Gauge({
value: this.aqi,
min: 0,
max: 500,
title: ‘AQI’
})
.width(200)
.height(200)
// 详细数据
Column() {
Row() {
Text(PM2.5: ${this.pm25.toFixed(1)} μg/m³)
Text(CO₂: ${this.co2.toFixed(0)} ppm)
.margin({ left: 20 })
Row() {
Text(TVOC: ${this.tvoc.toFixed(0)} ppb)
Text(更新时间: ${this.lastUpdate})
.margin({ left: 20 })
.margin({ top: 10 })
.margin({ top: 20 })
// 同步状态
Text(this.syncStatus)
.fontColor(this.syncStatus.includes('成功') ? '#4CAF50' : '#F44336')
.margin({ top: 20 })
// 控制按钮
Row() {
Button('手动同步')
.onClick(() => {
this.triggerSync();
})
Button('历史数据')
.margin({ left: 20 })
.onClick(() => {
// 跳转到历史数据页面
})
.margin({ top: 30 })
.width(‘100%’)
.height('100%')
.padding(20)
aboutToAppear() {
// 监听传感器数据更新
EventBus.on('sensorDataUpdated', (data) => {
this.updateUI(data);
});
// 监听同步状态变化
EventBus.on('syncStatusChanged', (status) => {
this.syncStatus = status;
});
// 初始数据加载
this.loadInitialData();
aboutToDisappear() {
EventBus.off('sensorDataUpdated');
EventBus.off('syncStatusChanged');
private loadInitialData(): void {
const data = airQualitySync.getCurrentData();
this.updateUI(data);
private updateUI(data: AirQualityData): void {
this.aqi = data.aqi;
this.pm25 = data.pm25;
this.co2 = data.co2;
this.tvoc = data.tvoc;
this.lastUpdate = new Date(data.timestamp).toLocaleTimeString();
private triggerSync(): void {
this.syncStatus = '同步中...';
// 获取最新传感器数据
const currentData = {
aqi: sensorFusion.getCurrentAQI(),
pm25: sensorFusion.getSensorData('pm25')?.value || 0,
co2: sensorFusion.getSensorData('co2')?.value || 0,
tvoc: sensorFusion.getSensorData('tvoc')?.value || 0,
timestamp: Date.now()
};
// 过滤异常值
const filteredData = {
...currentData,
pm25: dataFilter.filter('pm25', currentData.pm25) || currentData.pm25,
co2: dataFilter.filter('co2', currentData.co2) || currentData.co2,
tvoc: dataFilter.filter('tvoc', currentData.tvoc) || currentData.tvoc
};
// 本地存储和同步
airQualitySync.syncLocalData(filteredData);
cloudSync.addToQueue(filteredData);
this.syncStatus = '同步请求已发送';
}
三、项目配置与权限
// module.json5
“module”: {
"requestPermissions": [
“name”: “ohos.permission.READ_AIR_SENSOR”,
"reason": "读取空气质量传感器数据"
},
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,
"reason": "同步数据到其他设备"
},
“name”: “ohos.permission.INTERNET”,
"reason": "上传数据到云端"
},
“name”: “ohos.permission.GET_NETWORK_INFO”,
"reason": "检测网络状况优化同步策略"
],
"abilities": [
“name”: “MainAbility”,
"type": "page",
"backgroundModes": ["dataTransfer"],
"visible": true
]
}
四、总结与扩展
本空气质量检测仪系统实现了三大核心技术:
多传感器数据融合:加权算法综合多种环境参数
智能云端同步:自适应网络和电量状况的节流策略
异常值过滤:基于统计学的IQR异常检测方法
扩展方向:
预测分析:基于历史数据预测空气质量变化趋势
智能报警:异常空气质量自动通知
健康建议:根据空气质量提供健康建议
多设备协同:组建分布式监测网络提高精度
离线模式:在网络不佳时本地存储更多数据
可视化分析:丰富的数据可视化展示
通过HarmonyOS的分布式能力,该系统可以实现手机、平板、智慧屏等多设备的实时数据同步,为用户提供全面的环境质量监测服务。
