HarmonyOS分布式传感器开发小知识

举报
Jack20 发表于 2026/06/20 00:04:03 2026/06/20
【摘要】 背景与动机你有没有遇到过这种场景:用平板做运动监测,但平板没有心率传感器;或者在车里用手机导航,想用车载的GPS获得更精准的定位;又或者在玩游戏时,想用手表的陀螺仪来控制视角。这就是分布式传感器要解决的问题——让传感器数据可以跨设备共享,一个设备可以使用另一个设备的传感器。不同设备的传感器配置差异很大。手机通常有加速度计、陀螺仪、GPS、心率传感器等;平板可能缺少心率传感器;电视可能只有简...

背景与动机

你有没有遇到过这种场景:用平板做运动监测,但平板没有心率传感器;或者在车里用手机导航,想用车载的GPS获得更精准的定位;又或者在玩游戏时,想用手表的陀螺仪来控制视角。

这就是分布式传感器要解决的问题——让传感器数据可以跨设备共享,一个设备可以使用另一个设备的传感器。

不同设备的传感器配置差异很大。手机通常有加速度计、陀螺仪、GPS、心率传感器等;平板可能缺少心率传感器;电视可能只有简单的环境光传感器;手表则可能有更丰富的健康传感器。分布式传感器打破了这种限制,让应用可以使用"整个超级终端"上所有可用的传感器。

核心原理

分布式传感器架构

分布式传感器基于以下几个核心概念:

  1. SensorProvider:传感器提供者,声明本设备的传感器能力
  2. SensorProxy:传感器代理,在远程设备上代表传感器实例
  3. SensorDataChannel:传感器数据通道,负责数据传输
  4. SensorFusion:传感器融合,整合多个传感器的数据
flowchart TB
    classDef primary fill:#4A90E2,stroke:#2E5C8A,stroke-width:2px,color:#fff
    classDef warning fill:#F5A623,stroke:#D4821C,stroke-width:2px,color:#fff
    classDef error fill:#E74C3C,stroke:#C0392B,stroke-width:2px,color:#fff
    classDef info fill:#7B68EE,stroke:#5A4FCF,stroke-width:2px,color:#fff

    subgraph Provider[传感器提供者]
        A1[加速度计]:::primary --> A2[SensorProvider]:::info
        A3[陀螺仪]:::primary --> A2
        A4[GPS]:::primary --> A2
        A5[心率]:::primary --> A2
    end

    subgraph Channel[数据通道]
        B1[数据采集]:::info --> B2[数据压缩]:::warning
        B2 --> B3[网络传输]:::error
        B3 --> B4[数据解压]:::warning
    end

    subgraph Consumer[传感器使用者]
        C1[SensorProxy]:::primary --> C2[数据校验]:::info
        C2 --> C3[SensorFusion]:::warning
        C3 --> C4[应用回调]:::primary
    end

    A2 --> B1
    B4 --> C1

传感器类型分类

分布式传感器支持多种传感器类型:

1. 运动传感器:加速度计、陀螺仪、重力传感器、线性加速度
2. 位置传感器:GPS、地磁传感器、方向传感器
3. 环境传感器:环境光、温度、湿度、气压、噪声
4. 健康传感器:心率、血氧、步数、睡眠

数据传输策略

传感器数据传输需要考虑带宽和延迟:

// 传感器数据传输配置
interface SensorTransportConfig {
    // 采样率
    samplingRate: number;
    
    // 传输模式
    transportMode: 'realtime' | 'batch' | 'ondemand';
    
    // 数据压缩
    compression: {
        enabled: boolean;
        algorithm: 'delta' | 'quantization' | 'none';
    };
    
    // 批处理配置
    batchConfig?: {
        maxSize: number;
        maxDelay: number;
    };
}

代码实战

示例一:基础分布式传感器使用

这是最基础的分布式传感器使用示例,在平板上使用手机的心率传感器。

// DistributedSensor.ets
import sensor from '@ohos.sensor';
import deviceManager from '@ohos.distributedDeviceManager';
import distributedSensor from '@ohos.distributedSensor';

export class DistributedSensor {
    private context: common.UIAbilityContext;
    private deviceManager: deviceManager.DeviceManager | null = null;
    
    // 本地传感器订阅者
    private localSubscribers: Map<string, sensor.SensorSubscriber> = new Map();
    
    // 远程传感器代理
    private remoteSensors: Map<string, distributedSensor.SensorProxy> = new Map();
    
    // 传感器状态
    private sensorState: SensorState = {
        activeSensors: [],
        dataBuffer: new Map()
    };

    constructor(context: common.UIAbilityContext) {
        this.context = context;
    }

    // 初始化
    async initialize(): Promise<void> {
        console.info('[DistributedSensor] Initializing...');
        
        try {
            // 初始化设备管理器
            this.deviceManager = deviceManager.createDeviceManager(
                this.context.applicationInfo.name
            );
            
            // 发现可用传感器
            await this.discoverSensors();
            
            console.info('[DistributedSensor] Initialized');
        } catch (error) {
            console.error('[DistributedSensor] Init failed:', error);
        }
    }

