Documentation ¶
Overview ¶
Package device provides basic device definition and management.
This package offers a definition of a basic device, D, as well as several implementations of D.
Users wishing to interact with real devices will find better utility in the "discovery" package, which uses this package to instantiate Remote devices for each discovered device.
Mutable is offered to track the pixel state of a given device and generate mutation packets to sync the device to that state.
Snapshot can be used to store a (potentially-sampled) pixel state of a given of device.
Optional Prometheus monitoring can be enabled by registering on startup (generally init()) via RegisterMonitoring.
Index ¶
- Variables
- func IsDone(d D) bool
- func RegisterMonitoring(reg prometheus.Registerer)
- type D
- type Info
- type Listener
- type Local
- func (d *Local) Addr() net.Addr
- func (d *Local) Close() error
- func (d *Local) DiscoveryHeaders() *protocol.DiscoveryHeaders
- func (d *Local) DoneC() <-chan struct{}
- func (d *Local) ID() string
- func (d *Local) Info() Info
- func (d *Local) Ordinal() Ordinal
- func (d *Local) Sender() (Sender, error)
- func (d *Local) Start(conn *net.UDPConn)
- func (d *Local) String() string
- func (d *Local) UpdateHeaders(dh *protocol.DiscoveryHeaders)
- type Monitoring
- type Mutable
- func (m *Mutable) ClonePixelsTo(strip int, target *pixel.Buffer)
- func (m *Mutable) GetPixel(strip, p int) pixel.P
- func (m *Mutable) Initialize(dh *protocol.DiscoveryHeaders)
- func (m *Mutable) NumStrips() int
- func (m *Mutable) PixelsPerStrip() int
- func (m *Mutable) SetPixel(strip, pixel int, v pixel.P) bool
- func (m *Mutable) SetPixels(strip int, pixels *pixel.Buffer)
- func (m *Mutable) SyncPacket() *protocol.Packet
- type Ordinal
- type Registry
- type Remote
- func (d *Remote) Addr() net.Addr
- func (d *Remote) DiscoveryHeaders() *protocol.DiscoveryHeaders
- func (d *Remote) DoneC() <-chan struct{}
- func (d *Remote) ID() string
- func (d *Remote) Info() (i Info)
- func (d *Remote) MarkDone()
- func (d *Remote) Ordinal() Ordinal
- func (d *Remote) Sender() (Sender, error)
- func (d *Remote) String() string
- func (d *Remote) UpdateHeaders(now time.Time, dh *protocol.DiscoveryHeaders)
- type Router
- type Sender
- type Snapshot
- type SnapshotManager
Constants ¶
This section is empty.
Variables ¶
var ErrNoRoute = errors.New("no route for device")
ErrNoRoute is a sentinel error that is returned by a Router's Route command when the requested device is not registered.
Functions ¶
func RegisterMonitoring ¶
func RegisterMonitoring(reg prometheus.Registerer)
RegisterMonitoring registers all of this package's monitoring metrics.
Types ¶
type D ¶
type D interface { // ID is this device's ID. It should be unique (within this system) to this // device, and should be consistent between executions, regardless of simple // reconfiguations on the device's part. // // A hardware address is suitable for this purpose. ID() string // Ordinal returns this Device's ordinal value. Ordinal() Ordinal // Sender returns a device Sender instance. // // Multiple Senders can be created for the same device; however, any // individual Sender is not safe for concurrent use (see Sender interface // for more information). // // It is the caller's responsibility to close the Sender when finished. Sender() (Sender, error) // DiscoveryHeaders returns the device's discovery protocol headers. // // DiscoveryHeaders may return nil if no headers are available. // // DiscoveryHeaders can be used to obtain a protocol.PacketReader, if packet // parsing is required. DiscoveryHeaders() *protocol.DiscoveryHeaders // DoneC is closed when this D is no longer considered active. DoneC() <-chan struct{} // Addr is this device's address. It may be nil. Addr() net.Addr // Info returns the current information and stats for this device. Info() Info }
D is a single device. It implements a generic device interface.
type Info ¶
type Info struct { PacketsReceived int64 BytesReceived int64 PacketsSent int64 BytesSent int64 Created time.Time Observed time.Time }
Info is a set of stats collected for this device.
type Listener ¶
type Listener interface { // HandlePacket is called for each Packet sent to this Router. // // pkt is a shared read-only object, and must not be modified. HandlePacket(d D, pkt *protocol.Packet) }
Listener is registered with a Router, and receives a callback for each routed packet.
type Local ¶
type Local struct { // The local device's ID. DeviceID string // OnPacketData is wthe callback that is called when new packet data is // received. // // OnPacketData must not be nil. // // The packet data is owned by a bufferpool.Pool. Recipients of the buffer may // Retain it and Release it to prevent it from reentering the pool. The buffer // that is handed to the callback is automatically Released when the callback // returns; the callback SHOULD NOT release the buffer. OnPacketData func(buf *bufferpool.Buffer) // UDPPacketPool, if not nil, is the packet pool to use for UDP packet data. // // If nil, a local packet pool will be generated and used. UDPPacketPool *bufferpool.Pool // Logger, if not nil, is the logger to use to log events. // // Changes to Logger after Start is called will have no effect. Logger logging.L // contains filtered or unexported fields }
Local is a local "virtual' device. A Local allows your local system to instantiate its own devices. Local can be useful for testing and the simluation of devices.
Local's exported fields must not be changed after Start is called.
func (*Local) Close ¶
Close closes the Local, freeing its remote connection resource and marking it Done.
After Close has returned, no more packet callbacks will be sent.
func (*Local) DiscoveryHeaders ¶
func (d *Local) DiscoveryHeaders() *protocol.DiscoveryHeaders
DiscoveryHeaders implements D.
func (*Local) Start ¶
Start finishes device setup and begins listening for packets.
The returned device presumes ownership over conn, and will close it when closed.
func (*Local) UpdateHeaders ¶
func (d *Local) UpdateHeaders(dh *protocol.DiscoveryHeaders)
UpdateHeaders sets the base discovery headers to use for this device.
These headers will be updated internally to include the local device address information.
UpdateHeaders must be called at least once before DiscoveryHeaders is invoked, ideally at setup.
type Monitoring ¶
type Monitoring struct {
// contains filtered or unexported fields
}
Monitoring is a thin wrapper around a D that logs monitoring information about that device.
type Mutable ¶
type Mutable struct {
// contains filtered or unexported fields
}
Mutable wraps a device, D, offering a method of setting and updating its pixel state.
Currently, Mutable is only implemented for PixelPusher devices.
Mutable is not safe for concurrent use; concurrent users must lock around it.
func (*Mutable) ClonePixelsTo ¶
ClonePixelsTo clones the contents of the specified pixel strip into target.
If strip references an invalid strip index, nothing will happen, and target will be unmodified.
func (*Mutable) GetPixel ¶
GetPixel returns the value of the specified pixel offset in the specified strip.
If p or strip are out of bounds, a zero-value pixel will be returned.
func (*Mutable) Initialize ¶
func (m *Mutable) Initialize(dh *protocol.DiscoveryHeaders)
Initialize ensures that each strip state matches the state described by the device's discovery headers.
Initialize can be called more than once, and will adjust the current strip and pixel count based on the current set of headers.
func (*Mutable) PixelsPerStrip ¶
PixelsPerStrip returns the number of pixels per strip.
func (*Mutable) SetPixel ¶
SetPixel sets the value of the specified pixel in the specified strip to v.
If the pixel exists and was modified, SetPixel will return true and note that it has been mutated.
If index is out of bounds, SetPixel will not change anything and return false.
func (*Mutable) SetPixels ¶
SetPixels sets the full set of pixels for this device to the value in pixels.
If pixels has the same flags and size as m's strip, SetPixels will be a fast buffer clone. Otherwise, pixels will be set pixel-by-pixel within bounds.
If strip is out of bounds, nothing will be updated.
func (*Mutable) SyncPacket ¶
SyncPacket generates a packet containing an update instruction for each modified strip. All strips will be marked unmodified after sync.
type Ordinal ¶
Ordinal is the device's ordinal value, identifying which logical group it belongs to.
func InvalidOrdinal ¶
func InvalidOrdinal() Ordinal
InvalidOrdinal returns an Ordinal that registers as invalid.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a generic device registry. It tracks devices by ID, records which group devices belong to, and removes device entries when they expire.
func (*Registry) DevicesForGroup ¶
DevicesForGroup returns the devices for the specified group.
If no devices are registered in that group, it will return an empty slice.
func (*Registry) Get ¶
Get returns the registered device for the specified ID.
If no device is registered for this ID, Get will return nil.
func (*Registry) GetUniqueOrdinal ¶
GetUniqueOrdinal returns the registered device for the specified ordinal.
If there is no device that is uniquely registered for o, GetOrdinal will return nil.
type Remote ¶
type Remote struct { // Logger, if not nil, is the logger that this device and its supporting // constructs will use. Logger logging.L // contains filtered or unexported fields }
Remote is a device implementation for a remote PixelPusher device.
Remote is typically backed by a discovered device's headers. In this case, Remote is a fully-functional local stub for that device and its most recent state.
Remote may also be constructed directly as a stub with MakeRemoteStub. In this case, it will not have access to any headers, and is used solely as a local stub to the remote device.
func MakeRemote ¶
func MakeRemote(id string, dh *protocol.DiscoveryHeaders) *Remote
MakeRemote initializes a Remote device instance.
The device must not be used until it has been observed via Observe(), at which point it will become fully active and valid.
func MakeRemoteStub ¶
MakeRemoteStub constructs a new Remote device without requiring a full set of headers.
MakeRemoteStub can be used to communicate with devices at known addresses.
func (*Remote) DiscoveryHeaders ¶
func (d *Remote) DiscoveryHeaders() *protocol.DiscoveryHeaders
DiscoveryHeaders implements D.
func (*Remote) MarkDone ¶
func (d *Remote) MarkDone()
MarkDone closes this device's done channel, shutting down any observation and marking this device "done" to external users.
MarkDone is safe for concurrent use, and may be called multiple times; however, calls past the first time will do nothing.
func (*Remote) UpdateHeaders ¶
func (d *Remote) UpdateHeaders(now time.Time, dh *protocol.DiscoveryHeaders)
UpdateHeaders live-updates this device's headers.
This can be used to update an instance of the device that has been observed with a new set of headers (e.g., via discovery).
type Router ¶
type Router struct { // Registry is the device registry. It is used to identify devices that will // receive routed packets. // // Registry must not be nil Registry *Registry // Logger is the logger that this Router should use. // // Setting or changing Logger should be done during Router setup, and is // not safe for concurrent use. Logger logging.L // contains filtered or unexported fields }
Router contains a registry of devices. Once registered, a device remains with the Router until it is either removed or marks itself done via DoneC.
A Router accepts a series of packets delivered to a specific device ID, and sends those packets to that device via a PacketWriter.
A Router operates on a device ID's Value field, rather than the full ID, since its targeted at sending recorded data, which will not include the ID's Type parameter.
func (*Router) AddListener ¶
AddListener registers a Listener with this Router.
func (*Router) RemoveListener ¶
RemoveListener removes a Listener from this Router.
If l is not registered, nothing will happen.
type Sender ¶
type Sender interface { // DatagramSender sends a raw datagram to the underlying device. // // Generally, users should prefer to send packets via SendPacket over // SendDatagram. network.DatagramSender // SendPacket writes the contents of packet to the target device. // // Unlike SendDatagram, SendPacket has the opportunity to examine the content // and intent of the packet and determine how to optimally send it to the // target device. // // Regardless of any internal buffering, SendPacket will not retain any of // packet. SendPacket(packet *protocol.Packet) error }
Sender is an interface that can dispatch data and packets to a single device.
Sender is not safe for concurrent use.
func MonitorSender ¶
MonitorSender wraps a Sender from d in a monitoring shim.
type Snapshot ¶
type Snapshot struct { // ID is the snapshot device ID. ID string // Strips is the set of strips on this device. Strips []*pixelpusher.StripState }
Snapshot represents a snapshot of the device state.
A Snapshot is an independent data clone.
Currently this only supports PixelPusher device states.
type SnapshotManager ¶
type SnapshotManager struct { // SampleRate is the snapshot sample rate. After a sample is taken, any // further samples will be ignored until SampleRate has passed. // // If SampleRate is <= 0, all samples will be taken. SampleRate time.Duration // contains filtered or unexported fields }
SnapshotManager manages device state snapshots.
TODO: Generalize for more than PixelPusher.
SnapshotManager is safe for concurrent use.
func (*SnapshotManager) Delete ¶
func (m *SnapshotManager) Delete(d D)
Delete removes any stored snapshot state for d.
func (*SnapshotManager) HandlePacket ¶
func (m *SnapshotManager) HandlePacket(d D, pkt *protocol.Packet)
HandlePacket accepts a packet, pkt, and updates its associated strip snapshot based on the packet's contents. If the packet isn't a pixel packet, it will be ignored.
func (*SnapshotManager) HasSnapshotForDevice ¶
func (m *SnapshotManager) HasSnapshotForDevice(d D) bool
HasSnapshotForDevice returns true if a snapshot is stored for d.
func (*SnapshotManager) SnapshotForDevice ¶
func (m *SnapshotManager) SnapshotForDevice(d D) *Snapshot
SnapshotForDevice returns the current snapshot for the specified device.