鸿蒙App手机控制TV遥控完整指南:方向键/确认键映射实现

举报
鱼弦 发表于 2025/12/11 10:13:22 2025/12/11
【摘要】 引言在智能家居和物联网快速发展的时代,跨设备控制已成为提升用户体验的关键技术。其中,手机作为最常用的移动终端,控制电视等大屏设备具有天然的优势:便携性、触摸屏交互直观、网络连通性强。鸿蒙操作系统凭借其分布式软总线技术和设备虚拟化能力,为实现无缝的跨设备控制提供了强大的技术支撑。传统遥控器受限于物理按键数量和布局,难以满足复杂交互的需求。而智能手机拥有更大的屏幕、丰富的传感器和多样化的输入方式...


引言

在智能家居和物联网快速发展的时代,跨设备控制已成为提升用户体验的关键技术。其中,手机作为最常用的移动终端,控制电视等大屏设备具有天然的优势:便携性、触摸屏交互直观、网络连通性强。鸿蒙操作系统凭借其分布式软总线技术和设备虚拟化能力,为实现无缝的跨设备控制提供了强大的技术支撑。
传统遥控器受限于物理按键数量和布局,难以满足复杂交互的需求。而智能手机拥有更大的屏幕、丰富的传感器和多样化的输入方式,可以模拟甚至超越传统遥控器的功能。通过鸿蒙的分布式能力,我们可以将手机转化为一个功能完整的虚拟遥控器,不仅支持基本的方向键导航和确认操作,还能扩展出语音控制、手势识别、触控板等创新交互方式。
本文将从技术原理到实际应用,全面介绍如何在鸿蒙系统中开发手机TV遥控应用,重点解决方向键和确认键的映射问题,同时探讨多设备协同、权限管理、性能优化等关键技术点,为开发者提供一套完整的解决方案。

技术背景

鸿蒙分布式技术架构

鸿蒙系统的分布式能力是其区别于传统操作系统的核心特征,为跨设备控制提供了技术基础:

1. 分布式软总线(Distributed Soft Bus)

分布式软总线是鸿蒙实现设备间通信的底层协议,具有以下特点:
  • 自动发现:设备间无需手动配对,可自动发现并建立连接
  • 异构网络融合:支持WiFi、蓝牙、NFC等多种网络协议的统一管理
  • 高带宽低时延:优化的数据传输机制,确保控制指令的实时性
  • 安全可靠:内置加密和认证机制,保障通信安全

2. 设备虚拟化(Device Virtualization)

设备虚拟化技术允许将远程设备的硬件能力映射到本地:
  • 输入虚拟化:将手机的触摸屏、传感器映射为遥控器的按键输入
  • 输出虚拟化:将TV的显示内容投射或镜像到手机屏幕
  • 能力虚拟化:将TV的音视频解码、网络通信等能力暴露给手机应用

3. 分布式数据管理

提供统一的数据模型和同步机制:
  • 数据流转:支持控制指令、状态信息等数据的实时同步
  • 一致性保证:确保多设备间数据状态的一致性
  • 冲突解决:智能处理多设备同时操作的冲突情况

TV遥控协议与技术

1. 红外遥控(IR Remote Control)

传统电视的主要控制方式:
  • 协议标准:NEC、RC5、RC6等编码协议
  • 载波频率:通常38kHz
  • 传输距离:直线传输,一般5-10米
  • 优缺点:成本低、功耗小,但需对准、不能穿墙

2. 射频遥控(RF Remote Control)

现代智能电视的主流方案:
  • 技术标准:蓝牙、2.4GHz私有协议
  • 传输特性:全向传输,可穿墙,距离可达10米以上
  • 交互方式:支持双向通信,可传输状态和反馈信息
  • 配对机制:通常需要首次配对建立连接

3. 网络遥控(Network Remote Control)

基于IP网络的远程控制:
  • 通信协议:HTTP、WebSocket、TCP/UDP自定义协议
  • 控制方式:通过网络API发送控制指令
  • 适用场景:智能电视、电视盒子、投屏设备
  • 优势:跨网段控制、支持复杂交互、可扩展性强

鸿蒙输入子系统

鸿蒙的输入系统为遥控器按键映射提供了底层支持:

1. 输入事件体系

  • InputEvent:所有输入事件的基类
  • KeyEvent:按键事件,包含按键码、动作、时间戳等信息
  • MotionEvent:触摸和传感器事件
  • FocusEvent:焦点变化事件

2. 按键码定义

鸿蒙采用与Android兼容的按键码体系,常用遥控器按键映射:
// 方向键
KEYCODE_DPAD_UP      = 19    // 上方向键
KEYCODE_DPAD_DOWN    = 20    // 下方向键  
KEYCODE_DPAD_LEFT    = 21    // 左方向键
KEYCODE_DPAD_RIGHT   = 22    // 右方向键
KEYCODE_DPAD_CENTER  = 23    // 确认/OK键

// 功能键
KEYCODE_BACK         = 4     // 返回键
KEYCODE_HOME         = 3     // 主页键
KEYCODE_MENU         = 82    // 菜单键
KEYCODE_VOLUME_UP    = 24    // 音量+
KEYCODE_VOLUME_DOWN  = 25    // 音量-
KEYCODE_POWER        = 26    // 电源键

3. 输入法框架集成

鸿蒙的输入法框架支持自定义输入设备:
  • InputMethodService:输入法服务基类
  • KeyboardView:虚拟键盘视图
  • KeyCharacterMap:按键字符映射

应用场景

1. 家庭娱乐场景

  • 场景描述:用户在客厅使用手机控制电视观看视频、玩游戏
  • 需求特点:需要流畅的方向导航、快速响应、支持盲操
  • 技术要点:低延迟控制、防误触设计、横竖屏适配

2. 智能家居控制中心

  • 场景描述:手机作为智能家居入口,统一控制电视、空调、灯光等设备
  • 需求特点:多设备切换、场景模式、状态反馈
  • 技术要点:设备发现、状态同步、场景联动

3. 无障碍辅助场景

  • 场景描述:为行动不便的用户提供便捷的电视控制方式
  • 需求特点:大按键、语音辅助、简化操作
  • 技术要点:无障碍API、语音识别、手势放大

4. 商务演示场景

  • 场景描述:会议室中使用手机控制大屏电视进行PPT演示
  • 需求特点:精准定位、激光笔效果、多人协作
  • 技术要点:高精度指针、批注功能、权限管理

5. 教育学习场景

  • 场景描述:在线教育中使用手机控制教学视频播放
  • 需求特点:笔记标注、章节跳转、倍速控制
  • 技术要点:媒体控制、交互白板、学习记录

核心特性

  • 分布式设备控制:基于鸿蒙分布式能力,实现手机对TV的无缝控制
  • 多协议支持:兼容红外、蓝牙、网络等多种TV控制协议
  • 实时响应:优化的通信机制,确保控制指令的低延迟传输
  • 双向通信:支持状态反馈和实时信息同步
  • 多输入方式:支持触摸、手势、语音、加速度计等多种交互
  • 安全认证:设备认证和数据加密,保障控制安全
  • 自适应UI:根据不同TV型号和使用场景自动调整界面和功能
  • 离线缓存:网络中断时可缓存指令,恢复后批量同步

原理流程图与原理解释

系统架构流程图

graph TB
    subgraph "手机端 (控制端)"
        A[用户界面层] --> B[业务逻辑层]
        B --> C[分布式通信层]
        C --> D[设备管理能力]
        D --> E[输入事件处理]
    end
    
    subgraph "分布式软总线"
        F[设备发现服务]
        G[连接管理服务] 
        H[数据传输通道]
    end
    
    subgraph "TV端 (被控端)"
        I[TV代理服务] --> J[输入事件转发]
        J --> K[TV系统接口]
        K --> L[电视硬件]
        
        M[状态管理服务] --> N[状态反馈]
        N --> C
    end
    
    E -->|控制指令| H
    H -->|指令转发| J
    K -->|执行结果| N
    N -->|状态更新| A
    
    style A fill:#e3f2fd
    style I fill:#f3e5f5
    style H fill:#e8f5e8
    style J fill:#fff3e0