    // 发现所有可用传感器(本地+远程)
    async discoverSensors(): Promise<SensorInfo[]> {
        console.info('[DistributedSensor] Discovering sensors');
        
        const allSensors: SensorInfo[] = [];
        
        // 1. 发现本地传感器
        const localSensors = await this.discoverLocalSensors();
        allSensors.push(...localSensors);
        
        // 2. 发现远程传感器
        const remoteSensors = await this.discoverRemoteSensors();
        allSensors.push(...remoteSensors);
        
        console.info('[DistributedSensor] Found', allSensors.length, 'sensors');
        return allSensors;
    }

    // 发现本地传感器
    private async discoverLocalSensors(): Promise<SensorInfo[]> {
        const sensors: SensorInfo[] = [];
        
        try {
            // 获取所有支持的传感器
            const supportedTypes = [
                sensor.SensorType.ACCELEROMETER,
                sensor.SensorType.GYROSCOPE,
                sensor.SensorType.HEART_RATE,
                sensor.SensorType.LIGHT,
                sensor.SensorType.LOCATION
            ];
            
            for (const type of supportedTypes) {
                try {
                    const info = await sensor.getSensorInfo(type);
                    sensors.push({
                        sensorId: `local_${type}`,
                        sensorType: type,
                        sensorName: info.sensorName,
                        deviceId: 'local',
                        deviceName: '本机',
                        isLocal: true,
                        capabilities: {
                            maxSamplingRate: info.maxSamplingRate,
                            minDelay: info.minDelay
                        }
                    });
                } catch (e) {
                    // 该传感器不存在,跳过
                }
            }
        } catch (error) {
            console.error('[DistributedSensor] Discover local failed:', error);
        }
        
        return sensors;
    }

    // 发现远程传感器
    private async discoverRemoteSensors(): Promise<SensorInfo[]> {
        const sensors: SensorInfo[] = [];
        
        if (!this.deviceManager) return sensors;
        
        try {
            // 获取在线设备
            const devices = this.deviceManager.getTrustedDeviceListSync();
            
            for (const device of devices) {
                if (device.deviceState !== deviceManager.DeviceState.ONLINE) {
                    continue;
                }
                
                // 查询设备的传感器能力
                try {
                    const deviceSensors = await distributedSensor.queryRemoteSensors(
                        device.deviceId
                    );
                    
                    for (const s of deviceSensors) {
                        sensors.push({
                            sensorId: `${device.deviceId}_${s.sensorType}`,
                            sensorType: s.sensorType,
                            sensorName: s.sensorName,
                            deviceId: device.deviceId,
                            deviceName: device.deviceName,
                            isLocal: false,
                            capabilities: s.capabilities
                        });
                    }
                } catch (e) {
                    console.error('[DistributedSensor] Query device failed:', device.deviceId, e);
                }
            }
        } catch (error) {
            console.error('[DistributedSensor] Discover remote failed:', error);
        }
        
        return sensors;
    }

    // 订阅传感器数据
    async subscribeSensor(
        sensorId: string, 
        callback: (data: SensorData) => void,
        options?: SubscribeOptions
    ): Promise<boolean> {
        console.info('[DistributedSensor] Subscribing to:', sensorId);
        
        // 解析传感器ID
        const [deviceId, sensorType] = this.parseSensorId(sensorId);
        
        if (deviceId === 'local') {
            // 订阅本地传感器
            return await this.subscribeLocalSensor(
                parseInt(sensorType), 
                callback, 
                options
            );
        } else {
            // 订阅远程传感器
            return await this.subscribeRemoteSensor(
                deviceId, 
                parseInt(sensorType), 
                callback, 
                options
            );
        }
    }

    // 订阅本地传感器
    private async subscribeLocalSensor(
        sensorType: sensor.SensorType,
        callback: (data: SensorData) => void,
        options?: SubscribeOptions
    ): Promise<boolean> {
        try {
            // 创建订阅者
            const subscriber: sensor.SensorSubscriber = {
                onSensorChanged: (data: sensor.SensorResponse) => {
                    callback({
                        sensorType: sensorType,
                        values: data.values,
                        timestamp: data.timestamp,
                        accuracy: data.accuracy
                    });
                }
            };
            
            // 订阅传感器
            const interval = options?.samplingInterval || 100000000;  // 默认100ms
            await sensor.subscribeSensor(sensorType, subscriber, { interval });
            
            // 保存订阅者
            this.localSubscribers.set(`local_${sensorType}`, subscriber);
            
            console.info('[DistributedSensor] Local sensor subscribed');
            return true;
        } catch (error) {
            console.error('[DistributedSensor] Subscribe local failed:', error);
            return false;
        }
    }

