The Problem

Satellite enthusiasts and amateur radio operators need a single web interface that can:

  • track celestial bodies and satellites in real time,
  • control ground‑station hardware (rotators, SDRs), and
  • receive, decode, and store radio signals.

Manually juggling separate tools for each task is error‑prone and slows mission planning.

What This Does

The repo bundles a browser‑based ground station.

  • Backend – backend/app.py starts a Flask API that serves telemetry, hardware control and database CRUD.
  • Frontend – frontend/src/App.jsx renders the React UI, consuming the API and providing map visualisations and SDR waterfall views.
  • Data Layer – backend/db/models.py defines SQLAlchemy models, while backend/alembic holds migration scripts (backend/alembic/versions/...).
  • SDR Decoding – backend/demodulators/* contains decoders for FSK, AM, FSK, SSTV, etc., and workers like backend/audio/deepgramtranscriptionworker.py.

How It Is Wired

INTERNAL CALL GRAPH
backend/app.py → create_app()
→ handlers/base.py → register_routes()
→ controllers/* → CRUD operations
→ crud/* → db/models.py
  • backend/app.py creates the Flask app and registers blueprints from backend/handlers.
  • Each handler imports controller functions, e.g., backend/controllers/rotator.py calls crud/rotators.py.
  • CRUD functions perform SQLAlchemy queries against models defined in backend/db/models.py.
  • Decoding workers are launched as separate processes; they read raw IQ samples from backend/audio/audiobroadcaster.py and write results to the database via crud/transmitters.py.
  • The React frontend starts at frontend/index.html, mounts App.jsx, and talks to the API using frontend/src/api/*.js.

The wiring is linear: API → handlers → controllers → crud → models. No deep recursion or cyclic dependencies were detected in the call graph.

How To Use It

Setup

# clone the original project
git clone https://github.com/moses-y/ground-station
cd ground-station

# build the Docker image (the Dockerfile is at the repo root)
docker build -t ground-station:dev .

Configuration

  • Backend environment: backend/.env (not in the repo; create one).
  • Frontend env: frontend/.env.development or frontend/.env.production – contains API base URL and feature flags.
  • Database: backend/pyproject.toml lists psycopg2-binary; set DATABASE_URL in the backend env.

Running

# start the container (exposes http://localhost:5000 for API, http://localhost:5173 for UI)
docker compose up --build

The Flask app runs from backend/app.py; Vite serves the React frontend from frontend/.

Real‑World Use

A hobbyist at an amateur satellite ground station runs the container on a Raspberry Pi.

# schedule a pass
curl -X POST http://localhost:5000/api/observations/ \
  -H "Content-Type: application/json" \
  -d '{"satellite_id": 25544, "time": "2026-10-12T00:00:00Z"}'

The UI shows the pass on the map, streams the SDR waterfall, and stores decoded packets in backend/db/models.py tables for later review.

Code Health & Issues

  • Low – secret‑shaped paths present: frontend/.env.development, frontend/.env.production.
  • No other static‑analysis findings were reported.
  • CI workflow exists (.github/workflows/tests.yml).
  • The project is GPL‑v3 licensed (LICENSE).

The Bottom Line

Ground‑Station delivers a full‑stack solution for satellite tracking and SDR decoding. Its clear separation of concerns (Flask API, React UI, SQLAlchemy models, decoders) makes extension straightforward. The main caveat is the committed environment files; review or remove them before production use. Suitable for operators who need a consolidated, web‑based ground‑station stack.