09-CSDN-02-智能家居模块实战总结

简介: 本项目基于React Native 0.75构建智能家居App,融合MQTT实现实时双向控制(灯、空调等),结合Redux统一状态管理与withDevice高阶组件复用逻辑;采用乐观更新保障UI零延迟响应,双通道(内网HTTP/外网MQTT)适配网络环境,完美解决多端同步、状态最终一致等IoT核心难题。(239字)

React Native + MQTT 实战:智能家居模块设计

技术栈:React Native 0.75 + Redux + MQTT
适用:IoT App、智能家居、设备远程控制

一、功能是什么

业主在 App 上控制家里联网的智能设备(灯、空调、窗帘、地暖、新风、摄像头),核心场景:

场景 说明
设备控制 单设备开关/调节(空调模式、灯光亮度等)
场景联动 一键执行"回家/离家/睡觉"等多设备组合动作
设备定时 指定设备在指定时间执行动作
状态实时同步 UI 与设备状态最终一致

关键要求:

  • UI 零延迟响应(用户操作完立即看到变化)
  • 控制指令要实时到达设备
  • 设备状态变化要实时回传到 UI
  • 同一设备多端同步(家里人和业主同时控制)

二、用到的技术栈

技术 角色 为什么用它
MQTT 设备控制 + 状态推送 Pub/Sub 模式天然适合 IoT,Topic 路由一对多,QoS 保证消息到达
NB MQTT SDK(公司自研) MQTT 客户端封装 屏蔽底层细节,提供 exec / fetchDeviceStates / subscribe 三个核心 API
Redux 设备状态总线 多个页面共享同一份设备状态,避免组件间通信
HOC 高阶组件 控制逻辑复用 8 种设备共用一套控制逻辑,只写 UI 不写业务
乐观更新(dispatch UPDATE_STATE) UI 0ms 响应 不等服务器,先变 UI
HTTP API(getHostConfig) 拿设备列表(静态数据) 设备配置是低频数据,走 HTTP 便于 CDN/缓存
WebSocket + 自家后端 不用于智能家居 项目里 WebSocket 只用于云对讲通知

三、核心协议原理(面试必备)

3.1 MQTT 是什么

MQTT = Message Queuing Telemetry Transport

  • 应用层协议,跑在 TCP 之上(也可以走 WebSocket)
  • 设计目标:IoT 设备在低带宽、不稳定网络下通信
  • 三大角色:Publisher(发布者)、Subscriber(订阅者)、Broker(代理服务器)

核心思想:发布/订阅(Pub/Sub),不是客户端-服务端直连。

发布者 ──> Broker ──> 所有订阅了相同 Topic 的订阅者

3.2 Topic 是什么

Topic = 消息的"频道",用 / 分层,类似文件系统路径。

home_001/light_001/status    ← 客厅灯状态
home_001/ac_001/status      ← 空调状态
home_001/+/status            ← + 通配符:home_001 下所有设备状态

订阅 home_001/+/status = 一次订阅所有设备状态变化。

3.3 为什么 IoT 用 MQTT 而不是 WebSocket

维度 MQTT WebSocket
模型 Pub/Sub(一对多) C/S(一对一)
一对多 ✅ Topic 路由天然支持 ❌ 要自己写循环
离线消息 ✅ Broker 暂存 ❌ 断了就丢
消息保留 ✅ 新订阅者能拿最新 ❌ 不支持
QoS ✅ 0/1/2 三级保证 ❌ 没内建
头部大小 2 字节(最小) 2-14 字节
适用 IoT 设备 Web 实时通信

3.4 HTTP vs MQTT 在本项目的取舍

业务 协议 原因
拿设备列表 HTTP 静态数据,一次性
拿设备初始状态 MQTT 一次拿全设备当前状态
订阅设备状态变化 MQTT 实时推送
控制设备 MQTT 实时双向

原则:静态/低频用 HTTP,实时/高频用 MQTT。


四、实现架构

