米家 MIOT React Native 插件 SDK — 项目架构与插件设计说明

SDK API_LEVEL: 10117 | 框架: React Native 0.61.0 + React 16.9.0 + React Navigation 2.x


米家开发者平台:https://iot.mi.com/

一、项目整体架构

miot-plugin-sdk/                     ← 工作空间根目录(不允许修改根 package.json)
├── miot-sdk/                        ← 核心 SDK(只读引用,不修改)
│   ├── Device.js                    ← 设备入口(WifiDevice / BluetoothLE)
│   ├── Service.js                   ← 服务层聚合(spec / scene / smarthome / storage...)
│   ├── Package.js                   ← 插件包管理(entry / entrance / exit)
│   ├── Host.js                      ← 宿主能力(文件系统、系统信息、语言)
│   ├── device/                      ← 设备抽象
│   │   ├── BasicDevice.js           ← 通用设备基类
│   │   ├── WifiDevice.js            ← WiFi 设备(subscribeMessages / loadProperties / callMethod)
│   │   └── bluetooth/               ← 蓝牙设备(connect / discoverServices / write / setNotify)
│   ├── service/
│   │   ├── spec.js                  ← Spec 协议读写(getPropertiesValue / setPropertiesValue / doAction)
│   │   ├── scene.js                 ← 场景/定时
│   │   ├── smarthome.js             ← 智能家居通用接口
│   │   └── storage.js               ← 本地存储
│   ├── ui/                          ← 通用 UI 组件库
│   │   ├── NavigationBar            ← 导航栏
│   │   ├── CommonSetting/           ← 通用设置(分享、固件升级、更多)
│   │   ├── ListItem, Card, Dialog, ColorPicker...  ← 可复用 UI 原子
│   │   └── ...
│   ├── resources/                   ← SDK 内置多语言和样式
│   ├── hooks/                       ← 内置 hooks
│   └── utils/                       ← 工具函数
│
├── projects/                        ← 所有设备插件项目(每个独立 npm 包,互不引用)
│   └── com.xiaomi.fan/    ← 风扇(示例)
│
├── bin/                             ← CLI 工具
│   ├── createProject.js             ← 创建项目
│   ├── runProject.js                ← 启动调试
│   └── template/                    ← 项目模板(empty / common / wifi / ble)
├── doc-md/                          ← SDK 文档(设备管理、蓝牙、功能接口、UI 组件)
└── eslint-mihome-plugin/            ← 自定义 ESLint 规则

核心约束

规则 说明
package.json 不可修改 修改会导致在线打包失败
第三方库只能装在 projects/xxx/ cd projects/xxx && npm install --save xxx
项目间不互相引用 每个 projects/ 下的项目是独立沙箱

二、设备通信协议

2.1 Spec vs Profile

Profile(旧协议) Spec / miot-spec(新协议)
年代 2019 年前的设备 现在的主流设备
属性标识 字符串名 "power" 数字索引 siid:2, piid:1
读属性 loadProperties('power', 'temperature') getPropertiesValue([{did, siid, piid}])
写属性 callMethod('set_power', ['on']) setPropertiesValue([{did, siid, piid, value}])
订阅格式 prop.power prop.2.1
方法调用 callMethod('button_pressed') doAction({did, siid, aiid, in:[]})

新设备统一用 Spec 协议,Profile 仅作历史兼容。

2.2 WiFi vs BLE 通信链路

WiFi 设备 — 服务端中转:

插件下发请求
  → setPropertiesValue([{did, siid, piid, value}])
  → 云端 → 设备 → 设备上报属性变更
  → DeviceEvent.deviceReceivedMessages 回调
  → 插件更新 UI

BLE 设备 — 直连蓝牙:

插件主动发起
  → checkBluetooth → startScan → connect
  → discoverServices → discoverCharacteristics
  → setNotify(读特征) / write(写特征)
  → BluetoothEvent 各类事件回调
  → 插件更新 UI

三、插件项目的三层分层设计

每个设备插件项目内部,推荐拆为三层:
各层职责边界

只管什么 不管什么
通信层 spec 协议读写、订阅/取消订阅、pending 防回退、错误码处理 UI 长什么样
UI 组件层 渲染、手势、动画、局部交互 数据从哪来、怎么发给设备
调度层 持有全局 state、组合通信层和 UI 层、处理跨组件逻辑(模式切换缓存、禁启用联动) 具体某个属性的协议细节

四、项目入口与路由

4.1 标准入口链

