map.js read capture.captured_at, but the backend stores the field as `timestamp`, so every marker popup rendered "Invalid Date". Fall back to timestamp and guard against unparseable values. Regenerated README popup screenshot to reflect the fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GigLez — Wigle for Sub-GHz IoT
A crowdsourced map of Sub-GHz RF devices. Upload a Flipper Zero .sub capture with GPS,
GigLez parses the signal, identifies the device by protocol signature, and pins it on an
interactive map — building an open dataset of the 300–928 MHz IoT world (garage doors,
doorbells, weather sensors, TPMS, remotes, and more).
Click any marker to see the automatically-identified device and match confidence:
Why
Wigle.net mapped the WiFi/Bluetooth/cellular world. Almost nobody has done the same for
Sub-GHz RF — the unlicensed ISM bands where garage remotes, alarm sensors, tire-pressure
monitors and cheap IoT gadgets chatter. GigLez collects those captures from any device
(Flipper Zero, LilyGo, RTL-SDR, HackRF — anything that emits .sub), identifies them, and
turns the aggregate into a labeled dataset for RF SIGINT research and ML training.
How it works
flowchart LR
A[".sub capture<br/>+ GPS"] --> B["Parser<br/>freq · preset · timing"]
B --> C["Category Router<br/>band + timing-ratio + pulse-count"]
C --> D["Protocol DB match<br/>+ confidence calibration"]
D --> E["GPS resolve<br/>filename / manifest"]
E --> F["Store"]
F --> G["Leaflet map"]
F --> H["Dataset export<br/>jsonl · csv · geojson"]
The identifier first routes a capture to a device category using frequency band, pulse timing ratios and pulse counts, then scores it only against protocols in that category and calibrates the confidence (spread + category-mismatch penalties). This routing step is what lifts identification accuracy over naive whole-database matching.
Features
- Device-agnostic upload — drag-and-drop
.subfiles; GPS from the filename or a manifest - Automatic identification — category routing → protocol-signature matching → confidence score
- Interactive map — Leaflet with marker clustering, frequency-band color coding, and a heatmap view
- Search & filter — by frequency, protocol, and geographic radius/bounding box
- Dataset export — stream the labeled corpus as JSONL, CSV, or GeoJSON for ML training
- Stats dashboard — total captures, unique devices, geographic coverage
Quick start
# install deps into a venv
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# run the app (simple mode — JSON-backed, no database required)
./start_web.sh
# or explicitly:
python3 -m uvicorn src.api.main_simple:app --host 0.0.0.0 --port 8000 --reload
Then open http://localhost:8000 for the map UI (/docs for the OpenAPI reference).
Modes.
main_simple.pyis the live app and needs no database — captures persist to a local JSON store, which is the fastest way to try GigLez. A full SQLAlchemy ORM path (PostgreSQL + PostGIS in production, SQLite in dev viaDATABASE_URL=sqlite:///./giglez.db) also exists for scaled deployments.
API
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/api/v1/captures/upload |
Upload .sub files + GPS manifest |
GET |
/api/v1/query/captures |
List stored captures |
GET |
/api/v1/captures/{id} |
Capture detail |
GET |
/api/v1/stats/summary |
Platform statistics |
GET |
/api/v1/export?format=jsonl|csv|geojson |
Export the labeled dataset |
GET |
/health |
Health check |
Supported formats
Flipper Zero .sub — both decoded key files (Protocol / Bit / Key) and RAW pulse
captures (RAW_Data timing arrays). .fff and PCAP ingest are on the roadmap.
Accuracy status
Identification is at Phase 0 — category routing plus a calibrated confidence model.
The current gate benchmark (scripts/benchmark_phase0.py) reports ~67% top-3 category
accuracy, but note this runs on synthetic .sub files generated from the protocol database
itself, so treat it as an upper bound, not a real-world number. Real-world validation
against field Flipper captures, and a hybrid heuristic + 1D-CNN ML ensemble, are the next
milestones.
Tech stack
Python · FastAPI · Leaflet.js · SQLAlchemy (PostgreSQL/PostGIS · SQLite) · Flipper .sub parsing
Roadmap
.subparser + GPS validation- Category-routed device identification (Phase 0)
- Web UI (map / upload / search / stats) + dataset export
- Real-world accuracy validation on field captures
- ML ensemble (heuristic + 1D CNN on raw pulses + statistical features)
- Community verification, accounts, leaderboard
- Docker deployment; 2.4/5 GHz (PCAP + OUI) as a later phase

