Documentation
¶
Overview ¶
Package nt4 provides a Go client for the NetworkTables 4 (NT4) protocol.
NT4 is a WebSocket-based pub/sub protocol used in FIRST Robotics Competition (FRC) for real-time data exchange between robots and control systems. This implementation uses MessagePack for binary serialization and supports all NT4 message types.
Quick Start ¶
Create a client and connect to an NT4 server:
opts := nt4.DefaultClientOptions("10.20.64.2")
client := nt4.NewClient(opts)
if err := client.Connect(); err != nil {
log.Fatal(err)
}
defer client.Disconnect()
Publishing Topics ¶
Publish a topic and send values:
topic := client.Publish("/robot/speed", nt4.TypeDouble, nil)
client.SetValue(topic, 42.5)
Or use convenience methods:
client.PublishDouble("/robot/speed", 42.5)
Subscribing to Topics ¶
Subscribe to topics and receive updates:
sub := client.Subscribe([]string{"/robot/speed"}, nil)
for update := range sub.Updates() {
fmt.Printf("%s = %v\n", update.Topic.Name, update.Value)
}
Subscribe with a callback:
opts := &nt4.SubscribeOptions{Prefix: true}
sub := client.Subscribe([]string{"/robot"}, opts)
sub.SetCallback(func(topic *Topic, timestamp int64, value any) {
fmt.Printf("%s = %v\n", topic.Name, value)
})
Time Synchronization ¶
The client automatically synchronizes time with the server every 3 seconds. Use GetServerTimeOffset() and GetLastRTT() to monitor synchronization.
Important Notes ¶
- The client does NOT automatically reconnect. Use ConnectWithRetry() for retry logic. - To receive topic announcements, you MUST have an active subscription. - Published topics receive server-assigned IDs only when subscribed. - Default port is 5810. - Timestamps are in microseconds (UnixMicro).
Type System ¶
NT4 supports the following types:
- Primitives: boolean, int, float, double, string
- Arrays: boolean[], int[], float[], double[], string[]
- Binary formats: raw, msgpack, protobuf, json
Use the Type constants (TypeBoolean, TypeDouble, etc.) when publishing topics.
Index ¶
- Constants
- Variables
- func TeamNumberToAddress(teamNumber int) string
- func TypeIDToString(typeID int) string
- func TypeStringToID(typeStr string) int
- type Client
- func (c *Client) Connect() error
- func (c *Client) ConnectWithRetry(ctx context.Context) error
- func (c *Client) Disconnect()
- func (c *Client) GetBoolean(name string, timeout time.Duration) (bool, bool)
- func (c *Client) GetDouble(name string, timeout time.Duration) (float64, bool)
- func (c *Client) GetInt(name string, timeout time.Duration) (int64, bool)
- func (c *Client) GetLastRTT() int64
- func (c *Client) GetServerTimeOffset() int64
- func (c *Client) GetString(name string, timeout time.Duration) (string, bool)
- func (c *Client) GetTopic(name string) *Topic
- func (c *Client) GetTopics() []*Topic
- func (c *Client) IsConnected() bool
- func (c *Client) Publish(name string, typeStr string, properties map[string]any) *Topic
- func (c *Client) PublishBoolean(name string, value bool) *Topic
- func (c *Client) PublishBooleanArray(name string, value []bool) *Topic
- func (c *Client) PublishDouble(name string, value float64) *Topic
- func (c *Client) PublishDoubleArray(name string, value []float64) *Topic
- func (c *Client) PublishInt(name string, value int64) *Topic
- func (c *Client) PublishIntArray(name string, value []int64) *Topic
- func (c *Client) PublishRaw(name string, value []byte) *Topic
- func (c *Client) PublishString(name string, value string) *Topic
- func (c *Client) PublishStringArray(name string, value []string) *Topic
- func (c *Client) SetProperties(name string, properties map[string]any)
- func (c *Client) SetValue(topic *Topic, value any)
- func (c *Client) Subscribe(topics []string, options *SubscribeOptions) *Subscription
- func (c *Client) SubscribeAndRetrieve(topic string, timeout time.Duration) any
- func (c *Client) SubscribeWithPrefix(prefix string, callback func(topic *Topic, timestamp int64, value any)) *Subscription
- func (c *Client) Unpublish(topic *Topic)
- func (c *Client) Unsubscribe(sub *Subscription)
- func (c *Client) WaitForConnection(ctx context.Context) error
- type ClientOptions
- type ConnectionError
- type DefaultLogger
- type LogLevel
- type Logger
- type ProtocolError
- type SilentLogger
- type SubscribeOptions
- type Subscription
- func (sub *Subscription) CloseUpdates()
- func (sub *Subscription) GetCallback() func(topic *Topic, timestamp int64, value any)
- func (sub *Subscription) InitUpdates(bufferSize int)
- func (sub *Subscription) SendUpdate(update TopicUpdate) bool
- func (sub *Subscription) SetCallback(callback func(topic *Topic, timestamp int64, value any))
- func (sub *Subscription) Updates() <-chan TopicUpdate
- type TimeoutError
- type Topic
- type TopicUpdate
- type ValidationError
Constants ¶
const ( TypeBoolean = "boolean" TypeDouble = "double" TypeInt = "int" TypeFloat = "float" TypeString = "string" TypeBooleanArray = "boolean[]" TypeDoubleArray = "double[]" TypeIntArray = "int[]" TypeFloatArray = "float[]" TypeStringArray = "string[]" TypeRaw = "raw" TypeMsgpack = "msgpack" TypeProtobuf = "protobuf" TypeJSON = "json" )
NT4 type strings.
const ( DataTypeBoolean = 0 DataTypeDouble = 1 DataTypeInt = 2 DataTypeFloat = 3 DataTypeString = 4 DataTypeBinary = 5 DataTypeBooleanArray = 16 DataTypeDoubleArray = 17 DataTypeIntArray = 18 DataTypeFloatArray = 19 DataTypeStringArray = 20 )
NT4 type binaries.
const DefaultPort = 5810
Default port for NT4 is on 5810.
Variables ¶
var ( // ErrNotConnected is returned when an operation requires an active connection. ErrNotConnected = errors.New("not connected to server") // ErrAlreadyConnected is returned when attempting to connect while already connected. ErrAlreadyConnected = errors.New("already connected to server") // ErrInvalidOptions is returned when client options are invalid. ErrInvalidOptions = errors.New("invalid client options") // ErrTopicNotFound is returned when a requested topic does not exist. ErrTopicNotFound = errors.New("topic not found") // ErrInvalidTopicID is returned when a topic ID is invalid or not yet assigned. ErrInvalidTopicID = errors.New("invalid topic ID") // ErrMessageEncoding is returned when message encoding/decoding fails. ErrMessageEncoding = errors.New("message encoding failed") // ErrMessageDecoding is returned when message decoding fails. ErrMessageDecoding = errors.New("message decoding failed") )
Common error types that can be checked with errors.Is().
Functions ¶
func TeamNumberToAddress ¶
FRC team number to a roboRIO server address. example: 2064 becomes "10.20.64.2".
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the main NT4 client that manages the WebSocket connection, topics, subscriptions, and time synchronization with the server.
func NewClient ¶
func NewClient(options ClientOptions) *Client
NewClient creates a new NT4 client with the specified options. Use DefaultClientOptions() for sensible defaults.
Example:
opts := nt4.DefaultClientOptions("10.20.64.2")
client := nt4.NewClient(opts)
func (*Client) Connect ¶
Connect establishes a WebSocket connection to the NT4 server. Returns an error if the connection fails.
For automatic retry logic, use ConnectWithRetry() instead.
func (*Client) ConnectWithRetry ¶
ConnectWithRetry attempts to connect to the server with automatic retries. It will keep retrying until successful or the context is cancelled.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := client.ConnectWithRetry(ctx); err != nil {
log.Fatal("Failed to connect:", err)
}
func (*Client) Disconnect ¶
func (c *Client) Disconnect()
Disconnect closes the connection to the NT4 server. Safe to call multiple times.
func (*Client) GetBoolean ¶
GetBoolean retrieves a boolean value from a topic. Returns (value, true) if successful, (false, false) if timeout or type mismatch.
func (*Client) GetDouble ¶
GetDouble retrieves a double value from a topic. Returns (value, true) if successful, (0, false) if timeout or type mismatch.
func (*Client) GetInt ¶
GetInt retrieves an int value from a topic. Returns (value, true) if successful, (0, false) if timeout or type mismatch.
func (*Client) GetLastRTT ¶
GetLastRTT returns the last measured round-trip time in microseconds.
func (*Client) GetServerTimeOffset ¶
GetServerTimeOffset returns the current server time offset in microseconds. This offset is used to convert local timestamps to server timestamps.
func (*Client) GetString ¶
GetString retrieves a string value from a topic. Returns (value, true) if successful, ("", false) if timeout or type mismatch.
func (*Client) IsConnected ¶
IsConnected returns true if the client is currently connected to the server.
func (*Client) Publish ¶
Publish announces a new topic to the server and returns the Topic handle. Use SetValue() to publish values to the topic.
Important: To receive the server-assigned topic ID in the announce message, you must have an active subscription. Otherwise, the topic will have ID 0.
Example:
topic := client.Publish("/robot/speed", nt4.TypeDouble, nil)
client.SetValue(topic, 42.5)
func (*Client) PublishBoolean ¶
PublishBoolean publishes a boolean topic with an initial value.
func (*Client) PublishBooleanArray ¶
PublishBooleanArray publishes a boolean array topic with an initial value.
func (*Client) PublishDouble ¶
PublishDouble publishes a double topic with an initial value.
func (*Client) PublishDoubleArray ¶
PublishDoubleArray publishes a double array topic with an initial value.
func (*Client) PublishInt ¶
PublishInt publishes an int topic with an initial value.
func (*Client) PublishIntArray ¶
PublishIntArray publishes an int array topic with an initial value.
func (*Client) PublishRaw ¶
PublishRaw publishes a raw binary topic with an initial value.
func (*Client) PublishString ¶
PublishString publishes a string topic with an initial value.
func (*Client) PublishStringArray ¶
PublishStringArray publishes a string array topic with an initial value.
func (*Client) SetProperties ¶
SetProperties updates properties for a topic.
func (*Client) SetValue ¶
SetValue publishes a value to a topic. The topic must have been created with Publish() or received via subscription.
func (*Client) Subscribe ¶
func (c *Client) Subscribe(topics []string, options *SubscribeOptions) *Subscription
Subscribe creates a subscription to one or more topics. Returns a Subscription that can be used to receive updates via the Updates() channel.
The topics parameter can contain exact topic names or patterns (if Prefix option is set). Set SubscribeOptions.Prefix to true to match topic prefixes.
Example:
// Subscribe to a single topic
sub := client.Subscribe([]string{"/robot/speed"}, nil)
// Subscribe to all topics with a prefix
opts := &nt4.SubscribeOptions{Prefix: true, All: true}
sub := client.Subscribe([]string{"/robot"}, opts)
// Receive updates
for update := range sub.Updates() {
fmt.Printf("%s = %v\n", update.Topic.Name, update.Value)
}
func (*Client) SubscribeAndRetrieve ¶
SubscribeAndRetrieve subscribes to a topic, waits for the first update, then unsubscribes. Returns nil if the timeout expires before receiving a value.
func (*Client) SubscribeWithPrefix ¶
func (c *Client) SubscribeWithPrefix(prefix string, callback func(topic *Topic, timestamp int64, value any)) *Subscription
SubscribeWithPrefix creates a subscription with prefix matching and callback.
func (*Client) Unsubscribe ¶
func (c *Client) Unsubscribe(sub *Subscription)
Unsubscribe removes an active subscription.
type ClientOptions ¶
type ClientOptions struct {
// Address of NT4 server (10.TE.AM.2 for rio, 127.0.0.1 for sim).
ServerAddress string
// NT4 Port.
// Default: 5810 (DefaultPort)
Port int
// Client identifier.
// Default: "Go-NT4-Client"
Identity string
// Called when the client connects to the server.
// Optional callback.
OnConnect func()
// Called when the client disconnects from the server.
// Optional callback.
OnDisconnect func()
// OnTopicAnnounce is called when a topic is announced by the server.
// To receive announcements, you must have an active subscription.
// Optional callback.
OnTopicAnnounce func(topic *Topic)
// OnTopicUnannounce is called when a topic is unannounced by the server.
// Optional callback.
OnTopicUnannounce func(topic *Topic)
// Wait between reconnection attempts when using ConnectWithRetry.
// Default: 1 second
ReconnectInterval time.Duration
// Logger instance.
// Default: NewDefaultLogger(LogLevelInfo)
// Use NewSilentLogger() to disable logging.
Logger Logger
}
NT4 client config.
func DefaultClientOptions ¶
func DefaultClientOptions(serverAddress string) ClientOptions
ClientOptions with defaults. See ClientOptions for serverAddress.
type ConnectionError ¶
ConnectionError represents an error that occurred during connection establishment.
func (*ConnectionError) Error ¶
func (e *ConnectionError) Error() string
Error implements the error interface.
func (*ConnectionError) Unwrap ¶
func (e *ConnectionError) Unwrap() error
Unwrap returns the underlying error.
type DefaultLogger ¶
type DefaultLogger struct {
// contains filtered or unexported fields
}
DefaultLogger provides a simple logger that writes to stdout using the standard library log package. It supports log levels and structured key-value pairs.
func NewDefaultLogger ¶
func NewDefaultLogger(level LogLevel) *DefaultLogger
NewDefaultLogger creates a new DefaultLogger with the specified log level. Use LogLevelInfo for normal operation, LogLevelDebug for troubleshooting, or LogLevelSilent to disable all logging.
func (*DefaultLogger) Debug ¶
func (l *DefaultLogger) Debug(msg string, keysAndValues ...any)
Debug logs a debug message if the log level is LogLevelDebug.
func (*DefaultLogger) Error ¶
func (l *DefaultLogger) Error(msg string, keysAndValues ...any)
Error logs an error message if the log level is LogLevelError or lower.
func (*DefaultLogger) Info ¶
func (l *DefaultLogger) Info(msg string, keysAndValues ...any)
Info logs an informational message if the log level is LogLevelInfo or lower.
func (*DefaultLogger) Warn ¶
func (l *DefaultLogger) Warn(msg string, keysAndValues ...any)
Warn logs a warning message if the log level is LogLevelWarn or lower.
type LogLevel ¶
type LogLevel int
LogLevel represents the severity of a log message.
const ( // LogLevelDebug enables all logging including verbose debug messages. LogLevelDebug LogLevel = iota // LogLevelInfo enables informational messages, warnings, and errors. LogLevelInfo // LogLevelWarn enables warnings and errors only. LogLevelWarn // LogLevelError enables error messages only. LogLevelError // LogLevelSilent disables all logging. LogLevelSilent )
type Logger ¶
type Logger interface {
// Debug logs a debug message with optional key-value pairs.
Debug(msg string, keysAndValues ...any)
// Info logs an informational message with optional key-value pairs.
Info(msg string, keysAndValues ...any)
// Warn logs a warning message with optional key-value pairs.
Warn(msg string, keysAndValues ...any)
// Error logs an error message with optional key-value pairs.
Error(msg string, keysAndValues ...any)
}
Logger is the interface for logging within the NT4 client. It follows a structured logging pattern with key-value pairs, similar to slog.
Example usage:
logger.Info("connected to server", "address", "10.20.64.2", "port", 5810)
logger.Error("connection failed", "error", err)
func NewSilentLogger ¶
func NewSilentLogger() Logger
NewSilentLogger returns a logger that discards all log messages.
type ProtocolError ¶
ProtocolError represents an error in NT4 protocol handling.
func (*ProtocolError) Error ¶
func (e *ProtocolError) Error() string
Error implements the error interface.
func (*ProtocolError) Unwrap ¶
func (e *ProtocolError) Unwrap() error
Unwrap returns the underlying error.
type SilentLogger ¶
type SilentLogger struct{}
SilentLogger is a logger that discards all log messages. Useful for testing or when you want to completely disable logging.
func (*SilentLogger) Debug ¶
func (l *SilentLogger) Debug(msg string, keysAndValues ...any)
Debug does nothing.
func (*SilentLogger) Error ¶
func (l *SilentLogger) Error(msg string, keysAndValues ...any)
Error does nothing.
func (*SilentLogger) Info ¶
func (l *SilentLogger) Info(msg string, keysAndValues ...any)
Info does nothing.
func (*SilentLogger) Warn ¶
func (l *SilentLogger) Warn(msg string, keysAndValues ...any)
Warn does nothing.
type SubscribeOptions ¶
type SubscribeOptions struct {
// Time between updates in seconds. (0 for fastest)
Periodic float64
// Send all values or only latest.
All bool
// Send topic announcements without values.
TopicsOnly bool
// If true, treats items in Topics as prefixes.
Prefix bool
}
Config for subscribers.
type Subscription ¶
type Subscription struct {
// Client assigned subscription ID.
UID int32
// List of topic paths subscribed to.
Topics []string
// Subscription config.
Options SubscribeOptions
// contains filtered or unexported fields
}
Active subscription to one or more topics.
func (*Subscription) CloseUpdates ¶
func (sub *Subscription) CloseUpdates()
Close the update channel. Called internally when unsubscribing.
func (*Subscription) GetCallback ¶
func (sub *Subscription) GetCallback() func(topic *Topic, timestamp int64, value any)
Get the current callback function.
func (*Subscription) InitUpdates ¶
func (sub *Subscription) InitUpdates(bufferSize int)
Creates the update channel with specified buffer size. Called internally when creating a subscription.
func (*Subscription) SendUpdate ¶
func (sub *Subscription) SendUpdate(update TopicUpdate) bool
Send an update to the channel. Returns true if sent, false if channel is full. Called internally.
func (*Subscription) SetCallback ¶
func (sub *Subscription) SetCallback(callback func(topic *Topic, timestamp int64, value any))
Set callback for topic updates. Non-blocking.
func (*Subscription) Updates ¶
func (sub *Subscription) Updates() <-chan TopicUpdate
Get the updates channel for this subscription. Updates are sent to both the channel and any registered callback.
Example:
for update := range subscription.Updates() {
fmt.Printf("Topic: %s, Value: %v\n", update.Topic.Name, update.Value)
}
type TimeoutError ¶
TimeoutError represents a timeout during an operation.
func (*TimeoutError) Error ¶
func (e *TimeoutError) Error() string
Error implements the error interface.
func (*TimeoutError) Unwrap ¶
func (e *TimeoutError) Unwrap() error
Unwrap returns the underlying error.
type Topic ¶
type Topic struct {
// Server assigned topic ID.
ID int32
// Topic path ("/robot/speed").
Name string
// NT4 type string (e.g., "double", "string", "boolean[]").
// Should be pulled from NT4 Type String constants.
Type string
// Type ID for binary messages.
// Should be pulled from NT4 Type Binary constants.
TypeID int
// Topic metadata (e.g., "persistent", "retained").
Properties map[string]any
// Publisher UID.
PubUID int32
// contains filtered or unexported fields
}
A NT4 topic.
func (*Topic) UpdateProperties ¶
Thread safe merge of new properties into current.
type TopicUpdate ¶
type TopicUpdate struct {
// Topic is the Network Table topic that was updated.
Topic *Topic
// Server timestamp microseconds.
Timestamp int64
// The value to be set. The value should align to the Topic type.
Value any
}
TopicUpdate represents an update to a subscribed topic.
type ValidationError ¶
ValidationError represents invalid input or configuration.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Error implements the error interface.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
bidirectional
command
|
|
|
publisher
command
|
|
|
subscriber
command
|
|
|
subscriber_callback
command
|
|
|
team_robot
command
|