Files
xiaomihome/xiaomi/homes.go
T
4566704 a3d94c4b9f chore: 提交高层 xiaomi 封装库及示例
- 新增 xiaomi/examples/ 下 8 个示例程序(用户/家庭查询、设备列表、开关/灯光/空调控制、属性订阅、高级过滤分类、SPEC 解析)
- miot_client_sub.go: 重构 SubProp/SubEvent,使用 buildPropTopic/buildEventTopic 支持通配符订阅(siid/piid=0 → +),并修复锁顺序问题(将 RequestRefreshProp 移到 Lock 外)
- spec_parser.go: 新增 downloadSpecFile 方法,本地 SPEC 文件缺失时自动从 miot-spec.org 下载
- ARCH_PLAN.md: 架构设计从 Proposed 更新为 Accepted(v1.0→v1.1),补充设备分类/工厂/SPEC 映射等模块设计
- xiaomi/: 新增 miot 上层强类型封装模块,包含 Client 主入口、用户/家庭/设备 API、属性读写、动作调用、订阅通知,以及 devices/ 设备控制抽象(Switch/Light/AirConditioner/Fan/Cover/Humidifier/Vacuum/WaterHeater/Thermostat)和 specs/ SPEC 查询辅助
- 更多 xiaomi 示例(风扇/窗帘/传感器控制)
2026-06-29 08:51:21 +08:00

133 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package xiaomi
import "context"
// GetHomeList 获取所有家庭列表
// 合并自有家庭 (home_list) 和共享家庭 (share_home_list)
func (c *Client) GetHomeList(ctx context.Context) ([]*HomeInfo, error) {
data, err := c.http.GetHomeInfos()
if err != nil {
return nil, wrapErr("GetHomeList", "", err)
}
var homes []*HomeInfo
// 解析自有家庭
if homeMap, ok := data["home_list"].(map[string]interface{}); ok {
for _, v := range homeMap {
if hm, ok := v.(map[string]interface{}); ok {
homes = append(homes, parseHomeInfo(hm, false))
}
}
}
// 解析共享家庭
if shareMap, ok := data["share_home_list"].(map[string]interface{}); ok {
for _, v := range shareMap {
if hm, ok := v.(map[string]interface{}); ok {
homes = append(homes, parseHomeInfo(hm, true))
}
}
}
return homes, nil
}
// GetHome 获取指定家庭详情(含房间)
func (c *Client) GetHome(ctx context.Context, homeID string) (*HomeInfo, error) {
homes, err := c.GetHomeList(ctx)
if err != nil {
return nil, err
}
for _, h := range homes {
if h.ID == homeID {
return h, nil
}
}
return nil, ErrHomeNotFound
}
// GetRooms 获取指定家庭的所有房间
func (c *Client) GetRooms(ctx context.Context, homeID string) ([]*RoomInfo, error) {
home, err := c.GetHome(ctx, homeID)
if err != nil {
return nil, err
}
rooms := make([]*RoomInfo, len(home.Rooms))
for i := range home.Rooms {
rooms[i] = &home.Rooms[i]
}
return rooms, nil
}
// GetRoomDevices 获取指定房间的设备 DID 列表。
// 优先使用 homeroom API 返回的 dids,为空时从设备列表按 room_id 过滤。
func (c *Client) GetRoomDevices(ctx context.Context, homeID, roomID string) ([]string, error) {
rooms, err := c.GetRooms(ctx, homeID)
if err != nil {
return nil, err
}
for _, r := range rooms {
if r.ID == roomID {
if len(r.DidList) > 0 {
return r.DidList, nil
}
break
}
}
// 退化:从设备列表按 room_id 过滤
devices, err := c.GetDevices(ctx, FilterByRoom(roomID))
if err != nil {
return nil, err
}
dids := make([]string, 0, len(devices))
for _, d := range devices {
dids = append(dids, d.DID)
}
return dids, nil
}
// parseHomeInfo 从 miot 返回的 map 解析 HomeInfo(含房间列表)
func parseHomeInfo(m map[string]interface{}, shared bool) *HomeInfo {
h := &HomeInfo{
ID: strVal(m, "home_id"),
Name: strVal(m, "home_name"),
UID: strVal(m, "uid"),
GroupID: strVal(m, "group_id"),
CityID: strVal(m, "city_id"),
Address: strVal(m, "address"),
ShareState: shared,
}
// 地理位置
if v, ok := m["longitude"]; ok {
h.Longitude = toFloat64(v)
}
if v, ok := m["latitude"]; ok {
h.Latitude = toFloat64(v)
}
// 解析设备列表
h.DidList = strSliceVal(m, "dids")
// 解析房间(room_info 是 map[string]interface{},key=room_id)
if roomMap, ok := m["room_info"].(map[string]interface{}); ok {
for _, v := range roomMap {
if rm, ok := v.(map[string]interface{}); ok {
h.Rooms = append(h.Rooms, RoomInfo{
ID: strVal(rm, "room_id"),
Name: strVal(rm, "room_name"),
HomeID: h.ID,
DidList: strSliceVal(rm, "dids"),
})
}
}
}
return h
}