Documentation
¶
Overview ¶
Package requestrules implements a declarative engine for polling on-demand NMEA 2000 data: send a request when a matching device comes online (or at startup), keep the data fresh, and re-request when a trigger PGN is seen — without duplicating ad-hoc request code per device/PGN.
The engine is transport-agnostic and has no dependency on the root lplex package (it operates on DeviceView, returns Request values). A driver (the broker) feeds it device/frame events and a clock tick, and transmits the Requests it returns.
Timing safety: every rule has a MinInterval — the floor between successive requests for the same (device, datum). The engine will never emit a request for the same target more often than MinInterval, regardless of how many triggers fire. An optional global floor caps the rate across all rules.
Index ¶
- type Config
- type DeviceView
- type Engine
- func (e *Engine) AddRule(r Rule) error
- func (e *Engine) InterestingPGNs() map[uint32]struct{}
- func (e *Engine) OnDeviceOffline(bus string, src uint8)
- func (e *Engine) OnDeviceOnline(d DeviceView) []Request
- func (e *Engine) OnFrame(bus string, src uint8, pgn uint32, data []byte) []Request
- func (e *Engine) Tick() []Request
- type Match
- type Request
- type Rule
- type Via
- type Want
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// GlobalMinInterval optionally caps the rate across ALL rules: no two
// requests are emitted closer together than this. 0 = no global cap.
GlobalMinInterval time.Duration
// Clock is injectable for tests; nil uses time.Now.
Clock func() time.Time
}
Config configures a new Engine.
type DeviceView ¶
type DeviceView struct {
Bus string
Source uint8
NAMEHex string
Manufacturer string
ManufacturerCode uint16
DeviceClass uint8
DeviceFunction uint8
DeviceInstance uint8
ModelID string
ProductCode uint16
}
DeviceView is the minimal device identity the engine matches against. The driver builds it from its own device registry (avoids an import cycle).
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine evaluates rules against device/frame events. All methods are safe for concurrent use, but in practice the driver calls them from one goroutine.
func (*Engine) InterestingPGNs ¶
InterestingPGNs returns the set of PGNs the engine cares about in OnFrame: the PGNs that mark a want fresh, plus the invalidation triggers. A driver (e.g. the broker) can check membership lock-free on its hot path and only call OnFrame for relevant frames, avoiding per-frame engine work.
func (*Engine) OnDeviceOffline ¶
OnDeviceOffline forgets a device so its freshness state is reset.
func (*Engine) OnDeviceOnline ¶
func (e *Engine) OnDeviceOnline(d DeviceView) []Request
OnDeviceOnline records a device as present and returns any requests triggered by OnOnline rules. Call when a device is first seen or its identity updates.
type Match ¶
type Match struct {
Manufacturer string
ManufacturerCode uint16 // 0 = any
ModelID string // exact, or "Prefix*"
DeviceClass *uint8
DeviceFunction *uint8
Name string // CAN NAME hex, exact (case-insensitive)
Source *uint8
Bus string
}
Match selects which devices a rule applies to. All set fields must match (logical AND); zero/empty fields are wildcards. ModelID matches case-insensitively and supports a single trailing '*' for prefix matching.
type Request ¶
type Request struct {
Bus string
Dst uint8
Via Via
PGN uint32 // ViaISORequest: PGN to request; ViaFrame: the frame's PGN
Data []byte // ViaFrame: the payload to send
Priority uint8
Rule string // originating rule name (for logging)
Want Want
}
Request is an action the driver should transmit.
type Rule ¶
type Rule struct {
Name string
Match Match
Wants []Want
Via Via
// Destination. If ToDevice is true the request is sent to the matched
// device's source address; otherwise to Dst (0 means 0xFF broadcast).
ToDevice bool
Dst uint8
// ViaFrame parameters.
FramePGN uint32
FramePriority uint8
FrameTemplate []byte // copied per request; SubKey written in if SubKeyWriteLen>0
SubKeyWriteOff int // byte offset in template to write the want's SubKey (LE)
SubKeyWriteLen int // 0 = don't write a subkey into the frame
SubKeyReadOff int // byte offset in a response to read the subkey (LE)
SubKeyReadLen int // 0 = responses are not sub-keyed
// Timing.
MinInterval time.Duration // REQUIRED: floor between requests for the same (device, want)
MaxAge time.Duration // refresh when the datum is older than this; 0 = request once
OnOnline bool // request when a matching device appears / at startup
InvalidateOn []uint32 // PGNs that, when seen from the device, mark wants stale
}
Rule is a declarative request rule. Construct directly (Go API) or via config.