鸿蒙App灯光控制(开关/亮度/色温调节)全解析【华为根技术】

举报
鱼弦 发表于 2025/12/12 10:50:46 2025/12/12
【摘要】 1. 引言随着物联网(IoT)和智能家居技术的飞速发展,灯光控制已从传统的物理开关演变为集成了智能感知、远程控制、场景联动等功能于一体的智能系统。鸿蒙操作系统凭借其分布式架构、软总线技术和原子化服务能力,为智能灯光控制提供了理想的平台,能够实现跨设备无缝协同、低延迟精准控制和丰富的场景化体验。本方案基于鸿蒙系统的分布式能力、设备管理能力、UI框架及后台服务机制,构建一个完整的智能灯光控制系统...


1. 引言

随着物联网(IoT)和智能家居技术的飞速发展,灯光控制已从传统的物理开关演变为集成了智能感知、远程控制、场景联动等功能于一体的智能系统。鸿蒙操作系统凭借其分布式架构、软总线技术和原子化服务能力,为智能灯光控制提供了理想的平台,能够实现跨设备无缝协同、低延迟精准控制和丰富的场景化体验。
本方案基于鸿蒙系统的分布式能力、设备管理能力、UI框架及后台服务机制,构建一个完整的智能灯光控制系统。该系统支持对各类智能灯具(如LED灯泡、灯带、吸顶灯等)的开关控制、亮度调节(0-100%)、色温调节(2500K-6500K暖冷光)以及RGB彩色灯光控制,同时具备场景模式(阅读、观影、睡眠等)、定时任务、语音控制和自动化联动等高级功能。通过手机、平板、智慧屏等多设备的分布式协同,用户可在任意终端便捷管理家中灯光,打造舒适、节能、个性化的光环境。

2. 技术背景

2.1 鸿蒙智能设备控制能力基础

鸿蒙系统为智能灯光控制提供了多层次的技术支撑:
核心技术
作用描述
在灯光控制中的应用
分布式软总线
设备间低延迟通信通道
手机/平板控制智能灯具,跨设备状态同步
设备虚拟化
将远端设备虚拟成本地设备
智慧屏直接控制客厅灯具,无需中转
原子化服务
免安装、即点即用的轻量化服务
快速控制灯光开关、调节亮度的原子化卡片
后台服务
长时间运行的任务管理
定时开关灯、场景模式的后台执行
数据管理
本地/分布式数据存储
保存用户偏好、场景配置、设备状态
UI框架(ArkUI)
声明式UI开发
直观的灯光控制界面(滑块、色盘等)
权限管理
精细化权限控制
确保灯光控制的安全性,防止未授权访问
传感器服务
光线、人体感应等数据采集
根据环境光自动调节亮度,人来灯亮人走灯灭

2.2 灯光控制技术架构

graph TD
    subgraph 控制终端层(多设备)
        A[手机] --> A1[灯光控制App]
        B[平板] --> B1[灯光控制App]
        C[智慧屏] --> C1[灯光控制App]
        D[智能手表] --> D1[快捷控制Widget]
    end
    
    subgraph 鸿蒙分布式中间件
        E[分布式软总线] --> F[设备发现服务]
        F --> G[设备连接管理]
        G --> H[命令路由中心]
        H --> I[状态同步服务]
        J[原子化服务框架] --> K[快捷控制入口]
    end
    
    subgraph 智能灯具层
        L[智能灯泡] --> L1[通信模块(WiFi/Zigbee)]
        M[灯带控制器] --> M1[通信模块]
        N[吸顶灯网关] --> N1[通信模块]
        L1 --> O[灯光驱动]
        M1 --> P[灯光驱动]
        N1 --> Q[灯光驱动]
    end
    
    subgraph 云服务与AI层
        R[华为云IoT平台] --> S[设备管理]
        S --> T[数据存储与分析]
        U[AI引擎] --> V[场景智能推荐]
        V --> W[自动化规则学习]
    end
    
    A1 --> H
    B1 --> H
    C1 --> H
    D1 --> K
    K --> H
    H --> L1
    H --> M1
    H --> N1
    L1 --> O
    M1 --> P
    N1 --> Q
    O --> S
    P --> S
    Q --> S
    S --> T
    T --> U

2.3 关键技术特性

  1. 多协议兼容:支持WiFi、蓝牙BLE、Zigbee、红外等多种通信协议,适配主流智能灯具品牌
  2. 分布式协同:手机设置的灯光状态实时同步到平板和智慧屏,多终端控制无冲突
  3. 精细控制:亮度调节精度达1%,色温调节步长100K,支持1600万色RGB调节
  4. 低延迟响应:本地控制延迟<100ms,远程控制延迟<300ms,接近物理开关体验
  5. 场景化联动:与人体感应、光线传感器联动,实现"回家开灯"、"日落调暗"等自动化场景
  6. 能耗监测:实时统计各灯具用电量,提供节能建议,支持峰谷电价时段自动调节
  7. 安全可靠:端到端加密通信,设备绑定认证,异常操作预警,保障家庭安全
  8. 离线控制:局域网内设备可直接通信,无互联网时仍可实现基本控制功能

3. 应用使用场景

3.1 典型应用场景分类

场景类型
需求描述
技术要求
实现重点
家庭日常照明
客厅、卧室灯光开关/亮度/色温调节
多设备控制、状态同步
分布式数据管理与UI同步
场景模式切换
阅读模式(暖光4000K)、观影模式(暗光)、睡眠模式(关灯)
场景配置存储、一键切换
场景模板与参数持久化
远程控制
外出时通过手机查看并控制家中灯光
云端连接、安全认证
设备在线状态检测与远程唤醒
定时任务
早晨7点渐亮唤醒,晚上11点自动关灯
定时器服务、渐变效果
后台服务与平滑过渡算法
语音控制
通过小艺语音助手控制灯光
语音识别集成、意图解析
原子化服务与语音指令映射
智能联动
开门时玄关灯亮,检测到人体移动时走廊灯亮
传感器数据接入、规则引擎
分布式事件总线与自动化规则
商业空间
店铺营业时间灯光自动开启,打烊后调暗节能
多设备分组管理、权限控制
设备分组与角色权限体系
特殊场合
派对模式(RGB变色闪烁)、节日主题灯光
动态效果生成、音乐律动
特效引擎与音频可视化

3.2 场景复杂度分析

  • 简单场景:单房间单灯具控制,本地WiFi网络,基础开关/亮度调节
  • 中级场景:多房间多灯具分组控制,场景模式切换,定时任务,局域网内多终端协同
  • 复杂场景:跨空间联动(如客厅与阳台灯光协同),传感器融合(人体+光线+时间),云端备份与恢复,第三方平台对接(如HomeKit、天猫精灵)
  • 企业级场景:大型商场/办公楼分区控制,能耗分析与优化,设备批量配置与维护,多用户权限管理

4. 核心原理与流程图

4.1 灯光控制系统架构图

graph TD
    subgraph 应用层
        A[灯光控制App] --> B[设备列表页]
        A --> C[灯光控制页]
        A --> D[场景管理页]
        A --> E[定时任务页]
        F[原子化服务卡片] --> G[快捷开关]
        F --> H[亮度调节]
    end
    
    subgraph 服务层
        I[DeviceManager] --> J[设备发现与连接]
        K[LightController] --> L[开关/亮度/色温控制]
        M[SceneManager] --> N[场景配置与执行]
        O[SchedulerService] --> P[定时任务调度]
        Q[NetworkManager] --> R[网络通信与协议适配]
        S[SensorMonitor] --> T[传感器数据采集]
    end
    
    subgraph 核心能力层
        U[DistributedData] --> V[设备状态分布式同步]
        W[Preferences] --> X[用户配置本地存储]
        Y[BackgroundTask] --> Z[后台服务管理]
        AA[Crypto] --> BB[通信加密]
    end
    
    subgraph 驱动层
        CC[WiFiDriver] --> DD[WiFi设备控制]
        EE[BleDriver] --> FF[蓝牙设备控制]
        GG[ZigbeeDriver] --> HH[Zigbee网关控制]
    end
    
    subgraph 硬件层
        II[智能灯泡] --> JJ[LED驱动电路]
        KK[灯带控制器] --> LL[PWM调光电路]
        MM[吸顶灯] --> NN[电源管理模块]
    end
    
    A --> I
    A --> K
    A --> M
    A --> O
    F --> K
    I --> J
    J --> R
    R --> CC
    R --> EE
    R --> GG
    CC --> II
    EE --> KK
    GG --> MM
    K --> L
    L --> V
    M --> N
    N --> X
    O --> P
    P --> Z
    T --> S
    S --> M
    V --> U
    U --> B
    U --> C

4.2 灯光控制工作流程

4.2.1 设备发现与控制流程