    // 订阅远程传感器
    private async subscribeRemoteSensor(
        deviceId: string,
        sensorType: sensor.SensorType,
        callback: (data: SensorData) => void,
        options?: SubscribeOptions
    ): Promise<boolean> {
        try {
            // 创建或获取传感器代理
            let proxy = this.remoteSensors.get(`${deviceId}_${sensorType}`);
            
            if (!proxy) {
                proxy = await distributedSensor.createSensorProxy({
                    sourceDeviceId: deviceId,
                    sensorType: sensorType
                });
                
                this.remoteSensors.set(`${deviceId}_${sensorType}`, proxy);
            }
            
            // 配置数据通道
            const channelConfig: distributedSensor.ChannelConfig = {
                samplingRate: options?.samplingInterval ? 
                    1000000000 / options.samplingInterval : 10,  // Hz
                transportMode: options?.transportMode || 'realtime',
                compression: {
                    enabled: true,
                    algorithm: 'delta'
                }
            };
            
            // 订阅数据
            await proxy.subscribe(channelConfig, (data: distributedSensor.SensorData) => {
                callback({
                    sensorType: sensorType,
                    values: data.values,
                    timestamp: data.timestamp,
                    accuracy: data.accuracy,
                    sourceDevice: deviceId
                });
            });
            
            console.info('[DistributedSensor] Remote sensor subscribed');
            return true;
        } catch (error) {
            console.error('[DistributedSensor] Subscribe remote failed:', error);
            return false;
        }
    }

    // 取消订阅传感器
    async unsubscribeSensor(sensorId: string): Promise<void> {
        console.info('[DistributedSensor] Unsubscribing:', sensorId);
        
        const [deviceId, sensorType] = this.parseSensorId(sensorId);
        
        if (deviceId === 'local') {
            // 取消本地订阅
            const subscriber = this.localSubscribers.get(sensorId);
            if (subscriber) {
                await sensor.unsubscribeSensor(parseInt(sensorType), subscriber);
                this.localSubscribers.delete(sensorId);
            }
        } else {
            // 取消远程订阅
            const proxy = this.remoteSensors.get(sensorId);
            if (proxy) {
                await proxy.unsubscribe();
            }
        }
    }

    // 订阅多个传感器(传感器融合)
    async subscribeMultipleSensors(
        sensorIds: string[],
        callback: (data: FusedSensorData) => void,
        options?: FusionOptions
    ): Promise<boolean> {
        console.info('[DistributedSensor] Subscribing multiple sensors');
        
        try {
            // 创建传感器融合器
            const fuser = new SensorFusion(options);
            
            // 订阅每个传感器
            const subscriptions: Promise<boolean>[] = sensorIds.map(sensorId => {
                return this.subscribeSensor(sensorId, (data) => {
                    fuser.addData(data);
                });
            });
            
            const results = await Promise.all(subscriptions);
            
            if (results.every(r => r)) {
                // 设置融合结果回调
                fuser.onFusedData(callback);
                
                return true;
            }
            
            return false;
        } catch (error) {
            console.error('[DistributedSensor] Subscribe multiple failed:', error);
            return false;
        }
    }

    // 获取传感器单次数据
    async getSensorData(sensorId: string): Promise<SensorData | null> {
        const [deviceId, sensorType] = this.parseSensorId(sensorId);
        
        if (deviceId === 'local') {
            // 获取本地传感器数据
            try {
                const data = await sensor.getSensorData(parseInt(sensorType));
                return {
                    sensorType: parseInt(sensorType),
                    values: data.values,
                    timestamp: data.timestamp
                };
            } catch (error) {
                console.error('[DistributedSensor] Get local data failed:', error);
                return null;
            }
        } else {
            // 获取远程传感器数据
            const proxy = this.remoteSensors.get(sensorId);
            if (proxy) {
                return await proxy.getData();
            }
            
            // 如果代理不存在,创建临时代理获取数据
            try {
                const tempProxy = await distributedSensor.createSensorProxy({
                    sourceDeviceId: deviceId,
                    sensorType: parseInt(sensorType)
                });
                
                const data = await tempProxy.getData();
                await tempProxy.release();
                
                return data;
            } catch (error) {
                console.error('[DistributedSensor] Get remote data failed:', error);
                return null;
            }
        }
    }

    // 解析传感器ID
    private parseSensorId(sensorId: string): [string, string] {
        const parts = sensorId.split('_');
        if (parts[0] === 'local') {
            return ['local', parts[1]];
        } else {
            return [parts[0], parts[1]];
        }
    }

    // 释放资源
    async release(): Promise<void> {
        console.info('[DistributedSensor] Releasing');
        
        // 取消所有本地订阅
        for (const [id, subscriber] of this.localSubscribers) {
            const [_, sensorType] = this.parseSensorId(id);
            await sensor.unsubscribeSensor(parseInt(sensorType), subscriber);
        }
        this.localSubscribers.clear();
        
        // 释放所有远程代理
        for (const proxy of this.remoteSensors.values()) {
            await proxy.release();
        }
        this.remoteSensors.clear();
        
        // 释放设备管理器
        if (this.deviceManager) {
            deviceManager.releaseDeviceManager(this.deviceManager);
            this.deviceManager = null;
        }
    }
}

