- 实现 MIoT 客户端核心功能(MQTT 连接、设备管理、属性读写) - 支持云端 API 调用与局域网设备发现(mDNS) - 集成国际化(i18n)多语言支持 - 添加 MIoT 设备规约解析器(spec_parser) - 包含单元测试与使用示例
380 lines
14 KiB
Markdown
380 lines
14 KiB
Markdown
# 第一批移植任务提示词 (P0 基础架构)
|
||
|
||
> 使用提示词时,将 `{编号}` 替换为对应任务的提示词正文。
|
||
|
||
---
|
||
|
||
## 任务 1.1 — miot_error.py → miot_error.go
|
||
|
||
```
|
||
## 任务:移植 MIoT 错误系统
|
||
|
||
源文件:D:\miot\py-miot\miot_error.py (151行)
|
||
目标文件:D:\miot\go-miot\miot_error.go (新建)
|
||
参考子文档:D:\miot\go-miot\migration\07-miot-err.md
|
||
|
||
### 需实现的内容
|
||
|
||
1. 错误码常量(Go 用 const iota,值对齐 Python 的 MIoTErrorCode 枚举):
|
||
- CODE_UNKNOWN = -10000, CODE_UNAVAILABLE = -10001, CODE_INVALID_PARAMS = -10002
|
||
- CODE_RESOURCE_ERROR = -10003, CODE_INTERNAL_ERROR = -10004
|
||
- CODE_UNAUTHORIZED_ACCESS = -10005, CODE_TIMEOUT = -10006
|
||
- CODE_OAUTH_UNAUTHORIZED = -10020, CODE_HTTP_INVALID_ACCESS_TOKEN = -10030
|
||
- CODE_MIPS_INVALID_RESULT = -10040, CODE_CERT_INVALID_CERT = -10050
|
||
- CODE_CONFIG_INVALID_INPUT = -10100, CODE_CONFIG_INVALID_STATE = -10101
|
||
- CODE_LAN_UNAVAILABLE = -10120
|
||
|
||
2. MIoTError 结构体,实现 error 接口:
|
||
- Code 字段(错误码), Message 字段(消息)
|
||
- Error() 方法返回 "code=N, message=xxx" 格式
|
||
- ToDict() 方法返回 map[string]interface{}
|
||
|
||
3. 13 个子错误类型(Go 用类型别名 + 构造函数):
|
||
MIoTOauthError, MIoTHttpError, MIoTMipsError, MIoTDeviceError,
|
||
MIoTSpecError, MIoTStorageError, MIoTCertError, MIoTClientError,
|
||
MIoTEvError, MipsServiceError, MIoTConfigError, MIoTOptionsError,
|
||
MIoTLanError
|
||
|
||
4. 文件头注释标注 "package miot"
|
||
|
||
### 注意事项
|
||
- 无外部依赖,可独立编译
|
||
- 每个子类型提供 NewXxxError(message string) 构造函数
|
||
- 错误码用 const int 定义,不要用 iota(因为值不是连续的)
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.2 — const.py → const.go
|
||
|
||
```
|
||
## 任务:移植 MIoT 常量系统
|
||
|
||
源文件:D:\miot\py-miot\const.py (161行)
|
||
目标文件:D:\miot\go-miot\const.go (新建)
|
||
参考子文档:D:\miot\go-miot\migration\08-miot-constant.md
|
||
|
||
### 需实现的内容
|
||
|
||
1. 字符串常量:
|
||
DOMAIN="xiaomi_home", DEFAULT_NAME="Xiaomi Home", DEFAULT_NICK_NAME="Xiaomi"
|
||
OAUTH2_CLIENT_ID, OAUTH2_AUTH_URL, DEFAULT_OAUTH2_API_HOST
|
||
DEFAULT_CLOUD_BROKER_HOST, DEFAULT_CLOUD_SERVER, DEFAULT_CTRL_MODE
|
||
DEFAULT_INTEGRATION_LANGUAGE, OAUTH_REDIRECT_URL
|
||
|
||
2. 数值常量:
|
||
MIHOME_HTTP_API_TIMEOUT=30, MIHOME_MQTT_KEEPALIVE=60
|
||
MIHOME_CERT_EXPIRE_MARGIN=3600*24*3, NETWORK_REFRESH_INTERVAL=30
|
||
SPEC_STD_LIB_EFFECTIVE_TIME=3600*24*14
|
||
MANUFACTURER_EFFECTIVE_TIME=3600*24*14
|
||
|
||
3. 变量(切片/映射,需在 var() 中定义):
|
||
SUPPORTED_PLATFORMS []string — 18 个平台名
|
||
UNSUPPORTED_MODELS []string — 4 个模型
|
||
CLOUD_SERVERS map[string]string — 6 个区域
|
||
SUPPORT_CENTRAL_GATEWAY_CTRL []string — ["cn"]
|
||
INTEGRATION_LANGUAGES map[string]string — 13 种语言
|
||
DEFAULT/MIN/MAX_COVER_DEAD_ZONE_WIDTH int
|
||
|
||
4. CA 证书常量:
|
||
MIHOME_CA_CERT_STR string — 两段 PEM 证书(用反引号多行字符串)
|
||
MIHOME_CA_CERT_SHA256 string
|
||
|
||
### 注意事项
|
||
- 无外部依赖,可独立编译
|
||
- Go 不支持类型混合的常量组,数值单独一组,字符串单独一组
|
||
- 路径常量(如文件路径)用 Go 的 os.Getenv 或相对路径,不对齐 Python 的字面值
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.3 — common.py → common.go
|
||
|
||
```
|
||
## 任务:移植 MIoT 通用工具
|
||
|
||
源文件:D:\miot\py-miot\common.py (189行)
|
||
目标文件:D:\miot\go-miot\common.go (新建)
|
||
参考子文档:D:\miot\go-miot\migration\06-miot-utils.md
|
||
|
||
### 需实现的内容
|
||
|
||
1. 工具函数(全部为包级公开函数):
|
||
- GenAbsolutePath(relativePath string) string — path.Join
|
||
- CalcGroupID(uid, homeID string) string — SHA1 取前 16 位 hex
|
||
- LoadJSONFile(filePath string) (map[string]interface{}, error)
|
||
- LoadYAMLFile(filePath string) (map[string]interface{}, error)
|
||
- RandomizeInt(value int, ratio float64) int
|
||
- RandomizeFloat(value float64, ratio float64) float64
|
||
- SlugifyName(name string) string — 可用 github.com/gosimple/slug
|
||
- SlugifyDID(cloudServer, did string) string — f"{cloudServer}_{did}" 后 slugify
|
||
|
||
2. MIoTHttp 工具类(可选,如已有 http_client.go 则跳过):
|
||
- Get(url string, params, headers map[string]string) (string, error)
|
||
- GetJSON(url string, params, headers map[string]string) (map[string]interface{}, error)
|
||
- Post / PostJSON 同理
|
||
|
||
3. MIoTMatcher(可选,评估是否需要 MQTT topic 匹配功能)
|
||
|
||
### 依赖
|
||
- encoding/json, encoding/yaml (或 gopkg.in/yaml.v3)
|
||
- crypto/sha1, encoding/hex
|
||
- github.com/gosimple/slug (可选)
|
||
- path/filepath, io/ioutil
|
||
|
||
### 注意事项
|
||
- 如果 go-miot 已有 http_client.go,HTTP 部分可跳过
|
||
- Slugify 如果用第三方库,需要在 go.mod 中添加依赖
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.4 — miot_storage.py → miot_storage.go
|
||
|
||
```
|
||
## 任务:移植 MIoT 存储系统
|
||
|
||
源文件:D:\miot\py-miot\miot_storage.py (789行)
|
||
目标文件:D:\miot\go-miot\miot_storage.go (新建)
|
||
依赖:miot_error.go, const.go
|
||
参考子文档:D:\miot\go-miot\migration\05-miot-storage.md
|
||
|
||
### 需实现的内容
|
||
|
||
1. MIoTStorage 结构体和方法:
|
||
- 字段:rootPath string, mu sync.RWMutex
|
||
- Load(domain, name string) ([]byte, error) — 读取文件
|
||
- Save(domain, name string, data interface{}) error — 支持 []byte/string/map/slice
|
||
- Remove(domain, name string) error
|
||
- RemoveDomain(domain string) error — 递归删除目录
|
||
- FileExists(domain, name string) bool
|
||
- SaveFile / LoadFile — 二进制原始读写(不加哈希)
|
||
- Clear() error — 清空所有存储
|
||
- 路径格式:{rootPath}/{domain}/{name}
|
||
|
||
2. 文件完整性:
|
||
- Save 时将 SHA256 哈希追加到文件末尾 (32 bytes)
|
||
- Load 时校验哈希,不一致返回 error
|
||
|
||
3. 异步支持:
|
||
- 用 goroutine + channel 实现异步方法(LoadAsync, SaveAsync 等)
|
||
- 注意并发安全(RWMutex)
|
||
|
||
4. 用户配置管理(可选,如果不需要可跳过):
|
||
- UpdateUserConfig / LoadUserConfig
|
||
|
||
5. MIoTCert 证书管理(可选,P0 阶段可以仅定义结构体):
|
||
- 证书加载、验证、生成 CSR 等方法可后续实现
|
||
|
||
### 注意事项
|
||
- Python 的 async/await → Go 的 goroutine + channel
|
||
- Python 的 asyncio.run_in_executor → Go 直接用 goroutine
|
||
- 文件路径用 filepath.Join,Windows 兼容
|
||
- 哈希校验失败返回明确错误
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.5 — miot_cloud.py → miot_cloud.go
|
||
|
||
```
|
||
## 任务:移植 MIoT 云端 HTTP 客户端
|
||
|
||
源文件:D:\miot\py-miot\miot_cloud.py (714行)
|
||
目标文件:D:\miot\go-miot\miot_cloud.go (新建)
|
||
依赖:miot_error.go, const.go, common.go
|
||
参考子文档:D:\miot\go-miot\migration\03-miot-cloud.md
|
||
|
||
### 需实现的内容
|
||
|
||
1. MIoTOauthClient 结构体(OAuth 授权客户端):
|
||
- 字段:clientID int64, redirectURL, oauthHost, deviceID, state string
|
||
- 构造函数 NewMIoTOauthClient(clientID, redirectURL, cloudServer, uuid string)
|
||
- GenAuthURL() — 生成授权 URL(URL 编码参数拼接)
|
||
- GetAccessToken(code string) (map[string]interface{}, error)
|
||
- RefreshAccessToken(refreshToken string) (map[string]interface{}, error)
|
||
- Close() — 关闭 HTTP 连接
|
||
- token 过期时间计算:expires_ts = time.Now() + expires_in*0.7
|
||
|
||
2. MIoTHttpClient 结构体(云端 API 客户端):
|
||
- 字段:host, baseURL, clientID, accessToken string
|
||
- 构造函数 NewMIoTHttpClient(cloudServer, clientID, accessToken string)
|
||
- UpdateHTTPHeader(cloudServer, clientID, accessToken string)
|
||
- HTTP 请求头设置:X-Client-BizId=haapi, Authorization=Bearer{token}
|
||
|
||
3. 核心 API 方法:
|
||
- GetUserInfo() — 获取用户信息
|
||
- GetHomeInfos() — 获取家庭信息(支持分页)
|
||
- GetDevices(homeIDs []string) — 获取设备列表(合并设备信息和家庭/房间归属)
|
||
- GetDevicesWithDIDs(dids []string) — 按 DID 批量获取设备
|
||
- GetProps(params []map) — 批量获取设备属性
|
||
- GetCentralCert(csr string) — 获取中央证书
|
||
- GetSeparatedSharedDevices() — 获取共享设备
|
||
- GetUID() — 获取用户 UID
|
||
|
||
4. 内部辅助方法:
|
||
- __mihome_api_get(urlPath, params) — GET 请求(处理 401/非200 状态码)
|
||
- __mihome_api_post(urlPath, data) — POST 请求
|
||
- __get_dev_room_page(maxID) — 分页获取设备和房间信息
|
||
- __get_device_list_page(dids, startDID) — 分页获取设备列表
|
||
|
||
### API 端点(关键):
|
||
POST /app/v2/ha/oauth/get_token — OAuth token
|
||
POST /app/v2/homeroom/gethome — 获取家庭
|
||
POST /app/v2/homeroom/get_dev_room_page — 设备房间分页
|
||
POST /app/v2/home/device_list_page — 设备列表分页
|
||
POST /app/v2/miotspec/prop/get — 属性批量获取
|
||
GET https://open.account.xiaomi.com/user/profile — 用户信息
|
||
|
||
### 注意事项
|
||
- 使用 net/http 标准库
|
||
- 设备过滤:跳过 miwifi.* 前缀,跳过 UNSUPPORTED_MODELS
|
||
- 分页逻辑:Python 用递归,Go 可以用 for 循环 + break
|
||
- Python asyncio.gather → Go sync.WaitGroup + goroutine
|
||
- 子设备处理:.s\d+ 后缀的设备合并到父设备
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.6 — miot_client.py → miot_client.go (补全)
|
||
|
||
```
|
||
## 任务:补全 MIoT 客户端
|
||
|
||
源文件:D:\miot\py-miot\miot_client.py
|
||
目标文件:D:\miot\go-miot\miot_client.go (现有,需补全)
|
||
参考子文档:D:\miot\go-miot\migration\01-miot-client.md
|
||
|
||
### 补全检查清单
|
||
|
||
1. 客户端初始化:
|
||
- 构造函数参数:cloudServer, accessToken, clientID, language, loop
|
||
- 依赖注入:MIoTHttpClient, MIoTSpecInstance(列表), MIoTStorage, MIoTLan
|
||
|
||
2. 设备管理:
|
||
- 设备发现和注册:从云端获取设备列表,创建 MIoTDevice 实例
|
||
- 设备存储:保存/加载设备实例到 storage
|
||
|
||
3. 属性操作:
|
||
- GetProp(did, siid, piid) — 优先本地 MIPS,回退云端
|
||
- SetProp(did, siid, piid, value) — 只走云端(或 MIPS if connected)
|
||
- 属性缓存和批量刷新
|
||
|
||
4. 事件订阅:
|
||
- 订阅设备事件(MIPS 推送 + 云端轮询)
|
||
- 事件回调管理
|
||
|
||
5. 资源管理:
|
||
- Init() — 初始化 MIPS、LAN、云端连接
|
||
- Close() — 关闭所有连接,释放资源
|
||
- 重连机制
|
||
|
||
### 关键结构体
|
||
|
||
type MIoTClient struct {
|
||
cloudServer string
|
||
accessToken string
|
||
clientID string
|
||
language string
|
||
httpClient *MIoTHttpClient
|
||
mipsClient *MIoTMipsClient
|
||
lanManager *MIoTLan
|
||
storage *MIoTStorage
|
||
devices map[string]*MIoTDevice
|
||
devMu sync.RWMutex
|
||
// ...
|
||
}
|
||
|
||
### 注意事项
|
||
- 先读现有 go-miot/miot_client.go,了解已实现的部分
|
||
- 只补全缺失功能,不要重写已有代码
|
||
- 并发安全(devices map 读写的锁保护)
|
||
- 错误处理:所有外部调用都要处理 error
|
||
```
|
||
|
||
---
|
||
|
||
## 任务 1.7 — miot_device.py → miot_device.go (补全)
|
||
|
||
```
|
||
## 任务:补全 MIoT 设备模型
|
||
|
||
源文件:D:\miot\py-miot\miot_device.py
|
||
目标文件:D:\miot\go-miot\miot_device.go (现有,需补全)
|
||
参考子文档:D:\miot\go-miot\migration\02-miot-device.md
|
||
|
||
### 补全检查清单
|
||
|
||
1. MIoTDevice 结构体:
|
||
- 基本字段:did, name, model, urn, token, ip, online bool
|
||
- 制造商字段:manufacturer, icon
|
||
- 归属字段:homeID, roomID, homeName, roomName, groupID
|
||
- 连接类型:connectType, rssi, ssid, bssid
|
||
- 版本:fwVersion
|
||
- 子设备:subDevices map[int]*MIoTDevice
|
||
- SPEC 引用:serviceList []*MIoTSpecService
|
||
|
||
2. 设备初始化:
|
||
- NewMIoTDevice(client *MIoTClient, did string) *MIoTDevice
|
||
- LoadFromCloud(client *MIoTClient, cloudData map) — 从云端数据填充
|
||
- LoadSPEC(client *MIoTClient) error — 从 SPEC 解析服务/属性/事件/动作
|
||
|
||
3. 属性操作:
|
||
- GetProp(siid, piid int) (interface{}, error) — 委托给 client.GetProp
|
||
- SetProp(siid, piid int, value interface{}) error — 委托给 client.SetProp
|
||
- GetFormattedProp(siid, piid int) — 含值格式化和精度处理
|
||
|
||
4. 设备状态:
|
||
- IsOnline() bool
|
||
- SetOnline(online bool)
|
||
- HasWiFi() — connectType != -1 判断
|
||
|
||
5. 序列化:
|
||
- ToDict() map[string]interface{} — 用于 storage 保存
|
||
- FromDict(data map[string]interface{}) *MIoTDevice — 从 storage 加载
|
||
|
||
### 注意事项
|
||
- 先读现有 go-miot/miot_device.go
|
||
- SPEC 解析可能依赖 spec_parser.go(尚未完整),先预留接口
|
||
- 子设备用指针切片而非递归结构
|
||
```
|
||
|
||
---
|
||
|
||
## 依赖关系图(第一批内部)
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ miot_error │ ← 无依赖
|
||
└──────┬──────┘
|
||
│
|
||
┌────────────────┼────────────────┐
|
||
▼ ▼ ▼
|
||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||
│ const │ │ common │ │ storage │
|
||
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
||
│ │ │
|
||
└───────────────┼───────────────┘
|
||
▼
|
||
┌──────────┐
|
||
│miot_cloud│
|
||
└────┬─────┘
|
||
│
|
||
┌─────────┴─────────┐
|
||
▼ ▼
|
||
┌──────────┐ ┌──────────┐
|
||
│miot_client│◄─────│miot_device│
|
||
└──────────┘ └──────────┘
|
||
```
|
||
|
||
## 执行顺序
|
||
|
||
1. miot_error (最独立,先做)
|
||
2. const (无依赖)
|
||
3. common (无依赖)
|
||
4. miot_storage (依赖 error)
|
||
5. miot_cloud (依赖 error/const/common)
|
||
6. miot_client (依赖 cloud/device/storage)
|
||
7. miot_device (依赖 client/spec)
|
||
```
|