- Morse alerts: axon -> A (threat tone), vr_headset -> E (single dit; benign, not treated as a surveillance threat) - README: 10 categories (add axon, vr_headset), correct the now-stale false-positive caveat (Silicon Labs + Raspberry Pi OUIs were removed from the Flock list; real Flock-on-RPi relies on name/mfr-id, not bare OUI) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
247 lines
10 KiB
Markdown
247 lines
10 KiB
Markdown
# Dantir — Surveillance Counter-Watcher
|
|
|
|
> *Sindarin:* **dan** (against / back) + **tir** (to watch) = *"counter-watcher."*
|
|
|
|
Dantir is a pocket-sized **BLE + WiFi surveillance-detection device** for the
|
|
Seeed XIAO ESP32-S3. It passively listens for the radio signatures of
|
|
surveillance hardware around you — Flock Safety ALPR cameras, Ring/Amazon
|
|
cameras, recording smart glasses, Bluetooth trackers, gunshot-detector nodes,
|
|
and law-enforcement gear — then alerts you with audio, light, and a live web
|
|
dashboard with a proximity radar.
|
|
|
|
It only **detects and documents**. It does not jam, spoof, or interfere with
|
|
anything. Awareness is the point: you can't push back against what you can't
|
|
see.
|
|
|
|
---
|
|
|
|
## Credits & Lineage
|
|
|
|
Dantir stands on the shoulders of others' work. Full respect and thanks to:
|
|
|
|
- **[Colonel Panic](https://colonelpanic.tech/) — [OUI Spy Unified Blue](https://github.com/colonelpanichacks/oui-spy-unified-blue)**
|
|
Dantir is a fork of OUI Spy Unified Blue's *Flock-You* mode. The detection
|
|
engine, session persistence, GPS handling, export pipeline, and dashboard
|
|
foundations all originate there. If you want a polished, pre-built detector,
|
|
buy one from Colonel Panic — support the upstream project.
|
|
- **[wgreenberg / flock-you](https://github.com/wgreenberg/flock-you)** — BLE
|
|
detection research and signature work that informs how Flock devices are
|
|
identified.
|
|
- **[deflock.me](https://deflock.me/)** — community-sourced surveillance device
|
|
signatures.
|
|
|
|
Dantir's changes over upstream: standalone single-mode firmware (no BOOT-button
|
|
mode dance), added WiFi promiscuous detection (Ring/Blink), expanded BLE
|
|
manufacturer-ID and category coverage, Morse-code category alerts, a proximity
|
|
radar dashboard, and peak-RSSI GPS tracking.
|
|
|
|
---
|
|
|
|
## What it detects
|
|
|
|
Dantir uses **seven detection methods** across BLE and WiFi:
|
|
|
|
| Method | Radio | How it matches |
|
|
|--------|-------|----------------|
|
|
| `mac_prefix` | BLE | MAC OUI against the Flock Safety prefix set (lowest confidence — see note) |
|
|
| `device_name` | BLE | Advertised name patterns (Flock, Penguin, Pigvision, Ring, Ray-Ban…) |
|
|
| `ble_mfr_id` | BLE | Bluetooth manufacturer company IDs |
|
|
| `raven_uuid` | BLE | Raven gunshot-detector service UUIDs (+ firmware-version estimate) |
|
|
| `wifi_probe` | WiFi | Probe-request source MAC OUI (promiscuous mode) |
|
|
| `wifi_beacon` | WiFi | Beacon-frame source MAC OUI (promiscuous mode) |
|
|
|
|
Detections are grouped into **ten categories**, each with its own Morse-code
|
|
audio signature on the buzzer:
|
|
|
|
| Category | Morse | What it covers |
|
|
|----------|:-----:|----------------|
|
|
| `flock` | ··-· (F) | Flock Safety / ALPR cameras, Penguin, Pigvision |
|
|
| `axon` | ·- (A) | Axon ALPR cameras (the vendor replacing Flock in some cities) |
|
|
| `glasses` | --· (G) | Camera-equipped smart glasses (Ray-Ban Meta, Oakley, Snap) |
|
|
| `vr_headset` | · (E) | VR headsets (Quest/Oculus) — benign; logged with a quiet blip, not a threat alert |
|
|
| `tracker` | - (T) | Bluetooth trackers (Tile, etc.) |
|
|
| `lawenf` | ·-·· (L) | Law-enforcement gear (TASER/Axon body-cams, Motorola Solutions) |
|
|
| `ring` | ·-· (R) | Ring / Blink / Amazon cameras |
|
|
| `camera` | ··· (S) | Other surveillance cameras (Hikvision, Arlo, Wyze) |
|
|
| `raven` | ···- (V) | Raven gunshot-detector nodes |
|
|
| `wifi` | ·-- (W) | Generic WiFi-side detections |
|
|
|
|
> **Detection is signature-based, not proof.** Many OUIs are shared across a
|
|
> chipset vendor's entire catalog, so a bare `mac_prefix` match is the
|
|
> lowest-confidence signal. Treat `device_name`, `ble_mfr_id`, and `raven_uuid`
|
|
> hits as higher confidence, and confirm visually before drawing conclusions.
|
|
> Known shared-OUI false-positive sources — e.g. a Silicon Labs prefix that also
|
|
> covers Wyze locks and OBD-II dongles, and the Raspberry Pi prefix — have been
|
|
> pulled from the Flock list; real Flock-on-RPi now relies on name (Penguin /
|
|
> Pigvision) and manufacturer ID, not a bare OUI.
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
- **Dual-radio scanning** — BLE active scan + WiFi promiscuous capture running
|
|
alongside the dashboard access point.
|
|
- **Morse-code alerts** — each category beeps its letter, so you can ID a hit
|
|
by ear without looking.
|
|
- **Foxhunter / proximity mode** — once a device is in range, a heartbeat beep
|
|
every 10 s helps you locate it; clears after 30 s with no new sightings.
|
|
- **NeoPixel feedback** — purple breathing when idle, red/pink flash on
|
|
detection, dim heartbeat glow while a device is nearby.
|
|
- **Live web dashboard** — proximity radar, live detection cards, stats, and
|
|
three themes (Purple, Tactical, Ithildin).
|
|
- **GPS tagging** — hardware GNSS (Seeed L76K) with phone-browser geolocation
|
|
fallback; tracks both first-seen and **peak-RSSI (closest-approach)** position.
|
|
- **Exports** — download a session as JSON, CSV, or KML (Google Earth).
|
|
- **Session persistence** — detections survive reboots; the prior session is
|
|
auto-backed up to onboard flash.
|
|
- **Optional battery monitoring** — LiPo percentage via a voltage divider, or
|
|
uptime display if the ADC is disabled.
|
|
|
|
---
|
|
|
|
## Hardware
|
|
|
|
### Bill of materials (per unit)
|
|
|
|
| Part | Notes | Approx. |
|
|
|------|-------|---------|
|
|
| Seeed XIAO ESP32-S3 (N8R8) | Main board; needs PSRAM variant | ~$9 |
|
|
| Passive buzzer | Audio + Morse alerts | ~$1 |
|
|
| WS2812 / NeoPixel | Status LED | ~$1 |
|
|
| Seeed L76K GNSS module | *Optional* — GPS tagging | ~$10 |
|
|
| U.FL→SMA pigtail + 2.4 GHz antenna | *Optional* — extends range | ~$6 |
|
|
|
|
> For external antenna use, the XIAO's RF switch 0-ohm resistor must be moved to
|
|
> the U.FL pad. The onboard PCB antenna works fine for getting started.
|
|
|
|
### Pin map
|
|
|
|
| Function | GPIO | XIAO pin |
|
|
|----------|:----:|:--------:|
|
|
| Buzzer | 3 | — |
|
|
| NeoPixel | 4 | — |
|
|
| GPS RX | 44 | D7 |
|
|
| GPS TX | 43 | D6 |
|
|
| Battery ADC *(optional, `-1` = off)* | 1 | A0 / D0 |
|
|
|
|
---
|
|
|
|
## Build & flash
|
|
|
|
Dantir is a [PlatformIO](https://platformio.org/) project (no Arduino IDE
|
|
sketch juggling required).
|
|
|
|
```bash
|
|
git clone https://github.com/rpriven/dantir.git
|
|
cd dantir
|
|
|
|
# Build
|
|
pio run
|
|
|
|
# Flash + open serial monitor (auto-detects the XIAO on USB)
|
|
pio run --target upload
|
|
pio device monitor
|
|
```
|
|
|
|
Target environment: `seeed_xiao_esp32s3` (defined in `platformio.ini`).
|
|
Libraries are pulled automatically: NimBLE-Arduino, ESP Async WebServer,
|
|
Adafruit NeoPixel, ArduinoJson, and TinyGPSPlus.
|
|
|
|
If `pio` isn't installed: `pip install platformio` (or use the PlatformIO IDE
|
|
extension for VS Code).
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
1. **Power on.** Dantir plays a boot "crow call" and starts scanning
|
|
immediately — no mode selection needed.
|
|
2. **Connect to the dashboard.** Join the WiFi access point:
|
|
- **SSID:** `dantir` • **Password:** `dantir123`
|
|
- Open **`http://192.168.4.1`** in a browser.
|
|
|
|
> ⚠️ **Change the defaults before any real use.** The stock AP credentials
|
|
> (`dantir` / `dantir123`) are published here and in the source — anyone
|
|
> within WiFi range of a device on stock firmware can open your live
|
|
> detection feed and GPS position. Edit `FY_AP_SSID` / `FY_AP_PASS` in
|
|
> `src/main.cpp` and re-flash before you take it out.
|
|
3. **(Optional) share phone GPS.** The dashboard can push your phone's
|
|
geolocation to the device as a fallback when no hardware GNSS fix is present.
|
|
Hardware GPS always takes priority when available.
|
|
4. **Walk.** Watch the radar and detection cards populate. Listen for the
|
|
Morse-letter beeps to ID categories by ear.
|
|
5. **Export.** Download the session as JSON / CSV / KML, or clear it to start
|
|
fresh (the cleared session is backed up automatically).
|
|
|
|
### Web API
|
|
|
|
The onboard server (port 80) exposes a small JSON API used by the dashboard:
|
|
|
|
| Endpoint | Purpose |
|
|
|----------|---------|
|
|
| `GET /` | Dashboard UI |
|
|
| `GET /api/detections` | Live detection list |
|
|
| `GET /api/stats` | Counts, GPS status, battery/uptime |
|
|
| `GET /api/gps?lat=&lon=&acc=` | Push phone GPS to the device |
|
|
| `GET /api/patterns` | Full signature database (MACs, names, MFR IDs, UUIDs) |
|
|
| `GET /api/export/{json,csv,kml}` | Download current session |
|
|
| `GET /api/history` · `/api/history/{json,kml}` | Prior session |
|
|
| `GET /api/clear` | Clear detections (backs up first) |
|
|
|
|
---
|
|
|
|
## Data & exports
|
|
|
|
Each detection records MAC, name, RSSI, detection method, category, first/last
|
|
seen, re-sighting count, Raven flag + firmware estimate, and **two** GPS fixes:
|
|
first-seen and peak-RSSI (closest approach). Exports:
|
|
|
|
- **JSON** — full structured record incl. `gps` and `best_gps` objects.
|
|
- **CSV** — flat table for spreadsheets/analysis.
|
|
- **KML** — placemarks for Google Earth; uses the peak-RSSI position when
|
|
available for the most accurate location.
|
|
|
|
Sessions auto-save to onboard flash (SPIFFS) every ~15 s and are restored on
|
|
boot, so a power cycle won't lose your data.
|
|
|
|
---
|
|
|
|
## Key configuration
|
|
|
|
Tunable `#define`s at the top of `src/main.cpp`:
|
|
|
|
| Setting | Default | Meaning |
|
|
|---------|:-------:|---------|
|
|
| `BLE_SCAN_DURATION` / `BLE_SCAN_INTERVAL` | 2 s / 3000 ms | BLE scan timing |
|
|
| `MAX_DETECTIONS` | 200 | Stored-detection capacity |
|
|
| `BATTERY_ADC_PIN` | `-1` | Set to a GPIO to enable battery monitoring |
|
|
| `BATTERY_FULL_V` / `BATTERY_EMPTY_V` | 4.2 V / 3.0 V | LiPo range |
|
|
| `FY_AP_SSID` / `FY_AP_PASS` | `dantir` / `dantir123` | Dashboard AP credentials |
|
|
| `FY_SAVE_INTERVAL` | 15000 ms | Session auto-save interval |
|
|
|
|
---
|
|
|
|
## Responsible use
|
|
|
|
Dantir is a **defensive, educational, passive** tool. It receives radio signals
|
|
that devices already broadcast publicly — the same advertisements your phone
|
|
sees — and matches them against known signatures. It transmits nothing at the
|
|
targets and interferes with nothing.
|
|
|
|
You are responsible for using it lawfully in your jurisdiction. Detect, learn,
|
|
document — don't harass, stalk, or disrupt. The goal is to make an invisible
|
|
surveillance landscape visible, not to interfere with it.
|
|
|
|
**A note on the tracker category.** Detecting Bluetooth trackers (Tile,
|
|
AirTag-class devices) is a defensive, anti-stalking use — it helps someone find
|
|
a tracker another person has planted on their car or belongings. Dantir
|
|
identifies *device classes* by their public radio signatures; it is not built
|
|
to locate or follow a specific person, and we ask that you don't try to.
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE) — Copyright (c) 2026 rpriven.
|
|
Based on **OUI Spy Unified Blue** by
|
|
[colonelpanichacks](https://github.com/colonelpanichacks/oui-spy-unified-blue).
|