HarmonyOS分布式传感器开发小知识
背景与动机
你有没有遇到过这种场景:用平板做运动监测,但平板没有心率传感器;或者在车里用手机导航,想用车载的GPS获得更精准的定位;又或者在玩游戏时,想用手表的陀螺仪来控制视角。
这就是分布式传感器要解决的问题——让传感器数据可以跨设备共享,一个设备可以使用另一个设备的传感器。
不同设备的传感器配置差异很大。手机通常有加速度计、陀螺仪、GPS、心率传感器等;平板可能缺少心率传感器;电视可能只有简单的环境光传感器;手表则可能有更丰富的健康传感器。分布式传感器打破了这种限制,让应用可以使用"整个超级终端"上所有可用的传感器。
核心原理
分布式传感器架构
分布式传感器基于以下几个核心概念:
- SensorProvider:传感器提供者,声明本设备的传感器能力
- SensorProxy:传感器代理,在远程设备上代表传感器实例
- SensorDataChannel:传感器数据通道,负责数据传输
- 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) {
// 处理批量数据
}
});
总结
分布式传感器让传感器数据突破了设备的物理限制,一个设备可以使用整个"超级终端"上所有可用的传感器。无论是使用远程的心率传感器、融合多设备的运动数据,还是构建环境感知系统,都为应用提供了更丰富的感知能力。
核心要点:
- 传感器发现与查询:自动发现本地和远程传感器
- 传感器代理:透明地使用远程传感器
- 传感器融合:整合多个传感器的数据提高精度
- 数据传输优化:压缩、批处理等策略减少传输开销
最佳实践:
- 处理时间戳同步问题
- 使用滤波器减少噪声影响
- 定期校准传感器消除漂移
- 根据应用需求选择合适的采样率和传输模式
- 善用传感器融合提高数据质量
分布式传感器是HarmonyOS分布式能力的重要组成,下一篇我们将探讨分布式位置服务,看看如何实现跨设备的定位能力。
- 点赞
- 收藏
- 关注作者
评论(0)