# 01 - miot_client.py 移植计划 ## 概览 | 项目 | 内容 | |------|------| | **Python 文件** | `py-miot/miot_client.py` (837行) | | **Go 文件** | `go-miot/miot_client.go` + `miot_client_api.go` + `miot_client_prop.go` + `miot_client_sub.go` | | **状态** | ⚠️ 部分实现 | | **优先级** | 🔴 P0 | | **预计工作量** | 8-12 小时 | ## Python 版本分析 ### 核心类 #### MIoTClient **位置**:第 31-837 行 **主要职责**: - 小米 IoT 设备的主客户端类 - 管理设备列表、属性刷新、命令发送 - 协调多个子模块(OAuth、Cloud、MIPS) **核心方法**: | 方法名 | 行号 | 功能 | Go 状态 | |--------|------|------|---------| | `__init__` | 31 | 初始化客户端,加载配置 | ✅ 已完成 | | `load_config` | 47 | 加载配置文件 | ✅ 已完成 | | `save_config` | 68 | 保存配置文件 | ✅ 已完成 | | `discover_devices` | 89 | 发现设备(从云端或本地) | ⚠️ 部分实现 | | `get_devices` | 125 | 获取设备列表 | ✅ 已完成 | | `get_device` | 142 | 根据 DID 获取单个设备 | ✅ 已完成 | | `refresh_devices` | 163 | 刷新设备列表(从云端) | ⚠️ 部分实现 | | `refresh_properties` | 201 | 批量刷新设备属性 | ⚠️ 部分实现 | | `send_command` | 267 | 发送控制命令 | ⚠️ 部分实现 | | `subscribe_prop` | 345 | 订阅属性变化 | ❌ 缺失 | | `unsubscribe_prop` | 389 | 取消订阅属性变化 | ❌ 缺失 | | `start_monitor` | 423 | 启动属性监控线程 | ❌ 缺失 | | `stop_monitor` | 467 | 停止属性监控线程 | ❌ 缺失 | | `poll_devices` | 501 | 轮询设备状态 | ❌ 缺失 | | `call_action` | 567 | 调用设备动作(如开启、关闭) | ⚠️ 部分实现 | | `get_device_prop` | 623 | 获取设备属性值 | ✅ 已完成 | | `set_device_prop` | 659 | 设置设备属性值 | ✅ 已完成 | | `run_mips_script` | 721 | 运行 MIPS 脚本 | ❌ 缺失 | | `close` | 789 | 关闭客户端,释放资源 | ⚠️ 部分实现 | ### 辅助函数 | 函数名 | 行号 | 功能 | Go 状态 | |--------|------|------|---------| | `load_token_from_env` | 812 | 从环境变量加载 token | ❌ 缺失 | | `parse_device_list` | 826 | 解析设备列表 JSON | ✅ 已完成 | ## Go 版本现状 ### 已实现的文件结构 ``` go-miot/ ├── miot_client.go # 主客户端类(对应 Python 的 MIoTClient) ├── miot_client_api.go # API 调用方法(对应 Python 的网络请求) ├── miot_client_prop.go # 属性相关方法(对应 Python 的 refresh_properties 等) ├── miot_client_sub.go # 订阅相关方法(对应 Python 的 subscribe_prop 等) └── miot_device.go # 设备类(对应 Python 的 MIoTDevice) ``` ### 缺失的功能 #### 1. 设备发现 (`discover_devices`) **Python 实现**: ```python def discover_devices(self, source: str = "cloud"): """发现设备""" if source == "cloud": return self.refresh_devices() elif source == "lan": return self._discover_lan_devices() else: raise ValueError(f"Unknown source: {source}") ``` **Go 缺失**: - ❌ LAN 设备发现(需要 `miot_lan.py`) - ⚠️ 云端设备发现已部分实现 #### 2. 属性订阅系统 (`subscribe_prop`, `unsubscribe_prop`) **Python 实现**: - 使用回调机制 - 支持多设备、多属性订阅 - 后台线程轮询 **Go 缺失**: - ❌ 完整的订阅系统 - ❌ 回调机制 - ❌ 后台轮询线程 #### 3. 属性监控 (`start_monitor`, `stop_monitor`) **Python 实现**: - 启动后台线程 - 定期轮询订阅的属性 - 触发回调 **Go 缺失**: - ❌ 后台 goroutine 管理 - ❌ 定时轮询 - ❌ 回调触发 #### 4. MIPS 脚本支持 (`run_mips_script`) **Python 实现**: - 调用 MIPS 客户端 - 执行自动化脚本 **Go 缺失**: - ❌ MIPS 客户端集成 - ❌ 脚本执行接口 ## 移植建议 ### 第一批任务(核心功能) 1. **补全 `discover_devices`** (2小时) - 实现 LAN 设备发现接口(占位) - 统一云端和本地发现的返回格式 2. **实现属性订阅系统** (4小时) - 设计回调接口(`PropertyChangeCallback`) - 实现 `SubscribeProp` 方法 - 实现 `UnsubscribeProp` 方法 - 管理订阅列表 3. **实现属性监控** (3小时) - 启动后台 goroutine - 定时轮询订阅的属性 - 比较属性变化,触发回调 - 实现优雅停止 ### 第二批任务(高级功能) 4. **MIPS 脚本支持** (2小时) - 集成 MIPS 客户端 - 实现 `RunMipsScript` 方法 5. **环境变量支持** (1小时) - 实现 `load_token_from_env` - 支持从环境变量读取配置 ## 技术难点 ### 1. 并发安全 **问题**:Python 版本使用线程,Go 版本需要使用 goroutine **建议**: - 使用 `sync.RWMutex` 保护共享状态 - 使用 channel 进行 goroutine 通信 - 避免全局变量 ### 2. 回调机制 **问题**:Python 使用函数回调,Go 需要使用接口或 channel **建议**: ```go // 方案 1:接口 type PropertyChangeCallback interface { OnPropertyChange(device *MIoTDevice, prop *Property, oldValue, newValue interface{}) } // 方案 2:函数类型 type PropertyChangeHandler func(device *MIoTDevice, prop *Property, oldValue, newValue interface{}) // 方案 3:Channel type PropertyChangeEvent struct { Device *MIoTDevice Property *Property OldValue interface{} NewValue interface{} } var PropertyChangeChan = make(chan PropertyChangeEvent, 100) ``` ### 3. 后台任务管理 **问题**:Python 使用 `threading.Thread`,Go 需要使用 goroutine 和 context **建议**: ```go type MIoTClient struct { // ... monitorCtx context.Context monitorCancel context.CancelFunc monitorWg sync.WaitGroup } func (c *MIoTClient) StartMonitor(interval time.Duration) error { c.monitorCtx, c.monitorCancel = context.WithCancel(context.Background()) c.monitorWg.Add(1) go func() { defer c.monitorWg.Done() ticker := time.NewTicker(interval) defer ticker.Stop() for { select { case <-c.monitorCtx.Done(): return case <-ticker.C: c.pollSubscribedProperties() } } }() return nil } ``` ## 测试计划 ### 单元测试 1. **设备发现测试** - 测试云端设备发现 - 测试本地设备发现(需要 mock) 2. **属性订阅测试** - 测试订阅和取消订阅 - 测试回调触发 - 测试并发订阅 3. **属性监控测试** - 测试启动和停止 - 测试定时轮询 - 测试优雅停止 ### 集成测试 1. **端到端测试** - 使用真实设备测试 - 测试完整流程:发现 → 订阅 → 监控 → 控制 ## 依赖关系 | 依赖文件 | 关系 | 说明 | |---------|------|------| | `miot_device.py` | 强依赖 | 设备类 | | `miot_cloud.py` | 强依赖 | 云端 API | | `miot_oauth.py` | 强依赖 | OAuth 认证 | | `miot_storage.py` | 强依赖 | 配置存储 | | `miot_mips.py` | 弱依赖 | MIPS 脚本 | | `miot_lan.py` | 弱依赖 | LAN 控制 | ## 移植优先级 | 任务 | 优先级 | 理由 | |------|--------|------| | 补全 `discover_devices` | 🔴 高 | 核心功能,影响设备发现 | | 实现属性订阅 | 🔴 高 | 核心功能,影响实时监控 | | 实现属性监控 | 🔴 高 | 核心功能,影响实时监控 | | MIPS 脚本支持 | 🟡 中 | 高级功能,可选 | | 环境变量支持 | 🟢 低 | 辅助功能,方便配置 | ## 进度跟踪 - [ ] 补全 `discover_devices` (预计 2小时) - [ ] 实现属性订阅系统 (预计 4小时) - [ ] 实现属性监控 (预计 3小时) - [ ] MIPS 脚本支持 (预计 2小时) - [ ] 环境变量支持 (预计 1小时) - [ ] 单元测试 (预计 4小时) - [ ] 集成测试 (预计 2小时) **总计**:18小时 --- **创建时间**:2026-06-28 **最后更新**:2026-06-28 **负责人**:待定