docs(iot): 存量英文注释中文化(仅注释,代码零字节改动)
- 5 个文件:123 行英文注释 → 99 行中文注释(中文更紧凑,内容无删减)。 - 机械校验(git diff -U0 去掉 // 行与空行)输出为空;gofmt -l 干净(改动前亦干净)。 - 验收:go build/vet/test ./internal/iot/... 全绿。
This commit is contained in:
1 parent
127c32b440
commit
2593765add
5 files changed
+99
-123
No files matched your search
+39
-50
@@ -1,72 +1,62 @@
|
||||
// Package iot provides the IoT device source abstraction for Cyrene v2.
|
||||
// Package iot 提供 Cyrene v2 的 IoT 设备来源抽象。
|
||||
//
|
||||
// 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 事件驱动").
|
||||
// 它把智能家居设备(灯、空调、窗帘、传感器、门锁)建模为强类型设备,交由可插拔的
|
||||
// Provider 管理。Provider 即设备来源;Manager 依据配置选定 Provider,对外提供
|
||||
// List/Control/Status,并把设备状态跃迁作为事件发布到进程内 bus,使其他子系统
|
||||
// (前端、记忆、推送)无需轮询即可感知设备变化(对照
|
||||
// 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.
|
||||
// 里程碑 M5 交付可插拔 Provider 骨架,外加一个 mock Provider:内置八台模拟设备,
|
||||
// 以及界定每种设备类型支持范围的 control_rules。真实 Provider 集成(MQTT、
|
||||
// Home Assistant)后续通过同一套 Provider 接口接入。
|
||||
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.
|
||||
// DeviceUpdateSubject 是设备状态跃迁事件发布所用的 bus 主题。订阅方使用该主题
|
||||
// (或 "iot.>")观察设备变化。
|
||||
const DeviceUpdateSubject = "iot.device_update"
|
||||
|
||||
// Sentinel errors returned by the iot subsystem. Use errors.Is to test for them.
|
||||
// iot 子系统返回的哨兵错误,判定时请用 errors.Is。
|
||||
var (
|
||||
// ErrDeviceNotFound is returned when a device ID is unknown to every
|
||||
// registered provider.
|
||||
// ErrDeviceNotFound 表示该设备 ID 对全部已注册 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 表示某动作不被该设备类型支持(受该类型的 capability 约束),
|
||||
// 或动作参数取值超出该类型的规则集合。
|
||||
ErrUnsupported = errors.New("iot: unsupported action")
|
||||
// ErrOffline is returned when a Control call targets an offline device.
|
||||
// ErrOffline 表示 Control 调用指向了离线设备。
|
||||
ErrOffline = errors.New("iot: device offline")
|
||||
// ErrInvalidParam is returned when an action parameter is missing or has the
|
||||
// wrong type.
|
||||
// ErrInvalidParam 表示动作参数缺失或类型错误。
|
||||
ErrInvalidParam = errors.New("iot: invalid parameter")
|
||||
// ErrUnknownProvider is returned when configuration names an unknown
|
||||
// provider.
|
||||
// ErrUnknownProvider 表示配置指定了未知的 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 表示尝试执行设备操作,但没有任何已注册的 Provider
|
||||
// (例如 "none" Provider)。
|
||||
ErrProviderNotRegistered = errors.New("iot: no provider registered")
|
||||
// ErrInvalidArgument is returned when an argument is nil or empty.
|
||||
// ErrInvalidArgument 表示传入参数为 nil 或空。
|
||||
ErrInvalidArgument = errors.New("iot: invalid argument")
|
||||
// ErrDuplicate is returned when a provider with the same name is registered
|
||||
// twice.
|
||||
// ErrDuplicate 表示同名 Provider 被注册了两次。
|
||||
ErrDuplicate = errors.New("iot: provider already registered")
|
||||
)
|
||||
|
||||
// Device is a single smart-home device exposed by a Provider.
|
||||
// Device 是由某个 Provider 暴露的单台智能家居设备。
|
||||
type Device struct {
|
||||
// ID is the globally unique device identifier used to target Control and
|
||||
// Status calls.
|
||||
// ID 是设备全局唯一标识,Control 与 Status 调用据此定位设备。
|
||||
ID string `json:"id"`
|
||||
// Name is the human-readable device label.
|
||||
// Name 是供人阅读的设备名称。
|
||||
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 是设备种类,例如 "light"、"ac"、"curtain"、"sensor"、"lock";
|
||||
// 类型决定 Provider 施加的 control_rules。
|
||||
Type string `json:"type"`
|
||||
// State holds the device's current key/value state; the keys depend on the
|
||||
// device Type.
|
||||
// State 保存设备当前的键值状态;具体键取决于设备的 Type。
|
||||
State map[string]any `json:"state"`
|
||||
// Online reports whether the device is currently reachable.
|
||||
// Online 表示设备当前是否可达。
|
||||
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.
|
||||
// Clone 返回 d 的副本,其中 State 为独立 map,因此调用方可以随意修改返回的设备
|
||||
// 而不影响 Provider 的内部状态。State 中的值按引用复制;mock Provider 只存放
|
||||
// 基本类型值。
|
||||
func (d Device) Clone() Device {
|
||||
cp := d
|
||||
if d.State != nil {
|
||||
@@ -78,18 +68,17 @@ func (d Device) Clone() Device {
|
||||
return cp
|
||||
}
|
||||
|
||||
// DeviceUpdate is the payload published to DeviceUpdateSubject when a device
|
||||
// state transitions, typically as the result of a Control call.
|
||||
// DeviceUpdate 是设备状态跃迁时发布到 DeviceUpdateSubject 的载荷,通常由一次
|
||||
// Control 调用产生。
|
||||
type DeviceUpdate struct {
|
||||
// Provider is the name of the provider that owns the device.
|
||||
// Provider 是拥有该设备的 Provider 名称。
|
||||
Provider string `json:"provider"`
|
||||
// Device is the post-transition device snapshot.
|
||||
// Device 是跃迁后的设备快照。
|
||||
Device Device `json:"device"`
|
||||
// Action is the control action that produced the transition.
|
||||
// Action 是触发该次跃迁的控制动作。
|
||||
Action string `json:"action"`
|
||||
// Params are the optional control parameters.
|
||||
// Params 是可选的控制参数。
|
||||
Params map[string]any `json:"params,omitempty"`
|
||||
// Message is a human-readable summary of the transition, surfaced to the
|
||||
// frontend device_update feed.
|
||||
// Message 是跃迁的可读摘要,会呈现到前端的 device_update 信息流中。
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
||||
)
|
||||
|
||||
// fakeProvider is a stub Provider used to exercise Manager.Register and the
|
||||
// device-operation routing without touching the concrete mockProvider.
|
||||
// fakeProvider 是桩 Provider,用于验证 Manager.Register 与设备操作路由,
|
||||
// 而不触碰具体的 mockProvider。
|
||||
type fakeProvider struct {
|
||||
name string
|
||||
device Device
|
||||
@@ -40,7 +40,7 @@ func (f fakeProvider) Status(_ context.Context, id string) (*Device, error) {
|
||||
return &cp, nil
|
||||
}
|
||||
|
||||
// recvIoT blocks until a DeviceUpdate is delivered or the deadline passes.
|
||||
// recvIoT 阻塞等待,直到收到一条 DeviceUpdate 或超过等待时限。
|
||||
func recvIoT(t *testing.T, ch <-chan DeviceUpdate, d time.Duration) DeviceUpdate {
|
||||
t.Helper()
|
||||
select {
|
||||
|
||||
+27
-32
@@ -13,35 +13,32 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
|
||||
)
|
||||
|
||||
// Manager is the IoT subsystem facade. It selects a Provider from
|
||||
// configuration, serves List/Control/Status, and publishes device state
|
||||
// transitions on the in-process bus as DeviceUpdate events.
|
||||
// Manager 是 IoT 子系统的门面:依据配置选定 Provider,对外提供
|
||||
// List/Control/Status,并把设备状态跃迁以 DeviceUpdate 事件的形式发布到进程内 bus。
|
||||
type Manager struct {
|
||||
providers []Provider
|
||||
bus bus.Bus
|
||||
log *slog.Logger
|
||||
}
|
||||
|
||||
// Option customizes a Manager built by New.
|
||||
// Option 用于定制由 New 构建的 Manager。
|
||||
type Option func(*Manager)
|
||||
|
||||
// WithBus injects an existing bus instead of letting the Manager create one. It
|
||||
// mirrors the other subsystems so iot.device_update flows on the shared bus and
|
||||
// reaches the gateway hub / background-trigger subscribers rather than staying
|
||||
// on an isolated manager-owned bus.
|
||||
// WithBus 注入现成的 bus,而不让 Manager 自建一个。此设计与其余子系统保持一致:
|
||||
// iot.device_update 由此流经共享 bus,能到达 gateway hub / 后台触发订阅者,
|
||||
// 而不是滞留在一个 Manager 私有的隔离 bus 上。
|
||||
func WithBus(b bus.Bus) Option {
|
||||
return func(m *Manager) { m.bus = b }
|
||||
}
|
||||
|
||||
// New builds a Manager from cfg, selecting the device Provider by cfg.Provider.
|
||||
// New 依据 cfg 构建 Manager,并以 cfg.Provider 选定设备 Provider。
|
||||
//
|
||||
// Supported providers: "" or "mock" registers the built-in mock provider with
|
||||
// eight simulated devices; "none" disables the subsystem (no provider is
|
||||
// registered, List returns an empty slice and Control/Status fail with
|
||||
// ErrDeviceNotFound). Any other value returns ErrUnknownProvider.
|
||||
// 支持的 Provider 取值:"" 或 "mock" 注册内置 mock Provider(八台模拟设备);
|
||||
// "none" 关闭该子系统(不注册任何 Provider,List 返回空切片,Control/Status 以
|
||||
// ErrDeviceNotFound 失败)。其他取值返回 ErrUnknownProvider。
|
||||
//
|
||||
// log may be nil; it is replaced with a discard logger. The Manager owns a
|
||||
// fresh, isolated bus exposed via Bus for subscribers to attach to.
|
||||
// log 可为 nil,此时会替换为丢弃输出的 logger。Manager 自持一个全新且隔离的 bus,
|
||||
// 经 Bus 暴露给订阅方挂接。
|
||||
func New(cfg config.IoTConfig, log *slog.Logger, opts ...Option) (*Manager, error) {
|
||||
m := &Manager{
|
||||
bus: bus.New(),
|
||||
@@ -58,7 +55,7 @@ func New(cfg config.IoTConfig, log *slog.Logger, opts ...Option) (*Manager, erro
|
||||
}
|
||||
m.providers = append(m.providers, mp)
|
||||
case "none":
|
||||
// No provider is registered: the subsystem is disabled.
|
||||
// 不注册任何 Provider:子系统处于关闭状态。
|
||||
default:
|
||||
return nil, fmt.Errorf("iot: new: provider %q: %w", cfg.Provider, ErrUnknownProvider)
|
||||
}
|
||||
@@ -66,8 +63,8 @@ func New(cfg config.IoTConfig, log *slog.Logger, opts ...Option) (*Manager, erro
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Register adds p as a device source. Registering a provider whose Name already
|
||||
// exists returns ErrDuplicate; a nil provider returns ErrInvalidArgument.
|
||||
// Register 把 p 注册为设备来源。注册的 Provider 若 Name 已存在,返回 ErrDuplicate;
|
||||
// p 为 nil 则返回 ErrInvalidArgument。
|
||||
func (m *Manager) Register(p Provider) error {
|
||||
if p == nil {
|
||||
return fmt.Errorf("iot: register: %w", ErrInvalidArgument)
|
||||
@@ -82,13 +79,13 @@ func (m *Manager) Register(p Provider) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bus returns the Manager's in-process event bus. Subscribers attach to
|
||||
// DeviceUpdateSubject (or "iot.>") to observe device state transitions.
|
||||
// Bus 返回 Manager 的进程内事件总线。订阅方挂接 DeviceUpdateSubject
|
||||
// (或 "iot.>")以观察设备状态跃迁。
|
||||
func (m *Manager) Bus() bus.Bus {
|
||||
return m.bus
|
||||
}
|
||||
|
||||
// List returns every device from every registered provider.
|
||||
// List 返回全部已注册 Provider 的所有设备。
|
||||
func (m *Manager) List(ctx context.Context) ([]Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -105,9 +102,8 @@ func (m *Manager) List(ctx context.Context) ([]Device, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Control applies action to the owning provider's device and, on success,
|
||||
// publishes a DeviceUpdate on the bus. It returns ErrDeviceNotFound when no
|
||||
// provider owns the device.
|
||||
// Control 把 action 施加到拥有该设备的 Provider 上,成功后向 bus 发布一条
|
||||
// DeviceUpdate。若没有任何 Provider 拥有该设备,返回 ErrDeviceNotFound。
|
||||
func (m *Manager) Control(ctx context.Context, deviceID, action string, params map[string]any) (*Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -129,8 +125,8 @@ func (m *Manager) Control(ctx context.Context, deviceID, action string, params m
|
||||
return nil, fmt.Errorf("iot: control %q: %w", deviceID, ErrDeviceNotFound)
|
||||
}
|
||||
|
||||
// Status returns the current state of the device owned by the matching provider.
|
||||
// It returns ErrDeviceNotFound when no provider owns the device.
|
||||
// Status 返回由匹配 Provider 所持有设备的当前状态。若没有任何 Provider 拥有该
|
||||
// 设备,返回 ErrDeviceNotFound。
|
||||
func (m *Manager) Status(ctx context.Context, deviceID string) (*Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -151,10 +147,9 @@ func (m *Manager) Status(ctx context.Context, deviceID string) (*Device, error)
|
||||
return nil, fmt.Errorf("iot: status %q: %w", deviceID, ErrDeviceNotFound)
|
||||
}
|
||||
|
||||
// publishUpdate fans a DeviceUpdate out on the bus. A publish failure (for
|
||||
// example a canceled context) is logged, not returned: the device state already
|
||||
// changed, and control should not be reported as failed because an observer did
|
||||
// not receive the event.
|
||||
// publishUpdate 把 DeviceUpdate 扇出到 bus。发布失败(例如 ctx 被取消)只记日志、
|
||||
// 不作为错误返回:设备状态已经改变,不应因为某个观察者没收到事件就把本次控制判为
|
||||
// 失败。
|
||||
func (m *Manager) publishUpdate(ctx context.Context, provider string, d Device, action string, params map[string]any) {
|
||||
msg := fmt.Sprintf("设备 %s · %s(%s)", d.Name, action, provider)
|
||||
if err := m.bus.Publish(ctx, DeviceUpdateSubject, DeviceUpdate{
|
||||
@@ -170,8 +165,8 @@ func (m *Manager) publishUpdate(ctx context.Context, provider string, d Device,
|
||||
m.log.Debug("iot device update published", "device", d.ID, "action", action, "provider", provider)
|
||||
}
|
||||
|
||||
// discardLogger returns log if non-nil, otherwise a logger that writes nowhere,
|
||||
// so New always has a safe logger to use.
|
||||
// discardLogger 在 log 非 nil 时原样返回,否则返回一个不写任何输出的 logger,
|
||||
// 保证 New 始终有可用的 logger。
|
||||
func discardLogger(log *slog.Logger) *slog.Logger {
|
||||
if log != nil {
|
||||
return log
|
||||
|
||||
+20
-25
@@ -11,10 +11,8 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
|
||||
)
|
||||
|
||||
// mockProvider is the built-in deterministic Provider with eight simulated
|
||||
// devices spread across every supported device type. It enforces the
|
||||
// control_rules (capability constraints) that bound what each device type
|
||||
// supports.
|
||||
// mockProvider 是内置的确定性 Provider,八台模拟设备覆盖全部受支持的设备类型。
|
||||
// 它施加 control_rules(capability 约束),界定每种设备类型的支持范围。
|
||||
type mockProvider struct {
|
||||
mu sync.RWMutex
|
||||
log *slog.Logger
|
||||
@@ -22,19 +20,18 @@ type mockProvider struct {
|
||||
rules map[string]typeRules
|
||||
}
|
||||
|
||||
// typeRules holds the control_rules for one device type: the set of supported
|
||||
// actions and how each mutates the device state.
|
||||
// typeRules 保存单一设备类型的 control_rules:受支持的动作集合,以及每个动作
|
||||
// 如何改动设备状态。
|
||||
type typeRules struct {
|
||||
supported map[string]applyFunc
|
||||
}
|
||||
|
||||
// applyFunc mutates d.State according to the action. It returns an error when
|
||||
// the parameters are invalid.
|
||||
// applyFunc 依据动作修改 d.State;参数非法时返回错误。
|
||||
type applyFunc func(d *Device, params map[string]any) error
|
||||
|
||||
const mockProviderName = "mock"
|
||||
|
||||
// Name returns the provider identifier.
|
||||
// Name 返回 Provider 标识。
|
||||
func (m *mockProvider) Name() string { return mockProviderName }
|
||||
|
||||
func newMockProvider(log *slog.Logger) (*mockProvider, error) {
|
||||
@@ -49,7 +46,7 @@ func newMockProvider(log *slog.Logger) (*mockProvider, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// List returns every device, sorted by ID for deterministic output.
|
||||
// List 返回全部设备,按 ID 排序以保证输出确定。
|
||||
func (m *mockProvider) List(ctx context.Context) ([]Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -64,7 +61,7 @@ func (m *mockProvider) List(ctx context.Context) ([]Device, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Status returns a clone of the named device.
|
||||
// Status 返回指定设备的副本。
|
||||
func (m *mockProvider) Status(ctx context.Context, deviceID string) (*Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -79,7 +76,7 @@ func (m *mockProvider) Status(ctx context.Context, deviceID string) (*Device, er
|
||||
return &cp, nil
|
||||
}
|
||||
|
||||
// Control applies action to the named device, enforcing the type's control_rules.
|
||||
// Control 对指定设备施加 action,并强制该类型的 control_rules。
|
||||
func (m *mockProvider) Control(ctx context.Context, deviceID, action string, params map[string]any) (*Device, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
@@ -109,7 +106,7 @@ func (m *mockProvider) Control(ctx context.Context, deviceID, action string, par
|
||||
return &cp, nil
|
||||
}
|
||||
|
||||
// buildRules returns the control_rules for every supported device type.
|
||||
// buildRules 返回全部受支持设备类型的 control_rules。
|
||||
func buildRules() map[string]typeRules {
|
||||
return map[string]typeRules{
|
||||
"light": lightRules(),
|
||||
@@ -120,7 +117,7 @@ func buildRules() map[string]typeRules {
|
||||
}
|
||||
}
|
||||
|
||||
// lightRules returns the control_rules for light devices.
|
||||
// lightRules 返回灯类设备的 control_rules。
|
||||
func lightRules() typeRules {
|
||||
return typeRules{supported: map[string]applyFunc{
|
||||
"on": func(d *Device, _ map[string]any) error {
|
||||
@@ -150,7 +147,7 @@ func lightRules() typeRules {
|
||||
}}
|
||||
}
|
||||
|
||||
// acRules returns the control_rules for AC devices.
|
||||
// acRules 返回空调设备的 control_rules。
|
||||
func acRules() typeRules {
|
||||
return typeRules{supported: map[string]applyFunc{
|
||||
"on": func(d *Device, _ map[string]any) error {
|
||||
@@ -185,7 +182,7 @@ func acRules() typeRules {
|
||||
}}
|
||||
}
|
||||
|
||||
// curtainRules returns the control_rules for curtain devices.
|
||||
// curtainRules 返回窗帘设备的 control_rules。
|
||||
func curtainRules() typeRules {
|
||||
return typeRules{supported: map[string]applyFunc{
|
||||
"open": func(d *Device, _ map[string]any) error {
|
||||
@@ -208,14 +205,13 @@ func curtainRules() typeRules {
|
||||
}}
|
||||
}
|
||||
|
||||
// sensorRules returns the control_rules for sensor devices. Sensors are
|
||||
// read-only: no action is supported, so any Control attempt returns
|
||||
// ErrUnsupported.
|
||||
// sensorRules 返回传感器设备的 control_rules。传感器只读:不支持任何动作,
|
||||
// 因此任何 Control 尝试都会返回 ErrUnsupported。
|
||||
func sensorRules() typeRules {
|
||||
return typeRules{supported: map[string]applyFunc{}}
|
||||
}
|
||||
|
||||
// lockRules returns the control_rules for lock devices.
|
||||
// lockRules 返回门锁设备的 control_rules。
|
||||
func lockRules() typeRules {
|
||||
return typeRules{supported: map[string]applyFunc{
|
||||
"lock": func(d *Device, _ map[string]any) error {
|
||||
@@ -233,9 +229,8 @@ func lockRules() typeRules {
|
||||
}}
|
||||
}
|
||||
|
||||
// mockDevices returns the eight seeded mock devices. It covers all five types;
|
||||
// ac.bedroom is seeded offline to exercise the Online field and the offline
|
||||
// control guard.
|
||||
// mockDevices 返回八台预置的模拟设备,覆盖全部五种类型;ac.bedroom 预置为离线,
|
||||
// 用于检验 Online 字段与离线控制保护逻辑。
|
||||
func mockDevices() []*Device {
|
||||
return []*Device{
|
||||
{ID: "ac.bedroom", Name: "卧室空调", Type: "ac", Online: false, State: map[string]any{"on": false, "temperature": 26, "mode": "cool"}},
|
||||
@@ -274,8 +269,8 @@ func clamp(n, lo, hi int) int {
|
||||
return n
|
||||
}
|
||||
|
||||
// intParam reads an integer action parameter, accepting int/int64/float64/string
|
||||
// shapes so JSON-decoded params work the same as literal ones.
|
||||
// intParam 读取整型动作参数,可接受 int/int64/float64/string 等多种形态,
|
||||
// 使 JSON 解码得到的参数与字面量参数行为一致。
|
||||
func intParam(p map[string]any, key string) (int, error) {
|
||||
v, ok := p[key]
|
||||
if !ok {
|
||||
|
||||
+10
-13
@@ -2,23 +2,20 @@ package iot
|
||||
|
||||
import "context"
|
||||
|
||||
// Provider is a pluggable source of IoT devices. Implementations own the device
|
||||
// state and enforce the control_rules (capability constraints) for each device
|
||||
// type, so a type's set of supported actions is its capability.
|
||||
// Provider 是可插拔的 IoT 设备来源。实现方持有设备状态,并为每种设备类型施加
|
||||
// control_rules(capability 约束)——因此某类型支持的动作集合即其能力边界。
|
||||
//
|
||||
// Implementations must be safe for concurrent use, because the Manager may serve
|
||||
// List/Control/Status from multiple goroutines.
|
||||
// 实现必须是并发安全的,因为 Manager 可能从多个 goroutine 并发调用
|
||||
// List/Control/Status。
|
||||
type Provider interface {
|
||||
// Name returns the stable provider identifier, used for logging and to
|
||||
// disambiguate providers registered on one Manager.
|
||||
// Name 返回稳定的 Provider 标识,用于日志,以及区分注册在同一 Manager 上的
|
||||
// 多个 Provider。
|
||||
Name() string
|
||||
// List returns every device currently known to the provider.
|
||||
// List 返回该 Provider 当前已知的全部设备。
|
||||
List(ctx context.Context) ([]Device, error)
|
||||
// Control applies action with params to the named device and returns the
|
||||
// post-transition device. It returns ErrDeviceNotFound for an unknown device
|
||||
// and ErrUnsupported for an action the device's type does not support.
|
||||
// Control 对指定设备施加 action(携带 params),并返回跃迁后的设备。
|
||||
// 设备未知时返回 ErrDeviceNotFound;设备类型不支持该动作时返回 ErrUnsupported。
|
||||
Control(ctx context.Context, deviceID, action string, params map[string]any) (*Device, error)
|
||||
// Status returns the current state of the named device. It returns
|
||||
// ErrDeviceNotFound when the device is unknown.
|
||||
// Status 返回指定设备的当前状态;设备未知时返回 ErrDeviceNotFound。
|
||||
Status(ctx context.Context, deviceID string) (*Device, error)
|
||||
}
|
||||
Reference in new issue
Block a user