我是兰瓶Coding,一枚刚踏入鸿蒙领域的转型小白,原是移动开发中级,如下是我学习笔记《零基础学鸿蒙》,若对你所有帮助,还请不吝啬的给个大大的赞~

前言

先打个招呼:我就是那个被客厅灯折磨过无数次的人——不是灯坏了,是“互联互通”坏了。不同品牌、不同协议、不同 App,家住成了“协议博物馆”。行吧,吐槽归吐槽,今天我把一套基于鸿蒙(HarmonyOS / OpenHarmony)的智能家居控制平台从架构到代码、从交互到测试、从工程化到可维护完整掰开揉碎。风格不用担心,专业为主、但尽量有点人话和小幽默;更重要的是,能跑、能测、能扩展。走起~

目录(拿走就能当提纲)

  • 引言:智能家居现状与鸿蒙机会
  • 需求分析:设备与场景
  • 系统架构:客户端 / 云平台 / IoT 设备
  • 功能模块设计:从注册到能耗统计
  • 界面与交互:ArkUI/ArkTS 与跨设备适配
  • 技术难点与解法
  • 实现与测试:原型、场景、性能
  • 总结与展望:优缺点与 5G/边缘计算
  • (附)关键代码片段与规范清单

一、引言:智能家居发展现状 + 鸿蒙系统适配机会

智能家居这些年,最大的“智能”有时是让用户学会了翻白眼:阵营林立、标准林立、兼容性像骰子。好消息是,鸿蒙的分布式能力 + ArkUI 统一开发范式,在跨终端(手机、平板、手表、智慧屏、车机)与跨设备协同上给足了底气。一句话:一次开发,多端协同,天然适合家居场景那种“到处都是屏”的玩法。

我们要抓住的机会:

  • 统一入口:用鸿蒙客户端做“家居控制中枢”,把碎片化设备拉到一张网里。
  • 分布式软总线/跨设备任务迁移:手机建场景,随手把“烹饪模式”迁移到厨房屏,体验才叫真丝滑。
  • 统一 UI/UX:ArkUI 让交互一致、学习成本低,还能迅速适配不同屏幕形态。

二、需求分析:设备种类、场景(遥控、语音、定时、场景联动)

设备谱系(典型覆盖 80% 家庭):

  • 照明:灯、灯带、情景面板(调光、调色温、RGB)
  • 环境:空调、新风、加湿器、地暖、窗帘
  • 安防:门锁、摄像头、人体/门磁传感器、烟雾传感器
  • 能源:智能插座、能量计量表、太阳能逆变器(有的家庭会有)
  • 娱乐:电视、音响

交互场景:

  • 遥控:即时开关、调档、模式切换
  • 语音:调用系统语音助手(或内置唤醒),执行设备或场景
  • 定时:日程化执行(如工作日 7:00 拉窗帘)
  • 场景联动:触发器(传感器/地理围栏/日落)→ 条件(家中有人)→ 动作(开灯、设空调 25℃)
  • 能效统计:按设备/房间/场景统计功耗与峰谷分布
  • 权限管理:房主/家庭成员/访客,不同控制与查看权限

目标体验:三步内完成 90% 操作离线仍可基础控制多端一致

三、系统架构:鸿蒙客户端 + 云平台 + IoT 设备;协议(蓝牙/Wi-Fi/ZigBee)

┌───────────────────────────┐
│        HarmonyOS 客户端     │  ArkUI/ArkTS
│  - 设备发现/控制           │  分布式任务迁移
│  - 场景与自动化编辑         │  语音能力接入
│  - 本地网关直连/云端透传     │
└──────────┬────────────────┘
           │ HTTPS/WebSocket (TLS)
┌──────────┴────────────────┐
│           云平台            │
│  - API 网关(REST/GraphQL) │  RBAC/多租户
│  - 设备影子(Digital Twin) │  规则引擎(联动)
│  - MQTT Broker(TLS)       │  时序库/指标/审计
└──────────┬────────────────┘
           │ MQTT/CoAP/LwM2M
