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.
Dantir stands on the shoulders of others' work. Full respect and thanks to:
- Colonel Panic — 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 — BLE detection research and signature work that informs how Flock devices are identified.
- 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.
Dantir uses seven detection methods across BLE and WiFi:
| Method | Radio | How it matches |
|---|---|---|
mac_prefix |
BLE | MAC OUI against ~20 Flock Safety prefixes |
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 eight 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 |
glasses |
--· (G) | Recording smart glasses (Ray-Ban Meta, Oakley, Snap) |
tracker |
- (T) | Bluetooth trackers (Tile, etc.) |
lawenf |
·-·· (L) | Law-enforcement gear (TASER/Axon, 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. OUI/manufacturer matches catch consumer hardware that shares the same chipset vendors (e.g. some Wyze, Hue, or OBD-II dongles can trip a low-confidence match). Treat
device_nameandble_mfr_idhits as higher confidence than a baremac_prefixmatch, and confirm visually before drawing conclusions.
- 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.
| 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.
| Function | GPIO | XIAO pin |
|---|---|---|
| Buzzer | 3 | — |
| NeoPixel | 4 | — |
| GPS RX | 44 | D7 |
| GPS TX | 43 | D6 |
Battery ADC (optional, -1 = off) |
1 | A0 / D0 |
Dantir is a PlatformIO project (no Arduino IDE sketch juggling required).
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 monitorTarget 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).
-
Power on. Dantir plays a boot "crow call" and starts scanning immediately — no mode selection needed.
-
Connect to the dashboard. Join the WiFi access point:
- SSID:
dantir• Password:dantir123 - Open
http://192.168.4.1in 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. EditFY_AP_SSID/FY_AP_PASSinsrc/main.cppand re-flash before you take it out. - SSID:
-
(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.
-
Walk. Watch the radar and detection cards populate. Listen for the Morse-letter beeps to ID categories by ear.
-
Export. Download the session as JSON / CSV / KML, or clear it to start fresh (the cleared session is backed up automatically).
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) |
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.
gpsandbest_gpsobjects. - 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.
Tunable #defines 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 |
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.
MIT — Copyright (c) 2026 rpriven. Based on OUI Spy Unified Blue by colonelpanichacks.