sequenceDiagram
    participant User as 用户
    participant App as 灯光控制App
    participant DeviceMgr as DeviceManager
    participant LightCtrl as LightController
    participant Device as 智能灯具
    participant Cloud as 云平台(可选)
    
    User->>App: 打开设备列表/添加设备
    App->>DeviceMgr: 扫描附近设备
    DeviceMgr->>DeviceMgr: 通过WiFi/BLE/Zigbee扫描
    DeviceMgr->>Device: 发送设备发现请求
    Device->>DeviceMgr: 响应设备信息(型号、状态)
    DeviceMgr->>App: 返回发现的设备列表
    App->>User: 显示设备列表(未绑定/已绑定)
    
    User->>App: 选择设备并绑定
    App->>DeviceMgr: 发起绑定请求
    DeviceMgr->>Device: 发送绑定指令(含认证信息)
    Device->>DeviceMgr: 确认绑定成功
    DeviceMgr->>App: 绑定成功通知
    App->>User: 提示绑定成功,设备添加到列表
    
    User->>App: 调节灯光(开关/亮度/色温)
    App->>LightCtrl: 发送控制指令(设备ID, 参数)
    LightCtrl->>LightCtrl: 参数校验(范围、合法性)
    LightCtrl->>DeviceMgr: 获取设备通信协议
    DeviceMgr->>LightCtrl: 返回协议信息(WiFi/BLE等)
    LightCtrl->>Device: 发送控制命令(编码为协议格式)
    Device->>LightCtrl: 执行结果反馈(成功/失败)
    LightCtrl->>App: 返回控制结果
    App->>User: 更新UI状态(如开关图标、亮度滑块)
    LightCtrl->>DeviceMgr: 更新设备状态缓存
    DeviceMgr->>DistributedData: 同步状态到其他设备

4.2.2 场景模式执行流程

sequenceDiagram
    participant User as 用户
    participant App as 灯光控制App
    participant SceneMgr as SceneManager
    participant LightCtrl as LightController
    participant Device as 智能灯具
    participant Scheduler as 定时任务服务
    
    User->>App: 创建/编辑场景(如"阅读模式")
    App->>SceneMgr: 打开场景编辑器
    SceneMgr->>User: 显示场景配置界面(选择设备、设置参数)
    User->>SceneMgr: 配置场景参数(客厅灯:开,亮度80%,色温4000K)
    SceneMgr->>SceneMgr: 验证参数有效性
    SceneMgr->>Preferences: 保存场景配置(JSON格式)
    Preferences->>SceneMgr: 保存成功确认
    SceneMgr->>App: 场景保存成功通知
    App->>User: 提示场景创建成功
    
    User->>App: 触发场景("阅读模式")
    App->>SceneMgr: 执行场景(场景ID)
    SceneMgr->>Preferences: 读取场景配置
    Preferences->>SceneMgr: 返回场景参数
    SceneMgr->>LightCtrl: 遍历场景中的设备控制指令
    loop 对每个设备
        LightCtrl->>Device: 发送控制命令(按场景参数)
        Device->>LightCtrl: 执行结果反馈
    end
    LightCtrl->>SceneMgr: 所有设备控制完成
    SceneMgr->>App: 场景执行结果
    App->>User: 显示场景执行成功(如所有灯已调至阅读模式)
    
    Scheduler->>Scheduler: 定时检查任务(如每天19:00执行"晚餐模式")
    Scheduler->>SceneMgr: 触发定时场景
    SceneMgr->>LightCtrl: 执行场景控制指令
    LightCtrl->>Device: 批量控制设备
    Device->>LightCtrl: 执行反馈
    LightCtrl->>SceneMgr: 场景执行完成

4.3 工作原理详解

  1. 设备发现与绑定
    • 应用启动时,DeviceManager通过分布式软总线和各通信协议(WiFi/BLE/Zigbee)扫描附近智能灯具
    • 发现设备后,通过设备型号匹配预置的设备驱动,发起绑定请求(含认证密钥)
    • 绑定成功后,设备信息(ID、型号、支持的功能)存储于本地Preferences和分布式数据库中,供多设备同步
  2. 控制指令下发
    • 用户在UI界面操作(如拖动亮度滑块),LightController接收控制参数(设备ID、开关状态、亮度值、色温值)
    • 参数经校验后,根据设备ID从DeviceManager获取通信协议,编码为对应协议的指令格式(如WiFi设备的JSON指令、BLE的特征值写入)
    • 指令通过对应驱动发送至设备,设备执行后返回状态反馈,更新本地状态和分布式缓存
  3. 状态同步机制
    • 采用鸿蒙DistributedData实现设备状态的分布式同步,任一终端控制灯光后,状态变更会广播至同一超级终端内的其他设备
    • 设备离线时,状态暂存于本地,上线后通过心跳包或主动查询同步最新状态
    • 本地Preferences作为一级缓存,存储用户配置(场景、定时任务),分布式数据库作为二级同步,确保数据一致性
  4. 场景与自动化
    • SceneManager负责场景配置的CRUD操作,场景参数以JSON格式存储,包含设备列表及各设备的目标状态
    • 定时任务由SchedulerService(基于鸿蒙BackgroundTask)管理,通过系统闹钟触发场景执行
    • 传感器数据(如人体红外、光线强度)通过SensorMonitor采集,结合规则引擎(如"光线<50lux且有人移动时开灯")触发自动化控制
  5. 安全与可靠性
    • 设备绑定采用密钥对认证,通信过程使用AES-128加密,防止指令篡改和窃听
    • 控制指令添加序列号和校验和,避免重复执行和错误执行
    • 网络异常时,指令缓存于本地队列,网络恢复后重发,确保控制可靠性

5. 环境准备

5.1 开发环境配置

# 1. 安装DevEco Studio 4.0+ (支持API 9+)
# 下载地址: https://developer.harmonyos.com/cn/develop/deveco-studio

# 2. 创建鸿蒙应用项目
# 步骤: File -> New -> Create Project -> 选择"Application" -> "Empty Ability"
# 配置项目信息:
#   - Project name: SmartLightControl
#   - Bundle name: com.example.smartlightcontrol
#   - Save location: 自定义路径
#   - Compile SDK: 9 (或更高版本)
#   - Device type: Phone + Tablet (勾选支持的设备类型)
#   - Language: ArkTS
#   - UI Framework: ArkUI (声明式开发范式)

# 3. 目录结构规划
SmartLightControl/
├── entry/                          # 主模块(灯光控制应用)
│   ├── src/
│   │   ├── main/
│   │   │   ├── ets/                # ArkTS源代码
│   │   │   │   ├── pages/          # 页面组件
│   │   │   │   │   ├── Index.ets            # 首页(设备列表)
│   │   │   │   │   ├── LightControl.ets     # 灯光控制页
│   │   │   │   │   ├── SceneManagement.ets # 场景管理页
│   │   │   │   │   ├── ScheduleTask.ets     # 定时任务页
│   │   │   │   │   └── Settings.ets        # 设置页
│   │   │   │   ├── components/      # 公共组件
│   │   │   │   │   ├── DeviceCard.ets       # 设备卡片组件
│   │   │   │   │   ├── BrightnessSlider.ets # 亮度滑块组件
│   │   │   │   │   ├── ColorTempPicker.ets # 色温选择器组件
│   │   │   │   │   ├── RgbColorPicker.ets  # RGB颜色选择器组件
│   │   │   │   │   └── SceneItem.ets        # 场景项组件
│   │   │   │   ├── model/           # 数据模型
│   │   │   │   │   ├── LightDevice.ets     # 灯光设备模型
│   │   │   │   │   ├── Scene.ets           # 场景模型
│   │   │   │   │   ├── Schedule.ets         # 定时任务模型
│   │   │   │   │   └── ControlCommand.ets  # 控制指令模型
│   │   │   │   ├── service/         # 业务逻辑服务
│   │   │   │   │   ├── DeviceManager.ets    # 设备管理服务
│   │   │   │   │   ├── LightController.ets # 灯光控制服务
│   │   │   │   │   ├── SceneManager.ets    # 场景管理服务
│   │   │   │   │   ├── SchedulerService.ets # 定时任务服务
│   │   │   │   │   ├── NetworkAdapter.ets  # 网络适配器(协议适配)
│   │   │   │   │   ├── DistributedSync.ets # 分布式同步服务
│   │   │   │   │   └── SensorMonitor.ets   # 传感器监控服务
│   │   │   │   ├── utils/           # 工具类
│   │   │   │   │   ├── Logger.ets           # 日志工具
│   │   │   │   │   ├── PreferencesUtil.ets # 偏好设置工具
│   │   │   │   │   ├── CryptoUtil.ets      # 加密工具
│   │   │   │   │   ├── ColorUtil.ets       # 颜色转换工具
│   │   │   │   │   └── TimeUtil.ets        # 时间工具
│   │   │   │   ├── application/    # 应用生命周期管理
│   │   │   │   │   ├── MainApplication.ets # 主应用入口
│   │   │   │   │   └── Ability.ets         # 能力基类
│   │   │   │   └── entryability/   # 应用入口能力
│   │   │   │       └── EntryAbility.ets    # 主入口能力
│   │   │   ├── resources/          # 资源文件
│   │   │   │   ├── base/
│   │   │   │   │   ├── element/    # 颜色、字符串、尺寸等资源
│   │   │   │   │   │   ├── color.json
│   │   │   │   │   │   ├── string.json
│   │   │   │   │   │   └── float.json
│   │   │   │   │   ├── media/      # 图片、图标资源
│   │   │   │   │   │   ├── icon_light_on.png
│   │   │   │   │   │   ├── icon_light_off.png
│   │   │   │   │   │   └── bg_scene_reading.jpg
│   │   │   │   │   ├── profile/    # 配置文件
│   │   │   │   │   │   ├── main_pages.json # 页面路由配置
│   │   │   │   │   │   └── module.json5    # 模块配置(权限、 abilities等)
│   │   │   │   │   └── rawfile/    # 原始资源文件(如设备协议文档)
│   │   │   └── module.json5        # 模块配置文件(权限声明等)
│   ├── build-profile.json5         # 构建配置
│   └──hvigorfile.ts                # 构建脚本
└── library/                         # 可选: 公共库模块(如设备协议解析库)
    ├── src/
    │   ├── main/
    │   │   ├── ets/
    │   │   │   └── utils/
    │   │   │       └── ProtocolParser.ets # 协议解析工具
    │   │   └── module.json5
    └── build-profile.json5

