Changelog
Release notes, fixes, and upgrade instructions. Unreleased entries describe work in progress.
Sections
3.1.0
-
Wi-Fi raw traffic is stable on supported chips. ESP32-C6 remains unsupported; see compatibility limits.
-
Monitor Demo mode now applies the motion-on and motion-off reading counts to state transitions and chart highlighting, and retains these settings while navigating between tools.
-
wifi_rawaccepts a destination throughtraffic_generator_target_mac. The default,auto, follows the associated AP after reconnects and BSSID pin changes. A unicast MAC sends direct MCS0 Null Data with two zero padding bytes to another sensor inexternalmode on the same channel: HT20 on 2.4 GHz, and VHT20 on C5 at 5 GHz. The transmitter keeps LLTF sensing. Update both peers together: earlier receivers accept only the unpadded 28-byte frame and reject the padded 30-byte form. No additional device role is required. Set it in ESPHome YAML,CONFIG_ESPECTRE_TRAFFIC_GENERATOR_TARGET_MAC,RuntimeConfig,RuntimeFrontendController::set_traffic_generator_target_mac(),update_sensing, or Monitor → Advanced sensing settings. Direct and MQTT share validation, state, and persistence; devices advertise support withfeatures.traffic_generator_target_mac. -
Discovery includes the optional station
mac_addressacross frontends. The Monitor's Destination MAC menu offers Automatic (AP) and discovered sensors, while retaining the configured destination when it is not found. Its refresh button searches on demand, without caching results or offering manual MAC entry. -
The SDK additions are source-compatible.
ICsiTrafficGenerator::set_target_mac()has a default implementation, andFrontendCommandEngine::execute()takes the raw destination callback as a new optional trailing parameter.RuntimeConfigErrorandEspectreDirectMethodgain one value each, so exhaustiveswitchstatements need a new case.read_direct_station_mac_address()andPeerDiscoveryCandidate::mac_addressexpose the optional discovery MAC. -
External traffic mode accepts direct non-QoS Null Data and unencrypted unicast ESP-NOW v1/v2 frames, subject to the existing CSI quality and capture-profile checks. C3-to-S3 acquisition is validated with both sources at HT20 MCS0, and with legacy OFDM/LLTF, with promiscuous mode disabled. Direct Null Data at MCS0 requires explicit transmitter HT20 bandwidth and a wildcard BSSID; the receiver keeps its standard HT20 profile. HT20 and VHT20 frames may carry exactly two zero padding bytes. ESP32-C6 needs them for valid CSI, and receives valid HT20 CSI from padded Null Data and unicast ESP-NOW.
3.0.0 Wi-Fi sensing SDK, standalone firmware, and browser tools
ESPectre 3.0 splits the sensing engine, runtime, and frontend so Wi-Fi motion detection can run inside other firmware. It turns the three release candidates into one stable release.
Coming from 2.x? Read up to "Upgrading from 2.x". Tested a release candidate? Jump to "For release candidate testers".
Highlights
- C++ source SDK on the ESP Component Registry as
francescopace/espectre, for C++17 or later and ESP-IDF 5.5.3 or later. ESP-IDF 6.x is build-validated only. See the SDK guide. - Standalone Native firmware with Direct HTTP, MQTT, Home Assistant discovery, and HTTPS OTA.
- Matter occupancy-sensor frontend that reports motion. Images are uncertified development builds without Matter OTA. See the Matter guide.
- Browser tools for installation, provisioning, configuration, and tuning, plus one
./espectreCLI. - Two detectors on a
0.0–1.0probability scale: Lightweight, the default, calibrates at startup; High Accuracy is a neural model that needs no calibration.
Sensing and CSI
- Timestamp-based temporal sampling replaces packet-count windows. Missing slots stay explicit.
- Both detectors use gain-invariant features, so AGC stays on. See the algorithm reference.
traffic_generator_modeselectsping(default),dns,dns_tcp,wifi_raw(experimental), orexternal.- Build-time capture policies
auto,lltf, andht-vht. ESP32-C5 adds 2.4/5 GHz selection; 5 GHz detection is uncharacterized. See CSI acquisition. - Retransmitted frames and stray ACKs no longer add CSI samples.
- Sensing resumes after roaming, and ESPHome skips periodic roaming scans.
- Raw CSI collection streams V8 records over HTTP, and
collectvalidates every capture.
SDK, integrations, and tools
- Modular SDK: use the full runtime or only the detectors through
espectre_core_sdk.h. MQTT, Direct, and provisioning are optional. - Dual license: GPLv3 or commercial. The ESPHome frontend stays GPLv3-only. See licensing.
- Separate SDK, application, and protocol versions with a documented compatibility contract. See SDK versioning.
- Direct HTTP and MQTT share one JSON contract. Direct uses
/espectre/v1on port62587, and discovery uses_espectre._tcp. See the API reference and discovery reference. - Official images accept only signed OTA updates. See official images and personal builds.
- Home Assistant Traffic Generator add-on (#168), with generator and station traffic reported separately (#182).
- Micro-ESPectre runs native Lightweight detection with HTTP delivery. High Accuracy stays host-side.
- Browser troubleshooting guide and an NM-CYD-C5 touch-display example by @RockBase-iot (#166).
- Dataset validation pairs recordings up to three hours apart with matching role and RSSI class.
Upgrading from 2.x
- Detectors:
mvs→lightweight,ml→high_accuracy,MVSDetector→LightweightDetector,MLDetector→HighAccuracyDetector. Scores and thresholds use0.0–1.0. - ESPHome YAML:
segmentation_window_size→segmentation_window_size_ms,evaluation_interval→evaluation_interval_ms,traffic_generator_rate→csi_target_pps. Removesegmentation_threshold,gain_lock,selected_subcarriers, publish-interval overrides, andble_*. Provision over Improv Serial. See the ESPHome guide. - Hostnames and entity IDs gain a MAC suffix, such as
espectre-a1b2c3.local(#179). Update OTA addresses and dashboards, and reapply any BSSID pin. Example YAML lives insrc/cpp/frontend/esphome/examples/. - CLI: use
./espectre, with MicroPython commands under./espectre micro. Browser tools,mqtt, andcollectreplace the oldmeworkflows. See the CLI guide. - Micro-ESPectre: reflash and redeploy. Device-side High Accuracy, MQTT, and UDP streaming are gone. See the Micro-ESPectre guide.
- Requirements: Python 3.14, ESPHome 2026.7.0 or later, and ESP-IDF 5.5.3 or later. PlatformIO and the old
components/espectre/layout are gone. - Leaving unsigned personal builds needs one USB flash of signed official firmware. Migrate dataset metadata to format
1.2.
For release candidate testers
Changed since 3.0.0-rc3
- Temporal admission fills free neighbouring slots: median occupancy 92.3% → 93.9%.
- High Accuracy retrained with
log1pinputs: worst paired recall 97.1% → 98.3% at the same 0.14% peak false-positive rate. - New
wifi_scan_allowed()for firmware that runs its own Wi-Fi scans. CsiCaptureProfileandCsiCapturePolicyare open enums, and the core-only detector interface sits outside the compatibility promise.- Dataset pairs can span three hours instead of 30 minutes.
- New browser troubleshooting guide.
Fixed since 3.0.0-rc3
- High Accuracy starting with the Lightweight threshold instead of
0.5(#186). - Lightweight calibration ignoring a traffic-source change, such as
ping→dns. - ESP32-S3 staying in calibration after a Wi-Fi reconnect.
- CSI runaway on weak links: retransmissions and ACKs pushed a 100 pps source to 217 records/s.
collectskipping its quality checks since rc1 and passing captures with long gaps.collecthanging on Ctrl+C, and failed sends leaving the CSI stream open.- Arduino source builds failing to link.
- Web flasher corrupting commands after a metadata read; it now uses esptool-js 0.7.0.
Upgrading from 3.0.0 release candidates
- ESPHome:
csi_traffic_mode→traffic_generator_mode, also for_select. Saved rc1/rc2csi_trafficsettings no longer migrate. Delete retired Native Home Assistant entities manually, and update firmware before using the add-on. - C++: apply the rc3 SDK migration table, then
TrafficGeneratorMode::EXTERNAL→EXTERNAL_HOST. ESPECTRE_SDK_VERSION_NUMBER→ESPECTRE_SDK_VERSION_AT_LEAST().espectre_device_id_from_mac()is gone.- API clients: resource methods replace
POST /request,motionreplaces telemetry, andGET /csireplaces raw-session commands. Diagnostics need explicitfields, and V7 records are gone. See the API reference. - Re-export custom High Accuracy weights; inference requires
ML_FEATURE_LOG_SCALE. TrafficGeneratorManager→TrafficGeneratorServiceintraffic_generator_service.h. Keep callingloop()on it and onCsiTrafficServiceafterstop().on_live_telemetry()takes aRuntimeSnapshot, andset_config()returnsfalseafter setup.persist_runtime_overridesdefaults tofalse; first-party firmware enables it.clear_persisted_overrides()erases saved controls.RuntimeConfig::thresholddefaults to the selected detector's value. Setup faults withoutCONFIG_ESP_WIFI_CSI_ENABLED.
3.0.0-rc3 SDK on the ESP Component Registry and ESP-IDF 6 support
Highlights
- Published the SDK as the
francescopace/espectrecomponent on the ESP Component Registry. - Added ESP-IDF 6.x support to the SDK, alongside 5.5.3 and later.
- Added the Home Assistant Traffic Generator add-on (#168).
- Improved device discovery and sensing recovery after Wi-Fi roaming.
Added
- ESP-IDF 6.x support in the SDK. Official firmware stays on 5.5.5; see SDK.md.
- Registry packages with a Wi-Fi sensing example, validated by consumer builds before and after publication.
- The SDK API reference on the website, covering every public type.
- A troubleshooting guide on the website, organized by symptom, including the traffic source fix for calibration that never finishes (#188).
- The Traffic Generator add-on for 64-bit Home Assistant OS, with an Ingress panel for traffic control and live diagnostics, including ESPHome devices (#168).
- Generator Rate and Traffic RX Rate sensors in Home Assistant (#182).
- Warnings when a runtime loop iteration or a traffic generator send stalls for 100 ms or more, naming the slow steps.
- An NM-CYD-C5 ESPHome example with a touch display, contributed by @RockBase-iot (#166).
BaseDetectorcalibration hookson_startup_calibration_abandoned(),startup_calibration_conclusive(), andcalibration_motion_ceiling(). Defaults keep the previous behavior.RuntimeConfig::persist_runtime_overrides: set it to false when your firmware owns configuration, so live control changes are neither restored nor saved.
Changed
- Breaking: Official ESPHome images use MAC-suffixed hostnames such as
espectre-a1b2c3.local. After the first update, use the new hostname for OTA and update dashboard entity IDs (#179). - Breaking: The SDK exports only its root include directory; use layer-prefixed includes such as
#include "runtime/runtime_config.h". - Breaking:
IEspectreRuntimeis internal.RuntimeConfigandWifiBandPolicymoved toruntime/runtime_config.h, which replacesruntime/runtime_interface.h. - Breaking:
espectre_sdk.hno longer includes the ESPectre Protocol; includeespectre_protocol_sdk.h. Diagnostic JSON helpers moved toruntime/runtime_diagnostics_protocol.h, and diagnostic profiles have named constants. - Breaking:
RuntimeDiagnosticsSnapshotgroups its fields aslink,traffic,csi,platform, andperformance, for examplecsi.accepted_total. Wire names are unchanged. - Breaking: Renamed SDK symbols so each name says what it controls, such as
TrafficGeneratorMode,RuntimeConfig::threshold, andset_threshold(). Wire names, ESPHome YAML keys, and saved settings are unchanged. - Breaking:
traffic_generator_mode: externalreplacescsi_traffic_modein the protocol, ESPHome YAML, Kconfig, and the SDK. The Home Assistant "CSI Traffic Ownership" select is gone; "CSI Traffic Source" gainsexternal. Saved settings migrate; update clients and firmware together. - Breaking:
kNativeLoopPriorityleft the SDK; the Native frontend defines its own. - Breaking: Removed unused SDK API, including
parse_json_array_objects(), twoRawCsiStopReasonvalues, andRawCsiPacketView::wifi_rx_start_ts_ns.publish_frontend_mqtt_message()drops itsconfigargument. - Breaking:
wifi_band_policydefaults toAUTOon every target. A hand-builtRuntimeConfig{}on ESP32-C5 now selects the band automatically. - Traffic diagnostics report internal generation (
generator_pps) and station traffic (traffic_tx_pps,traffic_rx_pps) separately, so the generator rate reads zero when no generator runs (#182). - The SDK requires MQTT and mDNS only when enabled, and no longer requires the HTTP server.
- ESPHome devices no longer run periodic roaming scans, which took the radio off-channel for up to 12 seconds every 5 minutes.
update_sensingreturnsunsupportedfor a threshold the device cannot change.- CLI discovery waits six seconds by default and asks devices to reply directly.
- One
cd.ymlworkflow publishes releases to the production registry andmainanddevelopsnapshots to the staging registry (#178).
Fixed
- Fixed runtime loop stalls from taking the lwIP core lock and from stopping the traffic generator. Firmware that drives
TrafficGeneratorManagerorCsiTrafficServicedirectly must keep callingloop()afterstop(). - Fixed sensing not resuming after roaming with a retained IPv4 address, and startup waiting on a Wi-Fi scan.
- Fixed CSI staying silent on S3 and C5 after switching from
wifi_rawto another traffic source. - Fixed Lightweight calibration: movement no longer pushes the threshold close to 1.0, and quiet rooms no longer drive it to about 0.01. It now stays between 0.095 and 0.987.
- Fixed MOTION and availability flickering during brief CSI coverage dips.
- Fixed
update_sensingapplying some fields before rejecting another. Custom frontends should pass the new optional validator toFrontendCommandEngine::execute(). - Fixed a failed startup calibration dropping the active detector, an unchanged detector losing its threshold, and
shutdown()leaving availability ready. - Fixed
espectre collectignoring its own startup calibration. - Fixed mDNS replies to common query types and browser discovery running out of HTTP connections. See DISCOVERY.md.
- Fixed Native rebooting while checking for OTA updates.
- Fixed
matter qrandmonitor --resetleaving the device in the firmware loader, and Matter reporting its version asunknown. - Fixed standalone Wi-Fi leaking resources, truncating full-length credentials, and giving up on reconnection.
- Fixed source-list builds of the Direct sources missing the mDNS link wrapper; use
ESPECTRE_RUNTIME_ESP_IDF_DIRECT_LINK_OPTIONS. - Fixed the WiFi Channel sensor showing decimals (#181).
Removed
- Breaking: Removed the
traffic_packets_totaldiagnostic; useget_generator_packets_total()orget_packets_received()(#182). - Breaking: Removed
initialize_primary_console(); integrations set up their own console. - Breaking: Removed
wifi_tx_rate.hfrom the services facade; callapply_station_tx_rate()fromnetwork_traffic.h. - Breaking: Removed
ESPECTRE_CORE_INCLUDE_DIRSandESPECTRE_RUNTIME_INCLUDE_DIRS. - Breaking: Removed CSI V7 binary record support. Existing NPZ datasets still load.
- Breaking: Removed
RuntimeProfileand its helpers; settraffic_generator_modeinstead. - Breaking: Removed
RuntimeSubcarrierSourceand the subcarrier snapshot fields; readRuntimeFrontendController::subcarriers(). - Breaking: Removed
csi_traffic_modehelpers,make_runtime_sensing_config(), andvisit_runtime_diagnostics(). Thevalidate_runtime_*()helpers are now internal. - Breaking: Removed the unused raw stream command path, including the last
FrontendCommandEngine::execute()argument. Raw CSI collection opens withGET /csi. - Breaking: Removed
handle_device_config_command()and its types; useparse_espectre_config_command()andparse_espectre_mqtt_config_command(). - Breaking: Removed
ESPECTRE_DIRECT_MAX_REQUEST_ID_SIZEandESPECTRE_DIRECT_MAX_METHOD_SIZE; useESPECTRE_COMMAND_ID_MAX_LENGTH. - Breaking: Removed
BaseDetector::packet_index_; readtotal_packets_.
SDK source migration
Updating C++ code from rc2 is a compile-and-replace pass. Behavior changes only where noted. The external traffic setting also changes on the wire, in Kconfig, and in ESPHome YAML; saved settings migrate on their own.
| rc2 | rc3 |
|---|---|
#include "runtime/runtime_interface.h" |
#include "runtime/runtime_config.h" |
IEspectreRuntime |
Internal; use RuntimeFrontendController |
Protocol, JSON, and transport contracts from espectre_sdk.h |
#include "espectre_protocol_sdk.h"; the services and MQTT headers include it |
Diagnostic JSON and field helpers in runtime/runtime_diagnostics.h |
runtime/runtime_diagnostics_protocol.h |
Profile masks 1U, 2U, 4U, 7U |
ESPECTRE_DIAGNOSTIC_PROFILE_NATIVE, _BRIDGE, _MICRO, _ALL |
CsiTrafficMode, config.csi_traffic_mode = EXTERNAL |
config.traffic_generator_mode = TrafficGeneratorMode::EXTERNAL |
RuntimeTrafficMode |
TrafficGeneratorMode |
config.csi_capture_profile |
config.csi_capture_policy |
config.segmentation_threshold |
config.threshold |
config.segmentation_window_size_ms |
config.window_size_ms |
RUNTIME_SEGMENTATION_THRESHOLD_DEFAULT |
RUNTIME_THRESHOLD_DEFAULT |
RUNTIME_SEGMENTATION_WINDOW_SIZE_MS_* |
RUNTIME_WINDOW_SIZE_MS_* |
set_threshold_runtime(), set_motion_hits_runtime(), set_detection_algorithm_runtime() |
set_threshold(), set_motion_hits(), set_detection_algorithm() |
set_csi_traffic_mode_runtime(EXTERNAL) |
set_traffic_generator_mode(TrafficGeneratorMode::EXTERNAL) |
set_traffic_generator_mode_runtime() |
set_traffic_generator_mode() |
traffic_mode_name(), parse_traffic_mode() |
traffic_generator_mode_name(), parse_traffic_generator_mode() |
runtime_traffic_mode_valid(), runtime_traffic_mode_supported() |
runtime_traffic_generator_mode_valid(), runtime_traffic_generator_mode_supported() |
csi_traffic_mode_name(), parse_csi_traffic_mode(), runtime_csi_traffic_mode_valid(), csi_traffic_mode_is_sensing_control() |
Removed; traffic_generator_mode_name() returns external |
csi_traffic_mode: (ESPHome YAML), CONFIG_ESPECTRE_CSI_TRAFFIC_MODE_EXTERNAL, csi_traffic_mode (protocol) |
traffic_generator_mode: external, CONFIG_ESPECTRE_TRAFFIC_GENERATOR_MODE_EXTERNAL, traffic_generator_mode: "external" |
make_runtime_sensing_config() |
RuntimeConfig{} |
snapshot.fixed_subcarriers |
controller.subcarriers() |
diagnostics.csi_accepted_total, diagnostics.wifi_rssi_dbm |
diagnostics.csi.accepted_total, diagnostics.link.rssi_dbm; see the grouping entry above |
on_periodic_update(snapshot, packets_received) |
on_periodic_update(snapshot, csi_accepted); same signature |
RuntimeProfile, RuntimeSubcarrierSource, visit_runtime_diagnostics() |
Removed |
FrontendCommandEngine::execute(..., raw_stream_callback) |
Drop the last argument; raw CSI collection opens with GET /csi |
handle_device_config_command() |
parse_espectre_config_command(), parse_espectre_mqtt_config_command() |
ESPECTRE_DIRECT_MAX_REQUEST_ID_SIZE |
ESPECTRE_COMMAND_ID_MAX_LENGTH |
ESPECTRE_DIRECT_MAX_METHOD_SIZE |
Removed; command names use the canonical registry |
BaseDetector::packet_index_ |
total_packets_ |
Two behavior changes need a decision:
- A hand-built
RuntimeConfig{}on ESP32-C5 now usesAUTOband selection. Setwifi_band_policy = WifiBandPolicy::BAND_2Gto keep 2.4 GHz. - If your firmware owns configuration, set
persist_runtime_overrides = falseso saved controls no longer override it.
3.0.0-rc2 Signed firmware, CSI capture controls, and standalone SDK builds
Highlights
- Verify browser downloads with signed catalogs; Native and ESPHome require signed OTA updates.
- Build all first-party frontends against extracted SDK bundles through
ESPECTRE_SDK_ROOT. - Select CSI capture profiles at build time and try experimental
wifi_rawtraffic on supported chips. - Read selected diagnostics over Direct HTTP and MQTT, including frontend loop timing.
Firmware and sensing
- Native OTA uses the shared firmware catalog; rolling firmware and SDK manifests use channel names.
- Reject invalid CSI and report stale sensing as unavailable, preserving raw CSI framing.
- Add
auto,lltf, andht-vhtcapture profiles; 5 GHz detection remains uncharacterized. See CSI.md. wifi_rawrequiresautoorlltfand is disabled on ESP32-C6;pingremains the default.- Allow custom IPv4 destinations for internal traffic generators. See SDK.md.
- Default station TX rates to 6.5 Mbps on classic ESP32 and Auto elsewhere, independently of sensing.
- Resume CSI after reassociation or roaming with retained IPv4 state, without requiring another
GOT_IPevent. - Pin CPU clocks per target, reclaim Native IRAM, and save 6 KiB in the C++ raw CSI queue.
SDK and diagnostics
- Derive SDK versions from packaged metadata or integrator overrides, independently of firmware versions; missing or incomplete metadata uses
0.0.0. - Move Improv Serial support outside the SDK and share command validators with ESPHome controls.
- Micro-ESPectre Direct validates JSON and parameters; non-empty bodies require the JSON media type.
- Share
csi_hw_error_ppsacross C++ and MicroPython, and expose C++ frontend loop duration asloop_time_ms.
Web tools, builds, and maintenance
- Show the newest Release or Preview firmware on the home badge, and suggest replacement routes on 404 pages.
- Reduce benchmark HTTP traffic, recover stale SSE readiness, and report setup failures with diagnostic evidence.
- Update ESPHome to
2026.9.0, host dependencies, and website packages, including the Rollup security fix. - Add dependency audits and quality reports; block releases on license violations, scanner failures, and applicable high, critical, or unscored CVEs.
- Store build packages, caches, and audit output under
.cache/.
Breaking changes and migration
- Diagnostics without
fieldsreturn a catalog; use explicit fields or["*"]for values. Upgrade clients and firmware together. See API.md. - OTA services, version comparison, release catalogs, and OTA types move from the SDK runtime to shared frontend code.
- Replace
RuntimeFrontendController::quiesce_for_ota()withquiesce(); replaceespectre_firmware_version()calls by supplying the application version through runtime interfaces. - Remove
RuntimeDiagnosticsSample::csi_classified_ppsandcsi_provenance_rejected_pps, plus diagnosticscsi_classified_totalandcsi_estimate_length_mismatch_total. - Remove
TemporalCsiSamplercountersduplicate_packets,missing_timestamp_packets, andgap_resets. - Convert
CONFIG_ESPECTRE_WIFI_TX_RATE_MBPSoverrides to strings"0","6", or"6.5", or remove them to adopt target defaults. - Update saved
CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITYoverrides to adopt the new default of1. - Rebuild and flash Micro-ESPectre firmware before deploying the application, which now requires
espectre_native_wifi. - Use USB when switching between unsigned personal builds and signed official firmware. Matter still has no OTA. See SETUP.md.
3.0.0-rc1 Wi-Fi sensing SDK, multi-frontend support, ready for new runtimes
ESPectre 3.0 makes Wi-Fi sensing a building block for your own products. This first release candidate introduces a C++ SDK and separates the sensing engine from the runtime and frontend, so developers can bring it into their own firmware and extend it to new integrations.
Install, configure, and tune a sensor from the browser, or use one CLI from the first firmware build through deployment, diagnostics, and CSI collection. ESPHome is joined by standalone Native and Matter firmware, all built on the shared sensing engine. Matter controller validation remains limited in this release candidate.
Highlights
- Embed ESPectre in your own product: the public C++ source SDK offers the sensing runtime or direct access to the detectors. Commercial licenses are available for proprietary firmware, alongside GPLv3 for open-source use.
- Add runtimes and frontends around the same sensing engine. Portable runtime contracts separate detection from platform services and product integrations. ESP-IDF is the supplied full runtime backend, with ESPHome, Native, and Matter reference frontends.
- Install and tune from the browser: the web suite at espectre.dev covers firmware flashing, Wi-Fi provisioning, device configuration, live monitoring, and detection tuning. Controls adapt to each device's supported capabilities.
- Use one CLI throughout the device lifecycle.
./espectrebuilds, flashes, provisions, deploys, discovers devices, and sends control requests. It also provides serial monitoring, diagnostics, raw CSI collection, and an interactive MQTT client. - Choose the detector for your product: Lightweight keeps CPU and memory costs low; High Accuracy uses a neural model and starts without quiet-room calibration. Both report motion on the same
0.0-1.0probability scale.
SDK, firmware, and tools
- The SDK has two public entry points.
espectre_core_sdk.hexposes the detectors and temporal sampler for products that already own CSI capture.espectre_sdk.hadds sensing, calibration, events, and the ESP-IDF runtime backend. The documented contract covers source compatibility, capabilities, ownership, threading, errors, optional components, and versioned release bundles. Logging is optional and frontend-owned, so the shared SDK does not depend onesp_logand remains silent unless the integration registers a sink. - Lightweight is the default detection profile, with a two-feature weighted model and startup calibration. High Accuracy uses an eight-feature phaseless neural model and starts from a trained threshold. Both use gain- and scale-invariant production features, so maintained firmware keeps AGC enabled.
- One versioned application API spans Direct HTTP, SSE, and optional MQTT. HTTP and MQTT share resource payloads, operation names, validation, and result codes. Direct resources live below
/espectre/v1on port62587, andGET /eventscarries resource snapshots and per-evaluation motion events. Native publishes its supported resource snapshots and control operations over MQTT;healthprovides retained availability and Last Will, while motion events remain unretained. Capability profiles declare the resources, operations, events, and features supported by each frontend. - Local discovery now uses one first-party DNS-SD service across every networked frontend. Devices advertise
_espectre._tcp.local.with their Direct endpoint and protocol metadata, and./espectre devicesvalidates that record instead of relying on ESPHome or Matter service schemas. The hosted portal can discover devices without an extension, cloud relay, or address-range scan: it resolves a fresh nonce-scoped.localhostname, then an eligible Native, ESPHome, or Matter device performs the bounded browse and returns validated endpoints. Browser discovery requires IPv4, working mDNS, and Local Network Access. - Native is standalone ESP-IDF firmware with Direct HTTP sensing and HTTPS OTA updates. MQTT and Home Assistant MQTT Discovery are optional. It uses standard Improv Serial for provisioning and has no BLE dependency.
- Matter adds a firmware frontend for the standard occupancy sensor device type. Each device generates its own onboarding data, and its QR code remains available from serial output, Improv Serial, the web flasher, or
./espectre matter qr. Sensing starts only after commissioning. Direct stores a BSSID preference for the commissioned SSID without changing Matter-owned credentials. The hardware benchmark commissions the device with a CHIP Tool build that matches the firmware, scores both detectors, and does not retain onboarding data or fabric secrets. Current images use development VID/PID and example device attestation credentials, do not support Matter OTA, and have limited controller validation. - Micro-ESPectre is a micropython, read-only sensing frontend. The deployed application uses Lightweight Detector, the shared managed traffic generator with deployment-time
ping,dns, ordns_tcpselection, six read-only HTTP resources plus session-only recalibration, one motion SSE stream, mDNS discovery, and serial logging. Its profile enforces production Origin validation, a 10-second SSE heartbeat, a 512-byte request limit, a 4,096-byte event limit, one client, and one frame in flight. The High Accuracy ML model remains available in Python for host research and C++/Python validation but is not copied to the device. - Temporal CSI sampling replaces packet-count windows. Packet timestamps define a stable slot grid that retains the candidate nearest each slot and leaves missing slots empty. Traffic generators avoid catch-up bursts, detector resets do not rephase the sampling grid, and ESP-IDF frontends expose explicit
ping, DNS/UDPdns, and persistentdns_tcpsources. Ping remains the shared schema default and the published product configuration default. - The runtime selects the CSI capture profile for each chip and band. ESP32-C5 defaults to automatic 2.4/5 GHz selection and can be pinned to either band, using HT20 on 2.4 GHz and VHT20 on 5 GHz while excluding HE capture. Detection quality on 5 GHz has not yet been characterized. ESP32 and ESP32-S2 select LLTF20 to admit legacy OFDM traffic while preserving the canonical centered 64-bin raw and detector views; other 2.4 GHz targets continue to use HT20.
- CSI collection runs over a single HTTP response across supported ESPectre frontends.
GET /espectre/v1/csistarts the exclusive collection and TCP close ends it, without a bearer or explicit start/stop commands../espectre collectstarts the shared external UDP marker generator before opening the response and saves CSI V8 records with PHY and device provenance. Derived sensing events pause during collection and resume only after sensing is ready. HTTP does not pace or decimate records, and bounded firmware queues report drops explicitly. - ML corpus curation and promotion keep selection and holdout distinct. New captures require explicit environment and dataset-role metadata before validation.
train_ml_model.py --evaluate-selectionruns candidate deployment gates without opening holdout, while--evaluate-gatesremains the final read-only check for a fixed candidate. - The web tools provision Native and ESPHome over standard Improv Serial, configure and monitor supported C++ frontends, manage Native MQTT and OTA settings, and read Matter onboarding data. The suite also includes a motion game and Wi-Fi Theremin. USB flashing, provisioning, and Matter QR reading require a Chromium-based browser. ESPHome images retain their fallback access point but no longer include BLE provisioning.
- Release downloads include factory and OTA images for ESPHome and Native, factory images for Matter, SDK bundles, and
firmware-compliance-<channel-or-version>.zip. Commercial licensing covers the shared engine and eligible integrations; the ESPHome frontend remains GPLv3-only. Contributions are subject to CLA and DCO checks. Native OTA accepts only a strictly newer release, prerelease, or rollinggit describeidentity.
Breaking changes and migration
- The unreleased Direct RPC contract is replaced without aliases. Replace
POST /espectre/v1/requestwith the resource methods documented inAPI.md; replace telemetry withmotion; replace explicit raw-session start, bearer-bound/csi, and stop with a singleGET /csiresponse lifetime; and update mDNS consumers to usepath=/espectre/v1without aneventsTXT field. MQTT clients must use the retained resource topics and consolidatedupdate_device,update_sensing,recalibrate,read_diagnostics,check_ota, andstart_otacommands. - Detector identifiers, C++ names, and the metric scale changed without compatibility aliases. Replace
mvswithlightweight,mlwithhigh_accuracy,MVSDetectorwithLightweightDetector,MLDetectorwithHighAccuracyDetector, and the correspondingDetectionAlgorithm::MVS/MLvalues withLIGHTWEIGHT/HIGH_ACCURACY. Update movement and threshold integrations from the former0–10assumptions to the shared0.0–1.0probability scale. - The repository command wrapper is now
./espectre. Run MicroPython commands under./espectre micro, and runcollectandmqttfrom the repository root. Replace the formermicro-espectre/meui,detect,stream, and collection workflows with the browser tools, the MQTT client, or./espectre collectas appropriate. Raw collection now uses HTTP, and--ppscontrols the external generator. - ESPHome configuration now follows the temporal sampler. Replace
segmentation_window_size,evaluation_interval, andtraffic_generator_ratewithsegmentation_window_size_ms,evaluation_interval_ms, a positivecsi_target_pps, and an explicitcsi_traffic_mode. Dropsegmentation_threshold,gain_lock,selected_subcarriers, the configurable publish interval, and the legacy BLE channel settingsble_channel_enabled,ble_server_id,ble_control_char_id,ble_sysinfo_char_id,ble_telemetry_char_id, andble_telemetry_interval_ms. Use Improv Serial for USB provisioning. - Micro-ESPectre is now read-only at runtime. MQTT transport and commands, device-side High Accuracy deployment, and the UDP CSI streamer are removed. Flash the matching project firmware once, keep Wi-Fi settings in
config_local.py, usemicro deployfor.mpy -O3application updates, and monitor through Direct HTTP, SSE, or serial output. - Micro-ESPectre now uses
espectre-<device_id>.local. Update manually saved endpoints or rediscover the device; the formerespectre-micro-<suffix>.localhostname has no compatibility alias. Itsdeviceresource and mDNS TXT record now use the ESP-IDF application version and target chip. - The supported build baseline changed. ESPHome requires at least
2026.7.0, host and ML workflows require Python3.14, ESP-IDF integrations require ESP-IDF>= 5.5, and PlatformIO-backed builds are no longer supported. - Dataset metadata moved from format
1.0to1.2. Consumers of 2.8.0.npzcaptures must migrate to the versioned metadata schema. - C++ integrations must move to the supported SDK facade. Include
espectre_sdk.h, keep dependencies flowing from frontend to runtime to core, and update code that depends on the formercomponents/espectre/layout or namespace. - ESPHome examples and firmware names changed. Replace repository paths beginning with
examples/withsrc/cpp/frontend/esphome/examples/, including package URLs that reference an example YAML file. Full-flash images now useespectre-esphome-<channel-or-version>-<chip>.bin, and OTA images useespectre-esphome-<channel-or-version>-<chip>-ota.bin.
2.8.0 Detection hardening, ML cross-chip reliability, and runtime motion policy
- Hardened detection and calibration across stacks with tighter NBVI defaults, Hampel enabled by default, a 100-packet default window, and a clearer edge-driven motion policy.
- Improved ML reliability across chips with shared CV-normalized turbulence, a refreshed 9-feature model, and stricter training/data quality controls.
- Made
pingthe default CSI traffic source, added./me detectfor live ML inference, and expanded notebooks and CI/test coverage.
2.7.0 ESPectre configuration over BLE and subcarrier normalization
- Added BLE runtime control as a first-class standalone integration surface, including live threshold updates and a Web Bluetooth example client.
- Extended CSI normalization to
256->128,228->114, and114->128payload remaps, with aligned behavior and tests across C++ and Micro-ESPectre.
2.6.0 ESP32-C5 support, context-aware calibration, and stricter validation targets
- Added ESP32-C5 support and hardened runtime handling on newer chips (
C5/C6). - Aligned calibration, thresholds, dataset metadata, and ML feature selection more strictly across C++ and Micro-ESPectre.
- Tightened validation targets to
Recall >95%andFP <5%and improved the related tooling and deploy diagnostics.
2.5.1 HT STBC multi-antenna router fix
- Fixed HT STBC CSI handling on ESP32-C5/C6 with multi-antenna routers by accepting 256-byte packets and using the first HT20 estimate.
- Fixed Micro-ESPectre NBVI calibration memory issues on ESP32-C3, improved calibration speed, and refreshed performance/snapshot documentation.
2.5.0 ML detector, training pipeline, and pre-built firmware
- Added the first experimental ML detector in both ESPHome/C++ and Micro-ESPectre/Python, with a training and weight-export pipeline.
- Added pre-built firmware releases for all supported ESP32 variants.
- Removed the PCA detector and the older P95 calibrator, leaving MVS plus NBVI as the main non-ML path at the time.
2.4.0 Live recalibration, adaptive threshold, and PCA
- Added live recalibration, adaptive thresholds by default, and a choice between MVS and experimental PCA detection.
- Standardized the runtime around HT20 CSI, improved calibration/subcarrier handling, and expanded tooling, tests, and Micro-ESPectre support.
2.3.0 End-of-year edition
- Added
ESPectre - The Game, a browser-based motion-controlled tuning and demo client. - Added sensor customization, external traffic mode,
pingtraffic generation, and configurable gain-lock behavior. - Improved channel-change handling, NBVI calibration, and board support, including tested ESP32-C3 and original ESP32 paths.
2.2.0 Gain lock, low-pass filter, and ML data collection
- Added gain-lock stabilization, low-pass filtering, and baseline variance normalization to make calibration more stable.
- Tightened NBVI behavior, moved variance evaluation to publish time, and auto-configured the required ESP-IDF options in the ESPHome path.
- Added the first labeled ML data-collection infrastructure (
me collect,.npz, andcsi_utils.py) plus broader testing/documentation.
2.1.0 Made for ESPHome compliance
- Updated all example configs to meet "Made for ESPHome" requirements, including provisioning, dashboard import, and project metadata.
- Unified and optimized variance and Hampel behavior across C++ and MicroPython.
- Expanded the test suite and coverage pipeline substantially.
2.0.0 ESPHome native integration
- Migrated the platform from standalone ESP-IDF firmware to an ESPHome native integration for Home Assistant.
- Established the dual-platform model: ESPHome/C++ for production, and Micro-ESPectre/MicroPython for R&D and rapid experimentation.
- Moved tests and CI to the ESPHome-oriented workflow with host-side CMake/CTest coverage.
1.5.0 Automatic subcarrier selection
- Added zero-configuration subcarrier selection using the Normalized Baseline Variability Index (NBVI) algorithm.
- Calibrated automatically at boot and after
factory_reset. - Defined NBVI as
NBVI = 0.3 × (σ/μ²) + 0.7 × (σ/μ). - Achieved F1 97.6%, recall 95.3%, precision 100%, and FP 0%.
1.4.0 Major refactoring and technical debt reduction
- Extracted feature calculation into
csi_features.c/h, reducingcsi_processor.cby 50%. - Centralized defaults in
espectre.hand validation invalidation.h/c. - Replaced variance calculation with a numerically stable two-pass implementation.
- Increased the traffic generator maximum from 50 to 1000 pps, with a default of 100 pps.
- Migrated the CLI from Bash to Python for cross-platform use.
- Added
tools/web/espectre-theremin.htmlfor CSI sonification. - Removed the redundant
min_length,max_length, andk_factorsegmentation parameters.
1.3.0 ESP32-C6 platform support
- Added Wi-Fi 6 (
802.11ax) support and the corresponding CSI configuration. - Made
thresholdandwindow_sizeconfigurable at runtime through MQTT. - Added
tools/web/espectre-monitor.htmlfor real-time visualization. - Added CPU and RAM usage to the
statscommand. - Simplified the MQTT message format and removed segment tracking.
1.2.1 Wi-Fi optimization
- Applied ESP-IDF Wi-Fi practices by disabling power saving (
WIFI_PS_NONE), making the country code configurable, and setting HT20 bandwidth.
1.2.0 Simplified architecture and MVS segmentation
- Added Moving Variance Segmentation (MVS) with an adaptive threshold.
- Switched to amplitude-based features, improving separation for skewness and kurtosis by 151%.
- Replaced UDP broadcast traffic generation with ICMP ping.
- Used all 64 available subcarriers instead of filtering the set to 52.
- Added
temporal_delta_meanandtemporal_delta_variance, bringing the feature count to 10.
1.1.0 Automatic calibration system
- Used Fisher's criterion to select four to six features automatically from a set of eight.
- Applied a fourth-order Butterworth filter with an 8 Hz cutoff.
- Added a Daubechies
db4wavelet filter for high-noise environments. - Persisted configuration in NVS across reboots.
- Split the implementation into 10 specialized modules.
1.0.0 Initial release
- Added CSI-based movement detection for ESP32-S3 with Hampel and Savitzky-Golay filters, 15 features, four detection states (
IDLE,MICRO,DETECTED, andINTENSE), MQTT publishing, and a CLI tool. - Supported traffic rates from 10 to 100 pps, latency below 50 ms, and a range of 3 to 8 m.