Harmony开发之设备发现与连接——分布式操作的起点

Harmony开发之设备发现与连接——分布式操作的起点

引入:自动发现附近可用设备

想象一下这样的场景:当你走进家门,手机自动发现并连接上家里的智能音响,开始播放你喜欢的音乐;当你在会议室做演示时,平板自动发现投影仪并建立连接,无需繁琐的线缆连接和设置。这种"开机即连"的无缝体验,正是HarmonyOS设备发现与连接技术带来的革命性变化。作为分布式操作的起点,设备发现与连接为多设备协同奠定了坚实基础。

一、设备发现与连接的核心价值

传统设备连接的痛点

在传统的IoT设备连接中,用户需要手动进入配对模式、搜索可用设备、手动选择目标并输入密码,这个过程不仅繁琐,还容易因操作失误导致连接失败。

HarmonyOS的解决方案

HarmonyOS通过分布式软总线技术,实现了设备的自动发现和透明连接。设备开机后自动广播自身信息,系统扫描到符合条件的设备自动发起连接,分布式能力完成跨设备数据传输和协作。

核心优势对比:

  • 自动发现:无需手动搜索,设备自动相互识别
  • 智能过滤:基于设备能力、账户关系等条件精准匹配
  • 安全认证:多重认证机制确保连接安全性
  • 多协议支持:统一抽象层支持蓝牙、Wi-Fi等多种通信方式

二、技术架构与核心组件

2.1 分布式软总线基础

分布式软总线(DSoftBus)是HarmonyOS分布式系统的神经网络,承载着设备发现、连接建立、数据传输等关键功能。它采用分层架构设计,位于HarmonyOS系统服务层,为上层应用提供统一的分布式通信能力。

核心模块组成:

  • 发现模块:负责检测附近的HarmonyOS设备,使用CoAP等协议进行轻量级传输
  • 连接管理模块:处理设备间连接的建立和维护
  • 传输模块:提供多种数据类型的传输能力
  • 安全模块:内置安全认证和数据加密机制

2.2 设备管理核心接口

HarmonyOS提供了@ohos.distributedHardware.deviceManager模块来完成设备管理功能,主要包括:

// 设备管理核心接口
interface DeviceManager {
  createDeviceManager(bundleName: string, callback: AsyncCallback<DeviceManager>): void;
  startDeviceDiscovery(subscribeId: number, options: DiscoverOptions): void;
  authenticateDevice(deviceId: string, authParam: AuthParam, callback: AsyncCallback<void>): void;
  getAvailableDeviceListSync(): DeviceInfo[];
}

三、设备发现实战开发

3.1 权限配置与初始化

在开始设备发现前,需要配置必要的权限并初始化设备管理实例。

权限配置(module.json5):

{
  "reqPermissions": [
    { 
      "name": "ohos.permission.DISTRIBUTED_DATASYNC",
      "reason": "用于设备发现和数据同步" 
    },
    { 
      "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE",
      "reason": "监听设备状态变化" 
    },
    { 
      "name": "ohos.permission.DISCOVER_BLUETOOTH",
      "reason": "蓝牙设备发现" 
    },
    { 
      "name": "ohos.permission.LOCATION",
      "reason": "位置权限用于设备发现" 
    }
  ]
}

设备管理初始化:

import deviceManager from '@ohos.distributedHardware.deviceManager';
import { BusinessError } from '@ohos.BasicServicesKit';

let dmInstance: deviceManager.DeviceManager | null = null;

// 创建设备管理实例
function initDeviceManager(): void {
  try {
    deviceManager.createDeviceManager('com.example.myapp', (err: BusinessError, data: deviceManager.DeviceManager) => {
      if (err) {
        console.error('DeviceManager create failed: ' + JSON.stringify(err));
        return;
      }
      dmInstance = data;
      console.info('DeviceManager created successfully');
      setupDeviceDiscovery();
    });
  } catch (error) {
    console.error('Init DeviceManager error: ' + JSON.stringify(error));
  }
}

