api/README.md was significantly out of date — referenced a non-existent
`app.py`, predated the entire `/api/flock/*` command-protocol surface,
and described the dashboard as if it only ingested live JSON.
Full rewrite:
- Quick start with the actual entrypoint (python flockyou.py)
- Sniffer command bar — table of all five buttons, what each one
sends to the device, what comes back, and the canonical
post-wardrive workflow (Pull Prev → Clear Prev) both as button
clicks and as curl invocations
- How replay detections are handled — no GPS temporal matching,
no overwrite of fresher live data, FLASH / RAM badges, the
flock_replay_complete socket event with its ok / count / reason
payload
- Toast colour semantics (green / blue / yellow / red)
- Endpoint reference table covering Sniffer, GPS, detections,
export/import, OUI lookup
- Socket.IO event table — both directions, with the new
flock_replay_complete / flock_status / flock_clear / flock_error
events from this branch
- JSON wire-format samples for live, replay, status, version,
replay_complete, clear, error
- Troubleshooting section keyed on the new failure modes (no_file /
crc_mismatch / device timeout / two-tabs-pulling-at-once)
The root README's "Running Flask" subsection gains a "Dashboard
command bar" block describing the same five buttons + replay visual
treatment, with a cross-reference to api/README.md for the full
detail.
Firmware (main.cpp): adds a line-based CMD:* protocol on the same
USB-CDC port that already streams live detection JSON, so Flask can pull
state without re-flashing:
- CMD:STATUS emits {"event":"status",...} with det count,
SPIFFS state, free heap, uptime, channel
- CMD:VERSION emits firmware identifier + compile-time constants
- CMD:DUMP_LIVE streams the in-RAM detection table as replay
JSON lines, then a replay_complete sentinel
- CMD:DUMP_PREV same, but reads /prev_session.json from SPIFFS
(parses the CRC envelope and the embedded array)
- CMD:CLEAR_LIVE wipes fyDet[] and dirties the autosave
- CMD:CLEAR_PREV deletes /prev_session.json and any /session.tmp
Implementation:
- Minimal string-aware JSON object reader (string-aware brace counter,
backslash handling) lifts entries from the SPIFFS array one at a
time without slurping the whole file
- jsonGetString / jsonGetInt field extractors over flat objects
- emitReplayDetection() reuses the existing Flask schema and adds
replay / replay_source / detection_count / device_first_ms /
device_last_ms so the host can tell historical from live
- serialCmdTick() runs once per loop() and only acts on completed
lines — non-blocking and safe alongside the live detection path
- dualPrintf buffer bumped 384 → 1024 B to fit the longer replay line
(and to remove a latent truncation risk on a long-SSID live line)
Flask (api/flockyou.py): turns the protocol into REST endpoints and
ingests replayed detections without confusing them with live ones:
- flock_reader now dispatches {"event":"status"|"version"|"clear"|
"replay_complete"|"error"} responses to threading.Event slots, and
routes {"replay":true,"detection_method":...} lines through a new
add_replay_detection_from_serial() that skips GPS temporal matching,
flags timestamp_source="device_replay", and merges into an existing
fresher live entry instead of overwriting it
- send_command(cmd, response_event_name, timeout) serializes one
command at a time and blocks until the matching event arrives
- new endpoints: /api/flock/{status,version,dump_prev,dump_live,
clear_prev,clear_live}
Verified: pio run completes clean (RAM 19.1%, flash 12.0%); flockyou.py
passes py_compile. README documents the protocol, the per-event shape,
and the canonical post-wardrive dump_prev → clear_prev workflow.
Brings the target OUI array up to parity with @NitekryDPaul's upstream
nite-oui-collection (April 2026):
- Adds 12 prefixes: 04:0d:84, f0:82:c0, 1c:34:f1, 38:5b:44, 94:34:69,
b4:e3:f9, b4:1e:52, 14:b5:cd, 94:2a:6f, f4:e2:c6, d4:11:d6, e0:0a:f6
- Demotes f8:a2:d6 — flagged as a Sony Media Player false positive
in his my_tested_flock.md notes, retained only as documentation in
the dataset's "Demoted / low confidence" section.
Active firmware count is now 42 (29 from @NitekryDPaul's original set,
12 April 2026 additions, 1 from Michael / DeFlockJoplin).
Also: replaces the stylised cyrillic researcher name with its decoded
form OrdoOuroborous and links his GitHub @nitekry, since the unicode
glyphs don't render reliably and made the credit hard to follow.
Adds Michael / DeFlockJoplin's high-precision detection method on top of
the NitekryDPaul baseline: a Flock camera is flagged when it transmits a
Probe Request (type=0 subtype=4) with a wildcard SSID IE (tag 0 len 0)
AND its addr2 matches the OUI list. Drive-test in Joplin: 11/12 cameras
caught with only 2 false positives.
- New AlertType ALERT_WILDCARD_PROBE, emitted as detection_method
'wifi_wildcard_probe' (high-precision class)
- Wildcard-probe hits suppress the addr2 broad alert for the same frame
to prevent double counting; non-probe OUI matches still emit as
'wifi_oui_addr2'
- IE parser returns tri-state (1=wildcard / 0=directed / -1=no SSID IE),
with FCS-trailer retry only on the -1 no-IE case
- addr1 receiver-side sleeper-catch and the optional addr3 + SSID paths
are unchanged — wildcard is purely additive
- 31st OUI 82:6b:f2 added to target_ouis[] and to the dataset doc; it's
the OUI of the 12th camera in Michael's drive-test that the original
30 didn't catch
- README explains the wildcard-probe method, credits Michael with a link
to github.com/DeflockJoplin/flock-you, and bumps Acknowledgments
Source: https://github.com/DeflockJoplin/flock-you
- Moved promiscuis-flock-you/{main.cpp,partitions.csv,platformio.ini} to root
- Removed BLE firmware (src/main.cpp, src/CMakeLists.txt) — the 'main' branch
still has it
- Removed the subfolder README (root README has the full walkthrough)
- Updated README paths and build commands for the flat layout
- Retagged the BLE companion section as a pointer to the 'main' branch
The 'promiscious' branch is now purely the WiFi promiscuous firmware plus
the shared Flask app (api/), datasets, and branding. Builds green with
the standard 'pio run' from the repo root.
The 'promiscious' branch is about the WiFi promiscuous detector, not BLE.
Reworked the root README to lead with:
- @NitekryDPaul credit front-and-center (30-OUI list + addr1 technique)
- What the WiFi firmware does and why promiscuous mode is the right tool
- Detection pipeline, OUI list, SPIFFS envelope format
- Flask dashboard integration with the wifi_oui_addr1/addr2 methods
- Hardware, build, config cheatsheet
- SMB 1-2 underground boot melody
The BLE firmware is now a short pointer to main at the bottom.
Explains how the new WiFi promiscuous firmware in promiscuis-flock-you/
complements the existing BLE detector — same hardware class, same Flask
dashboard schema, complementary RF coverage.
Full research credit to ØяĐöØцяöЪöяцฐ / @NitekryDPaul for the 30-OUI
target list and the addr1-receiver detection technique. Added to
Acknowledgments.
Complete rewrite of standalone Flock-You firmware:
- Remove WiFi promiscuous mode, all detection is now BLE-only
- Add web dashboard served on AP "flockyou" at 192.168.4.1
- GPS wardriving via phone browser Geolocation API
- SPIFFS session persistence with auto-save every 60s
- Prior session tab (PREV) survives reboots
- KML export for Google Earth (current + prior session)
- JSON/CSV export with GPS coordinates
- Serial JSON output for Flask live ingestion
- Crow call boot sounds with detection/heartbeat alerts
- 200 unique device storage with FreeRTOS mutex
- Flask app: add KML import endpoint, GPS data handling
- Update platformio.ini with AsyncWebServer, ArduinoJson 7, SPIFFS partition
- Rewrite README to reflect current functionality