Build improvements:
- Enable ccache via IDF_CCACHE_ENABLE=1
- Mount /var/cache/ccache volume for persistent cache
- Show ccache stats after build
Deployment improvements:
- Deploy to all sensors in parallel (max 3)
- Reduced total deploy time from ~2.5min to ~1min
Note: Runner needs /var/cache/ccache directory with write permissions
Instead of having ESP devices download from Gitea (TLS cert issues),
the runner now serves firmware via local HTTP server and triggers
OTA with the local URL.
Plan for REST API backend (purple team/OPSEC/OSINT):
- Phase 1: Project scaffold, SQLAlchemy models, podman
- Phase 2: UDP collector for sensor data streams
- Phase 3: Core API endpoints (sensors, devices, alerts, probes, events)
- Phase 4: OSINT features (OUI lookup, BLE company ID mapping)
- Phase 5: Fleet management API
Port allocation:
- TCP 5500: HTTP REST API
- UDP 5500: Sensor data collector
- UDP 5501: Sensor commands (outbound)
Also documents completed v1.8 (HTTPS OTA) and v1.9 (multi-channel
scanning, BLE fingerprinting) milestones.
Multi-channel scanning (CHANSCAN command):
- Periodic channel hopping (1-13) with 100ms dwell for broader probe capture
- CHANSCAN ON/OFF/NOW/INTERVAL subcommands
- New NVS keys: chanscan (i8), chanscan_int (i32)
- Emits EVENT,hostname,chanscan=done channels=13 on completion
- PROBE_DATA now includes channel number
BLE fingerprinting:
- Extended BLE_DATA format with company_id, tx_power, flags
- Extracts manufacturer data from BLE advertisements
- Common IDs: 0x004C (Apple), 0x00E0 (Google), 0x0075 (Samsung)
STATUS output now includes chanscan=on/off field.
- Triggers on manual workflow_dispatch with deploy=true
- Triggers automatically on version tags (v*)
- Deploys to muddy-storm, amber-maple, hollow-acorn via OTA
- Uses podman to rebuild, then serves firmware via HTTP
CALIBRATE command captures per-subcarrier CSI amplitudes over a timed
window and stores the averaged baseline in NVS. PRESENCE command enables
real-time scoring via normalized Euclidean distance against the baseline,
with rolling window averaging and 10s holdoff on state transitions.
New commands: CALIBRATE [3-60|STATUS|CLEAR], PRESENCE [ON|OFF|THRESHOLD]
New NVS keys: bl_amps (blob), bl_nsub, presence, pr_thresh
New STATUS fields: presence=, pr_score=
New events: calibrate=done, presence=0|1
Add 7-phase power profiling command (POWERTEST) that cycles through
idle, CSI 10/100 Hz, BLE-only, combined, tx_low/tx_high with EVENT
markers for external power meter correlation. Saves/restores all
settings on completion.
Update roadmap: mark v1.4 done, add v2.0 hardware upgrade milestone
for ESP32-S3/C6 with WiFi FTM / 802.11mc inter-sensor ranging.
Start one HTTP server, send OTA commands to all devices simultaneously,
wait for reboot, then verify all in parallel. Cuts fleet OTA from ~90s
to ~30s. Sequential mode remains the default.
Usage: esp-fleet ota --parallel [firmware.bin]
The main component in ESP-IDF auto-includes all components; explicit
REQUIRES overrides this and breaks the build. mbedtls is available
without it. Also moved flood detection globals above config_load_nvs
to fix undeclared identifier errors.
Firmware:
- HMAC-SHA256 command authentication (AUTH command, NVS persisted)
- Deauth flood detection with ring buffer and aggregate ALERT_DATA
- FLOODTHRESH command (count + window, NVS persisted)
- New STATUS fields: auth=on/off, flood_thresh=5/10
- mbedtls dependency in CMakeLists.txt, rx_buf increased to 192
Tools:
- esp-cmd/esp-fleet/esp-ota import sign_command from esp_ctl.auth
- Commands auto-signed when ESP_CMD_SECRET env var is set
Docs:
- CHEATSHEET: AUTH, FLOODTHRESH, HMAC auth, OUI, watch, osint sections
- TASKS: v1.3 completed section with all new features
- WiFi channel in STATUS (channel=)
- Boot counter persisted in NVS (boots=)
- RSSI min/max tracked from CSI frames since boot (rssi_min=, rssi_max=)
- Actual CSI rate computed from csi_count/uptime_s (csi_rate=)
Enable CONFIG_FREERTOS_USE_TRACE_FACILITY and
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS so PROFILE command reports
per-task CPU usage. Increase cmd_task stack from 4KB to 6KB — was
down to 516 bytes free with current PROFILE reply size.
Promiscuous mode (deauth/probe detection) disables CSI data collection
on original ESP32 at the driver level. Guard with #if !CONFIG_IDF_TARGET_ESP32
to only enable on newer chips where the two coexist.
- Promote CSI packet counter to global, add csi_count= to STATUS
- Add uptime_s= (raw seconds) to STATUS for programmatic parsing
- Emit EVENT on WiFi reconnect with rssi and ip fields
- Add SCANRATE command (5-300s) to tune BLE scan restart interval
- Add PROBERATE command (1-300s) to tune probe dedup cooldown
Replace all CONFIG_CSI_HOSTNAME usage with runtime s_hostname variable.
Load from NVS on boot (falls back to Kconfig default). HOSTNAME <name>
sets hostname, persists to NVS, updates mDNS live. HOSTNAME (no arg)
queries current value. One firmware binary now works for all devices.
Use 460800 baud for USB flash (921600 fails on some boards). Document
new sensor hostname prefix in all data packet formats. Add USB flash
notes section.
Check off sensor ID, deauth detection, chip temperature, BLE alerting,
dwell time, timestamped logging. Advance TASKS sprint to v1.1. Clean
completed items from TODO.
Enable WiFi promiscuous mode (MGMT filter only) to detect deauth and
disassociation frames. Sends ALERT_DATA packets via UDP with sender MAC,
target MAC, and RSSI. Coexists with CSI via separate callback path.