feat: 初始化小米 IoT (MIoT) 智能家居 Go 库

- 实现 MIoT 客户端核心功能(MQTT 连接、设备管理、属性读写)
- 支持云端 API 调用与局域网设备发现(mDNS)
- 集成国际化(i18n)多语言支持
- 添加 MIoT 设备规约解析器(spec_parser)
- 包含单元测试与使用示例
This commit is contained in:
2026-06-28 22:05:49 +08:00
parent ac442812b4
commit 3a44cb9e6a
118 changed files with 31630 additions and 0 deletions
+218
View File
@@ -0,0 +1,218 @@
# 示例计划
> 目录:`go-miot/examples/`
> 公共配置:`go-miot/examples/config/config.go`
> **约束:禁用命令行参数 + 禁用环境变量,仅用 config.json,其余变量直接硬编码**
## 目录结构
```
go-miot/examples/
├── config/
│ └── config.go # 公共配置加载(token、cloudServer、clientID 等)
├── cloud_oauth/
│ └── main.go # OAuth 授权流程
├── cloud_devices/
│ └── main.go # 云端设备列表 + 属性读写 + 动作调用
├── mips_subscribe/
│ └── main.go # MQTT 订阅(事件/属性/设备状态)
├── lan_control/
│ └── main.go # LAN 设备发现 + 控制
├── mdns_discovery/
│ └── main.go # mDNS 网关发现
├── network_monitor/
│ └── main.go # 网络状态监控
├── storage_manage/
│ └── main.go # 证书 + 存储管理
├── spec_parser/
│ └── main.go # SPEC 解析 + 属性/服务查询
└── full_client/
└── main.go # 完整客户端(上述全部集成)
```
## 公共配置 `config/config.go`
提供 `LoadConfig(path string)` 从 JSON 文件读取:
```json
{
"cloud_server": "cn",
"client_id": "2882303761520251711",
"access_token": "your_token",
"refresh_token": "your_refresh_token",
"uid": "your_uid",
"uuid": "your_uuid",
"redirect_url": "http://localhost:8123",
"language": "en"
}
```
无命令行参数,无环境变量。其余变量在示例 `main.go` 中直接硬编码定义。
---
## 示例列表
### 1. cloud_oauth — OAuth 授权流程
**覆盖模块**:`miot_cloud.go`(MIoTOauthClient)
**流程**:
1. 创建 MIoTOauthClient
2. 生成授权 URL → 打印(用户浏览器打开)
3. 等待用户输入回调 code
4. 用 code 获取 access_token + refresh_token
5. 用 refresh_token 刷新 token
6. 打印最终 token
**依赖**:config
---
### 2. cloud_devices — 云端设备管理
**覆盖模块**:`miot_cloud.go`(MIoTHttpClient)
**流程**:
1. 创建 MIoTHttpClient(用 config 的 token)
2. GetUserInfo → 打印用户信息
3. GetHomeInfos → 打印家庭列表
4. GetDevices → 打印所有设备
5. 任选一个设备,GetProp(did, siid, piid) → 读取属性
6. SetProp(did, siid, piid, value) → 设置属性
7. DoAction(did, siid, aiid, inList) → 执行动作
**依赖**:config
---
### 3. mips_subscribe — MQTT 实时订阅
**覆盖模块**:`mips_client.go`
**流程**:
1. 创建 MipsCloudClient(broker + cert)
2. Connect
3. 订阅设备属性变化(SubProp)
4. 订阅设备事件(SubEvent)
5. 订阅设备状态(SubDeviceState)
6. 打印收到的消息,运行 60 秒后退出
**依赖**:config(需 token 获取 cert)+ storage cert
---
### 4. lan_control — LAN 设备控制
**覆盖模块**:`miot_lan.go`
**流程**:
1. 创建 MIoTNetwork(获取本地网卡)
2. 创建 MIoTLan(需设备 did + token)
3. Start → 等待设备发现
4. 列出已发现的 LAN 设备
5. SubProp 订阅属性
6. SendToDevice 发送控制指令
7. 等待 30 秒观察结果
**依赖**:config(需 did + token)
---
### 5. mdns_discovery — mDNS 网关发现
**覆盖模块**:`miot_mdns.go`
**流程**:
1. 创建 MipsService
2. Init → 开始扫描
3. SubServiceChange 订阅变化
4. 打印发现的网关(did、ip、port、groupID)
5. GetServices 按 groupID 查询
6. 运行 30 秒
**依赖**:无(纯网络扫描)
---
### 6. network_monitor — 网络状态监控
**覆盖模块**:`miot_network.go`
**流程**:
1. 创建 MIoTNetwork
2. Init → 获取当前网络状态
3. GetNetworkStatus → 打印在线状态
4. GetNetworkInfo → 打印所有网卡
5. SubNetworkStatus → 订阅状态变化
6. SubNetworkInfo → 订阅网卡变化
7. 运行 30 秒
**依赖**:无
---
### 7. storage_manage — 存储/证书管理
**覆盖模块**:`miot_storage.go`
**流程**:
1. 创建 MIoTStorage(指定 rootPath)
2. Save / Load / Remove 测试
3. LoadUserConfig / UpdateUserConfig
4. 创建 MIoTCert → VerifyCACert
5. LoadUserKey / LoadUserCert
6. 创建 DeviceManufacturer → GetName
**依赖**:config(uid + cloudServer)
---
### 8. spec_parser — SPEC 解析
**覆盖模块**:`spec_parser.go`
**流程**:
1. 创建 MIoTStorage + MIoTSpecParser
2. Parse("urn:miot-spec-v2:device:light:0000A001:yeelink-light1:1") → MIoTSpecInstance
3. 遍历 Services → Properties → 打印 name/iid/format/access/valueRange
4. 遍历 Services → Actions → 打印 in/out 参数
5. 演示 EvalExpr / ValueFormat / ValuePrecision
6. 演示 ValueList.Names / GetValueByDescription
**依赖**:storage + specs/ 目录
---
### 9. full_client — 完整客户端
**覆盖模块**:全部
**流程**:
1. 创建 MIoTClient(config 全部字段)
2. Init → 初始化 OAuth/HTTP/Cert/Storage
3. RefreshDevices → 从云端获取设备
4. 启动 MIPS 订阅(设备状态 + 属性变化)
5. 启动 LAN 发现
6. 启动 mDNS 发现
7. 启动网络监控
8. 等待 Ctrl+C 退出,Deinit 清理
**依赖**:全部 config 字段
---
## 执行顺序(建议)
```
config → cloud_oauth ─┐
├→ cloud_devices → mips_subscribe
│
network_monitor ────────┤ (独立)
spec_parser ─────────┤
mdns_discovery ──────┤ (独立)
│
└→ storage_manage → lan_control → full_client
```
可首先生成 `config` 包,后续示例全部依赖它。