// Command diag_sdk 用完整 SDK 封装(xiaomi.NewClient + devices.Create)重现生产控制路径。 // // 目的:验证 SDK 封装层解析出的属性绑定(on/target-temperature 绑到哪个 siid)。 // 与生产同链路:ac.TurnOn / ac.SetTargetTemp → SetProp(绑定siid) → 云端。 // // 注意:会初始化 MQTT,但用自定义 uuid(client id 唯一,不和生产进程冲突)。 // 在开发机运行;dataDir 指向与生产相同的 spec 缓存(拷一份或指定生产目录)。 package main import ( "context" "fmt" "os" "time" "git.zeroonesoft.cn/golib/xiaomihome/xiaomi" "git.zeroonesoft.cn/golib/xiaomihome/xiaomi/devices" ) // ── 配置:按需修改 ── const ( accessToken = "V3_1GfW88WpawoKACRqwdYBb86In_I5e8r8stZdRPXI1PR4zZgIEm4cbjNwn0wYa6-ZQtIliJJerf-iI0W9Lx8t6fm7Ln16w0RVAmYO3e9XubJ0dK7D3eM_zBlCcVmQCla6Sx0BKQv_YXI9E2zXXopKaRjIUWyx0lb0YcE7oEopLuvfA0sEFoTohVKt543KnHJH" // 米家 OAuth access_token uid = "2897121707" // 小米帐号 UID homeID = int64(619001787902) // 家庭 ID targetDID = "2188673403" // 目标设备 did dataDir = "D:/xiaomihome/go-xiaomihome/miot/examples/diag_sdk/data" // 本 demo 自己的 spec 缓存目录 // ────────────────────── ) func main() { ctx := context.Background() cfg := xiaomi.Config{ AuthInfo: xiaomi.AuthInfo{AccessToken: accessToken}, UUID: "diag-sdk-" + time.Now().Format("150405"), // 唯一 uuid,不占生产 client id UID: uid, DataDir: dataDir, HomeIDs: []int64{homeID}, } client, err := xiaomi.NewClient(ctx, cfg) if err != nil { fmt.Fprintf(os.Stderr, "NewClient 失败: %v\n", err) os.Exit(1) } defer client.Close() fmt.Println("SDK 客户端 OK") info, err := client.GetDevice(ctx, targetDID) if err != nil || info == nil { fmt.Fprintf(os.Stderr, "获取设备 %s 失败: %v\n", targetDID, err) os.Exit(1) } fmt.Printf("设备: %s (%s)\nURN: %s\n", info.Name, info.Model, info.URN) dev, err := devices.NewDevice(client, info) if err != nil { fmt.Fprintf(os.Stderr, "创建设备控制失败: %v\n", err) os.Exit(1) } if dev == nil { fmt.Fprintf(os.Stderr, "设备类型不支持\n") os.Exit(1) } ac, ok := dev.(devices.AirConditioner) if !ok { fmt.Fprintf(os.Stderr, "设备不是 AirConditioner(got %T)\n", dev) os.Exit(1) } fmt.Println("AirConditioner 封装 OK") // 读取当前状态(封装层) if props, err := ac.FetchProps(ctx); err != nil { fmt.Printf("FetchProps 失败: %v\n", err) } else { fmt.Printf("封装层状态: on=%v mode=%s target=%.0f current=%.0f fan=%s hum=%d\n", props.On, props.Mode, props.TargetTemperature, props.Temperature, props.FanLevel, props.CurrentHumidity) } // 控制(观察日志里 SetProp 写的 siid) fmt.Println("\n=== 控制序列(看 SetProp 日志的 siid) ===") if err := ac.TurnOn(ctx); err != nil { fmt.Printf("TurnOn 失败: %v\n", err) } else { fmt.Println("TurnOn OK") } time.Sleep(500 * time.Millisecond) if err := ac.SetTargetTemp(ctx, 26); err != nil { fmt.Printf("SetTargetTemp 失败: %v\n", err) } else { fmt.Println("SetTargetTemp(26) OK") } time.Sleep(500 * time.Millisecond) if ac.HasFanSpeed() { if err := ac.SetFanSpeed(ctx, "medium"); err != nil { fmt.Printf("SetFanSpeed 失败: %v\n", err) } else { fmt.Println("SetFanSpeed(medium) OK") } } else { fmt.Println("HasFanSpeed = false") } time.Sleep(500 * time.Millisecond) if err := ac.SetMode(ctx, "cool"); err != nil { fmt.Printf("SetMode 失败: %v\n", err) } else { fmt.Println("SetMode(cool) OK") } time.Sleep(500 * time.Millisecond) if err := ac.TurnOff(ctx); err != nil { fmt.Printf("TurnOff 失败: %v\n", err) } else { fmt.Println("TurnOff OK") } time.Sleep(500 * time.Millisecond) // 控制后回读 if props, err := ac.FetchProps(ctx); err != nil { fmt.Printf("FetchProps 失败: %v\n", err) } else { fmt.Printf("控制后状态: on=%v mode=%s target=%.0f current=%.0f fan=%s hum=%d\n", props.On, props.Mode, props.TargetTemperature, props.Temperature, props.FanLevel, props.CurrentHumidity) } }