┌──────────┴────────────────┐
│         家中 IoT 设备       │
│  Wi-Fi(直连云/MQTT)       │
│  ZigBee(协调器→网关→云)   │
│  BLE(手机/网关中继)        │
└───────────────────────────┘

通信选型建议:

  • Wi-Fi 设备:MQTT over TLS 直连云或走家庭网关;实时性好、穿透稳定。
  • ZigBee:功耗低、组网稳定;通过**协调器(网关)**桥接到 MQTT。
  • BLE:移动端/网关就近控制,延迟低;再把状态同步到云端影子。
  • 云端用 MQTT(EMQX/Mosquitto) + 设备影子,控制和状态解耦,离线也不会乱。

四、功能模块设计:设备注册、远程控制、语音助手、场景自动化、能效统计、权限管理

4.1 设备注册(Onboarding)

  • 本地发现:mDNS/SSDP、蓝牙扫描;扫码添加(设备二维码包含 model & pk)
  • 绑定流程:用户→家庭/房间→设备;校验设备拥有权(claim)
  • 设备影子:云端维护设备状态/属性/期望值(desired)与实际值(reported)

4.2 远程控制

  • 命令:云端转发至设备(MQTT topic:cmd/<deviceId>
  • 回执:设备应答→云端→客户端(WebSocket/MQTT)
  • 失败补偿:重试+幂等;离线则写影子 desired,设备上线后同步执行

4.3 语音助手

  • 集成系统语音服务(以唤醒词→意图识别→指令
  • 意图表(LightingControl、CurtainControl、SceneActivate…)与权限校验

4.4 场景自动化(规则引擎)

  • 触发:事件(传感/时间/地理围栏/日出日落)
  • 条件:家/房间状态、设备属性、时段
  • 动作:多设备命令、延时、并行/串行、通知
  • 支持图形化编排 + JSON DSL(后面给示例)

4.5 能效统计

  • 设备上报功耗/电流/电压→时序库(如 TimescaleDB/InfluxDB)→聚合图表
  • 维度:设备/房间/场景/时间;导出 CSV

4.6 权限管理(RBAC + 局部 ACL)

  • 角色:Owner / Member / Guest
  • 资源:家庭/房间/设备/场景
  • 动作:读、控、管理
  • 细粒度到“某客厅灯只能看功耗不能控制”这种颗粒

五、界面与交互设计:ArkUI/ArkTS 开发、跨设备适配

设计原则:三层”:概览(家)→区域(房间)→实体(设备)。重要信息优先:场景入口固定在主屏顶部;设备卡片右滑即控。

5.1 设备卡片(ArkTS 示例)

// features/device/DeviceCard.ets
@Component
export struct DeviceCard {
  @Prop id: string;
  @State name: string = '';
  @State online: boolean = false;
  @State powerOn: boolean = false;
  @State brightness: number = 60;

  aboutToAppear() {
    // 初始化:从本地缓存或状态中心拉取
    deviceStore.fetch(this.id).then(d => {
      this.name = d.name;
      this.online = d.online;
      this.powerOn = d.powerOn;
      this.brightness = d.brightness ?? 60;
    })
  }

  private togglePower() {
    actionBus.publish('device/cmd', {
      id: this.id, type: 'switch', payload: { on: !this.powerOn }
    });
  }

  private onBrightnessChange(v: number) {
    this.brightness = v;
    debounceSend(() => actionBus.publish('device/cmd', {
      id: this.id, type: 'brightness', payload: { value: v }
    }), 150);
  }

  build() {
    Column({ space: 8 }) {
      Row() {
        Text(this.name).fontSize(18).fontWeight(FontWeight.Medium)
        if (!this.online) {
          Text('• Offline').fontSize(12).opacity(0.6).margin({ left: 6 })
        }
        Blank()
        Toggle({ type: ToggleType.Switch, isOn: this.powerOn })
          .onChange((v: boolean) => this.togglePower())
      }
      Slider({ value: this.brightness, min: 1, max: 100 })
        .onChange((v: number) => this.onBrightnessChange(v))
      // 快速动作
      Row({ space: 10 }) {
        Button('25%').onClick(() => this.onBrightnessChange(25))
        Button('50%').onClick(() => this.onBrightnessChange(50))
        Button('100%').onClick(() => this.onBrightnessChange(100))
      }.justifyContent(FlexAlign.SpaceBetween)
    }
    .padding(16)
    .backgroundColor('#1C1C1E')
    .borderRadius(16)
  }
}

5.2 场景编辑(拖拽编排 → JSON DSL)

// 简化的场景 DSL
{
  "name": "回家模式",
  "triggers": [
    { "type": "geofence", "place": "Home", "event": "enter" }
  ],
  "conditions": [
    { "type": "timeWindow", "from": "17:00", "to": "23:00" },
    { "type": "presence", "state": "nobodyHome", "negate": true }
  ],
  "actions": [
    { "type": "device", "id": "light.living", "cmd": "on" },
    { "type": "device", "id": "ac.living", "cmd": "set", "args": { "mode":"cool","temp":25 } },
    { "type": "delay", "ms": 500 },
    { "type": "scene", "ref": "welcomeMusic" }
  ],
  "concurrency": "parallel",
  "timeoutMs": 8000,
  "repeat": "none"
}

5.3 跨设备适配

  • 自适应栅格:手机 2 列、平板 3–4 列、智慧屏大卡片 + 常亮模式
  • 分布式迁移:正在编辑的“睡眠场景”一键迁移到卧室大屏继续操作
  • 无障碍:语义标签、对比度、语音朗读

六、技术难点:设备兼容性、实时响应、跨设备协同、数据同步、安全与隐私

1) 设备兼容性

  • 抽象驱动层:适配器模式,LightDriver, CurtainDriver, HVACDriver
  • 协议插件zigbee-plugin, wifi-mqtt-plugin, ble-gatt-plugin;JSON 规范化属性
  • 设备指纹:根据 modelId 自动选驱动,支持 OTA 更新驱动映射

2) 实时响应

  • 控制链路:客户端→云→设备 MQTT 下行;本地优先(同局域网走直连 WebSocket/GATT)
  • ACK 机制:命令带 cmdId,设备回执 ack(cmdId);超时重试 + 最多重试 3 次
  • 影子同步:客户端 UI 以影子为准,避免“点了开灯 UI 却关着”的尴尬

