feat: AC 三合一设备支持 + 新增 Plug/Gateway 驱动 + Cover 结构化重构
**AC 驱动增强** - 支持 thermostat + air-conditioner + air-fresh 多服务三合一设备,属性跨服务合并解析 - 新增 specResolver.findValListInService/findInService/hasService/serviceShortName 方法 - 移除 KindThermostat,heater/electric-blanket/thermostat 重新归类为 KindAirConditioner **Cover 窗帘重构** - CoverProps 结构化:Position/Status/Fault 分离 - SetPosition 优先写 target-position,回退 current-position - OnPropsChanged/FetchProps 支持多属性同步刷新 **新增设备类型** - Plug 驱动:插座/插头,支持开合、在线状态、属性变更订阅 - Gateway 驱动:网关设备类型识别 - miot/miot_errors.go:新增 MIoT 云端错误码定义 **MIoT 客户端健壮性** - SetProp 空结果视为失败;设备被移除或离线时自动刷新设备列表 - GetDevices 的 has_more 改用 parseBool 严格解析 - MIPS SubscribeMany 批量订阅减少往返 - matchURN 改为按段精确匹配,避免 tofan 误匹配 fan **Bridge** - 移除 Thermostat case,Cover 改用结构化 CoverProps - 新增设备创建后自动订阅属性变更 **其他** - 日志整体 Info → Debug 降噪 - .gitignore 忽略 /.codebuddy/memory - 更新 devices_test 与 08_adv_filter_classify 示例
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
// Command diag_control 直接控制米家设备(纯 HTTP,不初始化 MQTT)。
|
||||
//
|
||||
// 控制序列:开空调 → 设温度 → 设模式 → 回读验证。
|
||||
// 与生产 SDK 同一云端链路(miotspec/prop/set),不占 MQTT client id。
|
||||
//
|
||||
// 用法:token/did 改下面常量,在生产环境 go run .(Linux 下 dataDir 填生产路径)。
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"xiaomihome/miot"
|
||||
)
|
||||
|
||||
// ── 配置:按需修改 ──
|
||||
const (
|
||||
accessToken = "V3_1GfW88WpawoKACRqwdYBb86In_I5e8r8stZdRPXI1PR4zZgIEm4cbjNwn0wYa6-ZQtIliJJerf-iI0W9Lx8t6fm7Ln16w0RVAmYO3e9XubJ0dK7D3eM_zBlCcVmQCla6Sx0BKQv_YXI9E2zXXopKaRjIUWyx0lb0YcE7oEopLuvfA0sEFoTohVKt543KnHJH" // 米家 OAuth access_token
|
||||
targetDID = "2188673403" // 目标设备 did
|
||||
dataDir = "/home/ubuntu/server/zoSmartUser/data" // spec 缓存目录(生产 Linux)
|
||||
// ──────────────────────
|
||||
)
|
||||
|
||||
func main() {
|
||||
if accessToken == "" {
|
||||
fmt.Fprintln(os.Stderr, "请先填写 accessToken")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
httpClient, err := miot.NewMIoTHttpClient("cn", miot.OAUTH2_CLIENT_ID, accessToken)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "创建 HTTP 客户端失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("HTTP 客户端 OK(未连接 MQTT),设备 %s\n", targetDID)
|
||||
|
||||
// 读取当前状态(控制前)
|
||||
readAll("控制前状态", httpClient)
|
||||
|
||||
// ── 控制序列 ──
|
||||
set("开空调 siid=4/piid=1=true", 4, 1, true, httpClient)
|
||||
set("设温度 siid=4/piid=2=26", 4, 2, float64(26), httpClient)
|
||||
set("设模式 siid=2/piid=2=1(Cool)", 2, 2, float64(1), httpClient)
|
||||
set("关空调 siid=4/piid=1=false", 4, 1, false, httpClient)
|
||||
|
||||
// 回读验证(控制后)
|
||||
readAll("控制后状态", httpClient)
|
||||
}
|
||||
|
||||
// set 写属性并回读验证。
|
||||
func set(label string, siid, piid int, value interface{}, c *miot.MIoTHttpClient) {
|
||||
fmt.Printf("\n=== %s ===\n", label)
|
||||
rs, err := c.SetProp([]miot.PropParam{{DID: targetDID, Siid: siid, Piid: piid, Value: value}})
|
||||
if err != nil {
|
||||
fmt.Printf(" 写失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
for _, r := range rs {
|
||||
fmt.Printf(" 写返回 code=%d\n", r.Code)
|
||||
}
|
||||
// 回读
|
||||
gr, err := c.GetProps([]miot.PropParam{{DID: targetDID, Siid: siid, Piid: piid}})
|
||||
if err != nil {
|
||||
fmt.Printf(" 回读失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
if len(gr) > 0 {
|
||||
fmt.Printf(" 回读 siid=%d/piid=%d = %v\n", siid, piid, gr[0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
// readAll 读取关键属性。
|
||||
func readAll(label string, c *miot.MIoTHttpClient) {
|
||||
fmt.Printf("\n--- %s ---\n", label)
|
||||
read := func(siid, piid int, name string) {
|
||||
rs, err := c.GetProps([]miot.PropParam{{DID: targetDID, Siid: siid, Piid: piid}})
|
||||
if err != nil {
|
||||
fmt.Printf(" %-28s 错误: %v\n", name, err)
|
||||
return
|
||||
}
|
||||
if len(rs) > 0 {
|
||||
fmt.Printf(" %-28s = %v\n", name, rs[0].Value)
|
||||
}
|
||||
}
|
||||
read(4, 1, "空调开关 siid=4/piid=1")
|
||||
read(4, 2, "空调温度 siid=4/piid=2")
|
||||
read(2, 2, "模式 siid=2/piid=2")
|
||||
read(2, 4, "地暖温度 siid=2/piid=4")
|
||||
read(5, 2, "环境温度 siid=5/piid=2")
|
||||
}
|
||||
Reference in New Issue
Block a user