// 传感器融合器
class SensorFusion {
    private options: FusionOptions;
    private dataBuffer: Map<string, SensorData[]> = new Map();
    private fusionCallback: ((data: FusedSensorData) => void) | null = null;
    
    // 时间同步窗口
    private syncWindow: number = 50;  // 50ms

    constructor(options?: FusionOptions) {
        this.options = options || {};
    }

    // 添加传感器数据
    addData(data: SensorData): void {
        const key = `${data.sourceDevice || 'local'}_${data.sensorType}`;
        
        if (!this.dataBuffer.has(key)) {
            this.dataBuffer.set(key, []);
        }
        
        const buffer = this.dataBuffer.get(key)!;
        buffer.push(data);
        
        // 限制缓冲大小
        if (buffer.length > 100) {
            buffer.shift();
        }
        
        // 尝试融合
        this.tryFusion();
    }

    // 尝试融合数据
    private tryFusion(): void {
        if (!this.fusionCallback) return;
        
        // 检查是否有足够的数据进行融合
        const now = Date.now();
        
        // 收集时间窗口内的数据
        const windowData: SensorData[] = [];
        
        for (const buffer of this.dataBuffer.values()) {
            const recent = buffer.filter(d => now - d.timestamp < this.syncWindow);
            if (recent.length > 0) {
                windowData.push(recent[recent.length - 1]);  // 取最新的
            }
        }
        
        if (windowData.length < 2) return;  // 至少需要两个传感器
        
        // 执行融合
        const fused = this.fuseData(windowData);
        
        if (fused) {
            this.fusionCallback(fused);
        }
    }

    // 融合数据
    private fuseData(data: SensorData[]): FusedSensorData | null {
        // 简单的融合策略:取平均或加权平均
        // 实际实现需要根据传感器类型使用合适的融合算法
        
        const timestamp = Date.now();
        
        // 示例:加速度计和陀螺仪融合得到姿态
        const accelerometer = data.find(d => d.sensorType === sensor.SensorType.ACCELEROMETER);
        const gyroscope = data.find(d => d.sensorType === sensor.SensorType.GYROSCOPE);
        
        if (accelerometer && gyroscope) {
            // 使用互补滤波融合姿态
            const attitude = this.complementaryFilter(accelerometer, gyroscope);
            
            return {
                timestamp: timestamp,
                dataType: 'attitude',
                values: attitude,
                accuracy: Math.min(accelerometer.accuracy || 3, gyroscope.accuracy || 3),
                sourceSensors: ['accelerometer', 'gyroscope']
            };
        }
        
        return null;
    }

    // 互补滤波
    private complementaryFilter(accel: SensorData, gyro: SensorData): number[] {
        const alpha = 0.98;  // 互补滤波系数
        
        // 简化的姿态计算
        const ax = accel.values[0];
        const ay = accel.values[1];
        const az = accel.values[2];
        
        // 从加速度计计算倾角
        const pitchAcc = Math.atan2(ax, Math.sqrt(ay * ay + az * az));
        const rollAcc = Math.atan2(ay, az);
        
        // 从陀螺仪积分(简化)
        const pitchGyro = gyro.values[0] * 0.01;  // 假设10ms间隔
        const rollGyro = gyro.values[1] * 0.01;
        
        // 互补滤波
        const pitch = alpha * pitchGyro + (1 - alpha) * pitchAcc;
        const roll = alpha * rollGyro + (1 - alpha) * rollAcc;
        
        return [pitch, roll, 0];  // yaw需要磁力计
    }

    // 设置融合回调
    onFusedData(callback: (data: FusedSensorData) => void): void {
        this.fusionCallback = callback;
    }
}

// 接口定义
interface SensorState {
    activeSensors: string[];
    dataBuffer: Map<string, SensorData[]>;
}

interface SensorInfo {
    sensorId: string;
    sensorType: sensor.SensorType;
    sensorName: string;
    deviceId: string;
    deviceName: string;
    isLocal: boolean;
    capabilities: SensorCapabilities;
}

interface SensorCapabilities {
    maxSamplingRate?: number;
    minDelay?: number;
    resolution?: number;
    power?: number;
}

interface SubscribeOptions {
    samplingInterval?: number;  // 纳秒
    transportMode?: 'realtime' | 'batch' | 'ondemand';
    batchSize?: number;
}

interface SensorData {
    sensorType: sensor.SensorType;
    values: number[];
    timestamp: number;
    accuracy?: number;
    sourceDevice?: string;
}

interface FusedSensorData {
    timestamp: number;
    dataType: string;
    values: number[];
    accuracy: number;
    sourceSensors: string[];
}

interface FusionOptions {
    syncWindow?: number;
    algorithm?: 'kalman' | 'complementary' | 'average';
}

示例二:跨设备运动追踪

使用多个设备的传感器进行运动追踪,提高精度和覆盖范围。

// CrossDeviceMotionTracking.ets
import distributedSensor from '@ohos.distributedSensor';

