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 示例(风扇/窗帘/传感器控制)
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package xiaomi
|
||||
|
||||
import "xiaomihome/miot"
|
||||
|
||||
// ========== 属性订阅 ==========
|
||||
|
||||
// SubProp 订阅设备属性变化通知
|
||||
// 内部调用 miot.MIoTClient.SubProp,在 adapter handler 中完成 map→PropertyValue 转换
|
||||
// siid/piid 为 0 表示订阅该设备所有属性
|
||||
// 返回 subscription ID(与 miot.SubProp 一致)
|
||||
func (c *Client) SubProp(did string, siid, piid int, handler PropHandler) (string, error) {
|
||||
wrappedHandler := func(params map[string]interface{}, ctx interface{}) {
|
||||
prop := &PropertyValue{
|
||||
DID: strVal(params, "did"),
|
||||
SIID: intVal(params, "siid"),
|
||||
PIID: intVal(params, "piid"),
|
||||
Code: intVal(params, "code"),
|
||||
Value: params["value"],
|
||||
Type: strVal(params, "type"),
|
||||
}
|
||||
handler(did, prop)
|
||||
}
|
||||
|
||||
subID := c.inner.SubProp(did, wrappedHandler, siid, piid)
|
||||
|
||||
c.mu.Lock()
|
||||
c.propSubs[subID] = did
|
||||
c.mu.Unlock()
|
||||
|
||||
return subID, nil
|
||||
}
|
||||
|
||||
// UnsubProp 取消属性订阅
|
||||
func (c *Client) UnsubProp(did string, subID string) error {
|
||||
c.inner.UnsubProp(did, subID)
|
||||
|
||||
c.mu.Lock()
|
||||
delete(c.propSubs, subID)
|
||||
c.mu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ========== 事件订阅 ==========
|
||||
|
||||
// SubEvent 订阅设备事件通知
|
||||
// 内部调用 miot.MIoTClient.SubEvent,完成 map→EventOccurred 转换
|
||||
func (c *Client) SubEvent(did string, siid, eiid int, handler EventHandler) (string, error) {
|
||||
wrappedHandler := func(params map[string]interface{}, ctx interface{}) {
|
||||
event := &EventOccurred{
|
||||
DID: strVal(params, "did"),
|
||||
SIID: intVal(params, "siid"),
|
||||
EIID: intVal(params, "eiid"),
|
||||
Timestamp: int64(intVal(params, "timestamp")),
|
||||
}
|
||||
|
||||
if args, ok := params["arguments"].(map[string]interface{}); ok {
|
||||
event.Arguments = args
|
||||
}
|
||||
|
||||
handler(did, event)
|
||||
}
|
||||
|
||||
subID := c.inner.SubEvent(did, wrappedHandler, siid, eiid)
|
||||
|
||||
c.mu.Lock()
|
||||
c.eventSubs[subID] = did
|
||||
c.mu.Unlock()
|
||||
|
||||
return subID, nil
|
||||
}
|
||||
|
||||
// UnsubEvent 取消事件订阅
|
||||
func (c *Client) UnsubEvent(did string, subID string) error {
|
||||
c.inner.UnsubEvent(did, subID)
|
||||
|
||||
c.mu.Lock()
|
||||
delete(c.eventSubs, subID)
|
||||
c.mu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ========== 设备状态订阅 ==========
|
||||
|
||||
// SubDeviceState 订阅设备在线状态变化
|
||||
// 内部调用 miot.MIoTClient.SubDeviceState,完成 MIoTDeviceState→DeviceState 转换
|
||||
func (c *Client) SubDeviceState(did string, handler DeviceStateHandler) error {
|
||||
wrappedHandler := func(did string, state miot.MIoTDeviceState, ctx interface{}) {
|
||||
var ds DeviceState
|
||||
switch state {
|
||||
case miot.DeviceStateOnline:
|
||||
ds = StateOnline
|
||||
case miot.DeviceStateOffline:
|
||||
ds = StateOffline
|
||||
default:
|
||||
return // DeviceStateDisable 忽略
|
||||
}
|
||||
handler(did, ds)
|
||||
}
|
||||
|
||||
return c.inner.SubDeviceState(did, wrappedHandler)
|
||||
}
|
||||
|
||||
// UnsubDeviceState 取消设备状态订阅
|
||||
func (c *Client) UnsubDeviceState(did string) error {
|
||||
return c.inner.UnsubDeviceState(did)
|
||||
}
|
||||
Reference in New Issue
Block a user