This repository hosts the Project Wedjat codebase, an end-to-end pipeline for satellite telemetry analysis. It features offline telemetry processing, per-satellite anomaly-model training, synthetic-fault benchmarking, a robust FastAPI backend, and a premium SvelteKit + Tailwind dashboard.
- Technical Details & Architecture: Deep dive into the system's design, ML models, and normalized telemetry structures.
- WEBSITE_PLAN.md: Web interface, Docker orchestration, and UX integration plan.
- .gemini/GEMINI.md: Active project context and agent instructions.
Core Pipeline & Backend:
- SatNOGS data pipeline: fetch -> decode -> normalize -> train -> benchmark.
- Python-based Kaitai Struct decoders (currently supporting UWE-4).
- Online streaming runtime for packet-by-packet autoencoder inference.
- FastAPI REST backend for telemetry streaming and model metrics.
- Containerized MQTT broker and TimescaleDB stack.
Frontend Dashboard:
- Svelte 5 frontend built with TailwindCSS and Observable Plot.
- Websocket-driven live telemetry feed with real-time anomaly highlighting.
- ML diagnostic views showing standardized deviation (Z-Score) and reconstruction errors.
- Exploratory Data Analysis (EDA) views for payload stats and orbital mechanics.
- Satellite pass prediction and operations console.
We use Pixi for the core Python environment, and Bun for the frontend.
Linux / macOS:
curl -fsSL https://pixi.sh/install.sh | bash
curl -fsSL https://bun.sh/install | bashWindows (PowerShell):
powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex"
powershell -c "irm bun.sh/install.ps1 | iex"Clone the repo and install dependencies:
git clone https://github.com/Mohamed-Badry/wedjat.git
cd wedjat
pixi install
cd frontend && bun install && cd ..To download telemetry, you need a SatNOGS API Token.
- Log in to SatNOGS Network.
- Go to Your Profile / Edit and copy your API Token.
- Create your config and paste your token:
cp .env.example .env
For the MQTT broker, TimescaleDB, FastAPI backend, and simulator:
docker compose up --buildWe use just (installed automatically by Pixi) to run all common tasks across the stack.
Recommended: Enter the Pixi environment first:
pixi shellFetch, decode, and normalize telemetry into structured, ML-ready numerical arrays.
just fetch # Download telemetry (interactive)
just fetch --norad 43880 # Download specific satellite
just process # Run decode + normalize pipeline (interactive)
just process --norad 43880 # Process specific satelliteTrain Autoencoder (VAE) models on the processed data and benchmark them.
just train --norad 43880 # Train VAE model for a specific satellite
just benchmark --norad 43880 # Run synthetic-fault benchmark
just train-benchmark 43880 100 # Train for 100 epochs, then benchmark immediatelyRun the minimal backend wedjat runtime and the beautiful SvelteKit dashboard.
just wedjat --norad 43880 --help # Run backend anomaly wedjat
just frontend-dev # Start frontend SvelteKit development server (localhost:5173)
just frontend-build # Build the frontend production bundle
just frontend-preview # Preview the production buildTo see all available commands, run just or just --list.
The project utilizes Docker Compose profiles to cleanly separate cloud resources from edge devices. Two deployment scripts are provided in the root directory:
Spins up the TimescaleDB, PyTorch Backend, and the production Bun SvelteKit frontend.
- Closed Ports (Secure Setup): Do not expose port
1883(unencrypted MQTT),9001(WebSocket MQTT),5432(PostgreSQL), or8000(FastAPI) to the public internet. They are closed or bound strictly to127.0.0.1. - Caddy reverse proxy (TLS/HTTPS): Caddy terminates TLS and routes standard traffic to the correct containers. Add this block to your
/etc/caddy/Caddyfileon the VPS to support secure real-time telemetry publishing:wedjat.space { # Secure MQTT over WebSockets (WSS) handle /mqtt { reverse_proxy localhost:9001 } # FastAPI API & WebSockets handle /api/* { reverse_proxy localhost:8000 } # Svelte frontend handle { reverse_proxy localhost:5173 } }
Spins up the local data buffer and Mosquitto broker on your antenna PC or Raspberry Pi.
- Scope: It now only boots the local broker container. This keeps the environment clean and avoids replaying simulated historical frames when setting up a fresh ground station.
- Publishing Telemetry: Your local SDR software (like
gr-satellites) publishes decoded frames to your local broker onlocalhost:1883.
To send decoded packets from your SDR antenna station, connect to the secure broker at wss://wedjat.space/mqtt on Port 443 (via the Caddy reverse proxy) and publish to the topic telemetry/live/{norad_id}.
The payload must be a JSON string structured exactly as follows:
{
"norad_id": 43880,
"timestamp": "2026-07-06T03:02:38Z",
"raw_frame": "8A8A8A8A8A8A608A8A8A8A8A8A6103F025821E130201...",
"station_id": "laptop_sdr_station_01",
"snr": 15.4
}norad_id: (Integer) The NORAD catalog identifier of the satellite (e.g.,43880for UWE-4).timestamp: (String, ISO-8601 UTC format) The exact time the packet was observed.raw_frame: (String, Hex-encoded) The raw binary frame output from the demodulator.station_id: (String, optional) Ground station identifier.snr: (Float, optional) Signal-to-noise ratio of the signal.
Project Wedjat is strictly organized to separate raw data pipelines, machine learning models, core logic, simulated environments, and user interfaces.
.
βββ data/ # Local data storage (ignored by git, populated by scripts)
β βββ raw/ # Stage 0: Raw JSONL files fetched directly from SatNOGS DB API
β β βββ 43880/ # e.g., UWE-4 raw telemetry records
β β βββ ... # Other satellite NORAD ID directories
β βββ interim/ # Stage 1: Kaitai-decoded telemetry CSVs (unaltered fields)
β βββ processed/ # Stage 2: SI-unit normalized telemetry CSVs mapped for Machine Learning
βββ frontend/ # Bun + SvelteKit Web Dashboard
β βββ src/
β β βββ lib/ # Shared internal components
β β β βββ api.ts # Strongly-typed fetch wrappers for the FastAPI backend
β β β βββ components/ # UI elements (charts, tables, layout components)
β β β βββ chart-theme.ts # Unified design tokens mapping CSS variables to SveltePlot
β β βββ routes/ # File-system based router pages
β β βββ (dashboard)/ # Authenticated/Main App layout group
β β β βββ dashboard/ # Dashboard views:
β β β βββ live/ # Real-time packet watcher feed
β β β βββ ml/ # Model telemetry root cause analysis & reports
β β β βββ eda/ # Exploratory Data Analysis (sensitivity, stats)
β β β βββ operations/# Satellite/model status summaries
β β β βββ inspector/ # Ground-truth telemetry variable explorer
β β βββ (landing)/ # Public facing landing pages
β βββ tailwind.config.ts # Tailwind design configuration (Amethyst themes, plugins)
β βββ package.json # Bun dependencies (SvelteKit, Tailwind, Lucide, Observable Plot)
βββ src/ # Python Backend & Shared Library Code
β βββ api/ # FastAPI Dashboard Endpoints
β β βββ main.py # Entrypoint: handles REST routes, artifacts, and summary stats
β β βββ Dockerfile # FastAPI service container definition
β βββ gr_sat/ # Core domain logic ("The Shared Core")
β β βββ decoders/ # Kaitai Struct adapters (e.g. uwe4.py, registry pattern)
β β βββ telemetry.py # Central abstractions for telemetry frames
β β βββ models/ # Shared PyTorch/Scikit models (VAE, Autoencoders, Scalers)
β β βββ utils/ # Data parsing and time manipulation helpers
β βββ simulator/ # Edge Simulator Environment
β βββ edge_node.py # Hardened Edge Simulator (TLS MQTT + Local CSV playback when disconnected)
β βββ Dockerfile # Simulator service container definition
βββ scripts/ # Executable Pipeline & ML Scripts
β βββ fetch_training_data.py # Pipeline Stage 0: Fetches SatNOGS historical API data
β βββ process_data.py # Pipeline Stage 1+2: Decodes & normalizes raw telemetry into ML arrays
β βββ train_model.py # Pipeline Stage 3: Trains VAE models on processed satellite data
β βββ generate_faults.py # Pipeline Stage 4: Injects synthetic faults and benchmarks models
β βββ wedjat_runtime.py # Minimal deterministic online runtime for stream processing
βββ notebooks/ # Interactive Jupytext Notebooks for Prototyping
β βββ uwe4_pipeline_eda.py # Multi-scale EDA, hyperparameter sweeps, statistical profiling
β βββ telemetry_inspector.py # Visual ground-truth debugger
βββ docs/ # Formal Documentation & Architecture
β βββ spec/ # Allium formally verified domain system contracts
β βββ architecture_diagrams/ # Architecture assets & Typst layouts
β βββ slides.typ # Typst presentation slides
βββ models/ # Persisted local ML artifacts (Scalers, PyTorch Models, Metadata)
βββ mosquitto/ # MQTT Broker configuration and TLS certificates
βββ tests/ # Python `unittest` regression coverage
βββ .gemini/ # Agentic context mandates & conversation brain (`GEMINI.md`)
βββ .agents/ # Custom Allium and domain skills for Antigravity
βββ docker-compose.yml # Docker development stack (MQTT, DB, API, Frontend, Simulator)
βββ justfile # Centralized task runner (Makefile alternative)
βββ pixi.toml # Conda-compatible environment & dependency manager
βββ pyproject.toml # Ruff linting & Python metadata
βββ README.md # You are here
The decoder system uses satnogs-decoders (Kaitai Structs) for binary parsing and a registry pattern for satellite-specific logic. To add support for a new satellite:
- Create
src/gr_sat/decoders/<satellite>.py - Subclass
BaseDecoderand implementdecode()+adapt() - Register with
@DecoderRegistry.register(NORAD_ID) - Import in
src/gr_sat/decoders/__init__.py
| Satellite | NORAD ID | Decoder | Status |
|---|---|---|---|
| UWE-4 | 43880 | decoders/uwe4.py |
Primary target, ~7 months of data |
| CUTE | 49263 | decoders/cute.py |
9600 bps GMSK, Active NASA Astrophysics payload |


