export class CrossDeviceMotionTracking {
    // 设备传感器配置
    private deviceSensors: Map<string, DeviceSensorConfig> = new Map();
    
    // 运动追踪器
    private motionTracker: MotionTracker | null = null;
    
    // 追踪状态
    private trackingState: TrackingState = {
        isTracking: false,
        position: { x: 0, y: 0, z: 0 },
        velocity: { x: 0, y: 0, z: 0 },
        orientation: { pitch: 0, roll: 0, yaw: 0 }
    };

    // 初始化运动追踪
    async initializeTracking(devices: DeviceConfig[]): Promise<void> {
        console.info('[MotionTracking] Initializing');
        
        // 创建运动追踪器
        this.motionTracker = new MotionTracker();
        
        // 为每个设备配置传感器
        for (const device of devices) {
            await this.setupDeviceSensors(device);
        }
        
        // 设置融合算法
        this.motionTracker.setFusionAlgorithm('kalman');
    }

    // 设置设备传感器
    private async setupDeviceSensors(device: DeviceConfig): Promise<void> {
        console.info('[MotionTracking] Setting up device:', device.deviceId);
        
        const sensorTypes = device.sensorTypes || [
            sensor.SensorType.ACCELEROMETER,
            sensor.SensorType.GYROSCOPE
        ];
        
        const subscribers: SensorSubscriber[] = [];
        
        for (const type of sensorTypes) {
            // 创建传感器代理
            const proxy = await distributedSensor.createSensorProxy({
                sourceDeviceId: device.deviceId,
                sensorType: type
            });
            
            // 订阅数据
            await proxy.subscribe({ samplingRate: 50 }, (data) => {
                this.motionTracker?.addSensorData({
                    deviceId: device.deviceId,
                    sensorType: type,
                    data: data,
                    timestamp: Date.now()
                });
            });
            
            subscribers.push({ sensorType: type, proxy: proxy });
        }
        
        // 保存配置
        this.deviceSensors.set(device.deviceId, {
            deviceId: device.deviceId,
            deviceName: device.deviceName,
            subscribers: subscribers,
            weight: device.weight || 1.0
        });
    }

    // 开始追踪
    async startTracking(): Promise<void> {
        console.info('[MotionTracking] Starting tracking');
        
        this.trackingState.isTracking = true;
        
        // 设置追踪结果回调
        this.motionTracker?.onTrackingUpdate((result: TrackingResult) => {
            this.trackingState.position = result.position;
            this.trackingState.velocity = result.velocity;
            this.trackingState.orientation = result.orientation;
            
            // 通知UI更新
            this.notifyTrackingUpdate(result);
        });
        
        // 开始追踪
        this.motionTracker?.start();
    }

    // 停止追踪
    async stopTracking(): Promise<void> {
        console.info('[MotionTracking] Stopping tracking');
        
        this.trackingState.isTracking = false;
        this.motionTracker?.stop();
    }

    // 获取当前位置
    getCurrentPosition(): Position3D {
        return { ...this.trackingState.position };
    }

    // 获取当前姿态
    getCurrentOrientation(): Orientation {
        return { ...this.trackingState.orientation };
    }

    // 获取追踪历史
    getTrackingHistory(duration: number): TrackingPoint[] {
        return this.motionTracker?.getHistory(duration) || [];
    }

    // 通知追踪更新
    private notifyTrackingUpdate(result: TrackingResult): void {
        AppStorage.setOrCreate('trackingPosition', result.position);
        AppStorage.setOrCreate('trackingOrientation', result.orientation);
    }
}

// 运动追踪器
class MotionTracker {
    private isRunning: boolean = false;
    private fusionAlgorithm: FusionAlgorithm | null = null;
    private updateCallback: ((result: TrackingResult) => void) | null = null;
    
    // 状态估计
    private stateEstimate: StateEstimate = {
        position: { x: 0, y: 0, z: 0 },
        velocity: { x: 0, y: 0, z: 0 },
        orientation: { pitch: 0, roll: 0, yaw: 0 },
        angularVelocity: { x: 0, y: 0, z: 0 }
    };
    
    // 历史数据
    private history: TrackingPoint[] = [];
    private maxHistory: number = 1000;

    // 添加传感器数据
    addSensorData(data: SensorDataWithDevice): void {
        if (!this.isRunning) return;
        
        // 根据传感器类型处理
        switch (data.sensorType) {
            case sensor.SensorType.ACCELEROMETER:
                this.processAccelerometer(data);
                break;
            case sensor.SensorType.GYROSCOPE:
                this.processGyroscope(data);
                break;
            case sensor.SensorType.LOCATION:
                this.processLocation(data);
                break;
        }
    }

