Skip to content

Binary Protocol Specification

Marc Sanchis edited this page Jun 8, 2025 · 1 revision

Binary Protocol Specification

This document defines the binary wire protocol used for communication between the vehicle and backend over TCP/UDP networks.

Protocol Overview

Transport Protocols: TCP (reliable) and UDP (fast)
Byte Order: Little-endian for all multi-byte fields
Character Encoding: ASCII for string fields
Packet Format: Fixed header + variable payload

Base Packet Structure

All packets follow this structure:

Byte Offset:  0        2        4+
             |========|========|========|
             |   Packet ID     | Payload |
             |   (uint16_le)   |   ...   |
             |========|========|========|

Field Descriptions:

  • Packet ID (2 bytes): Little-endian uint16 identifying packet type
  • Payload (variable): Packet-specific binary data

Message Types

1. Data Packets

Purpose: Continuous telemetry data from vehicle sensors

Structure:

Byte Offset:  0        2        4+
             |========|========|========|
             |   Packet ID     | Values  |
             |   (uint16_le)   | (ADJ)   |
             |========|========|========|

Value Encoding:

  • uint8: 1 byte unsigned integer
  • uint16: 2 bytes unsigned integer (little-endian)
  • uint32: 4 bytes unsigned integer (little-endian)
  • uint64: 8 bytes unsigned integer (little-endian)
  • int8: 1 byte signed integer (two's complement)
  • int16: 2 bytes signed integer (little-endian, two's complement)
  • int32: 4 bytes signed integer (little-endian, two's complement)
  • int64: 8 bytes signed integer (little-endian, two's complement)
  • float32: 4 bytes IEEE 754 single-precision (little-endian)
  • float64: 8 bytes IEEE 754 double-precision (little-endian)
  • bool: 1 byte (0x00 = false, 0x01 = true)
  • enum: Encoded as underlying integer type

Example: VCU Regulator Packet (ID: 211)

Packet Definition (ADJ):
{
    "id": 211,
    "variables": ["valve_state", "reference_pressure", "actual_pressure"]
}

Measurements:
- valve_state: uint8 enum (0=closed, 1=open, 2=error)
- reference_pressure: float32 (bar)
- actual_pressure: float32 (bar)

Binary Data:
Byte:  0    1    2    3    4    5    6    7    8    9   10
Data: 0xD3 0x00 0x01 0x42 0x08 0x00 0x00 0x42 0x04 0x66 0x66
Field: [ID 211] [valve=1] [ref_pressure=8.5] [act_pressure=8.1]

2. Protection Packets

Purpose: Safety alerts and fault notifications

Complete Structure:

Byte Offset:  0        2        4        5        6        7+
             |========|========|========|========|========|========|
             |   Packet ID     |  type  |  kind  |  Name String    |
             |   (uint16_le)   |(uint8) |(uint8) |  (null-term)    |
             |========|========|========|========|========|========|
             |           Protection Data (variable)                 |
             |========|========|========|========|========|========|
             |counter |counter | second | minute | hour   | day    |
             |(uint16)|(uint16)|(uint8) |(uint8) |(uint8) |(uint8) |
             |========|========|========|========|========|========|
             | month  |       year      |
             |(uint8) |   (uint16_le)   |
             |========|========|========|

Protection Types:

0x00: IntType (int32)      0x06: LongType (int64)
0x01: FloatType (float32)  0x07: Uint8Type (uint8)
0x02: DoubleType (float64) 0x08: Uint16Type (uint16)  
0x03: CharType (uint8)     0x09: Uint32Type (uint32)
0x04: BoolType (bool)      0x0A: Uint64Type (uint64)
0x05: ShortType (int16)    0x0B: Int8Type (int8)

Protection Kinds:

0x00: Below              - Value below threshold
0x01: Above              - Value above threshold  
0x02: OutOfBounds        - Value outside range
0x03: Equals             - Value equals condition
0x04: NotEquals          - Value not equals condition
0x05: ErrorHandler       - System error condition
0x06: TimeAccumulation   - Time-based fault
0x07: Warning            - General warning

Example: Brake pressure above safe limit

Binary Data:
Byte:     0    1    2    3    4-18              19-22      23-26
Data:   0x02 0x00 0x01 0x01 "brake_pressure\0" 0x42D20000 0x42C80000
Field:  [ID=2] [float32] [above] [name] [current=105.0] [threshold=100.0]

3. Order Packets

Purpose: Commands sent from backend to vehicle

Add Order Structure:

Byte Offset:  0        2        4        6+
             |========|========|========|========|
             |   Packet ID     | Count  | Order IDs |
             |   (uint16_le)   |(uint16)|  (uint16s) |
             |========|========|========|========|

Example: Add State Orders (ID: 5)

Binary Data:
Byte:     0    1    2    3    4    5    6    7
Data:   0x05 0x00 0x02 0x00 0x10 0x00 0x11 0x00  
Field:  [ID=5] [count=2] [order1=16] [order2=17]

4. State Space Packets

Purpose: Control system state matrices

Structure:

Byte Offset:  0        2        4+
             |========|========|========|
             |   Packet ID     | Matrix  |
             |   (uint16_le)   |(8x15*4) |
             |========|========|========|

Matrix Encoding: 8x15 matrix of float32 values (480 bytes)

  • Row-major order encoding
  • Each float32 is 4 bytes little-endian IEEE 754

File Transfer Protocol (TFTP)

Standard TFTP Operations

Read Request (RRQ):

Opcode | Filename | 0 | Mode | 0
   2   | string   |   | "octet" |

Write Request (WRQ):

Opcode | Filename | 0 | Mode | 0
   2   | string   |   | "octet" |

Data Block:

Opcode | Block# | Data
   3   |   2    | 0-512 bytes

Acknowledgment:

Opcode | Block#
   4   |   2

Error:

Opcode | ErrorCode | ErrMsg | 0
   5   |     2     | string |

BLCU Operations

  • Firmware Upload: Backend writes firmware to vehicle
  • Configuration Download: Backend reads config from vehicle
  • Log File Download: Backend retrieves logs from vehicle

Network Configuration

Port Assignments

  • TCP_CLIENT: 50401 (backend connects to vehicle)
  • TCP_SERVER: 50500 (vehicle connects to backend)
  • UDP: 8000 (bidirectional communication)
  • TFTP: 69 (file transfers)

IP Addressing

  • Backend: 127.0.0.9 (configurable)
  • Vehicle Boards: Per-board IPs in ADJ configuration

Implementation Guidelines

Endianness Handling

All multi-byte integers use little-endian byte order:

binary.LittleEndian.Uint16(data)  // Read 16-bit value
binary.LittleEndian.Uint32(data)  // Read 32-bit value

Error Handling

  • TCP Connection Lost: Automatic reconnection with exponential backoff
  • UDP Packet Loss: Statistics tracking, no retransmission
  • Malformed Packets: Packet discarded, connection maintained
  • Invalid Packet ID: Warning logged, packet skipped

Performance Considerations

  • UDP Preferred: For high-frequency data packets (>10 Hz)
  • TCP Required: For order packets and file transfers
  • Buffer Sizes: 64KB receive buffers recommended
  • Concurrent Connections: Support for multiple vehicle boards

Packet Validation

  • Minimum packet size: 2 bytes (packet ID only)
  • Maximum packet size: 1500 bytes (Ethernet MTU limit)
  • Payload length: Validated against ADJ specifications
  • Checksum: Currently not implemented, planned for future

Debugging and Monitoring

Tools Available

  • Packet Sender: Generate test packets for development
  • Network Sniffer: Capture and analyze traffic
  • Wireshark: Deep packet inspection with custom dissectors

Common Issues

  • Byte Order: Ensure little-endian encoding
  • String Termination: Null-terminated ASCII strings
  • Alignment: No padding requirements for structures
  • Version Mismatch: ADJ specification sync between vehicle and backend

For complete implementation details, see the backend source code in pkg/transport/ and the ADJ specifications in adj/ directories.

Clone this wiki locally