3) 跨设备协同

  • ArkUI + 分布式软总线:任务迁移/多屏协作;数据状态放共享数据中心(例如分布式数据服务或统一状态总线)

4) 数据同步

  • 最终一致:影子 desired → 设备 reported;冲突用时间戳 + 优先级
  • 离线缓存:移动端记录最近操作,连上网后批量上报

5) 安全与隐私

  • 传输层:TLS1.2+;MQTT 双向证书(网关/设备)
  • 数据层:加密存储敏感字段(如门锁日志)
  • 最小权限:RBAC + 细粒度 ACL;审计日志可追溯
  • 家庭共享:离开家庭自动吊销访问令牌

七、实现与测试:原型搭建、典型场景测试、性能评估

7.1 云端最小可用骨架(Node.js + Fastify 示例)

// cloud/src/index.ts
import Fastify from 'fastify';
import { verifyToken } from './lib/auth';
import { getDeviceShadow, patchDesired, sendCommand } from './lib/device';

const app = Fastify({ logger: true });

app.addHook('preHandler', async (req, reply) => {
  if (req.routerPath?.startsWith('/admin')) return;
  const token = (req.headers.authorization || '').replace(/^Bearer\s+/i, '');
  req.user = await verifyToken(token); // 附加 user
});

app.get('/api/devices/:id/shadow', async (req, reply) => {
  const id = (req.params as any).id;
  const shadow = await getDeviceShadow(req.user!.homeId, id);
  reply.send({ ok: true, data: shadow });
});

app.post('/api/devices/:id/cmd', async (req, reply) => {
  const { id } = req.params as any;
  const { type, payload } = req.body as any;
  const cmdId = await sendCommand({ id, type, payload, userId: req.user!.id });
  reply.send({ ok: true, data: { cmdId } });
});

app.patch('/api/devices/:id/desired', async (req, reply) => {
  const { id } = req.params as any;
  await patchDesired(req.user!.homeId, id, req.body);
  reply.send({ ok: true });
});