    // 处理加速度计数据
    private processAccelerometer(data: SensorDataWithDevice): void {
        const accel = data.data.values;
        
        // 去除重力分量
        const gravity = this.estimateGravity();
        const linearAccel = {
            x: accel[0] - gravity.x,
            y: accel[1] - gravity.y,
            z: accel[2] - gravity.z
        };
        
        // 积分得到速度和位置
        const dt = 0.02;  // 20ms
        this.stateEstimate.velocity.x += linearAccel.x * dt;
        this.stateEstimate.velocity.y += linearAccel.y * dt;
        this.stateEstimate.velocity.z += linearAccel.z * dt;
        
        this.stateEstimate.position.x += this.stateEstimate.velocity.x * dt;
        this.stateEstimate.position.y += this.stateEstimate.velocity.y * dt;
        this.stateEstimate.position.z += this.stateEstimate.velocity.z * dt;
        
        // 触发更新
        this.emitUpdate();
    }

    // 处理陀螺仪数据
    private processGyroscope(data: SensorDataWithDevice): void {
        const gyro = data.data.values;
        
        // 更新角速度
        this.stateEstimate.angularVelocity = {
            x: gyro[0],
            y: gyro[1],
            z: gyro[2]
        };
        
        // 积分得到姿态
        const dt = 0.02;
        this.stateEstimate.orientation.pitch += gyro[0] * dt;
        this.stateEstimate.orientation.roll += gyro[1] * dt;
        this.stateEstimate.orientation.yaw += gyro[2] * dt;
        
        this.emitUpdate();
    }

    // 处理GPS数据
    private processLocation(data: SensorDataWithDevice): void {
        const location = data.data.values;
        
        // GPS数据直接更新位置
        this.stateEstimate.position = {
            x: location[0],  // 经度
            y: location[1],  // 纬度
            z: location[2]   // 高度
        };
        
        this.emitUpdate();
    }

    // 估计重力方向
    private estimateGravity(): Vector3D {
        // 使用姿态估计重力方向
        const g = 9.8;
        const { pitch, roll } = this.stateEstimate.orientation;
        
        return {
            x: g * Math.sin(roll),
            y: -g * Math.sin(pitch) * Math.cos(roll),
            z: -g * Math.cos(pitch) * Math.cos(roll)
        };
    }

    // 发送更新
    private emitUpdate(): void {
        if (!this.updateCallback) return;
        
        const result: TrackingResult = {
            timestamp: Date.now(),
            position: { ...this.stateEstimate.position },
            velocity: { ...this.stateEstimate.velocity },
            orientation: { ...this.stateEstimate.orientation }
        };
        
        // 记录历史
        this.history.push({
            timestamp: result.timestamp,
            position: result.position,
            orientation: result.orientation
        });
        
        if (this.history.length > this.maxHistory) {
            this.history.shift();
        }
        
        this.updateCallback(result);
    }

    // 开始追踪
    start(): void {
        this.isRunning = true;
    }

    // 停止追踪
    stop(): void {
        this.isRunning = false;
    }

    // 设置融合算法
    setFusionAlgorithm(algorithm: 'kalman' | 'complementary'): void {
        // 实际实现需要创建对应的融合算法实例
    }

    // 设置更新回调
    onTrackingUpdate(callback: (result: TrackingResult) => void): void {
        this.updateCallback = callback;
    }

    // 获取历史数据
    getHistory(duration: number): TrackingPoint[] {
        const now = Date.now();
        return this.history.filter(p => now - p.timestamp < duration);
    }
}

// 接口定义
interface DeviceSensorConfig {
    deviceId: string;
    deviceName: string;
    subscribers: SensorSubscriber[];
    weight: number;
}

interface SensorSubscriber {
    sensorType: sensor.SensorType;
    proxy: distributedSensor.SensorProxy;
}

interface TrackingState {
    isTracking: boolean;
    position: Position3D;
    velocity: Vector3D;
    orientation: Orientation;
}

interface Position3D {
    x: number;
    y: number;
    z: number;
}

interface Vector3D {
    x: number;
    y: number;
    z: number;
}

interface Orientation {
    pitch: number;
    roll: number;
    yaw: number;
}

interface SensorDataWithDevice {
    deviceId: string;
    sensorType: sensor.SensorType;
    data: SensorData;
    timestamp: number;
}

interface TrackingResult {
    timestamp: number;
    position: Position3D;
    velocity: Vector3D;
    orientation: Orientation;
}

interface TrackingPoint {
    timestamp: number;
    position: Position3D;
    orientation: Orientation;
}

interface StateEstimate {
    position: Position3D;
    velocity: Vector3D;
    orientation: Orientation;
    angularVelocity: Vector3D;
}

interface DeviceConfig {
    deviceId: string;
    deviceName: string;
    sensorTypes?: sensor.SensorType[];
    weight?: number;
}

示例三:环境感知与智能响应

使用分布式环境传感器实现智能场景响应。

// EnvironmentAwareSystem.ets
import distributedSensor from '@ohos.distributedSensor';

export class EnvironmentAwareSystem {
    // 环境传感器订阅
    private environmentSensors: Map<string, distributedSensor.SensorProxy> = new Map();
    
    // 环境状态
    private environmentState: EnvironmentState = {
        lightLevel: 0,
        temperature: 0,
        humidity: 0,
        noiseLevel: 0,
        userPresence: false
    };
    