3.2 启动设备发现

配置发现参数并启动设备扫描过程。

function setupDeviceDiscovery(): void {
  if (!dmInstance) {
    return;
  }

  // 配置发现参数
  const discoverOptions: deviceManager.DiscoverOptions = {
    subscribeId: 1001, // 订阅ID
    mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE, // 主动发现模式
    medium: deviceManager.ExchangeMedium.COAP, // 使用CoAP协议
    freq: deviceManager.ExchangeFreq.HIGH, // 高频发现
    isSameAccount: true, // 同一账户设备
    isWakeRemote: true, // 唤醒远程设备
    capability: deviceManager.Capability.OSD // 设备能力过滤
  };

  // 启动设备发现
  dmInstance.startDeviceDiscovery(discoverOptions);
  
  // 注册设备发现回调
  registerDeviceCallbacks();
}

function registerDeviceCallbacks(): void {
  if (!dmInstance) {
    return;
  }

  // 监听设备发现事件
  dmInstance.on('deviceFound', (data: deviceManager.DeviceInfo) => {
    console.info('Device found: ' + JSON.stringify(data));
    handleFoundDevice(data);
  });

  // 监听设备状态变化
  dmInstance.on('deviceStateChange', (data: deviceManager.DeviceStateInfo) => {
    console.info('Device state changed: ' + JSON.stringify(data));
    handleDeviceStateChange(data);
  });

  // 监听发现失败事件
  dmInstance.on('discoverFail', (reason: string) => {
    console.error('Discovery failed: ' + reason);
  });
}

3.3 设备过滤与识别

发现设备后需要进行过滤和识别,确保只连接目标设备。

function handleFoundDevice(deviceInfo: deviceManager.DeviceInfo): void {
  // 基础设备信息验证
  if (!deviceInfo.deviceId || !deviceInfo.deviceName) {
    console.warn('Invalid device info');
    return;
  }

  // 设备类型过滤(只连接手机、平板、智慧屏等)
  const allowedTypes = [
    deviceManager.DeviceType.PHONE,
    deviceManager.DeviceType.TABLET,
    deviceManager.DeviceType.TV
  ];
  
  if (!allowedTypes.includes(deviceInfo.deviceType)) {
    console.info('Skip device type: ' + deviceInfo.deviceType);
    return;
  }

  // 设备能力验证
  if (!hasRequiredCapability(deviceInfo)) {
    console.info('Device does not have required capability');
    return;
  }

  // 设备可信状态检查
  if (isTrustedDevice(deviceInfo.deviceId)) {
    console.info('Found trusted device: ' + deviceInfo.deviceName);
    onTrustedDeviceFound(deviceInfo);
  } else {
    console.info('Found untrusted device: ' + deviceInfo.deviceName);
    onUntrustedDeviceFound(deviceInfo);
  }
}

// 检查设备是否具备所需能力
function hasRequiredCapability(deviceInfo: deviceManager.DeviceInfo): boolean {
  // 这里可以根据业务需求检查设备能力
  return deviceInfo.capabilityBitmap.includes(deviceManager.Capability.OSD);
}

// 检查设备是否已认证
function isTrustedDevice(deviceId: string): boolean {
  // 从本地存储或系统服务中检查设备可信状态
  const trustedDevices = getTrustedDevicesFromStorage();
  return trustedDevices.includes(deviceId);
}

四、设备认证与连接建立

4.1 设备认证流程

发现目标设备后,需要建立安全连接,认证是确保设备可信的关键步骤。

// 设备认证参数配置
interface AuthConfig {
  authType: deviceManager.AuthType;
  appName: string;
  extraInfo?: Record<string, Object>;
}

