93 lines
4.0 KiB
Go
93 lines
4.0 KiB
Go
// Package iot provides the IoT device source abstraction for Cyrene v2.
|
|
//
|
|
// It models smart-home devices (light, AC, curtain, sensor, lock) as typed
|
|
// devices managed by pluggable providers. A Provider is a device source; the
|
|
// Manager selects a provider from configuration, exposes List/Control/Status,
|
|
// and publishes device state transitions as events on the in-process bus so
|
|
// other subsystems (frontend, memory, push) observe changes without polling
|
|
// (DevDocs/02-development-constraints.md "IoT 设备状态 bus 事件驱动").
|
|
//
|
|
// Milestone M5 delivers the pluggable provider skeleton plus a mock provider
|
|
// with eight simulated devices and the control_rules that bound what each device
|
|
// type supports. Real provider integrations (MQTT, Home Assistant) plug in later
|
|
// through the same Provider interface.
|
|
package iot
|
|
|
|
import "errors"
|
|
|
|
// DeviceUpdateSubject is the bus subject on which device state transitions are
|
|
// published. Subscribers use this subject (or "iot.>") to observe device
|
|
// changes.
|
|
const DeviceUpdateSubject = "iot.device_update"
|
|
|
|
// Sentinel errors returned by the iot subsystem. Use errors.Is to test for them.
|
|
var (
|
|
// ErrDeviceNotFound is returned when a device ID is unknown to every
|
|
// registered provider.
|
|
ErrDeviceNotFound = errors.New("iot: device not found")
|
|
// ErrUnsupported is returned when an action is not supported for a device's
|
|
// type (the device type's capability constraint), or when an action
|
|
// parameter value is outside the type's rule set.
|
|
ErrUnsupported = errors.New("iot: unsupported action")
|
|
// ErrOffline is returned when a Control call targets an offline device.
|
|
ErrOffline = errors.New("iot: device offline")
|
|
// ErrInvalidParam is returned when an action parameter is missing or has the
|
|
// wrong type.
|
|
ErrInvalidParam = errors.New("iot: invalid parameter")
|
|
// ErrUnknownProvider is returned when configuration names an unknown
|
|
// provider.
|
|
ErrUnknownProvider = errors.New("iot: unknown provider")
|
|
// ErrProviderNotRegistered is returned when a device operation is attempted
|
|
// but no provider is registered (for example the "none" provider).
|
|
ErrProviderNotRegistered = errors.New("iot: no provider registered")
|
|
// ErrInvalidArgument is returned when an argument is nil or empty.
|
|
ErrInvalidArgument = errors.New("iot: invalid argument")
|
|
// ErrDuplicate is returned when a provider with the same name is registered
|
|
// twice.
|
|
ErrDuplicate = errors.New("iot: provider already registered")
|
|
)
|
|
|
|
// Device is a single smart-home device exposed by a Provider.
|
|
type Device struct {
|
|
// ID is the globally unique device identifier used to target Control and
|
|
// Status calls.
|
|
ID string `json:"id"`
|
|
// Name is the human-readable device label.
|
|
Name string `json:"name"`
|
|
// Type is the device kind, for example "light", "ac", "curtain", "sensor" or
|
|
// "lock". The type determines the control_rules a Provider enforces.
|
|
Type string `json:"type"`
|
|
// State holds the device's current key/value state; the keys depend on the
|
|
// device Type.
|
|
State map[string]any `json:"state"`
|
|
// Online reports whether the device is currently reachable.
|
|
Online bool `json:"online"`
|
|
}
|
|
|
|
// Clone returns a copy of d with an independent State map, so callers can mutate
|
|
// the returned device without affecting the provider's internal state. Values in
|
|
// State are copied by reference; the mock provider stores only primitives.
|
|
func (d Device) Clone() Device {
|
|
cp := d
|
|
if d.State != nil {
|
|
cp.State = make(map[string]any, len(d.State))
|
|
for k, v := range d.State {
|
|
cp.State[k] = v
|
|
}
|
|
}
|
|
return cp
|
|
}
|
|
|
|
// DeviceUpdate is the payload published to DeviceUpdateSubject when a device
|
|
// state transitions, typically as the result of a Control call.
|
|
type DeviceUpdate struct {
|
|
// Provider is the name of the provider that owns the device.
|
|
Provider string
|
|
// Device is the post-transition device snapshot.
|
|
Device Device
|
|
// Action is the control action that produced the transition.
|
|
Action string
|
|
// Params are the optional control parameters.
|
|
Params map[string]any
|
|
}
|