index.js
  → 配置 Package.disableAutoCheckUpgrade(WiFi 自动检测固件升级)
  → 监听 PackageEvent.packageAuthorizationCancel(用户撤销授权 → 清缓存 + 退出)
  → Package.entry(App)

App(class 组件)
  → 根据 Package.entrance 决定初始路由
    • Entrance.Main → MainPage(从设备列表点击进入)
    • Entrance.Scene → ScenePage(从场景/自动化进入)
  → createStackNavigator 注册所有页面
  → 统一 NavigationBar 配置(title/left/right)
  → 配置页面切换动画(interpolator)

4.2 典型页面路由

MainPage  ─→  SettingPage (设置)
          ─→  ScenePage   (场景)
          ─→  XiaoAiPage  (小爱训练)
SettingPage
  └── CommonSettingPage(分享、固件升级、更多设置)

五、国际化(i18n)方案

推荐方案(简洁,适合多数项目)

// utils/Strings.js
import Host from 'miot/Host';
const LANGUAGE = Host.locale.language;  // 'zh' | 'en'

const getStrings = (strings) => strings[LANGUAGE] || strings.en;

const Strings = getStrings({
  zh: { power: '开关', setting: '设置', ... },
  en: { power: 'Power', setting: 'Settings', ... },
});

export default Strings;

// 使用
<Text>{Strings.power}</Text>

支持占位符:'电量 {level}%'formatString(Strings.battery, {level: 80})电量 80%

模板方案(多语言,15种)

// resources/strings/index.js
import { Resources } from 'miot';
import { Language } from 'miot/resources';
// switch-case 按语言加载对应 .js 文件

六、新设备插件开发流程

Step 1 — 创建项目

npm run create com.xxx.yyy.zzz -type wifi    # WiFi 设备
npm run create com.xxx.yyy.zzz -type ble     # BLE 设备
npm run create com.xxx.yyy.zzz -type common  # 通用模板

Step 2 — 定义 spec 属性映射

utils/constant.ts 中定义:

// 1. ValueType 枚举
export const ValueType = { bool: 0, uint8: 1, uint16: 3, uint32: 5, ... };

// 2. AttrKey — 属性映射(从设备 spec 文档获取 siid/piid/type)
export const AttrKey = {
  power: { key: 'power', siid: 2, piid: 1, type: ValueType.bool },
  // ... 按设备 spec 逐个添加
};

// 3. FormatPropsKey — 上报格式转换
export const FormatPropsKey = {
  "prop.2.1": AttrKey.power.key,
  // ...
};

// 4. Attr — 属性枚举值
export const Attr = {
  light: { off: 0, on: 1, ... },
  // ...
};

Step 3 — 搭建 MainPage(调度层)

复用自定义通信层骨架

Step 4 — 开发 UI 组件

按设备功能拆分 Presentational 组件,每个组件:

  • 只接收 props(数据 + 回调)
  • 不 import AttrKey 或 Service.spec
  • 可复用 SDK 内置 UI(ListItem, Card, ColorPicker…)

Step 5 — 配置路由和入口

  • project.json — 设置 min_sdk_api_level
  • index.jsPackage.entry(App)
  • App — 注册路由、配置入口分发
  • SettingPage — 配置 CommonSetting(分享、固件升级等)

Step 6 — 国际化

  • utils/Strings.js — 中英文文案
  • 所有用户可见文字通过 Strings.xxx 引用,不硬编码中文

Step 7 — 调试与发布

npm start com.xxx.yyy.zzz          # 启动调试(米家 APP 扫码)
npm run publish com.xxx.yyy.zzz     # 发布构建

七、快速参考

常用 SDK API

import { Package, Device, Service, Host, DeviceEvent } from 'miot';
import { PackageEvent, BluetoothEvent } from 'miot';
import { NavigationBar, CommonSettingPage, SETTING_KEYS } from 'miot/ui';
import { Resources, Styles } from 'miot/resources';

常用设备操作

// WiFi Spec 设备
Service.spec.getPropertiesValue([{did, siid, piid}])
Service.spec.setPropertiesValue([{did, siid, piid, value}])
Device.getDeviceWifi().subscribeMessages('prop.2.1', 'prop.3.1')

// BLE 设备
Bluetooth.checkBluetoothIsEnabled()
Bluetooth.startScan(timeout, ...serviceUUIDs)
Device.getBluetoothLE(peripheralUUID).connect()
bleDevice.getService(uuid).getCharacteristic(uuid).setNotify(true)
bleDevice.getService(uuid).getCharacteristic(uuid).write(value)

// 通用
Device.name / Device.model / Device.deviceID / Device.isOnline / Device.isOwner
Host.locale.language
Package.exit()
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