5.2 权限配置

entry/src/main/module.json5
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone", "tablet"],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "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": "LightControlAbility",
        "srcEntry": "./ets/application/LightControlAbility.ets",
        "description": "灯光控制能力",
        "icon": "$media:light_control_icon",
        "label": "$string:LightControlAbility_label",
        "exported": true,
        "backgroundModes": ["dataTransfer", "location"] // dataTransfer用于后台设备通信
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "$string:distributed_datasync_reason",
        "usedScene": {
          "abilities": ["EntryAbility", "LightControlAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.ACCESS_NETWORK_STATE",
        "reason": "$string:access_network_state_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.BLUETOOTH",
        "reason": "$string:bluetooth_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.DISCOVER_BLUETOOTH",
        "reason": "$string:discover_bluetooth_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.USE_BLUETOOTH",
        "reason": "$string:use_bluetooth_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.LOCATION",
        "reason": "$string:location_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
        "reason": "$string:keep_background_running_reason",
        "usedScene": {
          "abilities": ["LightControlAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.READ_MEDIA",
        "reason": "$string:read_media_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.WRITE_MEDIA",
        "reason": "$string:write_media_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ],
    "extensionAbilities": [
      {
        "name": "SchedulerExtAbility",
        "type": "service",
        "srcEntry": "./ets/service/SchedulerService.ets",
        "description": "定时任务后台服务",
        "exported": true,
        "backgroundModes": ["dataTransfer"]
      }
    ],
    "definePermissions": [
      {
        "name": "com.example.smartlightcontrol.permission.LIGHT_CONTROL",
        "grantMode": "system_grant",
        "availableLevel": "normal",
        "description": "灯光控制权限"
      }
    ]
  }
}

5.3 依赖配置

entry/build-profile.json5
{
  "apiType": "stageMode",
  "buildOption": {
    "strictMode": {
      "caseSensitiveCheck": true,
      "useNormalizedOHMUrl": true
    },
    "arkOptions": {
      "debug": false,
      "optimize": true
    }
  },
  "buildOptionSet": [
    {
      "name": "release",
      "arkOptions": {
        "debug": false,
        "optimize": true
      }
    }
  ],
  "targets": [
    {
      "name": "default",
      "applyToProducts": ["default"]
    }
  ],
  "products": [
    {
      "name": "default",
      "compatibleSdkVersion": "9",
      "runtimeOS": "HarmonyOS",
      "signingConfig": "default"
    }
  ],
  "dependencies": {
    "@ohos.data.preferences": "9.0.0",
    "@ohos.distributedData": "9.0.0",
    "@ohos.bluetooth": "9.0.0",
    "@ohos.net.connection": "9.0.0",
    "@ohos.sensor": "9.0.0",
    "@ohos.utils": "9.0.0",
    "@ohos.backgroundTaskManager": "9.0.0",
    "library": "file:../library" // 引用公共库(如果有)
  }
}

6. 详细代码实现

6.1 数据模型定义

entry/src/main/ets/model/LightDevice.ets
/**
 * 灯光设备数据模型
 */

/**
 * 设备基本信息
 */
export interface DeviceInfo {
  deviceId: string;            // 设备唯一标识(UUID或MAC地址)
  deviceName: string;          // 设备名称(用户自定义或默认)
  deviceType: DeviceType;      // 设备类型
  brand: string;               // 品牌
  model: string;               // 型号
  firmwareVersion: string;     // 固件版本
  isOnline: boolean;           // 是否在线
  isBound: boolean;            // 是否已绑定
  bindTime: number;            // 绑定时间(时间戳)
  lastActiveTime: number;      // 最后活跃时间(时间戳)
  location: string;            // 设备位置(如"客厅"、"卧室")
  roomId?: string;             // 所属房间ID(可选)
}

/**
 * 设备类型枚举
 */
export enum DeviceType {
  LED_BULB = "led_bulb",       // LED灯泡
  LED_STRIP = "led_strip",     // LED灯带
  CEILING_LIGHT = "ceiling_light", // 吸顶灯
  TABLE_LAMP = "table_lamp",   // 台灯
  SPOTLIGHT = "spotlight",     // 射灯
  STRIP_LIGHT = "strip_light", // 灯条
  PANEL_LIGHT = "panel_light"  // 面板灯
}

/**
 * 灯光能力描述
 */
export interface LightCapability {
  supportSwitch: boolean;       // 支持开关
  supportBrightness: boolean;   // 支持亮度调节(0-100%)
  minBrightness: number;        // 最小亮度(%)
  maxBrightness: number;        // 最大亮度(%)
  supportColorTemperature: boolean; // 支持色温调节(2500K-6500K)
  minColorTemp: number;         // 最暖色温(K)
  maxColorTemp: number;         // 最冷色温(K)
  supportRGB: boolean;          // 支持RGB彩色调节
  supportDimmingCurve: boolean; // 支持调光曲线(线性/对数)
  supportTiming: boolean;       // 支持独立定时
  supportScene: boolean;        // 支持场景模式
  maxScenes: number;            // 最大支持场景数
}

/**
 * 灯光状态
 */
export interface LightState {
  powerOn: boolean;             // 开关状态
  brightness: number;           // 亮度(0-100, 仅支持亮度时有效)
  colorTemperature: number;     // 色温(2500-6500K, 仅支持色温时有效)
  rgbColor?: { r: number; g: number; b: number }; // RGB颜色(0-255, 仅支持RGB时有效)
  hue?: number;                 // 色调(0-360, 可选)
  saturation?: number;          // 饱和度(0-100, 可选)
  temperatureUnit: TemperatureUnit; // 色温单位
  dimmingCurve: DimmingCurve;  // 调光曲线
  transitionTime: number;       // 状态切换过渡时间(毫秒)
  lastUpdateTime: number;       // 状态最后更新时间(时间戳)
}

/**
 * 色温单位枚举
 */
export enum TemperatureUnit {
  KELVIN = "kelvin",           // 开尔文(K)
  MIREDS = "mireds"            // 微倒度(mireds, 1e6/K)
}

/**
 * 调光曲线枚举
 */
export enum DimmingCurve {
  LINEAR = "linear",           // 线性调光
  LOGARITHMIC = "logarithmic", // 对数调光(符合人眼感知)
  S_CURVE = "s_curve"          // S型曲线(平滑过渡)
}

/**
 * 完整的灯光设备信息
 */
export interface LightDevice extends DeviceInfo {
  capability: LightCapability;  // 设备能力
  state: LightState;            // 当前状态
  networkInfo: NetworkInfo;     // 网络信息
  energyConsumption?: EnergyConsumption; // 能耗信息(可选)
  groupIds: string[];           // 所属分组ID列表
}

/**
 * 网络信息
 */
export interface NetworkInfo {
  protocol: NetworkProtocol;    // 通信协议
  ipAddress?: string;          // IP地址(仅WiFi设备)
  port?: number;                // 端口号(仅WiFi设备)
  bleAddress?: string;         // BLE地址(仅BLE设备)
  zigbeeNodeId?: string;       // Zigbee节点ID(仅Zigbee设备)
  signalStrength: number;       // 信号强度(0-100, -1表示未知)
  connectionType: ConnectionType; // 连接方式
}

/**
 * 网络协议枚举
 */
export enum NetworkProtocol {
  WiFi = "wifi",               // WiFi
  BluetoothLE = "ble",         // 蓝牙低功耗(BLE)
  Zigbee = "zigbee",           // Zigbee
  Infrared = "infrared",       // 红外(需网关)
  Matter = "matter"            // Matter协议(新兴标准)
}

/**
 * 连接方式枚举
 */
export enum ConnectionType {
  DIRECT = "direct",           // 直连(设备直接与手机通信)
  GATEWAY = "gateway",         // 网关中继(通过网关连接)
  CLOUD = "cloud"              // 云端中继(通过云平台连接)
}

/**
 * 能耗信息
 */
export interface EnergyConsumption {
  todayConsumption: number;     // 今日耗电量(kWh)
  monthlyConsumption: number;   // 本月耗电量(kWh)
  averagePower: number;         // 平均功率(W)
  voltage?: number;             // 电压(V, 可选)
  current?: number;             // 电流(A, 可选)
  powerFactor?: number;         // 功率因数(可选)
}

/**
 * 控制指令类型
 */
export enum ControlCommandType {
  SWITCH = "switch",           // 开关指令
  BRIGHTNESS = "brightness",   // 亮度调节指令
  COLOR_TEMP = "color_temp",   // 色温调节指令
  RGB_COLOR = "rgb_color",     // RGB颜色调节指令
  SCENE = "scene",             // 场景切换指令
  TIMING = "timing"            // 定时设置指令
}

/**
 * 控制指令基类
 */
export interface BaseControlCommand {
  commandId: string;            // 指令唯一ID(用于去重和追踪)
  deviceId: string;            // 目标设备ID
  commandType: ControlCommandType; // 指令类型
  timestamp: number;           // 指令生成时间戳
  transitionTime?: number;     // 过渡时间(可选, 覆盖设备默认)
  priority: CommandPriority;   // 指令优先级
}

/**
 * 指令优先级枚举
 */
export enum CommandPriority {
  HIGH = 0,                    // 高(立即执行, 如安全相关)
  NORMAL = 1,                  // 普通(默认)
  LOW = 2                      // 低(可合并或延迟执行)
}

/**
 * 开关指令
 */
export interface SwitchCommand extends BaseControlCommand {
  commandType: ControlCommandType.SWITCH;
  powerOn: boolean;             // 目标开关状态
}

/**
 * 亮度调节指令
 */
export interface BrightnessCommand extends BaseControlCommand {
  commandType: ControlCommandType.BRIGHTNESS;
  brightness: number;           // 目标亮度(0-100)
  curve?: DimmingCurve;         // 调光曲线(可选)
}

/**
 * 色温调节指令
 */
export interface ColorTemperatureCommand extends BaseControlCommand {
  commandType: ControlCommandType.COLOR_TEMP;
  colorTemperature: number;     // 目标色温(2500-6500K)
  unit: TemperatureUnit;        // 色温单位
}

/**
 * RGB颜色调节指令
 */
export interface RgbColorCommand extends BaseControlCommand {
  commandType: ControlCommandType.RGB_COLOR;
  rgbColor: { r: number; g: number; b: number }; // 目标RGB颜色(0-255)
  brightness?: number;          // 可选: 同时设置亮度(0-100)
}

/**
 * 场景切换指令
 */
export interface SceneCommand extends BaseControlCommand {
  commandType: ControlCommandType.SCENE;
  sceneId: string;              // 场景ID
  sceneParams?: Record<string, any>; // 场景参数(可选)
}

/**
 * 定时设置指令
 */
export interface TimingCommand extends BaseControlCommand {
  commandType: ControlCommandType.TIMING;
  taskId?: string;              // 定时任务ID(更新时需指定)
  action: "add" | "update" | "delete"; // 操作类型
  schedule: Schedule;           // 定时计划
}

/**
 * 定时计划
 */
export interface Schedule {
  name: string;                // 任务名称
  triggerTime: number;         // 触发时间(时间戳)
  repeatType: RepeatType;       // 重复类型
  repeatDays?: number[];        // 重复日期(0-6, 0=周日, 可选)
  enabled: boolean;             // 是否启用
  action: Omit<BaseControlCommand, "commandId" | "timestamp">; // 执行的动作
}

/**
 * 重复类型枚举
 */
export enum RepeatType {
  ONCE = "once",               // 单次
  DAILY = "daily",             // 每天
  WEEKLY = "weekly",           // 每周
  MONTHLY = "monthly"          // 每月
}

/**
 * 设备发现结果
 */
export interface DeviceDiscoveryResult {
  devices: LightDevice[];       // 发现的设备列表
  protocol: NetworkProtocol;    // 发现使用的协议
  timestamp: number;            // 发现时间
}

6.2 工具类实现

entry/src/main/ets/utils/Logger.ets
/**
 * 日志工具类 - 封装系统日志接口,提供分级日志功能
 */
export class Logger {
  private static readonly TAG_PREFIX: string = 'SmartLightControl';
  private static readonly IS_DEBUG: boolean = true; // 发布版本应设为false

  /**
   * 调试日志
   * @param message 日志内容
   * @param tag 日志标签(默认为TAG_PREFIX)
   */
  static d(message: string, tag: string = Logger.TAG_PREFIX): void {
    if (Logger.IS_DEBUG) {
      console.debug(`[${tag}] ${message}`);
    }
  }

  /**
   * 信息日志
   * @param message 日志内容
   * @param tag 日志标签
   */
  static i(message: string, tag: string = Logger.TAG_PREFIX): void {
    console.info(`[${tag}] ${message}`);
  }

  /**
   * 警告日志
   * @param message 日志内容
   * @param tag 日志标签
   */
  static w(message: string, tag: string = Logger.TAG_PREFIX): void {
    console.warn(`[${tag}] ${message}`);
  }

  /**
   * 错误日志
   * @param message 日志内容
   * @param tag 日志标签
   * @param error 错误对象(可选)
   */
  static e(message: string, tag: string = Logger.TAG_PREFIX, error?: Error): void {
    let logMsg = `[${tag}] ${message}`;
    if (error) {
      logMsg += `, Error: ${error.message}, Stack: ${error.stack || 'no stack'}`;
    }
    console.error(logMsg);
  }

  /**
   * 关键日志(用于记录严重问题)
   * @param message 日志内容
   * @param tag 日志标签
   */
  static wtf(message: string, tag: string = Logger.TAG_PREFIX): void {
    console.error(`[${tag}] WTF: ${message}`);
  }

  /**
   * 性能计时开始
   * @param label 计时标签
   */
  static timeStart(label: string): void {
    if (Logger.IS_DEBUG) {
      console.time(`[${Logger.TAG_PREFIX}] ${label}`);
    }
  }

  /**
   * 性能计时结束
   * @param label 计时标签
   */
  static timeEnd(label: string): void {
    if (Logger.IS_DEBUG) {
      console.timeEnd(`[${Logger.TAG_PREFIX}] ${label}`);
    }
  }

  /**
   * 设备相关日志
   * @param message 日志内容
   * @param deviceId 设备ID
   */
  static device(message: string, deviceId: string): void {
    Logger.i(`Device[${deviceId.substring(0, 8)}...]: ${message}`, 'Device');
  }

  /**
   * 控制指令日志
   * @param message 日志内容
   * @param command 控制指令
   */
  static command(message: string, command: import('./LightDevice').BaseControlCommand): void {
    Logger.i(`Command[${command.commandId.substring(0, 8)}...][${command.commandType}]: ${message}`, 'Command');
  }
}
entry/src/main/ets/utils/PreferencesUtil.ets
import preferences from '@ohos.data.preferences';
import Logger from './Logger';

/**
 * 偏好设置工具类 - 封装Preferences API,提供设备配置、场景、定时任务的本地存储
 */
export class PreferencesUtil {
  private static readonly DB_NAME: string = 'SmartLightPrefs'; // 数据库名称
  private static prefsInstance: preferences.Preferences | null = null;

  /**
   * 获取Preferences实例(单例模式)
   */
  private static async getPrefsInstance(): Promise<preferences.Preferences> {
    if (!PreferencesUtil.prefsInstance) {
      try {
        // 获取应用上下文(实际开发中需通过AbilityContext获取)
        const context = globalThis.abilityContext; // 假设在Ability中设置了全局上下文
        PreferencesUtil.prefsInstance = await preferences.getPreferences(context, PreferencesUtil.DB_NAME);
        Logger.d('Preferences实例初始化成功', 'PreferencesUtil');
      } catch (error) {
        Logger.e('获取Preferences实例失败', 'PreferencesUtil', error as Error);
        throw new Error('Failed to get preferences instance');
      }
    }
    return PreferencesUtil.prefsInstance;
  }

  /**
   * 存储键值对
   * @param key 键名
   * @param value 值(支持string/number/boolean/Array/object)
   */
  static async put(key: string, value: any): Promise<void> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      let valueToPut: string;
      // 非字符串类型需序列化
      if (typeof value !== 'string') {
        valueToPut = JSON.stringify(value);
      } else {
        valueToPut = value;
      }
      await prefs.put(key, valueToPut);
      await prefs.flush(); // 立即持久化
      Logger.d(`存储键值对成功: key=${key}`, 'PreferencesUtil');
    } catch (error) {
      Logger.e(`存储键值对失败: key=${key}`, 'PreferencesUtil', error as Error);
      throw error;
    }
  }

  /**
   * 获取字符串值
   * @param key 键名
   * @param defaultValue 默认值
   */
  static async getString(key: string, defaultValue: string = ''): Promise<string> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const value = await prefs.get(key, defaultValue) as string;
      Logger.d(`获取字符串值成功: key=${key}, value=${value}`, 'PreferencesUtil');
      return value;
    } catch (error) {
      Logger.e(`获取字符串值失败: key=${key}`, 'PreferencesUtil', error as Error);
      return defaultValue;
    }
  }

  /**
   * 获取数值
   * @param key 键名
   * @param defaultValue 默认值
   */
  static async getNumber(key: string, defaultValue: number = 0): Promise<number> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const valueStr = await prefs.get(key, defaultValue.toString()) as string;
      const value = parseFloat(valueStr);
      Logger.d(`获取数值成功: key=${key}, value=${value}`, 'PreferencesUtil');
      return isNaN(value) ? defaultValue : value;
    } catch (error) {
      Logger.e(`获取数值失败: key=${key}`, 'PreferencesUtil', error as Error);
      return defaultValue;
    }
  }

  /**
   * 获取布尔值
   * @param key 键名
   * @param defaultValue 默认值
   */
  static async getBoolean(key: string, defaultValue: boolean = false): Promise<boolean> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const valueStr = await prefs.get(key, defaultValue.toString()) as string;
      const value = valueStr.toLowerCase() === 'true';
      Logger.d(`获取布尔值成功: key=${key}, value=${value}`, 'PreferencesUtil');
      return value;
    } catch (error) {
      Logger.e(`获取布尔值失败: key=${key}`, 'PreferencesUtil', error as Error);
      return defaultValue;
    }
  }

  /**
   * 获取对象(自动反序列化JSON)
   * @param key 键名
   * @param defaultValue 默认值
   */
  static async getObject<T>(key: string, defaultValue: T): Promise<T> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const valueStr = await prefs.get(key, '') as string;
      if (!valueStr) {
        return defaultValue;
      }
      const value = JSON.parse(valueStr) as T;
      Logger.d(`获取对象成功: key=${key}`, 'PreferencesUtil');
      return value;
    } catch (error) {
      Logger.e(`获取对象失败: key=${key}`, 'PreferencesUtil', error as Error);
      return defaultValue;
    }
  }

  /**
   * 删除键
   * @param key 键名
   */
  static async delete(key: string): Promise<void> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      await prefs.delete(key);
      await prefs.flush();
      Logger.d(`删除键成功: key=${key}`, 'PreferencesUtil');
    } catch (error) {
      Logger.e(`删除键失败: key=${key}`, 'PreferencesUtil', error as Error);
      throw error;
    }
  }

  /**
   * 清空所有键值对
   */
  static async clear(): Promise<void> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const allKeys = await prefs.keys();
      for (const key of allKeys) {
        await prefs.delete(key);
      }
      await prefs.flush();
      Logger.d('清空所有键值对成功', 'PreferencesUtil');
    } catch (error) {
      Logger.e('清空所有键值对失败', 'PreferencesUtil', error as Error);
      throw error;
    }
  }

  /**
   * 获取所有键名
   */
  static async getAllKeys(): Promise<string[]> {
    try {
      const prefs = await PreferencesUtil.getPrefsInstance();
      const keys = await prefs.keys();
      Logger.d(`获取所有键名成功, 共${keys.length}个`, 'PreferencesUtil');
      return keys;
    } catch (error) {
      Logger.e('获取所有键名失败', 'PreferencesUtil', error as Error);
      return [];
    }
  }

  /**
   * 存储设备列表
   * @param devices 设备列表
   */
  static async saveDeviceList(devices: import('./LightDevice').LightDevice[]): Promise<void> {
    await PreferencesUtil.put('device_list', devices);
    Logger.i(`保存设备列表成功, 共${devices.length}台设备`, 'PreferencesUtil');
  }

  /**
   * 获取设备列表
   */
  static async getDeviceList(): Promise<import('./LightDevice').LightDevice[]> {
    const defaultDevices: import('./LightDevice').LightDevice[] = [];
    return await PreferencesUtil.getObject('device_list', defaultDevices);
  }

  /**
   * 存储场景配置
   * @param scenes 场景列表
   */
  static async saveScenes(scenes: any[]): Promise<void> { // 实际应使用Scene模型
    await PreferencesUtil.put('scenes', scenes);
    Logger.i(`保存场景配置成功, 共${scenes.length}个场景`, 'PreferencesUtil');
  }

  /**
   * 获取场景配置
   */
  static async getScenes(): Promise<any[]> { // 实际应使用Scene模型
    const defaultScenes: any[] = [];
    return await PreferencesUtil.getObject('scenes', defaultScenes);
  }

  /**
   * 释放资源
   */
  static async release(): Promise<void> {
    if (PreferencesUtil.prefsInstance) {
      await PreferencesUtil.prefsInstance.close();
      PreferencesUtil.prefsInstance = null;
      Logger.d('Preferences资源已释放', 'PreferencesUtil');
    }
  }
}
entry/src/main/ets/utils/ColorUtil.ets
import Logger from './Logger';