┌─────────────────────────────────────────────────────────────────┐
│                  智能家居模块完整架构                               │
└─────────────────────────────────────────────────────────────────┘

                          手机 App
                              │
                              ▼
              ┌───────────────────────────────┐
              │  withDevice HOC(核心)            │
              │  - 接收 device + control            │
              │  - connect Redux 拿状态            │
              │  - 注入 onControl 函数              │
              └───────────────────────────────┘
                              │
                  用户操作 │ 设备渲染
                              ▼
              ┌───────────────────────────────┐
              │  设备组件(AC/Curtain/DimmingLight..)│
              │  - 只关心 UI 渲染                   │
              │  - 调用 this.props.onControl(...)   │
              └───────────────────────────────┘
                              │
                  onControl │ 乐观更新 + 双通道下发
                              ▼
              ┌────────────────────────────────────┐
              │  外网(99%):NB_SDK.exec(topic, data) │
              │       ↓ MQTT                       │
              │  阿里云 MQTT Broker                  │
              │       ↓                           │
              │  家里智能家居主机                      │
              │       ↓                           │
              │  设备执行 → 状态变化 → MQTT 上报 → │
              │  NB_SDK.on('message') → dispatch    │
              └────────────────────────────────────┘
                              │
                  设备状态最终回到 Redux
                              ▼
              ┌───────────────────────────────┐
              │  totalState.states[DEVICE_ID]    │
              │  UI 自动重渲染(PureComponent)     │
              └───────────────────────────────┘

五、核心实现:withDevice HOC

5.1 完整代码

// src/components/Device/HOC/Device.js
export default withDevice = (WrappedComponent) => {
   
  @connect(({
   totalState, home, intranet}) => ({
   
    states: totalState.states,        // ← 设备实时状态(来自 Redux)
    home,                              // ← 房屋列表 + 当前选中
    isIntranet: intranet.isIntranet,   // ← 是否内网模式
    intranetIp: intranet.intranetIp,
  }))
  class Component extends React.PureComponent {
   
    constructor(props) {
   
      super(props);
      const {
   home: {
   list, current}, device} = props;
      const home = list && list.find(item => item.id == current);
      this.topic = home && home.TOPIC;       // ← MQTT 主题
      this.device = device;                  // ← HOC 自己持有 device
    }

    onControl = (data) => {
   
      const {
   dispatch, intranetIp, isIntranet} = this.props;
      const device = this.device;

      data = {
   deviceId: '' + device.DEVICE_ID, ...data};

      // ① 乐观更新:UI 立即响应(0ms)
      dispatch({
   type: UPDATE_STATE, payload: data});

      // ② 调光灯亮度转 16 进制(协议要求)
      if (data.Brightness != null) {
   
        data.Brightness = data.Brightness.toString(16);
      }

      // ③ 双通道:内网走 HTTP,外网走 MQTT
      if (isIntranet) {
   
        Api.IntranetControlDevice(intranetIp, device.DEVICE_ID, data);
      } else {
   
        NB_SDK.exec(this.topic, {
   
          ...data,
          execMobile: global.phone,
          platform: IS_IOS ? 'iOS' : 'Android',
          appName: '星智家',
          appVersion: global.version,
        });
      }
    };

    render() {
   
      const {
   states, status, ...resetProps} = this.props;
      const state = states[device.DEVICE_ID] || {
   };
      return (
        <WrappedComponent
          device={
   device}                  // ← 透传
          onControl={
   this.onControl}       // ← 注入
          state={
   state}                    // ← 注入
          {
   ...resetProps}                  // ← 其他 props 透传
        />
      );
    }
  }
  return hoistNonReactStatics(Component, WrappedComponent);
};

5.2 HOC 的 4 个核心设计

设计 作用
乐观更新 UI 0ms 响应,不等云端
双通道 内网 HTTP / 外网 MQTT,根据 isIntranet 自动切换
Topic 隔离 每个房屋有自己的 TOPIC,避免指令串扰
PureComponent + hoistNonReactStatics 避免不必要渲染 + 保留静态方法

5.3 设备组件用法

// src/components/Device/AC.js
@withDevice
export default class AC extends PureComponent {
   
  setMode = mode => {
   
    this.props.onControl({
   Mode: mode});  // ← 调用 HOC 注入的
  };
  render() {
   
    const {
   device, state} = this.props;  // ← 从 HOC 透传
    return <View><Text>{
   device.NAME}</Text></View>;
  }
}

关键:8 种设备只用关心 UI,业务逻辑全部在 HOC 里。新增设备类型只需写 UI,零冗余。