    // 场景规则
    private sceneRules: SceneRule[] = [];

    // 初始化环境感知
    async initialize(): Promise<void> {
        console.info('[EnvironmentAware] Initializing');
        
        // 订阅环境传感器
        await this.subscribeEnvironmentSensors();
        
        // 加载场景规则
        this.loadSceneRules();
    }

    // 订阅环境传感器
    private async subscribeEnvironmentSensors(): Promise<void> {
        // 发现所有环境传感器
        const sensors = await this.discoverEnvironmentSensors();
        
        for (const sensorInfo of sensors) {
            try {
                const proxy = await distributedSensor.createSensorProxy({
                    sourceDeviceId: sensorInfo.deviceId,
                    sensorType: sensorInfo.sensorType
                });
                
                await proxy.subscribe({ samplingRate: 1 }, (data) => {
                    this.handleEnvironmentData(sensorInfo.sensorType, data);
                });
                
                this.environmentSensors.set(sensorInfo.sensorId, proxy);
            } catch (error) {
                console.error('[EnvironmentAware] Subscribe failed:', error);
            }
        }
    }

    // 发现环境传感器
    private async discoverEnvironmentSensors(): Promise<SensorInfo[]> {
        // 实际实现需要查询所有设备的环境传感器
        return [];
    }

    // 处理环境数据
    private handleEnvironmentData(sensorType: sensor.SensorType, data: SensorData): void {
        switch (sensorType) {
            case sensor.SensorType.LIGHT:
                this.environmentState.lightLevel = data.values[0];
                break;
            case sensor.SensorType.AMBIENT_TEMPERATURE:
                this.environmentState.temperature = data.values[0];
                break;
            case sensor.SensorType.RELATIVE_HUMIDITY:
                this.environmentState.humidity = data.values[0];
                break;
        }
        
        // 检查场景规则
        this.evaluateSceneRules();
    }

    // 加载场景规则
    private loadSceneRules(): void {
        this.sceneRules = [
            {
                name: '夜间模式',
                condition: (state) => state.lightLevel < 10,
                action: () => this.applyNightMode()
            },
            {
                name: '节能模式',
                condition: (state) => state.temperature > 28,
                action: () => this.applyPowerSavingMode()
            },
            {
                name: '舒适模式',
                condition: (state) => 
                    state.temperature >= 20 && 
                    state.temperature <= 26 &&
                    state.humidity >= 40 &&
                    state.humidity <= 60,
                action: () => this.applyComfortMode()
            }
        ];
    }

    // 评估场景规则
    private evaluateSceneRules(): void {
        for (const rule of this.sceneRules) {
            if (rule.condition(this.environmentState)) {
                console.info('[EnvironmentAware] Triggering rule:', rule.name);
                rule.action();
            }
        }
    }

    // 应用夜间模式
    private applyNightMode(): void {
        console.info('[EnvironmentAware] Applying night mode');
        // 降低亮度、启用护眼模式等
    }

    // 应用节能模式
    private applyPowerSavingMode(): void {
        console.info('[EnvironmentAware] Applying power saving mode');
        // 降低性能、减少后台活动等
    }

    // 应用舒适模式
    private applyComfortMode(): void {
        console.info('[EnvironmentAware] Applying comfort mode');
        // 调整显示、音量等到舒适水平
    }
}

// 接口定义
interface EnvironmentState {
    lightLevel: number;
    temperature: number;
    humidity: number;
    noiseLevel: number;
    userPresence: boolean;
}

interface SceneRule {
    name: string;
    condition: (state: EnvironmentState) => boolean;
    action: () => void;
}

踰坑与注意事项

坑一:传感器数据时间戳不同步

问题描述:不同设备的传感器数据时间戳基准不同,导致融合时时间对齐错误。

解决方案:使用NTP或PTP进行时间同步

// 时间同步器
class TimeSynchronizer {
    private offsets: Map<string, number> = new Map();
    
    // 测量时间偏移
    async measureOffset(deviceId: string): Promise<number> {
        const t1 = Date.now();
        
        // 向远程设备发送时间查询
        const remoteTime = await this.queryRemoteTime(deviceId);
        
        const t2 = Date.now();
        
        // 计算往返延迟和偏移
        const rtt = t2 - t1;
        const offset = remoteTime - (t1 + rtt / 2);
        
        this.offsets.set(deviceId, offset);
        
        return offset;
    }
    
    // 转换时间戳
    convertTimestamp(deviceId: string, remoteTimestamp: number): number {
        const offset = this.offsets.get(deviceId) || 0;
        return remoteTimestamp - offset;
    }
}

坑二:传感器数据噪声

问题描述:传感器数据存在噪声,直接使用会导致结果抖动。

解决方案:使用滤波器

// 低通滤波器
class LowPassFilter {
    private alpha: number;
    private lastValue: number[] | null = null;
    
    constructor(alpha: number = 0.1) {
        this.alpha = alpha;
    }
    