function authenticateDevice(deviceInfo: deviceManager.DeviceInfo): void {
  if (!dmInstance) {
    return;
  }

  const authConfig: AuthConfig = {
    authType: deviceManager.AuthType.PIN_CODE, // PIN码认证
    appName: 'MyDistributedApp',
    extraInfo: {
      'authTimeout': 30000, // 30秒超时
      'maxRetryCount': 3    // 最大重试次数
    }
  };

  const authParam: deviceManager.AuthParam = {
    authType: authConfig.authType,
    appName: authConfig.appName,
    extraInfo: authConfig.extraInfo
  };

  dmInstance.authenticateDevice(deviceInfo.deviceId, authParam, (err: BusinessError) => {
    if (err) {
      console.error('Authentication failed: ' + JSON.stringify(err));
      handleAuthFailure(deviceInfo.deviceId, err);
      return;
    }
    
    console.info('Authentication successful for device: ' + deviceInfo.deviceName);
    handleAuthSuccess(deviceInfo);
  });
}

// 认证成功处理
function handleAuthSuccess(deviceInfo: deviceManager.DeviceInfo): void {
  // 保存设备可信状态
  saveTrustedDevice(deviceInfo.deviceId);
  
  // 建立业务连接
  establishBusinessConnection(deviceInfo);
  
  // 更新UI状态
  updateDeviceConnectionStatus(deviceInfo.deviceId, 'connected');
}

// 认证失败处理
function handleAuthFailure(deviceId: string, error: BusinessError): void {
  console.error('Device authentication failed: ', error);
  
  // 根据错误码进行相应处理
  switch (error.code) {
    case 201: // 权限错误
      requestMissingPermissions();
      break;
    case 202: // 设备不支持
      showDeviceNotSupportedToast();
      break;
    case 203: // 认证超时
      retryAuthentication(deviceId);
      break;
    default:
      showAuthenticationErrorToast();
  }
}

4.2 连接管理与状态维护

建立连接后需要维护连接状态和处理异常情况。

class DeviceConnectionManager {
  private connectedDevices: Map<string, deviceManager.DeviceInfo> = new Map();
  private connectionListeners: Set<ConnectionListener> = new Set();
  
  // 添加设备到连接池
  addConnectedDevice(deviceInfo: deviceManager.DeviceInfo): void {
    this.connectedDevices.set(deviceInfo.deviceId, deviceInfo);
    this.notifyConnectionChange('connected', deviceInfo);
  }
  
  // 移除设备连接
  removeConnectedDevice(deviceId: string): void {
    const deviceInfo = this.connectedDevices.get(deviceId);
    if (deviceInfo) {
      this.connectedDevices.delete(deviceId);
      this.notifyConnectionChange('disconnected', deviceInfo);
    }
  }
  
  // 获取所有已连接设备
  getConnectedDevices(): deviceManager.DeviceInfo[] {
    return Array.from(this.connectedDevices.values());
  }
  
  // 注册连接状态监听
  addConnectionListener(listener: ConnectionListener): void {
    this.connectionListeners.add(listener);
  }
  
  // 通知连接状态变化
  private notifyConnectionChange(status: 'connected' | 'disconnected', deviceInfo: deviceManager.DeviceInfo): void {
    this.connectionListeners.forEach(listener => {
      try {
        listener.onDeviceConnectionChanged(status, deviceInfo);
      } catch (error) {
        console.error('Connection listener error: ', error);
      }
    });
  }
  
  // 清理资源
  cleanup(): void {
    this.connectedDevices.clear();
    this.connectionListeners.clear();
  }
}

// 使用示例
const connectionManager = new DeviceConnectionManager();

// 添加连接状态监听
connectionManager.addConnectionListener({
  onDeviceConnectionChanged: (status, deviceInfo) => {
    console.info(`Device ${deviceInfo.deviceName} ${status}`);
    updateDeviceListUI();
  }
});

五、完整实战案例:多设备音乐共享

5.1 场景描述

实现一个多设备音乐共享应用,手机作为控制中心,可以自动发现附近的音响设备并建立连接,实现音乐的无缝切换和播放。

5.2 核心实现

// 音乐设备管理器
class MusicDeviceManager {
  private deviceManager: deviceManager.DeviceManager | null = null;
  private musicDevices: Map<string, MusicDevice> = new Map();
  
