鸿蒙空气质量监测仪开发指南

一、系统架构设计

基于HarmonyOS的空气质量监测系统采用四层架构:

  1. ​感知层​​:多传感器数据采集(PM2.5、CO2、TVOC等)
  2. ​处理层​​:数据预处理与异常过滤
  3. ​同步层​​:跨设备数据同步与云端备份
  4. ​节能层​​:智能节流策略

https://example.com/harmony-airquality-arch.png

二、核心代码实现

1. 传感器预热优化

// SensorManager.ets
import sensor from '@ohos.sensor';
import powerManagement from '@ohos.powerManagement';

class SensorManager {
  private static instance: SensorManager = null;
  private sensorList: Array<string> = ['pm2.5', 'co2', 'tvoc'];
  private isPreheating: boolean = false;
  private preheatTimer: number = 0;
  
  // 预热时间配置(毫秒)
  private preheatTimes = {
    'pm2.5': 30000,   // 30秒
    'co2': 60000,     // 1分钟
    'tvoc': 45000     // 45秒
  };
  
  // 优化后的预热策略
  private optimizedPreheat(sensorType: string): Promise<void> {
    return new Promise((resolve) => {
      // 1. 快速启动基础读数
      sensor.on(sensorType, (data) => {
        if (this.isStable(data)) {
          resolve();
          sensor.off(sensorType);
        }
      });
      
      // 2. 动态调整预热时间
      const baseTime = this.preheatTimes[sensorType];
      const powerMode = powerManagement.getPowerMode();
      const adjustedTime = powerMode === powerManagement.PowerMode.POWER_SAVE ? 
                         baseTime * 0.7 : // 省电模式缩短预热
                         baseTime;
      
      // 3. 强制超时保障
      this.preheatTimer = setTimeout(() => {
        sensor.off(sensorType);
        resolve();
      }, adjustedTime);
    });
  }
  
  // 判断数据是否稳定
  private isStable(sensorData: any): boolean {
    // 实现稳定性检测逻辑
    // ...
  }
  
  // 并行预热所有传感器
  public async preheatAll(): Promise<void> {
    this.isPreheating = true;
    
    await Promise.all(
      this.sensorList.map(type => this.optimizedPreheat(type))
    );
    
    this.isPreheating = false;
  }
}

2. 数据异常波动过滤

// DataFilter.ets
class DataFilter {
  private static instance: DataFilter = null;
  private historyData: Map<string, Array<number>> = new Map();
  private readonly MAX_HISTORY = 10;
  
  // 改进的卡尔曼滤波器实现
  kalmanFilter(sensorType: string, newValue: number): number {
    if (!this.historyData.has(sensorType)) {
      this.historyData.set(sensorType, []);
    }
    
    const history = this.historyData.get(sensorType);
    const lastValue = history.length > 0 ? history[history.length - 1] : newValue;
    
    // 简化的卡尔曼滤波
    const processNoise = 0.01;
    const measurementNoise = 0.1;
    const estimatedError = 1;
    
    let kalmanGain = estimatedError / (estimatedError + measurementNoise);
    const filteredValue = lastValue + kalmanGain * (newValue - lastValue);
    
    // 更新历史数据
    history.push(filteredValue);
    if (history.length > this.MAX_HISTORY) {
      history.shift();
    }
    
    return filteredValue;
  }
  
  // 基于统计的异常值检测
  isOutlier(sensorType: string, value: number): boolean {
    const history = this.historyData.get(sensorType) || [];
    if (history.length < 3) return false;
    
    const mean = history.reduce((a, b) => a + b, 0) / history.length;
    const stdDev = Math.sqrt(
      history.reduce((sq, n) => sq + Math.pow(n - mean, 2), 0) / history.length
    );
    
    return Math.abs(value - mean) > 3 * stdDev;
  }
  
  // 综合处理流程
  processData(sensorType: string, rawValue: number): number | null {
    // 1. 应用卡尔曼滤波
    const filtered = this.kalmanFilter(sensorType, rawValue);
    
    // 2. 检测异常值
    if (this.isOutlier(sensorType, filtered)) {
      return null; // 丢弃异常值
    }
    
    return filtered;
  }
}

3. 云端同步智能节流

// CloudSyncManager.ets
import distributedData from '@ohos.distributedData';
import http from '@ohos.net.http';