六、完整调用流程

6.0 设备控制时序图

mermaid diagram

6.1 MQTT 初始化流程

用户登录成功
   ↓
Api.getHomesByToken(token)
   ↓
返回房屋列表(含 TOPIC、HOME_ID、hostId)
   ↓
dispatch(saveHomes(homes)) → Redux home.list
   ↓
dispatch(changeCurrentHome(homeId))
   ↓
dispatch(fetchTotalInfoAndStatus)
   ↓
┌────────────────────────────────────────────────────┐
│ 1. Api.getMqttConnectInfo(hostId)                  │
│    → 返回 {uri, userName, password, isEmqxCloud}    │
│ 2. NB_SDK.initConnection({uri, clientId, ...})     │
│ 3. NB_SDK.connect({userName, password, ...})       │
│ 4. onConnected 回调                                │
│    ├─ Api.getHostConfig(HOME_ID) → 拿设备列表       │
│    ├─ NB_SDK.fetchDeviceStates(topic) → 拿设备状态   │
│    └─ NB_SDK.connection.subscribe(topic) → 订阅变化  │
└────────────────────────────────────────────────────┘

6.2 设备控制流程

用户点击"调光灯 80%"
   ↓
DeviceCard 点击 → onModal({type, device})
   ↓
Home.js setState({modalProps: {type: 'DimmingLight', device}})
   ↓
<DimmingLight {...modalProps} />  (被 withDevice 包装)
   ↓
HOC 接 props(device, type...)
   ↓
用户操作:调用 this.props.onControl({Brightness: 80})
   ↓
HOC.onControl:
   ├─ dispatch UPDATE_STATE → Redux → UI 立即变 80%(乐观更新)
   └─ NB_SDK.exec(topic, {Brightness: '50'})  ← 16 进制
       ↓
       MQTT Broker → 主机 → 设备 → 状态变化 → MQTT 上报
       ↓
       NB_SDK.on('message') → dispatch UPDATE_STATE → UI 最终一致

七、4 个关键技术参数

