Documentation
¶
Overview ¶
Serialmux provides an abstraction over a serial port with the ability for multiple clients to subscribe to events from the serial port and send commands to a single serial port device.
Index ¶
- Constants
- Variables
- func ClassifyPayload(payload string) string
- func CurrentStateSnapshot() map[string]any
- func HandleConfigResponse(payload string) error
- func HandleEvent(d *db.DB, payload string) error
- func HandleRadarObject(d *db.DB, payload string) error
- func HandleRawData(d *db.DB, payload string) error
- type DisabledSerialMux
- func (d *DisabledSerialMux) AttachAdminRoutes(mux *http.ServeMux)
- func (d *DisabledSerialMux) Close() error
- func (d *DisabledSerialMux) Initialise() error
- func (d *DisabledSerialMux) Monitor(ctx context.Context) error
- func (d *DisabledSerialMux) SendCommand(string) error
- func (d *DisabledSerialMux) Subscribe() (string, chan string)
- func (d *DisabledSerialMux) Unsubscribe(id string)
- type MockOpenCall
- type MockSerialPort
- type MockSerialPortFactory
- type Parity
- type RealSerialPortFactory
- type SerialMux
- func (s *SerialMux[T]) AttachAdminRoutes(mux *http.ServeMux)
- func (s *SerialMux[T]) Close() error
- func (s *SerialMux[T]) Initialise() error
- func (s *SerialMux[T]) Monitor(ctx context.Context) error
- func (s *SerialMux[T]) SendCommand(command string) error
- func (s *SerialMux[T]) Subscribe() (string, chan string)
- func (s *SerialMux[T]) Unsubscribe(id string)
- type SerialMuxInterface
- type SerialPortFactory
- type SerialPortMode
- type SerialPortOpener
- type SerialPorter
- type StopBits
- type TestableSerialPort
- func (t *TestableSerialPort) AddReadData(data []byte)
- func (t *TestableSerialPort) Close() error
- func (t *TestableSerialPort) GetWrittenData() []byte
- func (t *TestableSerialPort) Read(p []byte) (n int, err error)
- func (t *TestableSerialPort) Reset()
- func (t *TestableSerialPort) SetReadTimeout(timeout time.Duration) error
- func (t *TestableSerialPort) Write(p []byte) (n int, err error)
- type TimeoutSerialPorter
Constants ¶
const ( EventTypeRadarObject = "radar_object" EventTypeRawData = "raw_data" EventTypeConfig = "config" EventTypeUnknown = "unknown" )
Variables ¶
var ErrWriteFailed = fmt.Errorf("failed to write to serial port")
Functions ¶
func ClassifyPayload ¶
ClassifyPayload inspects a payload string and returns a simple event type token. The classification is intentionally conservative and mirrors the previous logic used in handlers.
func CurrentStateSnapshot ¶ added in v0.5.0
CurrentStateSnapshot returns a shallow copy of the latest config values received from the device. Returns nil if no config has been received yet. Callers must treat the returned map and all nested values (maps, slices, etc.) as read-only. Code that needs to modify the data should first deep-copy it.
func HandleConfigResponse ¶
Types ¶
type DisabledSerialMux ¶
type DisabledSerialMux struct {
// contains filtered or unexported fields
}
DisabledSerialMux is a no-op SerialMux implementation used when the radar hardware is absent (for --disable-radar). It allows the server and admin routes to run without a real device. Unlike the previous simple implementation, this version tracks subscribers so their channels can be deterministically closed on Unsubscribe() or Close(), allowing readers to unblock predictably during shutdown.
func NewDisabledSerialMux ¶
func NewDisabledSerialMux() *DisabledSerialMux
func (*DisabledSerialMux) AttachAdminRoutes ¶
func (d *DisabledSerialMux) AttachAdminRoutes(mux *http.ServeMux)
func (*DisabledSerialMux) Close ¶
func (d *DisabledSerialMux) Close() error
func (*DisabledSerialMux) Initialise ¶
func (d *DisabledSerialMux) Initialise() error
func (*DisabledSerialMux) SendCommand ¶
func (d *DisabledSerialMux) SendCommand(string) error
func (*DisabledSerialMux) Subscribe ¶
func (d *DisabledSerialMux) Subscribe() (string, chan string)
func (*DisabledSerialMux) Unsubscribe ¶
func (d *DisabledSerialMux) Unsubscribe(id string)
type MockOpenCall ¶ added in v0.5.0
type MockOpenCall struct {
Path string
Mode *SerialPortMode
}
MockOpenCall records details of an Open call.
type MockSerialPort ¶
type MockSerialPort struct {
io.Reader
io.WriteCloser
}
MockSerialPort implements SerialPorter for testing
func (*MockSerialPort) SyncClock ¶
func (m *MockSerialPort) SyncClock() error
type MockSerialPortFactory ¶ added in v0.5.0
type MockSerialPortFactory struct {
// Port is the port to return from Open
Port SerialPorter
// Error is returned by Open if set
Error error
// OpenCalls records all Open calls
OpenCalls []MockOpenCall
// contains filtered or unexported fields
}
MockSerialPortFactory implements SerialPortFactory for testing.
func NewMockSerialPortFactory ¶ added in v0.5.0
func NewMockSerialPortFactory(port SerialPorter) *MockSerialPortFactory
NewMockSerialPortFactory creates a new MockSerialPortFactory.
func (*MockSerialPortFactory) LastCall ¶ added in v0.5.0
func (f *MockSerialPortFactory) LastCall() *MockOpenCall
LastCall returns the most recent Open call, or nil if none.
func (*MockSerialPortFactory) Open ¶ added in v0.5.0
func (f *MockSerialPortFactory) Open(path string, mode *SerialPortMode) (SerialPorter, error)
Open returns the configured port or error.
func (*MockSerialPortFactory) Reset ¶ added in v0.5.0
func (f *MockSerialPortFactory) Reset()
Reset clears all recorded calls.
type RealSerialPortFactory ¶ added in v0.5.0
type RealSerialPortFactory struct{}
RealSerialPortFactory implements SerialPortFactory using the go.bug.st/serial library.
func NewRealSerialPortFactory ¶ added in v0.5.0
func NewRealSerialPortFactory() *RealSerialPortFactory
NewRealSerialPortFactory creates a new RealSerialPortFactory.
func (*RealSerialPortFactory) Open ¶ added in v0.5.0
func (f *RealSerialPortFactory) Open(path string, mode *SerialPortMode) (SerialPorter, error)
Open opens a real serial port at the specified path.
type SerialMux ¶
type SerialMux[T SerialPorter] struct { // contains filtered or unexported fields }
SerialMux is a generic serial port multiplexer that allows multiple clients to subscribe to events from a single serial port.
func NewMockSerialMux ¶
func NewMockSerialMux(mockLine []byte) *SerialMux[*MockSerialPort]
NewMockSerialMux creates a SerialMux instance backed by a mock serial port
func NewRealSerialMux ¶
NewRealSerialMux creates a SerialMux instance backed by a real serial port at the given path.
func NewSerialMux ¶
func NewSerialMux[T SerialPorter](port T) *SerialMux[T]
NewSerialMux creates a SerialMux instance backed by a serial port at the given path.
func (*SerialMux[T]) AttachAdminRoutes ¶
func (*SerialMux[T]) Initialise ¶
Initialise syncs the clock and TZ offset to the device and sets some default output modes to ensure that we can parse the results.
func (*SerialMux[T]) Monitor ¶
Monitor monitors the serial port for events and sends them to subscribers
func (*SerialMux[T]) SendCommand ¶
SendCommand sends a command to the serial port.
func (*SerialMux[T]) Unsubscribe ¶
Unsubscribe removes a subscriber from the serial mux.
type SerialMuxInterface ¶
type SerialMuxInterface interface {
// Subscribe creates a new channel for receiving line events from the serial
// port. The channel ID is used to identify the unique channel when
// unsubscribing.
Subscribe() (string, chan string)
// Unsubscribe removes a channel from the list of subscribers.
Unsubscribe(string)
// SendCommand writes the provided command to the serial port.
SendCommand(string) error
// Monitor reads lines from the serial port and sends them to the
// appropriate channels.
Monitor(context.Context) error
// Close closes all subscribed channels and closes the serial port.
Close() error
Initialise() error
// AttachAdminRoutes attaches admin debugging endpoints to the given HTTP
// mux served at /debug/. These routes are accessible only over
// localhost/via Tailscale and are not publicly accessible.
AttachAdminRoutes(*http.ServeMux)
}
SerialMuxInterface defines the interface for the SerialMux type.
type SerialPortFactory ¶ added in v0.5.0
type SerialPortFactory interface {
// Open opens a serial port at the specified path with the given mode.
Open(path string, mode *SerialPortMode) (SerialPorter, error)
}
SerialPortFactory defines an interface for creating serial ports. This abstraction enables dependency injection of serial port creation.
type SerialPortMode ¶ added in v0.5.0
SerialPortMode defines serial port configuration parameters.
func DefaultSerialPortMode ¶ added in v0.5.0
func DefaultSerialPortMode() *SerialPortMode
DefaultSerialPortMode returns the default mode for radar sensors.
type SerialPortOpener ¶ added in v0.5.0
type SerialPortOpener func(path string, mode *SerialPortMode) (SerialPorter, error)
SerialPortOpener is a function type for opening serial ports. This allows for easier testing by replacing the opener function.
type SerialPorter ¶
type SerialPorter interface {
io.ReadWriter
io.Closer
}
SerialPorter defines the minimal interface needed for a serial port. This abstraction enables unit testing without real serial hardware.
type TestableSerialPort ¶ added in v0.5.0
type TestableSerialPort struct {
// ReadBuffer holds data to be returned by Read calls
ReadBuffer *bytes.Buffer
// WriteBuffer captures data written to the port
WriteBuffer *bytes.Buffer
// ReadLatency adds a delay to each Read call
ReadLatency time.Duration
// WriteLatency adds a delay to each Write call
WriteLatency time.Duration
// ReadError is returned by the next Read call if set
ReadError error
// WriteError is returned by the next Write call if set
WriteError error
// CloseError is returned by Close if set
CloseError error
// Closed indicates whether Close was called
Closed bool
// ReadCalls records the number of Read calls
ReadCalls int
// WriteCalls records the number of Write calls
WriteCalls int
// ReadTimeout is the current read timeout
ReadTimeout time.Duration
// BlockReads causes Read to block until data is added or Close is called
BlockReads bool
// contains filtered or unexported fields
}
TestableSerialPort implements SerialPorter with configurable behaviour for testing. It provides fine-grained control over reads, writes, errors, and latency.
func NewTestableSerialPort ¶ added in v0.5.0
func NewTestableSerialPort() *TestableSerialPort
NewTestableSerialPort creates a new TestableSerialPort for testing.
func (*TestableSerialPort) AddReadData ¶ added in v0.5.0
func (t *TestableSerialPort) AddReadData(data []byte)
AddReadData adds data to be returned by subsequent Read calls.
func (*TestableSerialPort) Close ¶ added in v0.5.0
func (t *TestableSerialPort) Close() error
Close marks the port as closed.
func (*TestableSerialPort) GetWrittenData ¶ added in v0.5.0
func (t *TestableSerialPort) GetWrittenData() []byte
GetWrittenData returns all data written to the port.
func (*TestableSerialPort) Read ¶ added in v0.5.0
func (t *TestableSerialPort) Read(p []byte) (n int, err error)
Read reads from the read buffer, optionally simulating latency and errors.
func (*TestableSerialPort) Reset ¶ added in v0.5.0
func (t *TestableSerialPort) Reset()
Reset clears all buffers and resets state.
func (*TestableSerialPort) SetReadTimeout ¶ added in v0.5.0
func (t *TestableSerialPort) SetReadTimeout(timeout time.Duration) error
SetReadTimeout implements TimeoutSerialPorter.
type TimeoutSerialPorter ¶ added in v0.5.0
type TimeoutSerialPorter interface {
SerialPorter
// SetReadTimeout sets the read timeout for the serial port.
SetReadTimeout(timeout time.Duration) error
}
TimeoutSerialPorter extends SerialPorter with timeout capabilities. This is an optional interface that serial ports may implement.