class CloudSyncManager {
  private static instance: CloudSyncManager = null;
  private dataManager: distributedData.DataManager;
  private lastSyncTime: number = 0;
  private syncQueue: Array<any> = [];
  private isSyncing: boolean = false;
  
  // 节流策略配置
  private syncStrategies = {
    normal: {
      interval: 60000,    // 1分钟
      batchSize: 10
    },
    powerSave: {
      interval: 300000,   // 5分钟
      batchSize: 5
    },
    poorNetwork: {
      interval: 900000,   // 15分钟
      batchSize: 3
    }
  };
  
  private currentStrategy = this.syncStrategies.normal;
  
  constructor() {
    this.dataManager = distributedData.createDataManager({
      bundleName: 'com.example.airquality',
      area: distributedData.Area.GLOBAL
    });
    
    this.checkNetworkConditions();
  }
  
  // 网络状态检测
  private checkNetworkConditions() {
    const connection = network.getDefaultNet();
    const powerMode = powerManagement.getPowerMode();
    
    if (powerMode === powerManagement.PowerMode.POWER_SAVE) {
      this.currentStrategy = this.syncStrategies.powerSave;
    } else if (connection.type === network.NetBearType.BEARER_CELLULAR) {
      this.currentStrategy = this.syncStrategies.poorNetwork;
    } else {
      this.currentStrategy = this.syncStrategies.normal;
    }
  }
  
  // 智能节流同步
  public async syncData(data: any): Promise<void> {
    // 添加到队列
    this.syncQueue.push(data);
    
    // 检查是否满足同步条件
    const now = Date.now();
    const shouldSync = 
      now - this.lastSyncTime > this.currentStrategy.interval ||
      this.syncQueue.length >= this.currentStrategy.batchSize;
    
    if (shouldSync && !this.isSyncing) {
      this.isSyncing = true;
      
      try {
        // 分批处理
        const batch = this.syncQueue.slice(0, this.currentStrategy.batchSize);
        await this.uploadToCloud(batch);
        
        // 更新状态
        this.lastSyncTime = now;
        this.syncQueue = this.syncQueue.slice(this.currentStrategy.batchSize);
        
        // 本地分布式同步
        this.dataManager.syncData('airquality_sync', {
          type: 'data_update',
          count: batch.length,
          timestamp: now
        });
      } catch (err) {
        console.error('云端同步失败:', JSON.stringify(err));
      } finally {
        this.isSyncing = false;
      }
    }
  }
  
  private async uploadToCloud(dataBatch: Array<any>): Promise<void> {
    const httpRequest = http.createHttp();
    await httpRequest.request(
      'https://api.airquality.example.com/v1/data',
      {
        method: 'POST',
        header: { 'Content-Type': 'application/json' },
        extraData: JSON.stringify({
          deviceId: deviceInfo.deviceId,
          data: dataBatch
        })
      }
    );
  }
}

4. 主界面与数据整合

// MainScreen.ets
import { SensorManager } from './SensorManager';
import { DataFilter } from './DataFilter';
import { CloudSyncManager } from './CloudSyncManager';

@Component
export struct MainScreen {
  @State airData: {
    pm25?: number;
    co2?: number;
    tvoc?: number;
    lastUpdated?: string;
  } = {};
  
  @State isPreheating: boolean = false;
  @State syncStatus: string = '等待同步';
  
  private sensorManager = SensorManager.getInstance();
  private dataFilter = DataFilter.getInstance();
  private cloudSync = CloudSyncManager.getInstance();
  private dataUpdateTimer: number = 0;
  
