diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0368ba --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# 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). + +![GigLez device map](docs/img/hero-map.png) + +Click any marker to see the automatically-identified device and match confidence: + +![Device identification popup](docs/img/device-popup.png) + +--- + +## 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 + +```mermaid +flowchart LR + A[".sub capture
+ GPS"] --> B["Parser
freq · preset · timing"] + B --> C["Category Router
band + timing-ratio + pulse-count"] + C --> D["Protocol DB match
+ confidence calibration"] + D --> E["GPS resolve
filename / manifest"] + E --> F["Store"] + F --> G["Leaflet map"] + F --> H["Dataset export
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 `.sub` files; 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 + +```bash +# 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.py` is 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 via `DATABASE_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 + +- [x] `.sub` parser + GPS validation +- [x] Category-routed device identification (Phase 0) +- [x] 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 diff --git a/docs/img/device-popup.png b/docs/img/device-popup.png new file mode 100644 index 0000000..5161657 Binary files /dev/null and b/docs/img/device-popup.png differ diff --git a/docs/img/hero-map.png b/docs/img/hero-map.png new file mode 100644 index 0000000..26ec69c Binary files /dev/null and b/docs/img/hero-map.png differ