/**
 * 颜色转换工具类 - 提供RGB、HSV、色温(K)之间的转换
 */
export class ColorUtil {
  /**
   * RGB转HSV
   * @param r 红色(0-255)
   * @param g 绿色(0-255)
   * @param b 蓝色(0-255)
   * @returns HSV对象{hue: 0-360, saturation: 0-100, value: 0-100}
   */
  static rgbToHsv(r: number, g: number, b: number): { hue: number; saturation: number; value: number } {
    // 归一化到0-1
    const normalizedR = r / 255;
    const normalizedG = g / 255;
    const normalizedB = b / 255;

    const max = Math.max(normalizedR, normalizedG, normalizedB);
    const min = Math.min(normalizedR, normalizedG, normalizedB);
    const delta = max - min;

    let hue = 0;
    const saturation = max === 0 ? 0 : (delta / max) * 100; // 饱和度0-100
    const value = max * 100; // 明度0-100

    if (delta !== 0) {
      switch (max) {
        case normalizedR:
          hue = ((normalizedG - normalizedB) / delta) % 6;
          break;
        case normalizedG:
          hue = (normalizedB - normalizedR) / delta + 2;
          break;
        case normalizedB:
          hue = (normalizedR - normalizedG) / delta + 4;
          break;
      }
      hue = Math.round(hue * 60);
      if (hue < 0) {
        hue += 360;
      }
    }

    Logger.d(`RGB(${r},${g},${b})转HSV: H=${hue}, S=${saturation.toFixed(1)}, V=${value.toFixed(1)}`, 'ColorUtil');
    return { hue, saturation, value };
  }

