Files
xiaomihome/xiaomi/devices/plug.go
T
4566704 cdc459b5ff fix(xiaomihome): 模块路径改为 git.zeroonesoft.cn/golib/xiaomihome
- 改动:go.mod module 声明与全部内部导入路径补全为完整域名路径,README 同步
- 原因:裸模块名无法被 go get 解析,发版前必须修正为 GOPRIVATE 可拉取路径
2026-10-05 08:53:23 +08:00

103 lines
2.5 KiB
Go

package devices
import (
"context"
"fmt"
"git.zeroonesoft.cn/golib/xiaomihome/xiaomi"
)
// Plug 插座/插头统一控制接口(电脑开机卡、智能插座等)。
type Plug interface {
Device
TurnOn(ctx context.Context) error
TurnOff(ctx context.Context) error
IsOn(ctx context.Context) (bool, error)
OnPropsChanged(handler func(on bool)) (string, error)
GetProps() PlugProps
FetchProps(ctx context.Context) (PlugProps, error)
}
// PlugProps 插座完整状态。
type PlugProps struct {
On bool `json:"on"`
}
type plugDevice struct {
BaseDevice
propOn siidPiid
propsCache PlugProps
}
// NewPlug creates a Plug control for the given device.
func NewPlug(client *xiaomi.Client, info *xiaomi.DeviceInfo) (Plug, error) {
if info == nil {
return nil, xiaomi.ErrDeviceNotFound
}
miotDev := client.GetMIoTDevice(info.DID)
if miotDev == nil || miotDev.SpecInstance() == nil {
return nil, fmt.Errorf("%w: device has no SPEC", xiaomi.ErrNotSupported)
}
d := &plugDevice{
BaseDevice: NewBaseDevice(client, info),
}
for _, svc := range miotDev.SpecInstance().Services {
for _, prop := range svc.Properties {
if propertyShortName(prop.Type) == "on" && !d.propOn.valid {
d.propOn = siidPiid{prop.SIID, prop.PIID, true}
}
}
}
if !d.propOn.valid {
return nil, fmt.Errorf("%w: no on property", xiaomi.ErrNotSupported)
}
return d, nil
}
func (d *plugDevice) TurnOn(ctx context.Context) error {
return d.SetProp(ctx, d.propOn.siid, d.propOn.piid, true)
}
func (d *plugDevice) TurnOff(ctx context.Context) error {
return d.SetProp(ctx, d.propOn.siid, d.propOn.piid, false)
}
func (d *plugDevice) IsOn(ctx context.Context) (bool, error) {
prop, err := d.GetProp(ctx, d.propOn.siid, d.propOn.piid)
if err != nil {
return false, err
}
b, _ := prop.Value.(bool)
return b, nil
}
func (d *plugDevice) OnPropsChanged(handler func(on bool)) (string, error) {
return d.SubProp(d.propOn.siid, d.propOn.piid, func(did string, prop *xiaomi.PropertyValue) {
if b, ok := prop.Value.(bool); ok {
d.propsCache.On = b
handler(b)
}
})
}
func (d *plugDevice) GetProps() PlugProps { return d.propsCache }
func (d *plugDevice) FetchProps(ctx context.Context) (PlugProps, error) {
props, err := d.client.GetProps(ctx, []xiaomi.PropKey{
{DID: d.info.DID, SIID: d.propOn.siid, PIID: d.propOn.piid},
})
if err != nil {
return d.propsCache, err
}
for _, p := range props {
if p.SIID == d.propOn.siid && p.PIID == d.propOn.piid {
d.propsCache.On, _ = p.Value.(bool)
}
}
return d.propsCache, nil
}