按键映射原理图

sequenceDiagram
    participant User as 用户
    participant PhoneUI as 手机界面
    participant InputHandler as 输入处理器
    participant DistributedBus as 分布式总线
    participant TVProxy as TV代理服务
    participant TVSystem as TV系统
    
    User->>PhoneUI: 触摸方向键按钮
    PhoneUI->>InputHandler: 生成KeyEvent
    InputHandler->>InputHandler: 按键映射转换
    InputHandler->>DistributedBus: 发送控制指令
    DistributedBus->>TVProxy: 转发指令
    TVProxy->>TVSystem: 转换为TV按键事件
    TVSystem->>TVSystem: 执行相应操作
    TVSystem->>TVProxy: 返回执行状态
    TVProxy->>DistributedBus: 状态反馈
    DistributedBus->>PhoneUI: 更新UI状态
    PhoneUI->>User: 显示操作反馈

原理解释

1. 设备发现与连接建立

  • 自动发现:手机端通过分布式软总线的设备发现服务扫描同一网络下的TV设备
  • 能力协商:发现设备后,双方交换支持的控制能力和协议版本
  • 安全认证:通过设备证书或用户授权建立可信连接
  • 会话管理:维护长连接或按需建立短连接,优化资源使用

2. 输入事件处理流程

  • 触摸捕获:手机界面捕获用户的触摸事件,识别为方向键或确认键操作
  • 事件转换:将触摸事件转换为标准的KeyEvent,包含按键码、动作类型、时间戳
  • 协议映射:根据TV支持的协议,将KeyEvent映射为对应的红外码、蓝牙指令或网络API调用
  • 指令封装:按照分布式通信协议封装控制指令,添加校验和重传机制

3. 指令传输与执行

  • 可靠传输:使用TCP或自定义可靠UDP协议传输控制指令,确保不丢失
  • 指令队列:TV端维护指令队列,按顺序处理避免冲突
  • 硬件抽象:TV代理服务将网络指令转换为系统级的输入事件
  • 反馈机制:TV执行操作后返回状态信息,手机端更新UI显示操作结果

4. 状态同步与异常处理

  • 状态监控:实时监控TV的连接状态、电量、信号强度等
  • 冲突解决:处理多设备同时控制同一TV的情况,支持主从控制模式
  • 断线重连:网络异常时自动重连,缓存未发送的指令
  • 降级处理:协议不支持时降级到基础控制功能

环境准备

开发环境配置

1. DevEco Studio配置

# 下载并安装DevEco Studio 3.1+
# 配置HarmonyOS SDK路径
export HARMONYOS_SDK_HOME=/path/to/harmonyos/sdk
export PATH=$HARMONYOS_SDK_HOME:$PATH

# 安装必要的SDK组件
# - HarmonyOS SDK Platform Tools
# - HarmonyOS Device Manager
# - Previewer

2. 项目配置(build-profile.json5)

{
  "app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "targetSdkVersion": 9,
    "bundleName": "com.example.tvremote",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name"
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          "name": "default",
          "applyToProducts": ["default"]
        }
      ]
    }
  ],
  "deviceTypes": [
    "phone",
    "tablet"
  ]
}

