refactor: 重构 token 管理,新增 NATS adapter 和多示例

按照 TOKEN_REFACTOR.md / FIX_CONFIG.md 方案重构核心层:
- miot: Init() 优先读 storage token,新增 RefreshAuthInfo() 和刷新回调
- xiaomi: Config 改用 AuthInfo 结构体(含 UUID/UID/DataDir/OnTokenRefreshed)
- xiaomi: NewClient(ctx, Config) 新签名,新增 RefreshToken(),后台自动刷新
- xiaomi/devices: 设备控制接口重构
- 新增示例 12_ac_subscribe,其余示例适配新 Config
This commit is contained in:
2026-06-30 12:16:49 +08:00
parent a3d94c4b9f
commit 8ffc9e4e44
33 changed files with 1019 additions and 593 deletions
+87
View File
@@ -0,0 +1,87 @@
# Config 补回 UUID / UID
> 2026-06-30
## UUID 和 UID 的作用
| 字段 | 作用 | 约束 |
|------|------|------|
| UUID | MIPS MQTT 客户端标识,`"ha.{uuid}"` 格式连接小米云端 MQTT | OAuth 前生成,永久不变,变更则 token 失效 |
| UID | 小米帐号唯一 ID,证书生成、storage 文件命名、OAuth 流程用到 | OAuth 后固定的,从 `GetHomeInfos` API 取 `uid` 字段 |
---
## 修改清单
### 1. `xiaomi/config.go`
```diff
type Config struct {
AccessToken string
RefreshToken string
+ UUID string // MIPS 设备标识,OAuth 前生成,永久不可变
+ UID string // 小米帐号 UID,OAuth 后从 API 获取
}
```
### 2. `xiaomi/client.go` — 第 33 行、第 40 行
```diff
- uuid := generateUUID()
+ if cfg.UUID == "" {
+ return nil, fmt.Errorf("xiaomi: Config.UUID is required")
+ }
+ uuid := cfg.UUID
- miot.NewMIoTClient("xiaomi_sdk", entryData, "", "cn", miot.CtrlModeAuto)
+ miot.NewMIoTClient("xiaomi_sdk", entryData, cfg.UID, "cn", miot.CtrlModeAuto)
```
### 3. 11 个示例文件 — 每个补两行
```
xiaomi/examples/01_user_home/main.go
xiaomi/examples/02_device_list/main.go
xiaomi/examples/03_switch_control/main.go
xiaomi/examples/04_light_control/main.go
xiaomi/examples/05_ac_control/main.go
xiaomi/examples/06_fan_control/main.go
xiaomi/examples/07_prop_subscribe/main.go
xiaomi/examples/08_adv_filter_classify/main.go
xiaomi/examples/09_spec_parser/main.go
xiaomi/examples/10_cover_control/main.go
xiaomi/examples/11_sensor_control/main.go
```
每个文件当前是:
```go
client, err := xiaomi.NewClient(ctx, xiaomi.Config{
AccessToken: cfg.AuthInfo.AccessToken,
RefreshToken: cfg.AuthInfo.RefreshToken,
})
```
改为:
```go
client, err := xiaomi.NewClient(ctx, xiaomi.Config{
AccessToken: cfg.AuthInfo.AccessToken,
RefreshToken: cfg.AuthInfo.RefreshToken,
UUID: cfg.UUID,
UID: cfg.UID,
})
```
---
## 调用方使用流程
```
1. OAuth 前:生成 UUID(crypto/rand 16字节 hex),存库
2. OAuth:获取 AccessToken + RefreshToken
3. OAuth 后:调 GetHomeInfos 获取 UID,存库
4. 每次创建 Client:从库读四个值传入 Config
5. Token 刷新:调 RefreshToken(),新 AccessToken/RefreshToken 写回库
UID 和 UUID 永不更新
```