This repository contains the Protocol Buffer definitions for the Terranova distributed control system. These definitions enable communication between various devices in the Terranova ecosystem including hubs, nodes, sensors, and actuators.
protobufs/
├── proto/ # Protocol Buffer definitions
│ ├── # Shared types and enumerations
│ │ ├── enums.proto # Device types and common enums
│ │ └── types.proto # Device UUIDs, CommandResult, GPSState, etc.
│ └── # Device-specific protocols + shared helpers
│ ├── device_common.proto # Shared commands (system info, ping, errors)
│ ├── device_routing.proto # UART-to-CAN bridge, discovery, firmware tools
│ ├── device_adc.proto # Analog-to-Digital Converter
│ ├── device_digital_output.proto # PWM/digital outputs
│ ├── device_rover.proto # Rover control
│ └── device_modbus_bridge.proto # Modbus RTU/TCP bridge
├── generated/ # Generated code (not committed)
│ └── nanopb/ # Nanopb C implementations
├── docs/ # Documentation
│ ├── PROTOCOL.md # Protocol specification
│ └── CHANGELOG.md # Version history
├── buf.yaml # Buf module + lint config
├── buf.gen.yaml # Buf codegen config (nanopb + TypeScript)
└── CMakeLists.txt # CMake build configuration
- Protocol Buffers Compiler:
protocversion 3.0 or higher - Nanopb: For embedded C code generation
- CMake: Version 3.15 or higher (for C/C++ projects)
- Buf (optional but recommended): Modern protobuf tooling
# Install protoc
brew install protobuf
# Install buf (recommended)
brew install bufbuild/buf/buf
# Install nanopb (if needed for C generation)
pip3 install nanopb# Install protoc
sudo apt-get install protobuf-compiler
# Install buf
curl -sSL "https://github.com/bufbuild/buf/releases/latest/download/buf-$(uname -s)-$(uname -m)" -o /usr/local/bin/buf
chmod +x /usr/local/bin/buf
# Install nanopb
pip3 install nanopb# Validate protos (compilation)
buf build
# Lint
buf lint
# Generate nanopb (C) + modern TypeScript
buf generatemkdir build && cd build
cmake ..
make# Generate for all proto files
protoc --proto_path=proto \
--nanopb_out=generated/nanopb \
proto/**/*.protoValidate your proto files before committing:
buf build
buf lintAll proto files use versioned packages:
package ringbahn;This allows for future API evolution while maintaining backward compatibility.
Add to your CMakeLists.txt:
add_subdirectory(path/to/protobufs)
target_link_libraries(your_target PRIVATE protobufs)# Generate Python code
protoc --proto_path=proto \
--python_out=. \
proto/**/*.protoSee Protocol Buffers documentation for language-specific generation.
All commands and telemetry are sent inside the Ringbahn frame. The base layout is:
- 0xA5 – Start-of-frame sentinel (not included in CRC)
- uint16 message_id – Host-assigned tracking ID for request/response correlation
- uint16 payload_length – Number of payload bytes
- payload – Protobuf bytes for the selected message
- crc16 – CRC computed over message_id, payload_length, and payload bytes
For UART links we also include addressing (inside the CRC):
- 12-byte sender UUID – Device UUID of the source
- 12-byte recipient UUID – Device UUID of the target
This removes the need for a giant envelope message. Each device only imports the proto file that defines the payload it cares about (e.g., device_adc.proto).
types.proto defines DeviceUUID, a fixed 12-byte identifier that mirrors the IDs carried in the Ringbahn header. DeviceInfo now contains this UUID along with any legacy short IDs so both discovery flows and payloads speak the same addressing language.
The system supports multiple device types:
DEVICE_TYPE_HUB: Main hub/coordinatorDEVICE_TYPE_NODE: Generic node moduleDEVICE_TYPE_ROUTING: UART-to-CAN routing bridge (handles discovery + firmware)DEVICE_TYPE_ADC: Analog-to-Digital ConverterDEVICE_TYPE_SD_ADC: Sigma-delta ADCDEVICE_TYPE_ROVER: Mobile robot platformDEVICE_TYPE_DIGITAL_OUT: PWM / digital output bridgeDEVICE_TYPE_MODBUS_BRIDGE: Modbus RTU/TCP bridge- Additional values can be added as needed in
enums.proto
- Request-Response: Commands return responses with matching message_id
- State Updates: Devices broadcast their
<Device>Statepayloads (e.g.,ADCState,RoverDeviceState) - Discovery: Automatic device detection via routing device
- Ping: In-band connectivity test using
PingCommand(returnsCommandResultwith success=1)
Note: Heartbeat/keep-alive is handled out-of-band by the transport layer and is not part of the protobuf protocol.
See PROTOCOL.md for detailed protocol specification.
proto/device_common.proto hosts messages that every device understands: SystemInfoRequest/Response, PingCommand, AcknowledgeResponse, and ErrorResponse.
proto/device_routing.proto defines the UART-to-CAN bridge. It now owns every discovery primitive (attached devices, active channel selection) as well as both firmware paths:
- Internal OTA: Commands (
InternalOta*) stream new firmware into the routing MCU and return compactInternalOtaStatusupdates. - Terraboot CAN bootloader:
Terraboot*messages map one-to-one with the Katapult/Terraboot protocol (connect,send_block,eof,request_block,complete,get_canbus_id) so routing firmware can forward frames down the CAN bus without extra wrappers.
All other device protos cover nodes that live exclusively on the CAN bus.
- Create a new proto file in
proto/(or extenddevice_common.protoif the command is shared). - Create a
.optionsfile for nanopb settings that matches the package name (ringbahn). - Update this README and the protocol docs to describe the new device's messages.
Use buf to detect breaking changes:
buf breaking --against '.git#branch=main'- Use clear, descriptive field names
- Add comments for all messages and fields
- Use enums for fixed sets of values
- Reserve field numbers for deleted fields
- Never change field numbers of existing fields
- Use
optionalfor nullable fields in proto3
Each proto file has a corresponding .options file that configures:
- Maximum array sizes (
max_count) - String buffer sizes (
max_size) - Fixed-length arrays (
fixed_length)
Example (device_adc.options):
ringbahn.ADCState.values max_count:8
The repository has been restructured for better organization. If you're migrating from the old flat structure:
- Old proto files are in
proto/(root level) - New proto files are organized in subdirectories
- CMakeLists.txt supports both old (
nanopb/) and new (generated/nanopb/) output paths - Package names now include version:
ringbahn
- Protocol Buffers Documentation
- Nanopb Documentation
- Buf Documentation
- Terranova Project Documentation
See LICENSE file for details.
- Create a feature branch
- Make your changes
- Run
buf buildandbuf lint - Run
buf generate - Submit a pull request
For questions or issues, please open an issue on GitHub or contact the Terranova team.
Version: 1.2.0
Last Updated: December 15, 2025
Maintainer: Terranova Team