Documentation
¶
Index ¶
- type ByteMaskDiff
- type ChangeEvent
- type ChangeEventType
- type ChangeReplayer
- type ChangeTracker
- func (ct *ChangeTracker) Process(ts time.Time, source uint8, pgnID uint32, data []byte, seq uint64) *ChangeEvent
- func (ct *ChangeTracker) Remove(source uint8, pgnID uint32, subKey uint64)
- func (ct *ChangeTracker) Reset()
- func (ct *ChangeTracker) Tick(now time.Time) []ChangeEvent
- func (ct *ChangeTracker) TrackedPairs() int
- type Config
- type DiffMethod
- type FieldTolerance
- type FieldToleranceDiff
- type SubKeyFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ByteMaskDiff ¶
type ByteMaskDiff struct{}
ByteMaskDiff is the default diff method. Any byte-level change is significant.
Short format (packets <= 8 bytes):
[mask:1] [changed bytes...]
Extended format (packets > 8 bytes):
[maskLen:2 LE] [mask bytes...] [changed bytes...]
func (ByteMaskDiff) Apply ¶
func (ByteMaskDiff) Apply(prev, diff []byte) []byte
type ChangeEvent ¶
type ChangeEvent struct {
Type ChangeEventType
Timestamp time.Time
Source uint8
PGN uint32
SubKey uint64
Seq uint64
Data []byte // Full data for Snapshot, diff for Delta, nil for Idle.
}
ChangeEvent is emitted by the ChangeTracker when a meaningful state change (or silence) is detected for a (source, PGN, subkey) tracking key.
type ChangeEventType ¶
type ChangeEventType uint8
ChangeEventType identifies the kind of change event.
const ( // Snapshot is the first observation for a key. Contains full packet data. Snapshot ChangeEventType = 1 // Delta means a significant change was detected. Contains a compact diff. Delta ChangeEventType = 2 // Idle means a source stopped producing for this key. Idle ChangeEventType = 3 )
func (ChangeEventType) String ¶
func (t ChangeEventType) String() string
type ChangeReplayer ¶
type ChangeReplayer struct {
// contains filtered or unexported fields
}
ChangeReplayer reconstructs full packet data from a stream of ChangeEvents. Maintains per-key state and applies diffs to recover the original packets.
func NewChangeReplayer ¶
func NewChangeReplayer(methods map[uint32]DiffMethod, subKeys map[uint32]SubKeyFunc) *ChangeReplayer
NewChangeReplayer creates a replayer. Pass the same methods and subkeys config used by the tracker that produced the events.
func (*ChangeReplayer) Apply ¶
func (r *ChangeReplayer) Apply(event ChangeEvent) ([]byte, error)
Apply processes a ChangeEvent and returns the reconstructed full packet data. Returns nil for Idle events (state is preserved but no data emitted). Returns an error if a Delta arrives without a prior Snapshot.
type ChangeTracker ¶
type ChangeTracker struct {
// contains filtered or unexported fields
}
ChangeTracker tracks per-(source, PGN, subkey) state and emits compact change events. Not goroutine-safe; designed for single-goroutine callers (like the broker's handleFrame).
func NewChangeTracker ¶
func NewChangeTracker(cfg Config) *ChangeTracker
NewChangeTracker creates a ChangeTracker with the given configuration. Automatically wires FieldToleranceDiff for any PGN in the registry that declares field-level tolerances, unless an explicit method is already set.
func (*ChangeTracker) Process ¶
func (ct *ChangeTracker) Process(ts time.Time, source uint8, pgnID uint32, data []byte, seq uint64) *ChangeEvent
Process handles an incoming frame and returns a ChangeEvent if the frame represents a meaningful state change. Returns nil for no-ops (unchanged data within tolerance).
func (*ChangeTracker) Remove ¶
func (ct *ChangeTracker) Remove(source uint8, pgnID uint32, subKey uint64)
Remove removes tracking state for a specific key.
func (*ChangeTracker) Tick ¶
func (ct *ChangeTracker) Tick(now time.Time) []ChangeEvent
Tick checks all tracked pairs for idle timeouts and returns Idle events for any that have exceeded their timeout. Call this periodically.
func (*ChangeTracker) TrackedPairs ¶
func (ct *ChangeTracker) TrackedPairs() int
TrackedPairs returns the number of actively tracked (source, PGN, subkey) pairs.
type Config ¶
type Config struct {
// DefaultMethod is the diff method used for PGNs without a specific override.
// Nil defaults to ByteMaskDiff.
DefaultMethod DiffMethod
// Methods maps specific PGNs to custom diff methods.
Methods map[uint32]DiffMethod
// SubKeys maps specific PGNs to sub-key extractor functions for
// multiplexed PGNs (e.g., Victron registers on PGN 61184).
SubKeys map[uint32]SubKeyFunc
// DefaultIdleTimeout is the fallback idle timeout when no PGN-specific
// timeout can be resolved. Defaults to 5s.
DefaultIdleTimeout time.Duration
// IdleMultiplier is applied to the PGN registry interval to compute
// the idle timeout. Defaults to 3.
IdleMultiplier int
// IdleTimeouts maps specific PGNs to explicit idle timeout overrides.
IdleTimeouts map[uint32]time.Duration
}
Config configures the ChangeTracker.
type DiffMethod ¶
type DiffMethod interface {
// Diff compares prev and curr, returning whether the change is significant
// and a compact diff encoding. If not significant, diff is nil.
Diff(prev, curr []byte) (significant bool, diff []byte)
// Apply reconstructs curr from prev and a diff produced by Diff.
Apply(prev, diff []byte) []byte
}
DiffMethod computes and applies compact binary diffs between packet payloads.
type FieldTolerance ¶
FieldTolerance defines a tolerance threshold for a named field. Changes within the tolerance are suppressed (not emitted as significant).
type FieldToleranceDiff ¶
type FieldToleranceDiff struct {
Inner DiffMethod
PGN uint32
Decode func([]byte) (any, error)
Tolerances []FieldTolerance
}
FieldToleranceDiff wraps an inner DiffMethod and uses PGN decode functions plus reflection to check field-level tolerances. If all changed fields are within their tolerance, the change is suppressed. The encoding is always delegated to the inner method (tolerances only gate significance).
The baseline is NOT updated when a change is suppressed, preventing tolerance drift over time.
func (*FieldToleranceDiff) Apply ¶
func (f *FieldToleranceDiff) Apply(prev, diff []byte) []byte
type SubKeyFunc ¶
SubKeyFunc extracts a sub-discriminator from raw packet data for multiplexed PGNs. Returns 0 for non-multiplexed PGNs (i.e., no sub-key extractor configured).