package devices import ( "context" "xiaomihome/xiaomi" ) // Cover 窗帘/晾衣架统一控制接口 type Cover interface { Device Open(ctx context.Context) error Close(ctx context.Context) error Stop(ctx context.Context) error SetPosition(ctx context.Context, pct int) error GetPosition(ctx context.Context) (int, error) OnPropsChanged(handler func(position int)) (string, error) GetProps() int FetchProps(ctx context.Context) (int, error) } type coverDevice struct { BaseDevice propMotor siidPiid propPosition siidPiid propsCache int } const ( coverMotorOpen = 1 coverMotorClose = 0 coverMotorStop = 2 ) func NewCover(client *xiaomi.Client, info *xiaomi.DeviceInfo) (Cover, error) { d := &coverDevice{BaseDevice: NewBaseDevice(client, info)} resolver := d.getSpecResolver() if resolver == nil { return nil, xiaomi.ErrNoSPEC } siid, piid, ok := resolver.find("motor-control") if !ok { return nil, xiaomi.ErrNotSupported } d.propMotor = siidPiid{siid, piid, true} if s, p, ok := resolver.find("current-position"); ok { d.propPosition = siidPiid{s, p, true} } return d, nil } func (d *coverDevice) Open(ctx context.Context) error { if !d.propMotor.valid { return xiaomi.ErrNotSupported } return d.SetProp(ctx, d.propMotor.siid, d.propMotor.piid, coverMotorOpen) } func (d *coverDevice) Close(ctx context.Context) error { if !d.propMotor.valid { return xiaomi.ErrNotSupported } return d.SetProp(ctx, d.propMotor.siid, d.propMotor.piid, coverMotorClose) } func (d *coverDevice) Stop(ctx context.Context) error { if !d.propMotor.valid { return xiaomi.ErrNotSupported } return d.SetProp(ctx, d.propMotor.siid, d.propMotor.piid, coverMotorStop) } func (d *coverDevice) SetPosition(ctx context.Context, pct int) error { if !d.propPosition.valid { return xiaomi.ErrNotSupported } return d.SetProp(ctx, d.propPosition.siid, d.propPosition.piid, pct) } func (d *coverDevice) GetPosition(ctx context.Context) (int, error) { if !d.propPosition.valid { return 0, xiaomi.ErrNotSupported } prop, err := d.GetProp(ctx, d.propPosition.siid, d.propPosition.piid) if err != nil { return 0, err } return toInt(prop.Value), nil } func (d *coverDevice) OnPropsChanged(handler func(position int)) (string, error) { if !d.propPosition.valid { return "", xiaomi.ErrNotSupported } return d.SubProp(0, 0, func(did string, prop *xiaomi.PropertyValue) { if prop.SIID == d.propPosition.siid && prop.PIID == d.propPosition.piid { d.propsCache = toInt(prop.Value) handler(d.propsCache) } }) } func (d *coverDevice) GetProps() int { return d.propsCache } func (d *coverDevice) FetchProps(ctx context.Context) (int, error) { pos, err := d.GetPosition(ctx) if err != nil { return d.propsCache, err } d.propsCache = pos return pos, nil }