参数 来源 作用
uri Api.getMqttConnectInfo(hostId) 返回 MQTT Broker 地址(wss://...)
clientId 自己生成(项目用 GID_newbest@@@XZJ_${timestamp}) 客户端唯一标识
username/password Api.getMqttConnectInfo 返回 MQTT 鉴权
TOPIC 房屋对象里(home.TOPIC) MQTT 主题前缀

TOPIC 是登录返回的房屋列表里就有的,不需要连接 MQTT 后获取。


八、其他项目想做这个功能怎么落地

8.1 技术选型建议

场景 推荐方案
几百-几千设备 MQTT(EMQX / Mosquitto) + Redis 持久化
几万设备 MQTT + Kafka 削峰 + 分级 Topic
设备数 < 100 甚至 WebSocket 都行
需要音视频通话 MQTT + WebRTC(不要混 MQTT 音视频)

8.2 协议设计

Topic 命名规范(推荐分层):

{产品线}/{家庭ID}/{设备类型}/{设备ID}/{动作}
例:smarthome/home_001/light/light_001/cmd
    smarthome/home_001/light/light_001/status

Message 格式(推荐 JSON):

{
   
  "deviceId": "light_001",
  "POWER": "ON",
  "Brightness": 80,
  "timestamp": 1692345678901,
  "execMobile": "13800138000"
}

8.3 实施步骤

第 1 步:搭 MQTT Broker
  - 本地测试:docker run -d -p 1883:1883 eclipse-mosquitto
  - 生产环境:EMQX Cloud / 阿里云 MQTT

第 2 步:定义 Topic 规范 + Message 格式
  - 文档化所有设备类型的字段
  - 定义 Topic 模板

第 3 步:实现设备端 SDK
  - ESP32 / STM32 等用 C SDK(MQTT 库)
  - 订阅自己 Topic 的 cmd 主题
  - 控制硬件 + 上报 status

第 4 步:实现 App 端 SDK
  - RN:react-native-mqtt-paho 或自研
  - 订阅设备 status 主题
  - publish 控制指令

第 5 步:实现控制逻辑
  - 乐观更新(先变 UI)
  - 异步下发指令
  - 订阅推送保证最终一致

第 6 步:HOC 抽象(如有多种设备)
  - 抽出 withXxx 高阶组件
  - 新增设备类型零冗余

第 7 步:监控 + 告警
  - Broker 连接数 / 消息 QPS / 错误率
  - 设备离线检测

8.4 注意事项

注意点 说明
TOPIC 必须后端预分配 App 端不能自己生成,否则串户
消息体不要太大 MQTT 限制 256KB,设备列表走 HTTP
QoS 级别 控制指令用 QoS 1(至少一次),状态推送用 QoS 0(最多一次)
ClientId 必须唯一 否则两个 App 连会被踢
心跳 + 重连 MQTT Broker 默认 60s 心跳,断线要自动重连
离线消息保留 设置 cleanSession: false,离线消息保留
安全 TOPIC 不要用敏感信息,用 UUID 即可
频控 高频控制指令要节流,防止设备执行不过来

九、本项目特殊点(避免踩坑)

坑 解决方案
8 设备代码重复 用 withDevice HOC 抽象
UI 与状态不同步 乐观更新 + 订阅最终一致
调光灯 10/16 进制 dispatch 用 10 进制,NB_SDK 用 16 进制
多个家庭切换 每个家庭独立 TOPIC + 独立 MQTT 连接
设备状态推送频繁 500ms 节流合并更新(项目 home.js 里实现)
多端同时控制同一设备 Redux 是单一数据源,最后一次 dispatch 生效

十、面试问答速记

Q1:智能家居为什么用 MQTT 不用 HTTP?

  • MQTT Pub/Sub 天然支持一对多(一个设备状态变化推送所有订阅者)
  • 内置 QoS 保证消息不丢
  • 头部小(2 字节),IoT 设备带宽友好
  • HTTP 是请求-响应,实时推送需要客户端轮询,效率低

Q2:8 种设备怎么共享一套控制逻辑?
用 withDevice HOC。HOC 内部 connect Redux 拿公共数据,提供 onControl 函数。8 种设备组件只需写 UI,业务逻辑统一。

Q3:乐观更新怎么实现的?

// HOC.onControl
dispatch({
   type: UPDATE_STATE, payload: data});  // ① 立即更新 Redux
NB_SDK.exec(topic, data);                         // ② 异步下发指令
// ③ 设备响应 → MQTT 推送 → 回调 → dispatch UPDATE_STATE(最终一致)

Q4:MQTT Topic 怎么设计?

  • 按业务分层:{产品线}/{家庭ID}/{设备类型}/{设备ID}/{动作}
  • App 端不生成 Topic,必须后端预分配
  • 用 UUID 避免敏感信息泄露

Q5:项目里 MQTT 和 HTTP 是怎么分工的?

  • HTTP:拿设备列表、用户权限、房屋信息(静态/低频数据)
  • MQTT:拿设备状态、订阅状态变化、控制设备(实时/高频数据)

十一、一句话总结

智能家居 = MQTT(实时控制 + 推送) + HTTP(静态数据) + Redux(状态总线) + HOC(逻辑复用) + 乐观更新(0ms 响应)。

十二、系统分层架构

整个项目的部署架构 4 层组成(和云对讲共用):

mermaid diagram


系列文章:① 云对讲模块 ② 智能家居模块(本文)

相关文章
|
2月前
|
人工智能 自然语言处理 数据挖掘
阿里云Token Plan:39元/月起全档位拆解,个人与团队版定价权益全解析
本文详解阿里云百炼Token Plan大模型订阅服务,该服务以Credits统一计量全模态模型调用消耗,分为39元/月起的个人版与150元/席/月起的团队版,配套Harness专属开发权益,兼容主流AI编程与智能体工具,同时清晰梳理其与Coding Plan的定位差异、适配场景及低成本选购全攻略,帮助个人开发者与企业团队实现大模型调用成本优化与预算可控。
|
2月前
|
数据采集 人工智能 JSON
我把 AI 插件接进了 Excel:一句话批量处理表格的实践记录
本文分享将AI插件深度集成至Excel/WPS的实战经验:告别VBA调试与网页工具格式错乱,实现“一句话”完成数据清洗、跨表关联、报表生成。支持双平台、本地处理、改前确认,安全高效。免费试用,适合高频表格工作者。
388 0
|
2月前
|
人工智能 数据可视化 前端开发
开学季,快来领取你的 AI 学习搭子!
开学季,Qoder 为学生送上专属福利:免费领取1个月CN专业版,助力开题、PPT、数据分析与简历制作;精选文献写作、图表生成、Excel分析、作品集设计等实用Skill;9.1–9.15小红书带话题#我的学习搭子Qoder发帖,即赠500积分!
478 0
|
3月前
|
JSON 缓存 API
#免费空气质量查询接口推荐:含 AQI、PM2.5 实时数据
本文实测整理了4个当前可用的免费空气质量接口:万维易源(官方、指标全、需appKey)、sojson(免注册免key、适合快速原型)、AQICN(全球覆盖、需免费token)、天行/易客云(需注册key)。含调用方式、字段对比与选型建议,助开发者高效接入AQI、PM2.5等实时数据。
1401 0
|
3月前
|
数据采集 存储 Web App开发
豆瓣读书爬虫:爬取TOP250图书评分与书评,做推荐系统数据源
本文详解如何爬取豆瓣读书TOP250数据构建图书推荐系统:剖析反爬机制(User-Agent伪装、IP限频、Cookie登录态),提供完整Python爬虫代码(含隧道代理集成)、CSV/数据库存储方案,并延伸至协同过滤与内容推荐实践,兼顾合规性与工程落地。
441 0
|
4月前
|
SQL 人工智能 数据库
机器友好,人类透明:面向 AI Agent 的企业级知识包装规范 OKF 深度指南
本文深度解析Google新发布的Open Knowledge Format(OKF)规范——一种专为AI Agent设计的轻量级知识包装标准。它以Markdown+YAML为核心,倡导原子化、去中心化的知识组织,通过index.md实现渐进式上下文加载,显著缓解RAG的噪声与Token爆炸问题,并与Karpathy的LLM Wiki形成“理念共鸣、路径互补”的双雄格局。
740 0
机器友好,人类透明:面向 AI Agent 的企业级知识包装规范 OKF 深度指南
|
5月前
|
人工智能 自然语言处理 运维
深入解析Token节流机制:用户维度 + 场景维度 + 频率限制的大模型降本方案.155
本文系统阐述大模型Token精细化管控体系,涵盖Token定义、拆分规则、成本关联及三大管控维度(场景分层、用户配额、频率限流),详解请求全流程校验、实时统计与动态优化闭环,并附Python实践代码。帮助企业从源头压缩无效消耗,优化资源分配,控制运营成本。
577 2
|
5月前
|
人工智能 自然语言处理 安全
Vibe Coding实战指南:堆砌Prompt没用,工程规范才是高效核心
本文揭秘vibe coding(提示词驱动开发)落地失败的根源:非提示词不精,而是工程规范缺位。基于8个真实商业项目经验,提出5步标准化实战法——锁需求边界、建工程骨架、模块化Prompt、自动化校验、增量式迭代,并推荐适配工具TRAE。强调:AI提效的前提,是人工前置定义架构、规范与校验规则。(239字)
|
4月前
|
网络协议 安全 应用服务中间件
阿里云SSL证书完全指南:从申请到Nginx/Tomcat/IIS全服务器部署实战
本文提供了一份完整的阿里云SSL证书申请与部署指南。首先介绍SSL/TLS证书的基础概念与阿里云证书类型选型,包括免费DV证书、付费OV/EV证书的区别与适用场景。然后详细讲解个人测试证书与正式证书的申请流程,涵盖自动DNS验证与手动DNS验证两种方式。证书签发后,分别针对Nginx、Tomcat、IIS三大主流Web服务器,给出从证书下载、上传、配置到验证的完整操作步骤与代码示例。最后总结了443端口开放、证书链完整性、配置文件路径等常见部署问题及解决方案,帮助读者一步到位完成HTTPS加密配置。
|
5月前
|
数据采集 人工智能 搜索推荐
AI搜索时代技术选型深度解析:GEO服务商评估框架与实战指南
本报告基于2026年Q1最新行业数据,系统解析GEO(生成式搜索引擎优化)市场:规模达186亿元、增速218%,但仅19%服务商具备自研能力。提出五维评估体系(技术架构25%、内容质量22%、可信度20%等),对比六大服务方向,并给出按预算与场景的精准选型建议。(239字)
631 1