  // 初始化音乐设备管理
  async initialize(): Promise<void> {
    try {
      this.deviceManager = await this.createDeviceManager();
      this.setupDeviceDiscovery();
      this.setupEventListeners();
    } catch (error) {
      console.error('MusicDeviceManager initialization failed: ', error);
    }
  }
  
  // 创建设备管理器
  private createDeviceManager(): Promise<deviceManager.DeviceManager> {
    return new Promise((resolve, reject) => {
      deviceManager.createDeviceManager('com.example.musicapp', (err, manager) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(manager);
      });
    });
  }
  
  // 设置设备发现
  private setupDeviceDiscovery(): void {
    if (!this.deviceManager) {
      return;
    }
    
    const options: deviceManager.DiscoverOptions = {
      subscribeId: 2001,
      mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
      medium: deviceManager.ExchangeMedium.COAP,
      freq: deviceManager.ExchangeFreq.NORMAL,
      isSameAccount: false, // 允许不同账户设备
      capability: deviceManager.Capability.AUDIO_PLAYBACK
    };
    
    this.deviceManager.startDeviceDiscovery(options);
  }
  
  // 处理发现的音乐设备
  private handleMusicDeviceFound(deviceInfo: deviceManager.DeviceInfo): void {
    // 检查是否支持音乐播放能力
    if (this.isMusicPlaybackDevice(deviceInfo)) {
      const musicDevice: MusicDevice = {
        deviceId: deviceInfo.deviceId,
        deviceName: deviceInfo.deviceName,
        deviceType: deviceInfo.deviceType,
        capabilities: this.getDeviceCapabilities(deviceInfo),
        connectionStatus: 'discovered'
      };
      
      this.musicDevices.set(deviceInfo.deviceId, musicDevice);
      this.onMusicDeviceDiscovered(musicDevice);
    }
  }
  
  // 连接到音乐设备
  async connectToMusicDevice(deviceId: string): Promise<void> {
    const device = this.musicDevices.get(deviceId);
    if (!device) {
      throw new Error('Device not found');
    }
    
    try {
      // 先进行设备认证
      await this.authenticateDevice(deviceId);
      
      // 建立音乐传输通道
      await this.establishMusicChannel(deviceId);
      
      device.connectionStatus = 'connected';
      this.onMusicDeviceConnected(device);
      
    } catch (error) {
      device.connectionStatus = 'error';
      this.onMusicDeviceConnectionFailed(device, error);
      throw error;
    }
  }
  
  // 播放音乐到指定设备
  async playMusicToDevice(deviceId: string, musicData: MusicData): Promise<void> {
    const device = this.musicDevices.get(deviceId);
    if (!device || device.connectionStatus !== 'connected') {
      throw new Error('Device not connected');
    }
    
    try {
      // 传输音乐数据
      await this.transferMusicData(deviceId, musicData);
      
      // 发送播放命令
      await this.sendPlayCommand(deviceId);
      
      console.info(`Music playing on ${device.deviceName}`);
      
    } catch (error) {
      console.error('Music playback failed: ', error);
      throw error;
    }
  }
}

// 使用示例
const musicManager = new MusicDeviceManager();

// 初始化并开始发现设备
musicManager.initialize().then(() => {
  console.info('Music device manager ready');
});

六、性能优化与最佳实践

6.1 发现性能优化

设备发现过程需要平衡功耗和发现效率。

// 智能发现策略
class SmartDiscoveryStrategy {
  private discoveryIntervals: Map<deviceManager.ExchangeFreq, number> = new Map([
    [deviceManager.ExchangeFreq.HIGH, 5000],    // 高频:5秒
    [deviceManager.ExchangeFreq.NORMAL, 15000],  // 正常:15秒
    [deviceManager.ExchangeFreq.LOW, 30000]      // 低频:30秒
  ]);
  
