No description
  • C++ 70.8%
  • HTML 22%
  • CMake 3.2%
  • Shell 2%
  • Dockerfile 2%
Find a file
2026-05-10 12:18:28 +02:00
.devcontainer Initial commit: Terrvex Core skeleton with web UI 2026-05-04 14:38:17 +02:00
app Added RS232 input for RTCM directly on box 2026-05-10 12:18:28 +02:00
deploy Added RS232 input for RTCM directly on box 2026-05-10 12:18:28 +02:00
docker Initial commit: Terrvex Core skeleton with web UI 2026-05-04 14:38:17 +02:00
hw/device-tree Initial commit: Terrvex Core skeleton with web UI 2026-05-04 14:38:17 +02:00
.gitignore Initial commit: Terrvex Core skeleton with web UI 2026-05-04 14:38:17 +02:00
CMakeLists.txt Initial commit: Terrvex Core skeleton with web UI 2026-05-04 14:38:17 +02:00
README.md Added RS232 input for RTCM directly on box 2026-05-10 12:18:28 +02:00

Terrvex Core — Torizon-oriented firmware skeleton

Compact RTK-GNSS + CAN edge daemon for the Terrvex Core box (Verdin-class i.MX8 modules running Torizon OS or Debian-compatible userspace). This repository provides:

  • A C++20 daemon (terrvex-core) with an extensible sensor layer (u-blox UBX, SocketCAN + decoder registry, GPIO via libgpiod, IIO power sense stub).
  • Multi-stage Docker build and a host-focused docker-compose file for on-device deployment.
  • A VS Code Dev Container toolchain (CMake, Boost, libgpiod, optional Docker CLI).

Architecture

  • GNSS: u-blox ZED-X20D — UART reader with UBX framing (NAV-PVT, NAV-RELPOSNED for heading/RTK flags). Replace stub CAN IDs / DIS scaling with values from your DIS CFM documentation.
  • CAN: Linux SocketCAN (can0, optional CAN-FD). Decoders implement ICandecoder and are registered in can_registry.cpp.
  • GPIO: libgpiod line requests for digital inputs (joystick buttons).
  • Power: reads the first in_voltage*_raw channel under an IIO sysfs path (configure iio_device_path).
  • Web UI (required): Embedded HTTP server (cpp-httplib) serves a mobile-friendly dashboard + configuration forms (app/web/index.html, Tailwind via CDN). REST: /api/v1/health, /api/v1/status, /api/v1/config (GET/POST). WebSocket: /api/v1/ws — client sends periodic ticks; each reply carries fresh telemetry JSON (terrvex.telemetry.v1).
  • Legacy tablet link: optional Boost.Beast WebSocket sink on websocket_port when "sink": "ws"; BLE GATT and USB CDC remain stubs.
  • USB gadget RNDIS/ECM and Avahi (terrvex.local) are documented under deploy/usb-gadget/ and deploy/avahi/ (host-side setup, not inside the app binary).

Prerequisites

  • Docker Desktop (macOS Apple Silicon is fine; images target linux/arm64 and linux/amd64 via Debian multi-arch packages).
  • On the module, Torizon OS (or Debian bookworm-compatible runtime with SocketCAN + /dev/gpiochip* + optional IIO).

Build (container)

From the repository root:

docker build -f docker/Dockerfile -t terrvex-core:local .

The runtime stage installs Boost system/thread and libgpiod; the binary is installed to /usr/local/bin/terrvex-core.

Run on target with docker compose

  1. Copy this repository (or CI artifacts) to the module.

  2. Ensure CAN is up, for example:

    sudo ip link set can0 up type can bitrate 500000
    
  3. Adjust deploy/config/config.json (UART, CAN, GPIO, web_port / web_root, optional legacy "sink": "ws").

  4. From deploy/:

    docker compose build
    docker compose up -d
    

The compose file uses network_mode: host, bind-mounts /dev and /run/udev, and includes device_cgroup_rules for common TTY/CAN/GPIO majors. For early bring-up you may temporarily set privileged: true on the service.

Environment overrides

  • TERVEX_CONFIG — JSON file path inside the container (default /etc/terrvex/config.json, bind-mounted from deploy/config).
  • TERVEX_GNSS_DEVICE — prepends --gnss-device via docker/entrypoint.sh.
  • TERVEX_WEB_ROOT — overrides static UI path (default in image: /usr/share/terrvex/web).

Web UI & USB / mDNS

  • Open http://<device-ip>:8080 with the default web_port (or http://127.0.0.1:8080 with network_mode: host on the module).
  • For Ethernet-over-USB, bring up a gadget and address (e.g. 192.168.100.1) per deploy/usb-gadget/README.md. Set web_port to 80 if you grant CAP_NET_BIND_SERVICE or run privileged.
  • For http://terrvex.local, install Avahi on the host per deploy/avahi/README.md.

Security: the bundled UI has no authentication; add auth/TLS before exposing on untrusted networks.

Local development (Dev Container)

Open the folder in VS Code and Reopen in Container. The dev image installs build dependencies and mounts the Docker socket so you can run docker build from inside the container.

Configure CMake (CMakeLists.txt at repo root) and build:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build
./build/app/terrvex-core --help

On macOS, SocketCAN and libgpiod are Linux-specific; use the container or a Linux VM for full linkage tests.

Configuration

  • CLI: see --help (app/src/config.cpp).
  • JSON: keys mirror AppConfig (deploy/config/config.json).
  • RTCM serial (optional): set rtcm_serial_enabled, rtcm_serial_device, and rtcm_serial_baud to forward RTCM from a second UART/RS232 port into the GNSS module on gnss_uart_device (TX to the receiver). Requires GNSS enabled; restart the daemon after changing serial settings.

Extending

  • Add CAN decoders: implement ICandecoder, register in register_* functions, include in can_registry.cpp.
  • Drop third-party C++ under app/third_party/ and bridge from third_party_adapter.cpp.
  • Promote BLE/USB stubs by implementing ITelemetrySink and selecting sink in JSON (ble / cdc).

Device tree

See hw/device-tree/README.md and the example fragment hw/device-tree/verdin-imx8mp-example.overlay.dts.

License

Proprietary / project-specific — add your SPDX identifier when you publish.