  /**
   * HSV转RGB
   * @param hue 色调(0-360)
   * @param saturation 饱和度(0-100)
   * @param value 明度(0-100)
   * @returns RGB对象{r: 0-255, g: 0-255, b: 0-255}
   */
  static hsvToRgb(hue: number, saturation: number, value: number): { r: number; g: number; b: number } {
    // 归一化到0-1
    const normalizedHue = hue / 60;
    const normalizedSaturation = saturation / 100;
    const normalizedValue = value / 100;

    const c = normalizedValue * normalizedSaturation;
    const x = c * (1 - Math.abs((normalizedHue % 2) - 1));
    const m = normalizedValue - c;

    let r = 0, g = 0, b = 0;

    const i = Math.floor(normalizedHue);
    switch (i) {
      case 0:
        r = c; g = x; b = 0;
        break;
      case 1:
        r = x; g = c; b = 0;
        break;
      case 2:
        r = 0; g = c; b = x;
        break;
      case 3:
        r = 0; g = x; b = c;
        break;
      case 4:
        r = x; g = 0; b = c;
        break;
      case 5:
        r = c; g = 0; b = x;
        break;
      default:
        r = c; g = x; b = 0;
    }

    // 还原并取整
    r = Math.round((r + m) * 255);
    g = Math.round((g + m) * 255);
    b = Math.round((b + m) * 255);

    Logger.d(`HSV(H=${hue}, S=${saturation}, V=${value})转RGB: (${r},${g},${b})`, 'ColorUtil');
    return { r, g, b };
  }

  /**
   * 色温(K)转RGB近似值
   * @param kelvin 色温(2500-6500K)
   * @returns RGB对象{r: 0-255, g: 0-255, b: 0-255}
   * 注: 此为近似转换,实际色温转RGB需更复杂算法
   */
  static colorTempToRgb(kelvin: number): { r: number; g: number; b: number } {
    // 限制色温范围
    const clampedKelvin = Math.max(2500, Math.min(6500, kelvin));
    let temp = clampedKelvin / 100;

    let r: number, g: number, b: number;

    // 基于Tanner Helland的简单近似公式
    if (temp <= 66) {
      r = 255;
      g = temp;
      g = 99.4708025861 * Math.log(g) - 161.1195681661;
    } else {
      r = temp - 60;
      r = 329.698727446 * Math.pow(r, -0.1332047592);
      g = temp - 60;
      g = 288.1221695283 * Math.pow(g, -0.0755148492);
    }

    if (temp >= 66) {
      b = 255;
    } else if (temp <= 19) {
      b = 0;
    } else {
      b = temp - 10;
      b = 138.5177312231 * Math.log(b) - 305.0447927307;
    }

    // 限制RGB值在0-255范围内
    r = Math.max(0, Math.min(255, Math.round(r)));
    g = Math.max(0, Math.min(255, Math.round(g)));
    b = Math.max(0, Math.min(255, Math.round(b)));

    Logger.d(`色温${kelvin}K转RGB: (${r},${g},${b})`, 'ColorUtil');
    return { r, g, b };
  }

  /**
   * RGB转十六进制颜色字符串
   * @param r 红色(0-255)
   * @param g 绿色(0-255)
   * @param b 蓝色(0-255)
   * @returns 十六进制字符串(如"#RRGGBB")
   */
  static rgbToHex(r: number, g: number, b: number): string {
    const hexR = r.toString(16).padStart(2, '0');
    const hexG = g.toString(16).padStart(2, '0');
    const hexB = b.toString(16).padStart(2, '0');
    const hex = `#${hexR}${hexG}${hexB}`.toUpperCase();
    Logger.d(`RGB(${r},${g},${b})转十六进制: ${hex}`, 'ColorUtil');
    return hex;
  }

  /**
   * 十六进制颜色字符串转RGB
   * @param hex 十六进制字符串(如"#RRGGBB"或"RRGGBB")
   * @returns RGB对象{r: 0-255, g: 0-255, b: 0-255}
   */
  static hexToRgb(hex: string): { r: number; g: number; b: number } {
    // 去除前缀并转为大写
    let pureHex = hex.startsWith('#') ? hex.substring(1) : hex;
    pureHex = pureHex.toUpperCase();

    // 验证长度
    if (pureHex.length !== 6) {
      throw new Error('Invalid hex color format, must be 6 characters');
    }

    // 解析RGB分量
    const r = parseInt(pureHex.substring(0, 2), 16);
    const g = parseInt(pureHex.substring(2, 4), 16);
    const b = parseInt(pureHex.substring(4, 6), 16);

    if (isNaN(r) || isNaN(g) || isNaN(b)) {
      throw new Error('Invalid hex color format, contains non-hex characters');
    }

    Logger.d(`十六进制${hex}转RGB: (${r},${g},${b})`, 'ColorUtil');
    return { r, g, b };
  }

  /**
   * 计算颜色的相对亮度(用于WCAG对比度检查)
   * @param r 红色(0-255)
   * @param g 绿色(0-255)
   * @param b 蓝色(0-255)
   * @returns 相对亮度(0-1)
   */
  static calculateRelativeLuminance(r: number, g: number, b: number): number {
    // 归一化并应用伽马校正
    const gammaCorrect = (channel: number) => {
      const normalized = channel / 255;
      return normalized <= 0.03928 
        ? normalized / 12.92 
        : Math.pow((normalized + 0.055) / 1.055, 2.4);
    };

    const rLinear = gammaCorrect(r);
    const gLinear = gammaCorrect(g);
    const bLinear = gammaCorrect(b);

    // 计算相对亮度(ITU-R BT.709系数)
    const luminance = 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear;
    return luminance;
  }