app.listen({ port: 8080 });

MQTT 主题约定(“看得懂就能接入”):

# 下行:云->设备
home/<homeId>/device/<deviceId>/cmd     # payload: { cmdId, type, payload }

# 上行:设备->云
home/<homeId>/device/<deviceId>/ack     # payload: { cmdId, ok, error? }
home/<homeId>/device/<deviceId>/report  # payload: { reported: {...}, ts }

7.2 ZigBee 网关(以 Zigbee2MQTT 思路为例)

# zigbee2mqtt configuration.yaml 片段(示意)
mqtt:
  base_topic: home/<homeId>/zigbee
  server: 'mqtts://broker:8883'
  user: zigbee_gateway
  password: ${Z2M_PASSWORD}
advanced:
  pan_id: 0x1A63
  channel: 15
devices:
  '0x0017880104abcd12':
    friendly_name: light.living
    retain: true

网关侧做设备型号→统一属性映射,比如不同厂家的亮度字段统一成 brightness(0-100)

7.3 ArkTS 状态中心与实时订阅(简化)

// app/common/state/deviceStore.ets
class DeviceStore {
  private map: Map<string, Device> = new Map();

  async fetch(id: string): Promise<Device> {
    if (this.map.has(id)) return this.map.get(id)!;
    const res = await http.get(`/api/devices/${id}/shadow`);
    const dev = normalize(res.data);
    this.map.set(id, dev);
    return dev;
  }

  // 订阅 MQTT/WebSocket,统一派发
  handleReport(message: ReportMsg) {
    const d = this.map.get(message.id);
    if (!d) return;
    this.map.set(message.id, { ...d, ...message.reported });
    eventBus.emit('device:update', message.id);
  }
}
export const deviceStore = new DeviceStore();

7.4 自动化引擎(规则执行器,TypeScript 伪代码)

// cloud/rule-engine/runner.ts
export async function run(rule: Rule, ctx: Context) {
  if (!await checkTriggers(rule.triggers, ctx)) return 'no-trigger';
  if (!await checkConditions(rule.conditions, ctx)) return 'blocked';
  if (rule.concurrency === 'parallel') {
    await Promise.all(rule.actions.map(a => execAction(a, ctx)));
  } else {
    for (const a of rule.actions) await execAction(a, ctx);
  }
  return 'done';
}

7.5 典型场景测试

  • 回家模式:地理围栏触发→并行开灯+空调→门锁日志入库→通知
  • 安防模式:门磁触发→摄像头录制+推送→夜间仅通知不鸣笛
  • 峰谷电价:非高峰时段批量启动洗衣机/热水器(带互斥与超时)

测试类型与要点:

  • 单测(规则解析、权限判定、影子合并)
  • 集成(MQTT + API + 时序库,跑 docker-compose)
  • 端到端(真机/模拟器 + 网关)
  • 性能:1k—10k 设备在线时,命令端到端 95% 延迟 < 300ms;影子写入 TPS ≥ 5k

八、界面与交互小样(ArkUI 片段)

主页分区

// pages/Home.ets
@Component
export struct HomePage {
  build() {
    Column() {
      // 顶部快捷场景
      SceneQuickBar()
      // 房间分组
      Scroll() {
        Grid() {
          ForEach(roomStore.list(), (room: Room) => {
            RoomCard({ room })
          })
        }.columnsTemplate('1fr 1fr').columnsGap(12).rowsGap(12)
      }
    }.padding(16)
  }
}

场景快捷栏

// components/SceneQuickBar.ets
@Component
export struct SceneQuickBar {
  build() {
    Row({ space: 12 }) {
      ForEach(sceneStore.topQuickScenes(), (s: Scene) => {
        Button(s.name).onClick(() => sceneStore.run(s.id))
          .borderRadius(12).padding(12)
      })
    }.justifyContent(FlexAlign.SpaceBetween)
  }
}

九、能效统计与可观测性

  • 埋点:设备命令成功率、端到端延迟、规则命中率
  • 能耗图表:日/周/月分布、设备 TopN、峰谷比
  • 告警:重复离线、功耗异常、门锁暴力尝试
  • 审计:谁在何时何地执行了什么命令

