Rename local 'arg' to 'val' in serial_task to avoid shadowing the
function parameter. Guard staged memcpy with nsub > 0 to satisfy
cppcheck uninitvar analysis.
Wire ESP-IDF's built-in 150-CA root bundle to the OTA HTTP client
so HTTPS OTA verifies server certificates. Pin bundle config in
sdkconfig.defaults. Replace dead artifact-copy step with Gitea
release creation on tag push. Bump CI container to IDF v5.5.
- VULN-012: Split STATUS into minimal (unauthed: hostname, uptime,
rssi, version, motion, presence) and full (authed: all internals,
build info, target IP, heap, NVS stats)
- VULN-011: Remove mDNS service advertisement and hardcoded "ESP32 CSI
Sensor" instance name; use hostname only
- VULN-021: Increase HMAC tag from 64 bits (16 hex) to 128 bits
(32 hex) — BREAKING: client scripts must update HMAC computation
- VULN-023: Enable PMF (802.11w) in sdkconfig.defaults to prevent
deauth attacks at protocol level
- Flip cmd_requires_auth() from blacklist to whitelist: only read-only
query commands are unauthenticated, all state-modifying commands now
require HMAC (VULN-007)
- Block AUTH OFF command to prevent remote auth disable; secret rotation
still allowed, full reset via FACTORY (VULN-005)
- Redact auth secret in boot log to first 4 chars only (VULN-003)
- Update HELP text to reflect AUTH change
- Generate 128-bit random auth secret on first boot via hardware RNG,
persist to NVS, log to serial for retrieval
- Gate destructive commands (OTA, FACTORY, REBOOT, TARGET, AUTH,
HOSTNAME set) behind HMAC authentication
- Read-only and operational commands remain open for monitoring
- Require WPA2/WPA3 for WiFi AP association (reject open/WEP)
ALERT TEMP <celsius> and ALERT HEAP <bytes> emit EVENT packets
when thresholds are crossed (60s holdoff). NVS-persisted, shown
in STATUS and CONFIG. Temp alerts require SOC_TEMP_SENSOR_SUPPORTED.
PING returns OK PONG for connectivity testing. LOG sets global
esp_log_level at runtime (NONE/ERROR/WARN/INFO/DEBUG/VERBOSE).
RSSI RESET clears min/max RSSI tracking counters. Compact HELP
text to fit 1400-byte reply buffer.
Firmware: HELP lists all 27 commands with syntax, CONFIG dumps
running config as key=value, FACTORY erases NVS and reboots.
Docs: update PROJECT, ROADMAP, TASKS, TODO to reflect v1.10
completion, v1.11 unreleased work, and esp32-web v0.1.5 state.
Remove stale v2.0 Flask phase-by-phase plan (now tracked in
~/git/esp32-web/). Clean deferred items from completed milestones.
LED command: LED [QUIET|AUTO]
- QUIET: LED off, turns solid on motion/presence detection, blinks on OTA
- AUTO: Original behavior (constant blink)
Persisted via NVS key 'led_quiet'.
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.
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.
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.
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.
- TARGET <ip> [port] command to change data destination live
- NVS persistence for target_ip and target_port
- Falls back to Kconfig defaults when no NVS config
- target= field added to STATUS reply
- config_save_str helper for NVS string storage
On-device CSI wander calculation (coefficient of variation over 50-packet
window). Rate drops to 10 Hz when idle, jumps to 100 Hz on motion with
3s holdoff. EVENT notifications sent to Pi on rate changes. New commands:
ADAPTIVE ON/OFF, THRESHOLD. RATE command disables adaptive mode.
All settings NVS-persisted.
Dual OTA partition table (ota_0/ota_1, 1920 KB each) on 4MB flash.
Firmware gains OTA command, LED_OTA double-blink, version in STATUS,
and automatic rollback validation. Pi-side esp-ota tool serves firmware
via HTTP and orchestrates the update flow. esp-fleet gains ota subcommand.
Firmware:
- mDNS announcement as <hostname>.local (configurable via Kconfig)
- Task watchdog with 30s timeout and auto-reboot on hang
- STATUS now returns human-readable uptime (e.g., 3d2h15m) and hostname
Pi-side tools:
- esp-cmd: mDNS hostname resolution (esp-cmd amber-maple.local STATUS)
- esp-fleet: parallel command to all sensors (esp-fleet status)
Tested on amber-maple — mDNS resolves, watchdog active, fleet tool works.
Firmware (app_main.c):
- UDP command listener on port 5501 (configurable via Kconfig)
- Commands: REBOOT, IDENTIFY, STATUS, RATE, POWER
- LED status indicator on GPIO2 (off/slow/fast blink/solid)
- NVS persistence for send_rate and tx_power settings
- Refactored ping to support stop/restart for dynamic rate changes
- TX power control via esp_wifi_set_max_tx_power()
Pi-side tooling:
- tools/esp-cmd: standalone Python3 UDP client for device management
Tested on amber-maple (ESP32 v3.1) with ESP-IDF v5.5.2.
Matches the version deployed on ESP32 sensors. Removes v6.1
workaround, updates all docs to reflect v5.5.2, regenerates
sdkconfig for the correct IDF version.