  /**
   * 计算两种颜色的对比度
   * @param rgb1 第一种颜色的RGB
   * @param rgb2 第二种颜色的RGB
   * @returns 对比度比值(≥1)
   */
  static calculateContrastRatio(
    rgb1: { r: number; g: number; b: number },
    rgb2: { r: number; g: number; b: number }
  ): number {
    const lum1 = ColorUtil.calculateRelativeLuminance(rgb1.r, rgb1.g, rgb1.b);
    const lum2 = ColorUtil.calculateRelativeLuminance(rgb2.r, rgb2.g, rgb2.b);

    const lighter = Math.max(lum1, lum2);
    const darker = Math.min(lum1, lum2);

    const contrastRatio = (lighter + 0.05) / (darker + 0.05);
    Logger.d(`颜色对比度: ${contrastRatio.toFixed(2)}:1`, 'ColorUtil');
    return contrastRatio;
  }
}
entry/src/main/ets/utils/CryptoUtil.ets
import cryptoFramework from '@ohos.security.cryptoFramework';
import util from '@ohos.util';
import Logger from './Logger';

/**
 * 加密工具类 - 提供AES对称加密、SHA哈希等安全功能
 */
export class CryptoUtil {
  private static readonly ALGORITHM_AES_GCM = "AES128|GCM|PKCS7";
  private static readonly KEY_ALIAS = "SmartLightControl_AES_Key";
  private static readonly IV_LENGTH = 12; // GCM推荐IV长度12字节
  private static readonly TAG_LENGTH = 16; // 认证标签长度16字节

  /**
   * 生成随机字节数组
   * @param length 字节长度
   * @returns 随机字节数组
   */
  static async generateRandomBytes(length: number): Promise<Uint8Array> {
    try {
      const randomGenerator = cryptoFramework.createRandomGenerator();
      const randomBytes = new Uint8Array(length);
      await randomGenerator.fill(randomBytes);
      Logger.d(`生成${length}字节随机数据`, 'CryptoUtil');
      return randomBytes;
    } catch (error) {
      Logger.e('生成随机字节失败', 'CryptoUtil', error as Error);
      throw error;
    }
  }

  /**
   * 获取或生成AES密钥
   * @returns AES密钥材料
   */
  private static async getOrCreateAesKey(): Promise<cryptoFramework.Key> {
    try {
      const keyStore = cryptoFramework.createKeyStore('cryptoFrameworkKeyStore');
      await keyStore.open();
      
      // 尝试获取现有密钥
      try {
        const existingKey = await keyStore.getKey(CryptoUtil.KEY_ALIAS);
        Logger.d('获取现有AES密钥成功', 'CryptoUtil');
        await keyStore.close();
        return existingKey;
      } catch (e) {
        // 密钥不存在,创建新密钥
        Logger.d('创建新的AES密钥', 'CryptoUtil');
        const symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES128');
        const keyBlob = await CryptoUtil.generateRandomBytes(16); // AES-128需要16字节密钥
        const key = await symKeyGenerator.convertKey(keyBlob, null);
        
        // 存储密钥
        await keyStore.addKey(CryptoUtil.KEY_ALIAS, key, null);
        await keyStore.close();
        return key;
      }
    } catch (error) {
      Logger.e('获取或创建AES密钥失败', 'CryptoUtil', error as Error);
      throw error;
    }
  }

  /**
   * AES-GCM加密数据
   * @param plaintext 明文数据(string或Uint8Array)
   * @returns 加密后的密文(包含IV和认证标签)
   */
  static async encryptAesGcm(plaintext: string | Uint8Array): Promise<{ iv: Uint8Array; ciphertext: Uint8Array; authTag: Uint8Array }> {
    try {
      // 准备明文数据
      let plainData: Uint8Array;
      if (typeof plaintext === 'string') {
        const textEncoder = new util.TextEncoder();
        plainData = textEncoder.encodeInto(plaintext);
      } else {
        plainData = plaintext;
      }

      // 生成随机IV
      const iv = await CryptoUtil.generateRandomBytes(CryptoUtil.IV_LENGTH);

      // 获取AES密钥
      const key = await CryptoUtil.getOrCreateAesKey();

      // 创建加密器
      const cipher = cryptoFramework.createCipher(CryptoUtil.ALGORITHM_AES_GCM);
      await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, {
        iv: iv,
        aad: new Uint8Array(0) // 附加认证数据(此处为空)
      });

      // 执行加密
      const encryptedData = await cipher.doFinal(plainData);

      // 提取认证标签(GCM模式下doFinal返回的密文包含认证标签)
      const ciphertext = encryptedData.slice(0, encryptedData.byteLength - CryptoUtil.TAG_LENGTH);
      const authTag = encryptedData.slice(encryptedData.byteLength - CryptoUtil.TAG_LENGTH);

      Logger.d(`AES-GCM加密成功, 明文长度=${plainData.byteLength}, 密文长度=${ciphertext.byteLength}`, 'CryptoUtil');
      return { iv, ciphertext, authTag };
    } catch (error) {
      Logger.e('AES-GCM加密失败', 'CryptoUtil', error as Error);
      throw error;
    }
  }

  /**
   * AES-GCM解密数据
   * @param iv 初始化向量
   * @param ciphertext 密文
   * @param authTag 认证标签
   * @returns 解密后的明文(string)
   */
  static async decryptAesGcm(iv: Uint8Array, ciphertext: Uint8Array, authTag: Uint8Array): Promise<string> {
    try {
      // 组合密文和认证标签
      const encryptedData = new Uint8Array([...ciphertext, ...authTag]);

      // 获取AES密钥
      const key = await CryptoUtil.getOrCreateAesKey();

      // 创建解密器
      const decipher = cryptoFramework.createCipher(CryptoUtil.ALGORITHM_AES_GCM);
      await decipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, {
        iv: iv,
        aad: new Uint8Array(0)
      });

      // 执行解密
      const decryptedData = await decipher.doFinal(encryptedData);

      // 转换为字符串
      const textDecoder = new util.TextDecoder();
      const plaintext = textDecoder.decodeToString(decryptedData);

      Logger.d(`AES-GCM解密成功, 密文长度=${ciphertext.byteLength}, 明文长度=${decryptedData.byteLength}`, 'CryptoUtil');
      return plaintext;
    } catch (error) {
      Logger.e('AES-GCM解密失败', 'CryptoUtil', error as Error);
      throw new Error('Decryption failed, invalid ciphertext or authentication failed');
    }
  }

  /**
   * SHA-256哈希计算
   * @param data 输入数据(string或Uint8Array)
   * @returns 哈希值(十六进制字符串)
   */
  static async sha256(data: string | Uint8Array): Promise<string> {
    try {
      let inputData: Uint8Array;
      if (typeof data === 'string') {
        const textEncoder = new util.TextEncoder();
        inputData = textEncoder.encodeInto(data);
      } else {
        inputData = data;
      }

      // 创建哈希器
      const hash = cryptoFramework.createHash("SHA256");
      await hash.update(inputData);

      // 获取哈希结果
      const digest = await hash.digest();
      const hashHex = Array.from(new Uint8Array(digest.data))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('')
        .toUpperCase();

      Logger.d(`SHA-256哈希计算成功, 输入长度=${inputData.byteLength}, 哈希长度=${hashHex.length}`, 'CryptoUtil');
      return hashHex;
    } catch (error) {
      Logger.e('SHA-256哈希计算失败', 'CryptoUtil', error as Error);
      throw error;
    }
  }

  /**
   * 生成设备认证令牌(基于设备ID和密钥)
   * @param deviceId 设备ID
   * @returns 认证令牌
   */
  static async generateAuthToken(deviceId: string): Promise<string> {
    const secretKey = "SmartLight_Control_Secret_Key"; // 实际应用中应从安全存储获取
    const data = `${deviceId}:${Date.now()}`;
    const token = await CryptoUtil.sha256(`${data}:${secretKey}`);
    Logger.d(`生成设备认证令牌: deviceId=${deviceId}`, 'CryptoUtil');
    return token;
  }
}

6.3 设备管理服务实现

entry/src/main/ets/service/DeviceManager.ets
import { LightDevice, DeviceDiscoveryResult, NetworkProtocol, DeviceType } from '../model/LightDevice';
import { Logger } from '../utils/Logger';
import { PreferencesUtil } from '../utils/PreferencesUtil';
import distributedDeviceManager from '@ohos.distributedHardware.deviceManager';
import bluetooth from '@ohos.bluetooth';
import network from '@ohos.net.connection';
import { BusinessError } from '@ohos.base';

/**
 * 设备管理服务 - 负责设备发现、绑定、状态管理和分布式同步
 */
export class DeviceManager {
  private static instance: DeviceManager;
  private deviceManager: distributedDeviceManager.DeviceManager | null = null;
  private discoveredDevices: Map<string, LightDevice> = new Map(); // 发现的设备(未绑定)
  private boundDevices: Map<string, LightDevice> = new Map();    // 已绑定的设备
  private context: any; // 应用上下文(AbilityContext)
  private isInitialized: boolean = false;
  private deviceStateListeners: Map<string, Set<DeviceStateListener>> = new Map();

  private constructor(context: any) {
    this.context = context;
    this.initDeviceManager();
  }

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