  build() {
    Column() {
      // 状态显示
      Row() {
        Text(this.isPreheating ? '传感器预热中...' : '实时监测中')
          .fontColor(this.isPreheating ? '#FF9800' : '#4CAF50')
        
        Text(`同步状态: ${this.syncStatus}`)
          .margin({ left: 20 })
      }
      .padding(10)
      
      // 数据展示
      if (this.airData.pm25 !== undefined) {
        Column() {
          Gauge({ 
            value: this.airData.pm25,
            min: 0,
            max: 500,
            title: 'PM2.5'
          })
          .width(200)
          .height(200)
          
          Row() {
            Text(`CO₂: ${this.airData.co2 || 0}ppm`)
              .margin({ right: 20 })
            
            Text(`TVOC: ${this.airData.tvoc || 0}ppb`)
          }
          .margin({ top: 20 })
        }
      }
      
      // 控制按钮
      Row() {
        Button('启动监测')
          .onClick(() => this.startMonitoring())
          .enabled(!this.isPreheating)
        
        Button('手动同步')
          .onClick(() => this.forceSync())
          .margin({ left: 20 })
      }
      .margin({ top: 30 })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
  
  private async startMonitoring(): Promise<void> {
    this.isPreheating = true;
    await this.sensorManager.preheatAll();
    this.isPreheating = false;
    
    // 开始定期更新数据
    this.dataUpdateTimer = setInterval(() => {
      this.updateAirQualityData();
    }, 5000);
  }
  
  private async updateAirQualityData(): Promise<void> {
    try {
      const rawData = await this.readSensorData();
      const processedData = this.processRawData(rawData);
      
      // 更新UI
      this.airData = {
        ...processedData,
        lastUpdated: new Date().toLocaleTimeString()
      };
      
      // 同步到云端
      this.cloudSync.syncData(processedData);
      this.syncStatus = '同步队列中';
    } catch (err) {
      console.error('更新数据失败:', JSON.stringify(err));
    }
  }
  
  private processRawData(rawData: any): any {
    return {
      pm25: this.dataFilter.processData('pm2.5', rawData.pm25),
      co2: this.dataFilter.processData('co2', rawData.co2),
      tvoc: this.dataFilter.processData('tvoc', rawData.tvoc)
    };
  }
  
  private async forceSync(): Promise<void> {
    this.syncStatus = '同步中...';
    try {
      await this.cloudSync.syncData(this.airData);
      this.syncStatus = '同步成功';
    } catch (err) {
      this.syncStatus = '同步失败';
    }
  }
  
  aboutToDisappear() {
    clearInterval(this.dataUpdateTimer);
  }
}

三、性能优化策略

1. 传感器协同采样

// SensorCoordinator.ets
class SensorCoordinator {
  private sensorSequence: Array<string> = [];
  private currentIndex: number = 0;
  
  // 优化采样顺序减少切换延迟
  optimizeSamplingOrder(sensors: Array<string>): void {
    // 按预热时间排序,先启动预热时间长的
    this.sensorSequence = [...sensors].sort((a, b) => 
      SensorManager.getInstance().getPreheatTime(b) - 
      SensorManager.getInstance().getPreheatTime(a)
    );
  }
  
  // 获取下一个应采样的传感器
  getNextSensor(): string | null {
    if (this.currentIndex >= this.sensorSequence.length) {
      this.currentIndex = 0;
      return null; // 一轮结束
    }
    
    return this.sensorSequence[this.currentIndex++];
  }
}

2. 自适应数据缓存

// DataCache.ets
class DataCache {
  private cache: Map<string, any> = new Map();
  private lastAccess: Map<string, number> = new Map();
  private readonly MAX_CACHE_SIZE = 50;
  
  set(key: string, value: any): void {
    // 清理旧缓存
    if (this.cache.size >= this.MAX_CACHE_SIZE) {
      const oldestKey = [...this.lastAccess.entries()]
        .reduce((a, b) => a[1] < b[1] ? a : b)[0];
      
      this.cache.delete(oldestKey);
      this.lastAccess.delete(oldestKey);
    }
    
    this.cache.set(key, value);
    this.lastAccess.set(key, Date.now());
  }
  
  get(key: string): any | undefined {
    if (this.cache.has(key)) {
      this.lastAccess.set(key, Date.now());
      return this.cache.get(key);
    }
    return undefined;
  }
}

四、项目配置

1. 权限配置

// 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
      }
    ]
  }
}

五、总结与扩展

本空气质量监测仪实现了三大核心优化:

  1. ​传感器预热优化​​:缩短30%的启动时间
  2. ​数据滤波算法​​:有效消除异常波动
  3. ​智能云端同步​​:根据网络和电量自动节流

​扩展方向​​:

  1. ​预测分析​​:基于历史数据预测空气质量变化趋势
  2. ​多设备协同​​:组建分布式监测网络提高精度
  3. ​智能报警​​:异常空气质量自动通知
  4. ​健康建议​​:根据空气质量提供健康建议
  5. ​可视化分析​​:丰富的数据可视化展示
  6. ​离线模式​​:在网络不佳时本地存储更多数据

通过HarmonyOS的分布式能力,该系统可以实现多设备间的数据协同和互补,构建更全面的环境监测网络,为用户提供更准确的空气质量信息。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