    filter(values: number[]): number[] {
        if (this.lastValue === null) {
            this.lastValue = values;
            return values;
        }
        
        const filtered = values.map((v, i) => {
            return this.alpha * v + (1 - this.alpha) * this.lastValue![i];
        });
        
        this.lastValue = filtered;
        return filtered;
    }
}

// 卡尔曼滤波器(简化版)
class SimpleKalmanFilter {
    private Q: number = 0.01;  // 过程噪声
    private R: number = 0.1;   // 测量噪声
    private P: number = 1;     // 估计误差
    private X: number = 0;     // 估计值
    
    update(measurement: number): number {
        // 预测
        const P_predict = this.P + this.Q;
        
        // 更新
        const K = P_predict / (P_predict + this.R);
        this.X = this.X + K * (measurement - this.X);
        this.P = (1 - K) * P_predict;
        
        return this.X;
    }
}

坑三:传感器漂移

问题描述:长时间使用后,传感器数据出现漂移,如陀螺仪零点漂移。

解决方案:定期校准

// 传感器校准器
class SensorCalibrator {
    // 零点偏移
    private zeroOffsets: Map<string, number[]> = new Map();
    
    // 执行零点校准
    async calibrateZeroPoint(
        sensorId: string, 
        duration: number = 3000
    ): Promise<void> {
        console.info('[Calibrator] Calibrating zero point for:', sensorId);
        
        // 收集静止状态下的数据
        const samples: number[][] = [];
        
        // 假设已经订阅传感器,收集数据
        // 实际实现需要等待数据回调
        
        await this.sleep(duration);
        
        // 计算平均值作为零点偏移
        if (samples.length > 0) {
            const avg = this.calculateAverage(samples);
            this.zeroOffsets.set(sensorId, avg);
            
            console.info('[Calibrator] Zero offset:', avg);
        }
    }
    
    // 应用校准
    applyCalibration(sensorId: string, values: number[]): number[] {
        const offset = this.zeroOffsets.get(sensorId);
        if (!offset) return values;
        
        return values.map((v, i) => v - offset[i]);
    }
    
    private calculateAverage(samples: number[][]): number[] {
        const count = samples.length;
        const dims = samples[0].length;
        const avg: number[] = new Array(dims).fill(0);
        
        for (const sample of samples) {
            for (let i = 0; i < dims; i++) {
                avg[i] += sample[i];
            }
        }
        
        return avg.map(v => v / count);
    }
    
    private sleep(ms: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

HarmonyOS 6适配

新增传感器数据流API

// 使用数据流API订阅传感器
const stream = distributedSensor.createSensorStream({
    sensorType: sensor.SensorType.ACCELEROMETER,
    deviceId: 'remote_device_id',
    config: {
        samplingRate: 100,
        bufferSize: 1000
    }
});

// 使用ReadableStream接口
const reader = stream.getReader();

while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    console.info('Sensor data:', value);
}

增强的传感器元数据

// 获取详细传感器信息
const sensorInfo = await distributedSensor.getDetailedSensorInfo(sensorId);

console.info('Sensor name:', sensorInfo.name);
console.info('Vendor:', sensorInfo.vendor);
console.info('Version:', sensorInfo.version);
console.info('Max range:', sensorInfo.maxRange);
console.info('Resolution:', sensorInfo.resolution);
console.info('Power:', sensorInfo.power, 'mA');
console.info('Min delay:', sensorInfo.minDelay, 'us');
console.info('Max delay:', sensorInfo.maxDelay, 'us');
console.info('Fifo reserved:', sensorInfo.fifoReservedEventCount);
console.info('Fifo max:', sensorInfo.fifoMaxEventCount);

传感器数据批处理

// 配置批处理模式
await proxy.subscribe({
    samplingRate: 100,
    batchConfig: {
        enabled: true,
        maxBatchSize: 100,      // 最多100个样本
        maxBatchDelay: 100      // 最多延迟100ms
    }
}, (batch: SensorDataBatch) => {
    console.info('Received batch with', batch.data.length, 'samples');
    
    for (const data of batch.data) {
        // 处理批量数据
    }
});

总结

分布式传感器让传感器数据突破了设备的物理限制,一个设备可以使用整个"超级终端"上所有可用的传感器。无论是使用远程的心率传感器、融合多设备的运动数据,还是构建环境感知系统,都为应用提供了更丰富的感知能力。

核心要点

  1. 传感器发现与查询:自动发现本地和远程传感器
  2. 传感器代理:透明地使用远程传感器
  3. 传感器融合:整合多个传感器的数据提高精度
  4. 数据传输优化:压缩、批处理等策略减少传输开销

最佳实践

  • 处理时间戳同步问题
  • 使用滤波器减少噪声影响
  • 定期校准传感器消除漂移
  • 根据应用需求选择合适的采样率和传输模式
  • 善用传感器融合提高数据质量

分布式传感器是HarmonyOS分布式能力的重要组成,下一篇我们将探讨分布式位置服务,看看如何实现跨设备的定位能力。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。