  /**
   * 初始化设备管理器(分布式设备管理和蓝牙管理)
   */
  private async initDeviceManager(): Promise<void> {
    try {
      Logger.d('初始化设备管理器', 'DeviceManager');

      // 初始化分布式设备管理器
      this.deviceManager = distributedDeviceManager.createDeviceManager(this.context);
      this.registerDeviceStateCallbacks();

      // 加载已绑定设备
      await this.loadBoundDevices();

      this.isInitialized = true;
      Logger.i('设备管理器初始化成功', 'DeviceManager');
    } catch (error) {
      Logger.e('设备管理器初始化失败', 'DeviceManager', error as BusinessError);
      this.isInitialized = false;
    }
  }

  /**
   * 注册设备状态回调(分布式设备上线/离线通知)
   */
  private registerDeviceStateCallbacks(): void {
    if (!this.deviceManager) return;

    // 设备上线回调
    this.deviceManager.on('deviceOnline', (device: distributedDeviceManager.DeviceInfo) => {
      Logger.i(`分布式设备上线: ${device.deviceName}(${device.deviceId}), 类型: ${device.deviceTypeId}`, 'DeviceManager');
      this.handleDeviceOnline(device);
    });

    // 设备离线回调
    this.deviceManager.on('deviceOffline', (device: distributedDeviceManager.DeviceInfo) => {
      Logger.i(`分布式设备离线: ${device.deviceName}(${device.deviceId})`, 'DeviceManager');
      this.handleDeviceOffline(device);
    });

    // 设备信息变更回调
    this.deviceManager.on('deviceInfoChanged', (device: distributedDeviceManager.DeviceInfo) => {
      Logger.d(`分布式设备信息变更: ${device.deviceName}`, 'DeviceManager');
      this.updateDistributedDeviceInfo(device);
    });
  }

  /**
   * 处理分布式设备上线
   */
  private handleDeviceOnline(device: distributedDeviceManager.DeviceInfo): void {
    // 检查是否为已知的灯光设备
    const knownDevice = this.boundDevices.get(device.deviceId);
    if (knownDevice) {
      // 更新设备在线状态
      const updatedDevice: LightDevice = {
        ...knownDevice,
        isOnline: true,
        lastActiveTime: Date.now()
      };
      this.boundDevices.set(device.deviceId, updatedDevice);
      this.notifyDeviceStateChanged(updatedDevice, 'online');
      Logger.device(`设备上线: ${knownDevice.deviceName}`, device.deviceId);
    }
  }

  /**
   * 处理分布式设备离线
   */
  private handleDeviceOffline(device: distributedDeviceManager.DeviceInfo): void {
    const knownDevice = this.boundDevices.get(device.deviceId);
    if (knownDevice) {
      const updatedDevice: LightDevice = {
        ...knownDevice,
        isOnline: false,
        lastActiveTime: Date.now()
      };
      this.boundDevices.set(device.deviceId, updatedDevice);
      this.notifyDeviceStateChanged(updatedDevice, 'offline');
      Logger.device(`设备离线: ${knownDevice.deviceName}`, device.deviceId);
    }
  }

  /**
   * 更新分布式设备信息
   */
  private updateDistributedDeviceInfo(device: distributedDeviceManager.DeviceInfo): void {
    const knownDevice = this.boundDevices.get(device.deviceId);
    if (knownDevice) {
      const updatedDevice: LightDevice = {
        ...knownDevice,
        deviceName: device.deviceName,
        lastActiveTime: Date.now()
      };
      this.boundDevices.set(device.deviceId, updatedDevice);
      this.notifyDeviceStateChanged(updatedDevice, 'info_updated');
    }
  }

  /**
   * 加载已绑定的设备(从本地存储)
   */
  private async loadBoundDevices(): Promise<void> {
    try {
      const savedDevices = await PreferencesUtil.getDeviceList();
      savedDevices.forEach(device => {
        this.boundDevices.set(device.deviceId, device);
        Logger.i(`加载已绑定设备: ${device.deviceName}(${device.deviceId})`, 'DeviceManager');
      });
      Logger.i(`共加载${savedDevices.length}台已绑定设备`, 'DeviceManager');
    } catch (error) {
      Logger.e('加载已绑定设备失败', 'DeviceManager', error as BusinessError);
    }
  }

  /**
   * 发现附近的智能灯具设备
   * @param protocols 要发现的协议类型(默认发现所有支持的协议)
   * @returns 发现的设备列表
   */
  async discoverDevices(protocols: NetworkProtocol[] = [NetworkProtocol.WiFi, NetworkProtocol.BluetoothLE]): Promise<DeviceDiscoveryResult> {
    if (!this.isInitialized) {
      await this.initDeviceManager();
    }

    Logger.d(`开始发现设备, 协议: ${protocols.join(',')}`, 'DeviceManager');
    const discoveredDevices: LightDevice[] = [];
    const timestamp = Date.now();

    try {
      // 根据协议类型选择发现方式
      for (const protocol of protocols) {
        let protocolDevices: LightDevice[] = [];
        switch (protocol) {
          case NetworkProtocol.WiFi:
            protocolDevices = await this.discoverWiFiDevices();
            break;
          case NetworkProtocol.BluetoothLE:
            protocolDevices = await this.discoverBleDevices();
            break;
          // 可扩展其他协议(Zigbee需网关配合)
          default:
            Logger.w(`不支持的协议类型: ${protocol}`, 'DeviceManager');
            continue;
        }
        discoveredDevices.push(...protocolDevices);
      }

      // 去重(基于deviceId)
      const uniqueDevicesMap = new Map<string, LightDevice>();
      discoveredDevices.forEach(device => {
        uniqueDevicesMap.set(device.deviceId, device);
      });
      const uniqueDevices = Array.from(uniqueDevicesMap.values());

      // 更新发现的设备缓存
      this.discoveredDevices.clear();
      uniqueDevices.forEach(device => {
        this.discoveredDevices.set(device.deviceId, device);
      });

      const result: DeviceDiscoveryResult = {
        devices: uniqueDevices,
        protocol: protocols.length === 1 ? protocols[0] : NetworkProtocol.WiFi, // 简化表示
        timestamp
      };

      Logger.i(`设备发现完成, 共发现${uniqueDevices.length}台设备`, 'DeviceManager');
      return result;
    } catch (error) {
      Logger.e('设备发现失败', 'DeviceManager', error as BusinessError);
      return { devices: [], protocol: NetworkProtocol.WiFi, timestamp };
    }
  }

  /**
   * 发现WiFi设备(通过UDP广播或mDNS)
   * 注: 实际实现需根据设备厂商协议调整,此处为简化示例
   */
  private async discoverWiFiDevices(): Promise<LightDevice[]> {
    Logger.d('发现WiFi设备', 'DeviceManager');
    const devices: LightDevice[] = [];

    // 模拟发现过程 - 实际应通过UDP socket发送发现请求并解析响应
    // 此处模拟发现2台WiFi设备
    const mockDevice1: LightDevice = {
      deviceId: `wifi_${Date.now()}_1`,
      deviceName: 'Living Room LED Bulb',
      deviceType: DeviceType.LED_BULB,
      brand: 'SmartLight',
      model: 'SL-W001',
      firmwareVersion: '1.0.2',
      isOnline: true,
      isBound: false,
      bindTime: 0,
      lastActiveTime: Date.now(),
      location: '客厅',
      capability: {
        supportSwitch: true,
        supportBrightness: true,
        minBrightness: 1,
        maxBrightness: 100,
        supportColorTemperature: true,
        minColorTemp: 2700,
        maxColorTemp: 6500,
        supportRGB: true,
        supportDimmingCurve: true,
        supportTiming: true,
        supportScene: true,
        maxScenes: 10
      },
      state: {
        powerOn: false,
        brightness: 80,
        colorTemperature: 4000,
        temperatureUnit: TemperatureUnit.KELVIN,
        dimmingCurve: DimmingCurve.LOGARITHMIC,
        transitionTime: 500,
        lastUpdateTime: Date.now()
      },
      networkInfo: {
        protocol: NetworkProtocol.WiFi,
        ipAddress: '192.168.1.100',
        port: 8080,
        signalStrength: 85,
        connectionType: ConnectionType.DIRECT
      },
      groupIds: ['living_room_group']
    };

    const mockDevice2: LightDevice = {
      deviceId: `wifi_${Date.now()}_2`,
      deviceName: 'Bedroom Ceiling Light',
      deviceType: DeviceType.CEILING_LIGHT,
      brand: 'SmartLight',
      model: 'SL-C002',
      firmwareVersion: '1.1.0',
      isOnline: true,
      isBound: false,
      bindTime: 0,
      lastActiveTime: Date.now(),
      location: '卧室',
      capability: {
        supportSwitch: true,
        supportBrightness: true,
        minBrightness: 10,
        maxBrightness: 100,
        supportColorTemperature: true,
        minColorTemp: 2500,
        maxColorTemp: 6000,
        supportRGB: false,
        supportDimmingCurve: true,
        supportTiming: true,
        supportScene: true,
        maxScenes: 5
      },
      state: {
        powerOn: true,
        brightness: 50,
        colorTemperature: 3000,
        temperatureUnit: TemperatureUnit.KELVIN,
        dimmingCurve: DimmingCurve.LOGARITHMIC,
        transitionTime: 800,
        lastUpdateTime: Date.now()
      },
      networkInfo: {
        protocol: NetworkProtocol.WiFi,
        ipAddress: '192.168.1.101',
        port: 8080,
        signalStrength: 70,
        connectionType: ConnectionType.DIRECT
      },
      groupIds: ['bedroom_group']
    };

    devices.push(mockDevice1, mockDevice2);
    Logger.i(`模拟发现${devices.length}台WiFi设备`, 'DeviceManager');
    return devices;
  }