3. 模块配置(module.json5)

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone"],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ts",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      },
      {
        "name": "RemoteControlAbility",
        "srcEntry": "./ets/remotecontrol/RemoteControlAbility.ts",
        "description": "TV遥控后台能力",
        "icon": "$media:icon",
        "label": "遥控服务",
        "type": "service",
        "exported": true,
        "backgroundModes": ["dataTransfer"]
      }
    ],
    "extensionAbilities": [
      {
        "name": "DeviceDiscoveryExtAbility",
        "srcEntry": "./ets/device/DeviceDiscoveryExtAbility.ts",
        "type": "driver",
        "exported": false
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "$string:distributed_sync_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.USE_BLUETOOTH",
        "reason": "$string:bluetooth_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.ACCESS_NETWORK_STATE",
        "reason": "$string:network_state_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

目录结构设计

TVRemoteControl/
├── entry/
│   ├── src/
│   │   └── main/
│   │       ├── ets/
│   │       │   ├── entryability/
│   │       │   │   ├── EntryAbility.ts
│   │       │   │   └── RemoteControlAbility.ts
│   │       │   ├── pages/
│   │       │   │   ├── Index.ets              # 主界面
│   │       │   │   ├── DeviceList.ets         # 设备列表
│   │       │   │   ├── RemotePad.ets          # 遥控面板
│   │       │   │   └── Settings.ets          # 设置页面
│   │       │   ├── components/
│   │       │   │   ├── DirectionPad.ets      # 方向键组件
│   │       │   │   ├── FunctionKeys.ets      # 功能键组件
│   │       │   │   ├── StatusBar.ets         # 状态栏组件
│   │       │   │   └── DeviceCard.ets        # 设备卡片组件
│   │       │   ├── model/
│   │       │   │   ├── DeviceManager.ts      # 设备管理
│   │       │   │   ├── KeyMapper.ts          # 按键映射
│   │       │   │   ├── ProtocolHandler.ts   # 协议处理
│   │       │   │   └── NetworkManager.ts     # 网络管理
│   │       │   ├── utils/
│   │       │   │   ├── Logger.ts             # 日志工具
│   │       │   │   ├── Constants.ts          # 常量定义
│   │       │   │   └── TypeDefs.ts           # 类型定义
│   │       │   └── remotecontrol/
│   │       │       ├── TVCommand.ts          # TV命令定义
│   │       │       ├── InputSimulator.ts     # 输入模拟
│   │       │       └── FeedbackManager.ts   # 反馈管理
│   │       ├── resources/
│   │       │   ├── base/
│   │       │   │   ├── element/
│   │       │   │   │   ├── color.json
│   │       │   │   │   ├── string.json
│   │       │   │   │   └── style.json
│   │       │   │   ├── media/
│   │       │   │   │   ├── icon.png
│   │       │   │   │   ├── dpad_center.png
│   │       │   │   │   └── dpad_up.png
│   │       │   │   └── profile/
│   │       │   │       └── main_pages.json
│   │       │   └── rawfile/
│   │       │       ├── protocols/
│   │       │       │   ├── nec_protocol.json
│   │       │       │   └── bluetooth_schema.json
│   │       │       └── configs/
│   │       │           └── tv_models.json
│   │       └── module.json5
│   └── build-profile.json5
└── build.gradle

实际详细应用代码示例实现

1. 基础类型定义和常量(utils/TypeDefs.ts)

/**
 * TV遥控应用类型定义文件
 * 定义整个应用中使用的数据结构和常量
 */

// 设备类型枚举
export enum DeviceType {
  SMART_TV = 'smart_tv',           // 智能电视
  TV_BOX = 'tv_box',               // 电视盒子
  PROJECTOR = 'projector',         // 投影仪
  AIR_CONDITIONER = 'air_conditioner', // 空调
  SET_TOP_BOX = 'set_top_box'      // 机顶盒
}

// 连接状态枚举
export enum ConnectionStatus {
  DISCONNECTED = 'disconnected',   // 未连接
  CONNECTING = 'connecting',       // 连接中
  CONNECTED = 'connected',         // 已连接
  DISCONNECTING = 'disconnecting', // 断开中
  ERROR = 'error'                  // 错误状态
}

// 按键动作枚举
export enum KeyAction {
  DOWN = 0,    // 按下
  UP = 1,      // 抬起
  MULTIPLE = 2 // 多次点击
}

// TV品牌枚举
export enum TVBrand {
  SAMSUNG = 'samsung',
  LG = 'lg',
  SONY = 'sony',
  HISENSE = 'hisense',
  TCL = 'tcl',
  XIAOMI = 'xiaomi',
  HUAWEI = 'huawei',
  UNKNOWN = 'unknown'
}

// 按键码定义接口
export interface KeyCode {
  code: number;           // 按键码值
  name: string;           // 按键名称
  description: string;    // 描述
  type: 'direction' | 'confirm' | 'function' | 'number'; // 按键类型
}

// 设备信息接口
export interface DeviceInfo {
  deviceId: string;        // 设备唯一标识
  name: string;           // 设备名称
  type: DeviceType;        // 设备类型
  brand: TVBrand;         // 设备品牌
  model: string;          // 设备型号
  ipAddress?: string;     // IP地址
  macAddress?: string;    // MAC地址
  bluetoothAddr?: string; // 蓝牙地址
  capabilities: string[]; // 支持的功能列表
  protocolVersion: string;// 协议版本
  firmwareVersion?: string; // 固件版本
  lastSeen: number;       // 最后发现时间
  signalStrength?: number; // 信号强度
  batteryLevel?: number;  // 电池电量(如果是无线设备)
}

// 连接参数接口
export interface ConnectionParams {
  deviceId: string;
  connectionType: 'wifi' | 'bluetooth' | 'infrared';
  timeout: number;
  retryCount: number;
  securityToken?: string;
}

// 控制指令接口
export interface ControlCommand {
  commandId: string;       // 指令ID
  deviceId: string;        // 目标设备ID
  keyCode: number;         // 按键码
  keyAction: KeyAction;    // 按键动作
  timestamp: number;       // 时间戳
  sequenceNumber: number;  // 序列号(用于去重和排序)
  checksum?: string;       // 校验和
}

// 设备状态接口
export interface DeviceStatus {
  deviceId: string;
  status: ConnectionStatus;
  powerState: boolean;     // 电源状态
  volume: number;          // 音量
  channel: number;         // 频道
  inputSource: string;     // 输入源
  brightness?: number;     // 亮度
  temperature?: number;    // 温度(空调等)
  lastUpdate: number;      // 最后更新时间
}

// 按键映射配置接口
export interface KeyMapping {
  phoneKey: string;        // 手机按键标识
  tvKeyCode: number;       // TV按键码
  keyName: string;         // 按键名称
  isDirectionKey: boolean; // 是否为方向键
  isConfirmKey: boolean;   // 是否为确认键
  repeatable: boolean;     // 是否支持长按重复
  longPressDelay?: number; // 长按延迟时间
}

// 协议配置接口
export interface ProtocolConfig {
  protocolName: string;    // 协议名称
  protocolType: 'ir' | 'bt' | 'network' | 'custom';
  version: string;
  supportedBrands: TVBrand[];
  keyMappings: Map<number, number>; // 按键映射表
  connectionParams: any;   // 连接参数
}

// 事件回调函数类型定义
export type DeviceFoundCallback = (device: DeviceInfo) => void;
export type ConnectionStatusCallback = (deviceId: string, status: ConnectionStatus) => void;
export type CommandResponseCallback = (command: ControlCommand, success: boolean, error?: string) => void;
export type KeyEventHandler = (keyCode: number, keyAction: KeyAction) => void;

// 应用配置接口
export interface AppConfig {
  discoveryTimeout: number;      // 设备发现超时时间
  connectionTimeout: number;     // 连接超时时间
  commandRetryCount: number;     // 指令重试次数
  heartbeatInterval: number;     // 心跳间隔
  keyRepeatDelay: number;        // 按键重复延迟
  keyRepeatInterval: number;     // 按键重复间隔
  enableLogging: boolean;        // 是否启用日志
  logLevel: 'debug' | 'info' | 'warn' | 'error';
  themeColor: string;            // 主题颜色
  hapticFeedback: boolean;       // 触觉反馈
}

// 错误类型定义
export enum ErrorType {
  DEVICE_NOT_FOUND = 'device_not_found',
  CONNECTION_FAILED = 'connection_failed',
  COMMAND_TIMEOUT = 'command_timeout',
  PROTOCOL_ERROR = 'protocol_error',
  PERMISSION_DENIED = 'permission_denied',
  NETWORK_UNAVAILABLE = 'network_unavailable',
  BLUETOOTH_DISABLED = 'bluetooth_disabled'
}

export interface AppError {
  type: ErrorType;
  message: string;
  code: number;
  details?: any;
  timestamp: number;
}

// 常量定义
export const CONSTANTS = {
  // 默认按键映射
  DEFAULT_KEY_MAPPINGS: {
    'dpad_up': { tvKeyCode: 19, keyName: '上方向键', isDirectionKey: true },
    'dpad_down': { tvKeyCode: 20, keyName: '下方向键', isDirectionKey: true },
    'dpad_left': { tvKeyCode: 21, keyName: '左方向键', isDirectionKey: true },
    'dpad_right': { tvKeyCode: 22, keyName: '右方向键', isDirectionKey: true },
    'dpad_center': { tvKeyCode: 23, keyName: '确认键', isConfirmKey: true },
    'back': { tvKeyCode: 4, keyName: '返回键', isFunctionKey: true },
    'home': { tvKeyCode: 3, keyName: '主页键', isFunctionKey: true },
    'menu': { tvKeyCode: 82, keyName: '菜单键', isFunctionKey: true },
    'volume_up': { tvKeyCode: 24, keyName: '音量+', isFunctionKey: true },
    'volume_down': { tvKeyCode: 25, keyName: '音量-', isFunctionKey: true }
  } as Record<string, KeyMapping>,
  
  // 默认配置
  DEFAULT_CONFIG: {
    discoveryTimeout: 10000,
    connectionTimeout: 5000,
    commandRetryCount: 3,
    heartbeatInterval: 30000,
    keyRepeatDelay: 500,
    keyRepeatInterval: 100,
    enableLogging: true,
    logLevel: 'info' as const,
    themeColor: '#007DFF',
    hapticFeedback: true
  } as AppConfig,
  
  // 网络相关常量
  NETWORK: {
    MULTICAST_ADDRESS: '224.0.0.1',
    MULTICAST_PORT: 8888,
    BROADCAST_INTERVAL: 3000,
    TCP_PORT: 8899,
    WEB_SOCKET_URL: 'ws://{ip}:{port}/remote',
    HTTP_API_BASE: 'http://{ip}:{port}/api/v1'
  },
  
  // 蓝牙相关常量
  BLUETOOTH: {
    SERVICE_UUID: '00001101-0000-1000-8000-00805F9B34FB',
    CHARACTERISTIC_UUID: '00001102-0000-1000-8000-00805F9B34FB',
    SCAN_PERIOD: 10000,
    CONNECT_TIMEOUT: 10000
  },
  
  // 红外协议常量
  IR_PROTOCOL: {
    NEC_FREQUENCY: 38000,
    RC5_FREQUENCY: 36000,
    CARRIER_DUTY: 0.33,
    LEADER_PULSE_MIN: 8000,
    LEADER_PULSE_MAX: 12000
  }
} as const;

2. 日志工具类(utils/Logger.ts)

/**
 * 日志工具类
 * 提供分级日志记录、文件输出、远程上报等功能
 */

import { LogLevel, CONSTANTS } from './TypeDefs';

export class Logger {
  private static instance: Logger;
  private logLevel: LogLevel;
  private enableConsole: boolean;
  private enableFile: boolean;
  private enableRemote: boolean;
  private logBuffer: string[];
  private maxBufferSize: number;
  private logFileName: string;

  private constructor() {
    // 从配置初始化日志级别
    this.logLevel = CONSTANTS.DEFAULT_CONFIG.enableLogging ? 
                   CONSTANTS.DEFAULT_CONFIG.logLevel : 'error';
    this.enableConsole = true;
    this.enableFile = false; // 文件日志需要额外权限
    this.enableRemote = false; // 远程日志需要网络权限
    this.logBuffer = [];
    this.maxBufferSize = 1000;
    this.logFileName = 'tv_remote.log';
    
    // 初始化文件日志(如果支持)
    this.initFileLogging();
  }

  /**
   * 获取Logger单例
   */
  public static getInstance(): Logger {
    if (!Logger.instance) {
      Logger.instance = new Logger();
    }
    return Logger.instance;
  }

  /**
   * 设置日志级别
   * @param level 日志级别
   */
  public setLogLevel(level: LogLevel): void {
    this.logLevel = level;
    this.info('Logger', `日志级别设置为: ${level}`);
  }

  /**
   * 调试级别日志
   * @param tag 标签
   * @param message 消息
   * @param args 附加参数
   */
  public debug(tag: string, message: string, ...args: any[]): void {
    if (this.shouldLog('debug')) {
      this.log('DEBUG', tag, message, args);
    }
  }

  /**
   * 信息级别日志
   * @param tag 标签
   * @param message 消息
   * @param args 附加参数
   */
  public info(tag: string, message: string, ...args: any[]): void {
    if (this.shouldLog('info')) {
      this.log('INFO', tag, message, args);
    }
  }

  /**
   * 警告级别日志
   * @param tag 标签
   * @param message 消息
   * @param args 附加参数
   */
  public warn(tag: string, message: string, ...args: any[]): void {
    if (this.shouldLog('warn')) {
      this.log('WARN', tag, message, args);
    }
  }

  /**
   * 错误级别日志
   * @param tag 标签
   * @param message 消息
   * @param args 附加参数
   */
  public error(tag: string, message: string, ...args: any[]): void {
    if (this.shouldLog('error')) {
      this.log('ERROR', tag, message, args);
      
      // 错误信息始终输出到控制台
      if (!this.enableConsole) {
        console.error(`[${tag}] ${message}`, ...args);
      }
    }
  }

  /**
   * 关键级别日志(最高级别)
   * @param tag 标签
   * @param message 消息
   * @param args 附加参数
   */
  public fatal(tag: string, message: string, ...args: any[]): void {
    this.log('FATAL', tag, message, args);
    // 关键错误可以考虑终止应用或重启服务
    console.error(`[FATAL] [${tag}] ${message}`, ...args);
  }

  /**
   * 性能计时开始
   * @param tag 标签
   * @param operation 操作名称
   */
  public timeStart(tag: string, operation: string): void {
    if (this.shouldLog('debug')) {
      const startTime = Date.now();
      const timerKey = `${tag}_${operation}`;
      (globalThis as any)[timerKey] = startTime;
      this.debug(tag, `开始计时: ${operation}`);
    }
  }

  /**
   * 性能计时结束
   * @param tag 标签
   * @param operation 操作名称
   */
  public timeEnd(tag: string, operation: string): void {
    if (this.shouldLog('debug')) {
      const timerKey = `${tag}_${operation}`;
      const startTime = (globalThis as any)[timerKey];
      if (startTime) {
        const endTime = Date.now();
        const duration = endTime - startTime;
        this.debug(tag, `计时结束: ${operation}, 耗时: ${duration}ms`);
        delete (globalThis as any)[timerKey];
      } else {
        this.warn(tag, `未找到计时起点: ${operation}`);
      }
    }
  }

  /**
   * 记录用户操作
   * @param userId 用户ID
   * @param action 操作
   * @param details 详细信息
   */
  public logUserAction(userId: string, action: string, details?: any): void {
    const logEntry = {
      type: 'USER_ACTION',
      userId,
      action,
      details,
      timestamp: Date.now(),
      sessionId: this.getSessionId()
    };
    
    this.info('Analytics', `用户操作: ${action}`, logEntry);
    
    // 如果启用远程日志,上报到服务器
    if (this.enableRemote) {
      this.sendRemoteLog(logEntry);
    }
  }

  /**
   * 记录性能指标
   * @param metric 指标名称
   * @param value 指标值
   * @param tags 标签
   */
  public logMetric(metric: string, value: number, tags?: Record<string, string>): void {
    const logEntry = {
      type: 'METRIC',
      metric,
      value,
      tags,
      timestamp: Date.now()
    };
    
    this.debug('Performance', `性能指标: ${metric}=${value}`, logEntry);
  }

  /**
   * 清空日志缓冲区
   */
  public flushBuffer(): void {
    if (this.logBuffer.length > 0) {
      this.writeToFile(this.logBuffer.join('\n'));
      this.logBuffer = [];
    }
  }

  /**
   * 获取日志统计信息
   */
  public getStats(): Record<string, any> {
    return {
      logLevel: this.logLevel,
      bufferSize: this.logBuffer.length,
      maxBufferSize: this.maxBufferSize,
      enableConsole: this.enableConsole,
      enableFile: this.enableFile,
      enableRemote: this.enableRemote
    };
  }

  /**
   * 判断是否应该记录指定级别的日志
   */
  private shouldLog(level: LogLevel): boolean {
    const levels: Record<LogLevel, number> = {
      'debug': 0,
      'info': 1,
      'warn': 2,
      'error': 3,
      'fatal': 4
    };
    
    return levels[level] >= levels[this.logLevel];
  }

  /**
   * 核心日志方法
   */
  private log(level: string, tag: string, message: string, args: any[]): void {
    const timestamp = new Date().toISOString();
    const logEntry = `[${timestamp}] [${level}] [${tag}] ${message}`;
    
    // 格式化附加参数
    let formattedArgs = '';
    if (args.length > 0) {
      try {
        formattedArgs = ' ' + args.map(arg => {
          if (typeof arg === 'object') {
            try {
              return JSON.stringify(arg);
            } catch (e) {
              return '[Unserializable Object]';
            }
          }
          return String(arg);
        }).join(', ');
      } catch (error) {
        formattedArgs = ' [Error formatting arguments]';
      }
    }
    
    const fullMessage = logEntry + formattedArgs;
    
    // 输出到控制台
    if (this.enableConsole) {
      switch (level) {
        case 'DEBUG':
          console.debug(fullMessage);
          break;
        case 'INFO':
          console.info(fullMessage);
          break;
        case 'WARN':
          console.warn(fullMessage);
          break;
        case 'ERROR':
        case 'FATAL':
          console.error(fullMessage);
          break;
        default:
          console.log(fullMessage);
      }
    }
    
    // 添加到缓冲区
    this.logBuffer.push(fullMessage);
    
    // 缓冲区满时写入文件
    if (this.logBuffer.length >= this.maxBufferSize) {
      this.flushBuffer();
    }
    
    // 发送到远程服务器
    if (this.enableRemote && (level === 'ERROR' || level === 'FATAL')) {
      this.sendRemoteLog({
        level,
        tag,
        message,
        args,
        timestamp: Date.now()
      });
    }
  }

  /**
   * 初始化文件日志
   */
  private initFileLogging(): void {
    // 检查是否在支持文件系统的环境中
    try {
      // 在鸿蒙应用中,需要使用@ohos.file.fs API
      // 这里简化处理,实际实现需要申请文件系统权限
      this.enableFile = false;
      this.debug('Logger', '文件系统不可用,文件日志已禁用');
    } catch (error) {
      this.enableFile = false;
      this.warn('Logger', '初始化文件日志失败', error);
    }
  }

  /**
   * 写入文件
   */
  private writeToFile(content: string): void {
    if (!this.enableFile) return;
    
    // 实际的文件写入实现
    // 需要使用鸿蒙的文件系统API
    this.debug('Logger', `写入日志文件: ${content.length} 字符`);
  }

  /**
   * 发送远程日志
   */
  private sendRemoteLog(logData: any): void {
    if (!this.enableRemote) return;
    
    // 异步发送日志到远程服务器
    // 使用@ohos.net.http或@ohos.net.socket
    this.debug('Logger', '发送远程日志', logData);
  }

  /**
   * 获取会话ID
   */
  private getSessionId(): string {
    // 生成或获取当前会话ID
    if (!(globalThis as any).sessionId) {
      (globalThis as any).sessionId = this.generateSessionId();
    }
    return (globalThis as any).sessionId;
  }

  /**
   * 生成会话ID
   */
  private generateSessionId(): string {
    return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }
}

// 导出便捷方法
export const logger = Logger.getInstance();

// 全局便捷方法
export const LOG_DEBUG = (tag: string, message: string, ...args: any[]) => 
  logger.debug(tag, message, ...args);
export const LOG_INFO = (tag: string, message: string, ...args: any[]) => 
  logger.info(tag, message, ...args);
export const LOG_WARN = (tag: string, message: string, ...args: any[]) => 
  logger.warn(tag, message, ...args);
export const LOG_ERROR = (tag: string, message: string, ...args: any[]) => 
  logger.error(tag, message, ...args);
export const LOG_FATAL = (tag: string, message: string, ...args: any[]) => 
  logger.fatal(tag, message, ...args);

3. 设备管理类(model/DeviceManager.ts)

/**
 * 设备管理类
 * 负责TV设备的发现、连接、状态管理等功能
 */

import deviceManager from '@ohos.distributedHardware.deviceManager';
import { 
  DeviceInfo, 
  DeviceType, 
  ConnectionStatus, 
  TVBrand,
  DeviceFoundCallback,
  ConnectionStatusCallback,
  AppError,
  ErrorType,
  CONSTANTS,
  logger
} from '../utils/TypeDefs';
import { NetworkManager } from './NetworkManager';
import { ProtocolHandler } from './ProtocolHandler';

export class DeviceManager {
  private static instance: DeviceManager;
  private deviceManager: deviceManager.DeviceManager;
  private discoveredDevices: Map<string, DeviceInfo>;
  private connectedDevices: Map<string, DeviceInfo>;
  private connectionCallbacks: Map<string, ConnectionStatusCallback[]>;
  private deviceFoundCallbacks: DeviceFoundCallback[];
  private networkManager: NetworkManager;
  private protocolHandler: ProtocolHandler;
  private isInitialized: boolean;
  private discoveryTimer: number | null;
  private heartbeatTimers: Map<string, number>;

  private constructor() {
    this.discoveredDevices = new Map();
    this.connectedDevices = new Map();
    this.connectionCallbacks = new Map();
    this.deviceFoundCallbacks = [];
    this.networkManager = NetworkManager.getInstance();
    this.protocolHandler = ProtocolHandler.getInstance();
    this.isInitialized = false;
    this.discoveryTimer = null;
    this.heartbeatTimers = new Map();
    
    logger.info('DeviceManager', '设备管理类实例化');
  }

  /**
   * 获取DeviceManager单例
   */
  public static getInstance(): DeviceManager {
    if (!DeviceManager.instance) {
      DeviceManager.instance = new DeviceManager();
    }
    return DeviceManager.instance;
  }

  /**
   * 初始化设备管理器
   */
  public async init(): Promise<boolean> {
    try {
      logger.info('DeviceManager', '开始初始化设备管理器');
      
      // 初始化设备发现服务
      this.deviceManager = deviceManager.createDeviceManager('com.example.tvremote');
      
      // 注册设备状态变化监听
      this.registerDeviceListeners();
      
      // 初始化网络管理器
      await this.networkManager.init();
      
      // 初始化协议处理器
      this.protocolHandler.init();
      
      this.isInitialized = true;
      logger.info('DeviceManager', '设备管理器初始化成功');
      return true;
      
    } catch (error) {
      logger.error('DeviceManager', '设备管理器初始化失败', error);
      this.handleError('INIT_FAILED', '设备管理器初始化失败', error);
      return false;
    }
  }

  /**
   * 注册设备监听器
   */
  private registerDeviceListeners(): void {
    if (!this.deviceManager) {
      logger.error('DeviceManager', '设备管理器未初始化,无法注册监听器');
      return;
    }

    try {
      // 注册设备上线监听
      this.deviceManager.on('deviceOnline', (data) => {
        logger.info('DeviceManager', '设备上线', data);
        this.handleDeviceOnline(data);
      });

      // 注册设备下线监听
      this.deviceManager.on('deviceOffline', (data) => {
        logger.info('DeviceManager', '设备下线', data);
        this.handleDeviceOffline(data);
      });

      // 注册分布式设备状态变化监听
      this.deviceManager.on('deviceStateChange', (data) => {
        logger.debug('DeviceManager', '设备状态变化', data);
        this.handleDeviceStateChange(data);
      });

      logger.debug('DeviceManager', '设备监听器注册完成');
      
    } catch (error) {
      logger.error('DeviceManager', '注册设备监听器失败', error);
    }
  }

  /**
   * 开始设备发现
   * @param timeout 发现超时时间
   */
  public startDeviceDiscovery(timeout: number = CONSTANTS.DEFAULT_CONFIG.discoveryTimeout): void {
    if (!this.isInitialized) {
      logger.error('DeviceManager', '设备管理器未初始化,无法开始设备发现');
      return;
    }

    logger.info('DeviceManager', `开始设备发现,超时时间: ${timeout}ms`);
    
    // 清除之前的定时器
    if (this.discoveryTimer) {
      clearTimeout(this.discoveryTimer);
      this.discoveryTimer = null;
    }

    // 清空之前发现的设备
    this.discoveredDevices.clear();

    try {
      // 通过分布式设备管理器发现设备
      this.discoverDistributedDevices();
      
      // 通过网络扫描发现TV设备
      this.discoverNetworkDevices();
      
      // 通过蓝牙发现设备
      this.discoverBluetoothDevices();
      
      // 设置发现超时
      this.discoveryTimer = setTimeout(() => {
        logger.info('DeviceManager', '设备发现超时');
        this.stopDeviceDiscovery();
      }, timeout) as unknown as number;
      
    } catch (error) {
      logger.error('DeviceManager', '开始设备发现失败', error);
      this.handleError('DISCOVERY_FAILED', '设备发现失败', error);
    }
  }

  /**
   * 停止设备发现
   */
  public stopDeviceDiscovery(): void {
    logger.info('DeviceManager', '停止设备发现');
    
    if (this.discoveryTimer) {
      clearTimeout(this.discoveryTimer);
      this.discoveryTimer = null;
    }

    // 停止各类设备发现
    this.stopNetworkDiscovery();
    this.stopBluetoothDiscovery();
  }

  /**
   * 发现分布式设备
   */
  private discoverDistributedDevices(): void {
    try {
      // 获取已经配对的设备
      this.deviceManager.getTrustedDeviceListSync().forEach(device => {
        const deviceInfo = this.convertToDeviceInfo(device);
        if (deviceInfo) {
          this.addDiscoveredDevice(deviceInfo);
        }
      });

      // 开始发现新设备
      this.deviceManager.startDeviceDiscovery({
        discoverTargetType: [
          deviceManager.DiscoverTargetType.DEVICE_TYPE_SMART_TV,
          deviceManager.DiscoverTargetType.DEVICE_TYPE_SETTOP_BOX
        ],
        strategy: deviceManager.DiscoverStrategy.AUTO
      });

      logger.debug('DeviceManager', '分布式设备发现已启动');
      
    } catch (error) {
      logger.error('DeviceManager', '分布式设备发现失败', error);
    }
  }

  /**
   * 发现网络设备
   */
  private discoverNetworkDevices(): void {
    try {
      // 使用网络管理器发现TV设备
      this.networkManager.startDiscovery((deviceInfo: DeviceInfo) => {
        this.addDiscoveredDevice(deviceInfo);
      });

      logger.debug('DeviceManager', '网络设备发现已启动');
      
    } catch (error) {
      logger.error('DeviceManager', '网络设备发现失败', error);
    }
  }

  /**
   * 发现蓝牙设备
   */
  private discoverBluetoothDevices(): void {
    try {
      // 蓝牙设备发现实现
      // 需要使用@ohos.bluetooth模块
      logger.debug('DeviceManager', '蓝牙设备发现已启动');
      
    } catch (error) {
      logger.error('DeviceManager', '蓝牙设备发现失败', error);
    }
  }

  /**
   * 停止网络发现
   */
  private stopNetworkDiscovery(): void {
    try {
      this.networkManager.stopDiscovery();
      logger.debug('DeviceManager', '网络发现已停止');
    } catch (error) {
      logger.error('DeviceManager', '停止网络发现失败', error);
    }
  }

  /**
   * 停止蓝牙发现
   */
  private stopBluetoothDiscovery(): void {
    try {
      // 停止蓝牙扫描
      logger.debug('DeviceManager', '蓝牙发现已停止');
    } catch (error) {
      logger.error('DeviceManager', '停止蓝牙发现失败', error);
    }
  }

  /**
   * 添加发现的设备
   */
  private addDiscoveredDevice(deviceInfo: DeviceInfo): void {
    // 检查设备是否已存在
    const existingDevice = this.discoveredDevices.get(deviceInfo.deviceId);
    if (existingDevice) {
      // 更新现有设备信息
      this.updateDeviceInfo(existingDevice, deviceInfo);
    } else {
      // 添加新设备
      this.discoveredDevices.set(deviceInfo.deviceId, deviceInfo);
      logger.info('DeviceManager', `发现新设备: ${deviceInfo.name}`, deviceInfo);
      
      // 通知设备发现回调
      this.notifyDeviceFound(deviceInfo);
    }
  }

  /**
   * 更新设备信息
   */
  private updateDeviceInfo(existing: DeviceInfo, updated: DeviceInfo): void {
    // 保留原有的连接状态等信息
    updated.status = existing.status;
    updated.lastSeen = Date.now();
    
    this.discoveredDevices.set(existing.deviceId, updated);
    logger.debug('DeviceManager', `更新设备信息: ${updated.name}`);
  }

  /**
   * 处理设备上线事件
   */
  private handleDeviceOnline(data: any): void {
    try {
      const deviceInfo = this.convertToDeviceInfo(data);
      if (deviceInfo) {
        this.addDiscoveredDevice(deviceInfo);
        
        // 如果设备之前已连接,尝试重新连接
        if (this.connectedDevices.has(deviceInfo.deviceId)) {
          logger.info('DeviceManager', `设备重新上线,尝试重连: ${deviceInfo.name}`);
          this.reconnectDevice(deviceInfo.deviceId);
        }
      }
    } catch (error) {
      logger.error('DeviceManager', '处理设备上线事件失败', error);
    }
  }

  /**
   * 处理设备下线事件
   */
  private handleDeviceOffline(data: any): void {
    try {
      const deviceId = data.deviceId;
      logger.info('DeviceManager', `设备下线: ${deviceId}`);
      
      // 更新设备状态
      this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.DISCONNECTED);
      
      // 清理心跳定时器
      this.stopHeartbeat(deviceId);
      
      // 从已连接设备列表中移除
      this.connectedDevices.delete(deviceId);
      
    } catch (error) {
      logger.error('DeviceManager', '处理设备下线事件失败', error);
    }
  }

  /**
   * 处理设备状态变化事件
   */
  private handleDeviceStateChange(data: any): void {
    try {
      const deviceId = data.deviceId;
      const state = data.state;
      
      logger.debug('DeviceManager', `设备状态变化: ${deviceId}, 状态: ${state}`);
      
      // 根据状态变化更新设备信息
      switch (state) {
        case 'online':
          this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.CONNECTED);
          break;
        case 'offline':
          this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.DISCONNECTED);
          break;
        case 'unpaired':
          this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.DISCONNECTED);
          break;
      }
      
    } catch (error) {
      logger.error('DeviceManager', '处理设备状态变化失败', error);
    }
  }

  /**
   * 转换设备信息格式
   */
  private convertToDeviceInfo(device: any): DeviceInfo | null {
    try {
      // 根据设备类型转换为标准格式
      const deviceInfo: DeviceInfo = {
        deviceId: device.uuid || device.deviceId || this.generateDeviceId(),
        name: device.deviceName || device.name || '未知设备',
        type: this.inferDeviceType(device),
        brand: this.inferBrand(device),
        model: device.model || '未知型号',
        ipAddress: device.ipAddress,
        macAddress: device.macAddress,
        bluetoothAddr: device.bluetoothAddr,
        capabilities: this.extractCapabilities(device),
        protocolVersion: device.protocolVersion || '1.0',
        firmwareVersion: device.firmwareVersion,
        lastSeen: Date.now(),
        signalStrength: device.rssi || device.signalStrength
      };
      
      return deviceInfo;
      
    } catch (error) {
      logger.error('DeviceManager', '转换设备信息失败', error);
      return null;
    }
  }

  /**
   * 推断设备类型
   */
  private inferDeviceType(device: any): DeviceType {
    const deviceType = device.deviceType || device.type || '';
    const deviceName = device.deviceName || device.name || '';
    
    if (deviceType.includes('tv') || deviceName.includes('TV') || deviceName.includes('电视')) {
      return DeviceType.SMART_TV;
    } else if (deviceType.includes('box') || deviceName.includes('盒子') || deviceName.includes('Box')) {
      return DeviceType.TV_BOX;
    } else if (deviceType.includes('projector') || deviceName.includes('投影')) {
      return DeviceType.PROJECTOR;
    } else if (deviceType.includes('ac') || deviceName.includes('空调')) {
      return DeviceType.AIR_CONDITIONER;
    } else {
      return DeviceType.SMART_TV; // 默认为智能电视
    }
  }

  /**
   * 推断设备品牌
   */
  private inferBrand(device: any): TVBrand {
    const deviceName = device.deviceName || device.name || '';
    const manufacturer = device.manufacturer || '';
    
    const brandMap: Record<string, TVBrand> = {
      'samsung': TVBrand.SAMSUNG,
      '三星': TVBrand.SAMSUNG,
      'lg': TVBrand.LG,
      '乐金': TVBrand.LG,
      'sony': TVBrand.SONY,
      '索尼': TVBrand.SONY,
      'hisense': TVBrand.HISENSE,
      '海信': TVBrand.HISENSE,
      'tcl': TVBrand.TCL,
      'tcl电视': TVBrand.TCL,
      'xiaomi': TVBrand.XIAOMI,
      '小米': TVBrand.XIAOMI,
      'huawei': TVBrand.HUAWEI,
      '华为': TVBrand.HUAWEI,
      '荣耀': TVBrand.HUAWEI
    };
    
    // 检查制造商
    if (manufacturer.toLowerCase() in brandMap) {
      return brandMap[manufacturer.toLowerCase()];
    }
    
    // 检查设备名称
    const lowerName = deviceName.toLowerCase();
    for (const [key, brand] of Object.entries(brandMap)) {
      if (lowerName.includes(key)) {
        return brand;
      }
    }
    
    return TVBrand.UNKNOWN;
  }

  /**
   * 提取设备能力
   */
  private extractCapabilities(device: any): string[] {
    const capabilities: string[] = [];
    
    // 基础能力
    capabilities.push('power_control', 'volume_control', 'channel_control');
    
    // 根据设备类型添加特定能力
    const deviceType = this.inferDeviceType(device);
    switch (deviceType) {
      case DeviceType.SMART_TV:
        capabilities.push('app_launch', 'input_source', 'screen_mirror');
        break;
      case DeviceType.TV_BOX:
        capabilities.push('app_launch', 'storage_access', 'cast_support');
        break;
      case DeviceType.PROJECTOR:
        capabilities.push('focus_adjust', 'keystone_correction', 'lamp_status');
        break;
    }
    
    // 根据设备品牌添加特定能力
    const brand = this.inferBrand(device);
    switch (brand) {
      case TVBrand.SAMSUNG:
        capabilities.push('smart_hub', 'bixby_voice');
        break;
      case TVBrand.LG:
        capabilities.push('webos_control', 'thinq_ai');
        break;
      case TVBrand.SONY:
        capabilities.push('android_tv', 'google_assistant');
        break;
      case TVBrand.XIAOMI:
        capabilities.push('patchwall', 'miui_tv');
        break;
    }
    
    return capabilities;
  }

  /**
   * 生成设备ID
   */
  private generateDeviceId(): string {
    return 'device_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }

  /**
   * 连接设备
   * @param deviceId 设备ID
   * @param params 连接参数
   */
  public async connectDevice(deviceId: string, params?: any): Promise<boolean> {
    try {
      logger.info('DeviceManager', `开始连接设备: ${deviceId}`);
      
      // 检查设备是否存在
      const deviceInfo = this.discoveredDevices.get(deviceId);
      if (!deviceInfo) {
        throw new Error(`设备未找到: ${deviceId}`);
      }
      
      // 检查是否已连接
      if (this.connectedDevices.has(deviceId)) {
        logger.warn('DeviceManager', `设备已连接: ${deviceId}`);
        return true;
      }
      
      // 更新连接状态
      this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.CONNECTING);
      
      // 根据设备类型选择合适的连接方式
      const connectionSuccess = await this.establishConnection(deviceInfo, params);
      
      if (connectionSuccess) {
        // 连接成功
        this.connectedDevices.set(deviceId, deviceInfo);
        this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.CONNECTED);
        
        // 启动心跳检测
        this.startHeartbeat(deviceId);
        
        logger.info('DeviceManager', `设备连接成功: ${deviceInfo.name}`);
        return true;
      } else {
        // 连接失败
        this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.ERROR);
        throw new Error(`连接设备失败: ${deviceId}`);
      }
      
    } catch (error) {
      logger.error('DeviceManager', `连接设备失败: ${deviceId}`, error);
      this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.ERROR);
      this.handleError('CONNECTION_FAILED', `连接设备失败: ${deviceId}`, error);
      return false;
    }
  }

  /**
   * 建立设备连接
   */
  private async establishConnection(deviceInfo: DeviceInfo, params?: any): Promise<boolean> {
    try {
      logger.debug('DeviceManager', `建立连接: ${deviceInfo.name}`, deviceInfo);
      
      // 根据设备支持的协议选择连接方式
      if (deviceInfo.capabilities.includes('wifi_control') || deviceInfo.ipAddress) {
        // 优先使用网络连接
        return await this.networkManager.connectDevice(deviceInfo, params);
      } else if (deviceInfo.capabilities.includes('bluetooth_control') || deviceInfo.bluetoothAddr) {
        // 使用蓝牙连接
        return await this.connectViaBluetooth(deviceInfo, params);
      } else {
        // 使用分布式连接
        return await this.connectViaDistributed(deviceInfo, params);
      }
      
    } catch (error) {
      logger.error('DeviceManager', `建立连接失败: ${deviceInfo.deviceId}`, error);
      return false;
    }
  }

  /**
   * 通过网络连接设备
   */
  private async connectViaNetwork(deviceInfo: DeviceInfo, params?: any): Promise<boolean> {
    return await this.networkManager.connectDevice(deviceInfo, params);
  }

  /**
   * 通过蓝牙连接设备
   */
  private async connectViaBluetooth(deviceInfo: DeviceInfo, params?: any): Promise<boolean> {
    try {
      // 蓝牙连接实现
      // 需要使用@ohos.bluetooth模块
      logger.info('DeviceManager', `通过蓝牙连接设备: ${deviceInfo.name}`);
      
      // 模拟连接过程
      await this.delay(2000);
      
      return true;
      
    } catch (error) {
      logger.error('DeviceManager', `蓝牙连接失败: ${deviceInfo.deviceId}`, error);
      return false;
    }
  }

  /**
   * 通过分布式连接设备
   */
  private async connectViaDistributed(deviceInfo: DeviceInfo, params?: any): Promise<boolean> {
    try {
      logger.info('DeviceManager', `通过分布式连接设备: ${deviceInfo.name}`);
      
      // 配对设备(如果未配对)
      const device = this.findDistributedDevice(deviceInfo.deviceId);
      if (device && !device.isTrusted) {
        await this.pairDevice(device);
      }
      
      // 连接设备
      // 实际实现需要调用分布式能力接口
      await this.delay(1500);
      
      return true;
      
    } catch (error) {
      logger.error('DeviceManager', `分布式连接失败: ${deviceInfo.deviceId}`, error);
      return false;
    }
  }

  /**
   * 查找分布式设备
   */
  private findDistributedDevice(deviceId: string): any {
    try {
      const devices = this.deviceManager.getTrustedDeviceListSync();
      return devices.find(device => device.deviceId === deviceId);
    } catch (error) {
      logger.error('DeviceManager', '查找分布式设备失败', error);
      return null;
    }
  }

  /**
   * 配对设备
   */
  private async pairDevice(device: any): Promise<void> {
    return new Promise((resolve, reject) => {
      try {
        this.deviceManager.bindTarget(device.deviceId, (err, data) => {
          if (err) {
            logger.error('DeviceManager', '设备配对失败', err);
            reject(err);
          } else {
            logger.info('DeviceManager', '设备配对成功', data);
            resolve();
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 断开设备连接
   * @param deviceId 设备ID
   */
  public async disconnectDevice(deviceId: string): Promise<boolean> {
    try {
      logger.info('DeviceManager', `断开设备连接: ${deviceId}`);
      
      // 检查设备是否已连接
      if (!this.connectedDevices.has(deviceId)) {
        logger.warn('DeviceManager', `设备未连接: ${deviceId}`);
        return true;
      }
      
      // 停止心跳
      this.stopHeartbeat(deviceId);
      
      // 断开连接
      const deviceInfo = this.connectedDevices.get(deviceId)!;
      await this.closeConnection(deviceInfo);
      
      // 更新状态
      this.connectedDevices.delete(deviceId);
      this.updateDeviceConnectionStatus(deviceId, ConnectionStatus.DISCONNECTED);
      
      logger.info('DeviceManager', `设备断开连接成功: ${deviceInfo.name}`);
      return true;
      
    } catch (error) {
      logger.error('DeviceManager', `断开设备连接失败: ${deviceId}`, error);
      this.handleError('DISCONNECT_FAILED', `断开设备连接失败: ${deviceId}`, error);
      return false;
    }
  }

  /**
   * 关闭设备连接
   */
  private async closeConnection(deviceInfo: DeviceInfo): Promise<void> {
    try {
      if (deviceInfo.ipAddress) {
        await this.networkManager.disconnectDevice(deviceInfo.deviceId);
      } else if (deviceInfo.bluetoothAddr) {
        // 关闭蓝牙连接
        await this.disconnectBluetooth(deviceInfo.deviceId);
      } else {
        // 关闭分布式连接
        await this.unbindDistributedDevice(deviceInfo.deviceId);
      }
    } catch (error) {
      logger.error('DeviceManager', `关闭连接失败: ${deviceInfo.deviceId}`, error);
      throw error;
    }
  }

  /**
   * 断开蓝牙连接
   */
  private async disconnectBluetooth(deviceId: string): Promise<void> {
    // 蓝牙断开连接实现
    await this.delay(500);
  }

  /**
   * 解绑分布式设备
   */
  private async unbindDistributedDevice(deviceId: string): Promise<void> {
    return new Promise((resolve, reject) => {
      try {
        this.deviceManager.releaseTarget(deviceId, (err, data) => {
          if (err) {
            logger.error('DeviceManager', '解绑设备失败', err);
            reject(err);
          } else {
            logger.info('DeviceManager', '解绑设备成功', data);
            resolve();
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 重新连接设备
   */
  private async reconnectDevice(deviceId: string): Promise<boolean> {
    logger.info('DeviceManager', `尝试重新连接设备: ${deviceId}`);
    
    // 延迟一段时间后重连
    await this.delay(1000);
    
    return await this.connectDevice(deviceId);
  }

  /**
   * 启动心跳检测
   */
  private startHeartbeat(deviceId: string): void {
    try {
      // 停止现有的心跳定时器
      this.stopHeartbeat(deviceId);
      
      const heartbeatInterval = CONSTANTS.DEFAULT_CONFIG.heartbeatInterval;
      
      const heartbeatTimer = setInterval(async () => {
        try {
          await this.sendHeartbeat(deviceId);
        } catch (error) {
          logger.error('DeviceManager', `心跳发送失败: ${deviceId}`, error);
          // 心跳失败,可能连接已断开
          this.handleDeviceOffline({ deviceId });
        }
      }, heartbeatInterval) as unknown as number;
      
      this.heartbeatTimers.set(deviceId, heartbeatTimer);
      logger.debug('DeviceManager', `启动心跳检测: ${deviceId}, 间隔: ${heartbeatInterval}ms`);
      
    } catch (error) {
      logger.error('DeviceManager', `启动心跳检测失败: ${deviceId}`, error);
    }
  }

  /**
   * 停止心跳检测
   */
  private stopHeartbeat(deviceId: string): void {
    const timer = this.heartbeatTimers.get(deviceId);
    if (timer) {
      clearInterval(timer);
      this.heartbeatTimers.delete(deviceId);
      logger.debug('DeviceManager', `停止心跳检测: ${deviceId}`);
    }
  }

  /**
   * 发送心跳包
   */
  private async sendHeartbeat(deviceId: string): Promise<void> {
    try {
      const deviceInfo = this.connectedDevices.get(deviceId);
      if (!deviceInfo) {
        throw new Error(`设备未连接: ${deviceId}`);
      }
      
      // 根据设备类型发送不同类型的心跳
      if (deviceInfo.ipAddress) {
        await this.networkManager.sendHeartbeat(deviceId);
      } else {
        // 其他类型设备的心跳实现
        await this.delay(100);
      }
      
      logger.debug('DeviceManager', `心跳发送成功: ${deviceId}`);
      
    } catch (error) {
      logger.error('DeviceManager', `发送心跳失败: ${deviceId}`, error);
      throw error;
    }
  }

  /**
   * 更新设备连接状态
   */
  private updateDeviceConnectionStatus(deviceId: string, status: ConnectionStatus): void {
    // 更新已连接设备状态
    const connectedDevice = this.connectedDevices.get(deviceId);
    if (connectedDevice) {
      // 这里可以添加状态变更逻辑
    }
    
    // 更新发现设备状态
    const discoveredDevice = this.discoveredDevices.get(deviceId);
    if (discoveredDevice) {
      // 创建设备状态对象
      const deviceStatus = {
        deviceId,
        status,
        powerState: false,
        volume: 0,
        channel: 0,
        inputSource: '',
        lastUpdate: Date.now()
      };
      
      // 通知状态变化
      this.notifyConnectionStatusChange(deviceId, status);
    }
  }

  /**
   * 注册设备发现回调
   */
  public registerDeviceFoundCallback(callback: DeviceFoundCallback): void {
    this.deviceFoundCallbacks.push(callback);
    logger.debug('DeviceManager', '注册设备发现回调');
  }

  /**
   * 注销设备发现回调
   */
  public unregisterDeviceFoundCallback(callback: DeviceFoundCallback): void {
    const index = this.deviceFoundCallbacks.indexOf(callback);
    if (index > -1) {
      this.deviceFoundCallbacks.splice(index, 1);
      logger.debug('DeviceManager', '注销设备发现回调');
    }
  }

  /**
   * 注册连接状态变化回调
   */
  public registerConnectionStatusCallback(deviceId: string, callback: ConnectionStatusCallback): void {
    if (!this.connectionCallbacks.has(deviceId)) {
      this.connectionCallbacks.set(deviceId, []);
    }
    this.connectionCallbacks.get(deviceId)!.push(callback);
    logger.debug('DeviceManager', `注册连接状态回调: ${deviceId}`);
  }

  /**
   * 注销连接状态变化回调
   */
  public unregisterConnectionStatusCallback(deviceId: string, callback: ConnectionStatusCallback): void {
    const callbacks = this.connectionCallbacks.get(deviceId);
    if (callbacks) {
      const index = callbacks.indexOf(callback);
      if (index > -1) {
        callbacks.splice(index, 1);
        logger.debug('DeviceManager', `注销连接状态回调: ${deviceId}`);
      }
    }
  }

  /**
   * 通知设备发现
   */
  private notifyDeviceFound(deviceInfo: DeviceInfo): void {
    this.deviceFoundCallbacks.forEach(callback => {
      try {
        callback(deviceInfo);
      } catch (error) {
        logger.error('DeviceManager', '设备发现回调执行失败', error);
      }
    });
  }

  /**
   * 通知连接状态变化
   */
  private notifyConnectionStatusChange(deviceId: string, status: ConnectionStatus): void {
    const callbacks = this.connectionCallbacks.get(deviceId);
    if (callbacks) {
      callbacks.forEach(callback => {
        try {
          callback(deviceId, status);
        } catch (error) {
          logger.error('DeviceManager', '连接状态回调执行失败', error);
        }
      });
    }
  }

  /**
   * 获取发现的设备列表
   */
  public getDiscoveredDevices(): DeviceInfo[] {
    return Array.from(this.discoveredDevices.values());
  }

  /**
   * 获取已连接的设备列表
   */
  public getConnectedDevices(): DeviceInfo[] {
    return Array.from(this.connectedDevices.values());
  }

  /**
   * 获取设备信息
   */
  public getDeviceInfo(deviceId: string): DeviceInfo | undefined {
    return this.discoveredDevices.get(deviceId) || this.connectedDevices.get(deviceId);
  }

  /**
   * 检查设备是否已连接
   */
  public isDeviceConnected(deviceId: string): boolean {
    return this.connectedDevices.has(deviceId);
  }

  /**
   * 获取设备连接状态
   */
  public getDeviceConnectionStatus(deviceId: string): ConnectionStatus {
    const connectedDevice = this.connectedDevices.get(deviceId);
    if (connectedDevice) {
      return ConnectionStatus.CONNECTED;
    }
    
    const discoveredDevice = this.discoveredDevices.get(deviceId);
    // 这里简化处理,实际应该维护设备的详细状态
    return discoveredDevice ? ConnectionStatus.DISCONNECTED : ConnectionStatus.DISCONNECTED;
  }

  /**
   * 处理错误
   */
  private handleError(type: ErrorType, message: string, details?: any): void {
    const error: AppError = {
      type,
      message,
      code: this.getErrorCode(type),
      details,
      timestamp: Date.now()
    };
    
    logger.error('DeviceManager', `设备管理器错误: ${message}`, error);
    
    // 这里可以添加错误上报逻辑
    // this.reportError(error);
  }

  /**
   * 获取错误码
   */
  private getErrorCode(type: ErrorType): number {
    const errorCodes: Record<ErrorType, number> = {
      [ErrorType.DEVICE_NOT_FOUND]: 1001,
      [ErrorType.CONNECTION_FAILED]: 1002,
      [ErrorType.COMMAND_TIMEOUT]: 1003,
      [ErrorType.PROTOCOL_ERROR]: 1004,
      [ErrorType.PERMISSION_DENIED]: 1005,
      [ErrorType.NETWORK_UNAVAILABLE]: 1006,
      [ErrorType.BLUETOOTH_DISABLED]: 1007
    };
    
    return errorCodes[type] || 9999;
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 销毁设备管理器
   */
  public destroy(): void {
    logger.info('DeviceManager', '销毁设备管理器');
    
    // 停止设备发现
    this.stopDeviceDiscovery();
    
    // 断开所有连接
    this.connectedDevices.forEach((_, deviceId) => {
      this.disconnectDevice(deviceId);
    });
    
    // 清理定时器
    this.heartbeatTimers.forEach((timer, deviceId) => {
      clearInterval(timer);
    });
    this.heartbeatTimers.clear();
    
    // 清理回调
    this.deviceFoundCallbacks = [];
    this.connectionCallbacks.clear();
    
    this.isInitialized = false;
  }
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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