Constellation OverwatchConstellation Overwatch
Integrations

Aero Arc Relay

Production-grade telemetry ingestion pipeline for MAVLink-enabled drones and autonomous systems

Production-grade telemetry ingestion pipeline for MAVLink-enabled drones and autonomous systems with high-performance NATS JetStream plumbing.

About

Aero Arc Relay is a high-confidence, async-buffered, fault-tolerant telemetry relay written in Go, designed for:

  • Drone fleets & robotics platforms
  • Research labs & autonomy teams
  • Cloud-native infrastructure
  • Real-time telemetry dashboards
  • Edge-to-cloud streaming pipelines

Relay handles MAVLink concurrency and message parsing, applies a unified envelope format, and delivers data to NATS JetStream, S3, GCS, or local storage with structured constellation logging, metrics, and health probes for orchestration.

Highlights

  • MAVLink ingest via gomavlib (UDP/TCP/Serial) with support for multiple dialects
  • NATS JetStream streaming with entity-specific subjects (constellation.telemetry.{entity_id})
  • Device State Tracking via NATS Key-Value stores (latest values for GPS, battery, attitude, etc.)
  • Data sinks with async queues and backpressure controls:
    • NATS JetStream - Modern streaming platform with persistence and replay
    • AWS S3 - Cloud object storage
    • Google Cloud Storage - GCS buckets
    • Local file storage with rotation
  • Token authentication - JWT and credentials file support for NATS
  • Constellation logging - Structured logging with Zap integration
  • Prometheus metrics at /metrics endpoint
  • Health/ready probes at /healthz and /readyz for orchestration
  • Graceful shutdown with context cancellation for clean container restarts
  • Environment variable support for secure credential management
  • Pure Go - No CGO dependencies, ARM64 compatible

Prerequisites

  • Go 1.24.0 or later
  • Task (Taskfile runner)
  • NATS server with JetStream enabled (for streaming functionality)
  • Docker and Docker Compose (for containerized deployment)

Quick Start

Installation

# Clone the repository
git clone https://github.com/Constellation-Overwatch/aero-arc-relay2constellation.git
cd aero-arc-relay2constellation

# Install dependencies
task deps

# Configure the application
cp configs/config.yaml.example configs/config.yaml
# Edit configs/config.yaml with your settings

# Start NATS server with JetStream
docker run -p 4222:4222 nats:latest -js

# Run the application
LOG_LEVEL=INFO task run

Docker Deployment

# Build the Docker image
task docker-build

# Start services with Docker Compose
task docker-run

# View logs
task logs

# Access metrics
curl http://localhost:2112/metrics

# Stop services
task docker-stop

Testing with SITL

We intentionally do not containerize SITL (Software In The Loop). SITL is a GUI-heavy simulator that varies by distro, rendering stack, and MAVLink tooling. Aero Arc Relay expects you to bring your own SITL or real drone and point it at the relay.

Example with ArduPilot SITL:

sim_vehicle.py --out=udp:<relay-ip>:14550

Configuration

Edit configs/config.yaml to configure your MAVLink endpoints and data sinks.

Configure connections to your MAVLink-enabled devices:

mavlink:
  dialect: "common"  # common, ardupilot, px4, minimal, standard, etc.
  endpoints:
    - name: "drone-1"
      protocol: "udp"      # udp, tcp, or serial
      drone_id: "drone-alpha"  # Optional: unique identifier for the drone
      mode: "1:1"           # 1:1 or multi
      port: 14550           # Required for UDP/TCP

Endpoint Modes:

ModeDescription
1:1One-to-one connection mode
multiMulti-connection mode for handling multiple clients

Protocols:

ProtocolDescription
udpUDP server/client mode
tcpTCP server/client mode
serialSerial port connection
sinks:
  nats:
    url: "nats://localhost:4222"
    subject: "constellation.telemetry.{entity_id}"  # Entity-specific routing
    token: "${NATS_TOKEN}"                          # JWT token for authentication
    queue_size: 1000
    backpressure_policy: "drop"                     # drop or block
    stream:
      name: "MAVLINK_TELEMETRY"
      subjects:
        - "constellation.telemetry.>"               # Captures all entity traffic
      storage: "file"                               # "memory" or "file"
      max_age: "24h"                                # Message retention
      max_msgs: 1000000                             # Max messages to retain
      compression: true                             # Enable S2 compression

Subject Patterns:

  • 1:1 mode: constellation.telemetry.{entity_id}constellation.telemetry.drone-alpha
  • Multi mode: constellation.telemetry.{org_id}constellation.telemetry.fleet-001

NATS JetStream KV (Device State)

Configure a Key-Value bucket to track the latest aggregated state of each device:

sinks:
  nats:
    kv:
      bucket: "mavlink_state"
      key_pattern: "{drone_id}"        # Key template
      description: "Current state of drone fleet"
      ttl: "24h"                       # Time-to-live for stale keys
      storage: "file"                  # "memory" or "file"
      max_bytes: 104857600             # Max bucket size (100MB)
      replicas: 1

Cloud Storage

sinks:
  s3:
    bucket: "your-telemetry-bucket"
    region: "us-west-2"
    access_key: "${AWS_ACCESS_KEY_ID}"
    secret_key: "${AWS_SECRET_ACCESS_KEY}"
    prefix: "telemetry"
    flush_interval: "1m"
    queue_size: 1000
    backpressure_policy: "drop"

Environment Variables

The configuration file supports environment variable expansion using ${VAR_NAME} syntax:

export NATS_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
export LOG_LEVEL="INFO"  # DEBUG, INFO, WARN, ERROR

NATS JetStream Streaming

Aero Arc Relay provides first-class support for NATS JetStream, offering persistent streaming with replay capabilities for MAVLink telemetry.

Key Benefits

  • Entity Isolation - Each drone/vehicle gets its own subject namespace
  • Replay Capability - Historical telemetry available for analysis and debugging
  • High Throughput - Optimized for real-time telemetry ingestion
  • Persistence - Configurable storage (memory/file) with retention policies
  • Authentication - JWT token and credentials file support
  • Compression - S2 compression for bandwidth optimization

Subject Architecture

The relay uses a hierarchical subject structure for optimal routing and filtering:

constellation.telemetry.{entity_id}

Examples:

  • Drone Alpha: constellation.telemetry.drone-alpha
  • Vehicle Beta: constellation.telemetry.vehicle-beta
  • Fleet Operations: constellation.telemetry.fleet-001

Consuming Messages

Subscribe to entity-specific or wildcard subjects:

# Subscribe to specific entity
nats sub "constellation.telemetry.drone-alpha"

# Subscribe to all telemetry
nats sub "constellation.telemetry.>"

# Subscribe to all drones
nats sub "constellation.telemetry.drone-*"

Telemetry Data Format

The relay uses a unified TelemetryEnvelope format for all messages:

{
  "drone_id": "drone-alpha",
  "source": "drone-1",
  "timestamp_relay": "2024-01-15T10:30:00Z",
  "timestamp_device": 1705315800.123,
  "msg_id": 0,
  "msg_name": "Heartbeat",
  "system_id": 1,
  "component_id": 1,
  "sequence": 42,
  "fields": {
    "type": "MAV_TYPE_QUADROTOR",
    "autopilot": "MAV_AUTOPILOT_ARDUPILOTMEGA",
    "base_mode": 89,
    "custom_mode": 4,
    "system_status": "MAV_STATE_ACTIVE"
  },
  "raw": "base64-encoded-raw-bytes"
}

Monitoring

Metrics Endpoint

Prometheus metrics are exposed at http://localhost:2112/metrics.

Health Endpoints

EndpointDescription
/healthzLiveness probe (always 200 if process is running)
/readyzReadiness probe (200 once sinks are initialized)

For full documentation and source code, see the GitHub repository.

On this page