  /**
   * 发现BLE设备(蓝牙低功耗)
   */
  private async discoverBleDevices(): Promise<LightDevice[]> {
    Logger.d('发现BLE设备', 'DeviceManager');
    const devices: LightDevice[] = [];

    try {
      // 检查蓝牙权限
      // 实际开发中需先申请BLUETOOTH、DISCOVER_BLUETOOTH权限

      // 开始BLE扫描
      await bluetooth.startBLEScan(null); // 扫描所有BLE设备
      Logger.d('BLE扫描已启动', 'DeviceManager');

      // 注册扫描结果回调(实际应通过事件监听获取扫描结果)
      // 此处简化处理,模拟发现1台BLE设备
      const mockBleDevice: LightDevice = {
        deviceId: `ble_${Date.now()}_1`,
        deviceName: 'Desk Lamp BLE',
        deviceType: DeviceType.TABLE_LAMP,
        brand: 'SmartLight',
        model: 'SL-B003',
        firmwareVersion: '2.0.1',
        isOnline: true,
        isBound: false,
        bindTime: 0,
        lastActiveTime: Date.now(),
        location: '书房',
        capability: {
          supportSwitch: true,
          supportBrightness: true,
          minBrightness: 0,
          maxBrightness: 100,
          supportColorTemperature: false,
          supportRGB: true,
          supportDimmingCurve: false,
          supportTiming: false,
          supportScene: true,
          maxScenes: 3
        },
        state: {
          powerOn: false,
          brightness: 100,
          rgbColor: { r: 255, g: 100, b: 50 },
          temperatureUnit: TemperatureUnit.KELVIN,
          dimmingCurve: DimmingCurve.LINEAR,
          transitionTime: 300,
          lastUpdateTime: Date.now()
        },
        networkInfo: {
          protocol: NetworkProtocol.BluetoothLE,
          bleAddress: 'AA:BB:CC:DD:EE:FF',
          signalStrength: 90,
          connectionType: ConnectionType.DIRECT
        },
        groupIds: ['study_group']
      };

      devices.push(mockBleDevice);
      Logger.i(`模拟发现${devices.length}台BLE设备`, 'DeviceManager');

      // 停止扫描(实际应在适当时候停止)
      // await bluetooth.stopBLEScan();
    } catch (error) {
      Logger.e('BLE设备发现失败', 'DeviceManager', error as BusinessError);
    }

    return devices;
  }

  /**
   * 绑定设备(将发现的设备添加到已绑定列表)
   * @param deviceId 设备ID
   * @returns 是否绑定成功
   */
  async bindDevice(deviceId: string): Promise<boolean> {
    const device = this.discoveredDevices.get(deviceId);
    if (!device) {
      Logger.w(`未找到要绑定的设备: ${deviceId}`, 'DeviceManager');
      return false;
    }

    try {
      // 模拟绑定过程(实际应与设备通信进行认证和配对)
      Logger.i(`开始绑定设备: ${device.deviceName}(${deviceId})`, 'DeviceManager');

      // 更新设备绑定状态
      const now = Date.now();
      const boundDevice: LightDevice = {
        ...device,
        isBound: true,
        bindTime: now,
        lastActiveTime: now
      };

      // 添加到已绑定设备列表
      this.boundDevices.set(deviceId, boundDevice);
      this.discoveredDevices.delete(deviceId);

      // 保存到本地存储
      await this.saveBoundDevices();

      // 通知设备状态变化
      this.notifyDeviceStateChanged(boundDevice, 'bound');

      Logger.i(`设备绑定成功: ${device.deviceName}`, 'DeviceManager');
      return true;
    } catch (error) {
      Logger.e(`设备绑定失败: ${deviceId}`, 'DeviceManager', error as BusinessError);
      return false;
    }
  }

  /**
   * 解绑设备
   * @param deviceId 设备ID
   * @returns 是否解绑成功
   */
  async unbindDevice(deviceId: string): Promise<boolean> {
    const device = this.boundDevices.get(deviceId);
    if (!device) {
      Logger.w(`未找到要解绑的设备: ${deviceId}`, 'DeviceManager');
      return false;
    }

    try {
      Logger.i(`开始解绑设备: ${device.deviceName}(${deviceId})`, 'DeviceManager');

      // 模拟解绑过程
      const unboundDevice: LightDevice = {
        ...device,
        isBound: false,
        bindTime: 0
      };

      // 从已绑定列表移除,添加到发现列表(可选)
      this.boundDevices.delete(deviceId);
      this.discoveredDevices.set(deviceId, unboundDevice);

      // 保存更新
      await this.saveBoundDevices();

      // 通知状态变化
      this.notifyDeviceStateChanged(unboundDevice, 'unbound');

      Logger.i(`设备解绑成功: ${device.deviceName}`, 'DeviceManager');
      return true;
    } catch (error) {
      Logger.e(`设备解绑失败: ${deviceId}`, 'DeviceManager', error as BusinessError);
      return false;
    }
  }

  /**
   * 保存已绑定设备到本地存储
   */
  private async saveBoundDevices(): Promise<void> {
    try {
      const devices = Array.from(this.boundDevices.values());
      await PreferencesUtil.saveDeviceList(devices);
      Logger.d(`保存已绑定设备成功, 共${devices.length}台`, 'DeviceManager');
    } catch (error) {
      Logger.e('保存已绑定设备失败', 'DeviceManager', error as BusinessError);
    }
  }

  /**
   * 获取所有已绑定的设备
   */
  getBoundDevices(): LightDevice[] {
    return Array.from(this.boundDevices.values());
  }

  /**
   * 获取设备信息(已绑定或发现的)
   * @param deviceId 设备ID
   */
  getDevice(deviceId: string): LightDevice | undefined {
    return this.boundDevices.get(deviceId) || this.discoveredDevices.get(deviceId);
  }

  /**
   * 更新设备状态(通常由LightController调用)
   * @param deviceId 设备ID
   * @param newState 新状态
   */
  updateDeviceState(deviceId: string, newState: Partial<LightDevice['state']>): boolean {
    const device = this.boundDevices.get(deviceId);
    if (!device) {
      Logger.w(`更新状态失败: 设备未绑定 ${deviceId}`, 'DeviceManager');
      return false;
    }

    // 更新状态
    const updatedState: LightDevice['state'] = {
      ...device.state,
      ...newState,
      lastUpdateTime: Date.now()
    };

    const updatedDevice: LightDevice = {
      ...device,
      state: updatedState
    };

    this.boundDevices.set(deviceId, updatedDevice);

    // 通知状态变化
    this.notifyDeviceStateChanged(updatedDevice, 'state_updated');

    Logger.device(`更新设备状态: ${JSON.stringify(newState)}`, deviceId);
    return true;
  }

  /**
   * 注册设备状态监听器
   * @param deviceId 设备ID(可选, 不填则监听所有设备)
   * @param listener 监听器
   */
  addDeviceStateListener(deviceId: string | null, listener: DeviceStateListener): void {
    const key = deviceId || 'all_devices';
    if (!this.deviceStateListeners.has(key)) {
      this.deviceStateListeners.set(key, new Set());
    }
    this.deviceStateListeners.get(key)!.add(listener);
    Logger.d(`注册设备状态监听器: ${key}`, 'DeviceManager');
  }

  /**
   * 移除设备状态监听器
   * @param deviceId 设备ID(可选)
   * @param listener 监听器
   */
  removeDeviceStateListener(deviceId: string | null, listener: DeviceStateListener): void {
    const key = deviceId || 'all_devices';
    const listeners = this.deviceStateListeners.get(key);
    if (listeners) {
      listeners.delete(listener);
      if (listeners.size === 0) {
        this.deviceStateListeners.delete(key);
      }
      Logger.d(`移除设备状态监听器: ${key}`, 'DeviceManager');
    }
  }

  /**
   * 通知设备状态变化
   * @param device 设备信息
   * @param changeType 变化类型
   */
  private notifyDeviceStateChanged(device: LightDevice, changeType: DeviceStateChangeType): void {
    // 通知特定设备的监听器
    const deviceListeners = this.deviceStateListeners.get(device.deviceId);
    if (deviceListeners) {
      deviceListeners.forEach(listener => {
        try {
          listener.onDeviceStateChanged(device, changeType);
        } catch (error) {
          Logger.e(`设备状态监听器回调异常: ${device.deviceId}`, 'DeviceManager', error as BusinessError);
        }
      });
    }

    // 通知所有设备的监听器
    const allListeners = this.deviceStateListeners.get('all_devices');
    if (allListeners) {
      allListeners.forEach(listener => {
        try {
          listener.onDeviceStateChanged(device, changeType);
        } catch (error) {
          Logger.e(`全局设备状态监听器回调异常`, 'DeviceManager', error as BusinessError);
        }
      });
    }
  }

  /**
   * 释放资源
   */
  release(): void {
    if (this.deviceManager) {
      this.deviceManager.off('deviceOnline');
      this.deviceManager.off('deviceOffline');
      this.deviceManager.off('deviceInfoChanged');
      this.deviceManager.release();
      this.deviceManager = null;
    }
    this.discoveredDevices.clear();
    this.boundDevices.clear();
    this.deviceStateListeners.clear();
    this.isInitialized = false;
    Logger.i('设备管理器资源已释放', 'DeviceManager');
  }
}

/**
 * 设备状态变化类型
 */
export enum DeviceStateChangeType {
  ONLINE = 'online',
  OFFLINE = 'offline',
  BOUND = 'bound',
  UNBOUND = 'unbound',
  STATE_UPDATED = 'state_updated',
  INFO_UPDATED = 'info_updated'
}

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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