🇺🇸 English · 🇲🇽 Español
Developed by Luis Xavier García Pimentel Ascencio.
Real-time telemetry stack for SAE off-road vehicles (Minibaja, Formula, Baja). Designed to be adopted by any team with minimal configuration: the repo ships working examples and templates, and each team keeps its own version in teams/ folders that git ignores.
| Folder | What it is | Status |
|---|---|---|
localDashboard/ |
Local stack, no internet. LoRa (binary TDM protocol) → pits laptop → InfluxDB + Grafana + web dashboard in Docker | Active |
liveDashboard/ |
Live stack, internet. ESP32 over WiFi (phone hotspot) → InfluxDB Cloud → Grafana Cloud | Active |
web/ |
Web dashboard. One engine + one app per team. Runs inside the local stack and can be hosted (Docker) for the live stack | Active |
legacyDashboard/ |
Original local stack (JSON over LoRa, ESP32 + SX1276) | Legacy |
Local stack:
Heltec V4 (car) ──LoRa 915 MHz──► Heltec V4 (pits) ──USB──► lora_receiver_v2.py ──► InfluxDB (Docker)
├─► Grafana :3001
└─► Web :8088
Live stack:
ESP32 (car) ──WiFi──► phone hotspot ──Internet──► InfluxDB Cloud ──► Grafana Cloud
└──────────► Web (hosted, Docker)
Everything in the repo works out of the box with the simulators. What belongs to a specific team (branding, boards, Grafana dashboards, firmware) lives in teams/ folders, which are ignored by git (only their README.md is versioned):
| What | Versioned example / template | Your team (ignored) | Selected with |
|---|---|---|---|
| Web dashboard | web/apps/ejemplo-local/, web/apps/ejemplo-live/ |
web/apps/teams/<team>/ |
WEB_APP (local) · APP (build) |
| Local Grafana dashboards | localDashboard/grafana/provisioning/dashboards/examples/ |
…/dashboards/teams/<team>/ |
GRAFANA_DASHBOARDS |
| Live Grafana Cloud dashboards | liveDashboard/grafana/examples/Live.json |
liveDashboard/grafana/teams/<team>/ |
import in Grafana Cloud |
| Firmware (local, live, legacy) | <stack>/firmware/template/ |
<stack>/firmware/teams/<team>/ |
flash from your folder |
To start your own: copy the example into teams/<your-team>/, adapt it, and point the variable to it. Each README explains the details.
TelemetryStack/
├── README.md / README.es.md ← this file (English / Spanish)
├── LICENSE · .gitignore · .gitattributes
├── localDashboard/ ← local stack (binary TDM over LoRa), no internet
│ ├── README.md ← full local stack guide
│ ├── docker-compose.yml ← InfluxDB :8087 + Grafana :3001 + web :8088 (built from ../web)
│ ├── .env.example ← credentials + which dashboards to run (WEB_APP, GRAFANA_DASHBOARDS)
│ ├── influxdb/
│ │ ├── init/create-buckets.sh ← creates telemetry-analisis on first start
│ │ └── create-read-token.sh ← read-only token for the web proxy
│ ├── grafana/
│ │ ├── provisioning/datasources/influxdb.yml
│ │ ├── provisioning/dashboards/
│ │ │ ├── dashboards.yml ← loads the GRAFANA_DASHBOARDS folder
│ │ │ ├── examples/ ← Live Crítico, Live Análisis, Post-Análisis
│ │ │ └── teams/ ← ignored: team dashboards
│ │ └── plugins/madrams-routemap-panel/ ← SVG route-map panel
│ ├── laptop/ ← pits laptop scripts
│ │ ├── lora_receiver_v2.py ← binary Route/Status structs → InfluxDB
│ │ ├── telemetry_simulator.py ← simulates the car (InfluxDB or virtual serial)
│ │ ├── sd_upload_v2.py ← SD card CSV → telemetry-analisis
│ │ ├── lap_detector.py · frenet_ideal.py ← laps, Frenet ideal lap, live delta
│ │ ├── optimal_route_app.py ← mouse-driven ideal-route tester
│ │ ├── grafana_setup.md ← variables and Flux queries for building dashboards
│ │ └── requirements.txt
│ └── firmware/ ← Heltec WiFi LoRa 32 V4 (SX1262 + RadioLib)
│ ├── README.md
│ ├── template/ ← firmware template: transmitter/ · receiver/
│ └── teams/ ← ignored: each team's firmware
├── liveDashboard/ ← live stack (WiFi → InfluxDB Cloud)
│ ├── README.md ← full live stack guide
│ ├── firmware/
│ │ ├── README.md
│ │ ├── template/transmitter/ ← firmware template (transmitter.ino + config.h.example)
│ │ └── teams/ ← ignored: each team's firmware
│ ├── grafana/
│ │ ├── examples/Live.json ← importable Grafana Cloud dashboard
│ │ └── teams/ ← ignored: team dashboards
│ ├── dataSimulator/simulator.py ← simulates the car → InfluxDB Cloud / MQTT
│ └── .env.example
├── web/ ← web dashboard (Vite + React + uPlot)
│ ├── README.md ← engine, apps, local and hosted use, panels
│ ├── src/ ← engine (same for every app) + tests
│ ├── apps/
│ │ ├── ejemplo-local/ ← example for the local stack
│ │ ├── ejemplo-live/ ← example for the live stack (custom theme)
│ │ └── teams/ ← ignored: each team's app
│ ├── Dockerfile · Caddyfile ← one image for the pits laptop and for hosting
│ └── docs/ ← screenshots
└── legacyDashboard/ ← legacy JSON stack (InfluxDB :8086, Grafana :3000)
├── README.md · docker-compose.yml · .env.example
├── firmware/ ← ESP32 + SX1276: template/ (Arduino) and teams/ (ignored)
├── laptop/ ← lora_receiver_local.py, sd_upload.py, dataSimulator/
└── influxdb/ · grafana/
Local (pits laptop, no internet):
cd localDashboard
cp .env.example .env # fill credentials
docker compose up -d # InfluxDB + Grafana + web dashboard
pip install -r laptop/requirements.txt
python3 laptop/telemetry_simulator.py --run_id sim_001 --mode influx --full-sim # or lora_receiver_v2.py with hardware
# Grafana http://localhost:3001 · Web http://localhost:8088Live (InfluxDB Cloud + Grafana Cloud):
cd liveDashboard
cp .env.example .env # InfluxDB Cloud URL, token, org, bucket
pip install influxdb-client python-dotenv paho-mqtt requests
python3 dataSimulator/simulator.py --target influx
# Grafana Cloud: Dashboards → New → Import → grafana/examples/Live.jsonHosted web dashboard (live):
cd web
docker build --build-arg APP=apps/ejemplo-live -t telemetry-web .
docker run -p 8080:80 -e INFLUX_URL=https://<region>.cloud2.influxdata.com \
-e INFLUX_READ_TOKEN=<read-only token> -e INFLUX_ORG=<org> -e INFLUX_BUCKET=<bucket> telemetry-webRequirements: Python 3.10+, Docker Desktop (local stack and web image), Node 24+ only to develop the web dashboard.
Credentials go in .env (and config.h for firmware) — never in code or in the repo. Each stack has its own .env.example; copy it to .env and ask the telemetry lead for the values. The web dashboard never sees an InfluxDB token: its proxy injects it server-side, and for hosted sites it must be a read-only token.
| File | Language | Scope |
|---|---|---|
README.md / README.es.md |
EN / ES | Overview, structure, examples vs. team versions, quick start |
localDashboard/README.md |
ES | Local stack: setup, scripts, InfluxDB schema, Grafana and web, team folders |
localDashboard/laptop/grafana_setup.md |
ES | Grafana variables and Flux queries for the local stack |
localDashboard/firmware/README.md |
EN | Heltec V4 firmware template: protocol, filling in the sensors, config.h |
liveDashboard/README.md |
ES | Live stack: InfluxDB/Grafana Cloud, firmware, simulator, importing dashboards |
liveDashboard/firmware/README.md |
EN/ES | Live firmware: template vs team folders, config.h |
web/README.md |
ES | Web dashboard: engine, apps, local/hosted use, panels, thresholds, themes |
legacyDashboard/README.md |
ES | Legacy JSON stack |
legacyDashboard/firmware/README.md |
EN | Legacy firmware, FreeRTOS tasks, SF/BW table |
legacyDashboard/laptop/README.md |
ES | Legacy laptop scripts |