鸿蒙空气质量检测仪系统开发指南 原创

进修的泡芙
发布于 2025-6-23 13:04
浏览
0收藏

鸿蒙空气质量检测仪系统开发指南

一、系统架构设计

基于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的分布式能力,该系统可以实现手机、平板、智慧屏等多设备的实时数据同步,为用户提供全面的环境质量监测服务。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