**命名统一(State → Props)** - 所有设备类型:XxxState → XxxProps,GetState() → GetProps(),FetchState() → FetchProps() - 回调接口:OnStateChanged → OnPropsChanged - Bridge 层类型别名、示例代码、文档同步更名 **新增设备类型** - KindPlug + Plug 驱动:智能插座/插头(TurnOn/TurnOff/IsOn/OnPropsChanged) - KindGateway + Gateway 驱动:网关设备类型识别 - KindOccupancySensor 从 KindSensor 独立,添加 OccupancyProps **设备分类系统改进** - classifyByModel 改为按 key 长度降序匹配(防止 sensor 先于 sensor-occupy) - 新增下划线变体识别(sensor_occupy、sensor_temp 等) - outlet 重新归类为 Plug(非 Switch) - 新增 Or() 组合过滤器 **连接桥增强** - 设备创建成功后自动订阅属性变更 - 新增 nil 防护检查 - 支持 Plug/Speaker/Gateway/Occupancy 类型的 FetchProps 刷新 - 日志级别 Info → Debug **AC 驱动增强** - 新增 HasPower()、GetElectricPower()、GetPowerConsumption() 功率接口 - ACProps 新增 ElectricPower、PowerConsumption 字段 - valMapper:Desc 为空时 fallback 用 Name,key 统一小写 **MIoT 核心** - 设备列表刷新改用 reflect.DeepEqual 全字段变更检测 - 移除 BLE/代理设备默认在线 hack - RefreshDeviceAllProps 增加离线检查 - 新增 miot_errors.go:MIoT 错误码定义 - 全局日志级别 Info→Debug/Warn(降低噪音) **示例与文档** - 所有示例代码同步 API 变更 - 传感器示例改用 Or 组合过滤器 - ARCH_PLAN 等迁移文档同步更新
320 lines
9.3 KiB
Markdown
320 lines
9.3 KiB
Markdown
# xiaomi 封装层示例程序规划
|
||
|
||
> 状态:Completed | 版本:v1.0 | 日期:2026-06-28 | 完成日期:2026-06-29
|
||
|
||
---
|
||
|
||
## 一、现状分析
|
||
|
||
### 已有示例
|
||
|
||
| 文件 | 状态 | 问题 |
|
||
|------|------|------|
|
||
| `xiaomi/examples/main.go` | 存在(224 行) | 几乎全是 `fmt.Println` 伪代码,非可运行的完整示例 |
|
||
|
||
### 目标
|
||
|
||
对标 `ARCH_PLAN.md` v1.1 的最终形态,覆盖完整 API 面,每个示例独立可理解、贴近实战。
|
||
|
||
---
|
||
|
||
## 二、示例架构
|
||
|
||
```
|
||
xiaomi/examples/
|
||
├── 01_user_home/ # 用户 + 家庭 + 房间信息
|
||
│ └── main.go
|
||
├── 02_device_list/ # 设备列表 + 过滤
|
||
│ └── main.go
|
||
├── 03_switch_control/ # 开关控制
|
||
│ └── main.go
|
||
├── 04_light_control/ # 灯光控制
|
||
│ └── main.go
|
||
├── 05_ac_control/ # 空调控制
|
||
│ └── main.go
|
||
├── 06_fan_cover/ # 风扇 + 窗帘控制
|
||
│ └── main.go
|
||
├── 07_prop_subscribe/ # 属性/事件/状态订阅
|
||
│ └── main.go
|
||
├── 08_adv_filter_classify/ # 高级过滤 + 分类 + 工厂
|
||
│ └── main.go
|
||
├── 09_spec_parser/ # SPEC 解析器独立使用(已有完整代码)
|
||
│ └── main.go
|
||
└── config/ # 共享配置模块(敏感信息统一管理)
|
||
└── config.go
|
||
```
|
||
|
||
---
|
||
|
||
## 三、各示例详述
|
||
|
||
### 01_user_home — 用户/家庭/房间信息
|
||
|
||
**覆盖 API**:
|
||
- `client.GetUserInfo(ctx)` → `*UserInfo`
|
||
- `client.GetHomeList(ctx)` → `[]*HomeInfo`(含经纬度、地址)
|
||
- `client.GetHome(ctx, homeID)` → `*HomeInfo`
|
||
- `client.GetRooms(ctx, homeID)` → `[]*RoomInfo`
|
||
- `client.GetRoomDevices(ctx, homeID, roomID)` → `[]string`
|
||
|
||
**演示重点**:
|
||
- context.WithTimeout 控制超时
|
||
- HomeInfo 的地里位置字段(CityID, Longitude, Latitude, Address)
|
||
- for-range 遍历家庭→房间→设备层级结构
|
||
|
||
---
|
||
|
||
### 02_device_list — 设备列表与过滤
|
||
|
||
**覆盖 API**:
|
||
- `client.GetDevices(ctx, opts...)` → `[]*DeviceInfo`
|
||
- `client.GetDevice(ctx, did)` → `*DeviceInfo`
|
||
- `client.RefreshDevices(ctx)` → error
|
||
- `FilterByHome` / `FilterByRoom` / `FilterByOnline` / `FilterByModel` / `FilterByKind`
|
||
- `DeviceInfo.DeviceKind()` 分类
|
||
|
||
**演示重点**:
|
||
- 多种过滤组合(在线+客厅、按型号、按种类)
|
||
- DeviceKind() 输出
|
||
- RefreshDevices 刷新时机
|
||
|
||
---
|
||
|
||
### 03_switch_control — 开关控制
|
||
|
||
**覆盖 API**:
|
||
- `devices.Create(client, info)` 工厂 → `Switch`
|
||
- `Switch.{TurnOn, TurnOff, Toggle, IsOn}(ctx)`
|
||
- `Switch.OnPropsChanged(handler)` 状态订阅
|
||
|
||
**演示重点**:
|
||
- 工厂创建单设备
|
||
- TurnOn/TurnOff/Toggle 完整链路
|
||
- IsOn 状态查询
|
||
- OnPropsChanged 回调演示
|
||
|
||
---
|
||
|
||
### 04_light_control — 灯光控制
|
||
|
||
**覆盖 API**:
|
||
- `Light.{TurnOn, TurnOff, Toggle}(ctx)`
|
||
- `Light.{SetBrightness, GetBrightness}(ctx, pct)`
|
||
- `Light.{SetColorTemp, GetColorTemp}(ctx, kelvin)`
|
||
- `Light.{SetColor, GetColor}(ctx, r, g, b)`
|
||
- `Light.OnPropsChanged(handler)`
|
||
|
||
**演示重点**:
|
||
- 亮度 0-100 调节
|
||
- 色温 2700K-6500K 调节
|
||
- RGB 颜色控制
|
||
- 不支持功能的降级处理(`GetBrightness` 返回 -1 → 跳过)
|
||
|
||
---
|
||
|
||
### 05_ac_control — 空调控制
|
||
|
||
**覆盖 API**:
|
||
- `AirConditioner.{TurnOn, TurnOff, IsOn}(ctx)`
|
||
- `SetMode(ctx, ACMode)` / `GetMode(ctx)` — cool/heat/dry/fan/auto
|
||
- `SetTargetTemp(ctx, celsius)` / `GetTargetTemp(ctx)` / `GetCurrentTemp(ctx)`
|
||
- `SetFanSpeed(ctx, FanSpeed)` / `GetFanSpeed(ctx)` — low/medium/high/auto
|
||
- `SetSwing(ctx, SwingMode)` / `GetSwing(ctx)` — off/vertical/horizontal/both
|
||
- `SetTargetHumidity(ctx, pct)` / `GetTargetHumidity(ctx)` / `GetCurrentHumidity(ctx)`
|
||
- `SetAuxHeat(ctx, on)` / `GetAuxHeat(ctx)`
|
||
- `SetEco(ctx, on)` / `GetEco(ctx)`
|
||
- `OnPropsChanged(handler)` → `ACState`
|
||
|
||
**演示重点**:
|
||
- 完整空调控制链路(开→设制冷→设26°C→自动风速→垂直摆风)
|
||
- OnPropsChanged 实时状态回调
|
||
- 不支持的功能优雅降级(如无湿度传感器,跳过湿度设置)
|
||
|
||
---
|
||
|
||
### 06_fan_cover — 风扇 + 窗帘控制
|
||
|
||
**覆盖 API**:
|
||
- `Fan.{TurnOn, TurnOff, SetSpeed, SetOscillation, SetNaturalWind}(ctx)`
|
||
- `Cover.{Open, Close, Stop, SetPosition, GetPosition}(ctx)`
|
||
|
||
**演示重点**:
|
||
- 风扇 4 档调速 + 摇头 + 自然风切换
|
||
- 窗帘百分比定位(0%=关, 100%=全开, 50%=半开)
|
||
- Cover 的 Open/Close/Stop 语义对比 SetPosition
|
||
|
||
---
|
||
|
||
### 07_prop_subscribe — 属性/事件/状态订阅
|
||
|
||
**覆盖 API**:
|
||
- `client.SubProp(did, siid, piid, PropHandler)` → subID
|
||
- `client.UnsubProp(did, subID)`
|
||
- `client.SubEvent(did, siid, eiid, EventHandler)` → subID
|
||
- `client.UnsubEvent(did, subID)`
|
||
- `client.SubDeviceState(did, DeviceStateHandler)`
|
||
- `client.UnsubDeviceState(did)`
|
||
|
||
**演示重点**:
|
||
- 订阅前后属性值对比
|
||
- 等待N秒展示属性/事件推送
|
||
- 取消订阅后不再收到回调
|
||
- 设备上下线状态监听
|
||
|
||
---
|
||
|
||
### 08_adv_filter_classify — 高级过滤 + 分类 + 工厂模式
|
||
|
||
**覆盖 API**:
|
||
- `devices.Classify(info)` → `Kind` 枚举
|
||
- `FilterByKind(kind)` 过滤器
|
||
- `devices.Create(client, info)` 工厂 → 各设备接口
|
||
- `devices.Kind` 所有枚举值
|
||
|
||
**演示重点**:
|
||
- 获取全部设备 → 按 Kind 分类 → 统计各类型数量
|
||
- 工厂批量创建:遍历 DeviceInfo → Create → type switch 分流
|
||
- 不支持的设备返回 nil → continue 跳过
|
||
- 输出表格:"设备名 | 型号 | 种类 | 状态"
|
||
|
||
---
|
||
|
||
### 09_spec_parser — SPEC 解析器独立使用
|
||
|
||
**覆盖 API**:
|
||
- specs 包全部公开 API(如果 specs 是公开的)
|
||
- SPEC 属性/事件/动作的枚举和查询
|
||
|
||
**演示重点**:
|
||
- 无需设备在线即可解析 SPEC
|
||
- 打印设备有哪些属性(text/switch/select/number/sensor)
|
||
- 打印设备有哪些事件和动作
|
||
|
||
---
|
||
|
||
## 四、共享配置模块 `config/config.go`
|
||
|
||
```go
|
||
package config
|
||
|
||
type Config struct {
|
||
ClientID string
|
||
ClientSecret string
|
||
AccessToken string // OAuth token(从环境变量或文件读取)
|
||
}
|
||
|
||
// LoadFromEnv 从环境变量加载配置
|
||
func LoadFromEnv() (*Config, error)
|
||
|
||
// LoadFromFile 从 JSON 文件加载配置
|
||
func LoadFromFile(path string) (*Config, error)
|
||
```
|
||
|
||
**设计原则**:
|
||
- 所有示例复用一个 config 加载逻辑,避免重复
|
||
- 仅 3 个字段,对应 xiaomi.Config
|
||
- 敏感信息从环境变量或文件读取,不硬编码
|
||
|
||
---
|
||
|
||
## 五、编码规范
|
||
|
||
### 5.1 统一约定
|
||
|
||
```
|
||
1. 每个示例的 main() 必须有 context.WithTimeout(30s)
|
||
2. 所有 IO 操作带 ctx
|
||
3. 错误必须处理(不忽略 err)
|
||
4. defer cancel() 放在 func main() 顶部
|
||
5. 日志用 log 包,不用 fmt.Print(方便区分日志级别)
|
||
6. 每个示例一句话说明功能(注释在 main 函数上方)
|
||
```
|
||
|
||
### 5.2 模板骨架
|
||
|
||
```go
|
||
// Package main demonstrates <功能简述>.
|
||
// 运行前提:已配置环境变量 XIAOMI_CLIENT_ID / XIAOMI_CLIENT_SECRET / XIAOMI_ACCESS_TOKEN。
|
||
package main
|
||
|
||
import (
|
||
"context"
|
||
"log"
|
||
"time"
|
||
|
||
"xiaomihome/xiaomi"
|
||
"xiaomihome/xiaomi/devices"
|
||
"xiaomihome/xiaomi/examples/config"
|
||
)
|
||
|
||
func main() {
|
||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||
defer cancel()
|
||
|
||
// 1. 加载配置
|
||
cfg, err := config.LoadFromEnv()
|
||
if err != nil {
|
||
log.Fatal("配置加载失败:", err)
|
||
}
|
||
|
||
// 2. 创建客户端(零 miot 引用)
|
||
client, err := xiaomi.NewClient(ctx, xiaomi.Config{
|
||
ClientID: cfg.ClientID,
|
||
ClientSecret: cfg.ClientSecret,
|
||
AccessToken: cfg.AccessToken,
|
||
})
|
||
if err != nil {
|
||
log.Fatal("创建客户端失败:", err)
|
||
}
|
||
defer client.Close()
|
||
|
||
// 3. 业务逻辑(根据示例不同)
|
||
// ...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、与 ARCH_PLAN.md 的对应关系
|
||
|
||
| ARCH_PLAN.md 目标 | 对应示例 |
|
||
|-------------------|---------|
|
||
| 用户/家庭/房间信息(GetUserInfo / GetHomeList) | 01_user_home |
|
||
| 设备列表 + Filter | 02_device_list |
|
||
| Switch 控制 + OnPropsChanged | 03_switch_control |
|
||
| Light 控制 | 04_light_control |
|
||
| AirConditioner 完整控制 | 05_ac_control |
|
||
| Fan / Cover 控制 | 06_fan_cover |
|
||
| SubProp / SubEvent / SubDeviceState 订阅 | 07_prop_subscribe |
|
||
| Classify / FilterByKind / Create 工厂 | 08_adv_filter_classify |
|
||
| SPEC 解析器 | 09_spec_parser |
|
||
| context.Context + 错误处理 | 全部示例 |
|
||
|
||
---
|
||
|
||
## 七、实施计划
|
||
|
||
| 序号 | 示例 | 文件 | 优先级 | 复杂度 |
|
||
|------|------|------|--------|--------|
|
||
| 0 | config 共享模块 | `config/config.go` | P0 | 小 |
|
||
| 1 | 用户/家庭/房间 | `01_user_home/main.go` | P0 | 小 |
|
||
| 2 | 设备列表+过滤 | `02_device_list/main.go` | P0 | 中 |
|
||
| 3 | 开关控制 | `03_switch_control/main.go` | P0 | 小 |
|
||
| 4 | 灯光控制 | `04_light_control/main.go` | P0 | 中 |
|
||
| 5 | 空调控制 | `05_ac_control/main.go` | P0 | 大 |
|
||
| 6 | 风扇+窗帘 | `06_fan_cover/main.go` | P1 | 中 |
|
||
| 7 | 订阅通知 | `07_prop_subscribe/main.go` | P1 | 大 |
|
||
| 8 | 高级过滤+工厂 | `08_adv_filter_classify/main.go` | P1 | 中 |
|
||
| 9 | SPEC 解析 | `09_spec_parser/main.go` | P2 | 小 |
|
||
| — | 统一 README | `examples/README.md` | P2 | 小 |
|
||
|
||
---
|
||
|
||
## 八、与现有 main.go 的关系
|
||
|
||
现有 `xiaomi/examples/main.go` 将被**替换**为上述 9 个独立示例。如果作为归档保留,可移到 `examples/_archive/main_old.go`。
|
||
|
||
---
|
||
|
||
*本文档已全部实施完成。*
|