Passive RF detection of Flock Safety ALPR cameras from WiGLE wardriving data
Project description
flockdar
Passive RF detection of Flock Safety ALPR (automatic license plate reader) cameras from WiGLE wardriving data.
Works with both the WiGLE Android app SQLite backup and WiGLE CSV exports (.csv.gz). All detection runs fully offline. Optional enrichment queries cross-reference hits against DeFlock/OSM, ALPRWatch, and the WiGLE API.
What it detects
| Device | RF signature | Confidence |
|---|---|---|
| Flock camera WiFi | SSID Flock-XXXXXX where XXXXXX matches last 6 of MAC |
High |
| Flock camera backhaul | WiFi SSID flocknet on eero hardware (80:da:13) |
High |
| Flock Safety hardware | MAC prefix b4:1e:52 (direct IEEE registration) |
High |
| Raven firmware (1.2+) | Custom BLE services 0x3100–0x3500 |
High |
| Penguin surveillance | BLE name Penguin-XXXXXXXXXX (10-digit numeric) |
High |
| Penguin surveillance | BLE manufacturer ID 2504 | Medium |
| Any Flock camera | OUI + WPA2-no-WPS + 2.4 GHz channel 1/6/11 | Medium |
| FS Ext Battery | BLE name FS Ext Battery |
Medium |
| Raven firmware (1.1.7) | BLE services 0x1809 / 0x1819 |
Low–Medium |
| Flock-family hardware | Chip-vendor OUI match (38 prefixes) | Low |
| Other surveillance | Axis, FLIR, Hanwha, Avigilon, etc. OUIs | Informational |
Quick start
Requires uv.
uv sync
uv run tui.py wigle_backup.sqlite
uv run tui.py WigleWifi_export.csv.gz
# or via installed script:
flockdar wigle_backup.sqlite
TUI keybindings
| Key | Action |
|---|---|
↑ / ↓ |
Navigate device list |
m |
Open selected location in Google Maps |
v |
Open in Google Street View |
c |
Copy MAC address(es) to clipboard |
n |
Enrich visible hits (OSM/DeFlock, ALPRWatch, WiGLE) |
w |
Configure WiGLE API credentials |
e |
Export visible hits to CSV |
k |
Export visible hits to KML |
g |
Export visible hits to GeoJSON |
o |
Open iD editor + copy OSM tags for selected camera |
r |
Reload / re-scan file |
q |
Quit |
The left sidebar has Confidence and Type filters and a Group nearby checkbox that collapses devices within 75 m of each other into a single cluster row.
Enrichment
Press n to cross-reference all visible hits against external databases. Results appear live in the Enriched table column and the detail panel.
| Source | Signal | Auth |
|---|---|---|
| DeFlock / OpenStreetMap | OSM_ALPR_NEARBY — confirmed ALPR node within 150 m |
None |
| ALPRWatch | ALPRWATCH_NEARBY — daily KMZ, cached 24 h |
None |
| WiGLE API | WIGLE_SEEN — first/last seen dates, sighting count |
API key |
WiGLE credentials — press w in the TUI, or set environment variables:
export WIGLE_API_NAME=your_api_name
export WIGLE_API_TOKEN=your_api_token
uv run tui.py wigle_backup.sqlite
Credentials are stored in ~/.config/flock-wigle/config.json (Unix: chmod 600).
Getting your WiGLE data
SQLite DB (preferred) — richer data, includes BLE service UUIDs and manufacturer IDs:
Open the WiGLE WiFi Wardriving app → Menu → Backup Database → copy wigle.sqlite off the device.
CSV export — no BLE service UUID data: wigle.net → My Account → Downloads, or app → Menu → Export to SD.
Running tests
uv run pytest
102 tests cover detect.py signal logic, enrich.py enrichers (via httpx.MockTransport), and signatures.py pattern correctness.
How detection works
detect.py runs every record through signatures.py and appends (label, detail) signal tuples to each Hit. Confidence is derived from which labels are present — no stored score:
- HIGH (3):
FLOCK_DIRECT_OUI,RAVEN_UUID_HIGH,FLOCKNET_SSID,FLOCK_CAMERA_SSID,PENGUIN_BLE_SSID - MEDIUM (2):
FLOCK_CAMERA_SSID_PATTERN,BLE_NAME,BACKHAUL_OUI_HIDDEN,FLOCK_WIFI_FP,FLOCK_MFGRID - LOW (1):
CHIP_OUI,SSID_PATTERN,RAVEN_UUID_OLD,SURVEILLANCE_OUI
Cluster groups nearby hits (union-find, 75 m radius) and reports the highest confidence across members.
What WiGLE passive scanning misses
Flock cameras spend most of their duty cycle asleep, waking briefly to upload. A passive WiGLE scan will miss cameras during sleep. The flock-you and FlockSquawk projects implement promiscuous 802.11 mode on ESP32 hardware, matching addr1 (receiver) as well as addr2 (transmitter) to catch cameras even while they sleep. Newer Flock firmware also emits wildcard probe requests (SSID length = 0) on wake-up — detectable only via raw frame capture.
Active GATT interrogation
Raven firmware exposes a readable GATT tree without authentication when within BLE range (~10 m). See signatures.py:RAVEN_CHARACTERISTICS for the full characteristic map. Key characteristics:
| UUID | Field |
|---|---|
0x2a26 |
Firmware version (1.1.7, 1.2.0, 1.3.1) |
0x3002 |
Serial number |
0x3101 / 0x3102 |
Camera's own GPS latitude / longitude |
0x3303 |
LTE operator |
0x3402 |
Most recent upload time |
Files
tui.py Textual TUI — main entry point
detect.py Detection logic (no UI dependency, importable)
enrich.py Async enrichers: OSM/DeFlock, ALPRWatch, WiGLE API
discover.py WiGLE-based discovery of unseen Flock cameras (cached)
signatures.py All OUI prefixes, BLE UUIDs, SSID/name patterns
esp32/ Planned ESP32 companion firmware (design phase)
tests/ pytest suite (asyncio_mode=auto)
pyproject.toml uv project — dependencies and scripts
CLAUDE.md Architecture notes for AI coding assistants
ESP32 companion (planned)
esp32/ contains the design spec for a companion firmware module that
runs on an ESP32 and detects Flock cameras in real time via:
- WiFi promiscuous mode — OUI-matched probe requests +
addr1receiver matching - BLE scanning —
FS Ext Battery, manufacturer ID 2504, etc. - JSON over USB serial — output consumed by
flockdar --serial /dev/ttyUSB0
See esp32/README.md for hardware list, output format, and
integration details. esp32/gen_oui_header.py generates the C header from
signatures.py so the OUI list stays in sync.
Headless / scripted use
from pathlib import Path
import asyncio
import detect
from enrich import build_enrichers, enrich_hits_async
hits, total = detect.run_detection(Path("wigle_backup.sqlite"))
enrichers = build_enrichers() # OSM + ALPRWatch; add WiGLE creds if wanted
asyncio.run(enrich_hits_async(hits, enrichers))
for h in hits:
print(h.confidence_label, h.mac, repr(h.ssid), h.signals_str())
Signature sources
Research attribution — cite these projects when reusing signature data:
- NitekryDPaul — WiFi OUI list via promiscuous-mode 802.11 analysis (flock-you dataset)
- NSM-Barii — Raven BLE service UUIDs, BLE name patterns, newer firmware probe-request technique (flock-back)
- f1yaw4y — Combined OUI list, surveillance OUIs, FlockSquawk firmware (FlockSquawk)
- DeFlock / FoggedLens — OSM ALPR crowdsourcing and enrichment API (deflock.org)
- ALPRWatch — ALPR location database (alprwatch.org)
Known false positives
| OUI / Pattern | Common non-Flock device | How to distinguish |
|---|---|---|
f4:6a:dd |
Barco ClickShare AV gear | SSID contains "ClickShare" |
e4:aa:ea |
Cisco CX20 conferencing | SSID is CX20-N |
14:5a:fc |
Generic BT consumer chips | Named laptop/headphone SSID |
74:4c:a1 |
Vizio soundbars | SSID starts VIZIO |
0000180a UUID |
Nearly all BLE devices | Do not use alone |
eero 80:da:13 (named SSID) |
Home/business mesh routers | Only flag blank or flocknet SSIDs |
License
MIT — see LICENSE. Research and educational use. Cite original researchers when reusing signature data.
This tool is for privacy research, transparency advocacy, and understanding the RF footprint of surveillance infrastructure. It does not interact with cameras or any live systems.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flockdar-0.1.0.tar.gz.
File metadata
- Download URL: flockdar-0.1.0.tar.gz
- Upload date:
- Size: 14.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
773fa81b0380eea61a9ca98d116710708f6fcb16f2adaecd9dac3f3435d0be6f
|
|
| MD5 |
a9fcee09b5bc6c08f2579ac43e4b47ee
|
|
| BLAKE2b-256 |
d14ccb44282095671c508377f3562c118a09edab86ef24dc048dda2716e955b1
|
File details
Details for the file flockdar-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flockdar-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7278dd3bdf2cabfed011baaf86eec47738e8ad19ceb409ffab5a2b49d9c327f7
|
|
| MD5 |
5b80a657320e42ea16d1da436a307484
|
|
| BLAKE2b-256 |
563849bddb92d6891d1282c688c672464602a53782274af6119eb9427918eba6
|