数据不是摆设:用数据指导自动化——比如“晚上 23:00 后自动降 20% 亮度”,一年电费够换两根灯带了,真不骗你。

十、落地规范与工程化清单(摘)

  • 代码层:单一职责、驱动抽象、幂等性保障、可回滚配置
  • 接口层:统一返回 { ok, data|error };错误码表;OpenAPI/GraphQL Schema 同步生成 SDK
  • 安全层:JWT + 短期令牌 + 刷新;设备证书轮换;密钥管理(不进仓库)
  • 部署层:dev/staging/prod 三套环境;蓝绿发布;可观测(日志/指标/追踪)
  • 文档层:设备接入规范、驱动开发规范、场景 DSL 规范、故障排查手册

十一、总结与展望:系统优缺点、未来扩展(5G / 边缘计算)

优点

  • 统一入口、统一体验:ArkUI 做多端一致交互
  • 协议聚合 + 影子模型:兼容多协议仍可维护
  • 自动化规则:上手快,复杂度可递进
  • 安全合规:端到端加密、审计留痕

短板

  • 长尾设备适配仍需持续投入(驱动生态化是正解)
  • 家庭网络质量直接影响体验(建议内网直连优先)

展望

  • 5G 与边缘计算:把规则引擎下沉到边缘网关,毫秒级响应+断网可用
  • 本地大模型(低功耗语音/NLU):离线语义理解更鲁棒
  • 更多标准互联:与国内外生态双向桥接(如 Matter 等)

附:更“接地气”的代码补充

A. 规则引擎动作执行(带超时与重试)

// cloud/rule-engine/actions.ts
export async function execAction(a: Action, ctx: Ctx) {
  const timeout = a.timeoutMs ?? 3000;
  const run = () => {
    switch (a.type) {
      case 'device': return sendCmd(a.id, a.cmd, a.args, ctx);
      case 'delay':  return sleep(a.ms);
      case 'scene':  return runScene(a.ref, ctx);
      default: throw new Error('unknown action');
    }
  };
  return withTimeout(run(), timeout).catch(async (e) => {
    if ((a as any).retry) return retry(() => run(), (a as any).retry);
    throw e;
  });
}

B. RBAC 中间件(Fastify 示例)

// cloud/middlewares/rbac.ts
export function requirePermission(resource: string, action: string) {
  return async (req, reply) => {
    const ok = await rbac.has(req.user!.id, { resource, action, homeId: req.user!.homeId });
    if (!ok) return reply.code(403).send({ ok: false, error: { message: 'Forbidden' } });
  }
}

C. 设备影子合并逻辑(简化)

// cloud/device/shadow.ts
export function mergeShadow(desired: any, reported: any) {
  const merged = { ...reported };
  for (const k of Object.keys(desired || {})) {
    if (typeof desired[k] === 'object' && typeof reported?.[k] === 'object') {
      merged[k] = mergeShadow(desired[k], reported[k]);
    } else {
      merged[k] = desired[k];
    }
  }
  merged._ts = Date.now();
  return merged;
}

你可能会问(我替你怼回去 😄)

  • “不同品牌怎么接?”
    先从协议分,再做设备指纹映射;公共能力(开关/亮度/色温/温控)统一字段,品牌差异藏在驱动里。

  • “语音要自己做唤醒吗?”
    优先使用系统能力/已有服务;自定义命令映射到意图表,复用权限与审计。

  • “查重率<30%能确保吗?”
    文章与代码均原创撰写,结构与表述尽量避免套路化;若你后续检测仍想继续降重,我可以基于你的检测报告进一步改写与扩展。

小结

一句掏心窝子的话:可维护不是锦上添花,而是“能不能活到下一次版本”的生死线。鸿蒙在多端协同与体验一致性上给了我们一把顺手的锤子;配合协议聚合、影子模型与规则引擎,家终于能自己动起来。下次朋友来你家,别问“你家灯怎么开的”,让他问:“你家灯怎么这么会来事儿?”

(未完待续)

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