  // 根据应用状态调整发现频率
  adjustDiscoveryFrequency(appState: 'foreground' | 'background'): deviceManager.ExchangeFreq {
    switch (appState) {
      case 'foreground':
        return deviceManager.ExchangeFreq.HIGH;
      case 'background':
        return deviceManager.ExchangeFreq.LOW;
      default:
        return deviceManager.ExchangeFreq.NORMAL;
    }
  }
  
  // 设备发现限流
  throttleDeviceDiscovery(discoveryCallback: () => void): () => void {
    let lastCallTime = 0;
    const throttleDelay = 2000; // 2秒限流
    
    return () => {
      const now = Date.now();
      if (now - lastCallTime > throttleDelay) {
        lastCallTime = now;
        discoveryCallback();
      }
    };
  }
}

6.2 连接池管理

对于需要维护多个设备连接的应用,连接池管理至关重要。

// 设备连接池管理
class DeviceConnectionPool {
  private connections: Map<string, DeviceConnection> = new Map();
  private maxConnections = 5; // 最大连接数
  
  // 添加连接
  addConnection(deviceId: string, connection: DeviceConnection): boolean {
    if (this.connections.size >= this.maxConnections) {
      // 连接数已达上限,清理最不活跃的连接
      this.cleanupInactiveConnections();
    }
    
    if (this.connections.size < this.maxConnections) {
      this.connections.set(deviceId, connection);
      return true;
    }
    
    return false;
  }
  
  // 清理不活跃连接
  private cleanupInactiveConnections(): void {
    const now = Date.now();
    const inactiveThreshold = 5 * 60 * 1000; // 5分钟
    
    for (const [deviceId, connection] of this.connections) {
      if (now - connection.lastActiveTime > inactiveThreshold) {
        connection.close();
        this.connections.delete(deviceId);
      }
    }
  }
  
  // 获取活跃连接数
  getActiveConnectionCount(): number {
    let count = 0;
    for (const connection of this.connections.values()) {
      if (connection.isActive()) {
        count++;
      }
    }
    return count;
  }
}

七、常见问题与解决方案

7.1 设备发现失败处理

// 设备发现故障排除
class DiscoveryTroubleshooter {
  // 检查发现失败原因
  diagnoseDiscoveryFailure(error: BusinessError): string {
    switch (error.code) {
      case 201: // 权限错误
        return '请检查应用是否具有设备发现相关权限';
      case 202: // 设备不支持
        return '当前设备不支持发现功能';
      case 203: // 网络不可用
        return '网络连接不可用,请检查网络设置';
      case 204: // 参数错误
        return '发现参数配置错误';
      default:
        return `未知错误: ${error.code}`;
    }
  }
  
  // 自动重试机制
  async retryDiscoveryWithBackoff(
    discoveryFn: () => Promise<void>, 
    maxRetries: number = 3
  ): Promise<void> {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        await discoveryFn();
        return; // 成功则返回
      } catch (error) {
        if (attempt === maxRetries) {
          throw error; // 最后一次尝试仍然失败
        }
        
        // 指数退避延迟
        const delay = Math.pow(2, attempt) * 1000;
        await this.delay(delay);
      }
    }
  }
}

总结

设备发现与连接是HarmonyOS分布式能力的起点,为多设备协同提供了基础支撑。通过本文的学习,你应该掌握了:

核心要点回顾:

  1. 设备发现机制:基于分布式软总线的自动发现能力,支持多种通信协议
  2. 安全认证流程:多重认证机制确保设备连接的安全性
  3. 连接状态管理:完整的连接生命周期管理和异常处理
  4. 性能优化策略:智能发现频率控制和连接池管理

行动建议:

  • 在应用初始化时合理配置设备发现参数,平衡功耗和发现效率
  • 实现完整的错误处理和重试机制,提升用户体验
  • 遵循最小权限原则,只申请必要的设备访问权限
  • 在适当的时机清理连接资源,避免内存泄漏

设备发现与连接技术的正确运用,将为你的HarmonyOS应用打开分布式世界的大门,为用户创造真正无缝的多设备协同体验。


posted @ 2025-12-24 10:40  wrystart  阅读(1)  评论(0)    收藏  举报