You are using staging server - a separate instance of the ESP Component Registry that allows you to try distribution tools and processes without affecting the real registry.

francescopace/espectre

3.0.0-rc2-53-gbf4ad78.develop

Pre-release
uploaded 2 hours ago
ESPectre SDK for Wi-Fi motion detection on ESP32 devices.

Api

# ESPectre SDK C++ API

Version: `3.0.0-rc2-53-gbf4ad78.develop`

Source commit: `bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971`

[SDK guide](README.md)

## Contents

- [ESPectre SDK](#indexpage)
- [Deprecated List](#deprecated)
- [Integration details](#sdk_integration)
- [espectre](#namespaceespectre)
- [espectre::detail](#namespaceespectre_1_1detail)
- [espectre::task\_scheduling](#namespaceespectre_1_1task__scheduling)
- [espectre::BaseDetector](#classespectre_1_1_base_detector)
- [espectre::CsiTrafficService](#classespectre_1_1_csi_traffic_service)
- [espectre::CsiTrafficServiceConfig](#structespectre_1_1_csi_traffic_service_config)
- [espectre::DirectHttpServiceConfig](#structespectre_1_1_direct_http_service_config)
- [espectre::DirectHttpServiceDiagnostics](#structespectre_1_1_direct_http_service_diagnostics)
- [espectre::DirectRequest](#structespectre_1_1_direct_request)
- [espectre::DirectWifiSnapshot](#structespectre_1_1_direct_wifi_snapshot)
- [espectre::EspIdfDirectHttpService](#classespectre_1_1_esp_idf_direct_http_service)
- [espectre::EspIdfMqttTransport](#classespectre_1_1_esp_idf_mqtt_transport)
- [espectre::EspIdfPeerDiscoveryService](#classespectre_1_1_esp_idf_peer_discovery_service)
- [espectre::EspectreApiEventDescriptor](#structespectre_1_1_espectre_api_event_descriptor)
- [espectre::EspectreApiRoute](#structespectre_1_1_espectre_api_route)
- [espectre::EspectreCapabilityProfile](#structespectre_1_1_espectre_capability_profile)
- [espectre::EspectreCommand](#structespectre_1_1_espectre_command)
- [espectre::EspectreDeviceConfig](#structespectre_1_1_espectre_device_config)
- [espectre::EspectreDeviceInfo](#structespectre_1_1_espectre_device_info)
- [espectre::EspectreExtensionRoute](#structespectre_1_1_espectre_extension_route)
- [espectre::EspectreNetworkInfo](#structespectre_1_1_espectre_network_info)
- [espectre::EspectreProtocolExtension](#structespectre_1_1_espectre_protocol_extension)
- [espectre::FrontendCommandContext](#structespectre_1_1_frontend_command_context)
- [espectre::FrontendCommandEngine](#classespectre_1_1_frontend_command_engine)
- [espectre::FrontendCommandResult](#structespectre_1_1_frontend_command_result)
- [espectre::FrontendDeviceConfigDefaults](#structespectre_1_1_frontend_device_config_defaults)
- [espectre::FrontendHaDiagnosticSensor](#structespectre_1_1_frontend_ha_diagnostic_sensor)
- [espectre::FrontendHaDiscoveryMessage](#structespectre_1_1_frontend_ha_discovery_message)
- [espectre::FrontendHaMqttSettings](#structespectre_1_1_frontend_ha_mqtt_settings)
- [espectre::FrontendWifiStationOptions](#structespectre_1_1_frontend_wifi_station_options)
- [espectre::HighAccuracyDetector](#classespectre_1_1_high_accuracy_detector)
- [espectre::ICsiTrafficGenerator](#classespectre_1_1_i_csi_traffic_generator)
- [espectre::ICsiTrafficIngress](#classespectre_1_1_i_csi_traffic_ingress)
- [espectre::IDirectHttpService](#classespectre_1_1_i_direct_http_service)
- [espectre::IDirectHttpService::DeferredRequestResult](#structespectre_1_1_i_direct_http_service_1_1_deferred_request_result)
- [espectre::IMqttTransport](#classespectre_1_1_i_mqtt_transport)
- [espectre::IPeerDiscoveryService](#classespectre_1_1_i_peer_discovery_service)
- [espectre::IRuntimeListener](#classespectre_1_1_i_runtime_listener)
- [espectre::IUdpDatagramSocket](#classespectre_1_1_i_udp_datagram_socket)
- [espectre::JsonFieldView](#structespectre_1_1_json_field_view)
- [espectre::JsonInput](#classespectre_1_1_json_input)
- [espectre::JsonObjectField](#structespectre_1_1_json_object_field)
- [espectre::LightweightDetector](#classespectre_1_1_lightweight_detector)
- [espectre::LogSink](#structespectre_1_1_log_sink)
- [espectre::MdnsBootstrapResponder](#classespectre_1_1_mdns_bootstrap_responder)
- [espectre::MdnsDiscoveryService](#classespectre_1_1_mdns_discovery_service)
- [espectre::MdnsDiscoveryServiceConfig](#structespectre_1_1_mdns_discovery_service_config)
- [espectre::MqttPayloadAssembler](#classespectre_1_1_mqtt_payload_assembler)
- [espectre::MqttTransportDiagnostics](#structespectre_1_1_mqtt_transport_diagnostics)
- [espectre::NetworkTrafficSnapshot](#structespectre_1_1_network_traffic_snapshot)
- [espectre::PeerDiscoveryCandidate](#structespectre_1_1_peer_discovery_candidate)
- [espectre::PeerDiscoverySnapshot](#structespectre_1_1_peer_discovery_snapshot)
- [espectre::PendingEvent](#classespectre_1_1_pending_event)
- [espectre::PendingQueue](#classespectre_1_1_pending_queue)
- [espectre::RawCsiHttpFramePrefix](#structespectre_1_1_raw_csi_http_frame_prefix)
- [espectre::RawCsiPacketView](#structespectre_1_1_raw_csi_packet_view)
- [espectre::RawCsiRecordHeaderV8](#structespectre_1_1_raw_csi_record_header_v8)
- [espectre::RawCsiSessionConfig](#structespectre_1_1_raw_csi_session_config)
- [espectre::RawCsiSessionController](#classespectre_1_1_raw_csi_session_controller)
- [espectre::RawCsiSessionDiagnostics](#structespectre_1_1_raw_csi_session_diagnostics)
- [espectre::RuntimeCapabilities](#structespectre_1_1_runtime_capabilities)
- [espectre::RuntimeConfig](#structespectre_1_1_runtime_config)
- [espectre::RuntimeControlUpdate](#structespectre_1_1_runtime_control_update)
- [espectre::RuntimeDiagnosticsSample](#structespectre_1_1_runtime_diagnostics_sample)
- [espectre::RuntimeDiagnosticsSampler](#classespectre_1_1_runtime_diagnostics_sampler)
- [espectre::RuntimeDiagnosticsSnapshot](#structespectre_1_1_runtime_diagnostics_snapshot)
- [espectre::RuntimeDiagnosticsSnapshot::Csi](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi)
- [espectre::RuntimeDiagnosticsSnapshot::Link](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_link)
- [espectre::RuntimeDiagnosticsSnapshot::Performance](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance)
- [espectre::RuntimeDiagnosticsSnapshot::Platform](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform)
- [espectre::RuntimeDiagnosticsSnapshot::Traffic](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic)
- [espectre::RuntimeDirectHttpBridge](#classespectre_1_1_runtime_direct_http_bridge)
- [espectre::RuntimeDirectHttpBridgeConfig](#structespectre_1_1_runtime_direct_http_bridge_config)
- [espectre::RuntimeEventMailbox](#classespectre_1_1_runtime_event_mailbox)
- [espectre::RuntimeFrontendController](#classespectre_1_1_runtime_frontend_controller)
- [espectre::RuntimeSnapshot](#structespectre_1_1_runtime_snapshot)
- [espectre::StandaloneWifiAccessPoint](#structespectre_1_1_standalone_wifi_access_point)
- [espectre::StandaloneWifiConfig](#structespectre_1_1_standalone_wifi_config)
- [espectre::StandaloneWifiInfo](#structespectre_1_1_standalone_wifi_info)
- [espectre::StandaloneWifiService](#classespectre_1_1_standalone_wifi_service)
- [espectre::StoredWifiConfig](#structespectre_1_1_stored_wifi_config)
- [espectre::TemporalCsiSampler](#classespectre_1_1_temporal_csi_sampler)
- [espectre::TrafficGeneratorManager](#classespectre_1_1_traffic_generator_manager)
- [espectre::UdpDatagramPeer](#structespectre_1_1_udp_datagram_peer)
- [espectre::WiFiLifecycleManager](#classespectre_1_1_wi_fi_lifecycle_manager)
- [espectre::WifiBssidPinService](#classespectre_1_1_wifi_bssid_pin_service)
- [espectre::WifiBssidPinServiceConfig](#structespectre_1_1_wifi_bssid_pin_service_config)
- [espectre::WifiBssidPinStationState](#structespectre_1_1_wifi_bssid_pin_station_state)
- [espectre::WifiProvisioningDefaults](#structespectre_1_1_wifi_provisioning_defaults)
- [espectre::WifiProvisioningService](#classespectre_1_1_wifi_provisioning_service)
- [espectre::detail::PendingEventLock](#classespectre_1_1detail_1_1_pending_event_lock)
- [espectre\_diagnostic\_field\_t](#structespectre__diagnostic__field__t)
- [base\_detector.h](#base__detector_8h)
- [csi\_capture\_profile.h](#csi__capture__profile_8h)
- [csi\_format.h](#csi__format_8h)
- [csi\_raw\_record.h](#csi__raw__record_8h)
- [csi\_traffic\_service.h](#csi__traffic__service_8h)
- [csi\_types.h](#csi__types_8h)
- [detector\_limits.h](#detector__limits_8h)
- [detector\_types.h](#detector__types_8h)
- [device\_config\_store.h](#device__config__store_8h)
- [device\_identity.h](#device__identity_8h)
- [diagnostic\_fields.h](#diagnostic__fields_8h)
- [direct\_http\_protocol.h](#direct__http__protocol_8h)
- [direct\_http\_service.h](#direct__http__service_8h)
- [direct\_http\_service\_esp\_idf.h](#direct__http__service__esp__idf_8h)
- [direct\_wifi\_snapshot\_esp\_idf.h](#direct__wifi__snapshot__esp__idf_8h)
- [espectre\_banner.h](#espectre__banner_8h)
- [espectre\_core\_sdk.h](#espectre__core__sdk_8h)
- [espectre\_log.h](#espectre__log_8h)
- [espectre\_mqtt\_sdk.h](#espectre__mqtt__sdk_8h)
- [espectre\_protocol.h](#espectre__protocol_8h)
- [espectre\_protocol\_sdk.h](#espectre__protocol__sdk_8h)
- [espectre\_sdk.h](#espectre__sdk_8h)
- [espectre\_sdk\_version.h](#espectre__sdk__version_8h)
- [espectre\_services\_sdk.h](#espectre__services__sdk_8h)
- [filter\_config.h](#filter__config_8h)
- [frontend\_bootstrap\_helpers.h](#frontend__bootstrap__helpers_8h)
- [frontend\_command\_engine.h](#frontend__command__engine_8h)
- [frontend\_ha\_mqtt\_helpers.h](#frontend__ha__mqtt__helpers_8h)
- [frontend\_mqtt\_helpers.h](#frontend__mqtt__helpers_8h)
- [high\_accuracy\_detector.h](#high__accuracy__detector_8h)
- [lightweight\_detector.h](#lightweight__detector_8h)
- [mdns\_bootstrap\_responder.h](#mdns__bootstrap__responder_8h)
- [mdns\_discovery\_service.h](#mdns__discovery__service_8h)
- [mqtt\_payload\_assembler.h](#mqtt__payload__assembler_8h)
- [mqtt\_transport.h](#mqtt__transport_8h)
- [mqtt\_transport\_esp\_idf.h](#mqtt__transport__esp__idf_8h)
- [network\_traffic.h](#network__traffic_8h)
- [nvs\_helpers.h](#nvs__helpers_8h)
- [peer\_discovery.h](#peer__discovery_8h)
- [peer\_discovery\_service\_esp\_idf.h](#peer__discovery__service__esp__idf_8h)
- [pending\_event.h](#pending__event_8h)
- [pending\_queue.h](#pending__queue_8h)
- [protocol\_json.h](#protocol__json_8h)
- [raw\_csi.h](#raw__csi_8h)
- [raw\_csi\_session\_controller.h](#raw__csi__session__controller_8h)
- [runtime\_capabilities.h](#runtime__capabilities_8h)
- [runtime\_config.h](#runtime__config_8h)
- [runtime\_config\_utils.h](#runtime__config__utils_8h)
- [runtime\_diagnostics.h](#runtime__diagnostics_8h)
- [runtime\_diagnostics\_protocol.h](#runtime__diagnostics__protocol_8h)
- [runtime\_direct\_http\_bridge.h](#runtime__direct__http__bridge_8h)
- [runtime\_event\_mailbox.h](#runtime__event__mailbox_8h)
- [runtime\_events.h](#runtime__events_8h)
- [runtime\_frontend\_controller.h](#runtime__frontend__controller_8h)
- [runtime\_sensing\_kconfig.h](#runtime__sensing__kconfig_8h)
- [runtime\_sensing\_schema.h](#runtime__sensing__schema_8h)
- [runtime\_snapshot.h](#runtime__snapshot_8h)
- [runtime\_time.h](#runtime__time_8h)
- [standalone\_wifi\_service.h](#standalone__wifi__service_8h)
- [task\_scheduling\_config.h](#task__scheduling__config_8h)
- [temporal\_csi\_sampler.h](#temporal__csi__sampler_8h)
- [traffic\_generator\_manager.h](#traffic__generator__manager_8h)
- [udp\_datagram\_socket.h](#udp__datagram__socket_8h)
- [wifi\_band\_helpers.h](#wifi__band__helpers_8h)
- [wifi\_bssid\_pin\_service.h](#wifi__bssid__pin__service_8h)
- [wifi\_lifecycle.h](#wifi__lifecycle_8h)
- [wifi\_provisioning\_service.h](#wifi__provisioning__service_8h)


<a id="indexpage"></a>

## ESPectre SDK

  

This reference covers the supported integration surface only. Every declaration included in the reference follows the SDK version contract; implementation dependencies that merely ship in the bundle are internal and may change in any release.

 

Start with the [SDK README](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/SDK.md>) for installation and a minimal application. Use [espectre\_sdk.h](#espectre__sdk_8h) for the sensing runtime, [espectre\_core\_sdk.h](#espectre__core__sdk_8h) for custom capture pipelines, [espectre\_protocol\_sdk.h](#espectre__protocol__sdk_8h) for the ESPectre Protocol and its transports, [espectre\_services\_sdk.h](#espectre__services__sdk_8h) for optional services, and [espectre\_mqtt\_sdk.h](#espectre__mqtt__sdk_8h) for the ESP-IDF MQTT implementation.

 

[Integration details](#sdk_integration) documents lifecycle, threading, source compatibility, and advanced integration contracts for this version of the SDK.

 

<a id="deprecated"></a>

## Deprecated List

  

Member [espectre::espectre\_device\_id\_from\_mac](#namespaceespectre_1adc03ef2a0c49d818c944747283819e1a) (const uint8\_t \*mac, size\_t mac\_len)

 

<a id="deprecated_1_deprecated000001"></a>

Runtime firmware uses the cached, domain-separated SHA-256 pseudonym from [`derive_runtime_device_id()`](#namespaceespectre_1a34031a60d78bbb6306047b3540b4f905) instead.

 

Member [espectre::ESPECTRE\_DIRECT\_MAX\_METHOD\_SIZE](#namespaceespectre_1a53e26f01271bcce51eabeb7f765385a1)

 

<a id="deprecated_1_deprecated000003"></a>

Command names are validated by the canonical registry.

 

Member [espectre::ESPECTRE\_DIRECT\_MAX\_REQUEST\_ID\_SIZE](#namespaceespectre_1a90f09ac217de8fc9fe33fa72d0dca455)

 

<a id="deprecated_1_deprecated000002"></a>

Use [`ESPECTRE_COMMAND_ID_MAX_LENGTH`](#namespaceespectre_1aa9bcecab1d67487af0b736b8637b6138); Direct uses the canonical limit.

 

<a id="sdk_integration"></a>

## Integration details

 

This guide covers the lifecycle, ownership, and compatibility contracts for the SDK sources identified by this reference.

  

Start with the [SDK README](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/SDK.md>) for installation and a minimal application.

 

<a id="sdk_integration_1integration_logging"></a>

### Logging



All SDK facades expose the portable logging contract in [`core/espectre_log.h`](#espectre__log_8h). ESPectre does not install a sink or fall back to `stdio`, so integrations that do not need logs have no logger dependency and do not evaluate filtered log arguments. To receive shared logs, register a complete `LogSink` before runtime setup:



```cpp
espectre::LogSink sink{
    product_context,
    &product_log_enabled,
    &product_log_write,
};
if (!espectre::set_log_sink(sink)) {
  return false;
}
```



The `enabled` callback decides whether a level and tag should be formatted. The `write` callback receives the level, tag, source line, format string, and a `va_list` that remains valid only for that call. ESPectre copies the callback value but does not own its context. Keep the context alive until `clear_log_sink()`, and register, replace, or clear the sink only while no runtime is active. Callbacks may arrive from the runtime owner task, ESP-IDF service tasks, or CSI capture paths, so they must be thread-safe, bounded, non-blocking, and must not call the ESPectre logger recursively.



For ESP-IDF Log v2, your sink can pass the callback's `va_list` to `esp_log_va`. ESP-IDF adds the standard level, timestamp, tag, and line ending. The included example shows how to register this adapter; declare the `log` dependency in your application component.

 

<a id="sdk_integration_1integration_supported_hardware"></a>

### Supported hardware



The targets listed in [Requirements](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/SDK.md#requirements>) use standard single-antenna Wi-Fi CSI with AGC active and 20 MHz bandwidth. No extra sensors or radio hardware are required.



Set `RuntimeConfig::wifi_band_policy` to choose `BAND_2G`, `BAND_5G`, or `AUTO`. Both a directly constructed `RuntimeConfig` and the Kconfig default use `AUTO`, which uses every band the radio has: automatic 2.4/5 GHz selection on ESP32-C5, and 2.4 GHz on single-band targets. The runtime applies the selected policy and pins 20 MHz bandwidth on the active band or bands. Unsupported policies fail setup instead of falling back silently, and packets outside the selected capture profile are dropped and counted.



Set `RuntimeConfig::csi_capture_policy` before setup to choose `CsiCapturePolicy::AUTO`, `LLTF`, or `HT_VHT`. `AUTO` uses LLTF20 for internal `wifi_raw`, VHT20 on a supported 5 GHz link, and HT20 otherwise, including on ESP32 and ESP32-S2. `LLTF` always selects LLTF20; `HT_VHT` selects VHT20 on a supported 5 GHz link and HT20 otherwise. All three policies work with automatic band selection on ESP32-C5. `wifi_raw` requires `AUTO` or `LLTF`. There is no runtime profile setter or persisted profile override. The canonical `device` resource reports the effective profile as the read-only `csi_profile`. [CSI.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/CSI.md#capture-profiles>) describes capture behavior and normalization.

 

<a id="sdk_integration_1integration_runtime_contract"></a>

### Runtime contract



These sections describe how the full runtime behaves once your firmware owns a `RuntimeFrontendController`.



<a id="sdk_integration_1integration_threading"></a>

#### Threading



The control surface is single-owner. Internal bounded mailboxes protect callback-to-loop handoff, but they do not make control calls thread-safe.



- Run `setup()`, `loop()`, and `shutdown()` on one task.

- Every `IRuntimeListener` callback is delivered on the caller's task: from `loop()` for sensing events, or inline on the task that invoked a control method. Work raised in the Wi-Fi CSI callback is deferred through an internal mailbox first, so no listener callback runs in interrupt or Wi-Fi driver context.

- Keep callbacks bounded and non-blocking. A slow callback delays the next `loop()` iteration; sufficiently long work can fill the bounded CSI mailbox and drop incoming frames. Queue network publication, NVS writes, and other potentially blocking work for a separate task.

- Call the controller setters only from the owner task. Queue commands received by network callbacks and apply them from that task's loop.

- Raw CSI packet callbacks are the deliberate exception: they run synchronously in the Wi-Fi CSI capture context. Keep them bounded, non-blocking, and allocation-free, and copy accepted samples into a preallocated bounded queue when another task must process them. Returning false reports a caller-owned drop or backpressure event; it does not stop collection.



Stopping raw collection synchronizes with any packet callback already in progress before releasing its context. The caller can reclaim that context after `stop_raw_collection()` succeeds. Raw callbacks must follow the owner-task rule for runtime controls; they must not stop collection themselves.



<a id="sdk_integration_1integration_advanced_task_scheduling"></a>

#### Advanced task scheduling



Full-runtime ESP-IDF integrations expose ESPectre-owned FreeRTOS priorities under the `Advanced task scheduling` menu. These settings are compile-time policies, not runtime controls. Values range from `1` to `10`; higher-priority tasks preempt lower-priority work. Change them only with workload-specific validation because an unsuitable priority can starve sensing, Direct delivery, managed traffic, or system networking. ESP-IDF continues to own the internal Wi-Fi and lwIP task priorities.



The shared runtime defines these priorities:



| Kconfig option | Default | Owner |
| --- | --- | --- |
| [`CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITY`](#task__scheduling__config_8h_1a1c07ae2423b6566d454316bfd9a8dcfa) | `1` | Direct HTTP server |
| [`CONFIG_ESPECTRE_DIRECT_WORKER_TASK_PRIORITY`](#task__scheduling__config_8h_1ab21ce3fdcc4837c2a0aecb8b3b58ca04) | `2` | Direct control responses and SSE delivery |
| [`CONFIG_ESPECTRE_RAW_WORKER_TASK_PRIORITY`](#task__scheduling__config_8h_1ac541f938b4a9aee9eb3e7edc08296acd) | `3` | Raw CSI HTTP delivery |
| [`CONFIG_ESPECTRE_TRAFFIC_TASK_PRIORITY`](#task__scheduling__config_8h_1a89bc52af94882fc610139f6ac25a80c8) | `1` | Managed PING or DNS traffic |



Your application owns the task that calls `RuntimeFrontendController::loop()`. Select its priority as part of your scheduling policy; the SDK's task settings do not set that priority.



The Direct HTTP server defaults to priority `1` on every target. Custom integrations can override it after workload-specific validation. Existing `sdkconfig` files retain explicitly saved priorities; set [`CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITY=1`](#task__scheduling__config_8h_1a1c07ae2423b6566d454316bfd9a8dcfa) to adopt the shared default in those builds.



<a id="sdk_integration_1integration_raw_csi_storage"></a>

#### Raw CSI storage



`prepare_ht20_detector_input` prepares a private centered buffer after the raw branch: it handles both LLTF edge tones and hardware-invalid classic +1, using explicit source metadata. `impute_ht20_lltf_detector_bins` is an older wrapper that handles only the LLTF edge tones. See [CSI.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/CSI.md#detector-input-and-raw-collection>) for the shared preparation policy.



The built-in capture pipeline normalizes LLTF, HT, and VHT samples to `HT20_CSI_LEN`: 128 bytes containing 64 complex subcarriers. `RawCsiPacketView` exposes this normalized view. Size capture queues for the normalized payload. `RAW_CSI_MAX_PAYLOAD_BYTES` defines the separate 512-byte payload limit for stored and transmitted records.



`EspIdfDirectHttpService` uses a 16-slot raw queue with 128 payload bytes per slot and sends records in batches of up to four. It allocates raw buffers when a session starts and releases them when it stops.



The queue can overflow during a stalled send, regardless of each slot's payload capacity. Inspect `raw_csi.raw_drop_total` separately from capture-quality rejections; see [CSI.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/CSI.md#capture-quality>).



<a id="sdk_integration_1integration_lifecycle"></a>

#### Lifecycle



`set_config()` -&gt; `setup(listener)` -&gt; `loop()` repeatedly -&gt; `shutdown()`. Create the default station interface and ESP event loop before `setup()`. Prefer setup before association so the CSI radio policy is applied at `WIFI_EVENT_STA_START`; setup after association is also supported and restores the station's current IPv4 state. The controller is reusable after `shutdown()`: the configuration survives and `set_config()` becomes effective again. `setup()` is idempotent, and a failed `setup()` leaves the controller un-setup so you can fix the config and retry.



By default the runtime remembers live control changes across reboots. `setup()` restores the traffic generator mode and motion hits saved in NVS, plus the detector when `RuntimeConfig::runtime_detector_selection_enabled` is set, and each controller setter saves its new value. The threshold is never saved. The runtime logs at INFO each saved value that differs from the config. Set `RuntimeConfig::persist_runtime_overrides` to false when your firmware owns configuration, for example from YAML or a cloud service: the config you pass is then the only source of truth, and the runtime neither reads nor writes saved controls.



The ESP-IDF runtime starts capture, traffic, and calibration immediately after connection or rearming. It observes startup traffic and attempts a receive-path refresh only if traffic continues for one second without any CSI callback. One second without observed traffic progress resets that observation. A callback suppresses recovery even when the packet is rejected by the detector; an absent or stopped external sender does not trigger recovery. This startup check is not a continuous watchdog for later traffic loss.



Recovery uses at most one asynchronous scan per sensing activation. Busy scan or connection state, or unconsumed scan results, defer the request in 500-ms intervals within a 15-second observation window. An accepted scan has a 30-second timeout. Success, failure, and timeout resume capture without repeating recovery in that activation. Disconnection, shutdown, and disarming cancel pending recovery; raw collection is not interrupted by it. Keep calling `loop()` throughout recovery.



The SDK reserves its scanner across recovery and result cleanup; `StandaloneWifiService::request_scan()` refuses overlapping requests. By default, the runtime releases its remaining scan results on the next loop turn after completion. Independent scanners must wait until `WiFiLifecycleManager::csi_receive_path_refresh_active()` becomes false before starting a scan. An idle driver does not prove result ownership: a subsequent scan can finish while its completion event is still queued.



For Wi-Fi stacks that scan autonomously and consume scan results, set `RuntimeConfig::wifi_scan_results_managed_externally` before setup. The runtime then leaves the driver result list to the Wi-Fi stack on completion, cancellation, and timeout, so delayed cleanup cannot erase a subsequent scan's results. The Wi-Fi stack is responsible for consuming or releasing recovery scan results, including partial results from failed scans. Independent calls to ESP-IDF scan APIs must still be serialized with the recovery request; the driver's busy check cannot atomically reserve the radio against another task starting a scan.



Register an optional `LogSink` before `setup()`. Do not replace or clear it until every runtime and callback source using it has shut down.



High Accuracy preserves the configured or live threshold when sensing starts, Wi-Fi reconnects, or raw collection ends. Explicit recalibration and switching detectors restore the detector's default threshold. Lightweight continues to derive its threshold through startup calibration.



Every calibration guards itself against motion. An evaluation above `BaseDetector::calibration_motion_ceiling()` restarts the calibration window and returns `calibration_packets` to zero. A recalibration on the channel, capture profile, and traffic generator mode of the last successful calibration also restarts above the live threshold when it is lower. If no full window fits within three calibration budgets, the calibration ends with `on_calibration_finished(snapshot, false)` and the threshold in force stays; after a rejected startup calibration, that is the configured threshold.



A calibration spends at least its base packet budget. While `BaseDetector::startup_calibration_conclusive()` returns false once the budget is spent, the calibration continues in steps of half that budget, up to three budgets, and `calibration_target_packets` grows with each step. Lightweight's rules and bounds are in [startup threshold calibration](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/ALGORITHMS.md#startup-threshold-calibration>).



`RuntimeSnapshot::ready_to_publish` clears at once while calibrating, when sensing services or the link stop, when the newest detector input is one detector window old, and while the window refills after a history reset. Temporal admission leaves some slots empty even at the nominal packet rate, so window coverage can briefly fall under the detector's valid-slot floor while input keeps arriving. Once sensing is ready, such a dip clears readiness only if it lasts one detector window; shorter dips never reach `on_sensing_readiness_changed()` or `snapshot()`. The runtime logs every readiness transition with its reason.



See [ALGORITHMS.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/ALGORITHMS.md#motion-hit-filtering>) for how evaluation cadence and hit filtering determine publish delay.



<a id="sdk_integration_1integration_errors"></a>

#### Errors



The control surface reports failure through `bool` returns and never throws. Runtime-backend, temporal-sampler, and detector storage allocations are non-throwing; an allocation failure makes `setup()` return false and reports the fault synchronously to the listener. A `false` means the call was rejected or could not be applied, and the runtime is unchanged. A call returns false for one of these reasons:



1. The value is outside the range published in [`runtime_sensing_schema.h`](#runtime__sensing__schema_8h).

2. The active runtime does not advertise the matching capability.

3. The runtime is not in a state that allows the call: for example, recalibration before `setup()` or while a calibration or raw collection is active, or raw collection without a Wi-Fi link.

4. The backend refused the change.

5. `setup()` could not allocate the runtime's bounded working storage.



Each method's documentation lists the cases that apply to it.



Asynchronous failures arrive instead through `IRuntimeListener::on_runtime_fault()`. Calibration outcome is reported by `on_calibration_finished(snapshot, success)`; a `false` there is not fatal, the runtime keeps sensing with the threshold that was in force before the calibration.



<a id="sdk_integration_1integration_capabilities"></a>

#### Capabilities



`RuntimeCapabilities` defaults every flag to false, so a runtime declares what it offers rather than inheriting a permissive default. Read `controller.capabilities()` after `setup()` and expose only what it advertises. The controller already refuses capability-gated calls; this check keeps unsupported controls out of the product interface.



<a id="sdk_integration_1integration_diagnostics"></a>

#### Diagnostics



Read `RuntimeFrontendController::diagnostics_sample()` for diagnostics. It returns the runtime's shared one-second `RuntimeDiagnosticsSample`: traffic and CSI rates plus the current link. Read the same sample across your transport adapters so their observation windows agree. It is `nullptr` before `setup()`.



`RuntimeDiagnosticsSample::csi_admitted_pps` is the detector input rate after temporal admission. `csi_accepted_pps` is the rate accepted by capture validation, before admission. Compare admitted PPS with `RuntimeConfig::csi_target_pps` together with `csi_occupancy_ratio`, callback-queue overflow, same-slot excess, missing-slot, stale, and out-of-order rates when a deployment underperforms. Occupancy is diagnostic telemetry and does not change the device send rate. [API.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/API.md#diagnostics>) owns the corresponding wire field names, units, and optionality.



<a id="sdk_integration_1integration_diagnostics_advanced"></a>

##### Advanced: cumulative counters



`RuntimeFrontendController::diagnostics()` returns the cumulative `RuntimeDiagnosticsSnapshot` behind the sample, grouped as `link`, `traffic`, `csi`, `platform`, and `performance`. The `csi` group also carries the callback queue's drop counter, occupancy, and capacity. Use it when you need totals, or a sampling interval other than one second. `RuntimeDiagnosticsSampler` turns two reads into rates without requiring a separate timer:



```cpp
// once, after runtime_.setup() succeeds
sampler_.reset(runtime_.diagnostics(), now_ms);

// whenever the existing periodic sensing callback runs
latest_ = sampler_.sample(runtime_.diagnostics(), now_ms);
```



The ESP-IDF runtime always collects these counters and bounded performance windows. `RuntimeDiagnosticsSnapshot` also reports heap and CPU frequency in `platform`, loop load and detector timing in `performance`, and CSI provenance rejection in `csi`. [API.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/API.md#diagnostics>) defines their transport representation.



<a id="sdk_integration_1integration_performance_sampling"></a>

#### Performance sampling



The runtime aggregates loop load and timing plus sampled detector evaluation timing in bounded 10-second windows. `RuntimeDiagnosticsSnapshot::performance` holds the latest complete window, and `platform` holds current, minimum, and largest-block heap values and configured CPU frequency. Collection is unconditional and does not emit a periodic debug log.



`performance.runtime_load_percent` measures wall time spent inside the ESPectre runtime loop, not whole-system CPU utilization. Wi-Fi callbacks only normalize and enqueue CSI; detector processing, inference, state transitions, and listener callback delivery run in the owning loop task. Transport work on private tasks is outside this measurement. Detector timing is sampled on an evaluation tick after approximately 1,000 detector packets. For High Accuracy, it covers ML feature extraction, inference, and state update.

 

<a id="sdk_integration_1integration_transport_adapters"></a>

### Transport adapters



SDK transport adapters should pass parsed requests through `FrontendCommandEngine` and preserve the canonical distinction between requester-scoped query results and state changes published to active transports. [API.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/API.md#contract-principles>) owns the message fields and cross-transport semantics; [ARCHITECTURE.md](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/ARCHITECTURE.md#shared-protocol-and-transport-services>) owns command-engine and adapter placement. Pass `RuntimeFrontendController::validate_control_update()` as the engine's sensing preflight, so an `update_sensing` request applies completely or not at all.



`RuntimeDirectHttpBridgeConfig::loop_time_ms_getter` optionally supplies the latest complete application loop duration in milliseconds. Measure the loop body that calls the runtime and processes application events; exclude work on other tasks and time between loop calls. If you omit the callback, selecting `loop_time_ms` returns `null`. This measurement is independent of the runtime performance-window average exposed as `loop_avg_us`.



The shared Direct service owns HTTP request lifetime, SSE delivery, deferred responses, and the owner-bound raw CSI session used by ESPectre. The ESP-IDF implementation assigns an opaque monotonically increasing token to each live connection, removes inbound work by token rather than file descriptor, and completes deferred work only while that token still identifies the originating client. The default interface implementation reports deferred delivery as unsupported, preserving source compatibility for transports that implement only synchronous requests.

 

<a id="sdk_integration_1integration_protocol_extensions"></a>

### Protocol extensions



All command parameters use `EspectreCommandValidator`: the parser checks JSON syntax and request structure, then invokes the callback registered on the SDK or application route. The callback receives decoded `JsonObjectField` values, validates parameters, and fills the command before dispatch. It must not change device state. For extension commands, `extension_parameters` initially contains the whole request from `parse_espectre_command()`, or the parameter object from `parse_espectre_command_request()`; the validator may replace it with normalized JSON built from the decoded fields. The SDK validator checks parameter types and ranges, including thresholds in `0–1` and motion hit counts in `1–20`.



`FrontendCommandEngine::execute()` and application extension handlers require a successfully parsed command. They check capabilities and operational state without repeating parameter validation. Direct runtime and service APIs retain their own argument checks because integrators can call them without a protocol parser.



`EspectreCapabilityProfile::extension` accepts an optional `EspectreProtocolExtension` supplied by your application. Each route declares its HTTP method and path, resource or operation name, command name, asynchronous behavior, MQTT availability, raw-collection policy, and parameter validator. The extension also lists its event names. `validate_protocol_extension()` rejects invalid descriptors and collisions with SDK routes, command names, resources, or events.



Use the same immutable catalog for capability output, `DirectHttpServiceConfig::protocol_extension`, `direct_http_request_to_command()`, and `parse_espectre_command()`. Keep it alive while the adapters use it. Direct and MQTT then validate parameters through the same callback, and an unregistered extension command is rejected. Your application enforces each route's MQTT availability, implements its commands, and publishes extension events through the normal transports. Advertise only extensions your application has enabled.



Your application owns firmware updates. You can use protocol extensions to expose its update commands while keeping the update mechanism and release policy in your application.



`RuntimeFrontendController::quiesce()` is a generic suspension operation: it disables telemetry and sensing services and stops active raw collection while retaining the configured backend. The caller restores its desired service and telemetry gates when resuming. It is useful before a firmware update or another temporary activity that needs CSI and sensing traffic to stop.

 

<a id="sdk_integration_1integration_versioning"></a>

### Versioning



Supply your application version explicitly through `EspectreDeviceInfo::firmware_version` and discovery or provisioning configuration. The SDK does not read the ESP-IDF application descriptor to determine it.



[`ESPECTRE_SDK_VERSION_STRING`](#espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74) identifies the SDK sources you compiled against. Use the component-wise [`ESPECTRE_SDK_VERSION_AT_LEAST(major, minor, patch)`](#espectre__sdk__version_8h_1a84f438434c7a7b020e175e84ae3ca6e8) to guard code that needs a given release. [`ESPECTRE_SDK_VERSION_NUMBER`](#espectre__sdk__version_8h_1addabd247bcb8243d35a37657c029571b) retains the historical `MMmmpp` packing for compatibility and compact telemetry, but it is not an ordering contract because Semantic Versioning components are not limited to two digits.



ESPectre uses Semantic Versioning for the published C++ source API:



- Patch releases preserve source compatibility and documented lifecycle, validation, ownership, threading, capability, and error semantics. Detector coefficients and generated model weights may change when validation gates demonstrate a compatible quality fix; exact floating-point telemetry is not a compatibility guarantee.

- Minor releases may append fields, add callbacks with default implementations, and add types, functions, or overloads. Existing calls keep their meaning, closed enums do not gain values, and removals require a prior deprecation in a released minor version.

- Major releases may remove deprecated APIs or otherwise break source compatibility, with migration notes in `CHANGELOG.md`.

- Prerelease and rolling `preview` or `develop` bundles may change before the corresponding final release. The compatibility promise begins at the final numeric release.



The SDK is distributed and consumed as source. It does not promise a stable binary ABI: rebuild the SDK and integration together with the same C++ standard library and ESP-IDF toolchain. Construct public configuration and snapshot structs with their defaults, then assign named fields as shown in this guide; positional aggregate initialization is outside the compatibility contract so new fields can be appended safely.



Everything reachable from [`espectre_sdk.h`](#espectre__sdk_8h) belongs to the stable runtime surface. The protocol contracts in [`espectre_protocol_sdk.h`](#espectre__protocol__sdk_8h) follow the same source-compatibility rules, and so do the public methods and configuration types that [`espectre_services_sdk.h`](#espectre__services__sdk_8h) and [`espectre_mqtt_sdk.h`](#espectre__mqtt__sdk_8h) expose for optional ESP-IDF services. [`espectre_core_sdk.h`](#espectre__core__sdk_8h) is a separate opt-in for custom capture pipelines. Its detector classes and documented public methods follow the same rules. Feature trackers, generated weights, and headers included only as implementation dependencies are not independent extension points.



The SDK reads its identity only from [`runtime/espectre_sdk_version.h`](#espectre__sdk__version_8h) and explicit compiler definitions. It does not inspect Git, source refs, environment variables, or the application version. Published SDK bundles stamp the release identity into that header and `idf_component.yml`; the CI packaging tools determine the identity before producing the bundle.



Integrators can stamp the same header or override all four macros together: [`ESPECTRE_SDK_VERSION_STRING`](#espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74), [`ESPECTRE_SDK_VERSION_MAJOR`](#espectre__sdk__version_8h_1a1c56ebb77dae087ea795df71afe1b36a), [`ESPECTRE_SDK_VERSION_MINOR`](#espectre__sdk__version_8h_1ab49f9a44dcd3be82d3b3e742d9334c23), and [`ESPECTRE_SDK_VERSION_PATCH`](#espectre__sdk__version_8h_1a74f3ae0b42f726bf3302abae42655339). A complete compiler override takes precedence over the packaged values. The string and numeric components must describe the same SDK release, and definitions must be consistent across the SDK and its consumers.



Without a complete identity, the SDK uses `"0.0.0"` and zero for all numeric version components. Incomplete overrides also fall back to these values rather than mixing metadata from different sources or failing compilation. `espectre_sdk_version()` always returns a non-null string; `"0.0.0"` means the SDK version is unknown, and version guards for newer releases evaluate to false. A source checkout without stamped metadata therefore reports `"0.0.0"`, even if it has Git tags.



The SDK manifest exposes the packaged identity once as `version`; `release_tag` names the GitHub release that carries the assets and may differ for rolling channels. Rolling GitHub tags remain `snapshot` for `preview` and `snapshot-dev` for `develop`. SDK identity is separate from the application version supplied by the integrator and `ESPECTRE_PROTOCOL_VERSION`, which versions the wire format.

 

<a id="sdk_integration_1integration_advanced_integrations"></a>

### Advanced integrations



The core-only path and source-list builds let an application supply more of the capture and build infrastructure.



<a id="sdk_integration_1integration_core_only"></a>

#### Core-only



If your firmware already owns Wi-Fi and CSI capture, include [`espectre_core_sdk.h`](#espectre__core__sdk_8h) and consume the detectors directly. The `core` detectors accept normalized CSI payloads and expose motion state, movement metric, and threshold control. The same facade exposes `TemporalCsiSampler`, which applies the production fixed-grid admission before `process_packet()`.



Detector and sampler working buffers use non-throwing allocation. Check `detector.is_valid()` after construction and the result of `sampler.configure(...)` before starting a custom pipeline; a false result means the requested bounded storage was unavailable. These objects are movable and intentionally non-copyable because their buffers own live temporal state.



The sampler tracks timing and slots; your integration stores the selected CSI payload. Handle each input in this order:



1. Call `admit()` before replacing the stored payload.

2. If `admit()` returns `true`, consume the stored payload: clear detector history when `reset_required()` is true, call `advance_missing_slots(missing_slots_before())`, and then call `process_packet()`.

3. If `gap_reset_required()` is true, clear detector history again before admitting post-gap data.

4. If `selected_current()` is true, replace the stored payload with the current normalized CSI.



At the end of a finite stream, call `flush()` and consume the stored payload if it returns `true`.



After each `update_state()`, re-read `get_threshold()`: Lightweight can lower it without a setter call, and the core-only path has no `on_threshold_changed()` hook. The sampler owns admission only; use `runtime/esp_idf/csi_pipeline.cpp` as the reference for CSI normalization, evaluation cadence, and hit filtering before committing to custom wiring.



A core-only integration owns the same two-view boundary between raw and detector input. Normalize the payload into the centered HT20 convention. For LLTF captures, call `zero_ht20_lltf_missing_bins()` on the raw view. Then copy the payload into a private detector buffer and call `prepare_ht20_detector_input()` only on that copy, passing the capture profile and the source metadata.



<a id="sdk_integration_1integration_build_integration"></a>

#### Build integration



Component Manager configures the registered component automatically. The following alternatives apply when you vendor SDK sources or maintain your own CMake target. Set the SDK root to the directory containing `espectre_sources.cmake`: the root of the registry archive, or `src/cpp/` in a GitHub/web bundle.



- **Core-only CMake**: include `espectre_sources.cmake` from the SDK root, compile `ESPECTRE_CORE_SOURCES`, and add `ESPECTRE_SHARED_INCLUDE_DIRS`. No ESP-IDF runtime sources are required.

- **Full-runtime CMake / ESP-IDF**: compile `ESPECTRE_CORE_SOURCES` and `ESPECTRE_RUNTIME_ESP_IDF_SOURCES`, then add `ESPECTRE_RUNTIME_FRONTEND_SUPPORT_SOURCES` or the per-capability Direct HTTP, MQTT, and provisioning lists only when the integration uses them. Add `ESPECTRE_SHARED_INCLUDE_DIRS` and the dependencies listed under [Optional capability groups](<https://github.com/francescopace/espectre/blob/bf4ad78f6e7ddaa2426bac13ab3db2ab49fe5971/docs/SDK.md#optional-capability-groups>).

- **Vendored ESP-IDF component**: copy the SDK root to your project's `components/espectre/` directory and add [`espectre`](#namespaceespectre) to your own component's `REQUIRES`. The sensing runtime is always built; the optional groups are opt-in under the "ESPectre SDK" menuconfig menu.

- **Toolchain**: C++17, ESP-IDF `>=5.5.3` for the `runtime/esp_idf` services. Repository builds use ESP-IDF `5.5.5`.



Source-list integrations and vendored ESP-IDF components use the version header directly; no version resolution step is required. For a GitHub/web SDK bundle extracted into `espectre/`, a complete core-only target is:



```cpp
set(ESPECTRE_CPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/espectre/src/cpp")
include("${ESPECTRE_CPP_ROOT}/espectre_sources.cmake")
add_library(espectre_core STATIC ${ESPECTRE_CORE_SOURCES})
target_compile_features(espectre_core PUBLIC cxx_std_17)
target_include_directories(espectre_core PUBLIC ${ESPECTRE_SHARED_INCLUDE_DIRS})
```



Link the application target to `espectre_core` to inherit the includes and C++ standard. Adjust `ESPECTRE_CPP_ROOT` to the SDK's location. If overriding the packaged SDK identity, apply all four version macros with `target_compile_definitions(espectre_core PUBLIC ...)` so consumers inherit them. The same approach works for a full-runtime source-list target.



The shared component does not require ESP-IDF's `log` component. A product that registers an `esp_log` adapter declares that dependency in its application component.



`ESPECTRE_SHARED_INCLUDE_DIRS` contains only the SDK root. Include the facades by name and any other SDK header by its layer-prefixed path, such as [`#include "runtime/runtime_config.h"`](#runtime__config_8h). SDK sources use the same form, so the layer directories stay off your search path: generic SDK basenames such as `utils.h` and `filters.h` cannot collide with headers of your own in either direction.

 

<a id="sdk_integration_1integration_published_sdk_channels"></a>

### Published SDK channels



The GitHub/web SDK bundles provide source archives for vendoring and evaluation. They use the repository-style layout below, separately from the registry component, and follow the firmware release channels:



| Channel | Source | Intended use |
| --- | --- | --- |
| `release` | latest tagged semver GitHub Release and `https://espectre.dev/artifacts/sdk/release/` | Final numeric versions are production candidates; prerelease tags are published explicitly as evaluation builds |
| `preview` | rolling `snapshot` GitHub prerelease and `https://espectre.dev/artifacts/sdk/preview/` | Validate `main` before the next release |
| `develop` | rolling `snapshot-dev` GitHub prerelease and `https://espectre.dev/artifacts/sdk/develop/` | Pre-main validation from `develop` |



Rolling releases publish `sdk-manifest-preview.json` and `sdk-manifest-develop.json`; the manifest filename follows the channel, while `release_tag` retains the GitHub tag shown above. Tagged releases publish `sdk-manifest-<release-tag>.json`.



Each GitHub/web SDK bundle includes:



- `docs/SDK.md`

- [`src/cpp/espectre_sdk.h`](#espectre__sdk_8h)

- [`src/cpp/espectre_core_sdk.h`](#espectre__core__sdk_8h)

- [`src/cpp/espectre_services_sdk.h`](#espectre__services__sdk_8h)

- [`src/cpp/espectre_mqtt_sdk.h`](#espectre__mqtt__sdk_8h)

- [`src/cpp/espectre_protocol_sdk.h`](#espectre__protocol__sdk_8h)

- `src/cpp/core/`

- `src/cpp/runtime/`

- `src/cpp/runtime/esp_idf/espectre_config/`

- `src/cpp/espectre_sources.cmake`

- `src/cpp/CMakeLists.txt`

- `src/cpp/idf_component.yml`

- `src/cpp/Kconfig.projbuild`

- `src/cpp/Doxyfile`

- `src/cpp/sdk_integration.dox`

- generated `src/cpp/core/ml_weights.h`

- `LICENSE`, `LICENSING.md`, and `THIRD_PARTY_NOTICES.md`



The published bundle is a versioned C++ source SDK with stamped packaging metadata, ready to vendor or unpack into your firmware tree. ESPectre is compiled together with the product firmware; the bundle does not include chip-specific precompiled libraries or promise binary ABI compatibility. In the bundled copy of this guide, repository-relative links point to GitHub URLs pinned to the commit or release tag used for that package. The `.tar.gz` and `.zip` archives are generated deterministically from the source commit timestamp, and the SDK manifest records a SHA-256 digest for each archive so consumers can verify downloaded bytes.

 

<a id="namespaceespectre"></a>

## espectre

  [`espectre::BaseDetector`](#classespectre_1_1_base_detector)

[`espectre::CsiTrafficService`](#classespectre_1_1_csi_traffic_service)

[`espectre::CsiTrafficServiceConfig`](#structespectre_1_1_csi_traffic_service_config)

[`espectre::DirectHttpServiceConfig`](#structespectre_1_1_direct_http_service_config)

[`espectre::DirectHttpServiceDiagnostics`](#structespectre_1_1_direct_http_service_diagnostics)

[`espectre::DirectRequest`](#structespectre_1_1_direct_request)

[`espectre::DirectWifiSnapshot`](#structespectre_1_1_direct_wifi_snapshot)

[`espectre::EspectreApiEventDescriptor`](#structespectre_1_1_espectre_api_event_descriptor)

[`espectre::EspectreApiRoute`](#structespectre_1_1_espectre_api_route)

[`espectre::EspectreCapabilityProfile`](#structespectre_1_1_espectre_capability_profile)

[`espectre::EspectreCommand`](#structespectre_1_1_espectre_command)

[`espectre::EspectreDeviceConfig`](#structespectre_1_1_espectre_device_config)

[`espectre::EspectreDeviceInfo`](#structespectre_1_1_espectre_device_info)

[`espectre::EspectreExtensionRoute`](#structespectre_1_1_espectre_extension_route)

[`espectre::EspectreNetworkInfo`](#structespectre_1_1_espectre_network_info)

[`espectre::EspectreProtocolExtension`](#structespectre_1_1_espectre_protocol_extension)

[`espectre::EspIdfDirectHttpService`](#classespectre_1_1_esp_idf_direct_http_service)

[`espectre::EspIdfMqttTransport`](#classespectre_1_1_esp_idf_mqtt_transport)

[`espectre::EspIdfPeerDiscoveryService`](#classespectre_1_1_esp_idf_peer_discovery_service)

[`espectre::FrontendCommandContext`](#structespectre_1_1_frontend_command_context)

[`espectre::FrontendCommandEngine`](#classespectre_1_1_frontend_command_engine)

[`espectre::FrontendCommandResult`](#structespectre_1_1_frontend_command_result)

[`espectre::FrontendDeviceConfigDefaults`](#structespectre_1_1_frontend_device_config_defaults)

[`espectre::FrontendHaDiagnosticSensor`](#structespectre_1_1_frontend_ha_diagnostic_sensor)

[`espectre::FrontendHaDiscoveryMessage`](#structespectre_1_1_frontend_ha_discovery_message)

[`espectre::FrontendHaMqttSettings`](#structespectre_1_1_frontend_ha_mqtt_settings)

[`espectre::FrontendWifiStationOptions`](#structespectre_1_1_frontend_wifi_station_options)

[`espectre::HighAccuracyDetector`](#classespectre_1_1_high_accuracy_detector)

[`espectre::ICsiTrafficGenerator`](#classespectre_1_1_i_csi_traffic_generator)

[`espectre::ICsiTrafficIngress`](#classespectre_1_1_i_csi_traffic_ingress)

[`espectre::IDirectHttpService`](#classespectre_1_1_i_direct_http_service)

[`espectre::IMqttTransport`](#classespectre_1_1_i_mqtt_transport)

[`espectre::IPeerDiscoveryService`](#classespectre_1_1_i_peer_discovery_service)

[`espectre::IRuntimeListener`](#classespectre_1_1_i_runtime_listener)

[`espectre::IUdpDatagramSocket`](#classespectre_1_1_i_udp_datagram_socket)

[`espectre::JsonFieldView`](#structespectre_1_1_json_field_view)

[`espectre::JsonInput`](#classespectre_1_1_json_input)

[`espectre::JsonObjectField`](#structespectre_1_1_json_object_field)

[`espectre::LightweightDetector`](#classespectre_1_1_lightweight_detector)

[`espectre::LogSink`](#structespectre_1_1_log_sink)

[`espectre::MdnsBootstrapResponder`](#classespectre_1_1_mdns_bootstrap_responder)

[`espectre::MdnsDiscoveryService`](#classespectre_1_1_mdns_discovery_service)

[`espectre::MdnsDiscoveryServiceConfig`](#structespectre_1_1_mdns_discovery_service_config)

[`espectre::MqttPayloadAssembler`](#classespectre_1_1_mqtt_payload_assembler)

[`espectre::MqttTransportDiagnostics`](#structespectre_1_1_mqtt_transport_diagnostics)

[`espectre::NetworkTrafficSnapshot`](#structespectre_1_1_network_traffic_snapshot)

[`espectre::PeerDiscoveryCandidate`](#structespectre_1_1_peer_discovery_candidate)

[`espectre::PeerDiscoverySnapshot`](#structespectre_1_1_peer_discovery_snapshot)

[`espectre::PendingEvent`](#classespectre_1_1_pending_event)

[`espectre::PendingQueue`](#classespectre_1_1_pending_queue)

[`espectre::RawCsiHttpFramePrefix`](#structespectre_1_1_raw_csi_http_frame_prefix)

[`espectre::RawCsiPacketView`](#structespectre_1_1_raw_csi_packet_view)

[`espectre::RawCsiRecordHeaderV8`](#structespectre_1_1_raw_csi_record_header_v8)

[`espectre::RawCsiSessionConfig`](#structespectre_1_1_raw_csi_session_config)

[`espectre::RawCsiSessionController`](#classespectre_1_1_raw_csi_session_controller)

[`espectre::RawCsiSessionDiagnostics`](#structespectre_1_1_raw_csi_session_diagnostics)

[`espectre::RuntimeCapabilities`](#structespectre_1_1_runtime_capabilities)

[`espectre::RuntimeConfig`](#structespectre_1_1_runtime_config)

[`espectre::RuntimeControlUpdate`](#structespectre_1_1_runtime_control_update)

[`espectre::RuntimeDiagnosticsSample`](#structespectre_1_1_runtime_diagnostics_sample)

[`espectre::RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler)

[`espectre::RuntimeDiagnosticsSnapshot`](#structespectre_1_1_runtime_diagnostics_snapshot)

[`espectre::RuntimeDirectHttpBridge`](#classespectre_1_1_runtime_direct_http_bridge)

[`espectre::RuntimeDirectHttpBridgeConfig`](#structespectre_1_1_runtime_direct_http_bridge_config)

[`espectre::RuntimeEventMailbox`](#classespectre_1_1_runtime_event_mailbox)

[`espectre::RuntimeFrontendController`](#classespectre_1_1_runtime_frontend_controller)

[`espectre::RuntimeSnapshot`](#structespectre_1_1_runtime_snapshot)

[`espectre::StandaloneWifiAccessPoint`](#structespectre_1_1_standalone_wifi_access_point)

[`espectre::StandaloneWifiConfig`](#structespectre_1_1_standalone_wifi_config)

[`espectre::StandaloneWifiInfo`](#structespectre_1_1_standalone_wifi_info)

[`espectre::StandaloneWifiService`](#classespectre_1_1_standalone_wifi_service)

[`espectre::StoredWifiConfig`](#structespectre_1_1_stored_wifi_config)

[`espectre::TemporalCsiSampler`](#classespectre_1_1_temporal_csi_sampler)

[`espectre::TrafficGeneratorManager`](#classespectre_1_1_traffic_generator_manager)

[`espectre::UdpDatagramPeer`](#structespectre_1_1_udp_datagram_peer)

[`espectre::WifiBssidPinService`](#classespectre_1_1_wifi_bssid_pin_service)

[`espectre::WifiBssidPinServiceConfig`](#structespectre_1_1_wifi_bssid_pin_service_config)

[`espectre::WifiBssidPinStationState`](#structespectre_1_1_wifi_bssid_pin_station_state)

[`espectre::WiFiLifecycleManager`](#classespectre_1_1_wi_fi_lifecycle_manager)

[`espectre::WifiProvisioningDefaults`](#structespectre_1_1_wifi_provisioning_defaults)

[`espectre::WifiProvisioningService`](#classespectre_1_1_wifi_provisioning_service)

[`espectre::detail`](#namespaceespectre_1_1detail)

[`espectre::task_scheduling`](#namespaceespectre_1_1task__scheduling)



<a id="namespaceespectre_1a99ebf34bc489f9258115ae3fc39c84cc"></a>

### `FrontendReadPayloadCallback`


```cpp
using espectre::FrontendReadPayloadCallback = std::function<std::string(const EspectreCommand &command)>
```

 

Build the JSON data for a read command such as `device` or `sensing`.

  

Return an empty string when the data is unavailable.

  

<a id="namespaceespectre_1a8e42108419d4fce5a5d1a958dd7674b0"></a>

### `FrontendDeviceLabelCallback`


```cpp
using espectre::FrontendDeviceLabelCallback = std::function<bool(const std::string &device_label, std::string *message)>
```

 

Apply a new user-facing device label; empty clears it.

   

<a id="namespaceespectre_1a7ef25a2cd5bc69f39d5c604bfa7205c1"></a>

### `FrontendThresholdCallback`


```cpp
using espectre::FrontendThresholdCallback = std::function<bool(float threshold, std::string *message)>
```

 

Apply a validated threshold on the 0..1 scale.

   

<a id="namespaceespectre_1ac9bb8399a317cda44a26fabc384d9415"></a>

### `FrontendMotionHitsCallback`


```cpp
using espectre::FrontendMotionHitsCallback = 
std::function<bool(uint8_t motion_on_hits, uint8_t motion_off_hits, std::string *message)>
```

 

Apply validated motion hit counts.

   

<a id="namespaceespectre_1ad31097089074dcd8b9cda39c061fe6fa"></a>

### `FrontendTrafficGeneratorModeCallback`


```cpp
using espectre::FrontendTrafficGeneratorModeCallback = std::function<bool(TrafficGeneratorMode mode, std::string *message)>
```

 

Switch the traffic generator mode.

   

<a id="namespaceespectre_1aeb40ee64d61b2f1df17f0a2fdd91edbc"></a>

### `FrontendDetectorCallback`


```cpp
using espectre::FrontendDetectorCallback = std::function<bool(DetectionAlgorithm algorithm, std::string *message)>
```

 

Switch the active detector.

   

<a id="namespaceespectre_1aa3d2cbbf3ae5675785b1f944ffedfd84"></a>

### `FrontendRecalibrateCallback`


```cpp
using espectre::FrontendRecalibrateCallback = std::function<bool(std::string *message)>
```

 

Start a recalibration; false reports the `busy` result code.

   

<a id="namespaceespectre_1ae7042efa563d462c22f07520e14049af"></a>

### `FrontendWifiBssidCallback`


```cpp
using espectre::FrontendWifiBssidCallback = 
std::function<bool(const EspectreCommand &command, std::string *message)>
```

 

Handle `scan_wifi`, `set_wifi_bssid`, `clear_wifi_bssid`, or `clear_wifi_credentials`, as named by `command.command`.

   

<a id="namespaceespectre_1a9bd446908b7d5f2991698aa087668f76"></a>

### `FrontendMqttConfigCallback`


```cpp
using espectre::FrontendMqttConfigCallback = 
std::function<bool(const EspectreCommand &command, bool clear, std::string *message)>
```

 

Apply `update_mqtt`, or clear the broker settings when `clear` is true.

   

<a id="namespaceespectre_1a0dde9bbbb9dbdb4c4fe1502ddf47ea7a"></a>

### `FrontendSensingControlCallback`


```cpp
using espectre::FrontendSensingControlCallback = std::function<bool(bool enabled, std::string *message)>
```

 

Arm or disarm the sensing services.

   

<a id="namespaceespectre_1a8d7fd8b1b46a31094dd6cdba42bfa903"></a>

### `FrontendSensingPreflightCallback`


```cpp
using espectre::FrontendSensingPreflightCallback = 
std::function<bool(const RuntimeControlUpdate &update, std::string *message)>
```

 

Check every sensing field of one `update_sensing` before any is applied.

  

Frontends built on [RuntimeFrontendController](#classespectre_1_1_runtime_frontend_controller) pass [`RuntimeFrontendController::validate_control_update()`](#classespectre_1_1_runtime_frontend_controller_1a4022d8f2e85a66c50222aac5d0cbd4f3).

  


<a id="namespaceespectre_1a988bb4b92b7b0de94be5d39ea3083d2f"></a>

### `wifi_band_policy_name`


```cpp
const char * espectre::wifi_band_policy_name(WifiBandPolicy policy)
```

 

Name of a Wi-Fi band policy: `2g`, `5g`, or `auto`.

   

<a id="namespaceespectre_1a587a11cb65ff1679a68d9d13ab53d2cb"></a>

### `traffic_generator_mode_name`


```cpp
const char * espectre::traffic_generator_mode_name(TrafficGeneratorMode mode)
```

 

Name of a traffic generator mode, such as `ping`, `dns`, or `external`.

   

<a id="namespaceespectre_1a00b12f22b91595a0e1c0fa56be36753d"></a>

### `detection_algorithm_name`


```cpp
const char * espectre::detection_algorithm_name(DetectionAlgorithm algorithm)
```

 

Name of a detector: `lightweight` or `high_accuracy`.

   

<a id="namespaceespectre_1a89421b6006f8113b7d9f54cb4ed202b8"></a>

### `parse_traffic_generator_mode`


```cpp
TrafficGeneratorMode espectre::parse_traffic_generator_mode(const char *mode)
```

 

Parse a traffic generator mode name.

  

Defaults to [`TrafficGeneratorMode::PING`](#namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5ae07ff41a486c27c095a15898dcca34d1).

  

<a id="namespaceespectre_1a58cce43945e826bdfe8db0e85cd5732c"></a>

### `parse_detection_algorithm`


```cpp
DetectionAlgorithm espectre::parse_detection_algorithm(const char *algorithm)
```

 

Parse a detector name.

  

Defaults to [`DetectionAlgorithm::LIGHTWEIGHT`](#namespaceespectre_1ae6098340c58c0355e67beaa092880c6ba56ab46ae63b63cb014aef408f34863a9).

  

<a id="namespaceespectre_1a21438506ac935cbc46862e5166c3d1eb"></a>

### `parse_wifi_band_policy`


```cpp
WifiBandPolicy espectre::parse_wifi_band_policy(const char *policy)
```

 

Parse a Wi-Fi band policy name.

  

Defaults to [`WifiBandPolicy::BAND_2G`](#namespaceespectre_1adb2211d7a11969b4ed8db08213d7b086ae5b0b1eaa95367f057b2c7cc12ec2301).

  


<a id="namespaceespectre_1ae9a5c52124fc67ad49536d43fd6d0077"></a>

### `format_espectre_device_id`


```cpp
std::string espectre::format_espectre_device_id(uint64_t device_id)
```

 

Format a device id in its canonical wire form.

   

<a id="namespaceespectre_1a56f23162b469f148e7bfeca818d5105b"></a>

### `parse_espectre_device_id`


```cpp
bool espectre::parse_espectre_device_id(const std::string &value, uint64_t *device_id)
```

 

Parse a device id from its wire form.

  

**Parameters**

- `value`: Formatted device id, as produced by [`format_espectre_device_id()`](#namespaceespectre_1ae9a5c52124fc67ad49536d43fd6d0077).
- `device_id`: Written only when parsing succeeds.

 

**Returns:** false on a malformed value, leaving the output untouched.

  

<a id="namespaceespectre_1adc03ef2a0c49d818c944747283819e1a"></a>

### `espectre_device_id_from_mac`


```cpp
uint64_t espectre::espectre_device_id_from_mac(const uint8_t *mac, size_t mac_len)
```

 

Pack the first six MAC bytes into the historical numeric representation.

  

**Deprecated:** 

Runtime firmware uses the cached, domain-separated SHA-256 pseudonym from [`derive_runtime_device_id()`](#namespaceespectre_1a34031a60d78bbb6306047b3540b4f905) instead.

  

<a id="namespaceespectre_1ae5c4f0a710fbd64b9efdda153e83b3b3"></a>

### `espectre_device_name`


```cpp
std::string espectre::espectre_device_name(uint64_t device_id, const char *chip=nullptr)
```

 

Conventional device name derived from the immutable device identifier.

   

<a id="namespaceespectre_1a975d496a575840d95675209e1294dda1"></a>

### `espectre_effective_device_id_u64`


```cpp
uint64_t espectre::espectre_effective_device_id_u64(const EspectreDeviceConfig &config)
```

 

The id actually in use.

  

Frontend startup replaces the zero sentinel.

  

<a id="namespaceespectre_1a7132956b729065dbed22f00e9edd8e7b"></a>

### `espectre_effective_device_id`


```cpp
std::string espectre::espectre_effective_device_id(const EspectreDeviceConfig &config)
```

 

[`espectre_effective_device_id_u64()`](#namespaceespectre_1a975d496a575840d95675209e1294dda1) in wire form.

   

<a id="namespaceespectre_1acaed5bdf8f0dd7e1592aa8c49fbc73be"></a>

### `espectre_effective_device_label`


```cpp
std::string espectre::espectre_effective_device_label(const EspectreDeviceConfig &config)
```

 

The configured label, or the effective device id when no label is set.

   

<a id="namespaceespectre_1aeaa6010650a78e01b8ad2c078335d102"></a>

### `normalize_protocol_device_info`


```cpp
EspectreDeviceInfo espectre::normalize_protocol_device_info(const EspectreDeviceInfo &info, const RuntimeSnapshot *snapshot, const char *default_frontend, const char *default_chip=nullptr)
```

 

Fill in the parts of a device info block the frontend did not set.

  

Takes the detector from `snapshot`, and `default_frontend` / `default_chip` where the caller left the field empty, so each frontend only states what is genuinely its own.

 

**Parameters**

- `info`: What the frontend knows about itself.
- `snapshot`: Source of the detector name. May be `nullptr` when no snapshot exists yet.
- `default_frontend`: Frontend name used when `info.frontend` is empty.
- `default_chip`: Chip name used when `info.chip` is empty.

 

**Returns:** A copy of `info` with the gaps filled.

  

<a id="namespaceespectre_1ac1edf42e0c351a6a291c91e0bf1ec7b0"></a>

### `clear_espectre_mqtt_config`


```cpp
void espectre::clear_espectre_mqtt_config(EspectreDeviceConfig *config)
```

 

Erase broker settings while preserving identity, for a config reset.

   

<a id="namespaceespectre_1a7d53b6c1f2382ba21a1bc8e3bd41d962"></a>

### `validate_espectre_mqtt_config`


```cpp
bool espectre::validate_espectre_mqtt_config(const EspectreDeviceConfig &config, std::string *error=nullptr)
```

 

Validate the complete MQTT endpoint in a device configuration.

  

The endpoint requires an exact `mqtt` or `mqtts` scheme, a DNS hostname, IPv4 address, or IPv6 address without URI framing, and a non-zero port.

 

**Parameters**

- `config`: Device configuration carrying the MQTT endpoint.
- `error`: Receives a human-readable reason on failure. May be `nullptr`.

 

**Returns:** `true` only when the complete endpoint is valid.

  

<a id="namespaceespectre_1abc400447710392b7e9d5cba40dbe685f"></a>

### `espectre_mqtt_configured`


```cpp
bool espectre::espectre_mqtt_configured(const EspectreDeviceConfig &config)
```

 

Return whether `config` contains a complete, valid MQTT endpoint.

   


<a id="namespaceespectre_1a32edcf9be1977beb72e27fd4900afc37"></a>

### `espectre_topic`


```cpp
std::string espectre::espectre_topic(const EspectreDeviceConfig &config, const char *suffix)
```

 

Build a full topic from this device's prefix and a trailing segment.

   

<a id="namespaceespectre_1af7d9b8dfa07f2d15f8ab478be3aafb48"></a>

### `espectre_health_payload`


```cpp
std::string espectre::espectre_health_payload(const EspectreDeviceConfig &config, bool online, uint32_t timestamp_ms)
```

 

Availability payload.

  

Publish it retained so late subscribers see it.

  

<a id="namespaceespectre_1aaf2c60d3cf259dfc145c5aa55b49162d"></a>

### `espectre_device_payload`


```cpp
std::string espectre::espectre_device_payload(const EspectreDeviceConfig &config, const EspectreDeviceInfo &info)
```

 

Stable device identity and build description.

  

Publish retained on connect.

  

<a id="namespaceespectre_1a2d5f998a0d1b9266434071e44192dee0"></a>

### `espectre_capabilities_payload`


```cpp
std::string espectre::espectre_capabilities_payload(const EspectreDeviceConfig &config, const EspectreDeviceInfo &info, const EspectreCapabilityProfile &capabilities)
```

 

Filtered command, event, feature, and configuration catalog.

   

<a id="namespaceespectre_1a10c3fe709e07f14529952203afcc3e8d"></a>

### `espectre_capabilities_payload`


```cpp
std::string espectre::espectre_capabilities_payload(const EspectreDeviceConfig &config, const EspectreDeviceInfo &info, bool supports_status=true, bool supports_config=false, bool supports_sensing_control=false, bool supports_wifi_bssid=false, bool supports_mqtt_config=false, bool supports_peer_discovery=false, bool supports_raw_csi=false, const EspectreProtocolExtension *extension=nullptr)
```

 

Flag-per-section form of the capability catalog.

  

Prefer the [`EspectreCapabilityProfile`](#structespectre_1_1_espectre_capability_profile) overload, which represents readable sections and individual commands independently.

  

<a id="namespaceespectre_1aec53df228c0e4a8235a57886f272fc16"></a>

### `espectre_motion_payload`


```cpp
std::string espectre::espectre_motion_payload(const EspectreDeviceConfig &config, const RuntimeSnapshot &snapshot, uint32_t timestamp_ms, uint32_t uptime_s, const char *frontend)
```

 

Current motion state and score.

  

The payload behind every detector evaluation.

  

<a id="namespaceespectre_1a6bc2369abcef6f55305c1f528ee32d2b"></a>

### `espectre_diagnostics_payload`


```cpp
std::string espectre::espectre_diagnostics_payload(const EspectreDeviceConfig &config, const RuntimeSnapshot &snapshot, uint32_t timestamp_ms, uint32_t uptime_s, float free_memory_kb, float loop_time_ms, const RuntimeDiagnosticsSample *diagnostics=nullptr)
```

 

Health counters plus optional rate and link diagnostics.

  

`diagnostics` carries CSI and link rates from [`RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler). Pass `nullptr` only for a frontend that does not expose extended diagnostics.

  

<a id="namespaceespectre_1a23723f52835cb183d122bbaf8c5348f7"></a>

### `espectre_command_result_payload`


```cpp
std::string espectre::espectre_command_result_payload(const EspectreDeviceConfig &config, const EspectreCommand &command, bool accepted, const char *code, const char *message, const std::string &data_json={})
```

 

Acknowledge a command, echoing its `command_id`.

  

Publish one for every command you parse, accepted or not; clients correlate on the id and otherwise cannot tell rejection from packet loss.

  

<a id="namespaceespectre_1ad3b52b52f70db1fa6a3a65c861702371"></a>

### `espectre_command_request_payload`


```cpp
std::string espectre::espectre_command_request_payload(const std::string &command_id, const std::string &command, const std::string &params_json="{}")
```

 

Build the canonical flat command request carried by MQTT and Direct HTTP.

   

<a id="namespaceespectre_1a7a2bb328d061562636f101a7201f5d72"></a>

### `espectre_fault_payload`


```cpp
std::string espectre::espectre_fault_payload(const EspectreDeviceConfig &config, const char *message, uint32_t timestamp_ms)
```

 

Runtime fault event shared by every transport.

   

<a id="namespaceespectre_1ab3c981ce263a1f565b33cdd705306a45"></a>

### `espectre_message_catalog_payload`


```cpp
std::string espectre::espectre_message_catalog_payload(const EspectreProtocolExtension *extension=nullptr)
```

 

One sample of every canonical message, for protocol inspection and conformance tests.

   


<a id="namespaceespectre_1affd612c44046053715f0e4947c579959"></a>

### `parse_espectre_command`


```cpp
bool espectre::parse_espectre_command(const std::string &payload, EspectreCommand *command, std::string *error, const EspectreProtocolExtension *extension=nullptr)
```

 

Parse a canonical flat command request, as received on the MQTT command topic.

  

**Parameters**

- `payload`: Raw message body as received.
- `command`: Populated on success. Check the `has_*` flags to see which fields the peer actually sent. On failure it is reset and may keep the `command_id` for the result payload.
- `error`: Receives a human-readable reason on failure. May be `nullptr`.
- `extension`: Optional frontend routes and their parameter validators.

 

**Returns:** false on malformed input or invalid parameters. An unknown command name parses successfully; [FrontendCommandEngine](#classespectre_1_1_frontend_command_engine) rejects it with the `unsupported` result code.

  

<a id="namespaceespectre_1a3719c5d411370f85344e700a2eb961a5"></a>

### `parse_espectre_command_request`


```cpp
bool espectre::parse_espectre_command_request(const std::string &command_id, const std::string &command_name, const std::string &params_json, EspectreCommand *command, std::string *error, const std::string &protocol_version=ESPECTRE_PROTOCOL_VERSION, const EspectreProtocolExtension *extension=nullptr)
```

 

Parse an already separated command name plus a JSON parameter object.

  

Frontend adapters use this after separating a canonical flat request into internal fields. Validation follows canonical envelope order: correlation identifier, protocol version, command name, and parameters.

  

<a id="namespaceespectre_1a688469ee24c9b9691d715dc273feaf95"></a>

### `parse_espectre_config_command`


```cpp
bool espectre::parse_espectre_config_command(const std::string &command, EspectreDeviceConfig *config, std::string *error)
```

 

Parse a legacy ASCII `SET_DEVICE_CONFIG:` command.

  

Carries one `key=value` pair, applied in place. A rejected command writes nothing.

 

**Parameters**

- `command`: Full command string, including the `SET_DEVICE_CONFIG:` prefix.
- `config`: Updated in place on success.
- `error`: Receives a human-readable reason on failure. May be `nullptr`.

  

<a id="namespaceespectre_1a89f2455d1366f9cca351588f426b9425"></a>

### `parse_espectre_mqtt_config_command`


```cpp
bool espectre::parse_espectre_mqtt_config_command(const std::string &command, EspectreDeviceConfig *config, std::string *error)
```

 

Parse a `SET_MQTT_CONFIG:` command, carrying the broker settings.

  

The complete command is parsed and validated before `config` is changed, so rejection leaves the previous value intact. `scheme`, `host`, and `port` are required; the rest keep their previous values.

  


<a id="namespaceespectre_1a2cf603b44b19bbfa3bb19e238387e886"></a>

### `load_stored_wifi_config`


```cpp
esp_err_t espectre::load_stored_wifi_config(StoredWifiConfig *config)
```

 

Load the saved station configuration; `ESP_ERR_INVALID_ARG` for a null `config`.

   

<a id="namespaceespectre_1aedba313a714d86f0c2f5e4c27e930c26"></a>

### `save_stored_wifi_config`


```cpp
esp_err_t espectre::save_stored_wifi_config(const StoredWifiConfig &config)
```

 

Save and commit the station configuration.

   

<a id="namespaceespectre_1a748cc12e82891ff8357c5400ddeba8be"></a>

### `clear_stored_wifi_config`


```cpp
esp_err_t espectre::clear_stored_wifi_config()
```

 

Erase the saved station configuration.

   

<a id="namespaceespectre_1a0b38592b6457d7241bf7d27ed727e206"></a>

### `load_pending_wifi_config`


```cpp
esp_err_t espectre::load_pending_wifi_config(StoredWifiConfig *config, bool *has_pending)
```

 

Load a staged candidate that has not been verified yet.

  

`has_pending` reports whether one exists. Used by [WifiProvisioningService](#classespectre_1_1_wifi_provisioning_service) to resume verification after a reboot.

  

<a id="namespaceespectre_1aad6feb37ea2ad9bf489303f43fe1b356"></a>

### `save_pending_wifi_config`


```cpp
esp_err_t espectre::save_pending_wifi_config(const StoredWifiConfig &config)
```

 

Stage a candidate configuration before applying it.

   

<a id="namespaceespectre_1a8096ad0bac3ccebebe9f58089d27a0fc"></a>

### `clear_pending_wifi_config`


```cpp
esp_err_t espectre::clear_pending_wifi_config()
```

 

Discard the staged candidate.

   

<a id="namespaceespectre_1aefa05fb8f5d8a1be93d9dd3a6d0fb39e"></a>

### `load_stored_device_config`


```cpp
esp_err_t espectre::load_stored_device_config(EspectreDeviceConfig *config, bool *has_saved_config)
```

 

Load the saved device label and broker settings into `config`.

  

`has_saved_config` may be `nullptr`; otherwise it reports whether saved settings exist. When they do, `config` is replaced and every field that is not stored takes its default, including `device_id`. Otherwise `config` is left unchanged.

  

<a id="namespaceespectre_1a895dff951a4439b9cc6f9469057602c7"></a>

### `save_stored_device_config`


```cpp
esp_err_t espectre::save_stored_device_config(const EspectreDeviceConfig &config)
```

 

Save and commit the device label and broker settings.

   

<a id="namespaceespectre_1a283d26d4b901e79e0d50bb31defa0af7"></a>

### `clear_stored_device_config`


```cpp
esp_err_t espectre::clear_stored_device_config()
```

 

Erase the saved device label and broker settings.

   


<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22a"></a>

### `RawCsiChipType`


```cpp
enum class RawCsiChipType : uint8_t
```

   

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aa696b031073e74bf2cb98e5ef201d4aa3"></a>

`UNKNOWN = 0`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aa789c376b43dbba68180fd04da73286da"></a>

`ESP32 = 1`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aab9eeaf6a16ca49f37df57620aed91b62"></a>

`S2 = 2`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aa1cf733d786a614c74862934365c1b5ca"></a>

`RESERVED_LEGACY_S2 = S2`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aae2ab7c65b21ed8cc1c3b642b5e36429e"></a>

`S3 = 3`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aa3abe124ecc82bf2c2e22e6058f38c50c"></a>

`C3 = 4`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aafea813d4ddba3c46cf8b8e664b92cdaa"></a>

`C5 = 5`

  

<a id="namespaceespectre_1a83022e1a22fdb212c86c99fc85d8b22aa7e8b9f5cab4a8fe24fad9fe4b7452702"></a>

`C6 = 6`

  

<a id="namespaceespectre_1a967920764a50523f0ce8f7c5e36a3a21"></a>

### `RawCsiRecordFlags`


```cpp
enum RawCsiRecordFlags : uint8_t
```

   

<a id="namespaceespectre_1a967920764a50523f0ce8f7c5e36a3a21a8d36260ce1b4352270abab92bfd65e38"></a>

`RAW_CSI_FLAG_FIRST_WORD_INVALID = 1u << 0`

  

<a id="namespaceespectre_1a967920764a50523f0ce8f7c5e36a3a21a4e720bd9bc21639dc5557441624cef2a"></a>

`RAW_CSI_FLAG_WIFI_RX_TS_VALID = 1u << 1`

  

<a id="namespaceespectre_1a967920764a50523f0ce8f7c5e36a3a21ad3840b82f9a900c6c97204ff67f6b8be"></a>

`RAW_CSI_FLAG_WIFI_RX_START_TS_NS_VALID = 1u << 2`

  

<a id="namespaceespectre_1a967920764a50523f0ce8f7c5e36a3a21a0051718291384eb75885c9b62e79cfa2"></a>

`RAW_CSI_FLAG_FRESH = 1u << 3`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363"></a>

### `RawCsiPhyMode`


```cpp
enum class RawCsiPhyMode : uint8_t
```

   

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a696b031073e74bf2cb98e5ef201d4aa3"></a>

`UNKNOWN = 0`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a456d016bd133625e5036aa9a556f2730"></a>

`LEGACY = 1`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a90d64eeba8247d656ef6b4800ec0f52f"></a>

`HT = 2`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a2d425dd35e072d51beffedbbefe7b7d9"></a>

`VHT = 3`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a384604b568b86c1b44f899ad0bb52cde"></a>

`HE_SU = 4`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a03deb58782326a275810c5b0d35b125c"></a>

`HE_MU = 5`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363ad5a697bbf088741bb5857cc870674d51"></a>

`HE_ERSU = 6`

  

<a id="namespaceespectre_1a679285b0ae641ff6d1446f1a7cb6a363a803d1726aa04a7d2ced45ac2099bb57d"></a>

`HE_TB = 7`

  

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9e"></a>

### `RawCsiLtfType`


```cpp
enum class RawCsiLtfType : uint8_t
```

   

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9ea696b031073e74bf2cb98e5ef201d4aa3"></a>

`UNKNOWN = 0`

  

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9ea23995e76e6c517049199861bd20a5f7f"></a>

`LLTF = 1`

  

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9ea1d815e95673dac609a01bfb986c2cceb"></a>

`HT_LTF = 2`

  

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9ea7b3f0f06d9c6307397f670944b74eabd"></a>

`VHT_LTF = 3`

  

<a id="namespaceespectre_1a04fa1bf9323c3efd3ff9998892a32e9ea2115a1e7b50842efe5fd7f8ee5793795"></a>

`HE_LTF = 4`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97"></a>

### `RawCsiChannelWidth`


```cpp
enum class RawCsiChannelWidth : uint8_t
```

   

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97a696b031073e74bf2cb98e5ef201d4aa3"></a>

`UNKNOWN = 0`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97a6776ebfc3912b4527d387fd703a69587"></a>

`MHZ_20 = 1`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97a0fac4da3580d6b66a5c1dc27478b7290"></a>

`MHZ_40 = 2`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97a5d49cf11445a99bc8fed070ce53db290"></a>

`MHZ_80 = 3`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97adc07c66d483ad17443b20de9fa00d9f8"></a>

`MHZ_160 = 4`

  

<a id="namespaceespectre_1a74c31f33edc1dcd2760c4cf242d01c97a6a082d35c82fdef562036b955f5b2836"></a>

`MHZ_80_80 = 5`

  

<a id="namespaceespectre_1adb2211d7a11969b4ed8db08213d7b086"></a>

### `WifiBandPolicy`


```cpp
enum class WifiBandPolicy : uint8_t
```

   

<a id="namespaceespectre_1adb2211d7a11969b4ed8db08213d7b086ae5b0b1eaa95367f057b2c7cc12ec2301"></a>

`BAND_2G = 0`

 

Restrict association to 2.4 GHz.

  

<a id="namespaceespectre_1adb2211d7a11969b4ed8db08213d7b086ac18a21d672f2013842acfe84a52dd1ff"></a>

`BAND_5G = 1`

 

Restrict association to 5 GHz.

  

Supported only by dual-band targets.

 

<a id="namespaceespectre_1adb2211d7a11969b4ed8db08213d7b086ae1f2d5134ed2543d38a0de9751cf75d9"></a>

`AUTO = 2`

 

Use every band the radio has.

  

A dual-band radio chooses between 2.4 GHz and 5 GHz; a 2.4 GHz-only radio behaves as `BAND_2G`. The default.

 

<a id="namespaceespectre_1aa28375cf8afd113582387290089d9d09"></a>

### `RuntimeOperationState`


```cpp
enum class RuntimeOperationState : uint8_t
```

   

<a id="namespaceespectre_1aa28375cf8afd113582387290089d9d09a9f53d28f082938342669ff6fa150947a"></a>

`SENSING = 0U`

  

<a id="namespaceespectre_1aa28375cf8afd113582387290089d9d09ad22e88ebf186a446048c76b8d21ca82d"></a>

`RAW_COLLECTION = 1U`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894b"></a>

### `RawCsiStopReason`


```cpp
enum class RawCsiStopReason : uint8_t
```

   

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba889d4358e2fdc68185c59ee7e3173f58"></a>

`REQUESTED = 0U`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba7ed8690dbfd5c0f83297bcefef1838b1"></a>

`OWNER_DISCONNECTED`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894bacad7f17799e0f75686d4c2b5487c0222"></a>

`RAW_DISCONNECTED`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba5b37c1f5e31bc66cb745596d15f9eb77"></a>

`WIFI_LOST`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba18ec90ed92f5ba900fc659058639a089"></a>

`CHANNEL_CHANGED`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba9781bf1cfd0bd74625eb7706e7851862"></a>

`BIND_TIMEOUT`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894ba5764d112dd5a2400b2474fe0655aa647"></a>

`SLOW_CLIENT`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894bab9984206799a7f9fe4bd1b6c18db8112"></a>

`SHUTDOWN`

  

<a id="namespaceespectre_1af156112b0ff4ebaccc0dd4792a7b894bae8c0c70879b5895c615677261d64a1ee"></a>

`INTERNAL_ERROR`

  

<a id="namespaceespectre_1a55fec3458e3b4db441f3bc69b8b4d531"></a>

### `CsiCaptureProfile`


```cpp
enum class CsiCaptureProfile : uint8_t
```

   

<a id="namespaceespectre_1a55fec3458e3b4db441f3bc69b8b4d531a24f04967c622932f7e0d14c6c6116bb9"></a>

`HT20 = 0`

  

<a id="namespaceespectre_1a55fec3458e3b4db441f3bc69b8b4d531a730bbbd2dbfeb3f9e7bbfc62c5d691dd"></a>

`LLTF20 = 1`

  

<a id="namespaceespectre_1a55fec3458e3b4db441f3bc69b8b4d531a6044439528133be9d5881fe2ffa3a740"></a>

`VHT20 = 2`

  

<a id="namespaceespectre_1a3ac8602b3ece6440ded84d1b663b0645"></a>

### `CsiCapturePolicy`


```cpp
enum class CsiCapturePolicy : uint8_t
```

 

Build-time policy resolved to a physical capture profile after association.

   

<a id="namespaceespectre_1a3ac8602b3ece6440ded84d1b663b0645ae1f2d5134ed2543d38a0de9751cf75d9"></a>

`AUTO = 0`

  

<a id="namespaceespectre_1a3ac8602b3ece6440ded84d1b663b0645a23995e76e6c517049199861bd20a5f7f"></a>

`LLTF = 1`

  

<a id="namespaceespectre_1a3ac8602b3ece6440ded84d1b663b0645aac7a6fd4ec8779cfac29a9102c93df3d"></a>

`HT_VHT = 2`

  

<a id="namespaceespectre_1ae6098340c58c0355e67beaa092880c6b"></a>

### `DetectionAlgorithm`


```cpp
enum class DetectionAlgorithm
```

 

Which detector runs.

  

See [ALGORITHMS.md](<https://github.com/francescopace/espectre/blob/main/docs/ALGORITHMS.md>) for how they differ.

  

<a id="namespaceespectre_1ae6098340c58c0355e67beaa092880c6ba56ab46ae63b63cb014aef408f34863a9"></a>

`LIGHTWEIGHT`

 

Lightweight feature fusion.

  

Self-calibrates, and needs no training data. Default.

 

<a id="namespaceespectre_1ae6098340c58c0355e67beaa092880c6ba3b9afd5243cb84a8cbef8865bce2b816"></a>

`HIGH_ACCURACY`

 

High-accuracy neural detector using the trained weights in `core/ml_weights.h`.

  

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5"></a>

### `TrafficGeneratorMode`


```cpp
enum class TrafficGeneratorMode
```

 

How the device gets the traffic that produces CSI.

  

CSI is only produced when packets arrive, so something has to keep the link busy. The first four modes run the internal generator at `csi_target_pps` with the given packet; `EXTERNAL` leaves it to another host.

  

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5ae07ff41a486c27c095a15898dcca34d1"></a>

`PING`

 

Internal generator, ICMP echo.

  

Default.

 

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5aed5f2bdecbd4bd349d09412d1ff6a6fb"></a>

`DNS`

 

Internal generator, DNS queries over connectionless UDP.

  

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5a8ad9afc2b5c72f5ed884633f4b187446"></a>

`DNS_TCP`

 

Internal generator, length-prefixed DNS queries over a persistent TCP connection.

  

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5a470317edc5e9cd9b77e1c82fc82879de"></a>

`WIFI_RAW`

 

Internal generator, raw Wi-Fi Null Data frames addressed to the associated AP.

  

<a id="namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5a3932d629fb5e2be9d09b3a4485b3cc9d"></a>

`EXTERNAL`

 

No internal generator: another host sends exact UDP markers or unicast ICMP Echo Requests, and the runtime listens for them.

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93e"></a>

### `RuntimeConfigError`


```cpp
enum class RuntimeConfigError : uint8_t
```

 

Machine-readable reason a [`RuntimeConfig`](#structespectre_1_1_runtime_config) cannot be applied.

   

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eab50339a10e1de285ac99d4c3990b8693"></a>

`NONE = 0`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eadb9ba49fd4f85872bd7304b9ce73532b"></a>

`WIFI_BAND_POLICY`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eabb9749dba30f14d44df3d90ff2f49347"></a>

`DETECTION_ALGORITHM`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea27eed88a405a5a259e3ef61b30a00774"></a>

`SEGMENTATION_THRESHOLD`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea80da7e62ceda7e8dc0eb0585fa571560"></a>

`SEGMENTATION_WINDOW_SIZE_MS`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eadc199c0de12fee330627b30dea330860"></a>

`CSI_TARGET_PPS`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eae056f1164f35461290677cb1f67ef46c"></a>

`TRAFFIC_GENERATOR_MODE`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eac49034d17b98b5149a39f1a81fc810d2"></a>

`CSI_TRAFFIC_UDP_PORT`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea775c24445714bd79b49d74b40ce5b984"></a>

`CSI_TRAFFIC_MULTICAST_GROUP`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea5a0515c621312c6f547a75ca3179a5d8"></a>

`EVALUATION_INTERVAL_MS`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eadc4869da089da59f51f497b0428ddc37"></a>

`MOTION_HITS`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea0b76f6df73c97bc34b5b05f921ba26ab"></a>

`LOWPASS_CUTOFF`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea20fa3b1aa41abbfaa8ec4bea23294cdf"></a>

`HAMPEL_WINDOW`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93eac9f13f6f6e556f06cf8f11c44e878cf6"></a>

`HAMPEL_THRESHOLD`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea36cb89ee1128f761a86aa8488f6a7dff"></a>

`TRAFFIC_GENERATOR_TARGET_IP`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ea10dc1b07406c7d3f6d4bc6fbd4bbffdf"></a>

`CSI_CAPTURE_PROFILE`

  

<a id="namespaceespectre_1afaec94f4ee217bc8f3f8f5214443c93ead0b82b03047ac28ad4989621265b475f"></a>

`CSI_CAPTURE_PROFILE_TRAFFIC`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8"></a>

### `EspectreDirectMethod`


```cpp
enum class EspectreDirectMethod : uint8_t
```

   

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a4a82c34eb02c0a85df93d1ce03d8cb73"></a>

`CAPABILITIES = 0`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a551b723eafd6a31d444fcb2f5920fbd3"></a>

`INFO`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a5f241c8c8f985b3c51e05d39cf030f4c"></a>

`STATUS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a73e99d350a4aa6f1a5af04ec29173f73"></a>

`CONFIG`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8ab84a5c31b5eb0f818f696c05c86cdc12"></a>

`DIAGNOSTICS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a6c64768599b8a2e5122925893460dea5"></a>

`SET_SENSING`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a1b4ee44dec7b7dc5418ea6a2a1657cea"></a>

`SET_DEVICE_LABEL`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a1e11be2ec8de268d919215833fb1a548"></a>

`SET_THRESHOLD`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a886b96586a5750ee3fa941509fce3583"></a>

`SET_MOTION_HITS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a64ecc60dfa1e5eef76e5ed276b19f502"></a>

`SET_DETECTOR`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8aa59a90d8e320711bc5365ecb24ec0f4e"></a>

`RECALIBRATE`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8ada16c5572a2d2983a2189d55399d72a4"></a>

`START_RAW_STREAM`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a08a5be2be93c4e9dcd813383eb4231fa"></a>

`STOP_RAW_STREAM`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a3f95f7923d4f70750d2d491cc662d6da"></a>

`SET_TRAFFIC_GENERATOR_MODE`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a1c09b3b226ddea0b13c18f4e294b4205"></a>

`WIFI_ACCESS_POINTS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a950b1d4cdc7a4119ca268ccc34cb51c5"></a>

`SCAN_WIFI_ACCESS_POINTS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a9de29080e74b98b067c928209641ee96"></a>

`SET_WIFI_BSSID`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8af1547d17befcf56ea02805e78b8a0a36"></a>

`CLEAR_WIFI_BSSID`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8af9f8177feaa1ee5fcc28d65333f4b285"></a>

`CLEAR_WIFI_CONFIG`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a1ff395f3838c8af5d53a3d0cbe18368d"></a>

`SET_MQTT_CONFIG`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8aa6cb515e3f7b084732d0890c5763eb20"></a>

`CLEAR_MQTT_CONFIG`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a1211f2728fa92bbcd91b84b900a5e464"></a>

`DISCOVER_PEERS`

  

<a id="namespaceespectre_1afca4c79a12b4b401c979d6232c2a0bd8a4905ac9d6a22bdfc1ae096094ce6248d"></a>

`COUNT`

  

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8"></a>

### `EspectreConfigSection`


```cpp
enum class EspectreConfigSection : uint8_t
```

   

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8ae5f5cd9fe71ac064a678f27c7d539ae8"></a>

`RUNTIME = 0`

  

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8ae10b6ab6a278644ce40631f62f360b6d"></a>

`DEVICE`

  

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8a2f0b4d2c0c3d64bbb2cd525dbba8b0d0"></a>

`WIFI`

  

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8aab0a7cf5deeda86b66467df64c3b6122"></a>

`MQTT`

  

<a id="namespaceespectre_1afc7c8d567fb0888be484d8ebdda994a8a4905ac9d6a22bdfc1ae096094ce6248d"></a>

`COUNT`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ff"></a>

### `EspectreEvent`


```cpp
enum class EspectreEvent : uint8_t
```

   

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffabb3d2d909c73fe49800949a344775f8b"></a>

`TELEMETRY = 0`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffa5f241c8c8f985b3c51e05d39cf030f4c"></a>

`STATUS`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffa551b723eafd6a31d444fcb2f5920fbd3"></a>

`INFO`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffa73e99d350a4aa6f1a5af04ec29173f73"></a>

`CONFIG`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffa893b3aaf1661e3717b18e8335ff93a72"></a>

`FAULT`

  

<a id="namespaceespectre_1a8c8b3454eae8a719a4f529bf205bf0ffa4905ac9d6a22bdfc1ae096094ce6248d"></a>

`COUNT`

  

<a id="namespaceespectre_1a673de3f0a8dc83c71f9a080a6e195084"></a>

### `EspectreApiRouteKind`


```cpp
enum class EspectreApiRouteKind : uint8_t
```

   

<a id="namespaceespectre_1a673de3f0a8dc83c71f9a080a6e195084a4f49da9035f276c0947466eb7c42249a"></a>

`RESOURCE = 0`

  

<a id="namespaceespectre_1a673de3f0a8dc83c71f9a080a6e195084ad6a0beecbcc46b64a23307ffc084ed36"></a>

`OPERATION`

  

<a id="namespaceespectre_1a673de3f0a8dc83c71f9a080a6e195084a2f05998d2a71cdc19b7109549bbe2646"></a>

`STREAM`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846"></a>

### `JsonValueType`


```cpp
enum class JsonValueType : uint8_t
```

   

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846a63b588d5559f64f89a416e656880b949"></a>

`STRING = 0`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846a34f55eca38e0605a84f169ff61a2a396"></a>

`NUMBER`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846ac48d5da12d702e73d6966069f2687376"></a>

`BOOLEAN`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846aa9f0aff2067f91437e50e4872b229e6a"></a>

`NULL_VALUE`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846a8eee8e217391199668cbac89472ace53"></a>

`OBJECT`

  

<a id="namespaceespectre_1ac017ab0ef298a8a5cd2ba8876dc67846acb4fb1757fb37c43cded35d3eb857c43"></a>

`ARRAY`

  

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadb"></a>

### `LogLevel`


```cpp
enum class LogLevel : uint8_t
```

 

Severity attached to one ESPectre log message.

   

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadbabb1ca97ec761fc37101737ba0aa2e7c5"></a>

`ERROR = 1`

  

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadba059e9861e0400dfbe05c98a841f3f96b"></a>

`WARNING = 2`

  

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadba551b723eafd6a31d444fcb2f5920fbd3"></a>

`INFO = 3`

  

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadbadc30ec20708ef7b0f641ef78b7880a15"></a>

`DEBUG = 4`

  

<a id="namespaceespectre_1adfd78003c463a47035e2de0ecd39cadbaec1f06e9fb39c4ef0729b3c7c9c8e8cc"></a>

`VERBOSE = 5`

  

<a id="namespaceespectre_1a7d37681f3243ed6bdd97aee1ed776857"></a>

### `MotionState`


```cpp
enum class MotionState
```

 

Debounced detector state.

   

<a id="namespaceespectre_1a7d37681f3243ed6bdd97aee1ed776857aa5daf7f2ebbba4975d61dab1c40188c7"></a>

`IDLE`

  

<a id="namespaceespectre_1a7d37681f3243ed6bdd97aee1ed776857af96e6ea7a7375bd60bad3f3caae3cf27"></a>

`MOTION`

  

<a id="namespaceespectre_1a1a2af5566391edd860e3585c8f8b4bb3"></a>

### `Ht20BinLayout`


```cpp
enum class Ht20BinLayout : uint8_t
```

   

<a id="namespaceespectre_1a1a2af5566391edd860e3585c8f8b4bb3a696b031073e74bf2cb98e5ef201d4aa3"></a>

`UNKNOWN = 0`

  

<a id="namespaceespectre_1a1a2af5566391edd860e3585c8f8b4bb3a21c97af368df9b59d1244bd698506814"></a>

`CENTERED`

  

<a id="namespaceespectre_1a1a2af5566391edd860e3585c8f8b4bb3a21994d6177b29e1128b2d7f0f8342057"></a>

`CLASSIC`

  

<a id="namespaceespectre_1a66960f4a1cf7a867acd1d1a7c9f52d18"></a>

### `MdnsResponderMode`


```cpp
enum class MdnsResponderMode : uint8_t
```

 

Who owns the ESP-IDF mDNS responder.

   

<a id="namespaceespectre_1a66960f4a1cf7a867acd1d1a7c9f52d18a2a353b2cdb13a76f32641ff7f25e4cea"></a>

`OWN_RESPONDER = 0`

 

This service initializes the responder, sets the hostname and instance name, and frees the responder at shutdown when it started it.

  

<a id="namespaceespectre_1a66960f4a1cf7a867acd1d1a7c9f52d18af8944176f9ecbfea29c227b401ad4a92"></a>

`USE_EXISTING_RESPONDER`

 

Another component, such as the Matter stack, owns the responder; this service only adds its DNS-SD service and announces it.

  

<a id="namespaceespectre_1afb799961d21e38195f1ad899880c3189"></a>

### `UdpReceiveResult`


```cpp
enum class UdpReceiveResult
```

   

<a id="namespaceespectre_1afb799961d21e38195f1ad899880c3189a0334b8669eb43f45f9bccb223186be65"></a>

`PACKET`

  

<a id="namespaceespectre_1afb799961d21e38195f1ad899880c3189aba2b45bdc11e2a4a6e86aab2ac693cbb"></a>

`EMPTY`

  

<a id="namespaceespectre_1afb799961d21e38195f1ad899880c3189abb1ca97ec761fc37101737ba0aa2e7c5"></a>

`ERROR`

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291fa"></a>

### `WifiBssidPinApplyState`


```cpp
enum class WifiBssidPinApplyState : uint8_t
```

 

Progress of a BSSID pin change.

   

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faaa5daf7f2ebbba4975d61dab1c40188c7"></a>

`IDLE = 0`

 

No change in progress.

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faa4ea687957de9caaad1e098e3e95aae9e"></a>

`VERIFYING`

 

The pin is applied and waiting for association and an address.

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faa704940fadc36a1ea05e200e3ccaeb298"></a>

`ROLLING_BACK`

 

The change failed; the previous pin is being restored.

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faaa949e143063cf0e9ab61dc7004280c35"></a>

`APPLIED`

 

The station connected with the requested pin, and it was saved.

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faaed701d1c3d474e00c7a2f416f8d6858c"></a>

`ROLLED_BACK`

 

The change failed or was discarded, and the previous pin is back.

  

<a id="namespaceespectre_1afd04e6f466bb9a85e3f867421d5291faab0abcd2350d0f34995a7eb78c6a3c035"></a>

`RECOVERY_REQUIRED`

 

Rollback failed or timed out; the station may need recovery.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339"></a>

### `WifiProvisioningApplyState`


```cpp
enum class WifiProvisioningApplyState : uint8_t
```

 

Progress of a staged Wi-Fi configuration change.

   

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339aa5daf7f2ebbba4975d61dab1c40188c7"></a>

`IDLE = 0`

 

No change in progress.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339a4ea687957de9caaad1e098e3e95aae9e"></a>

`VERIFYING`

 

The candidate is applied and waiting for association and an address.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339a704940fadc36a1ea05e200e3ccaeb298"></a>

`ROLLING_BACK`

 

The candidate failed; the last-known-good settings are being restored.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339aa949e143063cf0e9ab61dc7004280c35"></a>

`APPLIED`

 

The candidate connected and was saved.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339aed701d1c3d474e00c7a2f416f8d6858c"></a>

`ROLLED_BACK`

 

The candidate failed and the last-known-good settings are back.

  

<a id="namespaceespectre_1a31d1131642dc8c0436b043e4c899c339ab0abcd2350d0f34995a7eb78c6a3c035"></a>

`RECOVERY_REQUIRED`

 

Rollback failed or timed out; reprovision over Improv Serial.

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aa"></a>

### `FrontendCommandChange`


```cpp
enum class FrontendCommandChange : uint8_t
```

 

Protocol resources a command changed, as a bit set.

  

Transports use it to republish the matching state after an accepted change.

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaab50339a10e1de285ac99d4c3990b8693"></a>

`NONE = 0U`

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaa785a1e256fca0cd6be7b3dced4281845"></a>

`HEALTH = 1U << 0U`

 

Health output changed.

  

The engine never reports it; frontends pass it to [`RuntimeDirectHttpBridge::publish_changes()`](#classespectre_1_1_runtime_direct_http_bridge_1ad59141bad149054a36f26958a9d3c1d7) to republish health.

 

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaae10b6ab6a278644ce40631f62f360b6d"></a>

`DEVICE = 1U << 1U`

 

Device label or identity.

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaa9f53d28f082938342669ff6fa150947a"></a>

`SENSING = 1U << 2U`

 

Sensing configuration or state.

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaa2f0b4d2c0c3d64bbb2cd525dbba8b0d0"></a>

`WIFI = 1U << 3U`

 

Wi-Fi station configuration.

  

<a id="namespaceespectre_1aa730eb411cfeec940ccae2c21b7fa2aaaab0a7cf5deeda86b66467df64c3b6122"></a>

`MQTT = 1U << 4U`

 

Broker configuration.

  

<a id="namespaceespectre_1a78137e71d7f05fcbfbda841d3a1fc91b"></a>

### `FrontendCommandOrigin`


```cpp
enum class FrontendCommandOrigin : uint8_t
```

 

Transport or frontend surface a command arrived through.

   

<a id="namespaceespectre_1a78137e71d7f05fcbfbda841d3a1fc91ba4c5d06b02c97731aaa976179c62dcf76"></a>

`DIRECT = 0U`

 

Direct HTTP.

  

<a id="namespaceespectre_1a78137e71d7f05fcbfbda841d3a1fc91baab0a7cf5deeda86b66467df64c3b6122"></a>

`MQTT`

 

MQTT command topic.

  

Only `update_device`, `update_sensing`, `recalibrate`, and `read_diagnostics` are accepted from it.

 

<a id="namespaceespectre_1a78137e71d7f05fcbfbda841d3a1fc91bac31870dbba5ac72e2f563d5d66586fcd"></a>

`ESPHOME`

 

An ESPHome entity or service.

  

<a id="namespaceespectre_1a78137e71d7f05fcbfbda841d3a1fc91baa8a5f21c20fd888a9397997f73863e73"></a>

`MATTER`

 

A Matter attribute or command.

  


<a id="namespaceespectre_1a7b0352147eec65c1f73a9d8714c4596d"></a>

### `raw_csi_packet_callback_t`


```cpp
using espectre::raw_csi_packet_callback_t = bool (*)(void *context, const RawCsiPacketView &packet)
```

 

Consume one packet synchronously from the Wi-Fi CSI capture context.

  

The callback must remain bounded, non-blocking, and allocation-free. It may copy the packet into a preallocated bounded queue for another task. Returning false reports that the consumer did not accept this packet, for example because that queue was full; collection continues, and the consumer owns any drop or backpressure accounting.

 

`context` is the opaque caller-owned value supplied to `start_raw_collection()`. `packet` is a normalized CSI view valid only during the call. Return true when the consumer accepted the packet, or false when it dropped it; the runtime does not stop collection on false.

  

<a id="namespaceespectre_1a478bd5431108f78995bfb1c53acc3e25"></a>

### `EspectreCommandValidator`


```cpp
using espectre::EspectreCommandValidator = bool (*)(const std::vector<JsonObjectField> &fields,
                                       EspectreCommand *command, std::string *error)
```

 

Validate decoded parameters and populate the command before dispatch.

  

The parser supplies valid JSON fields and the command identity. Fields from [parse\_espectre\_command()](#namespaceespectre_1affd612c44046053715f0e4947c579959) also include the request's `command_id` and `command`. Validators must not execute commands or change device state. Ignore command output after a rejected validation.

  

<a id="namespaceespectre_1a47f56ef0a5dfb7004c12e04f60fcc511"></a>

### `LogEnabledCallback`


```cpp
using espectre::LogEnabledCallback = bool (*)(void *context, LogLevel level, const char *tag)
```

 

Return whether a sink accepts a message with the supplied level and tag.

   

<a id="namespaceespectre_1af956f386b6f44926d0860f7ca0dffdd0"></a>

### `LogWriteCallback`


```cpp
using espectre::LogWriteCallback = void (*)(void *context, LogLevel level, const char *tag, int line,
                                 const char *format, va_list args)
```

 

Consume one enabled ESPectre log message before the supplied argument list expires.

   

<a id="namespaceespectre_1a1eaac1c4c744a0c2aa7a1013a884087e"></a>

### `SelectedSubcarriers`


```cpp
using espectre::SelectedSubcarriers = std::array<uint8_t, HT20_SELECTED_BAND_SIZE>
```

   

<a id="namespaceespectre_1a813ec6a7ade93fd50621b8138c0ebe92"></a>

### `FrontendMqttConnectedCallback`


```cpp
using espectre::FrontendMqttConnectedCallback = std::function<void(bool)>
```

   

<a id="namespaceespectre_1a5c8f69b635e49d299f2dadb56b43074d"></a>

### `MdnsTxtRecords`


```cpp
using espectre::MdnsTxtRecords = std::vector<std::pair<std::string, std::string>>
```

 

DNS-SD TXT records as key and value pairs.

  

A `txtvers` entry is always transmitted first.

  

<a id="namespaceespectre_1aaca2bec6937994f03279640eba6ea6a2"></a>

### `standalone_wifi_callback_t`


```cpp
using espectre::standalone_wifi_callback_t = std::function<void()>
```

 

Connection-state callback, delivered from [StandaloneWifiService::loop()](#classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c).

   

<a id="namespaceespectre_1a841cce05055be401e9d7f541f67c0f17"></a>

### `standalone_wifi_scan_callback_t`


```cpp
using espectre::standalone_wifi_scan_callback_t = 
std::function<void(esp_err_t, const std::vector<StandaloneWifiAccessPoint> &)>
```

 

Scan result callback, delivered from [StandaloneWifiService::loop()](#classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c).

  

Receives `ESP_OK` or the driver error, and at most 32 access points sorted by descending RSSI.

  

<a id="namespaceespectre_1a8b131fc80e5f6619153aaf47d7a61dc9"></a>

### `csi_traffic_packet_callback_t`


```cpp
using espectre::csi_traffic_packet_callback_t = void (*)(void *, const UdpDatagramPeer &, uint64_t)
```

 

Called for each accepted external traffic packet, from the ingress loop().

  

Receives the registered context, the sender, and the cumulative count of accepted packets.

  

<a id="namespaceespectre_1a64ef59dbd1b0e33b0d19ba5ead0b9301"></a>

### `wifi_connected_callback_t`


```cpp
using espectre::wifi_connected_callback_t = std::function<void(const esp_netif_ip_info_t &)>
```

   

<a id="namespaceespectre_1ab5095f85174c76bb5eef718e24479044"></a>

### `wifi_disconnected_callback_t`


```cpp
using espectre::wifi_disconnected_callback_t = std::function<void()>
```

   

<a id="namespaceespectre_1a2eaa099b9086c9f90afcc8001d90afdc"></a>

### `wifi_csi_rx_refresh_callback_t`


```cpp
using espectre::wifi_csi_rx_refresh_callback_t = std::function<void(esp_err_t)>
```

   

<a id="namespaceespectre_1a664f7aebe8d7f8986a2d83e28357cc87"></a>

### `FrontendCommandCapabilities`


```cpp
using espectre::FrontendCommandCapabilities = EspectreCapabilityProfile
```

 

The advertised surface a command must belong to before it is executed.

   


<a id="namespaceespectre_1a186d8ab957e623995b7886680bed2b29"></a>

### `RAW_CSI_RECORD_MAGIC`


```cpp
constexpr uint16_t espectre::RAW_CSI_RECORD_MAGIC = 0x4353U
```

   

<a id="namespaceespectre_1aa6cd6c48916e2a6c73f2a3368ba29afe"></a>

### `RAW_CSI_RECORD_VERSION_V8`


```cpp
constexpr uint8_t espectre::RAW_CSI_RECORD_VERSION_V8 = 8U
```

   

<a id="namespaceespectre_1acab3236d6dc24a0de6613d494177569a"></a>

### `RAW_CSI_RECORD_VERSION`


```cpp
constexpr uint8_t espectre::RAW_CSI_RECORD_VERSION = RAW_CSI_RECORD_VERSION_V8
```

   

<a id="namespaceespectre_1a24dad547c0781d8f0f29395e0bed182f"></a>

### `RAW_CSI_MAX_PAYLOAD_BYTES`


```cpp
constexpr size_t espectre::RAW_CSI_MAX_PAYLOAD_BYTES = 512U
```

   

<a id="namespaceespectre_1a6d19fef4bba723c7e98adda2a45aed2c"></a>

### `RAW_CSI_MAX_RECORD_BYTES`


```cpp
constexpr size_t espectre::RAW_CSI_MAX_RECORD_BYTES                                              =
sizeof(RawCsiRecordHeaderV8) + RAW_CSI_MAX_PAYLOAD_BYTES
```

   

<a id="namespaceespectre_1ad97c50bf378e0be4ecca2d57aae35f21"></a>

### `ESPECTRE_RAW_CSI_ENDPOINT`


```cpp
constexpr char espectre::ESPECTRE_RAW_CSI_ENDPOINT[][] = "/espectre/v1/csi"
```

   

<a id="namespaceespectre_1a1571e2dbb44f5b5edacc83b4d1539ea9"></a>

### `ESPECTRE_RAW_CSI_PROTOCOL_VERSION`


```cpp
constexpr uint8_t espectre::ESPECTRE_RAW_CSI_PROTOCOL_VERSION = 1U
```

   

<a id="namespaceespectre_1a2c47aea6a64e9bbf1699a0066f9c437f"></a>

### `ESPECTRE_RAW_CSI_RECORD_VERSION`


```cpp
constexpr uint8_t espectre::ESPECTRE_RAW_CSI_RECORD_VERSION = RAW_CSI_RECORD_VERSION_V8
```

   

<a id="namespaceespectre_1a74df0adfb1aeee5b74d72ff5650afc51"></a>

### `ESPECTRE_RAW_CSI_SESSION_ID_BYTES`


```cpp
constexpr size_t espectre::ESPECTRE_RAW_CSI_SESSION_ID_BYTES = 16U
```

   

<a id="namespaceespectre_1ad78ee1950a9973d84c25e6b5e925aff4"></a>

### `ESPECTRE_RAW_CSI_RESPONSE_MAGIC`


```cpp
constexpr uint32_t espectre::ESPECTRE_RAW_CSI_RESPONSE_MAGIC = 0x52505345U
```

   

<a id="namespaceespectre_1a212cc7fe3aa038d9e1326fc8037ee3db"></a>

### `RUNTIME_CSI_CAPTURE_PROFILE_DEFAULT_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_CSI_CAPTURE_PROFILE_DEFAULT_NAME = "auto"
```

   

<a id="namespaceespectre_1a177c18a106b6080f362093d71a68fabf"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_PING_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_PING_NAME = "ping"
```

   

<a id="namespaceespectre_1a15bc0df459745afa7ae4f9e4c6f34b5f"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_DNS_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_DNS_NAME = "dns"
```

   

<a id="namespaceespectre_1ae6e8beabd6199438e40524e01b53c22b"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_DNS_TCP_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_DNS_TCP_NAME = "dns_tcp"
```

   

<a id="namespaceespectre_1a4013ba85b37d675d5a44588073b4b670"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_WIFI_RAW_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_WIFI_RAW_NAME = "wifi_raw"
```

   

<a id="namespaceespectre_1a315b2fe0bb0c4b2d1ce61f619538cdde"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_EXTERNAL_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_EXTERNAL_NAME = "external"
```

   

<a id="namespaceespectre_1ae798b6e9325d406dacc0ab49f991df26"></a>

### `RUNTIME_TRAFFIC_GENERATOR_MODE_DEFAULT_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_TRAFFIC_GENERATOR_MODE_DEFAULT_NAME = "ping"
```

   

<a id="namespaceespectre_1af8f4e638e243e4b5a4cc9f781821abd6"></a>

### `RUNTIME_DETECTION_ALGORITHM_LIGHTWEIGHT_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_DETECTION_ALGORITHM_LIGHTWEIGHT_NAME = "lightweight"
```

   

<a id="namespaceespectre_1a5827219e367d7820fa6e9e996e16ea27"></a>

### `RUNTIME_DETECTION_ALGORITHM_HIGH_ACCURACY_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_DETECTION_ALGORITHM_HIGH_ACCURACY_NAME = "high_accuracy"
```

   

<a id="namespaceespectre_1a44d5c8854bb3a570793dcee5542244d5"></a>

### `RUNTIME_DETECTION_ALGORITHM_DEFAULT_NAME`


```cpp
constexpr const char* const espectre::RUNTIME_DETECTION_ALGORITHM_DEFAULT_NAME = "lightweight"
```

   

<a id="namespaceespectre_1afd6e4e1d251c290d51df4263fda0750d"></a>

### `RUNTIME_THRESHOLD_MIN`


```cpp
constexpr float espectre::RUNTIME_THRESHOLD_MIN = 0.0f
```

   

<a id="namespaceespectre_1a5a433a007084875084bee62d094cab95"></a>

### `RUNTIME_THRESHOLD_MAX`


```cpp
constexpr float espectre::RUNTIME_THRESHOLD_MAX = 1.0f
```

   

<a id="namespaceespectre_1a2f7c72dc6bebf5bf906536101a6b1345"></a>

### `RUNTIME_HIGH_ACCURACY_THRESHOLD_MAX`


```cpp
constexpr float espectre::RUNTIME_HIGH_ACCURACY_THRESHOLD_MAX = 1.0f
```

   

<a id="namespaceespectre_1a4f0959b9772eefeae08cb0770015eee7"></a>

### `RUNTIME_THRESHOLD_DEFAULT`


```cpp
constexpr float espectre::RUNTIME_THRESHOLD_DEFAULT = LIGHTWEIGHT_DEFAULT_THRESHOLD
```

   

<a id="namespaceespectre_1ae1871531cd739565548b365e003788fd"></a>

### `RUNTIME_WINDOW_SIZE_MS_MIN`


```cpp
constexpr uint32_t espectre::RUNTIME_WINDOW_SIZE_MS_MIN = 1000U
```

   

<a id="namespaceespectre_1a4c208f0f3bb11b8ff3aa3e51674b033e"></a>

### `RUNTIME_WINDOW_SIZE_MS_MAX`


```cpp
constexpr uint32_t espectre::RUNTIME_WINDOW_SIZE_MS_MAX = 2000U
```

   

<a id="namespaceespectre_1a13c8a64d1ea77fb65719fc2ffb8bdb45"></a>

### `RUNTIME_WINDOW_SIZE_MS_DEFAULT`


```cpp
constexpr uint32_t espectre::RUNTIME_WINDOW_SIZE_MS_DEFAULT = 1000U
```

   

<a id="namespaceespectre_1abcca8e8bd6537b2fed9f7dc11e62236c"></a>

### `RUNTIME_CSI_TARGET_PPS_MIN`


```cpp
constexpr uint32_t espectre::RUNTIME_CSI_TARGET_PPS_MIN = 1U
```

   

<a id="namespaceespectre_1a403c34b91ec353131e952dac15bf2ff4"></a>

### `RUNTIME_CSI_TARGET_PPS_MAX`


```cpp
constexpr uint32_t espectre::RUNTIME_CSI_TARGET_PPS_MAX = 500U
```

   

<a id="namespaceespectre_1a583bc098543bc63653f26960274b2ad1"></a>

### `RUNTIME_CSI_TARGET_PPS_DEFAULT`


```cpp
constexpr uint32_t espectre::RUNTIME_CSI_TARGET_PPS_DEFAULT = 100U
```

   

<a id="namespaceespectre_1adac330f75e60dcf8bbc56efa51cac931"></a>

### `RUNTIME_HEARTBEAT_INTERVAL_MS`


```cpp
constexpr uint32_t espectre::RUNTIME_HEARTBEAT_INTERVAL_MS = 1000U
```

   

<a id="namespaceespectre_1aa957a79703f3f36f20564faaf6993407"></a>

### `RUNTIME_EVALUATION_INTERVAL_MS_MIN`


```cpp
constexpr uint32_t espectre::RUNTIME_EVALUATION_INTERVAL_MS_MIN = 10
```

   

<a id="namespaceespectre_1a76f1e1c451892d2a18476282920c5083"></a>

### `RUNTIME_EVALUATION_INTERVAL_MS_MAX`


```cpp
constexpr uint32_t espectre::RUNTIME_EVALUATION_INTERVAL_MS_MAX = 10000
```

   

<a id="namespaceespectre_1abc8035d1720779136e60e9a88a0e8379"></a>

### `RUNTIME_EVALUATION_INTERVAL_MS_DEFAULT`


```cpp
constexpr uint32_t espectre::RUNTIME_EVALUATION_INTERVAL_MS_DEFAULT = 250
```

   

<a id="namespaceespectre_1a7f65a463577a02ef0bdfe49dd9d8c1a5"></a>

### `RUNTIME_MOTION_HITS_MIN`


```cpp
constexpr uint8_t espectre::RUNTIME_MOTION_HITS_MIN = 1
```

   

<a id="namespaceespectre_1a42ac71e1ad53db97efbf0898dfba62a0"></a>

### `RUNTIME_MOTION_HITS_MAX`


```cpp
constexpr uint8_t espectre::RUNTIME_MOTION_HITS_MAX = 20
```

   

<a id="namespaceespectre_1a028b847c20853cced681ca0ff3ad147c"></a>

### `RUNTIME_MOTION_ON_HITS_DEFAULT`


```cpp
constexpr uint8_t espectre::RUNTIME_MOTION_ON_HITS_DEFAULT = 4
```

   

<a id="namespaceespectre_1a40824ccf41b07b064f7525a39576cf94"></a>

### `RUNTIME_MOTION_OFF_HITS_DEFAULT`


```cpp
constexpr uint8_t espectre::RUNTIME_MOTION_OFF_HITS_DEFAULT = 3
```

   

<a id="namespaceespectre_1a6dc500d40bcaf9eb8c919fe6e09cd022"></a>

### `RUNTIME_LOWPASS_ENABLED_DEFAULT`


```cpp
constexpr bool espectre::RUNTIME_LOWPASS_ENABLED_DEFAULT = false
```

   

<a id="namespaceespectre_1a0b99ade66a66ac0a13036513a81f6603"></a>

### `RUNTIME_LOWPASS_CUTOFF_MIN`


```cpp
constexpr float espectre::RUNTIME_LOWPASS_CUTOFF_MIN = 5.0f
```

   

<a id="namespaceespectre_1af586a478157c4558cda661fa83d923cd"></a>

### `RUNTIME_LOWPASS_CUTOFF_MAX`


```cpp
constexpr float espectre::RUNTIME_LOWPASS_CUTOFF_MAX = 20.0f
```

   

<a id="namespaceespectre_1a772d7d6b6983a5c8494423e18fffaf53"></a>

### `RUNTIME_LOWPASS_CUTOFF_DEFAULT`


```cpp
constexpr float espectre::RUNTIME_LOWPASS_CUTOFF_DEFAULT = 11.0f
```

   

<a id="namespaceespectre_1af46a5471c983b1f109895d59157feb20"></a>

### `RUNTIME_HAMPEL_ENABLED_DEFAULT`


```cpp
constexpr bool espectre::RUNTIME_HAMPEL_ENABLED_DEFAULT = true
```

   

<a id="namespaceespectre_1a47c2f441115ede397c06d5bc899ec450"></a>

### `RUNTIME_HAMPEL_WINDOW_MIN`


```cpp
constexpr uint8_t espectre::RUNTIME_HAMPEL_WINDOW_MIN = 3
```

   

<a id="namespaceespectre_1a49f3bcfd4d73eab0387bdddee7ee938b"></a>

### `RUNTIME_HAMPEL_WINDOW_MAX`


```cpp
constexpr uint8_t espectre::RUNTIME_HAMPEL_WINDOW_MAX = 11
```

   

<a id="namespaceespectre_1a288d1fd358e79e234ddeb67716b7a409"></a>

### `RUNTIME_HAMPEL_WINDOW_DEFAULT`


```cpp
constexpr uint8_t espectre::RUNTIME_HAMPEL_WINDOW_DEFAULT = 7
```

   

<a id="namespaceespectre_1ae5995a8c638215586d44542666335423"></a>

### `RUNTIME_HAMPEL_THRESHOLD_MIN`


```cpp
constexpr float espectre::RUNTIME_HAMPEL_THRESHOLD_MIN = 1.0f
```

   

<a id="namespaceespectre_1a0791cf4717749234bd7f410e0835296a"></a>

### `RUNTIME_HAMPEL_THRESHOLD_MAX`


```cpp
constexpr float espectre::RUNTIME_HAMPEL_THRESHOLD_MAX = 10.0f
```

   

<a id="namespaceespectre_1aef979169064e256a1dc21d83268a8413"></a>

### `RUNTIME_HAMPEL_THRESHOLD_DEFAULT`


```cpp
constexpr float espectre::RUNTIME_HAMPEL_THRESHOLD_DEFAULT = 5.0f
```

   

<a id="namespaceespectre_1a7c7e37b036bf9c750ffad94cc3f38f9b"></a>

### `RUNTIME_NETWORK_PORT_MIN`


```cpp
constexpr uint16_t espectre::RUNTIME_NETWORK_PORT_MIN = 1U
```

   

<a id="namespaceespectre_1a0f402dae6c22e383c6b47630879afa75"></a>

### `RUNTIME_NETWORK_PORT_MAX`


```cpp
constexpr uint16_t espectre::RUNTIME_NETWORK_PORT_MAX = UINT16_MAX
```

   

<a id="namespaceespectre_1aa38060237841c079d8afb7e5ad41071b"></a>

### `RUNTIME_CSI_TRAFFIC_UDP_PORT_DEFAULT`


```cpp
constexpr uint16_t espectre::RUNTIME_CSI_TRAFFIC_UDP_PORT_DEFAULT = 5555
```

   

<a id="namespaceespectre_1a65e83d64d1c3f527d18a1da78e0b8dab"></a>

### `RUNTIME_CSI_TRAFFIC_MULTICAST_GROUP_DEFAULT`


```cpp
constexpr const char* const espectre::RUNTIME_CSI_TRAFFIC_MULTICAST_GROUP_DEFAULT = "239.255.0.1"
```

   

<a id="namespaceespectre_1a7d2c42f00556433c50808762f93556bc"></a>

### `RUNTIME_CSI_TRAFFIC_MARKER_BYTES`


```cpp
constexpr uint8_t espectre::RUNTIME_CSI_TRAFFIC_MARKER_BYTES[][] = {0xF0U, 0x9FU, 0x91U, 0xBBU}
```

   

<a id="namespaceespectre_1a0217d11161d783391700195752d0abe9"></a>

### `RUNTIME_CSI_TRAFFIC_MARKER_LENGTH`


```cpp
constexpr size_t espectre::RUNTIME_CSI_TRAFFIC_MARKER_LENGTH = 4U
```

   

<a id="namespaceespectre_1a08717633496abf2eeb11f9a12f83c3e2"></a>

### `RUNTIME_CSI_TRAFFIC_MARKER_UTF8`


```cpp
constexpr const char* const espectre::RUNTIME_CSI_TRAFFIC_MARKER_UTF8 = "👻"
```

   

<a id="namespaceespectre_1ac0d561a007409fc2c0a940f9e5db2c8d"></a>

### `RUNTIME_CSI_TRAFFIC_EXPECTED_PAYLOAD_MAX`


```cpp
constexpr size_t espectre::RUNTIME_CSI_TRAFFIC_EXPECTED_PAYLOAD_MAX = 16U
```

   

<a id="namespaceespectre_1a647011431c82d51c8630e5304f968023"></a>

### `ESPECTRE_DEVICE_LABEL_MAX_LENGTH`


```cpp
constexpr size_t espectre::ESPECTRE_DEVICE_LABEL_MAX_LENGTH = 32U
```

 

Matter Basic Information NodeLabel limit, shared by all Direct frontends.

   

<a id="namespaceespectre_1a44771ad0a8deef4590f951be92242be3"></a>

### `ESPECTRE_COMMAND_MAX_PAYLOAD_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_COMMAND_MAX_PAYLOAD_SIZE = 2048U
```

 

Maximum serialized command-request size accepted by every transport.

   

<a id="namespaceespectre_1a27be540efef19a111bae40cf08a98cfe"></a>

### `ESPECTRE_PROTOCOL_VERSION`


```cpp
constexpr const char* espectre::ESPECTRE_PROTOCOL_VERSION = "1.0"
```

 

Protocol version reported by capabilities and discovery.

   

<a id="namespaceespectre_1a28134da0cfd709e9903630c9a4e1ffcd"></a>

### `ESPECTRE_DNS_SD_TXT_SCHEMA_VERSION`


```cpp
constexpr const char* espectre::ESPECTRE_DNS_SD_TXT_SCHEMA_VERSION = "1"
```

 

DNS-SD TXT record schema advertised as the RFC 6763 `txtvers` value.

   

<a id="namespaceespectre_1aa9bcecab1d67487af0b736b8637b6138"></a>

### `ESPECTRE_COMMAND_ID_MAX_LENGTH`


```cpp
constexpr size_t espectre::ESPECTRE_COMMAND_ID_MAX_LENGTH = 64U
```

 

Maximum canonical command correlation identifier length.

   

<a id="namespaceespectre_1a26505654b6fa88f6cc3c9f86b64958e9"></a>

### `ESPECTRE_TOPIC_PREFIX`


```cpp
constexpr const char* espectre::ESPECTRE_TOPIC_PREFIX = "espectre/v1/devices"
```

 

Default MQTT topic root.

  

Override per device with [`EspectreDeviceConfig::topic_prefix`](#structespectre_1_1_espectre_device_config_1ae89cde8ec77492cd8dd8fb315206630f).

  

<a id="namespaceespectre_1a86c5bfd099c8fce0440c7bf8aab22d86"></a>

### `ESPECTRE_DEFAULT_DEVICE_ID`


```cpp
constexpr uint64_t espectre::ESPECTRE_DEFAULT_DEVICE_ID = 0U
```

 

Sentinel meaning "use the runtime-generated device id".

   

<a id="namespaceespectre_1a13bc6643d765f244dd767ad20084a3fd"></a>

### `ESPECTRE_DEFAULT_DEVICE_LABEL`


```cpp
constexpr const char* espectre::ESPECTRE_DEFAULT_DEVICE_LABEL = ""
```

 

Empty label, meaning the device id is used as the display name.

   

<a id="namespaceespectre_1a3bc81a65899ce7cc811b7897ea57bedb"></a>

### `ESPECTRE_DIRECT_HTTP_PORT`


```cpp
constexpr uint16_t espectre::ESPECTRE_DIRECT_HTTP_PORT = 0xF47BU
```

 

ESPectre service port: low 16 bits of U+1F47B GHOST (0xF47B).

   

<a id="namespaceespectre_1a9b21dc9879a1b2d70a1582f213c49a2b"></a>

### `ESPECTRE_DIRECT_HTTP_BASE_ENDPOINT`


```cpp
constexpr const char* espectre::ESPECTRE_DIRECT_HTTP_BASE_ENDPOINT = "/espectre/v1"
```

   

<a id="namespaceespectre_1a09e93416235f3d4fe07de4eee57db81f"></a>

### `ESPECTRE_DIRECT_HTTP_EVENTS_ENDPOINT`


```cpp
constexpr const char* espectre::ESPECTRE_DIRECT_HTTP_EVENTS_ENDPOINT = "/espectre/v1/events"
```

   

<a id="namespaceespectre_1a1c5ba9b3707b5eb96b6f3bab004fcfcd"></a>

### `ESPECTRE_DIRECT_HTTP_TRANSPORT`


```cpp
constexpr const char* espectre::ESPECTRE_DIRECT_HTTP_TRANSPORT = "http"
```

   

<a id="namespaceespectre_1adfc7361b80006da4cca67b96224221d9"></a>

### `ESPECTRE_DIRECT_MAX_REQUEST_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_DIRECT_MAX_REQUEST_SIZE = ESPECTRE_COMMAND_MAX_PAYLOAD_SIZE
```

   

<a id="namespaceespectre_1adb8f7243a68de4e7cd7ebad471875d51"></a>

### `ESPECTRE_DIRECT_MAX_RESPONSE_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_DIRECT_MAX_RESPONSE_SIZE = 8192U
```

   

<a id="namespaceespectre_1a90f09ac217de8fc9fe33fa72d0dca455"></a>

### `ESPECTRE_DIRECT_MAX_REQUEST_ID_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_DIRECT_MAX_REQUEST_ID_SIZE = ESPECTRE_COMMAND_ID_MAX_LENGTH
```

  

**Deprecated:** 

Use [`ESPECTRE_COMMAND_ID_MAX_LENGTH`](#namespaceespectre_1aa9bcecab1d67487af0b736b8637b6138); Direct uses the canonical limit.

  

<a id="namespaceespectre_1a53e26f01271bcce51eabeb7f765385a1"></a>

### `ESPECTRE_DIRECT_MAX_METHOD_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_DIRECT_MAX_METHOD_SIZE = 64U
```

  

**Deprecated:** 

Command names are validated by the canonical registry.

  

<a id="namespaceespectre_1a0480250c15d0e8b1a160fc5a825823bf"></a>

### `LIGHTWEIGHT_DEFAULT_THRESHOLD`


```cpp
constexpr float espectre::LIGHTWEIGHT_DEFAULT_THRESHOLD = 0.6621854538596202f
```

   

<a id="namespaceespectre_1ad5207970e48af47dc7eb1604269bdc58"></a>

### `LIGHTWEIGHT_MIN_THRESHOLD`


```cpp
constexpr float espectre::LIGHTWEIGHT_MIN_THRESHOLD = 0.0f
```

   

<a id="namespaceespectre_1ad092437163d2cdb5c5df9649cdd4c66d"></a>

### `LIGHTWEIGHT_MAX_THRESHOLD`


```cpp
constexpr float espectre::LIGHTWEIGHT_MAX_THRESHOLD = 1.0f
```

   

<a id="namespaceespectre_1a738158b5a07a1d20dd13553fefe9aba4"></a>

### `LIGHTWEIGHT_STARTUP_THRESHOLD_FACTOR`


```cpp
constexpr float espectre::LIGHTWEIGHT_STARTUP_THRESHOLD_FACTOR = 1.0f
```

   

<a id="namespaceespectre_1aa2efb98c798884ab306a6643c116b2a0"></a>

### `HIGH_ACCURACY_DEFAULT_THRESHOLD`


```cpp
constexpr float espectre::HIGH_ACCURACY_DEFAULT_THRESHOLD = 0.5f
```

   

<a id="namespaceespectre_1a9133aa008e101764566e0cb2742e7184"></a>

### `HIGH_ACCURACY_MIN_THRESHOLD`


```cpp
constexpr float espectre::HIGH_ACCURACY_MIN_THRESHOLD = 0.0f
```

   

<a id="namespaceespectre_1a8300aec6a3a88076cfd2a44a2aa1484e"></a>

### `HIGH_ACCURACY_MAX_THRESHOLD`


```cpp
constexpr float espectre::HIGH_ACCURACY_MAX_THRESHOLD = 1.0f
```

   

<a id="namespaceespectre_1af86772d17580cec4bfe57f8481c5c88c"></a>

### `HIGH_ACCURACY_METRIC_SCALE`


```cpp
constexpr float espectre::HIGH_ACCURACY_METRIC_SCALE = 1.0f
```

   

<a id="namespaceespectre_1ade1005795568ea8d80776ac6b6c222c8"></a>

### `LOWPASS_CUTOFF_DEFAULT`


```cpp
constexpr float espectre::LOWPASS_CUTOFF_DEFAULT = 11.0f
```

   

<a id="namespaceespectre_1aac038424c0e9b371ea394c5def3b5158"></a>

### `LOWPASS_CUTOFF_MIN`


```cpp
constexpr float espectre::LOWPASS_CUTOFF_MIN = 5.0f
```

   

<a id="namespaceespectre_1a4accb9aa168687b87a9c3b8202af831c"></a>

### `LOWPASS_CUTOFF_MAX`


```cpp
constexpr float espectre::LOWPASS_CUTOFF_MAX = 20.0f
```

   

<a id="namespaceespectre_1a71e1289119eb2029acb401ef6d5b0aec"></a>

### `LOWPASS_SAMPLE_RATE`


```cpp
constexpr float espectre::LOWPASS_SAMPLE_RATE = 100.0f
```

   

<a id="namespaceespectre_1a5cf095597de0a42f1bbe7f2838440b19"></a>

### `HAMPEL_TURBULENCE_WINDOW_MIN`


```cpp
constexpr uint8_t espectre::HAMPEL_TURBULENCE_WINDOW_MIN = 3U
```

   

<a id="namespaceespectre_1a43683e30117786c03a0f4d5a05bee629"></a>

### `HAMPEL_TURBULENCE_WINDOW_MAX`


```cpp
constexpr uint8_t espectre::HAMPEL_TURBULENCE_WINDOW_MAX = 11U
```

   

<a id="namespaceespectre_1a6014322636960da116aac379b07e896e"></a>

### `HAMPEL_TURBULENCE_WINDOW_DEFAULT`


```cpp
constexpr uint8_t espectre::HAMPEL_TURBULENCE_WINDOW_DEFAULT = 7U
```

   

<a id="namespaceespectre_1aaaab9e2cd7ff1dda6dccd548c48dfd97"></a>

### `HAMPEL_TURBULENCE_THRESHOLD_DEFAULT`


```cpp
constexpr float espectre::HAMPEL_TURBULENCE_THRESHOLD_DEFAULT = 5.0f
```

   

<a id="namespaceespectre_1a173e10371ac46c7dcb7e9fa395102541"></a>

### `HT20_NUM_SUBCARRIERS`


```cpp
constexpr uint16_t espectre::HT20_NUM_SUBCARRIERS = 64U
```

   

<a id="namespaceespectre_1ad7a70d37c99a12759ec87883d9bf5651"></a>

### `HT20_CSI_LEN`


```cpp
constexpr uint16_t espectre::HT20_CSI_LEN = 128U
```

   

<a id="namespaceespectre_1abc9115b9cb972953049e3dee66e7aa16"></a>

### `HT20_CSI_LEN_DOUBLE`


```cpp
constexpr uint16_t espectre::HT20_CSI_LEN_DOUBLE = 256U
```

   

<a id="namespaceespectre_1a95d2500724b3e1de4424ce0ec2dc4aae"></a>

### `HT20_CSI_LEN_SHORT`


```cpp
constexpr uint16_t espectre::HT20_CSI_LEN_SHORT = 114U
```

   

<a id="namespaceespectre_1aaa977261eaadbc6e80a6a9d0201b061d"></a>

### `LLTF20_CSI_LEN_SHORT`


```cpp
constexpr uint16_t espectre::LLTF20_CSI_LEN_SHORT = 106U
```

   

<a id="namespaceespectre_1a3807e5300bedcf7488f0db72003bab08"></a>

### `HT20_CSI_LEN_SHORT_DOUBLE`


```cpp
constexpr uint16_t espectre::HT20_CSI_LEN_SHORT_DOUBLE = 228U
```

   

<a id="namespaceespectre_1a591e14532ba43e92d1c5d222343a48f5"></a>

### `HT20_CSI_LEN_SHORT_LEFT_PAD`


```cpp
constexpr uint8_t espectre::HT20_CSI_LEN_SHORT_LEFT_PAD = 8U
```

   

<a id="namespaceespectre_1acd18a86eaa0c26991bb7007b43c0c653"></a>

### `HT20_GUARD_BAND_LOW`


```cpp
constexpr uint8_t espectre::HT20_GUARD_BAND_LOW = 4U
```

   

<a id="namespaceespectre_1ab563bdf9c7b5fc82fac271db91e70349"></a>

### `HT20_GUARD_BAND_HIGH`


```cpp
constexpr uint8_t espectre::HT20_GUARD_BAND_HIGH = 60U
```

   

<a id="namespaceespectre_1ae8f908725d3ea09ffe13d62ab0b3afbd"></a>

### `HT20_DC_SUBCARRIER`


```cpp
constexpr uint8_t espectre::HT20_DC_SUBCARRIER = 32U
```

   

<a id="namespaceespectre_1a634c531cce6a62b80e8e6b30cd9c68e2"></a>

### `HT20_SELECTED_BAND_SIZE`


```cpp
constexpr uint8_t espectre::HT20_SELECTED_BAND_SIZE = 12U
```

   

<a id="namespaceespectre_1ab5d5a6532e6d524fa4932baec3f9c86f"></a>

### `DEFAULT_SUBCARRIERS`


```cpp
constexpr uint8_t espectre::DEFAULT_SUBCARRIERS[HT20_SELECTED_BAND_SIZE][HT20_SELECTED_BAND_SIZE]                                              = {
    4U, 8U, 13U, 18U, 23U, 28U, 36U, 41U, 46U, 51U, 56U, 60U,
}
```

   

<a id="namespaceespectre_1af5dd9de9f8a533814ab31e3a9b488355"></a>

### `LIGHTWEIGHT_AUTOCORR_CENTER`


```cpp
constexpr float espectre::LIGHTWEIGHT_AUTOCORR_CENTER = 0.3919344866784947f
```

   

<a id="namespaceespectre_1ae572d68a06e48c1544396336d7c412aa"></a>

### `LIGHTWEIGHT_AUTOCORR_SCALE`


```cpp
constexpr float espectre::LIGHTWEIGHT_AUTOCORR_SCALE = 0.3798648330757351f
```

   

<a id="namespaceespectre_1a5e4947ea9b5684a8fbd155531a727666"></a>

### `LIGHTWEIGHT_AUTOCORR_WEIGHT`


```cpp
constexpr float espectre::LIGHTWEIGHT_AUTOCORR_WEIGHT = 5.083034533668216f
```

   

<a id="namespaceespectre_1aca6d5e503235ecac39b4e8ec723ba222"></a>

### `LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_CENTER`


```cpp
constexpr float espectre::LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_CENTER = 0.24612139211074338f
```

   

<a id="namespaceespectre_1a1b4a48f416593b0a97f723dc2f4def92"></a>

### `LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_SCALE`


```cpp
constexpr float espectre::LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_SCALE = 0.20056599613462603f
```

   

<a id="namespaceespectre_1a47e21f8dcc7a45f3a90efcbae0803d6e"></a>

### `LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_WEIGHT`


```cpp
constexpr float espectre::LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_WEIGHT = 4.997501915217463f
```

   

<a id="namespaceespectre_1a183fb0399b6369183f9ee7b498d27379"></a>

### `LIGHTWEIGHT_INTERCEPT`


```cpp
constexpr float espectre::LIGHTWEIGHT_INTERCEPT = 1.0776769868761f
```

   

<a id="namespaceespectre_1ad874aec6dbb9e9e06005175f622a5d91"></a>

### `LIGHTWEIGHT_TRAIN_IDLE_Q95_LOGIT`


```cpp
constexpr float espectre::LIGHTWEIGHT_TRAIN_IDLE_Q95_LOGIT = -2.253902812716911f
```

   

<a id="namespaceespectre_1a8a8f6f5076e59d8c14e9b68b6b15d071"></a>

### `LIGHTWEIGHT_STARTUP_QUANTILE`


```cpp
constexpr float espectre::LIGHTWEIGHT_STARTUP_QUANTILE = 0.95f
```

   

<a id="namespaceespectre_1a46e2adfff54810a8e86d93dc6e0acf04"></a>

### `LIGHTWEIGHT_STARTUP_STRENGTH`


```cpp
constexpr float espectre::LIGHTWEIGHT_STARTUP_STRENGTH = 0.5f
```

   

<a id="namespaceespectre_1a453cecc04ac26e8ba1da62b5e55f36aa"></a>

### `LIGHTWEIGHT_STARTUP_SAMPLE_LIMIT`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_STARTUP_SAMPLE_LIMIT = 120U
```

   

<a id="namespaceespectre_1ab9ef1c62b9a0dfe2f0df849fafc39c79"></a>

### `LIGHTWEIGHT_STARTUP_BASE_SAMPLES`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_STARTUP_BASE_SAMPLES = 40U
```

   

<a id="namespaceespectre_1afbf741d652247d7e0cb7aabc79ce3716"></a>

### `LIGHTWEIGHT_STARTUP_BURST_SAMPLES`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_STARTUP_BURST_SAMPLES = 20U
```

   

<a id="namespaceespectre_1ab52047428b1805ee4d7f3f68b4ad9fd2"></a>

### `LIGHTWEIGHT_STARTUP_RECHECK_SAMPLES`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_STARTUP_RECHECK_SAMPLES = 12U
```

   

<a id="namespaceespectre_1a0fe088856427bd90fb5f1a39f10a2844"></a>

### `LIGHTWEIGHT_STARTUP_BURST_LOGITS`


```cpp
constexpr float espectre::LIGHTWEIGHT_STARTUP_BURST_LOGITS = 2.5f
```

   

<a id="namespaceespectre_1a78b7a41d61a00786ee8108d4701b094e"></a>

### `LIGHTWEIGHT_STARTUP_MIN_SAMPLES`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_STARTUP_MIN_SAMPLES = 28U
```

   

<a id="namespaceespectre_1abc0f3d7eab8e80060094c75444814dd1"></a>

### `LIGHTWEIGHT_CALIBRATION_MOTION_LOGIT`


```cpp
constexpr float espectre::LIGHTWEIGHT_CALIBRATION_MOTION_LOGIT = 5.0f
```

   

<a id="namespaceespectre_1ae63029cfe685635a12ca9c03b4b8550f"></a>

### `LIGHTWEIGHT_NOISY_LINK_THRESHOLD`


```cpp
constexpr float espectre::LIGHTWEIGHT_NOISY_LINK_THRESHOLD = 0.89f
```

   

<a id="namespaceespectre_1a01b743a22c6a69557f80126341092991"></a>

### `LIGHTWEIGHT_SETTLE_BLOCKS`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_SETTLE_BLOCKS = 12U
```

   

<a id="namespaceespectre_1ad4819b7e3ae66e4891815046b4675f7d"></a>

### `LIGHTWEIGHT_SETTLE_BLOCK_EVALUATIONS`


```cpp
constexpr uint8_t espectre::LIGHTWEIGHT_SETTLE_BLOCK_EVALUATIONS = 20U
```

   

<a id="namespaceespectre_1a54ab674f4c505a089ca14218b46b1fa1"></a>

### `LIGHTWEIGHT_SETTLE_MARGIN_LOGITS`


```cpp
constexpr float espectre::LIGHTWEIGHT_SETTLE_MARGIN_LOGITS = 2.7f
```

   

<a id="namespaceespectre_1a66fe1d687dfe9106731a7ed5e8136092"></a>

### `HT20_CLASSIC_ONLY_NULL_BINS`


```cpp
constexpr uint8_t espectre::HT20_CLASSIC_ONLY_NULL_BINS[][] = {29, 30, 31, 33, 34, 35}
```

   

<a id="namespaceespectre_1a460991f7f0cd4871fd1f338fc166b81c"></a>

### `HT20_CENTERED_ONLY_NULL_BINS`


```cpp
constexpr uint8_t espectre::HT20_CENTERED_ONLY_NULL_BINS[][] = {1, 2, 3, 61, 62, 63}
```

   

<a id="namespaceespectre_1a87ab0d558b48a21c390b13b6c153c68d"></a>

### `HT20_LLTF_MISSING_BINS`


```cpp
constexpr uint8_t espectre::HT20_LLTF_MISSING_BINS[][] = {4, 5, 59, 60}
```

   

<a id="namespaceespectre_1ad8f2e24e1681c31efcee0dc5e508af26"></a>

### `TEMPORAL_CSI_MICROSECONDS_PER_SECOND`


```cpp
constexpr uint32_t espectre::TEMPORAL_CSI_MICROSECONDS_PER_SECOND = 1000000U
```

   

<a id="namespaceespectre_1a2af3fbdcae0da1f75af14e8a39ab629c"></a>

### `TEMPORAL_CSI_MINIMUM_COVERAGE_NUMERATOR`


```cpp
constexpr uint8_t espectre::TEMPORAL_CSI_MINIMUM_COVERAGE_NUMERATOR = 7U
```

   

<a id="namespaceespectre_1aff60a06668015197e15387349e04bb3d"></a>

### `TEMPORAL_CSI_MINIMUM_COVERAGE_DENOMINATOR`


```cpp
constexpr uint8_t espectre::TEMPORAL_CSI_MINIMUM_COVERAGE_DENOMINATOR = 10U
```

   

<a id="namespaceespectre_1aa590854a8a59e96754371b7f35c4e48e"></a>

### `TEMPORAL_CSI_SLOT_HALF_DENOMINATOR`


```cpp
constexpr uint8_t espectre::TEMPORAL_CSI_SLOT_HALF_DENOMINATOR = 2U
```

   

<a id="namespaceespectre_1a8911611945c4d9384150e5a08552bda0"></a>

### `DETECTOR_WINDOW_SIZE_MS_MIN`


```cpp
constexpr uint32_t espectre::DETECTOR_WINDOW_SIZE_MS_MIN = 1000U
```

   

<a id="namespaceespectre_1a57fa4ae3e3020de3ce66fd00fd14b939"></a>

### `DETECTOR_WINDOW_SIZE_MS_MAX`


```cpp
constexpr uint32_t espectre::DETECTOR_WINDOW_SIZE_MS_MAX = 2000U
```

   

<a id="namespaceespectre_1a7f6cf82a5d4e26e53ee0f6b852dbabb2"></a>

### `DETECTOR_WINDOW_SIZE_MS_DEFAULT`


```cpp
constexpr uint32_t espectre::DETECTOR_WINDOW_SIZE_MS_DEFAULT = 1000U
```

   

<a id="namespaceespectre_1a292d263e8e374c65abb1c76af1121781"></a>

### `DETECTOR_DEFAULT_WINDOW_SIZE`


```cpp
constexpr uint16_t espectre::DETECTOR_DEFAULT_WINDOW_SIZE = 100
```

   

<a id="namespaceespectre_1af760f0ac7095300522fff6ea2edb6d7c"></a>

### `DETECTOR_MIN_WINDOW_SIZE`


```cpp
constexpr uint16_t espectre::DETECTOR_MIN_WINDOW_SIZE = 1
```

   

<a id="namespaceespectre_1ac7c47f062cc8d9adfd7881bd9fdbfdfb"></a>

### `DETECTOR_MAX_WINDOW_SIZE`


```cpp
constexpr uint16_t espectre::DETECTOR_MAX_WINDOW_SIZE = 1000
```

   

<a id="namespaceespectre_1aabc8a97ebb800fc8c97d279664c586eb"></a>

### `CALIBRATION_NUM_WINDOWS`


```cpp
constexpr uint16_t espectre::CALIBRATION_NUM_WINDOWS = 10
```

   

<a id="namespaceespectre_1aae96d7ab4eb211aac2c5f72d9b3a480c"></a>

### `CALIBRATION_DEFAULT_BUFFER_SIZE`


```cpp
constexpr uint16_t espectre::CALIBRATION_DEFAULT_BUFFER_SIZE                                                =
DETECTOR_DEFAULT_WINDOW_SIZE * CALIBRATION_NUM_WINDOWS
```

   

<a id="namespaceespectre_1ade89f4e051867c201a53266ca487bc00"></a>

### `EVALUATION_INTERVAL_US`


```cpp
constexpr uint32_t espectre::EVALUATION_INTERVAL_US = 250000U
```

   

<a id="namespaceespectre_1a24a334c3fa5dbbc227cf527faf402913"></a>

### `L1_DELTA_LAG_US`


```cpp
constexpr uint32_t espectre::L1_DELTA_LAG_US = 100000U
```

   

<a id="namespaceespectre_1ae59e57079a7c71da7ba4b2c9a87868b3"></a>

### `TURB_AUTOCORR_LAG_US`


```cpp
constexpr uint32_t espectre::TURB_AUTOCORR_LAG_US = 10000U
```

   

<a id="namespaceespectre_1abd53db5fbc189b5864021cac6914fb5c"></a>

### `DETECTOR_L1_DELTA_LAG_DEFAULT`


```cpp
constexpr uint16_t espectre::DETECTOR_L1_DELTA_LAG_DEFAULT = 10U
```

   

<a id="namespaceespectre_1adb267e831a03088b59bb2b2924af6027"></a>

### `DETECTOR_AUTOCORR_LAG_DEFAULT`


```cpp
constexpr uint16_t espectre::DETECTOR_AUTOCORR_LAG_DEFAULT = 1U
```

   

<a id="namespaceespectre_1a7864a488a9f0bc50ab7048258047247b"></a>

### `L1_DELTA_LAG_MAX`


```cpp
constexpr uint16_t espectre::L1_DELTA_LAG_MAX = 32
```

   

<a id="namespaceespectre_1a5eb2d1d16fb41389c7e99d23fc36759d"></a>

### `MIN_PLAUSIBLE_PACKET_INTERVAL_US`


```cpp
constexpr uint32_t espectre::MIN_PLAUSIBLE_PACKET_INTERVAL_US = 200U
```

   

<a id="namespaceespectre_1ab18ef5b016f2a45b3e57911383e7a528"></a>

### `WIFI_CHANNEL_AUTO`


```cpp
constexpr int espectre::WIFI_CHANNEL_AUTO = 0
```

   

<a id="namespaceespectre_1ac6072079a5ee71395587ea95286469a8"></a>

### `WIFI_CHANNEL_2G_MAX`


```cpp
constexpr int espectre::WIFI_CHANNEL_2G_MAX = 14
```

   

<a id="namespaceespectre_1a859a9a7b26d35879fde75cdda7a32f85"></a>

### `kEspectreAsciiLogoLines`


```cpp
constexpr const char* espectre::kEspectreAsciiLogoLines[][]                                                     = {
    "  _____ ____  ____           __            ",
    " | ____/ ___||  _ \\ ___  ___| |_ _ __ ___ ",
    " |  _| \\___ \\| |_) / _ \\/ __| __| '__/ _ \\",
    " | |___ ___) |  __/  __/ (__| |_| | |  __/",
    " |_____|____/|_|   \\___|\\___|\\__|_|  \\___|",
}
```

   

<a id="namespaceespectre_1abc7070382b2620aad729f294d9f00e8d"></a>

### `ESPECTRE_PEER_DISCOVERY_TIMEOUT_MS`


```cpp
constexpr uint32_t espectre::ESPECTRE_PEER_DISCOVERY_TIMEOUT_MS = 3000U
```

   

<a id="namespaceespectre_1a1eb28ce7d48bbb1551343b78c62eb44a"></a>

### `ESPECTRE_PEER_DISCOVERY_MAX_DEVICES`


```cpp
constexpr size_t espectre::ESPECTRE_PEER_DISCOVERY_MAX_DEVICES = 8U
```

   

<a id="namespaceespectre_1a763c9fa6ba6bfe96f1f5d73d2f1eb1ce"></a>

### `ESPECTRE_PEER_DISCOVERY_MAX_ADDRESSES`


```cpp
constexpr size_t espectre::ESPECTRE_PEER_DISCOVERY_MAX_ADDRESSES = 2U
```

   

<a id="namespaceespectre_1a0ab265cc384a2f5d3c4b58f335984291"></a>

### `ESPECTRE_PEER_DISCOVERY_MAX_RESULT_SIZE`


```cpp
constexpr size_t espectre::ESPECTRE_PEER_DISCOVERY_MAX_RESULT_SIZE = 3584U
```

   


<a id="namespaceespectre_1a35ddf262655083501dcdf68b4d934ac0"></a>

### `espectre_sdk_version`


```cpp
constexpr const char * espectre::espectre_sdk_version()
```

 

The SDK version as a string, usable where a macro is not.

  

**Returns:** [`ESPECTRE_SDK_VERSION_STRING`](#espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74), or `"0.0.0"` when unknown. Never null; valid for the process lifetime.

  

<a id="namespaceespectre_1a739067c18cf8673bbc45564cd2a29f2b"></a>

### `runtime_operation_state_name`


```cpp
const char * espectre::runtime_operation_state_name(RuntimeOperationState state)
```

   

<a id="namespaceespectre_1adf6bece0a78ea38870c47f1f721ac096"></a>

### `csi_capture_profile_name`


```cpp
constexpr const char * espectre::csi_capture_profile_name(CsiCaptureProfile profile)
```

   

<a id="namespaceespectre_1a2d1b08a1daef9612d8f797d055f1d84f"></a>

### `csi_capture_profile_uses_lltf`


```cpp
constexpr bool espectre::csi_capture_profile_uses_lltf(CsiCaptureProfile profile)
```

   

<a id="namespaceespectre_1ab673d1c40a3ffe2f300776a1501b1131"></a>

### `resolve_csi_capture_profile`


```cpp
constexpr CsiCaptureProfile espectre::resolve_csi_capture_profile(bool prefers_lltf20, bool supports_vht20, uint8_t wifi_channel, CsiCapturePolicy requested=CsiCapturePolicy::AUTO)
```

 

Resolve the configured capture policy from target capabilities and link channel.

   

<a id="namespaceespectre_1afe16dc0f8dcdb90f8c11b66b03233a35"></a>

### `runtime_threshold_max`


```cpp
constexpr float espectre::runtime_threshold_max(DetectionAlgorithm algorithm)
```

   

<a id="namespaceespectre_1ac2918b7136144625515b36b675d28ee5"></a>

### `runtime_detection_algorithm_valid`


```cpp
constexpr bool espectre::runtime_detection_algorithm_valid(DetectionAlgorithm algorithm)
```

   

<a id="namespaceespectre_1ada2e034534b4f6addb0485fd61bf9924"></a>

### `runtime_traffic_generator_mode_valid`


```cpp
constexpr bool espectre::runtime_traffic_generator_mode_valid(TrafficGeneratorMode mode)
```

   

<a id="namespaceespectre_1a7ebccf5d9764673ec697cac7c059b6f9"></a>

### `runtime_default_threshold`


```cpp
constexpr float espectre::runtime_default_threshold(DetectionAlgorithm algorithm)
```

   

<a id="namespaceespectre_1ae40d935f9a093b8daca17290196df3fa"></a>

### `validate_runtime_threshold`


```cpp
bool espectre::validate_runtime_threshold(float threshold)
```

 

Whether a threshold is finite and inside the range shared by every detector.

   

<a id="namespaceespectre_1a662ded5428c534fcee07d8886852da0a"></a>

### `validate_runtime_threshold_for_algorithm`


```cpp
bool espectre::validate_runtime_threshold_for_algorithm(float threshold, DetectionAlgorithm algorithm)
```

 

Whether a threshold is finite and inside the range of one detector.

   

<a id="namespaceespectre_1a302757e6d7e73d410887f8b7728711a5"></a>

### `runtime_traffic_generator_mode_supported`


```cpp
bool espectre::runtime_traffic_generator_mode_supported(TrafficGeneratorMode mode)
```

 

Whether this build target supports the internal traffic source; host builds accept every valid mode.

   

<a id="namespaceespectre_1a067fa3b169bc3aeb3cbb2679eb388ac0"></a>

### `runtime_capture_profile_supports_traffic`


```cpp
bool espectre::runtime_capture_profile_supports_traffic(CsiCapturePolicy profile, TrafficGeneratorMode mode)
```

 

Whether a configured CSI profile can be combined with the internal source.

   

<a id="namespaceespectre_1a3204487b096871eb46f055d2a8088907"></a>

### `validate_runtime_config`


```cpp
RuntimeConfigError espectre::validate_runtime_config(const RuntimeConfig &config)
```

 

Validate the complete configuration before creating runtime state.

   

<a id="namespaceespectre_1a464f8d16630630601b5136ed82097b34"></a>

### `runtime_config_error_message`


```cpp
const char * espectre::runtime_config_error_message(RuntimeConfigError error)
```

 

Stable diagnostic label for a configuration error.

  

Never returns `nullptr`.

  

<a id="namespaceespectre_1a2afe57057faedef421c7c717f9cc3e33"></a>

### `apply_runtime_control_update`


```cpp
RuntimeConfig espectre::apply_runtime_control_update(RuntimeConfig config, const RuntimeControlUpdate &update)
```

 

Return `config` with `update` applied, as the controller setters apply it.

  

Fields apply in the order detector, threshold, motion hits, then traffic generator mode. Switching to a different detector also adopts that detector's default threshold unless the update sets one. Pass the result to [validate\_runtime\_config()](#namespaceespectre_1a3204487b096871eb46f055d2a8088907) to check the change before applying it.

  

<a id="namespaceespectre_1a87461d595b73c9764e020c3ecd7eea14"></a>

### `runtime_traffic_target_addr`


```cpp
uint32_t espectre::runtime_traffic_target_addr(const RuntimeConfig &config, uint32_t gateway_addr)
```

 

Resolve the internal traffic destination in network byte order; empty uses the gateway, and invalid IPv4 returns zero.

   

<a id="namespaceespectre_1aec161d888273753b9117d92eb3273246"></a>

### `append_runtime_csi_quality_diagnostics_json`


```cpp
void espectre::append_runtime_csi_quality_diagnostics_json(std::string *out, const RuntimeDiagnosticsSnapshot &diagnostics)
```

 

Append capture-quality counters to an already opened JSON object.

   

<a id="namespaceespectre_1a43f43b5fa48477941d70036166ca22c1"></a>

### `append_runtime_performance_diagnostics_json`


```cpp
void espectre::append_runtime_performance_diagnostics_json(std::string *out, const RuntimeDiagnosticsSnapshot &diagnostics, bool include_current_memory=true)
```

 

Append shared platform and performance fields to an existing JSON object.

  

The object must already contain at least one field. Metrics from an incomplete aggregation window are emitted as `null`; unsupported detector timing is identified separately by `detection_timing_supported`.

  

<a id="namespaceespectre_1aea3b512c1c34b6be4240d0839da17a4d"></a>

### `validate_diagnostic_fields`


```cpp
bool espectre::validate_diagnostic_fields(const std::vector< std::string > &fields, unsigned profile=ESPECTRE_DIAGNOSTIC_PROFILE_ALL)
```

 

Validate diagnostic paths, groups, or an exclusive wildcard against the canonical registry.

   

<a id="namespaceespectre_1abdb85601916430789d63639f7708ff4a"></a>

### `diagnostic_response`


```cpp
std::string espectre::diagnostic_response(const std::vector< std::string > &fields, unsigned profile, const std::function< std::string(const char *)> &value)
```

 

Serialize the catalog without reading values, or only selected values from the supplied provider.

  

`profile` is a mask of `ESPECTRE_DIAGNOSTIC_PROFILE_*` values. Empty selections return the catalog. The provider returns one JSON scalar. Unknown profile fields produce an empty response.

  

<a id="namespaceespectre_1ad8e4b0d6a83b94536fa09d8cc9aacc67"></a>

### `runtime_diagnostic_value`


```cpp
std::string espectre::runtime_diagnostic_value(const char *key, const RuntimeDiagnosticsSample *sample, const std::function< const RuntimeDiagnosticsSnapshot &()> &snapshot)
```

 

Read a shared scalar from a cached rate sample or a lazily acquired runtime snapshot.

   

<a id="namespaceespectre_1a9f389e2f1e12234188f554dc04490ab3"></a>

### `read_network_traffic`


```cpp
NetworkTrafficSnapshot espectre::read_network_traffic()
```

 

Read cumulative station counters and refresh the tracked WIFI\_STA\_DEF handle.

  

Call once after creating the station to start tracking and establish a rate baseline, then on each diagnostic interval. Counters persist across sensing restarts and wrap modulo 2^32. Reads and packet updates are thread-safe; the two counters are sampled independently. No payload is inspected.

 

Compile ESPECTRE\_RUNTIME\_ESP\_IDF\_TRAFFIC\_SOURCES and link with ESPECTRE\_RUNTIME\_ESP\_IDF\_TRAFFIC\_LINK\_OPTIONS when consuming the source groups directly. The SDK component already supplies these link options.

  

<a id="namespaceespectre_1a9864a7885166c767516635cd059a8ef6"></a>

### `apply_station_tx_rate`


```cpp
esp_err_t espectre::apply_station_tx_rate()
```

 

Apply the station transmit-rate policy to the associated access point.

  

`CONFIG_ESPECTRE_WIFI_TX_RATE_MBPS` selects Auto, OFDM 6 Mbps, or HT20 MCS0 with long GI; Auto and TX A-MPDU builds leave driver rate selection unchanged. The full runtime applies it itself. Integrations that own the Wi-Fi station call it after every association, including reassociation, and before starting CSI. Requires ESPECTRE\_RUNTIME\_ESP\_IDF\_TRAFFIC\_SOURCES.

 

**Returns:** `ESP_OK`, or the driver error that prevented applying the policy.

  

<a id="namespaceespectre_1a79c04e29909488dd8aae7ee4df04c124"></a>

### `validate_protocol_extension`


```cpp
bool espectre::validate_protocol_extension(const EspectreProtocolExtension &extension, std::string *error=nullptr)
```

 

Reject malformed descriptors and collisions with the SDK or another extension entry.

   

<a id="namespaceespectre_1a042b26831152547bc29a3a8cedd7e5d7"></a>

### `find_extension_route`


```cpp
const EspectreExtensionRoute * espectre::find_extension_route(const EspectreProtocolExtension *extension, const std::string &command)
```

 

Find a command in a valid extension; a null or invalid extension has no routes.

   

<a id="namespaceespectre_1a1f22c8af7f655d2ab62a805f5827bcec"></a>

### `espectre_api_routes`


```cpp
const EspectreApiRoute * espectre::espectre_api_routes(size_t *count)
```

 

Return the immutable v1 resource registry and its entry count.

   

<a id="namespaceespectre_1ad369de74fc2722fa68d76a20e9277e43"></a>

### `espectre_api_events`


```cpp
const EspectreApiEventDescriptor * espectre::espectre_api_events(size_t *count)
```

   

<a id="namespaceespectre_1ad13f75740e4fefd7137021f0b3b5318f"></a>

### `parse_json_object_views`


```cpp
bool espectre::parse_json_object_views(const JsonInput &input, size_t offset, size_t length, std::vector< JsonFieldView > *fields, std::string *error=nullptr)
```

 

Validate an object range, rejecting duplicate fields, without copying its values.

   

<a id="namespaceespectre_1adf2555a878b431297e221c26e14c6800"></a>

### `parse_json_array_object_views`


```cpp
bool espectre::parse_json_array_object_views(const JsonInput &input, size_t offset, size_t length, std::vector< std::vector< JsonFieldView > > *objects, std::string *error=nullptr)
```

 

Validate an array of objects and retain field offsets relative to the array range.

   

<a id="namespaceespectre_1aba834ba61d7ff59cc037d0d8b13f6dc6"></a>

### `parse_json_string_value`


```cpp
bool espectre::parse_json_string_value(const JsonInput &input, size_t offset, size_t length, std::string *value, std::string *error=nullptr)
```

 

Decode one complete JSON string token from the specified input range.

   

<a id="namespaceespectre_1a64b54752d746f722b1176a3fe995caef"></a>

### `append_json_string`


```cpp
void espectre::append_json_string(std::string *out, const char *value)
```

   

<a id="namespaceespectre_1a4c1693617d0914f60a81ced263a8fb72"></a>

### `append_json_pair`


```cpp
void espectre::append_json_pair(std::string *out, const char *key, const char *value, bool first=false)
```

   

<a id="namespaceespectre_1a3e05f93260fcedb1a0f010c52825ac67"></a>

### `has_json_key`


```cpp
bool espectre::has_json_key(const std::string &payload, const char *key)
```

   

<a id="namespaceespectre_1ada7befc8e455d080569e41b4072dffa6"></a>

### `extract_json_string`


```cpp
std::string espectre::extract_json_string(const std::string &payload, const char *key)
```

   

<a id="namespaceespectre_1ac22e051693ae366770a862f8ae6511de"></a>

### `extract_json_number_token`


```cpp
std::string espectre::extract_json_number_token(const std::string &payload, const char *key)
```

   

<a id="namespaceespectre_1ad94497c9202bbf4d01870ca2e7ce5dd1"></a>

### `decode_urlencoded_component`


```cpp
bool espectre::decode_urlencoded_component(const std::string &encoded, std::string *decoded, std::string *error=nullptr)
```

   

<a id="namespaceespectre_1ae9a669e530c21661ba4bf329fc86927d"></a>

### `encode_urlencoded_component`


```cpp
std::string espectre::encode_urlencoded_component(const std::string &value)
```

   

<a id="namespaceespectre_1a6089f509e536788cce4984fc7569bf9a"></a>

### `parse_urlencoded_key_value_pairs`


```cpp
bool espectre::parse_urlencoded_key_value_pairs(const std::string &payload, std::vector< std::pair< std::string, std::string > > *pairs, std::string *error=nullptr)
```

   

<a id="namespaceespectre_1a20e153bb946d91e4aae1899f1c26586b"></a>

### `parse_json_object_fields`


```cpp
bool espectre::parse_json_object_fields(const std::string &payload, std::vector< JsonObjectField > *fields, std::string *error=nullptr)
```

 

Parse and validate one complete JSON object, rejecting duplicate field names.

   

<a id="namespaceespectre_1ab8ee058514ade62ed06d26edd5ad5e72"></a>

### `parse_json_array_objects`


```cpp
bool espectre::parse_json_array_objects(const std::string &payload, std::vector< std::vector< JsonObjectField > > *objects, std::string *error=nullptr)
```

 

Parse a complete array of objects, rejecting invalid or non-object entries.

   

<a id="namespaceespectre_1ac9e20ff827dae90b16db7b332fa4dc19"></a>

### `parse_json_array_strings`


```cpp
bool espectre::parse_json_array_strings(const std::string &payload, std::vector< std::string > *strings, std::string *error=nullptr)
```

 

Parse a complete array containing only JSON strings.

   

<a id="namespaceespectre_1ae7d7210fe0bec5db1ba8ad2face750b2"></a>

### `find_json_object_field`


```cpp
const JsonObjectField * espectre::find_json_object_field(const std::vector< JsonObjectField > &fields, const char *name)
```

   

<a id="namespaceespectre_1a138e724fbe594802da86d2961939cd7f"></a>

### `parse_direct_http_request`


```cpp
bool espectre::parse_direct_http_request(const std::string &http_method, const std::string &path, const std::string &payload, DirectRequest *request, std::string *error=nullptr, const EspectreProtocolExtension *extension=nullptr)
```

   

<a id="namespaceespectre_1abcacfcd112472bfc62c59a502f647ceb"></a>

### `direct_http_request_to_command`


```cpp
bool espectre::direct_http_request_to_command(const DirectRequest &request, EspectreCommand *command, std::string *error=nullptr, const EspectreProtocolExtension *extension=nullptr)
```

   

<a id="namespaceespectre_1a5509432cbeaff50ecf7e2b7d5ace8bd9"></a>

### `espectre_transport_mapping_payload`


```cpp
std::string espectre::espectre_transport_mapping_payload()
```

 

How each canonical message maps onto Direct HTTP routes and MQTT topics.

   

<a id="namespaceespectre_1ac57dce35f8b2fdb1cdfe072f3f4feb14"></a>

### `espectre_protocol_catalog_payload`


```cpp
std::string espectre::espectre_protocol_catalog_payload(const EspectreProtocolExtension *extension=nullptr)
```

 

Combined message-model and transport-mapping catalog for protocol inspection.

   

<a id="namespaceespectre_1a34031a60d78bbb6306047b3540b4f905"></a>

### `derive_runtime_device_id`


```cpp
uint64_t espectre::derive_runtime_device_id()
```

 

Return the cached 64-bit SHA-256 pseudonym derived from the station MAC.

   

<a id="namespaceespectre_1a0f5171c004f18f155e1cd453c8eb4801"></a>

### `derive_runtime_device_id_string`


```cpp
std::string espectre::derive_runtime_device_id_string()
```

 

Return the cached canonical text for [`derive_runtime_device_id()`](#namespaceespectre_1a34031a60d78bbb6306047b3540b4f905).

   

<a id="namespaceespectre_1ab070877204ffb133b519d0b163420df6"></a>

### `make_runtime_sensing_config_from_kconfig`


```cpp
RuntimeConfig espectre::make_runtime_sensing_config_from_kconfig()
```

 

Build a [`RuntimeConfig`](#structespectre_1_1_runtime_config) from the `ESPECTRE_*` menuconfig options.

  

This is the ergonomic path on ESP-IDF: expose the sensing settings in menuconfig, call this at boot, and override only the fields your product computes at runtime.

 

```cpp
espectre::RuntimeConfig config = espectre::make_runtime_sensing_config_from_kconfig();
config.device_id = my_device_id();
controller.set_config(config);
```

 

Every value is range-checked against the schema in [`runtime_sensing_schema.h`](#runtime__sensing__schema_8h). An out-of-range or unparseable option falls back to the documented default and logs a warning rather than failing the boot, so a bad `sdkconfig` degrades instead of bricking the device.

 

Options absent from the build, for instance when the SDK Kconfig is not sourced, compile to their defaults. Fields with no Kconfig option, such as `device_id` and the stream settings, keep their [`RuntimeConfig`](#structespectre_1_1_runtime_config) defaults.

 

**Returns:** A validated configuration, ready for [`RuntimeFrontendController::set_config()`](#classespectre_1_1_runtime_frontend_controller_1a6bc5d2dea03c406e822c0fc917e54840).

  

<a id="namespaceespectre_1a4ce213aabcd22d32aa6f62e83a2bda1e"></a>

### `set_log_sink`


```cpp
bool espectre::set_log_sink(const LogSink &sink)
```

 

Register a complete frontend logging sink.

  

Registration must happen before runtime setup, and replacement is supported only while no ESPectre runtime is active. An invalid sink leaves the current registration unchanged.

 

**Parameters**

- `sink`: Callback value copied by ESPectre.

 

**Returns:** `true` when both required callbacks were registered.

  

<a id="namespaceespectre_1a61ab03223d965fdc086b55a8527ed204"></a>

### `clear_log_sink`


```cpp
void espectre::clear_log_sink()
```

 

Clear the current sink while no ESPectre runtime is active.

   

<a id="namespaceespectre_1aceb53f160132829964a6b4d69347ed4e"></a>

### `log_enabled`


```cpp
bool espectre::log_enabled(LogLevel level, const char *tag)
```

 

Return whether the current sink accepts one level and tag.

  

**Parameters**

- `level`: Message severity.
- `tag`: Stable logger tag.

 

**Returns:** `false` when no complete sink is registered or the sink filters the message.

  

<a id="namespaceespectre_1a09a51380aebbfbfacbb14b51c7604653"></a>

### `make_default_subcarriers`


```cpp
constexpr SelectedSubcarriers espectre::make_default_subcarriers()
```

   

<a id="namespaceespectre_1a6bd20096271ae7a56b205e06ac9c7e86"></a>

### `ht20_bins_with_energy`


```cpp
uint8_t espectre::ht20_bins_with_energy(const int8_t *csi_data, const uint8_t *bins, uint8_t count, bool first_word_invalid=false)
```

   

<a id="namespaceespectre_1a7d1d5b5cec71e45a58dfc64c0ba441cd"></a>

### `detect_ht20_bin_layout`


```cpp
Ht20BinLayout espectre::detect_ht20_bin_layout(const int8_t *csi_data, size_t csi_len, bool first_word_invalid=false)
```

 

Identify which HT20 bin ordering a 64-subcarrier payload uses.

  

Requires positive evidence in both directions: one guard set must be entirely null and the other entirely populated. Absence of energy alone is not enough, because a sparse or degenerate payload is null under both conventions.

 

**Parameters**

- `csi_data`: Raw CSI payload (interleaved I/Q pairs)
- `csi_len`: Payload length in bytes (must be HT20\_CSI\_LEN)
- `first_word_invalid`: Ignore the two hardware-invalid source pairs

 

**Returns:** The detected layout, or UNKNOWN when the evidence is inconclusive

  

<a id="namespaceespectre_1ad95f5d8710d3ea0b07337e581593c63e"></a>

### `zero_ht20_lltf_missing_bins`


```cpp
bool espectre::zero_ht20_lltf_missing_bins(int8_t *csi_data, size_t csi_len)
```

 

Mark LLTF's unavailable edge tones as missing in a normalized raw view.

  

**Parameters**

- `csi_data`: Centered, interleaved I/Q HT20 payload to update in place.
- `csi_len`: Payload length in bytes; must equal HT20\_CSI\_LEN.

 

**Returns:** true when the payload was updated, or false for invalid input.

  

<a id="namespaceespectre_1a56a1f68a4399f8754598fe6aa6c86a09"></a>

### `prepare_ht20_detector_input`


```cpp
bool espectre::prepare_ht20_detector_input(int8_t *csi_data, size_t csi_len, bool lltf, bool first_word_invalid=false, Ht20BinLayout source_layout=Ht20BinLayout::UNKNOWN)
```

 

Prepare a private centered detector buffer from normalized raw CSI.

  

Fill LLTF edge tones from -26/+26 and hardware-invalid classic +1 from +2. Source metadata, never a zero value, selects the latter. DC and guards stay unchanged. Call only on a private detector buffer, after raw delivery splits.

 

**Parameters**

- `csi_data`: Private centered, interleaved I/Q HT20 buffer to update.
- `csi_len`: Payload length in bytes; must equal HT20\_CSI\_LEN.
- `lltf`: Whether the capture profile lacks the LLTF edge tones.
- `first_word_invalid`: Whether the first four source bytes were invalid.
- `source_layout`: Original source ordering, before centered normalization.

 

**Returns:** true for a prepared buffer, or false for invalid input or unknown ordering of a flagged source; invalid input is not modified.

  

<a id="namespaceespectre_1ab70480c9cd9d9a706a1777486c4d073d"></a>

### `impute_ht20_lltf_detector_bins`


```cpp
bool espectre::impute_ht20_lltf_detector_bins(int8_t *csi_data, size_t csi_len)
```

 

Prepare the legacy LLTF-only detector view in a private buffer.

   

<a id="namespaceespectre_1a8e38da349464d03ae50a403cab4f977a"></a>

### `rotate_ht20_classic_to_centered`


```cpp
void espectre::rotate_ht20_classic_to_centered(const int8_t *csi_data, int8_t *out)
```

 

Rotate a classic-order HT20 payload into the centered convention.

  

Rotating by half the FFT size is its own inverse, so one swap of the payload halves maps `0~31, -32~-1` onto `-32~+31`.

 

**Parameters**

- `csi_data`: Source payload of HT20\_CSI\_LEN bytes
- `out`: Destination buffer of HT20\_CSI\_LEN bytes (must not alias the source)

  

<a id="namespaceespectre_1a20a50c9af4bbb66528f0c0491e92b3e8"></a>

### `calculate_spatial_turbulence`


```cpp
float espectre::calculate_spatial_turbulence(const float *magnitudes, const uint8_t *subcarriers, uint8_t num_subcarriers, uint16_t max_subcarrier=64)
```

 

Calculate spatial turbulence from pre-calculated magnitudes.

  

Spatial turbulence is the coefficient of variation (standard deviation divided by mean) of magnitudes across selected subcarriers, so it does not depend on the receiver gain. It measures the spatial variability of the Wi-Fi channel - higher values indicate motion/disturbance.

 

**Parameters**

- `magnitudes`: Array of magnitude values (one per subcarrier)
- `subcarriers`: Array of selected subcarrier indices
- `num_subcarriers`: Number of selected subcarriers (max 12)
- `max_subcarrier`: Maximum valid subcarrier index (default: 64 for HT20)

 

**Returns:** Turbulence value

  

<a id="namespaceespectre_1ae28970c57767d93ae75b3410225d51b1"></a>

### `extract_subcarrier_amplitudes`


```cpp
uint8_t espectre::extract_subcarrier_amplitudes(const int8_t *csi_data, size_t csi_len, const uint8_t *subcarriers, uint8_t num_subcarriers, float *out, uint8_t out_capacity)
```

 

Extract subcarrier amplitudes from raw CSI data (I/Q pairs).

  

**Parameters**

- `csi_data`: Raw CSI data (interleaved I/Q pairs, Espressif format)
- `csi_len`: Length of CSI data in bytes
- `subcarriers`: Array of selected subcarrier indices
- `num_subcarriers`: Number of selected subcarriers
- `out`: Output amplitude buffer
- `out_capacity`: Capacity of the output buffer

 

**Returns:** Number of amplitudes written

  

<a id="namespaceespectre_1ac837a8b05d79f7e5e2b3978ab2791fb8"></a>

### `extract_packet_subcarrier_amplitudes`


```cpp
uint8_t espectre::extract_packet_subcarrier_amplitudes(const int8_t *csi_data, size_t csi_len, float *out, uint8_t out_capacity)
```

 

Extract one packet-wide amplitude frame for reuse by multiple feature paths.

   

<a id="namespaceespectre_1a5a120acf2ff3297fe7d5658e12e79a25"></a>

### `fill_packet_subcarrier_energies`


```cpp
uint8_t espectre::fill_packet_subcarrier_energies(const int8_t *csi_data, size_t csi_len, float *out, uint8_t out_capacity)
```

 

Fill one packet-wide squared-magnitude frame for energy-domain consumers.

   

<a id="namespaceespectre_1a9d29e561f008ffa26b8d57f46f6e1ca5"></a>

### `energies_to_amplitudes_in_place`


```cpp
void espectre::energies_to_amplitudes_in_place(float *values, uint8_t count)
```

   

<a id="namespaceespectre_1a7ee2f120717498da48852634a0db88ca"></a>

### `select_subcarrier_amplitudes`


```cpp
uint8_t espectre::select_subcarrier_amplitudes(const float *packet_amplitudes, uint8_t packet_count, const uint8_t *subcarriers, uint8_t num_subcarriers, float *out, uint8_t out_capacity)
```

 

Select the configured tones from a packet-wide amplitude frame.

   

<a id="namespaceespectre_1a15c3caa66a486b64ea5b4baa16f6c9fc"></a>

### `select_adjacent_aggregated_subcarrier_amplitudes`


```cpp
uint8_t espectre::select_adjacent_aggregated_subcarrier_amplitudes(const float *packet_amplitudes, uint8_t packet_count, const uint8_t *subcarriers, uint8_t num_subcarriers, uint8_t width, float *out, uint8_t out_capacity)
```

 

Select adjacent-bin mean amplitudes from a packet-wide amplitude frame.

   

<a id="namespaceespectre_1ab089846cad43726fc4d5ee80271586e3"></a>

### `extract_adjacent_aggregated_subcarrier_amplitudes`


```cpp
uint8_t espectre::extract_adjacent_aggregated_subcarrier_amplitudes(const int8_t *csi_data, size_t csi_len, const uint8_t *subcarriers, uint8_t num_subcarriers, uint8_t width, float *out, uint8_t out_capacity)
```

 

Extract one mean magnitude per selected tone from adjacent live HT20 bins.

  

Windows are clamped to bins 4..60 and skip the DC null at bin 32.

  

<a id="namespaceespectre_1a56c215b39ccf2e01b773e922a484459b"></a>

### `calculate_spatial_turbulence_from_amplitudes`


```cpp
float espectre::calculate_spatial_turbulence_from_amplitudes(const float *amplitudes, uint8_t count)
```

   

<a id="namespaceespectre_1a2dc522f2419538854cf164ca24220b66"></a>

### `calculate_spatial_turbulence_from_csi`


```cpp
float espectre::calculate_spatial_turbulence_from_csi(const int8_t *csi_data, size_t csi_len, const uint8_t *subcarriers, uint8_t num_subcarriers)
```

 

Calculate spatial turbulence directly from raw CSI data (I/Q pairs).

  

This is a convenience wrapper that calculates magnitudes internally before computing spatial turbulence, the coefficient of variation of the selected magnitudes.

 

HT20 only: 64 subcarriers, 128 bytes CSI data.

 

**Parameters**

- `csi_data`: Raw CSI data (interleaved I/Q pairs)
- `csi_len`: Length of CSI data in bytes (expected: 128 for HT20)
- `subcarriers`: Array of selected subcarrier indices
- `num_subcarriers`: Number of selected subcarriers (max 12)

 

**Returns:** Turbulence value

  

<a id="namespaceespectre_1aaec036cc9ad204a6e3fc1abd72d00ef9"></a>

### `temporal_window_slots`


```cpp
uint32_t espectre::temporal_window_slots(uint32_t target_pps, uint32_t window_size_ms)
```

 

Return the fixed-grid slot count for a target rate and window duration.

   

<a id="namespaceespectre_1a06e0cbe94d9c977e8c5f7d7976890d0d"></a>

### `temporal_minimum_valid_slots`


```cpp
uint32_t espectre::temporal_minimum_valid_slots(uint32_t window_slots)
```

 

Return the minimum occupied slots required for a ready window.

   

<a id="namespaceespectre_1a8a21858a93018db73d09ee475c20e11c"></a>

### `temporal_minimum_sample_spacing_us`


```cpp
uint32_t espectre::temporal_minimum_sample_spacing_us(uint32_t target_pps)
```

 

Return the minimum spacing between selected candidates at a target rate.

   

<a id="namespaceespectre_1ad4c7901011b5435695529f5f5a01e8bf"></a>

### `read_direct_wifi_snapshot`


```cpp
DirectWifiSnapshot espectre::read_direct_wifi_snapshot()
```

 

Read the current ESP-IDF station configuration and association without credentials.

   

<a id="namespaceespectre_1a911b097ab2cd0645acb686a8d64040b3"></a>

### `read_direct_wifi_connected`


```cpp
bool espectre::read_direct_wifi_connected()
```

 

Read cached IPv4 link readiness without querying the Wi-Fi driver.

   

<a id="namespaceespectre_1a2dab48606d782213e70dae8808b0fdd9"></a>

### `load_frontend_device_config`


```cpp
EspectreDeviceConfig espectre::load_frontend_device_config(const FrontendDeviceConfigDefaults &defaults, const char *log_tag, const char *stored_config_message, const char *load_error_prefix)
```

   

<a id="namespaceespectre_1a9c0cb264d4cfce2b1652a1da5e178fb3"></a>

### `setup_frontend_wifi_station`


```cpp
esp_err_t espectre::setup_frontend_wifi_station(WifiProvisioningService *provisioning, StandaloneWifiService *wifi_manager, const FrontendWifiStationOptions &options, const char *log_tag, const char *stored_config_message)
```

   

<a id="namespaceespectre_1ae48174400d9601d7260ae60e07591908"></a>

### `frontend_ha_mqtt_enabled`


```cpp
bool espectre::frontend_ha_mqtt_enabled()
```

   

<a id="namespaceespectre_1ad0ab3784ab4c2449af25b7fb4f8a80b6"></a>

### `build_frontend_ha_mqtt_settings`


```cpp
FrontendHaMqttSettings espectre::build_frontend_ha_mqtt_settings(const EspectreDeviceConfig &config, const EspectreDeviceInfo &info, const char *frontend_name)
```

   

<a id="namespaceespectre_1a5114c22b690a7c5684ade9d26b0294f4"></a>

### `build_frontend_ha_discovery_message`


```cpp
bool espectre::build_frontend_ha_discovery_message(const FrontendHaMqttSettings &settings, const EspectreDeviceInfo &info, bool supports_detector, bool supports_motion_hits, bool supports_traffic_control, size_t index, FrontendHaDiscoveryMessage *message)
```

 

Build one discovery message in publication order; false marks the end.

   

<a id="namespaceespectre_1ac317e956257fb2f5f6171e5fe42affd6"></a>

### `build_frontend_ha_discovery_messages`


```cpp
std::vector< FrontendHaDiscoveryMessage > espectre::build_frontend_ha_discovery_messages(const FrontendHaMqttSettings &settings, const EspectreDeviceInfo &info, bool supports_detector, bool supports_motion_hits, bool supports_traffic_control)
```

   

<a id="namespaceespectre_1a859fb9c76658edbda893921726ab1f0b"></a>

### `setup_frontend_mqtt_transport`


```cpp
bool espectre::setup_frontend_mqtt_transport(IMqttTransport *transport, const EspectreDeviceConfig &config, IMqttTransport::CommandCallback command_callback, FrontendMqttConnectedCallback connected_callback, const char *log_tag)
```

   

<a id="namespaceespectre_1a5698df454955c92dd61cef93bbe3437f"></a>

### `publish_frontend_mqtt_message`


```cpp
bool espectre::publish_frontend_mqtt_message(IMqttTransport *transport, const EspectreDeviceConfig &config, const char *suffix, const std::string &payload, bool retain)
```

   

<a id="namespaceespectre_1a07966aaab03a7ae12577400864e36b30"></a>

### `publish_frontend_mqtt_status`


```cpp
bool espectre::publish_frontend_mqtt_status(IMqttTransport *transport, const EspectreDeviceConfig &config, bool online, uint32_t timestamp_ms)
```

   

<a id="namespaceespectre_1a09e7fae5dc31f12962e6537107073fad"></a>

### `publish_frontend_mqtt_command_result`


```cpp
bool espectre::publish_frontend_mqtt_command_result(IMqttTransport *transport, const EspectreDeviceConfig &config, const FrontendCommandResult &result)
```

   

<a id="namespaceespectre_1aa9d1ab4fa6250571247a25c88d68acf7"></a>

### `nvs_init_with_erase_fallback`


```cpp
esp_err_t espectre::nvs_init_with_erase_fallback()
```

   

<a id="namespaceespectre_1a2a3712a02c829f91e0da24cf3eec56a6"></a>

### `apply_wifi_bssid_pin`


```cpp
bool espectre::apply_wifi_bssid_pin(const std::string &bssid, std::string *message, bool *station_transition_started=nullptr)
```

 

Apply or clear the ESP-IDF station BSSID pin through a Wi-Fi state-machine restart.

   

<a id="namespaceespectre_1a3d748e9f1b0d5dbe5388efb97e13569d"></a>

### `to_csi_traffic_config`


```cpp
CsiTrafficServiceConfig espectre::to_csi_traffic_config(const RuntimeConfig &config)
```

 

Project runtime configuration onto transport-independent CSI traffic policy.

   

<a id="namespaceespectre_1af3215fab6f83ede00987d248b8399c94"></a>

### `wifi_band_policy_is_supported`


```cpp
constexpr bool espectre::wifi_band_policy_is_supported(WifiBandPolicy policy)
```

 

Return whether this build can honor the requested band policy.

  

`AUTO` uses the bands the radio has, so it is valid everywhere and means 2.4 GHz on single-band targets. `BAND_5G` needs dual-band silicon.

  

<a id="namespaceespectre_1a964290548f98cd616789767c4f34b690"></a>

### `wifi_channel_matches_band_policy`


```cpp
constexpr bool espectre::wifi_channel_matches_band_policy(int channel, WifiBandPolicy policy)
```

 

Return whether a channel hint is compatible with the requested band.

   

<a id="namespaceespectre_1ae7131ef838a5d0f599a6e4dbcda5830c"></a>

### `wifi_channel_is_supported`


```cpp
constexpr bool espectre::wifi_channel_is_supported(int channel)
```

 

Report whether an optional channel hint is usable on this build.

  

2.4 GHz channels are contiguous; the 5 GHz channel numbers are the 20 MHz centers of the UNII bands, which are spaced four channels apart from 36 and from 149. Passing a 5 GHz channel a 2.4 GHz-only radio cannot tune would fail silently at association time, so those numbers are rejected there.

 

**Parameters**

- `channel`: Channel number, or WIFI\_CHANNEL\_AUTO for no hint

 

**Returns:** true when the channel can be configured on this build

  

<a id="namespaceespectre_1a106a2c32bc0d816e1221218b7b0c0d94"></a>

### `wifi_channel_supported_description`


```cpp
const char * espectre::wifi_channel_supported_description()
```

 

Describe the accepted channel hint values for operator-facing errors.

  

**Returns:** A short human-readable range description

  

<a id="namespaceespectre_1ac6f0a44c679e44a001705073485c13f4"></a>

### `wifi_channel_supported_description`


```cpp
const char * espectre::wifi_channel_supported_description(WifiBandPolicy policy)
```

   

<a id="namespaceespectre_1a46e196c7dcc084bdc7b9db150635bfd0"></a>

### `wifi_bssid_pin_apply_state_name`


```cpp
const char * espectre::wifi_bssid_pin_apply_state_name(WifiBssidPinApplyState state)
```

 

Protocol name of an apply state, such as `verifying` or `rolled_back`.

   

<a id="namespaceespectre_1a6df158d98f79adc5e2759b133ecf52e8"></a>

### `wifi_provisioning_apply_state_name`


```cpp
const char * espectre::wifi_provisioning_apply_state_name(WifiProvisioningApplyState state)
```

 

Protocol name of an apply state, such as `verifying` or `rolled_back`.

   

<a id="namespaceespectre_1a401a56fc8d13271aa575ac137e41dd93"></a>

### `log_espectre_banner`


```cpp
template <typename Logger>
void espectre::log_espectre_banner(Logger &&log_line)
```

   

<a id="namespaceespectre_1ad29105f65f58304d2b72dfec2a198393"></a>

### `frontend_command_parse_error_code`


```cpp
const char * espectre::frontend_command_parse_error_code(const std::string &error)
```

 

Map a canonical command parse failure to its stable result code.

   

<a id="namespaceespectre_1af1ba3349774c2074ec11664168dc616f"></a>

### `operator|`


```cpp
FrontendCommandChange espectre::operator|(FrontendCommandChange lhs, FrontendCommandChange rhs)
```

 

Combine change flags.

   

<a id="namespaceespectre_1abf3a6449bc675492ac72bdb143df9948"></a>

### `frontend_command_allowed_during_raw_collection`


```cpp
bool espectre::frontend_command_allowed_during_raw_collection(const std::string &command, const EspectreProtocolExtension *extension=nullptr)
```

 

Whether a command may run while raw CSI collection is active.

  

Reads and configuration commands that do not touch sensing are allowed; extension routes declare their own policy.

  

<a id="namespaceespectre_1a4bebef550879193c62fbeba6f47cee5a"></a>

### `validate_peer_discovery_candidates`


```cpp
PeerDiscoverySnapshot espectre::validate_peer_discovery_candidates(const std::vector< PeerDiscoveryCandidate > &candidates, uint32_t station_address, uint32_t station_netmask, uint32_t elapsed_ms, bool timed_out)
```

 

Validate, deduplicate, sort, and serialize one bounded discovery result.

   

<a id="namespaceespectre_1a70a8d3f60a08466d66856679d67ad911"></a>

### `peer_discovery_snapshot_json`


```cpp
std::string espectre::peer_discovery_snapshot_json(const PeerDiscoverySnapshot &snapshot)
```

   

<a id="namespaceespectre_1a371a57d18d999de733c9e7cfa628c6c0"></a>

### `monotonic_now_us`


```cpp
uint64_t espectre::monotonic_now_us()
```

   

<a id="namespaceespectre_1a74347339c609120224a1110d79205927"></a>

### `monotonic_now_ms`


```cpp
uint32_t espectre::monotonic_now_ms()
```

   


<a id="namespaceespectre_1_1detail"></a>

## espectre::detail

  [`espectre::detail::PendingEventLock`](#classespectre_1_1detail_1_1_pending_event_lock)



<a id="namespaceespectre_1_1detail_1a4328f2b1fc284e8db1bcf5c82b823899"></a>

### `required_amplitude_bins`


```cpp
constexpr std::array< bool, HT20_NUM_SUBCARRIERS > espectre::detail::required_amplitude_bins(const uint8_t *subcarriers, uint8_t count, uint8_t width)
```

   

<a id="namespaceespectre_1_1detail_1ac20c5153000523ffb25a8b9459d6f546"></a>

### `required_energies_to_amplitudes`


```cpp
template <uint8_t Width>
void espectre::detail::required_energies_to_amplitudes(float *values, uint8_t count, const uint8_t *subcarriers, uint8_t subcarrier_count, bool aggregated)
```

   


<a id="namespaceespectre_1_1task__scheduling"></a>

## espectre::task\_scheduling

  

<a id="namespaceespectre_1_1task__scheduling_1aa4d1b82dcd846f10a6788c92d721c631"></a>

### `kDirectHttpdPriority`


```cpp
constexpr uint32_t espectre::task_scheduling::kDirectHttpdPriority                                            =
CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITY
```

   

<a id="namespaceespectre_1_1task__scheduling_1a7ab02a1007eac7ec5986596a9da76ef6"></a>

### `kDirectWorkerPriority`


```cpp
constexpr uint32_t espectre::task_scheduling::kDirectWorkerPriority                                             =
CONFIG_ESPECTRE_DIRECT_WORKER_TASK_PRIORITY
```

   

<a id="namespaceespectre_1_1task__scheduling_1a9161d912c84e540b1a25df4ec85fcdd5"></a>

### `kRawWorkerPriority`


```cpp
constexpr uint32_t espectre::task_scheduling::kRawWorkerPriority                                          =
CONFIG_ESPECTRE_RAW_WORKER_TASK_PRIORITY
```

   

<a id="namespaceespectre_1_1task__scheduling_1aeb066e2810db7b56cf4a6b62d7296998"></a>

### `kTrafficPriority`


```cpp
constexpr uint32_t espectre::task_scheduling::kTrafficPriority = CONFIG_ESPECTRE_TRAFFIC_TASK_PRIORITY
```

   

<a id="namespaceespectre_1_1task__scheduling_1af6a58fae684eb2597f88823b34ca8f5d"></a>

### `kNativeLoopPriority`


```cpp
constexpr uint32_t espectre::task_scheduling::kNativeLoopPriority                                           =
CONFIG_ESPECTRE_NATIVE_LOOP_TASK_PRIORITY
```

   


<a id="classespectre_1_1_base_detector"></a>

## espectre::BaseDetector



```cpp
#include <core/base_detector.h>
```



```cpp
class espectre::BaseDetector
```

 

Abstract base class for motion detection algorithms.

  

Provides shared functionality:

- Turbulence buffer management (circular buffer)

- Hampel and low-pass filtering

- CSI processing and spatial turbulence calculation

 

Subclasses must implement:

- [update\_state()](#classespectre_1_1_base_detector_1a261ca504b8a5fb2e915c6354f3e9ddf6): detection algorithm logic; it assigns [`current_metric_`](#classespectre_1_1_base_detector_1ac744d80062fb6c9fcf64d122e2865362), which [get\_motion\_metric()](#classespectre_1_1_base_detector_1ab7ea59db54d734cc87815e0a7aebd972) returns

- [get\_threshold()](#classespectre_1_1_base_detector_1ab1b2a5a33a086a50783cc158f56a6b8c) / [set\_threshold()](#classespectre_1_1_base_detector_1a9614847f36f3a391ff2df8e0f77fc1da): threshold management

- [get\_name()](#classespectre_1_1_base_detector_1af1a3b2c9adb5ad7b550acfd7230a1503): detector name for logging

 

<a id="classespectre_1_1_base_detector_1a704e1cd629bbfa076f09ff78f8589449"></a>

### `turbulence_buffer_`


```cpp
float* espectre::BaseDetector::turbulence_buffer_
```

   

<a id="classespectre_1_1_base_detector_1a803bf375787e80593d21eae6c86cdca1"></a>

### `ordered_turbulence_`


```cpp
float* espectre::BaseDetector::ordered_turbulence_
```

   

<a id="classespectre_1_1_base_detector_1a111ed542d50cc07a7d19b7d4c723d605"></a>

### `buffer_index_`


```cpp
uint16_t espectre::BaseDetector::buffer_index_
```

   

<a id="classespectre_1_1_base_detector_1a5dfe97b27a2071b41ba5522df54d1d74"></a>

### `buffer_count_`


```cpp
uint16_t espectre::BaseDetector::buffer_count_
```

   

<a id="classespectre_1_1_base_detector_1ab6a65687542789b85ea50d08f8889411"></a>

### `valid_buffer_count_`


```cpp
uint16_t espectre::BaseDetector::valid_buffer_count_
```

   

<a id="classespectre_1_1_base_detector_1a6390a37f6eab391953b2902ccad28e19"></a>

### `minimum_valid_samples_`


```cpp
uint16_t espectre::BaseDetector::minimum_valid_samples_
```

   

<a id="classespectre_1_1_base_detector_1a531deb4e201dd7315f89a77144c0cb66"></a>

### `window_size_`


```cpp
uint16_t espectre::BaseDetector::window_size_
```

   

<a id="classespectre_1_1_base_detector_1a7c807d680f10bfd7c6956812b7413749"></a>

### `state_`


```cpp
MotionState espectre::BaseDetector::state_
```

   

<a id="classespectre_1_1_base_detector_1ac744d80062fb6c9fcf64d122e2865362"></a>

### `current_metric_`


```cpp
float espectre::BaseDetector::current_metric_
```

   

<a id="classespectre_1_1_base_detector_1a39ecf887d2f955fe53c2efdede92915b"></a>

### `total_packets_`


```cpp
uint32_t espectre::BaseDetector::total_packets_
```

   

<a id="classespectre_1_1_base_detector_1a3b899045c8ad6a5d932af413615b6274"></a>

### `packet_index_`


```cpp
uint32_t espectre::BaseDetector::packet_index_
```

   

<a id="classespectre_1_1_base_detector_1a71cfdb211ee4311aee2347e61b00d941"></a>

### `packet_timestamp_us_`


```cpp
uint64_t espectre::BaseDetector::packet_timestamp_us_
```

   

<a id="classespectre_1_1_base_detector_1ac627c02075ead3e632d29811dc4e3c20"></a>

### `has_packet_timestamp_`


```cpp
bool espectre::BaseDetector::has_packet_timestamp_
```

   

<a id="classespectre_1_1_base_detector_1ad8976c91d321a26c1a35ff75eb5bbeb6"></a>

### `hampel_state_`


```cpp
hampel_filter_state_t espectre::BaseDetector::hampel_state_
```

   

<a id="classespectre_1_1_base_detector_1a82b7aac2d9a18c7403a64556b64f23c6"></a>

### `lowpass_state_`


```cpp
lowpass_filter_state_t espectre::BaseDetector::lowpass_state_
```

   


<a id="classespectre_1_1_base_detector_1ac70f1692bdd644c0589f426d8267b681"></a>

### `BaseDetector`


```cpp
explicit espectre::BaseDetector::BaseDetector(uint16_t window_size=DETECTOR_DEFAULT_WINDOW_SIZE)
```

 

Constructor.

  

**Parameters**

- `window_size`: Buffer window size in the inclusive range defined by DETECTOR\_MIN\_WINDOW\_SIZE and DETECTOR\_MAX\_WINDOW\_SIZE

  

<a id="classespectre_1_1_base_detector_1a2062504291217a724134d103d8a73d59"></a>

### `~BaseDetector`


```cpp
virtual espectre::BaseDetector::~BaseDetector()
```

   

<a id="classespectre_1_1_base_detector_1a5d2806fada882285a9b8fa8848179238"></a>

### `BaseDetector`


```cpp
espectre::BaseDetector::BaseDetector(BaseDetector &&other) noexcept
```

   

<a id="classespectre_1_1_base_detector_1a565d9425c07877ff82b9950feb65a429"></a>

### `operator=`


```cpp
BaseDetector & espectre::BaseDetector::operator=(BaseDetector &&other) noexcept
```

   

<a id="classespectre_1_1_base_detector_1a2602479812119dada1826c3d996520de"></a>

### `BaseDetector`


```cpp
espectre::BaseDetector::BaseDetector(const BaseDetector &)=delete
```

   

<a id="classespectre_1_1_base_detector_1a25933318888d59fa2cfa90ac594fb0c8"></a>

### `operator=`


```cpp
BaseDetector & espectre::BaseDetector::operator=(const BaseDetector &)=delete
```

   

<a id="classespectre_1_1_base_detector_1a121de67ca4480d53819bd6fb45bc7253"></a>

### `process_packet`


```cpp
virtual void espectre::BaseDetector::process_packet(const int8_t *csi_data, size_t csi_len, const uint8_t *selected_subcarriers=nullptr, uint8_t num_subcarriers=0, int8_t rssi_dbm=INT8_MIN)
```

 

Process one normalized, temporally admitted CSI packet.

  

Calculates spatial turbulence from CSI data, applies filtering, and stores in circular buffer.

 

**Parameters**

- `csi_data`: Normalized CSI data (I/Q interleaved)
- `csi_len`: Length of CSI data
- `selected_subcarriers`: Array of subcarrier indices
- `num_subcarriers`: Number of selected subcarriers
- `rssi_dbm`: Link RSSI for this packet, or INT8\_MIN when unknown

  

<a id="classespectre_1_1_base_detector_1ad432493bba41a1951f7d2ee2e7666a4d"></a>

### `set_packet_timestamp_us`


```cpp
void espectre::BaseDetector::set_packet_timestamp_us(uint64_t timestamp_us)
```

 

Supply the monotonic arrival timestamp consumed by time-binned features.

   

<a id="classespectre_1_1_base_detector_1afeafa0d2e142db2f73eff87230164288"></a>

### `reset`


```cpp
virtual void espectre::BaseDetector::reset()
```

 

Reset detector state.

  

Resets state machine but preserves buffer ("warm" restart).

  

<a id="classespectre_1_1_base_detector_1a8aa4a67f587b5e575346e3bf529f96f2"></a>

### `get_state`


```cpp
virtual MotionState espectre::BaseDetector::get_state() const
```

 

Get current motion state.

   

<a id="classespectre_1_1_base_detector_1a474ff45b6a2ef2cb061f86603e76d475"></a>

### `is_valid`


```cpp
virtual bool espectre::BaseDetector::is_valid() const
```

 

Return whether all base detector working storage was allocated.

   

<a id="classespectre_1_1_base_detector_1a909126a7761b02f5f58c19103cd91053"></a>

### `is_ready`


```cpp
virtual bool espectre::BaseDetector::is_ready() const
```

 

Check if detector is ready.

  

Ready once the window has filled and its valid slots reach the floor set by [set\_minimum\_valid\_samples()](#classespectre_1_1_base_detector_1a9732e34f845a2eb619ac9f42e1096353).

  

<a id="classespectre_1_1_base_detector_1a5e047ba665b25faf9e5088df58302f50"></a>

### `advance_missing_slots`


```cpp
virtual void espectre::BaseDetector::advance_missing_slots(uint32_t count)
```

 

Advance packet-indexed feature rings for absent temporal slots.

   

<a id="classespectre_1_1_base_detector_1a9732e34f845a2eb619ac9f42e1096353"></a>

### `set_minimum_valid_samples`


```cpp
void espectre::BaseDetector::set_minimum_valid_samples(uint16_t count)
```

 

Set the valid-slot occupancy floor used by [`is_ready()`](#classespectre_1_1_base_detector_1a909126a7761b02f5f58c19103cd91053).

   

<a id="classespectre_1_1_base_detector_1a4ca1de3311c1895fbaa1295e7c8ec9ec"></a>

### `get_total_packets`


```cpp
virtual uint32_t espectre::BaseDetector::get_total_packets() const
```

 

Get total packets processed.

   

<a id="classespectre_1_1_base_detector_1a261ca504b8a5fb2e915c6354f3e9ddf6"></a>

### `update_state`


```cpp
virtual void espectre::BaseDetector::update_state()=0
```

 

Update state machine (call at the detector evaluation interval).

  

Subclasses implement their detection algorithm here.

  

<a id="classespectre_1_1_base_detector_1ab7ea59db54d734cc87815e0a7aebd972"></a>

### `get_motion_metric`


```cpp
float espectre::BaseDetector::get_motion_metric() const
```

 

Get current motion metric value.

  

Subclasses assign [`current_metric_`](#classespectre_1_1_base_detector_1ac744d80062fb6c9fcf64d122e2865362) at the end of their [`update_state()`](#classespectre_1_1_base_detector_1a261ca504b8a5fb2e915c6354f3e9ddf6).

 

**Returns:** Primary metric, on the detector's 0..1 probability scale

  

<a id="classespectre_1_1_base_detector_1a9614847f36f3a391ff2df8e0f77fc1da"></a>

### `set_threshold`


```cpp
virtual bool espectre::BaseDetector::set_threshold(float threshold)=0
```

 

Set detection threshold.

  

**Parameters**

- `threshold`: New threshold value

 

**Returns:** true if value was accepted

  

<a id="classespectre_1_1_base_detector_1a6badc6950f8328f4bd77ff50ea47fee4"></a>

### `set_adaptive_threshold`


```cpp
virtual bool espectre::BaseDetector::set_adaptive_threshold(float threshold)
```

 

Apply a detector-specific startup-calibrated threshold.

   

<a id="classespectre_1_1_base_detector_1ab1b2a5a33a086a50783cc158f56a6b8c"></a>

### `get_threshold`


```cpp
virtual float espectre::BaseDetector::get_threshold() const =0
```

 

Get current threshold.

   

<a id="classespectre_1_1_base_detector_1af1a3b2c9adb5ad7b550acfd7230a1503"></a>

### `get_name`


```cpp
virtual const char * espectre::BaseDetector::get_name() const =0
```

 

Get detector name for logging.

   

<a id="classespectre_1_1_base_detector_1ab3ff821066a78493f9f91dda37001310"></a>

### `get_startup_threshold_factor`


```cpp
virtual float espectre::BaseDetector::get_startup_threshold_factor() const
```

 

Get the detector-specific automatic startup multiplier.

  

threshold = threshold\_metric x factor, where `threshold_metric` comes from the shared startup calibrator.

  

<a id="classespectre_1_1_base_detector_1ad476a9ddaeda232d21c7b85b8323f482"></a>

### `startup_gate_enabled`


```cpp
virtual bool espectre::BaseDetector::startup_gate_enabled() const
```

 

Whether startup calibration uses the calibrator's consistency gate.

  

The gate can end a calibration early on a quiet, motion, quiet pattern. No shipped detector enables it.

  

<a id="classespectre_1_1_base_detector_1ab7d3688dc470cfcf828d247d16baf990"></a>

### `startup_calibration_conclusive`


```cpp
virtual bool espectre::BaseDetector::startup_calibration_conclusive() const
```

 

Whether the calibration evidence collected so far can set a threshold.

  

The runtime asks each time the calibration budget is spent. While the answer is false, the calibration continues in steps of half its initial budget, up to three times that budget. The default always concludes.

  

<a id="classespectre_1_1_base_detector_1af95777f1e1d327c1e73fd077d4559949"></a>

### `calibration_motion_ceiling`


```cpp
virtual float espectre::BaseDetector::calibration_motion_ceiling() const
```

 

Motion metric above which a calibration evaluation counts as motion.

  

An evaluation above it restarts the calibration window. A recalibration under the setup of the last successful calibration also restarts above the live threshold when that is lower. The default, infinity, leaves calibration without an absolute reference.

  

<a id="classespectre_1_1_base_detector_1a23b1db60d0ab0f31516e345f571fa01c"></a>

### `on_startup_calibration_begin`


```cpp
virtual void espectre::BaseDetector::on_startup_calibration_begin()
```

 

Hook called immediately before startup calibration begins.

   

<a id="classespectre_1_1_base_detector_1af003e89702b0e5bd97028e0b5ce4591b"></a>

### `on_startup_calibration_complete`


```cpp
virtual void espectre::BaseDetector::on_startup_calibration_complete()
```

 

Hook called when startup calibration completes successfully.

  

Detectors can freeze session-specific state here before the runtime performs its warm clear between calibration and steady-state detection.

  

<a id="classespectre_1_1_base_detector_1a2fd7526029ee8acb74e713e70a1af750"></a>

### `on_startup_calibration_abandoned`


```cpp
virtual void espectre::BaseDetector::on_startup_calibration_abandoned()
```

 

Hook called when a calibration ends without a result.

  

The runtime keeps the threshold in force before the calibration began. Detectors discard the evidence collected since [on\_startup\_calibration\_begin()](#classespectre_1_1_base_detector_1a23b1db60d0ab0f31516e345f571fa01c) and resume the adaptation they had, or start adapting the threshold in force if no calibration has completed.

  

<a id="classespectre_1_1_base_detector_1a62329885a69c9b2bdadfb0635f171d61"></a>

### `configure_lowpass`


```cpp
virtual void espectre::BaseDetector::configure_lowpass(bool enabled, float cutoff_hz=LOWPASS_CUTOFF_DEFAULT)
```

 

Configure low-pass filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `cutoff_hz`: Cutoff frequency (5.0-20.0 Hz)

  

<a id="classespectre_1_1_base_detector_1aa1401e5000e0a766275dfa0e37e10fb4"></a>

### `configure_hampel`


```cpp
virtual void espectre::BaseDetector::configure_hampel(bool enabled, uint8_t window_size=HAMPEL_TURBULENCE_WINDOW_DEFAULT, float threshold=HAMPEL_TURBULENCE_THRESHOLD_DEFAULT)
```

 

Configure Hampel filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `window_size`: Window size (3-11)
- `threshold`: MAD multiplier threshold

  

<a id="classespectre_1_1_base_detector_1a80285cefc4541552ee897557e8339da2"></a>

### `clear_buffer`


```cpp
virtual void espectre::BaseDetector::clear_buffer()
```

 

Clear turbulence buffer (cold restart).

  

Virtual so detectors with additional state (e.g. L1-Delta profile rings) can extend the cold clear.

  

<a id="classespectre_1_1_base_detector_1aaf32952ebf0ad274b164f9595d6ae491"></a>

### `get_turbulence_buffer`


```cpp
const float * espectre::BaseDetector::get_turbulence_buffer() const
```

 

Get turbulence buffer pointer.

   

<a id="classespectre_1_1_base_detector_1a01a376fa621d31e9e122686aa1f58c1e"></a>

### `get_buffer_count`


```cpp
uint16_t espectre::BaseDetector::get_buffer_count() const
```

 

Get number of window slots filled, including missing slots.

   

<a id="classespectre_1_1_base_detector_1a836410ad2d0b965fe812c249b1756a7a"></a>

### `get_valid_buffer_count`


```cpp
uint16_t espectre::BaseDetector::get_valid_buffer_count() const
```

 

Get number of filled window slots that hold a measured sample.

   

<a id="classespectre_1_1_base_detector_1a76ad118e4803e800bac0df5870dbfbd4"></a>

### `get_window_size`


```cpp
uint16_t espectre::BaseDetector::get_window_size() const
```

 

Get configured window size.

   

<a id="classespectre_1_1_base_detector_1ad9b1e80293dbaf06f2ef18d56401ccef"></a>

### `get_last_turbulence`


```cpp
float espectre::BaseDetector::get_last_turbulence() const
```

 

Get last turbulence value.

   

<a id="classespectre_1_1_base_detector_1aa7baf15ce9ba07d078f09a8566f4e326"></a>

### `is_lowpass_enabled`


```cpp
bool espectre::BaseDetector::is_lowpass_enabled() const
```

 

Check if low-pass filter is enabled.

   

<a id="classespectre_1_1_base_detector_1ab9793996d7abbf858af925cd2f2fb725"></a>

### `is_hampel_enabled`


```cpp
bool espectre::BaseDetector::is_hampel_enabled() const
```

 

Check if Hampel filter is enabled.

   


<a id="classespectre_1_1_base_detector_1ad4b8b59d9e7d07dc689450a5c28a5f75"></a>

### `clear_evaluation_state_`


```cpp
void espectre::BaseDetector::clear_evaluation_state_()
```

 

Drop the last evaluation result.

  

Anything that invalidates the window must also invalidate what was derived from it, or the next publish ships a metric computed from samples the detector no longer holds. Owned here so a detector cannot clear one half and forget the other.

  

<a id="classespectre_1_1_base_detector_1ad05573f50021c0404ed629f1500f304e"></a>

### `process_amplitudes`


```cpp
void espectre::BaseDetector::process_amplitudes(const float *amplitudes, uint8_t count)
```

   

<a id="classespectre_1_1_base_detector_1a8ad0a3fdd14591477ebd01681e0ce84b"></a>

### `packet_timestamp_us_or`


```cpp
uint64_t espectre::BaseDetector::packet_timestamp_us_or(uint64_t fallback) const
```

   

<a id="classespectre_1_1_base_detector_1a93b91a3da1f77896a922e0a50efc9d77"></a>

### `add_turbulence_to_buffer`


```cpp
void espectre::BaseDetector::add_turbulence_to_buffer(float turbulence)
```

 

Add turbulence value to buffer (with filtering).

   

<a id="classespectre_1_1_base_detector_1a2d514487a053702a159e0d3435007450"></a>

### `ordered_turbulence`


```cpp
const float * espectre::BaseDetector::ordered_turbulence(uint16_t &count) const
```

 

View the turbulence ring in chronological order.

  

Returns the ring itself while it is still filling (already in order), and the base-owned reorder buffer once it wraps. Returns nullptr when there is nothing to read or the reorder buffer could not be allocated.

 

**Parameters**

- `count`: Receives the number of valid samples

  


<a id="classespectre_1_1_base_detector_1a1697649add47e9e80ebd4e29a50a795a"></a>

### `alloc_zeroed_floats`


```cpp
static float * espectre::BaseDetector::alloc_zeroed_floats(uint16_t count)
```

 

Allocate a zeroed float buffer on the heap.

  

Shared by the detectors so no feature helper puts a window-sized array on the CSI callback stack.

 

**Returns:** nullptr when count is 0 or the allocation fails

  


<a id="classespectre_1_1_csi_traffic_service"></a>

## espectre::CsiTrafficService



```cpp
#include <runtime/csi_traffic_service.h>
```



```cpp
class espectre::CsiTrafficService
```

 

Keeps CSI-bearing traffic flowing in the configured mode.

  

Internal modes drive the generator; `EXTERNAL` drives the listener, which accepts the ESPectre traffic marker. The full runtime owns one of these; firmware that captures CSI itself can use it directly.

 

**Par:** Threading

Call every method from one owner task, including [loop()](#classespectre_1_1_csi_traffic_service_1a5460f876c4d4c3d67cb964f87bfc49fe).

 

<a id="classespectre_1_1_csi_traffic_service_1ac9e4fa69ec1c128db3a3be5a80d13499"></a>

### `CsiTrafficService`


```cpp
espectre::CsiTrafficService::CsiTrafficService(ICsiTrafficGenerator &traffic_generator, ICsiTrafficIngress &traffic_ingress)
```

 

Bind the generator and listener.

  

Neither is owned; both must outlive the service.

  

<a id="classespectre_1_1_csi_traffic_service_1a2463a9630c708756b78379f60e4304d5"></a>

### `init`


```cpp
void espectre::CsiTrafficService::init(const CsiTrafficServiceConfig &config)
```

 

Configure the mode, rate, and listener while stopped.

   

<a id="classespectre_1_1_csi_traffic_service_1a055f139cc1504b5a9ea8d095b4c030da"></a>

### `start`


```cpp
bool espectre::CsiTrafficService::start(uint32_t target_addr=0U)
```

 

Start the source for the configured mode; a running source is left as is.

  

`target_addr` is the internal generator's IPv4 destination in network byte order, ignored in `EXTERNAL` mode. Returns false when the source fails to start.

  

<a id="classespectre_1_1_csi_traffic_service_1ac059347bfc8b0aea38d2501c18cc87f3"></a>

### `stop`


```cpp
void espectre::CsiTrafficService::stop()
```

 

Stop the generator and the listener.

   

<a id="classespectre_1_1_csi_traffic_service_1a5460f876c4d4c3d67cb964f87bfc49fe"></a>

### `loop`


```cpp
void espectre::CsiTrafficService::loop()
```

 

Advance whichever source is running.

   

<a id="classespectre_1_1_csi_traffic_service_1acc1994d066d676521b378a7afea9928a"></a>

### `set_packet_callback`


```cpp
void espectre::CsiTrafficService::set_packet_callback(csi_traffic_packet_callback_t callback, void *context=nullptr)
```

 

Register the callback for accepted external packets.

   

<a id="classespectre_1_1_csi_traffic_service_1a9d1a8fb3968bd5e33d9c337d318670b4"></a>

### `is_running`


```cpp
bool espectre::CsiTrafficService::is_running() const
```

 

Whether the source for the configured mode is running.

   

<a id="classespectre_1_1_csi_traffic_service_1adeaf0bf26e4ca70025b4039c5ea6b00b"></a>

### `get_last_sender`


```cpp
bool espectre::CsiTrafficService::get_last_sender(UdpDatagramPeer *out_peer) const
```

 

Sender of the latest accepted external packet; false before the first one.

   

<a id="classespectre_1_1_csi_traffic_service_1ae9898ad9c4e5fc4ce168ac6fc27b851e"></a>

### `get_packets_received`


```cpp
uint64_t espectre::CsiTrafficService::get_packets_received() const
```

 

Accepted external packets since [init()](#classespectre_1_1_csi_traffic_service_1a2463a9630c708756b78379f60e4304d5).

   

<a id="classespectre_1_1_csi_traffic_service_1a8d04f3ce450e6dae24e9586ca1a0e5f5"></a>

### `get_generator_packets_total`


```cpp
uint32_t espectre::CsiTrafficService::get_generator_packets_total() const
```

 

Successful internal generator sends; zero in external mode.

   

<a id="classespectre_1_1_csi_traffic_service_1a66bc64c398ab10a4921ccc6a4f0403de"></a>

### `internal_icmp_identifier`


```cpp
uint16_t espectre::CsiTrafficService::internal_icmp_identifier() const
```

 

ICMP identifier of the internal ping traffic.

   

<a id="classespectre_1_1_csi_traffic_service_1acf8e9d5ff43fdcf137613571f0a2c868"></a>

### `mode`


```cpp
TrafficGeneratorMode espectre::CsiTrafficService::mode() const
```

 

Mode set by the last [init()](#classespectre_1_1_csi_traffic_service_1a2463a9630c708756b78379f60e4304d5).

   


<a id="structespectre_1_1_csi_traffic_service_config"></a>

## espectre::CsiTrafficServiceConfig



```cpp
#include <runtime/csi_traffic_service.h>
```



```cpp
struct espectre::CsiTrafficServiceConfig
```

 

Traffic policy for [CsiTrafficService](#classespectre_1_1_csi_traffic_service); build it with [to\_csi\_traffic\_config()](#namespaceespectre_1a3d748e9f1b0d5dbe5388efb97e13569d).

  

<a id="structespectre_1_1_csi_traffic_service_config_1a9c1cdc17665c3549f07c3c5bb68cb06d"></a>

### `mode`


```cpp
TrafficGeneratorMode espectre::CsiTrafficServiceConfig::mode {TrafficGeneratorMode::PING}
```

 

Internal generator mode, or `EXTERNAL` to listen for another host.

   

<a id="structespectre_1_1_csi_traffic_service_config_1a50268f115b693da1cb0fa47cab4f6a40"></a>

### `rate_pps`


```cpp
uint32_t espectre::CsiTrafficServiceConfig::rate_pps {100U}
```

 

Internal generator send rate, in packets per second.

   

<a id="structespectre_1_1_csi_traffic_service_config_1af04a97ecbce02d1d10d0c4e31d337a42"></a>

### `udp_port`


```cpp
uint16_t espectre::CsiTrafficServiceConfig::udp_port {5555U}
```

 

UDP port the external listener binds.

   

<a id="structespectre_1_1_csi_traffic_service_config_1ae0ba87c83740f931991bb4666afa6c1d"></a>

### `multicast_group`


```cpp
std::string espectre::CsiTrafficServiceConfig::multicast_group
```

 

IPv4 multicast group the external listener joins; empty for unicast only.

   


<a id="structespectre_1_1_direct_http_service_config"></a>

## espectre::DirectHttpServiceConfig



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
struct espectre::DirectHttpServiceConfig
```

  

<a id="structespectre_1_1_direct_http_service_config_1afdc25c605172c283f046b864fc75f536"></a>

### `allowed_origins`


```cpp
std::vector<std::string> espectre::DirectHttpServiceConfig::allowed_origins
```

   

<a id="structespectre_1_1_direct_http_service_config_1ad302cbbe428f3ebf2c46b235c23f420c"></a>

### `device_id`


```cpp
uint64_t espectre::DirectHttpServiceConfig::device_id {0U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1ac197b814e5841ac86aef20a349bc53c9"></a>

### `port`


```cpp
uint16_t espectre::DirectHttpServiceConfig::port {ESPECTRE_DIRECT_HTTP_PORT}
```

   

<a id="structespectre_1_1_direct_http_service_config_1ab2ba838a2fc400029f6f5a16c086f077"></a>

### `max_event_clients`


```cpp
size_t espectre::DirectHttpServiceConfig::max_event_clients {2U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1a06fc309448ba84ebbac7f1419bdf4f64"></a>

### `max_pending_requests`


```cpp
size_t espectre::DirectHttpServiceConfig::max_pending_requests {4U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1ad25d287f420112dfec65715119b10dcf"></a>

### `outbound_queue_depth`


```cpp
size_t espectre::DirectHttpServiceConfig::outbound_queue_depth {8U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1a5d5ddecc43f3c19e1534b1c593c80a07"></a>

### `max_requests_per_second`


```cpp
uint16_t espectre::DirectHttpServiceConfig::max_requests_per_second {20U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1abba7b1ff7aa346cd9c4574d1771afd4f"></a>

### `max_mutations_per_minute`


```cpp
uint16_t espectre::DirectHttpServiceConfig::max_mutations_per_minute {60U}
```

   

<a id="structespectre_1_1_direct_http_service_config_1af076038c08cbdbb6811eb2b09db08762"></a>

### `allow_missing_origin`


```cpp
bool espectre::DirectHttpServiceConfig::allow_missing_origin {false}
```

   

<a id="structespectre_1_1_direct_http_service_config_1ae2c8f96e540149e33adc4db28ac8a95b"></a>

### `allow_http_loopback_origins`


```cpp
bool espectre::DirectHttpServiceConfig::allow_http_loopback_origins {false}
```

   

<a id="structespectre_1_1_direct_http_service_config_1a1a1ee541cab1a782eed9074764ae269b"></a>

### `protocol_extension`


```cpp
const EspectreProtocolExtension* espectre::DirectHttpServiceConfig::protocol_extension {nullptr}
```

 

Optional frontend routes.

  

The immutable catalog must outlive this service.

  


<a id="structespectre_1_1_direct_http_service_config_1a937605cc8df763b5e028a051c3b47e4a"></a>

### `for_first_party_portals`


```cpp
static DirectHttpServiceConfig espectre::DirectHttpServiceConfig::for_first_party_portals()
```

 

Configuration for ESPectre's production and validation portals.

   


<a id="structespectre_1_1_direct_http_service_diagnostics"></a>

## espectre::DirectHttpServiceDiagnostics



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
struct espectre::DirectHttpServiceDiagnostics
```

  

<a id="structespectre_1_1_direct_http_service_diagnostics_1a9c7f0142a8d93556baeef9fdf63849a3"></a>

### `event_client_limit`


```cpp
size_t espectre::DirectHttpServiceDiagnostics::event_client_limit {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1ac707ab3bad71aef5cbb19e79c636f910"></a>

### `queue_capacity`


```cpp
size_t espectre::DirectHttpServiceDiagnostics::queue_capacity {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a8563f7956f0a9d8ffa358cf031b090d5"></a>

### `accepted_connections`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::accepted_connections {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a46d844448509e03ed47183648d9d0eec"></a>

### `rejected_connections`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::rejected_connections {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a1130f2f2217163e5f7c69d96eeaaa46c"></a>

### `malformed_requests`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::malformed_requests {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a3759c6627ef3e77a8070c56b37a938bd"></a>

### `oversized_requests`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::oversized_requests {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1afbda12528b3158bfe8b73e1729b18f74"></a>

### `rate_limited_requests`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::rate_limited_requests {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a5fedcd05e4e07aba75115a19fd2a0b7c"></a>

### `dropped_motion_events`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::dropped_motion_events {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1a642fe94b20a7c7e54f41fd513b9159d7"></a>

### `send_failures`


```cpp
uint32_t espectre::DirectHttpServiceDiagnostics::send_failures {0U}
```

   

<a id="structespectre_1_1_direct_http_service_diagnostics_1aec94025f197cf1408f7a52556db86fa7"></a>

### `queued_messages`


```cpp
size_t espectre::DirectHttpServiceDiagnostics::queued_messages {0U}
```

   


<a id="structespectre_1_1_direct_request"></a>

## espectre::DirectRequest



```cpp
#include <runtime/direct_http_protocol.h>
```



```cpp
struct espectre::DirectRequest
```

  

<a id="structespectre_1_1_direct_request_1adf922ed00c7a0f4e1f3639003ada642b"></a>

### `command_id`


```cpp
std::string espectre::DirectRequest::command_id
```

   

<a id="structespectre_1_1_direct_request_1ad00a242692f23702edc510466a3ddd18"></a>

### `command`


```cpp
std::string espectre::DirectRequest::command
```

   

<a id="structespectre_1_1_direct_request_1af1b326b84679b121e4495d128ce2f769"></a>

### `params`


```cpp
std::string espectre::DirectRequest::params {"{}"}
```

 

Syntactically valid JSON object containing command parameters.

   

<a id="structespectre_1_1_direct_request_1ad8acda6c3a8dd15be0dc5c1de5abd580"></a>

### `path`


```cpp
std::string espectre::DirectRequest::path
```

 

Request path, retained for resource-aware response handling.

   

<a id="structespectre_1_1_direct_request_1af80d15f9b41df7b5fb69e9cc2d8cde3e"></a>

### `http_method`


```cpp
std::string espectre::DirectRequest::http_method
```

 

HTTP method selected by the transport route.

   

<a id="structespectre_1_1_direct_request_1ae8e60534fc082b6e015412d3d8512ec7"></a>

### `asynchronous`


```cpp
bool espectre::DirectRequest::asynchronous {false}
```

 

Whether the accepted operation completes asynchronously.

   


<a id="structespectre_1_1_direct_wifi_snapshot"></a>

## espectre::DirectWifiSnapshot



```cpp
#include <runtime/esp_idf/direct_wifi_snapshot_esp_idf.h>
```



```cpp
struct espectre::DirectWifiSnapshot
```

  

<a id="structespectre_1_1_direct_wifi_snapshot_1a35fad680fbddf95dfc3d949827f25531"></a>

### `configured`


```cpp
bool espectre::DirectWifiSnapshot::configured {false}
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1a77b5b090fbac01ef3c6b04098cb774fb"></a>

### `connected`


```cpp
bool espectre::DirectWifiSnapshot::connected {false}
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1a654870b989f58fde00d8322e0fd4c09e"></a>

### `ssid`


```cpp
std::string espectre::DirectWifiSnapshot::ssid
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1a71e273d8802c9243de20cacf56d6257a"></a>

### `bssid`


```cpp
std::string espectre::DirectWifiSnapshot::bssid
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1a22518d182419dba3ff69f9500ed5a0bb"></a>

### `band`


```cpp
std::string espectre::DirectWifiSnapshot::band
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1aab4926f5f413440ec92938acd524c94f"></a>

### `channel`


```cpp
uint8_t espectre::DirectWifiSnapshot::channel {0U}
```

   

<a id="structespectre_1_1_direct_wifi_snapshot_1af8aa80bf3f802d719965d1dd4acf8c2a"></a>

### `rssi_dbm`


```cpp
int16_t espectre::DirectWifiSnapshot::rssi_dbm {INT16_MIN}
```

   


<a id="classespectre_1_1_esp_idf_direct_http_service"></a>

## espectre::EspIdfDirectHttpService



```cpp
#include <runtime/esp_idf/direct_http_service_esp_idf.h>
```



```cpp
class espectre::EspIdfDirectHttpService : public espectre::IDirectHttpService
```

  [`espectre::IDirectHttpService`](#classespectre_1_1_i_direct_http_service)



<a id="classespectre_1_1_esp_idf_direct_http_service_1af089ad0dc1f04f6c6df779fd334f253a"></a>

### `EspIdfDirectHttpService`


```cpp
espectre::EspIdfDirectHttpService::EspIdfDirectHttpService()
```

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1ac347e2a473f454a0dd361a2d2993e10f"></a>

### `~EspIdfDirectHttpService`


```cpp
espectre::EspIdfDirectHttpService::~EspIdfDirectHttpService() override
```

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1a7b8d45f4be693a762e4abe82fc2a20bf"></a>

### `setup`


```cpp
bool espectre::EspIdfDirectHttpService::setup(const DirectHttpServiceConfig &config, RequestHandler request_handler, ClientCountCallback client_count_callback) override
```

 

Configure and start the endpoint.

  

Safe to call again after shutdown.

  

<a id="classespectre_1_1_esp_idf_direct_http_service_1ae225e3119210aad76296207a590e13b6"></a>

### `setup_deferred`


```cpp
bool espectre::EspIdfDirectHttpService::setup_deferred(const DirectHttpServiceConfig &config, DeferredRequestHandler request_handler, ClientCountCallback client_count_callback) override
```

 

Configure a handler that may complete a request later.

  

The default preserves source compatibility for external transports that implement only synchronous Direct requests. A successful deferred handler must eventually call [complete\_deferred\_response()](#classespectre_1_1_esp_idf_direct_http_service_1a47b68b279c034d769daa2a257ae56a4e) with the opaque token.

  

<a id="classespectre_1_1_esp_idf_direct_http_service_1a47b68b279c034d769daa2a257ae56a4e"></a>

### `complete_deferred_response`


```cpp
bool espectre::EspIdfDirectHttpService::complete_deferred_response(uint64_t request_token, std::string response) override
```

 

Queue a deferred response only if the originating connection is live.

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1abbe2a278b424a1165475d8ffca79b78a"></a>

### `loop`


```cpp
void espectre::EspIdfDirectHttpService::loop() override
```

 

Pump deferred receive, dispatch, send work, and application callbacks from the frontend task.

  

Request, client-count, and raw-stop callbacks are never delivered from HTTP server or streaming worker tasks.

  

<a id="classespectre_1_1_esp_idf_direct_http_service_1a69bb753b2d9164edb8e4103810dff6d0"></a>

### `shutdown`


```cpp
void espectre::EspIdfDirectHttpService::shutdown() override
```

 

Stop accepting clients, close sockets, and release queued messages.

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1ada58a458d98dd8e124db39f943c3a2e5"></a>

### `running`


```cpp
bool espectre::EspIdfDirectHttpService::running() const override
```

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1ab361c7437c09142a8ef9c1c155923c49"></a>

### `event_client_count`


```cpp
size_t espectre::EspIdfDirectHttpService::event_client_count() const override
```

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1a6b1b073f0208576039b7e738b4924764"></a>

### `publish_event`


```cpp
bool espectre::EspIdfDirectHttpService::publish_event(const std::string &event_name, const std::string &data_json, bool replaceable_telemetry) override
```

 

Queue a normalized event for every connected client.

  

Telemetry events may replace an older queued event with the same name. State transitions and command responses must never be replaced by telemetry. Returns false when no client can accept the event.

  

<a id="classespectre_1_1_esp_idf_direct_http_service_1a53a673575c7d1bcd9b5c36415bb90883"></a>

### `diagnostics`


```cpp
DirectHttpServiceDiagnostics espectre::EspIdfDirectHttpService::diagnostics() const override
```

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1ac4e80472b1ff46d590b53873837ad3f5"></a>

### `set_raw_session_requested_callback`


```cpp
void espectre::EspIdfDirectHttpService::set_raw_session_requested_callback(RawSessionRequestedCallback callback) override
```

 

Register the frontend-task callback that opens collection for GET /csi.

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1a109597c4e5df813e81eb915429705722"></a>

### `start_raw_session`


```cpp
bool espectre::EspIdfDirectHttpService::start_raw_session(const RawCsiSessionConfig &config, RawSessionStoppedCallback stopped_callback) override
```

 

Begin one owner-bound raw session on the service's binary endpoint.

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1ac5b0595da73f263666c1db28954a6a26"></a>

### `stop_raw_session`


```cpp
bool espectre::EspIdfDirectHttpService::stop_raw_session(RawCsiStopReason reason) override
```

 

Stop the active raw session and close its binary socket.

  

The stopped callback is delivered by [loop()](#classespectre_1_1_esp_idf_direct_http_service_1abbe2a278b424a1165475d8ffca79b78a), or synchronously while [shutdown()](#classespectre_1_1_esp_idf_direct_http_service_1a69bb753b2d9164edb8e4103810dff6d0) completes on the owning frontend task.

  

<a id="classespectre_1_1_esp_idf_direct_http_service_1a6526110c0aa5da0fb3811dbdd53e20a7"></a>

### `offer_raw_packet`


```cpp
bool espectre::EspIdfDirectHttpService::offer_raw_packet(const RawCsiPacketView &packet) override
```

 

Copy one callback-scoped sample into the transport's bounded raw slots.

   

<a id="classespectre_1_1_esp_idf_direct_http_service_1af5f94e87f550721eca27dbbe0fda720a"></a>

### `raw_diagnostics`


```cpp
RawCsiSessionDiagnostics espectre::EspIdfDirectHttpService::raw_diagnostics() const override
```

   


<a id="classespectre_1_1_esp_idf_mqtt_transport"></a>

## espectre::EspIdfMqttTransport



```cpp
#include <runtime/esp_idf/mqtt_transport_esp_idf.h>
```



```cpp
class espectre::EspIdfMqttTransport : public espectre::IMqttTransport
```

  [`espectre::IMqttTransport`](#classespectre_1_1_i_mqtt_transport)



<a id="classespectre_1_1_esp_idf_mqtt_transport_1a2da630d0212338987259bff4a10a9d80"></a>

### `setup`


```cpp
bool espectre::EspIdfMqttTransport::setup(const EspectreDeviceConfig &config) override
```

 

Configure and start connecting.

  

Asynchronous: true means the client started, not that it reached the broker. Wait for the connection callback before expecting publishes to land. Calling it again tears down the previous client and reconfigures.

 

**Returns:** false when the configuration cannot produce a client, such as an empty [`EspectreDeviceConfig::mqtt_host`](#structespectre_1_1_espectre_device_config_1a6bc7843ffc079108684b040e77b59c89).

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1aec31bc8f488bfc7a6b72555a29fc3b3b"></a>

### `loop`


```cpp
void espectre::EspIdfMqttTransport::loop() override
```

 

Pump the client and dispatch callbacks.

  

Called from the frontend loop.

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1a273e04c6fb334df6d1c4e479f8a1e4b3"></a>

### `shutdown`


```cpp
void espectre::EspIdfMqttTransport::shutdown() override
```

 

Disconnect and release resources.

  

Safe to repeat.

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1afa5c443e6863e93a2dd9f32f2e613f35"></a>

### `connected`


```cpp
bool espectre::EspIdfMqttTransport::connected() const override
```

 

True while the broker connection is established.

   

<a id="classespectre_1_1_esp_idf_mqtt_transport_1af284c13242edeeff5b8b3d886cc65579"></a>

### `publish`


```cpp
bool espectre::EspIdfMqttTransport::publish(const std::string &topic, const std::string &payload, bool retain) override
```

 

Publish to an absolute topic.

  

**Parameters**

- `topic`: Full topic name, not a suffix.
- `payload`: Message body, copied before returning.
- `retain`: Ask the broker to retain the message, for state a late subscriber must still see, such as availability.

 

**Returns:** false when disconnected or the bounded publish queue rejects the message. Published at QoS 0, so true means queued locally, not delivered to the broker.

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1a67952e68321ad9cdcfc1b82622ec3a7b"></a>

### `publish_suffix`


```cpp
bool espectre::EspIdfMqttTransport::publish_suffix(const char *suffix, const std::string &payload, bool retain) override
```

 

Publish under this device's protocol topic prefix.

  

The prefix comes from the [`EspectreDeviceConfig`](#structespectre_1_1_espectre_device_config) passed to [`setup()`](#classespectre_1_1_esp_idf_mqtt_transport_1a2da630d0212338987259bff4a10a9d80), so callers pass only the trailing segment, for example `"motion"`.

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1a8cec31260ab4daf4f66751350c8ca667"></a>

### `subscribe`


```cpp
bool espectre::EspIdfMqttTransport::subscribe(const std::string &topic, MessageCallback callback) override
```

 

Register a topic and its handler.

  

Idempotent per topic: subscribing again replaces the handler. May be called before the connection is up; the subscription is issued on connect.

 

**Returns:** false for an empty topic or an empty callback.

  

<a id="classespectre_1_1_esp_idf_mqtt_transport_1aa7f6deb4f262fc2c1ec7afccfeb1200e"></a>

### `set_command_callback`


```cpp
void espectre::EspIdfMqttTransport::set_command_callback(CommandCallback callback) override
```

 

Handler for the device command topic, which the transport subscribes itself.

   

<a id="classespectre_1_1_esp_idf_mqtt_transport_1afb71bdbc4863a47767a5007d654c3b95"></a>

### `set_connection_callback`


```cpp
void espectre::EspIdfMqttTransport::set_connection_callback(ConnectionCallback callback) override
```

 

Handler for connection state changes, including reconnects.

   

<a id="classespectre_1_1_esp_idf_mqtt_transport_1a3a2d1e7ab0d60a4e392bd2fc79b4eddb"></a>

### `diagnostics`


```cpp
MqttTransportDiagnostics espectre::EspIdfMqttTransport::diagnostics() const override
```

 

Bounded outbound queue, drop, failure, and reconnect counters.

   


<a id="classespectre_1_1_esp_idf_peer_discovery_service"></a>

## espectre::EspIdfPeerDiscoveryService



```cpp
#include <runtime/esp_idf/peer_discovery_service_esp_idf.h>
```



```cpp
class espectre::EspIdfPeerDiscoveryService : public espectre::IPeerDiscoveryService
```

  [`espectre::IPeerDiscoveryService`](#classespectre_1_1_i_peer_discovery_service)



<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a40d1c980ae37e291ab24d88d201b757c"></a>

### `~EspIdfPeerDiscoveryService`


```cpp
espectre::EspIdfPeerDiscoveryService::~EspIdfPeerDiscoveryService() override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1ac001c1c13c4cbf01a9c6f27c1f422ad9"></a>

### `set_local_candidate`


```cpp
void espectre::EspIdfPeerDiscoveryService::set_local_candidate(PeerDiscoveryCandidate candidate) override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a7e51c6f94d43415b96582ea34fdf2f72"></a>

### `set_wifi_ready`


```cpp
void espectre::EspIdfPeerDiscoveryService::set_wifi_ready(bool ready) override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a147df34c433a40e27398f15c86fe821a"></a>

### `ready`


```cpp
bool espectre::EspIdfPeerDiscoveryService::ready() const override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a7cfe6e21dbfb5bd468d11c133256228b"></a>

### `active`


```cpp
bool espectre::EspIdfPeerDiscoveryService::active() const override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a8dcaf36dcea15b9bbe995f8c9914d62c"></a>

### `start`


```cpp
bool espectre::EspIdfPeerDiscoveryService::start(Completion completion) override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1a24e9feb077b08613329dc00f73531a0f"></a>

### `loop`


```cpp
void espectre::EspIdfPeerDiscoveryService::loop() override
```

   

<a id="classespectre_1_1_esp_idf_peer_discovery_service_1ad1b83e460b89a31850f30dce514c1794"></a>

### `shutdown`


```cpp
void espectre::EspIdfPeerDiscoveryService::shutdown() override
```

   


<a id="structespectre_1_1_espectre_api_event_descriptor"></a>

## espectre::EspectreApiEventDescriptor



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreApiEventDescriptor
```

  

<a id="structespectre_1_1_espectre_api_event_descriptor_1a7a8c650cd6ccf9c4372ef17bc5b71c36"></a>

### `name`


```cpp
const char* espectre::EspectreApiEventDescriptor::name
```

   

<a id="structespectre_1_1_espectre_api_event_descriptor_1ace0597942f8c3f7cad93752cebf512e6"></a>

### `event`


```cpp
EspectreEvent espectre::EspectreApiEventDescriptor::event
```

   

<a id="structespectre_1_1_espectre_api_event_descriptor_1ab37408482a4f126a88e34f7cebf51bf3"></a>

### `capability`


```cpp
EspectreDirectMethod espectre::EspectreApiEventDescriptor::capability
```

   


<a id="structespectre_1_1_espectre_api_route"></a>

## espectre::EspectreApiRoute



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreApiRoute
```

 

One canonical HTTP/resource mapping used by routing and capability output.

  

<a id="structespectre_1_1_espectre_api_route_1aa9709d67003f68cf23436eac4af47c2e"></a>

### `http_method`


```cpp
const char* espectre::EspectreApiRoute::http_method
```

   

<a id="structespectre_1_1_espectre_api_route_1a6a3ed1667d54ee57d4f8fc708581fd4d"></a>

### `path`


```cpp
const char* espectre::EspectreApiRoute::path
```

   

<a id="structespectre_1_1_espectre_api_route_1a7d6922e283a7c596184408e5ed8d5173"></a>

### `name`


```cpp
const char* espectre::EspectreApiRoute::name
```

   

<a id="structespectre_1_1_espectre_api_route_1a4afdd946b5eb049671a273fcc8f5de23"></a>

### `command`


```cpp
const char* espectre::EspectreApiRoute::command
```

   

<a id="structespectre_1_1_espectre_api_route_1a6e59efe828f71299c8d903d0d4799952"></a>

### `capability`


```cpp
EspectreDirectMethod espectre::EspectreApiRoute::capability
```

   

<a id="structespectre_1_1_espectre_api_route_1aba7095f764f6e13917e91a3e0ea25999"></a>

### `kind`


```cpp
EspectreApiRouteKind espectre::EspectreApiRoute::kind
```

   

<a id="structespectre_1_1_espectre_api_route_1a028522628d85078d9bac937d34941959"></a>

### `asynchronous`


```cpp
bool espectre::EspectreApiRoute::asynchronous
```

   

<a id="structespectre_1_1_espectre_api_route_1aa2589bf5cb55b904bb69b14b75096f15"></a>

### `validate`


```cpp
EspectreCommandValidator espectre::EspectreApiRoute::validate {nullptr}
```

   


<a id="structespectre_1_1_espectre_capability_profile"></a>

## espectre::EspectreCapabilityProfile



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreCapabilityProfile
```

 

Exact Direct command, event, and readable-configuration surface advertised by a frontend.

  

<a id="structespectre_1_1_espectre_capability_profile_1a3754a33de52acb5734ddc4c97b01db6a"></a>

### `methods`


```cpp
std::array<bool, static_cast<size_t>(EspectreDirectMethod::COUNT)> espectre::EspectreCapabilityProfile::methods {}
```

   

<a id="structespectre_1_1_espectre_capability_profile_1a0b35ac4d5e323f6f33573c1d8ccbe418"></a>

### `config_sections`


```cpp
std::array<bool, static_cast<size_t>(EspectreConfigSection::COUNT)> espectre::EspectreCapabilityProfile::config_sections {}
```

   

<a id="structespectre_1_1_espectre_capability_profile_1aaa03a4984112db226532b8fdf554594e"></a>

### `events`


```cpp
std::array<bool, static_cast<size_t>(EspectreEvent::COUNT)> espectre::EspectreCapabilityProfile::events {{true, true, true, true, true}}
```

   

<a id="structespectre_1_1_espectre_capability_profile_1a06c2e9bb86e8d0a0cebddd4a0e138087"></a>

### `extension`


```cpp
const EspectreProtocolExtension* espectre::EspectreCapabilityProfile::extension {nullptr}
```

 

Optional frontend-owned catalog, shared with its transport parsers.

   


<a id="structespectre_1_1_espectre_capability_profile_1af6f094856d4f5e4108cb0751672c007f"></a>

### `supports`


```cpp
bool espectre::EspectreCapabilityProfile::supports(EspectreDirectMethod method) const
```

   

<a id="structespectre_1_1_espectre_capability_profile_1a19fd61ef7f0e7960ff2909a5f6243f2f"></a>

### `set`


```cpp
void espectre::EspectreCapabilityProfile::set(EspectreDirectMethod method, bool enabled=true)
```

   

<a id="structespectre_1_1_espectre_capability_profile_1acb8dbe5a2f5fc8bad1adbec8194105c0"></a>

### `has`


```cpp
bool espectre::EspectreCapabilityProfile::has(EspectreConfigSection section) const
```

   

<a id="structespectre_1_1_espectre_capability_profile_1a0b55fb321de02c836169680bf579c20c"></a>

### `set`


```cpp
void espectre::EspectreCapabilityProfile::set(EspectreConfigSection section, bool enabled=true)
```

   

<a id="structespectre_1_1_espectre_capability_profile_1ae2b3b98049b2856d1feb176c0b7ff19c"></a>

### `publishes`


```cpp
bool espectre::EspectreCapabilityProfile::publishes(EspectreEvent event) const
```

   

<a id="structespectre_1_1_espectre_capability_profile_1a6d960b939d2d7ed6753d984ae159ac58"></a>

### `set`


```cpp
void espectre::EspectreCapabilityProfile::set(EspectreEvent event, bool enabled=true)
```

   

<a id="structespectre_1_1_espectre_capability_profile_1aa8e981afc3beacf03785a5dd13580e14"></a>

### `clear_events`


```cpp
void espectre::EspectreCapabilityProfile::clear_events()
```

   


<a id="structespectre_1_1_espectre_command"></a>

## espectre::EspectreCommand



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreCommand
```

 

A parsed control command.

  

Fields are optional by design: each `has_*` flag says whether the peer actually sent that field, so an unset value is never confused with a zero the caller meant. Apply only the flagged fields.

 

<a id="structespectre_1_1_espectre_command_1ae9f9733cf3d838398d3f8ef2e34b0821"></a>

### `command_id`


```cpp
std::string espectre::EspectreCommand::command_id
```

 

Correlation id echoed in the result payload.

  

May be empty.

  

<a id="structespectre_1_1_espectre_command_1afd0d4b74c5d8fb75f1238fed99612bcd"></a>

### `command`


```cpp
std::string espectre::EspectreCommand::command
```

 

Command verb, for example `"update_sensing"` or `"recalibrate"`.

   

<a id="structespectre_1_1_espectre_command_1a04c58cb2c7dc527168ea428e33310164"></a>

### `diagnostic_fields`


```cpp
std::vector<std::string> espectre::EspectreCommand::diagnostic_fields
```

 

Diagnostic paths to return; empty requests the catalog, and \["\*"\] requests all values.

   

<a id="structespectre_1_1_espectre_command_1a56690f670653ae3479daf1c622dfb6d2"></a>

### `sensing_enabled`


```cpp
bool espectre::EspectreCommand::sensing_enabled {false}
```

 

Requested sensing-service state for `update_sensing`.

   

<a id="structespectre_1_1_espectre_command_1ab7fce7acc1aa3eaf54985c2e2fc30918"></a>

### `has_sensing_enabled`


```cpp
bool espectre::EspectreCommand::has_sensing_enabled {false}
```

   

<a id="structespectre_1_1_espectre_command_1a4a6f143d3f0aa6eac8daa17e7435f316"></a>

### `device_label`


```cpp
std::string espectre::EspectreCommand::device_label
```

 

User-facing label requested by `update_device`; empty clears it.

   

<a id="structespectre_1_1_espectre_command_1aa1fe0f3fe39cfcf457a736113b33a71e"></a>

### `has_device_label`


```cpp
bool espectre::EspectreCommand::has_device_label {false}
```

 

Whether the command carried a valid string-valued [`device_label`](#structespectre_1_1_espectre_command_1a4a6f143d3f0aa6eac8daa17e7435f316).

   

<a id="structespectre_1_1_espectre_command_1ad1c410f2a60ad18eb5a257b486be4fb2"></a>

### `threshold`


```cpp
float espectre::EspectreCommand::threshold {0.0f}
```

   

<a id="structespectre_1_1_espectre_command_1a29fe6ed5b45c203e74bc9a066ff829be"></a>

### `has_threshold`


```cpp
bool espectre::EspectreCommand::has_threshold {false}
```

   

<a id="structespectre_1_1_espectre_command_1a80157a00785372468fa10b0b07ca1c54"></a>

### `motion_on_hits`


```cpp
uint8_t espectre::EspectreCommand::motion_on_hits {0U}
```

   

<a id="structespectre_1_1_espectre_command_1aea051c66df201eda9db54461f910781e"></a>

### `motion_off_hits`


```cpp
uint8_t espectre::EspectreCommand::motion_off_hits {0U}
```

   

<a id="structespectre_1_1_espectre_command_1a4cfaaf9bd50ec4b32f10279c611694f2"></a>

### `has_motion_hits`


```cpp
bool espectre::EspectreCommand::has_motion_hits {false}
```

   

<a id="structespectre_1_1_espectre_command_1a216bdbeabae77df5241b82de126dbdb4"></a>

### `traffic_generator_mode`


```cpp
std::string espectre::EspectreCommand::traffic_generator_mode
```

   

<a id="structespectre_1_1_espectre_command_1a89245feb9fe935e4f9207fac6c52a379"></a>

### `has_traffic_generator_mode`


```cpp
bool espectre::EspectreCommand::has_traffic_generator_mode {false}
```

   

<a id="structespectre_1_1_espectre_command_1ad706b46d3d8a0128a06d88cfa7cbefbe"></a>

### `detector`


```cpp
std::string espectre::EspectreCommand::detector
```

   

<a id="structespectre_1_1_espectre_command_1a754b3484de80075b8fa2cc0ea435af1c"></a>

### `has_detector`


```cpp
bool espectre::EspectreCommand::has_detector {false}
```

   

<a id="structespectre_1_1_espectre_command_1a24c6d08b3dacb6745b4c398b2c041234"></a>

### `wifi_bssid`


```cpp
std::string espectre::EspectreCommand::wifi_bssid
```

   

<a id="structespectre_1_1_espectre_command_1a8d345b5004accd98a6c536e34ccfc212"></a>

### `has_wifi_bssid`


```cpp
bool espectre::EspectreCommand::has_wifi_bssid {false}
```

   

<a id="structespectre_1_1_espectre_command_1a269c13bff465eca13b5a9218a238cc15"></a>

### `wifi_bssid_force`


```cpp
bool espectre::EspectreCommand::wifi_bssid_force {false}
```

 

Force reassociation even when [`wifi_bssid`](#structespectre_1_1_espectre_command_1a24c6d08b3dacb6745b4c398b2c041234) is already active.

   

<a id="structespectre_1_1_espectre_command_1a6e9584841c1b52066a4d4ea1fb84e14a"></a>

### `has_wifi_bssid_force`


```cpp
bool espectre::EspectreCommand::has_wifi_bssid_force {false}
```

   

<a id="structespectre_1_1_espectre_command_1a80590239b5b628431a94e8a94f881fc8"></a>

### `mqtt_scheme`


```cpp
std::string espectre::EspectreCommand::mqtt_scheme
```

   

<a id="structespectre_1_1_espectre_command_1a6ccd1af691634288857285ddef21ce43"></a>

### `mqtt_host`


```cpp
std::string espectre::EspectreCommand::mqtt_host
```

   

<a id="structespectre_1_1_espectre_command_1a578d1b64dc9bfecad0b7d2acc5ebdc10"></a>

### `mqtt_username`


```cpp
std::string espectre::EspectreCommand::mqtt_username
```

   

<a id="structespectre_1_1_espectre_command_1a4462672aafd9991d02ccec4897ab31c8"></a>

### `mqtt_password`


```cpp
std::string espectre::EspectreCommand::mqtt_password
```

   

<a id="structespectre_1_1_espectre_command_1a88fdc71c132a8589fc5dd0a62ef2458a"></a>

### `mqtt_topic_prefix`


```cpp
std::string espectre::EspectreCommand::mqtt_topic_prefix
```

   

<a id="structespectre_1_1_espectre_command_1a970cc86b87aa22ed74f7d1761187ad27"></a>

### `mqtt_port`


```cpp
uint16_t espectre::EspectreCommand::mqtt_port {0U}
```

   

<a id="structespectre_1_1_espectre_command_1ae6b2b6b7f272b8168fccba36e046c4b7"></a>

### `has_mqtt_scheme`


```cpp
bool espectre::EspectreCommand::has_mqtt_scheme {false}
```

   

<a id="structespectre_1_1_espectre_command_1a483cee09f1e344a19ab61f85519b37b6"></a>

### `has_mqtt_host`


```cpp
bool espectre::EspectreCommand::has_mqtt_host {false}
```

   

<a id="structespectre_1_1_espectre_command_1ae7ba0aa42d1640c1a059992e9f3e5ad3"></a>

### `has_mqtt_username`


```cpp
bool espectre::EspectreCommand::has_mqtt_username {false}
```

   

<a id="structespectre_1_1_espectre_command_1a3622a2d30ac29af8409fd070dddb09c3"></a>

### `has_mqtt_password`


```cpp
bool espectre::EspectreCommand::has_mqtt_password {false}
```

   

<a id="structespectre_1_1_espectre_command_1aa5b9810294f426dd4f8e3b48abd810d9"></a>

### `has_mqtt_topic_prefix`


```cpp
bool espectre::EspectreCommand::has_mqtt_topic_prefix {false}
```

   

<a id="structespectre_1_1_espectre_command_1ac25f88011125cec697bd5a3cf2fd9067"></a>

### `has_mqtt_port`


```cpp
bool espectre::EspectreCommand::has_mqtt_port {false}
```

   

<a id="structespectre_1_1_espectre_command_1aec085c9f5943af0864d214935cd6c08e"></a>

### `extension_parameters`


```cpp
std::string espectre::EspectreCommand::extension_parameters
```

 

JSON parameters for a frontend extension command.

  

Initially the whole request from [parse\_espectre\_command()](#namespaceespectre_1affd612c44046053715f0e4947c579959), or the parameter object from [parse\_espectre\_command\_request()](#namespaceespectre_1a3719c5d411370f85344e700a2eb961a5); its validator may normalize them.

  


<a id="structespectre_1_1_espectre_device_config"></a>

## espectre::EspectreDeviceConfig



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreDeviceConfig
```

 

Device identity and broker settings.

  

Frontends persist this so a device keeps its identity and connection across reboots and reprovisioning.

 

<a id="structespectre_1_1_espectre_device_config_1a81f5bcd174ba6f52c81481ce172d274a"></a>

### `device_id`


```cpp
uint64_t espectre::EspectreDeviceConfig::device_id {ESPECTRE_DEFAULT_DEVICE_ID}
```

 

Stable device identity.

  

Zero means use the runtime-generated value.

  

<a id="structespectre_1_1_espectre_device_config_1aca7110074cb8deafe9fc8653dd2ded4f"></a>

### `device_label`


```cpp
std::string espectre::EspectreDeviceConfig::device_label {ESPECTRE_DEFAULT_DEVICE_LABEL}
```

 

Human-readable name.

  

Empty falls back to the formatted device id.

  

<a id="structespectre_1_1_espectre_device_config_1add9bc633f1f75f7c12ddf44d83965335"></a>

### `mqtt_scheme`


```cpp
std::string espectre::EspectreDeviceConfig::mqtt_scheme
```

 

Broker transport scheme: `mqtt` or `mqtts`.

  

Empty disables MQTT.

  

<a id="structespectre_1_1_espectre_device_config_1a6bc7843ffc079108684b040e77b59c89"></a>

### `mqtt_host`


```cpp
std::string espectre::EspectreDeviceConfig::mqtt_host
```

 

Broker DNS hostname, IPv4 address, or IPv6 address, without URI framing.

   

<a id="structespectre_1_1_espectre_device_config_1ac8aed6d2ebbe21bfc26583502a705f75"></a>

### `mqtt_port`


```cpp
uint16_t espectre::EspectreDeviceConfig::mqtt_port {0U}
```

 

Broker port.

  

Zero means MQTT is not configured.

  

<a id="structespectre_1_1_espectre_device_config_1aaedefcaaec63f7b9bf2d46e69be0e6cb"></a>

### `mqtt_username`


```cpp
std::string espectre::EspectreDeviceConfig::mqtt_username
```

 

Broker credentials.

  

Leave empty for anonymous brokers.

  

<a id="structespectre_1_1_espectre_device_config_1afe6956ffef02ae5a6a5b807c3fbe47cc"></a>

### `mqtt_password`


```cpp
std::string espectre::EspectreDeviceConfig::mqtt_password
```

   

<a id="structespectre_1_1_espectre_device_config_1ae89cde8ec77492cd8dd8fb315206630f"></a>

### `topic_prefix`


```cpp
std::string espectre::EspectreDeviceConfig::topic_prefix {ESPECTRE_TOPIC_PREFIX}
```

 

Topic root.

  

Change it only if you also change every consumer.

  


<a id="structespectre_1_1_espectre_device_info"></a>

## espectre::EspectreDeviceInfo



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreDeviceInfo
```

 

What the device advertises about itself.

  

The `supports_*` flags are internal inputs used to build the filtered `capabilities` catalog. They are deliberately omitted from `info` so clients have one authoritative feature-discovery surface.

 

<a id="structespectre_1_1_espectre_device_info_1a98e0874253f5cc0a4fb98aaa26ecfcab"></a>

### `frontend`


```cpp
std::string espectre::EspectreDeviceInfo::frontend {"unknown"}
```

 

Frontend name, for example `"native"`, `"matter"`, or your own.

   

<a id="structespectre_1_1_espectre_device_info_1a30cedb7142b425b1a8e7ad27840191d1"></a>

### `firmware_version`


```cpp
std::string espectre::EspectreDeviceInfo::firmware_version {"unknown"}
```

 

Application version supplied by the frontend or integrator.

   

<a id="structespectre_1_1_espectre_device_info_1ac0ea5c264b21400d093ec20f44c690a9"></a>

### `chip`


```cpp
std::string espectre::EspectreDeviceInfo::chip {"unknown"}
```

 

Chip target, normally `CONFIG_IDF_TARGET`.

   

<a id="structespectre_1_1_espectre_device_info_1afeac4f05b3c3cc10e8db70d07ce07aab"></a>

### `detector`


```cpp
std::string espectre::EspectreDeviceInfo::detector
```

 

Active detector.

  

Left empty, it is filled from the snapshot.

  

<a id="structespectre_1_1_espectre_device_info_1a8cb8d65d9f6669566e70928e93bd8428"></a>

### `csi_profile`


```cpp
std::string espectre::EspectreDeviceInfo::csi_profile
```

 

Automatically selected CSI capture profile.

  

Left empty, it is filled from the snapshot.

  

<a id="structespectre_1_1_espectre_device_info_1a372030a3cb91330001da9723f4398247"></a>

### `supports_info`


```cpp
bool espectre::EspectreDeviceInfo::supports_info {true}
```

   

<a id="structespectre_1_1_espectre_device_info_1a437aec304310ffbadb7ed306345486f7"></a>

### `supports_diagnostics`


```cpp
bool espectre::EspectreDeviceInfo::supports_diagnostics {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1a3d5ea9c20ebbdf08c195ebf44860af6d"></a>

### `supports_device_config`


```cpp
bool espectre::EspectreDeviceInfo::supports_device_config {false}
```

 

`update_device` is honored and persists the user-facing label.

   

<a id="structespectre_1_1_espectre_device_info_1ac71dfcd58f5a2e8acc8496b742789344"></a>

### `supports_runtime_threshold`


```cpp
bool espectre::EspectreDeviceInfo::supports_runtime_threshold {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1aa5dc916c596456bf20292c70a0ff57d3"></a>

### `supports_runtime_motion_hits`


```cpp
bool espectre::EspectreDeviceInfo::supports_runtime_motion_hits {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1a1dc9fa2a45b8c5264b74378f5a62a0de"></a>

### `supports_runtime_detector`


```cpp
bool espectre::EspectreDeviceInfo::supports_runtime_detector {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1a7cf705f7ef81bc61231f21342ead22ae"></a>

### `supports_manual_recalibration`


```cpp
bool espectre::EspectreDeviceInfo::supports_manual_recalibration {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1ab96702463074b99a02d75e8448457920"></a>

### `supports_traffic_control`


```cpp
bool espectre::EspectreDeviceInfo::supports_traffic_control {false}
```

   

<a id="structespectre_1_1_espectre_device_info_1a1ae5306a262f1fceb0ace63065f3319a"></a>

### `traffic_mode`


```cpp
std::string espectre::EspectreDeviceInfo::traffic_mode
```

 

Traffic generator mode: `"ping"`, `"dns"`, `"dns_tcp"`, `"wifi_raw"`, or `"external"`.

  

Omitted from `info` when empty.

  

<a id="structespectre_1_1_espectre_device_info_1a9c6cd13342039c01196f9daa1bcf923b"></a>

### `csi_target_pps`


```cpp
uint32_t espectre::EspectreDeviceInfo::csi_target_pps {0U}
```

 

Internal traffic generator and temporal-grid target rate, in packets per second.

  

Omitted from `info` when zero.

  

<a id="structespectre_1_1_espectre_device_info_1addb54a961ad4acc29e410accb302b7f3"></a>

### `csi_traffic_udp_port`


```cpp
uint16_t espectre::EspectreDeviceInfo::csi_traffic_udp_port {0U}
```

 

UDP destination port used by the external CSI traffic generator.

   

<a id="structespectre_1_1_espectre_device_info_1a5e0e130624c638beeb2ca61c619bdecd"></a>

### `csi_traffic_multicast_group`


```cpp
std::string espectre::EspectreDeviceInfo::csi_traffic_multicast_group
```

 

IPv4 multicast group used by external CSI traffic, or empty for unicast-only operation.

   

<a id="structespectre_1_1_espectre_device_info_1a3dd182a7125e610e68f7158e3c09e20e"></a>

### `evaluation_interval_ms`


```cpp
uint32_t espectre::EspectreDeviceInfo::evaluation_interval_ms {0U}
```

 

Detector evaluation cadence, in milliseconds.

  

Omitted from `info` when zero. Canonical MQTT telemetry follows this interval.

  

<a id="structespectre_1_1_espectre_device_info_1a538ad375d04edaca9dc2fad775a23bf0"></a>

### `network`


```cpp
EspectreNetworkInfo espectre::EspectreDeviceInfo::network {}
```

   


<a id="structespectre_1_1_espectre_extension_route"></a>

## espectre::EspectreExtensionRoute



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreExtensionRoute
```

 

One frontend-owned route, shared by capability output and both transports.

  

<a id="structespectre_1_1_espectre_extension_route_1aab83e58cb053c7bb88f5c757f3ffdcb7"></a>

### `http_method`


```cpp
const char* espectre::EspectreExtensionRoute::http_method
```

   

<a id="structespectre_1_1_espectre_extension_route_1a11999df7cabf53bee4cd44e705f3b5ed"></a>

### `path`


```cpp
const char* espectre::EspectreExtensionRoute::path
```

   

<a id="structespectre_1_1_espectre_extension_route_1acb880c342282379b5504f90d611dd6e6"></a>

### `name`


```cpp
const char* espectre::EspectreExtensionRoute::name
```

   

<a id="structespectre_1_1_espectre_extension_route_1a283adbd2404039858219bb25b22c219e"></a>

### `command`


```cpp
const char* espectre::EspectreExtensionRoute::command
```

   

<a id="structespectre_1_1_espectre_extension_route_1a63477d3373b59335ed35c7fc30d44de7"></a>

### `kind`


```cpp
EspectreApiRouteKind espectre::EspectreExtensionRoute::kind
```

   

<a id="structespectre_1_1_espectre_extension_route_1a6259d196f36470a17e7c8e9833c6d609"></a>

### `asynchronous`


```cpp
bool espectre::EspectreExtensionRoute::asynchronous {false}
```

   

<a id="structespectre_1_1_espectre_extension_route_1a63cb47c8281f9d461f8c74c046a874af"></a>

### `mqtt`


```cpp
bool espectre::EspectreExtensionRoute::mqtt {false}
```

 

Whether the frontend command binding permits invocation over MQTT.

   

<a id="structespectre_1_1_espectre_extension_route_1a241fd946420c88d2acc33b131ca8fd17"></a>

### `allowed_during_raw_collection`


```cpp
bool espectre::EspectreExtensionRoute::allowed_during_raw_collection {false}
```

   

<a id="structespectre_1_1_espectre_extension_route_1a6d826025d23f40a66dbe03639c4d4f02"></a>

### `validate`


```cpp
EspectreCommandValidator espectre::EspectreExtensionRoute::validate {nullptr}
```

   


<a id="structespectre_1_1_espectre_network_info"></a>

## espectre::EspectreNetworkInfo



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreNetworkInfo
```

 

Link details available to frontends.

  

Canonical MQTT info publishes only the channel.

 

<a id="structespectre_1_1_espectre_network_info_1a539c43609365b6dc97ca3a953545b8a5"></a>

### `ip_address`


```cpp
std::string espectre::EspectreNetworkInfo::ip_address
```

   

<a id="structespectre_1_1_espectre_network_info_1abd4271a4c76579a0d556462cadd32ccf"></a>

### `mac_address`


```cpp
std::string espectre::EspectreNetworkInfo::mac_address
```

   

<a id="structespectre_1_1_espectre_network_info_1afb3afd351ae9f6c2fe654e23557b2130"></a>

### `channel`


```cpp
uint8_t espectre::EspectreNetworkInfo::channel {0U}
```

 

Wi-Fi channel in use.

  

Zero when unknown.

  


<a id="structespectre_1_1_espectre_protocol_extension"></a>

## espectre::EspectreProtocolExtension



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
struct espectre::EspectreProtocolExtension
```

 

Immutable frontend additions.

  

Keep this object alive while adapters use it.

 

<a id="structespectre_1_1_espectre_protocol_extension_1a09ee85f8d1fe38009b808ff420b13476"></a>

### `routes`


```cpp
std::vector<EspectreExtensionRoute> espectre::EspectreProtocolExtension::routes
```

   

<a id="structespectre_1_1_espectre_protocol_extension_1abcc84f7a49add2cd410f5a8d60de2b76"></a>

### `events`


```cpp
std::vector<std::string> espectre::EspectreProtocolExtension::events
```

   


<a id="structespectre_1_1_frontend_command_context"></a>

## espectre::FrontendCommandContext



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
struct espectre::FrontendCommandContext
```

 

Where a command came from.

  

<a id="structespectre_1_1_frontend_command_context_1afa2f9a45ea6a720e082bbc48dedcc414"></a>

### `origin`


```cpp
FrontendCommandOrigin espectre::FrontendCommandContext::origin {FrontendCommandOrigin::DIRECT}
```

   

<a id="structespectre_1_1_frontend_command_context_1ab5e3b6101f580199bbf31688f2514d4e"></a>

### `connection_token`


```cpp
uint64_t espectre::FrontendCommandContext::connection_token {0U}
```

 

Opaque identity of the originating Direct connection; zero otherwise.

   


<a id="classespectre_1_1_frontend_command_engine"></a>

## espectre::FrontendCommandEngine



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
class espectre::FrontendCommandEngine
```

 

Dispatches parsed protocol commands to frontend callbacks.

  

One engine serves every transport, so Direct HTTP, MQTT, and frontend surfaces apply the same capability checks and report the same result codes. The engine is stateless: frontends supply the capabilities and a callback for each kind of change they support. A command whose capability is not advertised, or whose callback is empty, is rejected as `unsupported`.

 

<a id="classespectre_1_1_frontend_command_engine_1a17c790151fd45182d2d020cd9d64019d"></a>

### `execute`


```cpp
FrontendCommandResult espectre::FrontendCommandEngine::execute(const EspectreCommand &command, const FrontendCommandContext &context, const FrontendCommandCapabilities &capabilities, FrontendReadPayloadCallback read_payload_callback, FrontendDeviceLabelCallback device_label_callback={}, FrontendThresholdCallback threshold_callback={}, FrontendMotionHitsCallback motion_hits_callback={}, FrontendTrafficGeneratorModeCallback traffic_generator_mode_callback={}, FrontendDetectorCallback detector_callback={}, FrontendRecalibrateCallback recalibrate_callback={}, FrontendWifiBssidCallback wifi_bssid_callback={}, FrontendMqttConfigCallback mqtt_config_callback={}, FrontendSensingControlCallback sensing_control_callback={}, FrontendSensingPreflightCallback sensing_preflight_callback={}) const
```

 

Execute a successfully parsed command.

  

Call a protocol parser first; this dispatcher checks capabilities and operational state, not parameters.

 

Read commands return the data from `read_payload_callback`. `update_sensing` first passes all its fields to `sensing_preflight_callback` and rejects the request as `invalid_params` if that fails, so nothing changes. It then applies the fields in order: detector, threshold, motion hits, traffic generator mode, then sensing state. A backend refusal after the preflight stops there; fields applied before it stay applied and are reported in [`FrontendCommandResult::changes`](#structespectre_1_1_frontend_command_result_1ac0e7393f21c05867f32f9678701a4fc6). Without a preflight callback, only capabilities are checked up front. Extension commands are not dispatched here; the application handles them.

  


<a id="structespectre_1_1_frontend_command_result"></a>

## espectre::FrontendCommandResult



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
struct espectre::FrontendCommandResult
```

 

Outcome of [FrontendCommandEngine::execute()](#classespectre_1_1_frontend_command_engine_1a17c790151fd45182d2d020cd9d64019d), ready for [`espectre_command_result_payload()`](#namespaceespectre_1a23723f52835cb183d122bbaf8c5348f7).

  

<a id="structespectre_1_1_frontend_command_result_1a4b54953067c0b0fcd0b038c252ed18d3"></a>

### `handled`


```cpp
bool espectre::FrontendCommandResult::handled {false}
```

 

Always true for results returned by the engine.

   

<a id="structespectre_1_1_frontend_command_result_1a10179374b91551f82aa42c753ac91d4d"></a>

### `accepted`


```cpp
bool espectre::FrontendCommandResult::accepted {false}
```

 

Whether the command was applied or its data returned.

   

<a id="structespectre_1_1_frontend_command_result_1a35b941acfbc8f0a40cd71fc4444eaa2d"></a>

### `command`


```cpp
EspectreCommand espectre::FrontendCommandResult::command {}
```

 

The command that was executed.

   

<a id="structespectre_1_1_frontend_command_result_1a054a49799aafb67785fc8e45f08b14c8"></a>

### `code`


```cpp
std::string espectre::FrontendCommandResult::code {"internal_error"}
```

 

Stable result code: `ok`, `unsupported`, `forbidden`, `invalid_params`, `unavailable`, or `busy`.

   

<a id="structespectre_1_1_frontend_command_result_1ab145d66eabc6ed3afd21183d93aecb23"></a>

### `message`


```cpp
std::string espectre::FrontendCommandResult::message
```

 

Human-readable outcome.

   

<a id="structespectre_1_1_frontend_command_result_1a5fad97cea2c08b2568ecd4e6a10a1f9b"></a>

### `data_json`


```cpp
std::string espectre::FrontendCommandResult::data_json
```

 

JSON data returned by a read command; empty otherwise.

   

<a id="structespectre_1_1_frontend_command_result_1ac0e7393f21c05867f32f9678701a4fc6"></a>

### `changes`


```cpp
FrontendCommandChange espectre::FrontendCommandResult::changes {FrontendCommandChange::NONE}
```

 

Resources the command changed.

  

A rejected `update_sensing` still reports the fields applied before the rejection, so republish whenever this is not `NONE`, whether or not the command was accepted.

  


<a id="structespectre_1_1_frontend_device_config_defaults"></a>

## espectre::FrontendDeviceConfigDefaults



```cpp
#include <runtime/esp_idf/frontend_bootstrap_helpers.h>
```



```cpp
struct espectre::FrontendDeviceConfigDefaults
```

  

<a id="structespectre_1_1_frontend_device_config_defaults_1a659cf3e49fbec2b285fef4fe3189c312"></a>

### `device_label`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::device_label {ESPECTRE_DEFAULT_DEVICE_LABEL}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1a85e6cdbfc4f4af2a7500bbe9445a1c64"></a>

### `mqtt_scheme`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::mqtt_scheme {""}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1a0cd73628ab466d42f4ede69287d42baa"></a>

### `mqtt_host`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::mqtt_host {""}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1ad2fc4516ea752d9bdf04a988edd4455b"></a>

### `mqtt_port`


```cpp
uint16_t espectre::FrontendDeviceConfigDefaults::mqtt_port {0U}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1ab2f2dfda15610082bab1c9ac3e032419"></a>

### `mqtt_username`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::mqtt_username {""}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1aa47a74274c8531654ba4df1df3f18ca3"></a>

### `mqtt_password`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::mqtt_password {""}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1a08565e041545e1d904857ee8a2326657"></a>

### `topic_prefix`


```cpp
const char* espectre::FrontendDeviceConfigDefaults::topic_prefix {ESPECTRE_TOPIC_PREFIX}
```

   

<a id="structespectre_1_1_frontend_device_config_defaults_1a1dcf1af494b14b5fde944157b30cf0ec"></a>

### `runtime_device_id`


```cpp
uint64_t espectre::FrontendDeviceConfigDefaults::runtime_device_id {0U}
```

   


<a id="structespectre_1_1_frontend_ha_diagnostic_sensor"></a>

## espectre::FrontendHaDiagnosticSensor



```cpp
#include <runtime/esp_idf/frontend_ha_mqtt_helpers.h>
```



```cpp
struct espectre::FrontendHaDiagnosticSensor
```

  

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a80fae5ab7d6d680529e1660f032d4ec8"></a>

### `name`


```cpp
std::string espectre::FrontendHaDiagnosticSensor::name
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a7ba7f5fbb9a271e618e1e69c670fdb72"></a>

### `key`


```cpp
std::string espectre::FrontendHaDiagnosticSensor::key
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a99372960224bd99cdf6099536c7180ee"></a>

### `object_id`


```cpp
std::string espectre::FrontendHaDiagnosticSensor::object_id
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a525e99d2d157a616b7f33fa17a4d43b7"></a>

### `state_topic`


```cpp
std::string espectre::FrontendHaDiagnosticSensor::state_topic
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a1e54481a565bb28da66564cc0a48575a"></a>

### `unit_of_measurement`


```cpp
const char* espectre::FrontendHaDiagnosticSensor::unit_of_measurement {nullptr}
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a68c00ff8cadb583266de1caf36b5a266"></a>

### `icon`


```cpp
const char* espectre::FrontendHaDiagnosticSensor::icon {nullptr}
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a84271971a0ad39ca08bf322ec9aacf9f"></a>

### `device_class`


```cpp
const char* espectre::FrontendHaDiagnosticSensor::device_class {nullptr}
```

   

<a id="structespectre_1_1_frontend_ha_diagnostic_sensor_1a88db374adaa551c9be06b4ef2614bec8"></a>

### `state_class_measurement`


```cpp
bool espectre::FrontendHaDiagnosticSensor::state_class_measurement {true}
```

   


<a id="structespectre_1_1_frontend_ha_discovery_message"></a>

## espectre::FrontendHaDiscoveryMessage



```cpp
#include <runtime/esp_idf/frontend_ha_mqtt_helpers.h>
```



```cpp
struct espectre::FrontendHaDiscoveryMessage
```

  

<a id="structespectre_1_1_frontend_ha_discovery_message_1a4e6b8493b03cc44a2bf674e83902cf22"></a>

### `topic`


```cpp
std::string espectre::FrontendHaDiscoveryMessage::topic
```

   

<a id="structespectre_1_1_frontend_ha_discovery_message_1abbf9846a07b76ef77dded5eff7fe2f9a"></a>

### `payload`


```cpp
std::string espectre::FrontendHaDiscoveryMessage::payload
```

   


<a id="structespectre_1_1_frontend_ha_mqtt_settings"></a>

## espectre::FrontendHaMqttSettings



```cpp
#include <runtime/esp_idf/frontend_ha_mqtt_helpers.h>
```



```cpp
struct espectre::FrontendHaMqttSettings
```

  

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a8d698ae0b479152a1541b2feee8c5b3e"></a>

### `discovery_prefix`


```cpp
std::string espectre::FrontendHaMqttSettings::discovery_prefix
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a7fb79e719d7e2d266759eaea05872c96"></a>

### `birth_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::birth_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1afded0cf1d681651914d115c267433088"></a>

### `availability_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::availability_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a1eab8acce95aa4a8a473bbb28383c4d4"></a>

### `availability_template`


```cpp
std::string espectre::FrontendHaMqttSettings::availability_template
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a6a46b306d5abd7cbe82652b88c607205"></a>

### `motion_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a3e9bb24b6ad400338516faf8c35cec1d"></a>

### `movement_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::movement_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a3062c20e610a4ad68e7afe7e850eeaa2"></a>

### `threshold_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::threshold_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a18fbd90a2a3ed2797ce8186f897a0fb3"></a>

### `threshold_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::threshold_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1acf6152f879910c7705e18a7608c1e5cb"></a>

### `motion_on_hits_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_on_hits_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1adf56175738267c11e5b760432603a681"></a>

### `motion_on_hits_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_on_hits_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a6e05ea3194206028b4f93e5d8de0450e"></a>

### `motion_off_hits_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_off_hits_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a26333e2e6f2475429d48a86be0373594"></a>

### `motion_off_hits_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_off_hits_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a22d72ad7a8c2b4fd8904dcfa2418ef8f"></a>

### `calibrate_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::calibrate_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a14ac2de9442389a5861f906465276415"></a>

### `calibrate_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::calibrate_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a9cda7589d40fc3547e29c496d6e02997"></a>

### `detector_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::detector_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a9a985fb5bb45df15025428de5cf0bfbe"></a>

### `detector_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::detector_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a9e81fc2b48889395da591a07b413b9ef"></a>

### `traffic_generator_mode_state_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::traffic_generator_mode_state_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a5e2c007cec86c2dcb03bf49781dc3d99"></a>

### `traffic_generator_mode_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::traffic_generator_mode_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a1e97a2be49e37b392da23d3093eddfd5"></a>

### `diagnostics_command_topic`


```cpp
std::string espectre::FrontendHaMqttSettings::diagnostics_command_topic
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1aebd7206ac2646bf74d76a78d9e8ed9ba"></a>

### `motion_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a0773e6e2399eb64fa91338f1da547b49"></a>

### `movement_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::movement_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a99b35971b177319b3037efa2ec0c3488"></a>

### `threshold_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::threshold_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1afa3ec3555092976c40b2216d58a377ca"></a>

### `motion_on_hits_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_on_hits_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1aac2915ea47c9dc2db666ae0abc668343"></a>

### `motion_off_hits_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::motion_off_hits_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a8ae34e66f2421743caf648499f1b1219"></a>

### `recalibrate_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::recalibrate_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a678649c91fad8ca213e0f25e0584ff4f"></a>

### `calibration_active_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::calibration_active_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a28772a882f61bba32dcc296ca2cf3c80"></a>

### `detector_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::detector_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1aadd5e5d5490b416e8592d69c079da520"></a>

### `traffic_generator_mode_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::traffic_generator_mode_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a80c4edcf18fa2eef5e66d9b437fd533d"></a>

### `diagnostics_object_id`


```cpp
std::string espectre::FrontendHaMqttSettings::diagnostics_object_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a5bf72ba04e894026945f7e412c9c410c"></a>

### `ha_object_prefix`


```cpp
std::string espectre::FrontendHaMqttSettings::ha_object_prefix
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a85a914412682eb7c3ff096355f7a40a7"></a>

### `diagnostic_sensors`


```cpp
std::vector<FrontendHaDiagnosticSensor> espectre::FrontendHaMqttSettings::diagnostic_sensors
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1abf85200e68fefd3aa06ec76013271550"></a>

### `device_id`


```cpp
std::string espectre::FrontendHaMqttSettings::device_id
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a5cf153b3ccf9a024f2d677ef7a9d892d"></a>

### `device_name`


```cpp
std::string espectre::FrontendHaMqttSettings::device_name
```

   

<a id="structespectre_1_1_frontend_ha_mqtt_settings_1a3293eeda4743499c6db7d62d3f4dece6"></a>

### `model`


```cpp
std::string espectre::FrontendHaMqttSettings::model
```

   


<a id="structespectre_1_1_frontend_wifi_station_options"></a>

## espectre::FrontendWifiStationOptions



```cpp
#include <runtime/esp_idf/frontend_bootstrap_helpers.h>
```



```cpp
struct espectre::FrontendWifiStationOptions
```

  

<a id="structespectre_1_1_frontend_wifi_station_options_1a206bffdeb0c807a05829aef07201b18e"></a>

### `ssid`


```cpp
const char* espectre::FrontendWifiStationOptions::ssid {nullptr}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1a29c8958337fe016cfaea779e71405d4e"></a>

### `password`


```cpp
const char* espectre::FrontendWifiStationOptions::password {nullptr}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1a9acbb9d91ae575bb9f865f78ef76d4de"></a>

### `bssid`


```cpp
const char* espectre::FrontendWifiStationOptions::bssid {nullptr}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1a38cbc5d9835a120fb95893d0f43e2448"></a>

### `configured_channel`


```cpp
int espectre::FrontendWifiStationOptions::configured_channel {0}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1aaea0f7e7c6dd4003c799294123f45692"></a>

### `max_retry`


```cpp
int espectre::FrontendWifiStationOptions::max_retry {8}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1acfef20b31152a3bd68da54724e0961c4"></a>

### `manage_csi_lifecycle`


```cpp
bool espectre::FrontendWifiStationOptions::manage_csi_lifecycle {false}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1ab768ec3b3ae37afbb890422e627e9e5d"></a>

### `start_manager`


```cpp
bool espectre::FrontendWifiStationOptions::start_manager {false}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1adc1b615bee32f339ac74c65f6db27683"></a>

### `change_callback`


```cpp
WifiProvisioningService::ChangeCallback espectre::FrontendWifiStationOptions::change_callback {}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1a84d42e71c8939635ed67ff8426c26ef6"></a>

### `connected_callback`


```cpp
standalone_wifi_callback_t espectre::FrontendWifiStationOptions::connected_callback {}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1aeae790292be454b20bf674bdd829592c"></a>

### `disconnected_callback`


```cpp
standalone_wifi_callback_t espectre::FrontendWifiStationOptions::disconnected_callback {}
```

   

<a id="structespectre_1_1_frontend_wifi_station_options_1aaa6cfc09dd4e9d59b5c52de40f8332f6"></a>

### `band_policy`


```cpp
WifiBandPolicy espectre::FrontendWifiStationOptions::band_policy {WifiBandPolicy::BAND_2G}
```

   


<a id="classespectre_1_1_high_accuracy_detector"></a>

## espectre::HighAccuracyDetector



```cpp
#include <core/high_accuracy_detector.h>
```



```cpp
class espectre::HighAccuracyDetector : public espectre::BaseDetector
```

 

Neural motion detector, using the MLP weights exported by training.

  

Unlike [`LightweightDetector`](#classespectre_1_1_lightweight_detector) it does not calibrate to the room: it ships a fixed threshold learned at training time, so it performs best in environments the training corpus represents. Check the per-chip figures in the [performance report](<https://github.com/francescopace/espectre/blob/main/docs/performance/README.md>) before choosing it over Lightweight.

 

Same usage as [`LightweightDetector`](#classespectre_1_1_lightweight_detector) on the core-only path, and the same threading rules. The weights in `core/ml_weights.h` are generated; see [ML\_TRAINING.md](<https://github.com/francescopace/espectre/blob/main/docs/ML_TRAINING.md>) to retrain them.

 [`espectre::BaseDetector`](#classespectre_1_1_base_detector)



<a id="classespectre_1_1_high_accuracy_detector_1a8abe924f8cfc5b950f03a81819660d50"></a>

### `HighAccuracyDetector`


```cpp
espectre::HighAccuracyDetector::HighAccuracyDetector(uint16_t window_size=DETECTOR_DEFAULT_WINDOW_SIZE, float threshold=HIGH_ACCURACY_DEFAULT_THRESHOLD, uint16_t lag=L1_DELTA_LAG)
```

 

Constructor.

  

**Parameters**

- `window_size`: Feature extraction window size in the inclusive range defined by DETECTOR\_MIN\_WINDOW\_SIZE and DETECTOR\_MAX\_WINDOW\_SIZE
- `threshold`: Motion detection threshold (0.0-1.0 on the ML probability scale)
- `lag`: Profile-displacement distance in packets. Production uses the nominal-rate default. Alternate values are for replay experiments and require retraining before deployment.

  

<a id="classespectre_1_1_high_accuracy_detector_1a419cca780bf04a8b49156eab81aba632"></a>

### `~HighAccuracyDetector`


```cpp
espectre::HighAccuracyDetector::~HighAccuracyDetector() override
```

   

<a id="classespectre_1_1_high_accuracy_detector_1aaa26e576e969f50a416ea9fa9be1f534"></a>

### `HighAccuracyDetector`


```cpp
espectre::HighAccuracyDetector::HighAccuracyDetector(HighAccuracyDetector &&other) noexcept
```

   

<a id="classespectre_1_1_high_accuracy_detector_1a753a343d584ca462f941244fa86704c5"></a>

### `operator=`


```cpp
HighAccuracyDetector & espectre::HighAccuracyDetector::operator=(HighAccuracyDetector &&other) noexcept
```

   

<a id="classespectre_1_1_high_accuracy_detector_1ad03f02184534d8d78022c4ef39bfe064"></a>

### `HighAccuracyDetector`


```cpp
espectre::HighAccuracyDetector::HighAccuracyDetector(const HighAccuracyDetector &)=delete
```

   

<a id="classespectre_1_1_high_accuracy_detector_1a88124904a2c79a845223d052c356d3f1"></a>

### `operator=`


```cpp
HighAccuracyDetector & espectre::HighAccuracyDetector::operator=(const HighAccuracyDetector &)=delete
```

   

<a id="classespectre_1_1_high_accuracy_detector_1a6b757cf36e76d564867142fbb7eed886"></a>

### `process_packet`


```cpp
void espectre::HighAccuracyDetector::process_packet(const int8_t *csi_data, size_t csi_len, const uint8_t *selected_subcarriers=nullptr, uint8_t num_subcarriers=0, int8_t rssi_dbm=INT8_MIN) override
```

 

Process one normalized, temporally admitted CSI packet.

  

Calculates spatial turbulence from CSI data, applies filtering, and stores in circular buffer.

 

**Parameters**

- `csi_data`: Normalized CSI data (I/Q interleaved)
- `csi_len`: Length of CSI data
- `selected_subcarriers`: Array of subcarrier indices
- `num_subcarriers`: Number of selected subcarriers
- `rssi_dbm`: Link RSSI for this packet, or INT8\_MIN when unknown

  

<a id="classespectre_1_1_high_accuracy_detector_1a346ad05afbe1ef410c4d66fb93b1ed82"></a>

### `advance_missing_slots`


```cpp
void espectre::HighAccuracyDetector::advance_missing_slots(uint32_t count) override
```

 

Advance packet-indexed feature rings for absent temporal slots.

   

<a id="classespectre_1_1_high_accuracy_detector_1ad2dc97f2244b7480e876aa2ec5434b09"></a>

### `update_state`


```cpp
void espectre::HighAccuracyDetector::update_state() override
```

 

Update state machine (call at the detector evaluation interval).

  

Subclasses implement their detection algorithm here.

  

<a id="classespectre_1_1_high_accuracy_detector_1ad74ad007107531f8d6256382723fdeea"></a>

### `clear_buffer`


```cpp
void espectre::HighAccuracyDetector::clear_buffer() override
```

 

Clear turbulence buffer (cold restart).

  

Virtual so detectors with additional state (e.g. L1-Delta profile rings) can extend the cold clear.

  

<a id="classespectre_1_1_high_accuracy_detector_1a2b06b097b5297dd0657135c35ed495ed"></a>

### `is_ready`


```cpp
bool espectre::HighAccuracyDetector::is_ready() const override
```

 

Check if detector is ready.

  

Ready once the window has filled and its valid slots reach the floor set by [set\_minimum\_valid\_samples()](#classespectre_1_1_base_detector_1a9732e34f845a2eb619ac9f42e1096353).

  

<a id="classespectre_1_1_high_accuracy_detector_1a5714b924b98643cec4011d1615aa9a42"></a>

### `is_valid`


```cpp
bool espectre::HighAccuracyDetector::is_valid() const override
```

 

Return whether all base detector working storage was allocated.

   

<a id="classespectre_1_1_high_accuracy_detector_1a05da3de784780af05d10273efdc079af"></a>

### `set_threshold`


```cpp
bool espectre::HighAccuracyDetector::set_threshold(float threshold) override
```

 

Set detection threshold.

  

**Parameters**

- `threshold`: New threshold value

 

**Returns:** true if value was accepted

  

<a id="classespectre_1_1_high_accuracy_detector_1aafe80e8f8559c570554a3d2712e68eca"></a>

### `get_threshold`


```cpp
float espectre::HighAccuracyDetector::get_threshold() const override
```

 

Get current threshold.

   

<a id="classespectre_1_1_high_accuracy_detector_1a6695e4d3a97f8387bda3f8ff6a227e81"></a>

### `get_name`


```cpp
const char * espectre::HighAccuracyDetector::get_name() const override
```

 

Get detector name for logging.

   

<a id="classespectre_1_1_high_accuracy_detector_1a1e1e180fb3242297ceb69bb55ad50a51"></a>

### `configure_hampel`


```cpp
void espectre::HighAccuracyDetector::configure_hampel(bool enabled, uint8_t window_size=HAMPEL_TURBULENCE_WINDOW_DEFAULT, float threshold=HAMPEL_TURBULENCE_THRESHOLD_DEFAULT) override
```

 

Configure Hampel filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `window_size`: Window size (3-11)
- `threshold`: MAD multiplier threshold

  

<a id="classespectre_1_1_high_accuracy_detector_1a1924bfdb1e6ae3c85172b3189551f2fe"></a>

### `configure_lowpass`


```cpp
void espectre::HighAccuracyDetector::configure_lowpass(bool enabled, float cutoff_hz=LOWPASS_CUTOFF_DEFAULT) override
```

 

Configure low-pass filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `cutoff_hz`: Cutoff frequency (5.0-20.0 Hz)

  


<a id="classespectre_1_1_i_csi_traffic_generator"></a>

## espectre::ICsiTrafficGenerator



```cpp
#include <runtime/csi_traffic_service.h>
```



```cpp
class espectre::ICsiTrafficGenerator
```

 

Internal traffic source that makes the access point answer the device.

  

[TrafficGeneratorManager](#classespectre_1_1_traffic_generator_manager) is the ESP-IDF implementation. Call every method from the owner task.

 

<a id="classespectre_1_1_i_csi_traffic_generator_1aa56d7c32d024963291509b76cd11da40"></a>

### `~ICsiTrafficGenerator`


```cpp
virtual espectre::ICsiTrafficGenerator::~ICsiTrafficGenerator()=default
```

   

<a id="classespectre_1_1_i_csi_traffic_generator_1a43ea91d3f4570aa0d281bae397c44ec8"></a>

### `init`


```cpp
virtual void espectre::ICsiTrafficGenerator::init(uint32_t target_pps, TrafficGeneratorMode mode)=0
```

 

Configure the send rate and mode while stopped.

   

<a id="classespectre_1_1_i_csi_traffic_generator_1aa91ad08e345f9f48335438c89990be27"></a>

### `start`


```cpp
virtual bool espectre::ICsiTrafficGenerator::start(uint32_t target_addr)=0
```

 

Start sending to an IPv4 address in network byte order; false on failure.

   

<a id="classespectre_1_1_i_csi_traffic_generator_1ae941653f3ec776a7b891486682ea053f"></a>

### `stop`


```cpp
virtual void espectre::ICsiTrafficGenerator::stop()=0
```

 

Stop sending and release the sender.

   

<a id="classespectre_1_1_i_csi_traffic_generator_1a7e069a25ab8bf08f7fcd07e4855e86e2"></a>

### `loop`


```cpp
virtual void espectre::ICsiTrafficGenerator::loop()=0
```

 

Advance periodic work from the owner task.

   

<a id="classespectre_1_1_i_csi_traffic_generator_1a199e6364991477c334ace5721c3b4b62"></a>

### `is_running`


```cpp
virtual bool espectre::ICsiTrafficGenerator::is_running() const =0
```

   

<a id="classespectre_1_1_i_csi_traffic_generator_1ae561e9b7aebda5148c1c62b97f9777d2"></a>

### `send_success_count`


```cpp
virtual uint32_t espectre::ICsiTrafficGenerator::send_success_count() const =0
```

 

Successful sends in the current session.

   

<a id="classespectre_1_1_i_csi_traffic_generator_1a92124965479b44d35b88a16a26d78775"></a>

### `icmp_identifier`


```cpp
virtual uint16_t espectre::ICsiTrafficGenerator::icmp_identifier() const =0
```

 

ICMP identifier used by ping traffic, so its replies can be recognized.

   


<a id="classespectre_1_1_i_csi_traffic_ingress"></a>

## espectre::ICsiTrafficIngress



```cpp
#include <runtime/csi_traffic_service.h>
```



```cpp
class espectre::ICsiTrafficIngress
```

 

Listener for traffic sent by another host in `EXTERNAL` mode.

  

Only datagrams whose payload matches the expected marker are counted and reported. Call every method from the owner task.

 

<a id="classespectre_1_1_i_csi_traffic_ingress_1a52abe6c059a0e7027b70c98f0f1d1ef5"></a>

### `~ICsiTrafficIngress`


```cpp
virtual espectre::ICsiTrafficIngress::~ICsiTrafficIngress()=default
```

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1a032e74b603c7c77e9a0c089d37c92784"></a>

### `init`


```cpp
virtual void espectre::ICsiTrafficIngress::init(uint16_t port)=0
```

 

Set the UDP port to bind at the next [start()](#classespectre_1_1_i_csi_traffic_ingress_1af32d5cf7242053f8a1998dec716362fd).

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1a4b1a7eafb45b592386a66fbeffcc5bc1"></a>

### `set_multicast_group`


```cpp
virtual void espectre::ICsiTrafficIngress::set_multicast_group(const char *group)=0
```

 

Set the multicast group to join, or `nullptr` for unicast only.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1a3d174084ec84ea73db71c60bee8b8f34"></a>

### `set_expected_payload`


```cpp
virtual void espectre::ICsiTrafficIngress::set_expected_payload(const uint8_t *payload, size_t len)=0
```

 

Set the payload a datagram must carry to be accepted.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1aa816a8caaec1016c7998756fd3031d45"></a>

### `set_packet_callback`


```cpp
virtual void espectre::ICsiTrafficIngress::set_packet_callback(csi_traffic_packet_callback_t callback, void *context=nullptr)=0
```

 

Register the per-packet callback; `context` is passed through unchanged.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1af32d5cf7242053f8a1998dec716362fd"></a>

### `start`


```cpp
virtual bool espectre::ICsiTrafficIngress::start()=0
```

 

Bind the socket and join the group; false on failure.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1af215abbbf80c1431220c5ab000fea810"></a>

### `stop`


```cpp
virtual void espectre::ICsiTrafficIngress::stop()=0
```

 

Close the socket.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1a5a6cc7046c6e4989caf2fa5ee3ac7c51"></a>

### `loop`


```cpp
virtual void espectre::ICsiTrafficIngress::loop()=0
```

 

Receive pending datagrams and deliver the callback.

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1aa443f08dd27cedcc84d2c732e3d860f5"></a>

### `is_running`


```cpp
virtual bool espectre::ICsiTrafficIngress::is_running() const =0
```

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1ac4cd5819ebc2847255bdfa5d9ecea39c"></a>

### `get_packets_received`


```cpp
virtual uint64_t espectre::ICsiTrafficIngress::get_packets_received() const =0
```

 

Accepted packets since [init()](#classespectre_1_1_i_csi_traffic_ingress_1a032e74b603c7c77e9a0c089d37c92784).

   

<a id="classespectre_1_1_i_csi_traffic_ingress_1aabedf208bf9ee9cd67baa5f03f4cc159"></a>

### `get_last_sender`


```cpp
virtual bool espectre::ICsiTrafficIngress::get_last_sender(UdpDatagramPeer *out_peer) const =0
```

 

Sender of the latest accepted packet; false before the first one.

   


<a id="classespectre_1_1_i_direct_http_service"></a>

## espectre::IDirectHttpService



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
class espectre::IDirectHttpService
```

 

Local HTTP endpoints shared by ESPectre firmware frontends.

  [`espectre::IDirectHttpService::DeferredRequestResult`](#structespectre_1_1_i_direct_http_service_1_1_deferred_request_result)



<a id="classespectre_1_1_i_direct_http_service_1a7d0434dbd3a5c12dffb28c2daffe5ec0"></a>

### `RequestHandler`


```cpp
using espectre::IDirectHttpService::RequestHandler = std::function<std::string(const DirectRequest &request)>
```

   

<a id="classespectre_1_1_i_direct_http_service_1a40bce5f4a53bdd8391e97b2cb7bbdb29"></a>

### `ResponseSentCallback`


```cpp
using espectre::IDirectHttpService::ResponseSentCallback = std::function<void(bool sent)>
```

   

<a id="classespectre_1_1_i_direct_http_service_1a01888012eaed141bfcf8cde8b25b36bf"></a>

### `DeferredRequestHandler`


```cpp
using espectre::IDirectHttpService::DeferredRequestHandler = 
std::function<DeferredRequestResult(uint64_t request_token, const DirectRequest &request)>
```

   

<a id="classespectre_1_1_i_direct_http_service_1a79e0cf4b601a74148e34ac9269b2d301"></a>

### `ClientCountCallback`


```cpp
using espectre::IDirectHttpService::ClientCountCallback = std::function<void(size_t event_client_count)>
```

   

<a id="classespectre_1_1_i_direct_http_service_1a586a3df77e489ea451bb53c0825736e2"></a>

### `RawSessionRequestedCallback`


```cpp
using espectre::IDirectHttpService::RawSessionRequestedCallback = std::function<bool(std::string *message)>
```

   

<a id="classespectre_1_1_i_direct_http_service_1af90d02bc26cb3c26b74f47858bfc898c"></a>

### `RawSessionStoppedCallback`


```cpp
using espectre::IDirectHttpService::RawSessionStoppedCallback = std::function<void(RawCsiStopReason reason)>
```

   


<a id="classespectre_1_1_i_direct_http_service_1a6942f8c8d9baa843bb95885b2d02e90f"></a>

### `~IDirectHttpService`


```cpp
virtual espectre::IDirectHttpService::~IDirectHttpService()=default
```

   

<a id="classespectre_1_1_i_direct_http_service_1a21bdc56c51f29cbfdec8545c8e52f705"></a>

### `setup`


```cpp
virtual bool espectre::IDirectHttpService::setup(const DirectHttpServiceConfig &config, RequestHandler request_handler, ClientCountCallback client_count_callback)=0
```

 

Configure and start the endpoint.

  

Safe to call again after shutdown.

  

<a id="classespectre_1_1_i_direct_http_service_1adb3a8a7bf1e9f08ce987142a1e7f9fce"></a>

### `setup_deferred`


```cpp
virtual bool espectre::IDirectHttpService::setup_deferred(const DirectHttpServiceConfig &config, DeferredRequestHandler request_handler, ClientCountCallback client_count_callback)
```

 

Configure a handler that may complete a request later.

  

The default preserves source compatibility for external transports that implement only synchronous Direct requests. A successful deferred handler must eventually call [complete\_deferred\_response()](#classespectre_1_1_i_direct_http_service_1a06fba7cb689b91f7be819faa83959575) with the opaque token.

  

<a id="classespectre_1_1_i_direct_http_service_1a06fba7cb689b91f7be819faa83959575"></a>

### `complete_deferred_response`


```cpp
virtual bool espectre::IDirectHttpService::complete_deferred_response(uint64_t request_token, std::string response)
```

 

Queue a deferred response only if the originating connection is live.

   

<a id="classespectre_1_1_i_direct_http_service_1a6f835ce9e9f17bd58c87b9b295f5a2c0"></a>

### `loop`


```cpp
virtual void espectre::IDirectHttpService::loop()=0
```

 

Pump deferred receive, dispatch, send work, and application callbacks from the frontend task.

  

Request, client-count, and raw-stop callbacks are never delivered from HTTP server or streaming worker tasks.

  

<a id="classespectre_1_1_i_direct_http_service_1ad8f2cf4aa8528504cfadfe34281e6e47"></a>

### `shutdown`


```cpp
virtual void espectre::IDirectHttpService::shutdown()=0
```

 

Stop accepting clients, close sockets, and release queued messages.

   

<a id="classespectre_1_1_i_direct_http_service_1af8e97ce6405baf11e9938a4040954ccd"></a>

### `running`


```cpp
virtual bool espectre::IDirectHttpService::running() const =0
```

   

<a id="classespectre_1_1_i_direct_http_service_1aae1a9b281bfcbbccf9d66df82eb02e0f"></a>

### `event_client_count`


```cpp
virtual size_t espectre::IDirectHttpService::event_client_count() const =0
```

   

<a id="classespectre_1_1_i_direct_http_service_1aebcaa2d23b59c0ab5b59b19ad6ff8b80"></a>

### `publish_event`


```cpp
virtual bool espectre::IDirectHttpService::publish_event(const std::string &event_name, const std::string &data_json, bool replaceable_telemetry)=0
```

 

Queue a normalized event for every connected client.

  

Telemetry events may replace an older queued event with the same name. State transitions and command responses must never be replaced by telemetry. Returns false when no client can accept the event.

  

<a id="classespectre_1_1_i_direct_http_service_1ad9436229255cef3652b5ad01e50776ff"></a>

### `diagnostics`


```cpp
virtual DirectHttpServiceDiagnostics espectre::IDirectHttpService::diagnostics() const =0
```

   

<a id="classespectre_1_1_i_direct_http_service_1a16aa9eb2c01a18b2b866cf6fc00cd29b"></a>

### `set_raw_session_requested_callback`


```cpp
virtual void espectre::IDirectHttpService::set_raw_session_requested_callback(RawSessionRequestedCallback callback)
```

 

Register the frontend-task callback that opens collection for GET /csi.

   

<a id="classespectre_1_1_i_direct_http_service_1a21cb31f0636c6ac84554baa3532c9c5e"></a>

### `start_raw_session`


```cpp
virtual bool espectre::IDirectHttpService::start_raw_session(const RawCsiSessionConfig &config, RawSessionStoppedCallback stopped_callback)
```

 

Begin one owner-bound raw session on the service's binary endpoint.

   

<a id="classespectre_1_1_i_direct_http_service_1ae2917eb53be05f00272a68d65e57b14e"></a>

### `stop_raw_session`


```cpp
virtual bool espectre::IDirectHttpService::stop_raw_session(RawCsiStopReason reason)
```

 

Stop the active raw session and close its binary socket.

  

The stopped callback is delivered by [loop()](#classespectre_1_1_i_direct_http_service_1a6f835ce9e9f17bd58c87b9b295f5a2c0), or synchronously while [shutdown()](#classespectre_1_1_i_direct_http_service_1ad8f2cf4aa8528504cfadfe34281e6e47) completes on the owning frontend task.

  

<a id="classespectre_1_1_i_direct_http_service_1af860d2e8e4bf884954de06e137b4e288"></a>

### `offer_raw_packet`


```cpp
virtual bool espectre::IDirectHttpService::offer_raw_packet(const RawCsiPacketView &packet)
```

 

Copy one callback-scoped sample into the transport's bounded raw slots.

   

<a id="classespectre_1_1_i_direct_http_service_1a78821b4bf5721bea25c4b8d0e8c96a62"></a>

### `raw_diagnostics`


```cpp
virtual RawCsiSessionDiagnostics espectre::IDirectHttpService::raw_diagnostics() const
```

   


<a id="structespectre_1_1_i_direct_http_service_1_1_deferred_request_result"></a>

## espectre::IDirectHttpService::DeferredRequestResult



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
struct espectre::IDirectHttpService::DeferredRequestResult
```

  

<a id="structespectre_1_1_i_direct_http_service_1_1_deferred_request_result_1a15136f0dc1f070fc1d4f92308833610a"></a>

### `deferred`


```cpp
bool espectre::IDirectHttpService::DeferredRequestResult::deferred {false}
```

   

<a id="structespectre_1_1_i_direct_http_service_1_1_deferred_request_result_1a67b7adb4a29195f681c2c036f0b1062b"></a>

### `response`


```cpp
std::string espectre::IDirectHttpService::DeferredRequestResult::response
```

   

<a id="structespectre_1_1_i_direct_http_service_1_1_deferred_request_result_1a86fb9d9ffe614b43ad86ffe37c1b8ea6"></a>

### `response_sent_callback`


```cpp
ResponseSentCallback espectre::IDirectHttpService::DeferredRequestResult::response_sent_callback {}
```

 

Runs on the frontend task after the response send attempt completes.

   


<a id="classespectre_1_1_i_mqtt_transport"></a>

## espectre::IMqttTransport



```cpp
#include <runtime/mqtt_transport.h>
```



```cpp
class espectre::IMqttTransport
```

 

The MQTT client seam.

  

Implement it to carry ESPectre Protocol messages over an MQTT stack you already own, then hand the instance to a frontend. [`EspIdfMqttTransport`](#classespectre_1_1_esp_idf_mqtt_transport) ([`mqtt_transport_esp_idf.h`](#mqtt__transport__esp__idf_8h)) is the shipped implementation over `esp-mqtt`.

 

Topic layout and payload schemas live in [API.md](<https://github.com/francescopace/espectre/blob/main/docs/API.md>), and [`espectre_protocol.h`](#espectre__protocol_8h) builds the payloads, so an implementation only has to move bytes.

 

**Par:** Contract for implementers

- The transport is driven from the frontend's task: [`loop()`](#classespectre_1_1_i_mqtt_transport_1a002372527235e03bac5686a7ef9be0ab) is where you pump your client and deliver queued callbacks.

- Publishing while disconnected must fail cleanly rather than block.

- Registered subscriptions must survive a reconnect. Callers subscribe once and expect the broker subscription to be reissued on the next connect.

 

<a id="classespectre_1_1_i_mqtt_transport_1acc0dc393b8a4f5c5224c1ca0d05f1ac5"></a>

### `CommandCallback`


```cpp
using espectre::IMqttTransport::CommandCallback = std::function<void(const std::string &)>
```

 

Payload of a message on the device command topic.

   

<a id="classespectre_1_1_i_mqtt_transport_1abf12230069adc2e4a4133c576b1b8266"></a>

### `ConnectionCallback`


```cpp
using espectre::IMqttTransport::ConnectionCallback = std::function<void(bool connected)>
```

 

Broker connection state changed; the argument is the new state.

   

<a id="classespectre_1_1_i_mqtt_transport_1af45c762723f4ec009cafb30d82b89952"></a>

### `MessageCallback`


```cpp
using espectre::IMqttTransport::MessageCallback = std::function<void(const std::string &, const std::string &)>
```

 

Message on a topic registered through [`subscribe()`](#classespectre_1_1_i_mqtt_transport_1a114eb79f1af4599ae9648eb87ae89797): `(topic, payload)`.

   


<a id="classespectre_1_1_i_mqtt_transport_1ad0c7866dc6c5ba5cf0d358b66df50349"></a>

### `~IMqttTransport`


```cpp
virtual espectre::IMqttTransport::~IMqttTransport()=default
```

   

<a id="classespectre_1_1_i_mqtt_transport_1ac7f78bbd532a797bf6b53e26d005269c"></a>

### `setup`


```cpp
virtual bool espectre::IMqttTransport::setup(const EspectreDeviceConfig &config)=0
```

 

Configure and start connecting.

  

Asynchronous: true means the client started, not that it reached the broker. Wait for the connection callback before expecting publishes to land. Calling it again tears down the previous client and reconfigures.

 

**Returns:** false when the configuration cannot produce a client, such as an empty [`EspectreDeviceConfig::mqtt_host`](#structespectre_1_1_espectre_device_config_1a6bc7843ffc079108684b040e77b59c89).

  

<a id="classespectre_1_1_i_mqtt_transport_1a002372527235e03bac5686a7ef9be0ab"></a>

### `loop`


```cpp
virtual void espectre::IMqttTransport::loop()=0
```

 

Pump the client and dispatch callbacks.

  

Called from the frontend loop.

  

<a id="classespectre_1_1_i_mqtt_transport_1a367dda8b9a7cc32831c3fec442cd21bc"></a>

### `shutdown`


```cpp
virtual void espectre::IMqttTransport::shutdown()=0
```

 

Disconnect and release resources.

  

Safe to repeat.

  

<a id="classespectre_1_1_i_mqtt_transport_1aef7b264520bd820dd1475efbce2de5df"></a>

### `connected`


```cpp
virtual bool espectre::IMqttTransport::connected() const =0
```

 

True while the broker connection is established.

   

<a id="classespectre_1_1_i_mqtt_transport_1a9a10597cee927b981bd42922ad51cd4e"></a>

### `publish`


```cpp
virtual bool espectre::IMqttTransport::publish(const std::string &topic, const std::string &payload, bool retain)=0
```

 

Publish to an absolute topic.

  

**Parameters**

- `topic`: Full topic name, not a suffix.
- `payload`: Message body, copied before returning.
- `retain`: Ask the broker to retain the message, for state a late subscriber must still see, such as availability.

 

**Returns:** false when disconnected or the bounded publish queue rejects the message. Published at QoS 0, so true means queued locally, not delivered to the broker.

  

<a id="classespectre_1_1_i_mqtt_transport_1adfa1ecc1df9c7fc39fb07181193b6844"></a>

### `publish_suffix`


```cpp
virtual bool espectre::IMqttTransport::publish_suffix(const char *suffix, const std::string &payload, bool retain)=0
```

 

Publish under this device's protocol topic prefix.

  

The prefix comes from the [`EspectreDeviceConfig`](#structespectre_1_1_espectre_device_config) passed to [`setup()`](#classespectre_1_1_i_mqtt_transport_1ac7f78bbd532a797bf6b53e26d005269c), so callers pass only the trailing segment, for example `"motion"`.

  

<a id="classespectre_1_1_i_mqtt_transport_1a114eb79f1af4599ae9648eb87ae89797"></a>

### `subscribe`


```cpp
virtual bool espectre::IMqttTransport::subscribe(const std::string &topic, MessageCallback callback)=0
```

 

Register a topic and its handler.

  

Idempotent per topic: subscribing again replaces the handler. May be called before the connection is up; the subscription is issued on connect.

 

**Returns:** false for an empty topic or an empty callback.

  

<a id="classespectre_1_1_i_mqtt_transport_1a65414cdc22b80c2da4450e2d06d42868"></a>

### `set_command_callback`


```cpp
virtual void espectre::IMqttTransport::set_command_callback(CommandCallback callback)=0
```

 

Handler for the device command topic, which the transport subscribes itself.

   

<a id="classespectre_1_1_i_mqtt_transport_1a383063c67062b06bd8cf8f3da0a07edb"></a>

### `set_connection_callback`


```cpp
virtual void espectre::IMqttTransport::set_connection_callback(ConnectionCallback callback)=0
```

 

Handler for connection state changes, including reconnects.

   

<a id="classespectre_1_1_i_mqtt_transport_1ab54187eeae50e6ded380bb419d005a46"></a>

### `diagnostics`


```cpp
virtual MqttTransportDiagnostics espectre::IMqttTransport::diagnostics() const
```

 

Bounded outbound queue, drop, failure, and reconnect counters.

   


<a id="classespectre_1_1_i_peer_discovery_service"></a>

## espectre::IPeerDiscoveryService



```cpp
#include <runtime/peer_discovery.h>
```



```cpp
class espectre::IPeerDiscoveryService
```

  

<a id="classespectre_1_1_i_peer_discovery_service_1a1cf223ccf5d6d21bf17a9b87ffef8beb"></a>

### `Completion`


```cpp
using espectre::IPeerDiscoveryService::Completion = std::function<void(PeerDiscoverySnapshot snapshot)>
```

   


<a id="classespectre_1_1_i_peer_discovery_service_1a47af08903f6fbd96795f32a2da5d2ee1"></a>

### `~IPeerDiscoveryService`


```cpp
virtual espectre::IPeerDiscoveryService::~IPeerDiscoveryService()=default
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1a8cee7d9b07243b4f198b202acf7e966e"></a>

### `set_local_candidate`


```cpp
virtual void espectre::IPeerDiscoveryService::set_local_candidate(PeerDiscoveryCandidate candidate)
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1a9dd1f18dada5bfa92db388cb380c8169"></a>

### `set_wifi_ready`


```cpp
virtual void espectre::IPeerDiscoveryService::set_wifi_ready(bool ready)=0
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1ac0290e5614d7ba46e6747f8f9c8e76fd"></a>

### `ready`


```cpp
virtual bool espectre::IPeerDiscoveryService::ready() const =0
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1a502f09da0fe65dd3b54377c43418b536"></a>

### `active`


```cpp
virtual bool espectre::IPeerDiscoveryService::active() const =0
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1a273a3530945f1215f9a75f18b83a56b7"></a>

### `start`


```cpp
virtual bool espectre::IPeerDiscoveryService::start(Completion completion)=0
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1aa2a2d8fe5b6313de00d94094f618d009"></a>

### `loop`


```cpp
virtual void espectre::IPeerDiscoveryService::loop()=0
```

   

<a id="classespectre_1_1_i_peer_discovery_service_1a5a198f14c09be33a478887cdb09b213c"></a>

### `shutdown`


```cpp
virtual void espectre::IPeerDiscoveryService::shutdown()=0
```

   


<a id="classespectre_1_1_i_runtime_listener"></a>

## espectre::IRuntimeListener



```cpp
#include <runtime/runtime_events.h>
```



```cpp
class espectre::IRuntimeListener
```

 

Everything the runtime tells your firmware.

  

Subclass it, override only what your product reacts to, and install it with `RuntimeFrontendController::setup(listener)`. Every callback has an empty default, so an integration that only cares about motion overrides one method.

 

**Par:** Threading and reentrancy

Callbacks are always delivered on the caller's task, never from an interrupt or the Wi-Fi driver:

- Sensing events (motion, readiness, periodic, live telemetry, calibration progress, and detector-driven threshold adaptation) originate in the CSI callback but are deferred through an internal mailbox and dispatched from `loop()`.

- Control-driven events (threshold writes, detector selection, and manual recalibration) fire inline on whichever task called the corresponding control method.

 [`on_threshold_changed()`](#classespectre_1_1_i_runtime_listener_1a6c97b8ed80d39f723a1d244b178c93f2) covers every threshold source: a setter, a calibration result, or Lightweight settled-level recovery.

 

Keep callbacks bounded and non-blocking. Slow work delays the next `loop()` iteration and can fill the bounded CSI mailbox, causing incoming frames to be dropped. Queue network publication, NVS writes, and other potentially blocking work for another task. Calling back into the controller is allowed, with one exception noted on [`on_runtime_fault()`](#classespectre_1_1_i_runtime_listener_1ae566b842c3e051c1230fe922a834a70f).

 

**Par:** Snapshot lifetime

The `snapshot` reference is only valid for the duration of the call. Copy it if you need it later.

 

**Par:** Readiness

Snapshots are delivered during startup calibration as well. Gate anything user-visible on [`RuntimeSnapshot::ready_to_publish`](#structespectre_1_1_runtime_snapshot_1a3e917a2d24bbe00e55416b9ddf3bffcd) so you do not report motion from an uncalibrated detector.

 

<a id="classespectre_1_1_i_runtime_listener_1a005de2f93b412c0fa098cb89bf150035"></a>

### `~IRuntimeListener`


```cpp
virtual espectre::IRuntimeListener::~IRuntimeListener()=default
```

   

<a id="classespectre_1_1_i_runtime_listener_1ac791b4ec86d1cfcd3cbb3f4a87981d79"></a>

### `on_sensing_readiness_changed`


```cpp
virtual void espectre::IRuntimeListener::on_sensing_readiness_changed(const RuntimeSnapshot &snapshot)
```

 

Public sensing readiness changed, including warm-up and input expiry.

  

[RuntimeFrontendController](#classespectre_1_1_runtime_frontend_controller) emits this from loop(), after caching the current snapshot, and once from an explicit shutdown() when sensing was ready; the controller destructor does not call the listener. Publish the sensing resource on both availability transitions.

 

**Parameters**

- `snapshot`: Current sensing state, including public readiness.

  

<a id="classespectre_1_1_i_runtime_listener_1a3b0fd8a11331f19d48085ccb4e9623d8"></a>

### `on_motion_state_changed`


```cpp
virtual void espectre::IRuntimeListener::on_motion_state_changed(const RuntimeSnapshot &snapshot)
```

 

The debounced motion state changed.

  

Edge-triggered and already filtered by `motion_on_hits` / `motion_off_hits`, so this is the hook for occupancy, relays, and notifications.

 

It also fires with [`MotionState::IDLE`](#namespaceespectre_1a7d37681f3243ed6bdd97aee1ed776857aa5daf7f2ebbba4975d61dab1c40188c7) when the Wi-Fi link drops, and that call carries `ready_to_publish == false`. A frontend that gates on that flag leaves its last published value in place across a disconnect; if your product would rather fail open, handle the not-ready edge explicitly instead of returning early.

 

**Parameters**

- `snapshot`: Sensing state at the moment of the change.

  

<a id="classespectre_1_1_i_runtime_listener_1a2d3d588024e38fa5db5b9a2ac92f2706"></a>

### `on_periodic_update`


```cpp
virtual void espectre::IRuntimeListener::on_periodic_update(const RuntimeSnapshot &snapshot, uint32_t csi_accepted)
```

 

Heartbeat, emitted every fixed [`RUNTIME_HEARTBEAT_INTERVAL_MS`](#namespaceespectre_1adac330f75e60dcf8bbc56efa51cac931) milliseconds.

  

Use it for status logging and diagnostics sampling rather than sensing telemetry. Movement and canonical MQTT telemetry follow detector evaluation through [`on_live_telemetry()`](#classespectre_1_1_i_runtime_listener_1a2473b19c1324d186b11ba596000acde9).

 

**Parameters**

- `snapshot`: Current sensing state, including the metric and threshold.
- `csi_accepted`: CSI packets the detector processed since the previous heartbeat, after temporal admission. This is the achieved sensing rate, not the capture-validation count in [`RuntimeDiagnosticsSnapshot::Csi::accepted_total`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a2d706255afa69bbfbc50492c82ffaa05).

  

<a id="classespectre_1_1_i_runtime_listener_1a6c97b8ed80d39f723a1d244b178c93f2"></a>

### `on_threshold_changed`


```cpp
virtual void espectre::IRuntimeListener::on_threshold_changed(const RuntimeSnapshot &snapshot)
```

 

The active threshold changed, from a control call, calibration, or detector-driven adaptation such as Lightweight settled-level recovery.

  

Refresh any threshold you mirror in a UI or a published entity. Live telemetry still carries the per-sample comparison value; this hook is the control-plane notification when that value itself has moved.

  

<a id="classespectre_1_1_i_runtime_listener_1a514dc3bb10087f78c374ba69265b7282"></a>

### `on_detector_changed`


```cpp
virtual void espectre::IRuntimeListener::on_detector_changed(const RuntimeSnapshot &snapshot)
```

 

The active detector changed.

  

Thresholds are per-detector, so [`on_threshold_changed()`](#classespectre_1_1_i_runtime_listener_1a6c97b8ed80d39f723a1d244b178c93f2) follows this one.

  

<a id="classespectre_1_1_i_runtime_listener_1a5d300e4e6a00a72a718f0c25aa181a34"></a>

### `on_calibration_started`


```cpp
virtual void espectre::IRuntimeListener::on_calibration_started(const RuntimeSnapshot &snapshot)
```

 

Startup calibration began; detection results are not valid yet.

  

Lightweight only. High Accuracy keeps a fixed threshold, so it skips this callback and reports [`on_calibration_finished()`](#classespectre_1_1_i_runtime_listener_1a27f8430a4a3b5b5dc6323765a2155e74) with `success` true at once.

  

<a id="classespectre_1_1_i_runtime_listener_1a27f8430a4a3b5b5dc6323765a2155e74"></a>

### `on_calibration_finished`


```cpp
virtual void espectre::IRuntimeListener::on_calibration_finished(const RuntimeSnapshot &snapshot, bool success)
```

 

Startup calibration finished.

  

The runtime releases completed threshold calibration resources before notifying the listener.

 

**Parameters**

- `snapshot`: Sensing state at completion, carrying the applied threshold.
- `success`: false when calibration was cancelled or could not settle on a threshold. The runtime keeps sensing with the threshold in force before this calibration, which after a failed startup calibration is the configured value. Treat this as a signal to surface, not a fatal error.

  

<a id="classespectre_1_1_i_runtime_listener_1a2473b19c1324d186b11ba596000acde9"></a>

### `on_live_telemetry`


```cpp
virtual void espectre::IRuntimeListener::on_live_telemetry(float movement, float threshold)
```

 

High-rate movement stream, one call per detector evaluation.

  

Frontends publish canonical telemetry and Movement Score from this hook. Considerably more frequent than [`on_periodic_update()`](#classespectre_1_1_i_runtime_listener_1a2d3d588024e38fa5db5b9a2ac92f2706); suppress it with `set_live_telemetry_enabled(false)` when nothing is watching.

 

**Parameters**

- `movement`: Current motion metric.
- `threshold`: Threshold it is compared against, on the same scale.

  

<a id="classespectre_1_1_i_runtime_listener_1ae566b842c3e051c1230fe922a834a70f"></a>

### `on_runtime_fault`


```cpp
virtual void espectre::IRuntimeListener::on_runtime_fault(const char *message)
```

 

A runtime-owned failure your firmware should surface.

  

**Parameters**

- `message`: Human-readable cause, valid only for this call.

 Do not drive the runtime from here beyond `shutdown()`: the fault is reported from inside runtime work, and re-entering control paths from it is not supported.

  


<a id="classespectre_1_1_i_udp_datagram_socket"></a>

## espectre::IUdpDatagramSocket



```cpp
#include <runtime/udp_datagram_socket.h>
```



```cpp
class espectre::IUdpDatagramSocket
```

  

<a id="classespectre_1_1_i_udp_datagram_socket_1aef6091336756e15eaca69b6c8d9c2614"></a>

### `~IUdpDatagramSocket`


```cpp
virtual espectre::IUdpDatagramSocket::~IUdpDatagramSocket()=default
```

   

<a id="classespectre_1_1_i_udp_datagram_socket_1a0902f85514a6eb87058257f6e03664e4"></a>

### `open`


```cpp
virtual bool espectre::IUdpDatagramSocket::open(uint16_t port, const char *multicast_group)=0
```

   

<a id="classespectre_1_1_i_udp_datagram_socket_1a6de650bf037bab96cc3fb3abe4e332d2"></a>

### `close`


```cpp
virtual void espectre::IUdpDatagramSocket::close()=0
```

   

<a id="classespectre_1_1_i_udp_datagram_socket_1afb8cf45cdfbf8d5ef06a9a05474d754f"></a>

### `receive`


```cpp
virtual UdpReceiveResult espectre::IUdpDatagramSocket::receive(uint8_t *buffer, size_t buffer_len, size_t *received_len, UdpDatagramPeer *peer)=0
```

   


<a id="structespectre_1_1_json_field_view"></a>

## espectre::JsonFieldView



```cpp
#include <runtime/protocol_json.h>
```



```cpp
struct espectre::JsonFieldView
```

 

Validated field whose raw JSON token remains in the caller-owned input.

  

<a id="structespectre_1_1_json_field_view_1a62caa94cc338b92850da051e8328c797"></a>

### `name`


```cpp
std::string espectre::JsonFieldView::name
```

 

Decoded field name.

   

<a id="structespectre_1_1_json_field_view_1aec7dff4b8b86809e57baf5a933757e35"></a>

### `type`


```cpp
JsonValueType espectre::JsonFieldView::type {JsonValueType::NULL_VALUE}
```

 

Kind of the referenced JSON token.

   

<a id="structespectre_1_1_json_field_view_1a922836069a9946b1a17a0ab6cb32e4ce"></a>

### `begin`


```cpp
size_t espectre::JsonFieldView::begin {0U}
```

 

Token offset relative to the parsed input range.

   

<a id="structespectre_1_1_json_field_view_1ad0218c3eb0b5b61915d3380de6105090"></a>

### `length`


```cpp
size_t espectre::JsonFieldView::length {0U}
```

 

Token size, including quotes and escapes for strings.

   


<a id="classespectre_1_1_json_input"></a>

## espectre::JsonInput



```cpp
#include <runtime/protocol_json.h>
```



```cpp
class espectre::JsonInput
```

 

Read-only JSON input that may span separately allocated buffers.

  

<a id="classespectre_1_1_json_input_1a768c8185680ba7ff5583c34929bbb2cd"></a>

### `~JsonInput`


```cpp
virtual espectre::JsonInput::~JsonInput()=default
```

   

<a id="classespectre_1_1_json_input_1a77bea6937bc2e2c2fc4b23e06e5d818e"></a>

### `size`


```cpp
virtual size_t espectre::JsonInput::size() const =0
```

 

Return the number of available bytes.

   

<a id="classespectre_1_1_json_input_1a192a1ed22238c3cd8ed7ee580eff86b0"></a>

### `operator[]`


```cpp
virtual char espectre::JsonInput::operator[](size_t offset) const =0
```

 

Read a byte at an offset strictly less than [size()](#classespectre_1_1_json_input_1a77bea6937bc2e2c2fc4b23e06e5d818e).

   


<a id="structespectre_1_1_json_object_field"></a>

## espectre::JsonObjectField



```cpp
#include <runtime/protocol_json.h>
```



```cpp
struct espectre::JsonObjectField
```

  

<a id="structespectre_1_1_json_object_field_1a1af29f07260e57a269cd982209e583b0"></a>

### `name`


```cpp
std::string espectre::JsonObjectField::name
```

   

<a id="structespectre_1_1_json_object_field_1a507478e78e0f77113b1672953cd6094d"></a>

### `type`


```cpp
JsonValueType espectre::JsonObjectField::type {JsonValueType::NULL_VALUE}
```

   

<a id="structespectre_1_1_json_object_field_1a5dd50afd8d4656c599e9681d33a469f1"></a>

### `value`


```cpp
std::string espectre::JsonObjectField::value
```

 

Decoded contents for strings, or the exact JSON token for every other type.

   


<a id="classespectre_1_1_lightweight_detector"></a>

## espectre::LightweightDetector



```cpp
#include <core/lightweight_detector.h>
```



```cpp
class espectre::LightweightDetector : public espectre::BaseDetector
```

 

The default detector: self-calibrating, no training data required.

  

Fuses turbulence autocorrelation with robust spread from a five-bin aggregated turbulence stream, and adapts its threshold to the room during startup calibration. After that, a long quiet stretch can still lower the live threshold when the opening was noisier than the rest of the session. The full runtime emits [`IRuntimeListener::on_threshold_changed()`](#classespectre_1_1_i_runtime_listener_1a6c97b8ed80d39f723a1d244b178c93f2) for that drop; a core-only integration must re-read [`get_threshold()`](#classespectre_1_1_lightweight_detector_1a6ec5c610ed3a5f766ba026a86d3f3110) after [`update_state()`](#classespectre_1_1_lightweight_detector_1a2c115275c63b3e4f4032d5218b1743d1). Prefer it unless you have a reason to run [`HighAccuracyDetector`](#classespectre_1_1_high_accuracy_detector).

 

Most integrations never construct one: [`RuntimeConfig::detection_algorithm`](#structespectre_1_1_runtime_config_1a3d14cc007fe6107bd81c6c6da176327a) selects it and the runtime owns the lifecycle. Drive it directly only on the core-only path, where your firmware already captures CSI:

 

```cpp
espectre::LightweightDetector detector;
if (!detector.is_valid()) { return; }
// For each slot retained by your temporal sampler:
detector.advance_missing_slots(missing_slots_before_this_packet);
detector.set_packet_timestamp_us(packet_timestamp_us);
detector.process_packet(csi, csi_len, espectre::DEFAULT_SUBCARRIERS,
                        espectre::HT20_SELECTED_BAND_SIZE, rssi_dbm);
// on your evaluation cadence:
detector.update_state();
if (detector.is_ready() && detector.get_state() == espectre::MotionState::MOTION) { ... }
```

 

[`is_ready()`](#classespectre_1_1_lightweight_detector_1ae7316e1b71611a18a03ad52b18f03ee7) is false until the window fills; results before that are not meaningful. See `runtime/esp_idf/csi_pipeline.cpp` for the reference normalization, cadence, and hit filtering around these calls, and [ALGORITHMS.md](<https://github.com/francescopace/espectre/blob/main/docs/ALGORITHMS.md>) for the algorithm itself.

 

**Par:** Threading

Not thread-safe. [`process_packet()`](#classespectre_1_1_lightweight_detector_1ad98770bd6ca93a90cc4baca9b45b72ce) and [`update_state()`](#classespectre_1_1_lightweight_detector_1a2c115275c63b3e4f4032d5218b1743d1) must not run concurrently.

 [`espectre::BaseDetector`](#classespectre_1_1_base_detector)



<a id="classespectre_1_1_lightweight_detector_1a2827677c475727e751cd53c70f215c46"></a>

### `LightweightDetector`


```cpp
espectre::LightweightDetector::LightweightDetector(uint16_t window_size=DETECTOR_DEFAULT_WINDOW_SIZE, float threshold=LIGHTWEIGHT_DEFAULT_THRESHOLD, uint16_t autocorr_lag=1U)
```

 

Constructor.

  

**Parameters**

- `window_size`: Detector window in packets
- `threshold`: Motion probability threshold
- `autocorr_lag`: Turbulence autocorrelation distance in packets

 Production uses the nominal-rate default. Alternate lags are exposed for replay experiments only: changing the feature offset requires validating the fitted coefficients before deployment. See `core/detector_timing.h`.

  

<a id="classespectre_1_1_lightweight_detector_1a3a8e768134861844f23a49dd0ad1cc16"></a>

### `~LightweightDetector`


```cpp
espectre::LightweightDetector::~LightweightDetector() override=default
```

   

<a id="classespectre_1_1_lightweight_detector_1a4dee4a11dd008112747999be2537ed5f"></a>

### `LightweightDetector`


```cpp
espectre::LightweightDetector::LightweightDetector(LightweightDetector &&other) noexcept=default
```

   

<a id="classespectre_1_1_lightweight_detector_1ad56def16d1aac6ff2bf2ff937de4c75f"></a>

### `operator=`


```cpp
LightweightDetector & espectre::LightweightDetector::operator=(LightweightDetector &&other) noexcept=default
```

   

<a id="classespectre_1_1_lightweight_detector_1a943f38c526f8402d109d2aa28a41c8f4"></a>

### `LightweightDetector`


```cpp
espectre::LightweightDetector::LightweightDetector(const LightweightDetector &)=delete
```

   

<a id="classespectre_1_1_lightweight_detector_1ade8a697de335b7644e9c9d4d29934526"></a>

### `operator=`


```cpp
LightweightDetector & espectre::LightweightDetector::operator=(const LightweightDetector &)=delete
```

   

<a id="classespectre_1_1_lightweight_detector_1ad98770bd6ca93a90cc4baca9b45b72ce"></a>

### `process_packet`


```cpp
void espectre::LightweightDetector::process_packet(const int8_t *csi_data, size_t csi_len, const uint8_t *selected_subcarriers=nullptr, uint8_t num_subcarriers=0, int8_t rssi_dbm=INT8_MIN) override
```

 

Process one normalized, temporally admitted CSI packet.

  

Calculates spatial turbulence from CSI data, applies filtering, and stores in circular buffer.

 

**Parameters**

- `csi_data`: Normalized CSI data (I/Q interleaved)
- `csi_len`: Length of CSI data
- `selected_subcarriers`: Array of subcarrier indices
- `num_subcarriers`: Number of selected subcarriers
- `rssi_dbm`: Link RSSI for this packet, or INT8\_MIN when unknown

  

<a id="classespectre_1_1_lightweight_detector_1aa93ad761aa4e7111ed6b0e2e30496366"></a>

### `advance_missing_slots`


```cpp
void espectre::LightweightDetector::advance_missing_slots(uint32_t count) override
```

 

Advance packet-indexed feature rings for absent temporal slots.

   

<a id="classespectre_1_1_lightweight_detector_1a2c115275c63b3e4f4032d5218b1743d1"></a>

### `update_state`


```cpp
void espectre::LightweightDetector::update_state() override
```

 

Update state machine (call at the detector evaluation interval).

  

Subclasses implement their detection algorithm here.

  

<a id="classespectre_1_1_lightweight_detector_1aadbd176e74980d13d4560b36d55728d7"></a>

### `reset`


```cpp
void espectre::LightweightDetector::reset() override
```

 

Reset detector state.

  

Resets state machine but preserves buffer ("warm" restart).

  

<a id="classespectre_1_1_lightweight_detector_1ae3c4afa60d1448f142853b296c9c94eb"></a>

### `clear_buffer`


```cpp
void espectre::LightweightDetector::clear_buffer() override
```

 

Clear turbulence buffer (cold restart).

  

Virtual so detectors with additional state (e.g. L1-Delta profile rings) can extend the cold clear.

  

<a id="classespectre_1_1_lightweight_detector_1a593fe23304af8dcedea11856fc1c495b"></a>

### `configure_hampel`


```cpp
void espectre::LightweightDetector::configure_hampel(bool enabled, uint8_t window_size=HAMPEL_TURBULENCE_WINDOW_DEFAULT, float threshold=HAMPEL_TURBULENCE_THRESHOLD_DEFAULT) override
```

 

Configure Hampel filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `window_size`: Window size (3-11)
- `threshold`: MAD multiplier threshold

  

<a id="classespectre_1_1_lightweight_detector_1a49437a685bbd6f18e6439e2d2cd1a650"></a>

### `configure_lowpass`


```cpp
void espectre::LightweightDetector::configure_lowpass(bool enabled, float cutoff_hz=LOWPASS_CUTOFF_DEFAULT) override
```

 

Configure low-pass filter.

  

**Parameters**

- `enabled`: Whether to enable the filter
- `cutoff_hz`: Cutoff frequency (5.0-20.0 Hz)

  

<a id="classespectre_1_1_lightweight_detector_1ae7316e1b71611a18a03ad52b18f03ee7"></a>

### `is_ready`


```cpp
bool espectre::LightweightDetector::is_ready() const override
```

 

Check if detector is ready.

  

Ready once the window has filled and its valid slots reach the floor set by [set\_minimum\_valid\_samples()](#classespectre_1_1_base_detector_1a9732e34f845a2eb619ac9f42e1096353).

  

<a id="classespectre_1_1_lightweight_detector_1a5313035ca79adb3270764b4f53021cdf"></a>

### `is_valid`


```cpp
bool espectre::LightweightDetector::is_valid() const override
```

 

Return whether all base detector working storage was allocated.

   

<a id="classespectre_1_1_lightweight_detector_1a03a94bf71221845a156b778aba9f2c4a"></a>

### `set_threshold`


```cpp
bool espectre::LightweightDetector::set_threshold(float threshold) override
```

 

Set detection threshold.

  

**Parameters**

- `threshold`: New threshold value

 

**Returns:** true if value was accepted

  

<a id="classespectre_1_1_lightweight_detector_1ab5359cd2f8ac714c018d6f0b11745ca1"></a>

### `set_adaptive_threshold`


```cpp
bool espectre::LightweightDetector::set_adaptive_threshold(float threshold) override
```

 

Apply a detector-specific startup-calibrated threshold.

   

<a id="classespectre_1_1_lightweight_detector_1a6ec5c610ed3a5f766ba026a86d3f3110"></a>

### `get_threshold`


```cpp
float espectre::LightweightDetector::get_threshold() const override
```

 

Get current threshold.

   

<a id="classespectre_1_1_lightweight_detector_1a9a64dac4614bdc6013375f59a15ecfe1"></a>

### `get_name`


```cpp
const char * espectre::LightweightDetector::get_name() const override
```

 

Get detector name for logging.

   

<a id="classespectre_1_1_lightweight_detector_1a7aa058c0d53152d81f5da9d1989fd141"></a>

### `get_startup_threshold_factor`


```cpp
float espectre::LightweightDetector::get_startup_threshold_factor() const override
```

 

Get the detector-specific automatic startup multiplier.

  

threshold = threshold\_metric x factor, where `threshold_metric` comes from the shared startup calibrator.

  

<a id="classespectre_1_1_lightweight_detector_1a4d060e026a59eb3c7c381992cf274b51"></a>

### `calibration_motion_ceiling`


```cpp
float espectre::LightweightDetector::calibration_motion_ceiling() const override
```

 

Motion metric above which a calibration evaluation counts as motion.

  

An evaluation above it restarts the calibration window. A recalibration under the setup of the last successful calibration also restarts above the live threshold when that is lower. The default, infinity, leaves calibration without an absolute reference.

  

<a id="classespectre_1_1_lightweight_detector_1a1cb63dff32578d0e76e5593057efec8b"></a>

### `startup_calibration_conclusive`


```cpp
bool espectre::LightweightDetector::startup_calibration_conclusive() const override
```

 

Whether the calibration evidence collected so far can set a threshold.

  

The runtime asks each time the calibration budget is spent. While the answer is false, the calibration continues in steps of half its initial budget, up to three times that budget. The default always concludes.

  

<a id="classespectre_1_1_lightweight_detector_1a5c3f2b65e433379face4641fb3398bb0"></a>

### `on_startup_calibration_begin`


```cpp
void espectre::LightweightDetector::on_startup_calibration_begin() override
```

 

Hook called immediately before startup calibration begins.

   

<a id="classespectre_1_1_lightweight_detector_1a3d0cb8a72ad26769ffddacc1db32b8ba"></a>

### `on_startup_calibration_complete`


```cpp
void espectre::LightweightDetector::on_startup_calibration_complete() override
```

 

Hook called when startup calibration completes successfully.

  

Detectors can freeze session-specific state here before the runtime performs its warm clear between calibration and steady-state detection.

  

<a id="classespectre_1_1_lightweight_detector_1ad1de55d8d9218f585284327b8931213d"></a>

### `on_startup_calibration_abandoned`


```cpp
void espectre::LightweightDetector::on_startup_calibration_abandoned() override
```

 

Hook called when a calibration ends without a result.

  

The runtime keeps the threshold in force before the calibration began. Detectors discard the evidence collected since [on\_startup\_calibration\_begin()](#classespectre_1_1_lightweight_detector_1a5c3f2b65e433379face4641fb3398bb0) and resume the adaptation they had, or start adapting the threshold in force if no calibration has completed.

  

<a id="classespectre_1_1_lightweight_detector_1a7c69093cdce4f6390740e79d4ec21647"></a>

### `get_turb_autocorr`


```cpp
float espectre::LightweightDetector::get_turb_autocorr() const
```

   

<a id="classespectre_1_1_lightweight_detector_1a79cc507df17c747f3340fdc600cce909"></a>

### `get_turb_iqr_over_mean_aggr`


```cpp
float espectre::LightweightDetector::get_turb_iqr_over_mean_aggr() const
```

   

<a id="classespectre_1_1_lightweight_detector_1a9759c675e359c00c802e049339f5327d"></a>

### `get_logit`


```cpp
float espectre::LightweightDetector::get_logit() const
```

   


<a id="structespectre_1_1_log_sink"></a>

## espectre::LogSink



```cpp
#include <core/espectre_log.h>
```



```cpp
struct espectre::LogSink
```

 

Frontend-owned logging callbacks.

  

ESPectre copies this value when it is registered but does not own [`context`](#structespectre_1_1_log_sink_1a0766bd86173c1c6da6bd67fecdd70e20). The context and callbacks must remain valid until the sink is cleared.

 

<a id="structespectre_1_1_log_sink_1a0766bd86173c1c6da6bd67fecdd70e20"></a>

### `context`


```cpp
void* espectre::LogSink::context {nullptr}
```

   

<a id="structespectre_1_1_log_sink_1a308ac37737bd18dc082d8b9efef056f2"></a>

### `enabled`


```cpp
LogEnabledCallback espectre::LogSink::enabled {nullptr}
```

   

<a id="structespectre_1_1_log_sink_1a27a477296e13456e0557b6b55cf57185"></a>

### `write`


```cpp
LogWriteCallback espectre::LogSink::write {nullptr}
```

   


<a id="classespectre_1_1_mdns_bootstrap_responder"></a>

## espectre::MdnsBootstrapResponder



```cpp
#include <runtime/esp_idf/mdns_bootstrap_responder.h>
```



```cpp
class espectre::MdnsBootstrapResponder
```

  

<a id="classespectre_1_1_mdns_bootstrap_responder_1a2b2f05c55613a24569190cb622829f7c"></a>

### `NONCE_HEX_LENGTH`


```cpp
constexpr size_t espectre::MdnsBootstrapResponder::NONCE_HEX_LENGTH = 24U
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1a6c834267d8586769daacedbfc5581981"></a>

### `RESPONSE_TTL_SECONDS`


```cpp
constexpr uint32_t espectre::MdnsBootstrapResponder::RESPONSE_TTL_SECONDS = 10U
```

   


<a id="classespectre_1_1_mdns_bootstrap_responder_1ad7c040408ec79f780ea13978cd007fa3"></a>

### `~MdnsBootstrapResponder`


```cpp
espectre::MdnsBootstrapResponder::~MdnsBootstrapResponder()
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1ab95bbcd82c6192e292f3f77658901262"></a>

### `setup`


```cpp
bool espectre::MdnsBootstrapResponder::setup()
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1ab785ffa19ea97dd9c4d05b5387959e06"></a>

### `update`


```cpp
bool espectre::MdnsBootstrapResponder::update(uint32_t ipv4_address)
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1a05d87c09dc6a1ee0072639e7dc45e573"></a>

### `loop`


```cpp
void espectre::MdnsBootstrapResponder::loop()
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1a6f5cfb8d78d6a2d0ca71ef60b3729478"></a>

### `shutdown`


```cpp
void espectre::MdnsBootstrapResponder::shutdown()
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1a19e169721cd9ef76e08250f05a009619"></a>

### `active`


```cpp
bool espectre::MdnsBootstrapResponder::active() const
```

   

<a id="classespectre_1_1_mdns_bootstrap_responder_1a8e12a6a872421c51e02d49853dc64ea7"></a>

### `ingest_query`


```cpp
void espectre::MdnsBootstrapResponder::ingest_query(const uint8_t *packet, size_t length, size_t interface, uint32_t source_ipv4, uint16_t source_port)
```

   


<a id="classespectre_1_1_mdns_discovery_service"></a>

## espectre::MdnsDiscoveryService



```cpp
#include <runtime/esp_idf/mdns_discovery_service.h>
```



```cpp
class espectre::MdnsDiscoveryService
```

 

Advertises one DNS-SD service on the Wi-Fi station interface.

  

Call [on\_wifi\_connected()](#classespectre_1_1_mdns_discovery_service_1a4756ee87d05459a8a95bb97062088c5b) and [on\_wifi\_disconnected()](#classespectre_1_1_mdns_discovery_service_1a90fffb53d97c2d76c5d1af84e3e5c681) from the firmware's connection callbacks so the service is announced after every reconnect.

 

**Par:** Threading

Call every method from one owner task.

 

<a id="classespectre_1_1_mdns_discovery_service_1a9bca4f5edf7810ea3426c21807da432d"></a>

### `setup`


```cpp
bool espectre::MdnsDiscoveryService::setup(const MdnsDiscoveryServiceConfig &config)
```

 

Replace any previous advertisement and add the configured service.

  

**Returns:** false for an incomplete configuration or when the responder rejects it. Resources acquired before the failure are released.

  

<a id="classespectre_1_1_mdns_discovery_service_1a8a4ead7333e20ee71e19fce8140fe287"></a>

### `update_txt`


```cpp
bool espectre::MdnsDiscoveryService::update_txt(const MdnsTxtRecords &txt_records)
```

 

Replace the TXT records; false before [setup()](#classespectre_1_1_mdns_discovery_service_1a9bca4f5edf7810ea3426c21807da432d) or when the responder rejects them.

   

<a id="classespectre_1_1_mdns_discovery_service_1a4756ee87d05459a8a95bb97062088c5b"></a>

### `on_wifi_connected`


```cpp
void espectre::MdnsDiscoveryService::on_wifi_connected()
```

 

Enable or announce the service on the station interface.

   

<a id="classespectre_1_1_mdns_discovery_service_1a90fffb53d97c2d76c5d1af84e3e5c681"></a>

### `on_wifi_disconnected`


```cpp
void espectre::MdnsDiscoveryService::on_wifi_disconnected()
```

 

Withdraw the station interface from an owned responder.

   

<a id="classespectre_1_1_mdns_discovery_service_1aea78330e76641592ac570c395273a9b4"></a>

### `shutdown`


```cpp
void espectre::MdnsDiscoveryService::shutdown()
```

 

Remove the service and free an owned responder.

  

Safe to repeat.

  

<a id="classespectre_1_1_mdns_discovery_service_1aa8896a8b2d043d58738b340d72dafb58"></a>

### `initialized`


```cpp
bool espectre::MdnsDiscoveryService::initialized() const
```

 

True between a successful [setup()](#classespectre_1_1_mdns_discovery_service_1a9bca4f5edf7810ea3426c21807da432d) and [shutdown()](#classespectre_1_1_mdns_discovery_service_1aea78330e76641592ac570c395273a9b4).

   

<a id="classespectre_1_1_mdns_discovery_service_1a5bc9235099cda7de927791866c0c9547"></a>

### `service_enabled`


```cpp
bool espectre::MdnsDiscoveryService::service_enabled() const
```

 

True while the service is announced on the station interface.

   


<a id="structespectre_1_1_mdns_discovery_service_config"></a>

## espectre::MdnsDiscoveryServiceConfig



```cpp
#include <runtime/esp_idf/mdns_discovery_service.h>
```



```cpp
struct espectre::MdnsDiscoveryServiceConfig
```

 

DNS-SD advertisement for [MdnsDiscoveryService](#classespectre_1_1_mdns_discovery_service).

  

See [DISCOVERY.md](<https://github.com/francescopace/espectre/blob/main/docs/DISCOVERY.md>) for the service type and TXT keys that ESPectre clients expect.

 

<a id="structespectre_1_1_mdns_discovery_service_config_1a1b122f1021e95de3f1668fcb67346cf9"></a>

### `hostname`


```cpp
std::string espectre::MdnsDiscoveryServiceConfig::hostname
```

 

Host label, up to 63 bytes.

  

Required with `OWN_RESPONDER`, optional otherwise.

  

<a id="structespectre_1_1_mdns_discovery_service_config_1a9c632f66f8b84dd2aabf6c5c75d46202"></a>

### `instance_name`


```cpp
std::string espectre::MdnsDiscoveryServiceConfig::instance_name
```

 

Human-readable service instance name.

  

Required.

  

<a id="structespectre_1_1_mdns_discovery_service_config_1a2b72aeb06aa4a27468f88314c1e1b8bd"></a>

### `service_type`


```cpp
std::string espectre::MdnsDiscoveryServiceConfig::service_type
```

 

Service type such as `_espectre`.

  

Required.

  

<a id="structespectre_1_1_mdns_discovery_service_config_1addcc38c93c25c34118c999bca3ec233a"></a>

### `service_protocol`


```cpp
std::string espectre::MdnsDiscoveryServiceConfig::service_protocol
```

 

Transport label such as `_tcp`.

  

Required.

  

<a id="structespectre_1_1_mdns_discovery_service_config_1a872e38c6f5141daa04bfa58db661efa7"></a>

### `port`


```cpp
uint16_t espectre::MdnsDiscoveryServiceConfig::port {0U}
```

 

Advertised port.

  

Required.

  

<a id="structespectre_1_1_mdns_discovery_service_config_1a046eb2615b1c2196f28367e02ebc87e9"></a>

### `txt_records`


```cpp
MdnsTxtRecords espectre::MdnsDiscoveryServiceConfig::txt_records
```

   

<a id="structespectre_1_1_mdns_discovery_service_config_1a43c7aa08b72548d6c707a2acef1b92b6"></a>

### `responder_mode`


```cpp
MdnsResponderMode espectre::MdnsDiscoveryServiceConfig::responder_mode {MdnsResponderMode::OWN_RESPONDER}
```

   


<a id="classespectre_1_1_mqtt_payload_assembler"></a>

## espectre::MqttPayloadAssembler



```cpp
#include <runtime/mqtt_payload_assembler.h>
```



```cpp
class espectre::MqttPayloadAssembler
```

  

<a id="classespectre_1_1_mqtt_payload_assembler_1ae7648d5e3141b89ddd898b43a21527f8"></a>

### `Result`


```cpp
enum class Result
```

   

<a id="classespectre_1_1_mqtt_payload_assembler_1ae7648d5e3141b89ddd898b43a21527f8a2e47f45b8584e07c8ebd4f693d8cfe10"></a>

`INCOMPLETE`

  

<a id="classespectre_1_1_mqtt_payload_assembler_1ae7648d5e3141b89ddd898b43a21527f8a3de44296982e58199afc513a715b12ba"></a>

`COMPLETE`

  

<a id="classespectre_1_1_mqtt_payload_assembler_1ae7648d5e3141b89ddd898b43a21527f8accc0377a8afbf50e7094f5c23a8af223"></a>

`INVALID`

  


<a id="classespectre_1_1_mqtt_payload_assembler_1a92e491dad0240bc4e4885b0400aecc8b"></a>

### `MAX_PAYLOAD_SIZE`


```cpp
constexpr size_t espectre::MqttPayloadAssembler::MAX_PAYLOAD_SIZE = ESPECTRE_COMMAND_MAX_PAYLOAD_SIZE
```

   


<a id="classespectre_1_1_mqtt_payload_assembler_1abe9b537f730d61ed783ba8b7d6b3e1fa"></a>

### `append`


```cpp
Result espectre::MqttPayloadAssembler::append(const char *data, size_t data_len, size_t total_len, size_t offset)
```

   

<a id="classespectre_1_1_mqtt_payload_assembler_1a2be44e2d3cb32c9add9f1c06eb3737ca"></a>

### `payload`


```cpp
std::string_view espectre::MqttPayloadAssembler::payload() const
```

   

<a id="classespectre_1_1_mqtt_payload_assembler_1afa907c956ada6e8b6da584de292088f1"></a>

### `reset`


```cpp
void espectre::MqttPayloadAssembler::reset()
```

   


<a id="structespectre_1_1_mqtt_transport_diagnostics"></a>

## espectre::MqttTransportDiagnostics



```cpp
#include <runtime/mqtt_transport.h>
```



```cpp
struct espectre::MqttTransportDiagnostics
```

  

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a57f23464d94bd6e89343fa67a9c5d891"></a>

### `queue_capacity`


```cpp
size_t espectre::MqttTransportDiagnostics::queue_capacity {0U}
```

   

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a25432ed4113bcf1ba97f39fe73777c9f"></a>

### `outbox_capacity_bytes`


```cpp
size_t espectre::MqttTransportDiagnostics::outbox_capacity_bytes {0U}
```

   

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a1a9aedeafb50f0aeda3b56b3912661a5"></a>

### `queued_publishes`


```cpp
size_t espectre::MqttTransportDiagnostics::queued_publishes {0U}
```

   

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a25bba45d97b4adeb25d61e3773829985"></a>

### `dropped_publishes`


```cpp
uint32_t espectre::MqttTransportDiagnostics::dropped_publishes {0U}
```

   

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a8b6bd7d2dfaac1e23aea8ecf8898eca2"></a>

### `publish_failures`


```cpp
uint32_t espectre::MqttTransportDiagnostics::publish_failures {0U}
```

   

<a id="structespectre_1_1_mqtt_transport_diagnostics_1a6a8233be7136f4a79616df527108b258"></a>

### `reconnects`


```cpp
uint32_t espectre::MqttTransportDiagnostics::reconnects {0U}
```

   


<a id="structespectre_1_1_network_traffic_snapshot"></a>

## espectre::NetworkTrafficSnapshot



```cpp
#include <runtime/esp_idf/network_traffic.h>
```



```cpp
struct espectre::NetworkTrafficSnapshot
```

 

Default Wi-Fi station packet counters, each wrapping modulo 2^32.

  

<a id="structespectre_1_1_network_traffic_snapshot_1a16937fe01691e172c038508a58285216"></a>

### `tx_packets`


```cpp
uint32_t espectre::NetworkTrafficSnapshot::tx_packets
```

 

Packets accepted by the station driver, excluding failed sends.

   

<a id="structespectre_1_1_network_traffic_snapshot_1a3e228990f34b6352a94c654882c86ce1"></a>

### `rx_packets`


```cpp
uint32_t espectre::NetworkTrafficSnapshot::rx_packets
```

 

Packets delivered by the station driver, including later stack drops.

   


<a id="structespectre_1_1_peer_discovery_candidate"></a>

## espectre::PeerDiscoveryCandidate



```cpp
#include <runtime/peer_discovery.h>
```



```cpp
struct espectre::PeerDiscoveryCandidate
```

  

<a id="structespectre_1_1_peer_discovery_candidate_1a2d5778b7ef895ea38a0cfc176e28866e"></a>

### `instance`


```cpp
std::string espectre::PeerDiscoveryCandidate::instance
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1ab89b27af773b55a3928fd8062ee2d86b"></a>

### `hostname`


```cpp
std::string espectre::PeerDiscoveryCandidate::hostname
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a0cb2d0eeab818141ddb73739215e56e8"></a>

### `device_id`


```cpp
std::string espectre::PeerDiscoveryCandidate::device_id
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1abad2df8531fd04b073e07f0cad38ad4a"></a>

### `name`


```cpp
std::string espectre::PeerDiscoveryCandidate::name
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1acbb95beb16745ead3f6f278dbd62d03b"></a>

### `frontend`


```cpp
std::string espectre::PeerDiscoveryCandidate::frontend
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a8a1a8899c7557f2b1e0cdf9684792731"></a>

### `txt_version`


```cpp
std::string espectre::PeerDiscoveryCandidate::txt_version
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a7d354f75bec29ca21378d5258cdf3b94"></a>

### `protocol_version`


```cpp
std::string espectre::PeerDiscoveryCandidate::protocol_version
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1ac354bb8df10122355d7eabf1072be6c0"></a>

### `transport`


```cpp
std::string espectre::PeerDiscoveryCandidate::transport
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a7ed3aee56d18d0e3a23a9f0f25b178cd"></a>

### `path`


```cpp
std::string espectre::PeerDiscoveryCandidate::path
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a1d45f9d1267ac44d120bf0d2c4266f03"></a>

### `firmware`


```cpp
std::string espectre::PeerDiscoveryCandidate::firmware
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a20721debec00cbc2392fbbc87473bd3d"></a>

### `chip`


```cpp
std::string espectre::PeerDiscoveryCandidate::chip
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a571b201c3eefb9ff5df2704436a9cd3f"></a>

### `capabilities`


```cpp
std::string espectre::PeerDiscoveryCandidate::capabilities
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a340e803e81a292c10c0bd5a868abb6d3"></a>

### `port`


```cpp
uint16_t espectre::PeerDiscoveryCandidate::port {0U}
```

   

<a id="structespectre_1_1_peer_discovery_candidate_1a4c4748768d568fcd2417c54669d0f28d"></a>

### `ipv4_addresses`


```cpp
std::vector<uint32_t> espectre::PeerDiscoveryCandidate::ipv4_addresses
```

   


<a id="structespectre_1_1_peer_discovery_snapshot"></a>

## espectre::PeerDiscoverySnapshot



```cpp
#include <runtime/peer_discovery.h>
```



```cpp
struct espectre::PeerDiscoverySnapshot
```

  

<a id="structespectre_1_1_peer_discovery_snapshot_1a473a8af1eaf8d087b009d62ab3f551ba"></a>

### `elapsed_ms`


```cpp
uint32_t espectre::PeerDiscoverySnapshot::elapsed_ms {0U}
```

   

<a id="structespectre_1_1_peer_discovery_snapshot_1a2a6b95456424813636302cdc39624ca2"></a>

### `timed_out`


```cpp
bool espectre::PeerDiscoverySnapshot::timed_out {false}
```

   

<a id="structespectre_1_1_peer_discovery_snapshot_1a79217af1072e21bb9c45b8c3a722f872"></a>

### `truncated`


```cpp
bool espectre::PeerDiscoverySnapshot::truncated {false}
```

   

<a id="structespectre_1_1_peer_discovery_snapshot_1abd303c6912222a2338686f1a0c120b8e"></a>

### `rejected_results`


```cpp
size_t espectre::PeerDiscoverySnapshot::rejected_results {0U}
```

   

<a id="structespectre_1_1_peer_discovery_snapshot_1ae14eb3461048718dbadd944cc5b6bf03"></a>

### `devices`


```cpp
std::vector<PeerDiscoveryCandidate> espectre::PeerDiscoverySnapshot::devices
```

   


<a id="classespectre_1_1_pending_event"></a>

## espectre::PendingEvent



```cpp
#include <runtime/pending_event.h>
```



```cpp
template <typename... Ts>
class espectre::PendingEvent
```

 

Single-slot mailbox carrying an event with an optional payload.

  

[post()](#classespectre_1_1_pending_event_1af79ae9ab56f40807b4bbff6b16bba1e0) records the event and overwrites any unconsumed payload, so events coalesce to the most recent one. [take()](#classespectre_1_1_pending_event_1ad03dda7136be67a473aea263aaa82bae) consumes at most one event per call. Single producer, single consumer.

 

Access is serialized with a lightweight critical section. On ESP-IDF this remains safe from both task and ISR context, including the CSI callback path. On host builds, tests use a regular mutex with the same coalescing semantics.

 

<a id="classespectre_1_1_pending_event_1af79ae9ab56f40807b4bbff6b16bba1e0"></a>

### `post`


```cpp
void espectre::PendingEvent< Ts >::post(Ts... values)
```

   

<a id="classespectre_1_1_pending_event_1ad03dda7136be67a473aea263aaa82bae"></a>

### `take`


```cpp
bool espectre::PendingEvent< Ts >::take(Ts &...out)
```

   

<a id="classespectre_1_1_pending_event_1aed0bf169385a4196d542dedec1ff35f5"></a>

### `clear`


```cpp
void espectre::PendingEvent< Ts >::clear()
```

   


<a id="classespectre_1_1_pending_queue"></a>

## espectre::PendingQueue



```cpp
#include <runtime/pending_queue.h>
```



```cpp
template <typename T, size_t Capacity>
class espectre::PendingQueue
```

 

Fixed-capacity FIFO for callback-to-loop handoff.

  

[post()](#classespectre_1_1_pending_queue_1aa971a069073a9d16138ff75e5ccb2ad4) never allocates or blocks: it returns false when the queue is full. The consumer drains records with [take()](#classespectre_1_1_pending_queue_1aa9b530fa51f2b30d7a1688bf10d32d58) from its owning task. T must remain trivially copyable because ESP-IDF protects the short copy with a critical section that must not run constructors, destructors, or heap allocation.

 

<a id="classespectre_1_1_pending_queue_1aa971a069073a9d16138ff75e5ccb2ad4"></a>

### `post`


```cpp
bool espectre::PendingQueue< T, Capacity >::post(const T &value)
```

   

<a id="classespectre_1_1_pending_queue_1a7d3f4c1a69924ab5eb5bfec2e0c8baca"></a>

### `post_overwrite_oldest`


```cpp
bool espectre::PendingQueue< T, Capacity >::post_overwrite_oldest(const T &value)
```

 

Append a record, discarding the oldest record when the queue is full.

  

**Returns:** true when no record was discarded.

  

<a id="classespectre_1_1_pending_queue_1aa9b530fa51f2b30d7a1688bf10d32d58"></a>

### `take`


```cpp
bool espectre::PendingQueue< T, Capacity >::take(T &value)
```

   

<a id="classespectre_1_1_pending_queue_1a38633383c3a20b1b53f82d8890e17525"></a>

### `clear`


```cpp
void espectre::PendingQueue< T, Capacity >::clear()
```

   

<a id="classespectre_1_1_pending_queue_1adf95f881daf5bbf3376b5f34c5199276"></a>

### `size`


```cpp
size_t espectre::PendingQueue< T, Capacity >::size() const
```

   


<a id="structespectre_1_1_raw_csi_http_frame_prefix"></a>

## espectre::RawCsiHttpFramePrefix



```cpp
#include <runtime/raw_csi.h>
```



```cpp
struct espectre::RawCsiHttpFramePrefix
```

  

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1aff63ce4fc7a4e08371da97d54cb746c5"></a>

### `magic`


```cpp
uint32_t espectre::RawCsiHttpFramePrefix::magic
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1ac4f5786b99681c4cad962c0f97dfafbf"></a>

### `version`


```cpp
uint8_t espectre::RawCsiHttpFramePrefix::version
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1a16b90d015a0fdb3b5fbc67ea5c925480"></a>

### `record_version`


```cpp
uint8_t espectre::RawCsiHttpFramePrefix::record_version
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1a4310fd9517fadbec9303fe3305c0a36d"></a>

### `header_len`


```cpp
uint16_t espectre::RawCsiHttpFramePrefix::header_len
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1a4519c8824b89b80a0fe4236319e2f840"></a>

### `session_id`


```cpp
uint8_t espectre::RawCsiHttpFramePrefix::session_id[ESPECTRE_RAW_CSI_SESSION_ID_BYTES][ESPECTRE_RAW_CSI_SESSION_ID_BYTES]
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1a1aab45e916774b1d37733a135b6ad862"></a>

### `stream_sequence`


```cpp
uint64_t espectre::RawCsiHttpFramePrefix::stream_sequence
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1ae2ce8f1c1b320fd785fa96cb84902e91"></a>

### `record_len`


```cpp
uint16_t espectre::RawCsiHttpFramePrefix::record_len
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1a1afdf43be2cc516e3a13302a17fa1d9e"></a>

### `flags`


```cpp
uint16_t espectre::RawCsiHttpFramePrefix::flags
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1aff647ce0eab14075108180bf3dabd939"></a>

### `fresh_record_total`


```cpp
uint64_t espectre::RawCsiHttpFramePrefix::fresh_record_total
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1abea7ebe4270089f9268e923847b02bf9"></a>

### `raw_drop_total`


```cpp
uint64_t espectre::RawCsiHttpFramePrefix::raw_drop_total
```

   

<a id="structespectre_1_1_raw_csi_http_frame_prefix_1ade022647201de886fa85623153e474fd"></a>

### `raw_send_backpressure_total`


```cpp
uint64_t espectre::RawCsiHttpFramePrefix::raw_send_backpressure_total
```

   


<a id="structespectre_1_1_raw_csi_packet_view"></a>

## espectre::RawCsiPacketView



```cpp
#include <runtime/raw_csi.h>
```



```cpp
struct espectre::RawCsiPacketView
```

 

Callback-scoped view of one normalized raw CSI packet.

  

The struct and the bytes addressed by [`csi`](#structespectre_1_1_raw_csi_packet_view_1a518f5bc92cc9b0b4d2d8ac60cda60cb1) are valid only for the duration of the capture callback. Copy them before returning if another task needs the sample. The built-in capture pipeline supplies HT20\_CSI\_LEN bytes (64 complex subcarriers) after LLTF, HT, or VHT normalization. This normalized capture bound is independent of RAW\_CSI\_MAX\_PAYLOAD\_BYTES, the record-format limit.

 

<a id="structespectre_1_1_raw_csi_packet_view_1a518f5bc92cc9b0b4d2d8ac60cda60cb1"></a>

### `csi`


```cpp
const int8_t* espectre::RawCsiPacketView::csi {nullptr}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a595517f6c85eedfe92c2bd0f3b27fdef"></a>

### `csi_len`


```cpp
uint16_t espectre::RawCsiPacketView::csi_len {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1ab750df6d53c73e68797581458488b832"></a>

### `captured_at_us`


```cpp
uint64_t espectre::RawCsiPacketView::captured_at_us {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a0961514d44a91e8922fb371098117fd2"></a>

### `wifi_rx_ts_us`


```cpp
uint32_t espectre::RawCsiPacketView::wifi_rx_ts_us {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1af3a7348adcbc7adff1ea8f07f9f75c75"></a>

### `wifi_rx_start_ts_ns`


```cpp
uint64_t espectre::RawCsiPacketView::wifi_rx_start_ts_ns {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a4550d70cf63fd67ecaaba4a96f7532aa"></a>

### `record_flags`


```cpp
uint8_t espectre::RawCsiPacketView::record_flags {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1af2ded4c9345b6b13f1136a1cc3d34f22"></a>

### `channel`


```cpp
uint8_t espectre::RawCsiPacketView::channel {0U}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a6b31d1c641df6c888905d3d1d2a15bc4"></a>

### `rssi_dbm`


```cpp
int8_t espectre::RawCsiPacketView::rssi_dbm {0}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a1c4362c1daa8093dccf22a2f20ef5529"></a>

### `noise_floor_dbm`


```cpp
int8_t espectre::RawCsiPacketView::noise_floor_dbm {0}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a66bf7a3613a973d694bed6c12e3b6948"></a>

### `phy_mode`


```cpp
RawCsiPhyMode espectre::RawCsiPacketView::phy_mode {RawCsiPhyMode::UNKNOWN}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a94a64374b6cedf012a2a0dfc63edcc94"></a>

### `ltf_type`


```cpp
RawCsiLtfType espectre::RawCsiPacketView::ltf_type {RawCsiLtfType::UNKNOWN}
```

   

<a id="structespectre_1_1_raw_csi_packet_view_1a1df4e8233c12a8488b33f692f28ab34f"></a>

### `channel_width`


```cpp
RawCsiChannelWidth espectre::RawCsiPacketView::channel_width {RawCsiChannelWidth::UNKNOWN}
```

   


<a id="structespectre_1_1_raw_csi_record_header_v8"></a>

## espectre::RawCsiRecordHeaderV8



```cpp
#include <runtime/csi_raw_record.h>
```



```cpp
struct espectre::RawCsiRecordHeaderV8
```

 

Transport-neutral raw CSI record emitted by Direct raw collection.

  

<a id="structespectre_1_1_raw_csi_record_header_v8_1a2be7e3fe64a7ad696429405bc01eb145"></a>

### `magic`


```cpp
uint16_t espectre::RawCsiRecordHeaderV8::magic
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a63bfbc147266f17ce8e0ca11fbd4eecc"></a>

### `version`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::version
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a9600a4ab094c962b3551e1886523e9f8"></a>

### `header_len`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::header_len
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a5f3a5c11eabed7999a830d818ec4904e"></a>

### `chip`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::chip
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a7e2b9459ba67ad46bb4a93384b35beff"></a>

### `flags`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::flags
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1aef74dacf16ba25a8ce3bde3d46b6979b"></a>

### `seq_num`


```cpp
uint32_t espectre::RawCsiRecordHeaderV8::seq_num
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1acd10191805ae0cc24b2cf50ce5b0ec86"></a>

### `num_subcarriers`


```cpp
uint16_t espectre::RawCsiRecordHeaderV8::num_subcarriers
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a023ae711e0a5af78d436ee6927e72a93"></a>

### `csi_len_bytes`


```cpp
uint16_t espectre::RawCsiRecordHeaderV8::csi_len_bytes
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1ad9da0926689f413708e83d94e29aa3e9"></a>

### `device_id`


```cpp
uint64_t espectre::RawCsiRecordHeaderV8::device_id
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a2309743c2ab9d1ec26e9e3f7ff4c8881"></a>

### `device_ticks_us`


```cpp
uint64_t espectre::RawCsiRecordHeaderV8::device_ticks_us
```

 

Monotonic device time captured with the CSI sample.

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a79e1bfe6b2254f5be7cf4f4a40020877"></a>

### `wifi_rx_ts_us`


```cpp
uint32_t espectre::RawCsiRecordHeaderV8::wifi_rx_ts_us
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1acf55ce899c8d2cf518a15b4c0f59b705"></a>

### `wifi_rx_start_ts_ns`


```cpp
uint64_t espectre::RawCsiRecordHeaderV8::wifi_rx_start_ts_ns
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1acc3237a83d4782265ec7256b0823e3f8"></a>

### `channel`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::channel
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1ad954b162911a918cff26d75ef6e4d07d"></a>

### `rssi_dbm`


```cpp
int8_t espectre::RawCsiRecordHeaderV8::rssi_dbm
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a95e7928f62ae72588421ba826bd080cc"></a>

### `noise_floor_dbm`


```cpp
int8_t espectre::RawCsiRecordHeaderV8::noise_floor_dbm
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a2a0ceacb775707eb740176834364b33a"></a>

### `transport_backpressure_total`


```cpp
uint64_t espectre::RawCsiRecordHeaderV8::transport_backpressure_total
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a9bea32173dff7bc07a0537cf8f41acf9"></a>

### `fresh_record_total`


```cpp
uint32_t espectre::RawCsiRecordHeaderV8::fresh_record_total
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a994a6ea793326afe12c8ecfde222a7b3"></a>

### `request_accepted_total`


```cpp
uint32_t espectre::RawCsiRecordHeaderV8::request_accepted_total
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1abd87cbb6fdffc6f3e26a0e9ed12725ad"></a>

### `phy_mode`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::phy_mode
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a855dfc7a80986911adf5c337c2dea3e1"></a>

### `ltf_type`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::ltf_type
```

   

<a id="structespectre_1_1_raw_csi_record_header_v8_1a1442437f89c541d25b34a6539d934916"></a>

### `channel_width`


```cpp
uint8_t espectre::RawCsiRecordHeaderV8::channel_width
```

   


<a id="structespectre_1_1_raw_csi_session_config"></a>

## espectre::RawCsiSessionConfig



```cpp
#include <runtime/raw_csi.h>
```



```cpp
struct espectre::RawCsiSessionConfig
```

  

<a id="structespectre_1_1_raw_csi_session_config_1a64034c747a85e38ec0b3e3393d87610d"></a>

### `session_id`


```cpp
uint8_t espectre::RawCsiSessionConfig::session_id[ESPECTRE_RAW_CSI_SESSION_ID_BYTES][ESPECTRE_RAW_CSI_SESSION_ID_BYTES] {}
```

   

<a id="structespectre_1_1_raw_csi_session_config_1a330ce1101930b0bc35e51a6dddfbeb89"></a>

### `device_id`


```cpp
uint64_t espectre::RawCsiSessionConfig::device_id {0U}
```

   

<a id="structespectre_1_1_raw_csi_session_config_1a3b93ff18005d0b24237d29635cb7184d"></a>

### `chip`


```cpp
RawCsiChipType espectre::RawCsiSessionConfig::chip {RawCsiChipType::UNKNOWN}
```

   


<a id="classespectre_1_1_raw_csi_session_controller"></a>

## espectre::RawCsiSessionController



```cpp
#include <runtime/esp_idf/raw_csi_session_controller.h>
```



```cpp
class espectre::RawCsiSessionController
```

  

<a id="classespectre_1_1_raw_csi_session_controller_1ae9cf91a097cfb99ff2017f48b0175201"></a>

### `StoppedCallback`


```cpp
using espectre::RawCsiSessionController::StoppedCallback = std::function<void(RawCsiStopReason reason)>
```

   

<a id="classespectre_1_1_raw_csi_session_controller_1abd15e43bf15014bdd32b80449dd791cb"></a>

### `StartedCallback`


```cpp
using espectre::RawCsiSessionController::StartedCallback = std::function<void()>
```

   


<a id="classespectre_1_1_raw_csi_session_controller_1aad3fc3c7ed2079d4945e2a61054e42dc"></a>

### `configure`


```cpp
void espectre::RawCsiSessionController::configure(IDirectHttpService *service, RuntimeFrontendController *runtime, uint64_t device_id, std::string chip, StoppedCallback stopped_callback={}, StartedCallback started_callback={})
```

   

<a id="classespectre_1_1_raw_csi_session_controller_1a1e7634c8a365a87f71f760acbc675f37"></a>

### `begin`


```cpp
bool espectre::RawCsiSessionController::begin(std::string *message=nullptr)
```

   

<a id="classespectre_1_1_raw_csi_session_controller_1a52e62ad8344a6e0ed58060f483fa0191"></a>

### `ensure_runtime_consistency`


```cpp
void espectre::RawCsiSessionController::ensure_runtime_consistency()
```

   

<a id="classespectre_1_1_raw_csi_session_controller_1aedcad49435d24cd25e14fff9ee1b79ba"></a>

### `shutdown`


```cpp
void espectre::RawCsiSessionController::shutdown(RawCsiStopReason reason=RawCsiStopReason::SHUTDOWN)
```

   

<a id="classespectre_1_1_raw_csi_session_controller_1a520a1ab907c02b461de790cd6342881e"></a>

### `active`


```cpp
bool espectre::RawCsiSessionController::active() const
```

   


<a id="structespectre_1_1_raw_csi_session_diagnostics"></a>

## espectre::RawCsiSessionDiagnostics



```cpp
#include <runtime/raw_csi.h>
```



```cpp
struct espectre::RawCsiSessionDiagnostics
```

  

<a id="structespectre_1_1_raw_csi_session_diagnostics_1a9d6559b9af3fe917d1d706cdfa9908fd"></a>

### `active`


```cpp
bool espectre::RawCsiSessionDiagnostics::active {false}
```

   

<a id="structespectre_1_1_raw_csi_session_diagnostics_1a00dfeb74a7853d881d5daf28fe46d19a"></a>

### `binary_bound`


```cpp
bool espectre::RawCsiSessionDiagnostics::binary_bound {false}
```

   

<a id="structespectre_1_1_raw_csi_session_diagnostics_1af028b03fa5574f470cb775528e731902"></a>

### `raw_drop_total`


```cpp
uint64_t espectre::RawCsiSessionDiagnostics::raw_drop_total {0U}
```

   

<a id="structespectre_1_1_raw_csi_session_diagnostics_1a949a317f2743710686258f4315cf8250"></a>

### `raw_send_backpressure_total`


```cpp
uint64_t espectre::RawCsiSessionDiagnostics::raw_send_backpressure_total {0U}
```

   

<a id="structespectre_1_1_raw_csi_session_diagnostics_1a4c48a663c7d565f0b9fe478e218b76a3"></a>

### `fresh_record_total`


```cpp
uint64_t espectre::RawCsiSessionDiagnostics::fresh_record_total {0U}
```

   

<a id="structespectre_1_1_raw_csi_session_diagnostics_1af7f644fe02ab9bea2e3ba52d33a5bc59"></a>

### `stream_sequence`


```cpp
uint64_t espectre::RawCsiSessionDiagnostics::stream_sequence {0U}
```

   


<a id="structespectre_1_1_runtime_capabilities"></a>

## espectre::RuntimeCapabilities



```cpp
#include <runtime/runtime_capabilities.h>
```



```cpp
struct espectre::RuntimeCapabilities
```

 

What a runtime actually offers its frontend.

  

Every flag defaults to false, so a runtime declares each capability explicitly. Protocol clients read these flags to learn which controls exist.

 

[`supports_live_telemetry`](#structespectre_1_1_runtime_capabilities_1a7c29851c92d3dce3570e44946c055948) describes the runtime side of the surface: whether it drives the live-telemetry callback at all.

 

<a id="structespectre_1_1_runtime_capabilities_1a73c517a443cb659c29fe03926926d7b6"></a>

### `supports_runtime_threshold_updates`


```cpp
bool espectre::RuntimeCapabilities::supports_runtime_threshold_updates {false}
```

 

`set_threshold()` is honored.

   

<a id="structespectre_1_1_runtime_capabilities_1a84d3b5bb447e02b9026bdb81f69db236"></a>

### `supports_runtime_motion_hits_updates`


```cpp
bool espectre::RuntimeCapabilities::supports_runtime_motion_hits_updates {false}
```

 

`set_motion_hits()` is honored; otherwise the controller refuses it.

   

<a id="structespectre_1_1_runtime_capabilities_1a8a74863f469d46c8a8441ef4e58c6b66"></a>

### `supports_runtime_detector_selection`


```cpp
bool espectre::RuntimeCapabilities::supports_runtime_detector_selection {false}
```

 

`set_detection_algorithm()` is honored.

  

Driven by [`RuntimeConfig::runtime_detector_selection_enabled`](#structespectre_1_1_runtime_config_1adb8b5784fab9a57ecc354c281b3cd799), since switching detectors also means persisting and restoring the choice.

  

<a id="structespectre_1_1_runtime_capabilities_1a1457a33557663be153d4472ac9192b20"></a>

### `supports_manual_recalibration`


```cpp
bool espectre::RuntimeCapabilities::supports_manual_recalibration {false}
```

 

`trigger_recalibration()` is honored; otherwise the controller refuses it.

   

<a id="structespectre_1_1_runtime_capabilities_1a7c29851c92d3dce3570e44946c055948"></a>

### `supports_live_telemetry`


```cpp
bool espectre::RuntimeCapabilities::supports_live_telemetry {false}
```

 

The runtime drives [`IRuntimeListener::on_live_telemetry()`](#classespectre_1_1_i_runtime_listener_1a2473b19c1324d186b11ba596000acde9) at all.

  

Use it for high-rate outputs such as a live movement score. Transport adapters decide how to forward live sensing.

  

<a id="structespectre_1_1_runtime_capabilities_1ab38fbc94f33d1f3dace27cca8e48f0c3"></a>

### `supports_extended_diagnostics`


```cpp
bool espectre::RuntimeCapabilities::supports_extended_diagnostics {false}
```

 

The runtime reports the extended fields used by diagnostics payloads.

   

<a id="structespectre_1_1_runtime_capabilities_1a9cb79d6a0f22efbcfecabc4d4747fedb"></a>

### `supports_traffic_control`


```cpp
bool espectre::RuntimeCapabilities::supports_traffic_control {false}
```

 

The runtime owns CSI traffic generation and can be asked to retune it.

   

<a id="structespectre_1_1_runtime_capabilities_1ae02edf210122c8ba729173b427c0dec2"></a>

### `supports_raw_csi`


```cpp
bool espectre::RuntimeCapabilities::supports_raw_csi {false}
```

 

The runtime can temporarily bypass sensing and expose normalized raw CSI.

   


<a id="structespectre_1_1_runtime_config"></a>

## espectre::RuntimeConfig



```cpp
#include <runtime/runtime_config.h>
```



```cpp
struct espectre::RuntimeConfig
```

 

Everything the runtime needs to know before `setup()`.

  

Every member is default-constructed to a supported production value, so [`RuntimeConfig{}`](#structespectre_1_1_runtime_config) is a working configuration for Lightweight Detection on internally generated traffic. Override only what your product changes.

 

Ranges are declared in [`runtime_sensing_schema.h`](#runtime__sensing__schema_8h) as `RUNTIME_<FIELD>_MIN` / `_MAX` / `_DEFAULT`, and the free functions in [`runtime_config_utils.h`](#runtime__config__utils_8h) validate against them. On ESP-IDF you can build this from menuconfig with [`make_runtime_sensing_config_from_kconfig()`](#namespaceespectre_1ab070877204ffb133b519d0b163420df6) instead of assigning fields by hand.

 

The config is copied into the runtime at `setup()`. Later edits to your own copy have no effect; use the [`RuntimeFrontendController`](#classespectre_1_1_runtime_frontend_controller) setters instead.

 

<a id="structespectre_1_1_runtime_config_1a8802e0c9228e203ce428e689604eed0a"></a>

### `wifi_band_policy`


```cpp
WifiBandPolicy espectre::RuntimeConfig::wifi_band_policy {WifiBandPolicy::AUTO}
```

 

Band available to the station while the runtime keeps the PHY at HT20.

  

The default, `AUTO`, uses every band the radio has, which means 2.4 GHz on single-band targets. `BAND_5G` requires dual-band silicon.

  

<a id="structespectre_1_1_runtime_config_1a11e3dabb6a3b11810eecd2cf0e082b35"></a>

### `csi_capture_policy`


```cpp
CsiCapturePolicy espectre::RuntimeConfig::csi_capture_policy {CsiCapturePolicy::AUTO}
```

 

Build-time CSI profile; AUTO resolves from chip, band, and the active traffic source.

  

No runtime setter.

  

<a id="structespectre_1_1_runtime_config_1a3d14cc007fe6107bd81c6c6da176327a"></a>

### `detection_algorithm`


```cpp
DetectionAlgorithm espectre::RuntimeConfig::detection_algorithm {DetectionAlgorithm::LIGHTWEIGHT}
```

 

Detection profile to run.

  

Lightweight self-calibrates; High Accuracy uses trained weights.

  

<a id="structespectre_1_1_runtime_config_1a4eaac5c4cc10b6d34f679ec1cb152671"></a>

### `threshold`


```cpp
float espectre::RuntimeConfig::threshold {RUNTIME_THRESHOLD_DEFAULT}
```

 

Motion probability threshold, on the same 0..1 scale as [`RuntimeSnapshot::movement_metric`](#structespectre_1_1_runtime_snapshot_1a6844aeb15178c5088d4564c5719361c7).

  

Lightweight Detection overwrites this during startup calibration, so the configured value only governs the pre-calibration window. High-Accuracy Detection keeps it as given.

  

<a id="structespectre_1_1_runtime_config_1af157afffd481dcc5a8eb9e2f64d281d0"></a>

### `window_size_ms`


```cpp
uint32_t espectre::RuntimeConfig::window_size_ms {RUNTIME_WINDOW_SIZE_MS_DEFAULT}
```

 

Detector window duration in milliseconds (1000..2000).

  

Runtimes resolve the duration to a fixed temporal grid from [`csi_target_pps`](#structespectre_1_1_runtime_config_1a0dbde3a8ad2fed884033fe0855153461); live arrival jitter never resizes the detector.

  

<a id="structespectre_1_1_runtime_config_1adb8b5784fab9a57ecc354c281b3cd799"></a>

### `runtime_detector_selection_enabled`


```cpp
bool espectre::RuntimeConfig::runtime_detector_selection_enabled {false}
```

 

Advertise runtime detector switching.

  

When true the runtime restores the persisted detector choice at `setup()` and sets [`RuntimeCapabilities::supports_runtime_detector_selection`](#structespectre_1_1_runtime_capabilities_1a8a74863f469d46c8a8441ef4e58c6b66). A persisted detector that differs from [`detection_algorithm`](#structespectre_1_1_runtime_config_1a3d14cc007fe6107bd81c6c6da176327a) also replaces [`threshold`](#structespectre_1_1_runtime_config_1a4eaac5c4cc10b6d34f679ec1cb152671) with that detector's default.

  

<a id="structespectre_1_1_runtime_config_1a0dbde3a8ad2fed884033fe0855153461"></a>

### `csi_target_pps`


```cpp
uint32_t espectre::RuntimeConfig::csi_target_pps {RUNTIME_CSI_TARGET_PPS_DEFAULT}
```

 

Target CSI sensing cadence, in packets per second.

  

This value is always positive and defines detector temporal slots as well as the target for managed traffic. [`traffic_generator_mode`](#structespectre_1_1_runtime_config_1aa7bf6c82465a049cfa6ca6fb3da7d134) alone selects who supplies traffic. The detector coefficients are fitted at 100 pps; see [ALGORITHMS.md](<https://github.com/francescopace/espectre/blob/main/docs/ALGORITHMS.md>) before moving far from it.

  

<a id="structespectre_1_1_runtime_config_1aa7bf6c82465a049cfa6ca6fb3da7d134"></a>

### `traffic_generator_mode`


```cpp
TrafficGeneratorMode espectre::RuntimeConfig::traffic_generator_mode {TrafficGeneratorMode::PING}
```

 

How the device gets CSI-bearing traffic: one of the internal generator modes, or `EXTERNAL` to listen for another host.

   

<a id="structespectre_1_1_runtime_config_1a3724c06056cbaa57995ec053a955403f"></a>

### `traffic_generator_target_ip`


```cpp
std::string espectre::RuntimeConfig::traffic_generator_target_ip
```

 

Unicast IPv4 destination for internal IP traffic; empty uses the Wi-Fi gateway.

  

Ignored by `wifi_raw`.

  

<a id="structespectre_1_1_runtime_config_1a351c09d60c62894a66d78bbcff516ba4"></a>

### `csi_traffic_udp_port`


```cpp
uint16_t espectre::RuntimeConfig::csi_traffic_udp_port {RUNTIME_CSI_TRAFFIC_UDP_PORT_DEFAULT}
```

 

UDP port used by the external CSI traffic mode.

   

<a id="structespectre_1_1_runtime_config_1a030014458960bd11b3848bba7f770d8e"></a>

### `csi_traffic_multicast_group`


```cpp
std::string espectre::RuntimeConfig::csi_traffic_multicast_group {RUNTIME_CSI_TRAFFIC_MULTICAST_GROUP_DEFAULT}
```

 

IPv4 multicast group joined by the UDP listener in `external`.

  

Empty disables the IGMP join. Unicast to the device IP still works.

  

<a id="structespectre_1_1_runtime_config_1a9ed14bbc7a7bbef728b2db39fc484553"></a>

### `device_id`


```cpp
uint64_t espectre::RuntimeConfig::device_id {0U}
```

 

Stable device identity used by the ESPectre Protocol and CSI streaming.

  

Assign [`derive_runtime_device_id()`](#namespaceespectre_1a34031a60d78bbb6306047b3540b4f905) to use the SDK's stable pseudonym from the Wi-Fi MAC. Zero is an unresolved sentinel; the controller does not replace it automatically.

  

<a id="structespectre_1_1_runtime_config_1ac210376be06dd066fcf78547733ee8af"></a>

### `evaluation_interval_ms`


```cpp
uint32_t espectre::RuntimeConfig::evaluation_interval_ms {RUNTIME_EVALUATION_INTERVAL_MS_DEFAULT}
```

 

Detector evaluation cadence in milliseconds.

   

<a id="structespectre_1_1_runtime_config_1a9ffb875a52b525060dc7996787d6fd3a"></a>

### `motion_on_hits`


```cpp
uint8_t espectre::RuntimeConfig::motion_on_hits {RUNTIME_MOTION_ON_HITS_DEFAULT}
```

 

Consecutive above-threshold evaluations before reporting motion (1..20).

   

<a id="structespectre_1_1_runtime_config_1a53ebfb156a2125c61fa675788784c301"></a>

### `motion_off_hits`


```cpp
uint8_t espectre::RuntimeConfig::motion_off_hits {RUNTIME_MOTION_OFF_HITS_DEFAULT}
```

 

Consecutive below-threshold evaluations before clearing motion (1..20).

   

<a id="structespectre_1_1_runtime_config_1a6b833d1269bc157a791dc100241087b7"></a>

### `lowpass_enabled`


```cpp
bool espectre::RuntimeConfig::lowpass_enabled {RUNTIME_LOWPASS_ENABLED_DEFAULT}
```

 

Enable the low-pass filter on the turbulence stream.

  

Off by default.

  

<a id="structespectre_1_1_runtime_config_1aa6a480f526a935faef46ee91c286ee5d"></a>

### `lowpass_cutoff`


```cpp
float espectre::RuntimeConfig::lowpass_cutoff {RUNTIME_LOWPASS_CUTOFF_DEFAULT}
```

 

Low-pass cutoff in Hz (5.0..20.0).

  

Ignored unless [`lowpass_enabled`](#structespectre_1_1_runtime_config_1a6b833d1269bc157a791dc100241087b7).

  

<a id="structespectre_1_1_runtime_config_1a36be148ebec6f2e07240cbd1c39e1ccb"></a>

### `hampel_enabled`


```cpp
bool espectre::RuntimeConfig::hampel_enabled {RUNTIME_HAMPEL_ENABLED_DEFAULT}
```

 

Enable Hampel outlier rejection on the turbulence stream.

  

On by default.

  

<a id="structespectre_1_1_runtime_config_1a034ce1a3a20c5509049fff9ba5e76c54"></a>

### `hampel_window`


```cpp
uint8_t espectre::RuntimeConfig::hampel_window {RUNTIME_HAMPEL_WINDOW_DEFAULT}
```

 

Hampel window in samples (3..11).

  

Ignored unless [`hampel_enabled`](#structespectre_1_1_runtime_config_1a36be148ebec6f2e07240cbd1c39e1ccb).

  

<a id="structespectre_1_1_runtime_config_1a36d865a656d4cd1856c709a340d3c63b"></a>

### `hampel_threshold`


```cpp
float espectre::RuntimeConfig::hampel_threshold {RUNTIME_HAMPEL_THRESHOLD_DEFAULT}
```

 

Hampel MAD multiplier (1.0..10.0).

  

Ignored unless [`hampel_enabled`](#structespectre_1_1_runtime_config_1a36be148ebec6f2e07240cbd1c39e1ccb).

  

<a id="structespectre_1_1_runtime_config_1a6e59c22554445734d3245bc0511757a4"></a>

### `wifi_scan_results_managed_externally`


```cpp
bool espectre::RuntimeConfig::wifi_scan_results_managed_externally {false}
```

 

The Wi-Fi stack consumes scan results, including CSI recovery scans.

  

Enable for stacks with autonomous scans, such as ESPHome. The runtime must not clear their driver result list, even after its own scan completes. Otherwise, independent scanners must wait until the SDK releases its scanner reservation after cleanup.

  

<a id="structespectre_1_1_runtime_config_1a246097b5af94d246329a089da27dd6f9"></a>

### `persist_runtime_overrides`


```cpp
bool espectre::RuntimeConfig::persist_runtime_overrides {true}
```

 

Remember runtime control changes across reboots.

  

When true, `setup()` restores the traffic generator mode and motion hits saved by earlier control calls, plus the detector when [`runtime_detector_selection_enabled`](#structespectre_1_1_runtime_config_1adb8b5784fab9a57ecc354c281b3cd799) is set, and those calls save their new values. Set it to false when your firmware owns configuration, for example from YAML or a cloud service: this config is then the only source of truth, and the runtime neither reads nor writes saved controls.

  


<a id="structespectre_1_1_runtime_control_update"></a>

## espectre::RuntimeControlUpdate



```cpp
#include <runtime/runtime_config_utils.h>
```



```cpp
struct espectre::RuntimeControlUpdate
```

 

A partial change to the live sensing controls.

  

Each `has_*` flag marks a field to change; the others keep their value. Validate the whole change before applying any field, so a request either applies completely or not at all.

 

<a id="structespectre_1_1_runtime_control_update_1a99a6c6a22ce08c61f57d090228475024"></a>

### `has_detection_algorithm`


```cpp
bool espectre::RuntimeControlUpdate::has_detection_algorithm {false}
```

   

<a id="structespectre_1_1_runtime_control_update_1a118cce94b78b4c30d0c72bcbe4524986"></a>

### `detection_algorithm`


```cpp
DetectionAlgorithm espectre::RuntimeControlUpdate::detection_algorithm {DetectionAlgorithm::LIGHTWEIGHT}
```

   

<a id="structespectre_1_1_runtime_control_update_1ae96d103c53d6cdd99e27eb351c36f51c"></a>

### `has_threshold`


```cpp
bool espectre::RuntimeControlUpdate::has_threshold {false}
```

   

<a id="structespectre_1_1_runtime_control_update_1af89fd90e55cdc213236631869ec0b310"></a>

### `threshold`


```cpp
float espectre::RuntimeControlUpdate::threshold {0.0f}
```

   

<a id="structespectre_1_1_runtime_control_update_1a7da412ee017c652b4dac4c53efc5e061"></a>

### `has_motion_hits`


```cpp
bool espectre::RuntimeControlUpdate::has_motion_hits {false}
```

   

<a id="structespectre_1_1_runtime_control_update_1a36c768e930c661ef52b0d94976b51e4f"></a>

### `motion_on_hits`


```cpp
uint8_t espectre::RuntimeControlUpdate::motion_on_hits {0U}
```

   

<a id="structespectre_1_1_runtime_control_update_1aa5a28dad01990c44ff99fd2aeb55aec0"></a>

### `motion_off_hits`


```cpp
uint8_t espectre::RuntimeControlUpdate::motion_off_hits {0U}
```

   

<a id="structespectre_1_1_runtime_control_update_1a2528ec9b8c78a5e81bc60afd1e5c9bf0"></a>

### `has_traffic_generator_mode`


```cpp
bool espectre::RuntimeControlUpdate::has_traffic_generator_mode {false}
```

   

<a id="structespectre_1_1_runtime_control_update_1a84401f569cf5386dac7115e7ea9e9cad"></a>

### `traffic_generator_mode`


```cpp
TrafficGeneratorMode espectre::RuntimeControlUpdate::traffic_generator_mode {TrafficGeneratorMode::PING}
```

   


<a id="structespectre_1_1_runtime_diagnostics_sample"></a>

## espectre::RuntimeDiagnosticsSample



```cpp
#include <runtime/runtime_diagnostics.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSample
```

 

Rate and link diagnostics derived from cumulative runtime counters.

  

Produced by the runtime-owned [`RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler). The rates are what the runtime's monotonic totals moved by between two periodic sensing updates, and every frontend reads the same latest sample.

 

A zero rate means the counter did not move over the interval, and the first sample after [`RuntimeDiagnosticsSampler::reset()`](#classespectre_1_1_runtime_diagnostics_sampler_1a255a7d6a981df30ffdce72d1b89495df) reports zero rates because it establishes the baseline. The link fields are carried through either way.

 

<a id="structespectre_1_1_runtime_diagnostics_sample_1a04f14702fc3d3c2ada6eaf0973d362db"></a>

### `generator_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::generator_pps {0.0f}
```

 

Successful internal generator sends per second; zero in external mode.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a3ff1ff0161be346bff367985d0721824"></a>

### `traffic_tx_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::traffic_tx_pps {0.0f}
```

 

Station network packets per second accepted by the driver.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a237c806beb2a88d33bb76877d6a07ce2"></a>

### `traffic_rx_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::traffic_rx_pps {0.0f}
```

 

Station network packets per second delivered by the driver.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a43ac7ee8b3dfdf6f3274d4e81dafcd16"></a>

### `csi_callback_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_callback_pps {0.0f}
```

 

Raw CSI callbacks per second, before any capture-level validation.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a125500562a6bc3ad824cf696cae8c9a4"></a>

### `csi_accepted_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_accepted_pps {0.0f}
```

 

CSI packets per second accepted by capture validation.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a701ee4b43a9b5f7a09a2f75a717e51ca"></a>

### `csi_admitted_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_admitted_pps {0.0f}
```

 

CSI packets per second admitted to the detector's temporal grid.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a76312bc2c4556eaf7bfa17a577d38dc9"></a>

### `csi_filtered_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_filtered_pps {0.0f}
```

 

CSI packets per second rejected by capture-level validation.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1aabbfd5e2dba6cd01ee3063247f02e314"></a>

### `csi_hw_error_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_hw_error_pps {0.0f}
```

 

Hardware-quality rejections per second, with one reason per rejected callback.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a4ef885c63bffa884bea39ae6a52785af"></a>

### `csi_pending_frame_drop_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_pending_frame_drop_pps {0.0f}
```

 

Valid CSI callbacks per second dropped because the pending queue was full.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a3027d157b651e64d5b50e08b0a88357c"></a>

### `csi_missing_slots_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_missing_slots_pps {0.0f}
```

 

Missing detector slots per second.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1aba879cef28a0cc1d02aa752f3bb09819"></a>

### `csi_excess_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_excess_pps {0.0f}
```

 

Same-slot excess drops per second.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a205207163e1676ca349806e25ca91107"></a>

### `csi_stale_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_stale_pps {0.0f}
```

 

Stale temporal drops per second.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a4351f6e1c87593f9c38fd5ae30657141"></a>

### `csi_out_of_order_pps`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_out_of_order_pps {0.0f}
```

 

Out-of-order temporal drops per second.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1a7cecc77e01848e3f2978a5814ec1568a"></a>

### `csi_occupancy_ratio`


```cpp
float espectre::RuntimeDiagnosticsSample::csi_occupancy_ratio {0.0f}
```

 

Valid-slot occupancy of the active temporal detector window.

   

<a id="structespectre_1_1_runtime_diagnostics_sample_1abac2acdc8b1e74cbde558ef87578c5fe"></a>

### `wifi_rssi_dbm`


```cpp
int8_t espectre::RuntimeDiagnosticsSample::wifi_rssi_dbm {INT8_MIN}
```

 

RSSI of the current association.

  

`INT8_MIN` when unavailable.

  

<a id="structespectre_1_1_runtime_diagnostics_sample_1a0dbd610d4f5bf12a6467446a19a98ecd"></a>

### `wifi_channel`


```cpp
uint8_t espectre::RuntimeDiagnosticsSample::wifi_channel {0U}
```

 

Primary channel of the current association.

  

Zero when unavailable.

  


<a id="classespectre_1_1_runtime_diagnostics_sampler"></a>

## espectre::RuntimeDiagnosticsSampler



```cpp
#include <runtime/runtime_diagnostics.h>
```



```cpp
class espectre::RuntimeDiagnosticsSampler
```

 

Converts cumulative diagnostics into rates over the interval between reads.

  

Call [`reset()`](#classespectre_1_1_runtime_diagnostics_sampler_1a255a7d6a981df30ffdce72d1b89495df) when the owning runtime starts. Counter resets are treated as a new epoch, so rearming a traffic source cannot underflow a rate. Station network counters wrap modulo 2^32 and are never reset by sensing restarts.

 

```cpp
// once, after controller.setup() succeeds:
sampler.reset(controller.diagnostics(), now_ms);
// on the runtime's existing sensing heartbeat:
latest = sampler.sample(controller.diagnostics(), now_ms);
```

 

**Par:** Threading

Not synchronized, and it holds the previous read. Sample it from the task that owns the runtime.

 

<a id="classespectre_1_1_runtime_diagnostics_sampler_1a255a7d6a981df30ffdce72d1b89495df"></a>

### `reset`


```cpp
void espectre::RuntimeDiagnosticsSampler::reset(const RuntimeDiagnosticsSnapshot &snapshot, uint32_t now_ms)
```

 

Establish the baseline the next [`sample()`](#classespectre_1_1_runtime_diagnostics_sampler_1aa63e9035ae799879686273cfab48e0bb) measures against.

  

**Parameters**

- `snapshot`: Current cumulative counters.
- `now_ms`: Monotonic frontend clock, in milliseconds.

  

<a id="classespectre_1_1_runtime_diagnostics_sampler_1aa63e9035ae799879686273cfab48e0bb"></a>

### `sample`


```cpp
RuntimeDiagnosticsSample espectre::RuntimeDiagnosticsSampler::sample(const RuntimeDiagnosticsSnapshot &snapshot, uint32_t now_ms)
```

 

Derive rates since the previous read and adopt this one as the baseline.

  

The caller owns the window. Call it from an existing periodic sensing update, so diagnostics do not add a timer.

 

**Parameters**

- `snapshot`: Current cumulative counters.
- `now_ms`: Monotonic frontend clock, in milliseconds.

 

**Returns:** Rates over the elapsed interval. The link fields are always carried through; the rates are zero when there is no baseline yet or no time has elapsed.

  


<a id="structespectre_1_1_runtime_diagnostics_snapshot"></a>

## espectre::RuntimeDiagnosticsSnapshot



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot
```

 

Low-frequency counters and radio state used by optional diagnostic surfaces.

  

This deliberately stays separate from [`RuntimeSnapshot`](#structespectre_1_1_runtime_snapshot): sensing snapshots travel through the hot callback path, while frontends query diagnostics when they already handle a periodic sensing update.

 

Counters are cumulative and monotonic within a session; pass them through [`RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler) to turn them into rates.

 [`espectre::RuntimeDiagnosticsSnapshot::Link`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_link)

[`espectre::RuntimeDiagnosticsSnapshot::Traffic`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic)

[`espectre::RuntimeDiagnosticsSnapshot::Csi`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi)

[`espectre::RuntimeDiagnosticsSnapshot::Platform`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform)

[`espectre::RuntimeDiagnosticsSnapshot::Performance`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance)



<a id="structespectre_1_1_runtime_diagnostics_snapshot_1aae60e81b8c408a1174e63cead0ba2c0f"></a>

### `link`


```cpp
Link espectre::RuntimeDiagnosticsSnapshot::link {}
```

 

Current Wi-Fi association.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1a0b12d908b3a5ffa2660e3c49cf80a7e0"></a>

### `traffic`


```cpp
Traffic espectre::RuntimeDiagnosticsSnapshot::traffic {}
```

 

Internal generator and station traffic counters.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1a2fa751d4c3ef9aa007a0bca99c4d2d45"></a>

### `csi`


```cpp
Csi espectre::RuntimeDiagnosticsSnapshot::csi {}
```

 

CSI capture, validation, and temporal admission counters.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1ae8d47c360ab2051a6e9365bbbf81059b"></a>

### `platform`


```cpp
Platform espectre::RuntimeDiagnosticsSnapshot::platform {}
```

 

Heap and CPU state.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1aeb1c046aad8ee83978aaeaa3e07ac0ea"></a>

### `performance`


```cpp
Performance espectre::RuntimeDiagnosticsSnapshot::performance {}
```

 

Runtime loop and detector timing over the latest complete window.

   


<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi"></a>

## espectre::RuntimeDiagnosticsSnapshot::Csi



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot::Csi
```

 

CSI capture, validation, and temporal admission counters.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a58a56d6df14be2d45414409bbc433ac1"></a>

### `callbacks_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::callbacks_total {0U}
```

 

Raw invocations of the ESP-IDF CSI callback.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a1cbb35d95f27648bcd49a3c54ca840ff"></a>

### `provenance_rejected_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::provenance_rejected_total {0U}
```

 

CSI callbacks rejected because their packet provenance did not match.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a2d706255afa69bbfbc50492c82ffaa05"></a>

### `accepted_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::accepted_total {0U}
```

 

CSI packets accepted by capture validation, before temporal admission.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a22041c8f2a777dc9d8babb576b85016a"></a>

### `admitted_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::admitted_total {0U}
```

 

CSI packets admitted to the detector's temporal grid.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1aa753669ebf30516781cb6766fb7b0007"></a>

### `filtered_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::filtered_total {0U}
```

 

CSI packets rejected by capture-level validation.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a7d5e0e121d2baf902fc706c6f719ae00"></a>

### `rx_error_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::rx_error_total {0U}
```

 

Packets rejected because the receiver reported an error.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a13b993e522bc083a7162b6247023e9aa"></a>

### `rx_end_error_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::rx_end_error_total {0U}
```

 

Packets rejected because reception ended with an error (HE-capable chips).

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1abbdc69cf02f596025fd472175db5186a"></a>

### `invalid_estimate_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::invalid_estimate_total {0U}
```

 

Packets rejected because the hardware CSI estimate was invalid (HE-capable chips).

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a7cf3507ad16a2660f684dfa8db078c49"></a>

### `invalid_first_word_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::invalid_first_word_total {0U}
```

 

Packets rejected because hardware-invalid source pairs affect live or unknown tones.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1ac06c37456ffb2adb026bf1dfd18ffa1c"></a>

### `sanitized_first_word_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::sanitized_first_word_total {0U}
```

 

Frames whose hardware-invalid guard pairs were zeroed without changing live tones.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1afaa97ed007c7026468d177902b99408a"></a>

### `pending_frame_drops_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::pending_frame_drops_total {0U}
```

 

Valid CSI callbacks dropped because the callback-to-runtime queue was full.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1adae60ebb0af559c8634279ef9af52b4f"></a>

### `missing_slots_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::missing_slots_total {0U}
```

 

Empty temporal detector slots observed before admitted packets.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1ae29ae900d52ecc9c1e43ba26d578d006"></a>

### `excess_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::excess_total {0U}
```

 

Valid packets dropped because their temporal slot was already occupied.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a90b777c93f1ef9eda9a00191038852ed"></a>

### `stale_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::stale_total {0U}
```

 

Packets rejected because processing began after the active window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a92c99b3151375b5708c389a876c94d1e"></a>

### `out_of_order_total`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Csi::out_of_order_total {0U}
```

 

Packets rejected because their timestamp moved backwards.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a9a1403a602d99acf261ccac34b2f9e71"></a>

### `occupancy_slots`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Csi::occupancy_slots {0U}
```

 

Valid slots in the current detector window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1aa85ca8f568eac8fe6f1c87895fb47d8d"></a>

### `window_slots`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Csi::window_slots {0U}
```

 

Total slots in the configured detector window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1aa6dc6c023a87726abf7926a87f53889f"></a>

### `pending_frames`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Csi::pending_frames {0U}
```

 

Frames currently waiting in the callback-to-runtime queue.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi_1a6de7b75234ada4b441e716c322c7c13d"></a>

### `pending_frame_capacity`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Csi::pending_frame_capacity {0U}
```

 

Fixed capacity of the callback-to-runtime queue.

   


<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_link"></a>

## espectre::RuntimeDiagnosticsSnapshot::Link



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot::Link
```

 

Current Wi-Fi association.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_link_1a1a0c4b19033b8d8c50c601df279f3d2a"></a>

### `rssi_dbm`


```cpp
int8_t espectre::RuntimeDiagnosticsSnapshot::Link::rssi_dbm {INT8_MIN}
```

 

RSSI of the current Wi-Fi association.

  

`INT8_MIN` when unavailable.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_link_1a34c1718530e3b312aa608e8e2841f0db"></a>

### `channel`


```cpp
uint8_t espectre::RuntimeDiagnosticsSnapshot::Link::channel {0U}
```

 

Primary channel of the current Wi-Fi association.

  

Zero when unavailable.

  


<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance"></a>

## espectre::RuntimeDiagnosticsSnapshot::Performance



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot::Performance
```

 

Runtime loop and detector timing over the latest complete window.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1aa174c35c42de7575833c9ef3d05ad883"></a>

### `window_ready`


```cpp
bool espectre::RuntimeDiagnosticsSnapshot::Performance::window_ready {false}
```

 

True after the first complete performance aggregation window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1afb7e2a4327e2523913a0792e7e94ee7d"></a>

### `window_duration_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::window_duration_us {0U}
```

 

Duration of the latest complete performance window, in microseconds.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1a00524727f0a68bed1c8fc44c8071257e"></a>

### `runtime_load_percent`


```cpp
float espectre::RuntimeDiagnosticsSnapshot::Performance::runtime_load_percent {0.0f}
```

 

Share of the window spent inside the ESPectre runtime loop.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1ad0a936672ea767895399572ad6c190b5"></a>

### `loop_samples`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::loop_samples {0U}
```

 

Runtime loop iterations measured in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1acbe4b4683543f3d6ebc125d73e3b9cd6"></a>

### `loop_average_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::loop_average_us {0U}
```

 

Mean runtime loop duration in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1a434abf9882bccb3678a59585c8987bf2"></a>

### `loop_maximum_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::loop_maximum_us {0U}
```

 

Maximum runtime loop duration in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1a44dfe9047ddcb0a5c1b668e0ea135086"></a>

### `detection_timing_supported`


```cpp
bool espectre::RuntimeDiagnosticsSnapshot::Performance::detection_timing_supported {false}
```

 

Whether this runtime executes a detector and reports its timing.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1a79dc17a478708a848658fc0c74a803e1"></a>

### `detection_samples`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::detection_samples {0U}
```

 

Detector evaluations measured in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1aaaab7a8d0a0d930811d8f1254e8257d0"></a>

### `detection_sum_us`


```cpp
uint64_t espectre::RuntimeDiagnosticsSnapshot::Performance::detection_sum_us {0U}
```

 

Total detector evaluation time in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1ab5bb43775ff08de32876ba8f82327d29"></a>

### `detection_average_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::detection_average_us {0U}
```

 

Mean detector evaluation time in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1aaf6c543bea5fe51e5117e19e486a289d"></a>

### `detection_minimum_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::detection_minimum_us {0U}
```

 

Minimum detector evaluation time in the latest complete window.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance_1abb6db305844c66eb70cf0a38fbf82c76"></a>

### `detection_maximum_us`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Performance::detection_maximum_us {0U}
```

 

Maximum detector evaluation time in the latest complete window.

   


<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform"></a>

## espectre::RuntimeDiagnosticsSnapshot::Platform



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot::Platform
```

 

Heap and CPU state.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform_1a50bdee8f9d007d0cd733c4940b9e23d4"></a>

### `free_memory_bytes`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Platform::free_memory_bytes {0U}
```

 

Current free heap in bytes.

  

Zero when unavailable.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform_1af9023a09884bcfadd8cb73a5e6dbcc46"></a>

### `minimum_free_memory_bytes`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Platform::minimum_free_memory_bytes {0U}
```

 

Minimum free heap observed since boot, in bytes.

  

Zero when unavailable.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform_1a3875ebe1ddc2d3b398816b3dab407839"></a>

### `largest_free_memory_block_bytes`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Platform::largest_free_memory_block_bytes {0U}
```

 

Largest currently allocatable heap block, in bytes.

  

Zero when unavailable.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform_1a6504e771d1e7bece46e85f1bf68ca58c"></a>

### `cpu_frequency_mhz`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Platform::cpu_frequency_mhz {0U}
```

 

Resolved CPU frequency in MHz.

  

Zero when unavailable.

  


<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic"></a>

## espectre::RuntimeDiagnosticsSnapshot::Traffic



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeDiagnosticsSnapshot::Traffic
```

 

Internal generator and station traffic counters.

  

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic_1a66992dc066c497b395cf4548a680389a"></a>

### `generator_packets_total`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Traffic::generator_packets_total {0U}
```

 

Successful internal generator sends; zero with external traffic ownership.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic_1a0d0a858a800c10c473eff07c22bfb2d1"></a>

### `tx_packets_total`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Traffic::tx_packets_total {0U}
```

 

Station packets accepted by the network driver; wraps modulo 2^32.

   

<a id="structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic_1ae0298f5b6b52bda34b53b7ef5c140248"></a>

### `rx_packets_total`


```cpp
uint32_t espectre::RuntimeDiagnosticsSnapshot::Traffic::rx_packets_total {0U}
```

 

Station packets delivered by the network driver; wraps modulo 2^32.

   


<a id="classespectre_1_1_runtime_direct_http_bridge"></a>

## espectre::RuntimeDirectHttpBridge



```cpp
#include <runtime/esp_idf/runtime_direct_http_bridge.h>
```



```cpp
class espectre::RuntimeDirectHttpBridge
```

 

Exposes the common runtime controls over the versioned Direct HTTP API.

  

Frontends retain ownership of their runtime and transport. The optional callback lets an adapter republish frontend-native entities after a Direct mutation, for example ESPHome number and select entities.

 

<a id="classespectre_1_1_runtime_direct_http_bridge_1a08b3b850fdc2a6fa96b6f77f00e381c6"></a>

### `ConfigChangedCallback`


```cpp
using espectre::RuntimeDirectHttpBridge::ConfigChangedCallback = std::function<void()>
```

   


<a id="classespectre_1_1_runtime_direct_http_bridge_1a11186d3fd85075cfa76082d3dcc2089f"></a>

### `setup`


```cpp
bool espectre::RuntimeDirectHttpBridge::setup(IDirectHttpService *service, RuntimeFrontendController *runtime, const RuntimeDirectHttpBridgeConfig &config, ConfigChangedCallback config_changed={})
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1a14f48cfe088fdc4d9e3b4983630d8840"></a>

### `loop`


```cpp
void espectre::RuntimeDirectHttpBridge::loop()
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1a3b7ed14517fe314ad124e7eaac7f2647"></a>

### `shutdown`


```cpp
void espectre::RuntimeDirectHttpBridge::shutdown()
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1a41168a884b23afcfaa6207b4232eaac4"></a>

### `running`


```cpp
bool espectre::RuntimeDirectHttpBridge::running() const
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1a3d62c7c02fe9edc2f9fdd446a6ff28ff"></a>

### `event_client_count`


```cpp
size_t espectre::RuntimeDirectHttpBridge::event_client_count() const
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1a2860a623e4969bcd4e6ab0a40162027c"></a>

### `publish_event`


```cpp
bool espectre::RuntimeDirectHttpBridge::publish_event(const char *event_name, const std::string &data_json, bool replaceable_telemetry=false)
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1ac737e2da4c867bcf341f3bfeb22d59bf"></a>

### `publish_motion`


```cpp
bool espectre::RuntimeDirectHttpBridge::publish_motion(const RuntimeSnapshot &snapshot)
```

   

<a id="classespectre_1_1_runtime_direct_http_bridge_1ad59141bad149054a36f26958a9d3c1d7"></a>

### `publish_changes`


```cpp
bool espectre::RuntimeDirectHttpBridge::publish_changes(FrontendCommandChange changes)
```

   


<a id="structespectre_1_1_runtime_direct_http_bridge_config"></a>

## espectre::RuntimeDirectHttpBridgeConfig



```cpp
#include <runtime/esp_idf/runtime_direct_http_bridge.h>
```



```cpp
struct espectre::RuntimeDirectHttpBridgeConfig
```

  

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a98a38f7328ca6e75524eaa76ae061b4c"></a>

### `frontend`


```cpp
std::string espectre::RuntimeDirectHttpBridgeConfig::frontend
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1aad0a4b9509731f7d97ddd668a73fc4a7"></a>

### `device_name`


```cpp
std::string espectre::RuntimeDirectHttpBridgeConfig::device_name
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a6d04303fb7d2db4b0f06c58cabf02a75"></a>

### `hostname`


```cpp
std::string espectre::RuntimeDirectHttpBridgeConfig::hostname
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1ac3bbaf6e0368a05bf57f6d51e6a199ac"></a>

### `firmware_version`


```cpp
std::string espectre::RuntimeDirectHttpBridgeConfig::firmware_version
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1ae9f04c562da67f6e9fd70129f7e70309"></a>

### `chip`


```cpp
std::string espectre::RuntimeDirectHttpBridgeConfig::chip
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1af7b33835649bf55581e73e0fc93df7ad"></a>

### `device_id`


```cpp
uint64_t espectre::RuntimeDirectHttpBridgeConfig::device_id {0U}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a0d722df897a745d3c48282f3a5badd7f"></a>

### `port`


```cpp
uint16_t espectre::RuntimeDirectHttpBridgeConfig::port {ESPECTRE_DIRECT_HTTP_PORT}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a16bfff616ea05aa8a9086a31aa8d8dc6"></a>

### `raw_csi`


```cpp
bool espectre::RuntimeDirectHttpBridgeConfig::raw_csi {false}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a357de25db9703b755cf566d95730092c"></a>

### `allow_missing_origin`


```cpp
bool espectre::RuntimeDirectHttpBridgeConfig::allow_missing_origin {false}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a157215245d7518fe4483f056a278f798"></a>

### `device_label_getter`


```cpp
std::function<std::string()> espectre::RuntimeDirectHttpBridgeConfig::device_label_getter
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1ab41b1bc76a6dc3eb78f6bcae2cc7c88e"></a>

### `device_label_setter`


```cpp
FrontendDeviceLabelCallback espectre::RuntimeDirectHttpBridgeConfig::device_label_setter
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a1de58ab64ec772200f6bf159a6b0bb67"></a>

### `wifi_snapshot_getter`


```cpp
std::function<DirectWifiSnapshot()> espectre::RuntimeDirectHttpBridgeConfig::wifi_snapshot_getter
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1ae284c51c72571be70a3a6d89aebf4c34"></a>

### `peer_discovery`


```cpp
IPeerDiscoveryService* espectre::RuntimeDirectHttpBridgeConfig::peer_discovery {nullptr}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1acab815a09347ea06d6f08d711c7cc284"></a>

### `diagnostics_sample_getter`


```cpp
std::function<const RuntimeDiagnosticsSample *()> espectre::RuntimeDirectHttpBridgeConfig::diagnostics_sample_getter
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a650302f6eeae5abd967d3ada89ff72fc"></a>

### `runtime_events`


```cpp
const RuntimeEventMailbox* espectre::RuntimeDirectHttpBridgeConfig::runtime_events {nullptr}
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a8930371a045d3abd60310248a304df6b"></a>

### `wifi_bssid_pin_setter`


```cpp
std::function<bool(const std::string &bssid, bool force, std::string *message)> espectre::RuntimeDirectHttpBridgeConfig::wifi_bssid_pin_setter
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1a8870d38f405961f6c2f95f7a2dd2317a"></a>

### `wifi_bssid_pin_preflight`


```cpp
std::function<bool(std::string *message)> espectre::RuntimeDirectHttpBridgeConfig::wifi_bssid_pin_preflight
```

   

<a id="structespectre_1_1_runtime_direct_http_bridge_config_1ab1411fd0f73a5d394dbfa1c3eb3cae34"></a>

### `loop_time_ms_getter`


```cpp
std::function<float()> espectre::RuntimeDirectHttpBridgeConfig::loop_time_ms_getter {}
```

 

Latest complete frontend loop duration in milliseconds; omitted callbacks yield null.

   


<a id="classespectre_1_1_runtime_event_mailbox"></a>

## espectre::RuntimeEventMailbox



```cpp
#include <runtime/runtime_event_mailbox.h>
```



```cpp
class espectre::RuntimeEventMailbox
```

 

Fixed-memory handoff from runtime listener callbacks to a frontend loop.

  

Motion-state changes retain FIFO ordering. If their bounded queue fills, posting keeps the newest state by discarding the oldest unconsumed state and reports the loss to the caller. Live telemetry is replaceable by design, so repeated posts coalesce to the newest snapshot.

 

All operations serialize their short value copies and are safe to call from different tasks. Drain the mailbox from one owning frontend task. This class is not intended for raw CSI callbacks or other ISR/driver contexts.

 

The mailbox never allocates and never invokes frontend code. The frontend remains responsible for publication, transport policy, and error handling.

 

<a id="classespectre_1_1_runtime_event_mailbox_1aa261f423c540d7b25a634e026893c9d2"></a>

### `kMotionStateCapacity`


```cpp
constexpr size_t espectre::RuntimeEventMailbox::kMotionStateCapacity = 4U
```

 

Maximum number of ordered motion-state changes retained.

   


<a id="classespectre_1_1_runtime_event_mailbox_1a210fe73397d29832b8437e54284b2b3a"></a>

### `RuntimeEventMailbox`


```cpp
espectre::RuntimeEventMailbox::RuntimeEventMailbox()=default
```

 

Construct an empty mailbox.

   

<a id="classespectre_1_1_runtime_event_mailbox_1acac8ca0bfe508013021819de3c513496"></a>

### `RuntimeEventMailbox`


```cpp
espectre::RuntimeEventMailbox::RuntimeEventMailbox(const RuntimeEventMailbox &)=delete
```

 

Mailboxes own synchronization state and cannot be copied.

   

<a id="classespectre_1_1_runtime_event_mailbox_1a27c244ca2820533e76bb5d84389deccc"></a>

### `operator=`


```cpp
RuntimeEventMailbox & espectre::RuntimeEventMailbox::operator=(const RuntimeEventMailbox &)=delete
```

 

Mailboxes own synchronization state and cannot be assigned.

   

<a id="classespectre_1_1_runtime_event_mailbox_1aa1e5bdcc75d829bd1bb7a0436d5f6f3c"></a>

### `post_motion_state`


```cpp
bool espectre::RuntimeEventMailbox::post_motion_state(const RuntimeSnapshot &snapshot)
```

 

Append a motion-state snapshot for ordered delivery.

  

When the queue is full, the oldest unconsumed snapshot is discarded so the eventual consumer still observes the newest state.

 

**Parameters**

- `snapshot`: Runtime state captured by `on_motion_state_changed()`.

 

**Returns:** `true` when every queued state was retained, or `false` when the oldest state had to be discarded.

  

<a id="classespectre_1_1_runtime_event_mailbox_1af2f3ac8fa1590beec480fbd97a5b1c5c"></a>

### `take_motion_state`


```cpp
bool espectre::RuntimeEventMailbox::take_motion_state(RuntimeSnapshot &snapshot)
```

 

Consume the oldest pending motion-state snapshot.

  

**Parameters**

- `snapshot`: Receives the snapshot when one is pending and remains unchanged otherwise.

 

**Returns:** `true` when a snapshot was consumed.

  

<a id="classespectre_1_1_runtime_event_mailbox_1add3140e9171121d8e525a71c74c8506d"></a>

### `post_live_telemetry`


```cpp
void espectre::RuntimeEventMailbox::post_live_telemetry(const RuntimeSnapshot &snapshot)
```

 

Store the newest replaceable live-telemetry snapshot.

  

**Parameters**

- `snapshot`: Runtime state with the callback's movement and threshold.

  

<a id="classespectre_1_1_runtime_event_mailbox_1a6f186ff4189a415c534c9192ecd8138f"></a>

### `take_live_telemetry`


```cpp
bool espectre::RuntimeEventMailbox::take_live_telemetry(RuntimeSnapshot &snapshot)
```

 

Consume the newest pending live-telemetry snapshot.

  

**Parameters**

- `snapshot`: Receives the snapshot when one is pending and remains unchanged otherwise.

 

**Returns:** `true` when a snapshot was consumed.

  

<a id="classespectre_1_1_runtime_event_mailbox_1aa70fbc51557b6a20ff80885a75b02fa8"></a>

### `post_threshold`


```cpp
void espectre::RuntimeEventMailbox::post_threshold(float threshold)
```

 

Store the newest replaceable threshold update.

   

<a id="classespectre_1_1_runtime_event_mailbox_1a6287a832d6ca1af858b56f1587ffea90"></a>

### `take_threshold`


```cpp
bool espectre::RuntimeEventMailbox::take_threshold(float &threshold)
```

 

Consume the newest pending threshold update.

   

<a id="classespectre_1_1_runtime_event_mailbox_1ad9a7a83373f51ddca801cf66653ab72b"></a>

### `motion_state_drops_total`


```cpp
uint32_t espectre::RuntimeEventMailbox::motion_state_drops_total() const
```

 

Cumulative ordered motion events discarded since construction.

   

<a id="classespectre_1_1_runtime_event_mailbox_1af50f6976e3f6cf006e62ea4863207d7f"></a>

### `clear`


```cpp
void espectre::RuntimeEventMailbox::clear()
```

 

Discard every unconsumed runtime event.

   


<a id="classespectre_1_1_runtime_frontend_controller"></a>

## espectre::RuntimeFrontendController



```cpp
#include <runtime/esp_idf/runtime_frontend_controller.h>
```



```cpp
class espectre::RuntimeFrontendController : private espectre::IRuntimeListener
```

 

The recommended entry point for firmware embedding ESPectre.

  

It owns the sensing runtime, caches the latest snapshot and discovered capabilities, and validates control calls before they reach the backend.

 

```cpp
class ProductFrontend : public espectre::IRuntimeListener {
 public:
  bool setup() {
    espectre::RuntimeConfig config;
    config.detection_algorithm = espectre::DetectionAlgorithm::LIGHTWEIGHT;
    runtime_.set_config(config);
    return runtime_.setup(this);
  }

  void loop() { runtime_.loop(); }

  void on_motion_state_changed(const espectre::RuntimeSnapshot &snapshot) override {
    if (snapshot.ready_to_publish) publish(snapshot.motion_state);
  }

 private:
  espectre::RuntimeFrontendController runtime_;
};
```

 

**Par:** Lifecycle

[`set_config()`](#classespectre_1_1_runtime_frontend_controller_1a6bc5d2dea03c406e822c0fc917e54840) -&gt; `setup(listener)` -&gt; [`loop()`](#classespectre_1_1_runtime_frontend_controller_1aa66c6b1a1a453f9ef9b4dfd27768c6f1) repeatedly -&gt; [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215). The controller is reusable after [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215): configuration survives, and [`set_config()`](#classespectre_1_1_runtime_frontend_controller_1a6bc5d2dea03c406e822c0fc917e54840) becomes effective again.

 

**Par:** Threading

Carries no internal locking. Run [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153), [`loop()`](#classespectre_1_1_runtime_frontend_controller_1aa66c6b1a1a453f9ef9b4dfd27768c6f1), and [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215) on one task. See [`espectre_sdk.h`](#espectre__sdk_8h) for the full contract, including where listener callbacks land and how to handle controls driven from a transport callback.

 

**Par:** Control calls before setup

The setters work before [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153) and simply update the pending configuration, so a frontend can accept provisioning commands during boot without special-casing the ordering.

 [`espectre::IRuntimeListener`](#classespectre_1_1_i_runtime_listener)



<a id="classespectre_1_1_runtime_frontend_controller_1ae54006efe65854689a9f22a5e2d19486"></a>

### `RuntimeFrontendController`


```cpp
espectre::RuntimeFrontendController::RuntimeFrontendController()
```

   

<a id="classespectre_1_1_runtime_frontend_controller_1ac4cb2c38604472e5a91773d63e4f86e9"></a>

### `~RuntimeFrontendController`


```cpp
espectre::RuntimeFrontendController::~RuntimeFrontendController() override
```

 

Shut the runtime down on scope exit without listener callbacks.

  

Call [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215) explicitly to receive the final readiness edge.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a6bc5d2dea03c406e822c0fc917e54840"></a>

### `set_config`


```cpp
void espectre::RuntimeFrontendController::set_config(const RuntimeConfig &config)
```

 

Stage the configuration used by the next [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153).

  

Ignored once setup has started, so reconfiguring a running runtime means [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215) first, or the setters for the fields that support live changes.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a0c93736a1d6dc29e8bd4bfb03bffa25a"></a>

### `config`


```cpp
RuntimeConfig & espectre::RuntimeFrontendController::config()
```

 

Mutable access to the staged configuration.

  

Provided so a frontend can adjust individual fields before [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153) without rebuilding the whole struct. After a successful setup it reflects the backend's effective configuration, including persisted overrides. Writing to it after setup stages the next setup only; live controls continue to validate against the active configuration.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a835cf53e8614e7b7dac7b2b5f5ac31e3"></a>

### `config`


```cpp
const RuntimeConfig & espectre::RuntimeFrontendController::config() const
```

 

Read-only view of the staged or last effective configuration.

   

<a id="classespectre_1_1_runtime_frontend_controller_1abe9fba2fd299106438728026bc018888"></a>

### `snapshot`


```cpp
const RuntimeSnapshot & espectre::RuntimeFrontendController::snapshot() const
```

 

Latest known snapshot, without querying the backend.

  

Refreshed automatically at [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153), by control calls, and before every listener callback is forwarded to your frontend. Use the cached snapshot for on-demand reads such as answering a status query; use the listener callbacks to react to change.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a9fe6055dcea10b65dc4e07a5855d38a9"></a>

### `diagnostics_sample`


```cpp
const RuntimeDiagnosticsSample * espectre::RuntimeFrontendController::diagnostics_sample() const
```

 

Latest one-second diagnostics: traffic and CSI rates plus the current link.

  

The recommended way to read diagnostics. The sample is owned by the runtime and shared by every reader. Returns `nullptr` before [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153).

  

<a id="classespectre_1_1_runtime_frontend_controller_1a621291d366aa0d0f47748724927c8a75"></a>

### `diagnostics`


```cpp
RuntimeDiagnosticsSnapshot espectre::RuntimeFrontendController::diagnostics() const
```

 

Advanced: cumulative counters behind [`diagnostics_sample()`](#classespectre_1_1_runtime_frontend_controller_1a9fe6055dcea10b65dc4e07a5855d38a9).

  

Use it for totals, or with [`RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler) for a custom sampling interval. Unlike [`snapshot()`](#classespectre_1_1_runtime_frontend_controller_1abe9fba2fd299106438728026bc018888), this queries the backend on every call, so invoke it from an existing periodic sensing callback, not from the hot loop. Returns a zeroed snapshot before [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153).

  

<a id="classespectre_1_1_runtime_frontend_controller_1a7dc5dd34287ce0af14346d436e15e8ef"></a>

### `capabilities`


```cpp
const RuntimeCapabilities & espectre::RuntimeFrontendController::capabilities() const
```

 

What the active backend supports.

  

Meaningful only after [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153).

 

Gate your product surface on it rather than hardcoding: the controller already refuses capability-gated calls, and this is how you avoid exposing a control the runtime will reject.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a2fa537d3e5ba87c01bcd42f2fabab0ea"></a>

### `subcarriers`


```cpp
const SelectedSubcarriers & espectre::RuntimeFrontendController::subcarriers() const
```

 

Subcarrier indices the detector measures on.

  

Fixed for this SDK version.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a93a43bbf7657e0681fd870504b2da3bf"></a>

### `is_setup_complete`


```cpp
bool espectre::RuntimeFrontendController::is_setup_complete() const
```

 

True between a successful [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153) and the next [`shutdown()`](#classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215).

   

<a id="classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153"></a>

### `setup`


```cpp
bool espectre::RuntimeFrontendController::setup(IRuntimeListener *listener)
```

 

Create the backend, apply the configuration, and start sensing.

  

Calling it twice is a no-op that returns true.

 

**Parameters**

- `listener`: Event sink, or `nullptr` for none. Not owned; it must outlive the controller.

 

**Returns:** false when the backend cannot start or its bounded working storage cannot be allocated. On failure the backend is dropped and the controller stays un-setup, so it is safe to fix the config and retry.

  

<a id="classespectre_1_1_runtime_frontend_controller_1aa66c6b1a1a453f9ef9b4dfd27768c6f1"></a>

### `loop`


```cpp
void espectre::RuntimeFrontendController::loop()
```

 

Advance runtime work and deliver pending listener callbacks.

  

Call it continuously from your loop task. Safe, and a no-op, before setup.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a676b16e92ff6025de8fdc400d2344215"></a>

### `shutdown`


```cpp
void espectre::RuntimeFrontendController::shutdown()
```

 

Stop sensing and release the backend.

  

Safe before setup and to repeat.

  

<a id="classespectre_1_1_runtime_frontend_controller_1abcf381fd02a5b47f239f61680f79a773"></a>

### `set_services_armed`


```cpp
void espectre::RuntimeFrontendController::set_services_armed(bool armed)
```

 

Gate runtime-owned services without tearing the runtime down.

  

Sticky: the value is remembered and reapplied to the backend created by a later [`setup()`](#classespectre_1_1_runtime_frontend_controller_1a4e448eb22ec37407f04ca7de09ee1153). Use it to stay silent until commissioning completes, or to pause CSI without dropping Wi-Fi. During raw collection the requested value is staged and applied when collection stops, because changing sensing services cannot interrupt the capture callback in place.

  

<a id="classespectre_1_1_runtime_frontend_controller_1ae334cb483e672900ac987aba31d073f0"></a>

### `set_live_telemetry_enabled`


```cpp
void espectre::RuntimeFrontendController::set_live_telemetry_enabled(bool enabled)
```

 

Enable or suppress [`IRuntimeListener::on_live_telemetry()`](#classespectre_1_1_i_runtime_listener_1a2473b19c1324d186b11ba596000acde9).

  

Also sticky.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a72ce3c88bf076a26033c2ff796e91db7"></a>

### `services_armed`


```cpp
bool espectre::RuntimeFrontendController::services_armed() const
```

 

Current armed state, including before setup.

   

<a id="classespectre_1_1_runtime_frontend_controller_1aa34bdedcf70f7a13dc90c91929123eec"></a>

### `quiesce`


```cpp
void espectre::RuntimeFrontendController::quiesce()
```

 

Temporarily quiet the runtime without releasing its backend or configuration.

  

Disables live telemetry and sensing services, and stops active raw collection. Restore the desired service and telemetry gates explicitly when resuming.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a74108feda3b239de79e7f74e1d0a286f"></a>

### `set_threshold`


```cpp
bool espectre::RuntimeFrontendController::set_threshold(float threshold)
```

 

Set the motion threshold, validating it against the active detector.

  

**Parameters**

- `threshold`: Value on the 0..1 metric scale.

 

**Returns:** false when out of range, or when the backend refuses it. Before setup the value is staged and returns true.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a297134ef51750ae4de0f1f4e9865ed9b"></a>

### `set_motion_hits`


```cpp
bool espectre::RuntimeFrontendController::set_motion_hits(uint8_t motion_on_hits, uint8_t motion_off_hits)
```

 

Set the hit filter.

  

**Parameters**

- `motion_on_hits`: Consecutive above-threshold evaluations to report motion (1..20). Higher trades latency for fewer false positives.
- `motion_off_hits`: Consecutive below-threshold evaluations to clear it (1..20).

 

**Returns:** false when either value is out of range, or when the runtime is up and does not advertise [`RuntimeCapabilities::supports_runtime_motion_hits_updates`](#structespectre_1_1_runtime_capabilities_1a84d3b5bb447e02b9026bdb81f69db236).

  

<a id="classespectre_1_1_runtime_frontend_controller_1a6b064a59cfbc88f56cebdcc53fa32aee"></a>

### `set_traffic_generator_mode`


```cpp
bool espectre::RuntimeFrontendController::set_traffic_generator_mode(TrafficGeneratorMode mode)
```

 

Change how the device gets CSI traffic: one of the internal generator modes, or [`TrafficGeneratorMode::EXTERNAL`](#namespaceespectre_1a41663f63d8455701e3a3d8e2ee838aa5a3932d629fb5e2be9d09b3a4485b3cc9d) to listen for another host.

  

**Returns:** false when the mode is invalid or unsupported on this target, or when the runtime is up and does not advertise [`RuntimeCapabilities::supports_traffic_control`](#structespectre_1_1_runtime_capabilities_1a9cb79d6a0f22efbcfecabc4d4747fedb).

  

<a id="classespectre_1_1_runtime_frontend_controller_1af1f0ea0d5537893247c360366a9abc08"></a>

### `set_detection_algorithm`


```cpp
bool espectre::RuntimeFrontendController::set_detection_algorithm(DetectionAlgorithm algorithm)
```

 

Switch detector while running.

  

The threshold follows the detector: the controller adopts the new detector's threshold rather than carrying the old value across scales.

 

**Returns:** false for an unknown algorithm, or when the runtime is up and does not advertise [`RuntimeCapabilities::supports_runtime_detector_selection`](#structespectre_1_1_runtime_capabilities_1a8a74863f469d46c8a8441ef4e58c6b66).

  

<a id="classespectre_1_1_runtime_frontend_controller_1a4022d8f2e85a66c50222aac5d0cbd4f3"></a>

### `validate_control_update`


```cpp
bool espectre::RuntimeFrontendController::validate_control_update(const RuntimeControlUpdate &update, std::string *message=nullptr) const
```

 

Check a combined change before applying any of it.

  

Applies `update` to a copy of the active configuration and validates the result, so a threshold is checked against the detector the same update selects, and a traffic generator mode against this chip and the CSI capture policy. Once the runtime is up, it also rejects fields whose capability is not advertised and any change during raw collection. Call it before the individual setters to apply a request completely or not at all; a setter can still fail afterwards when the backend refuses, for example on an allocation or NVS failure.

 

**Parameters**

- `update`: Fields to change.
- `message`: Receives the reason on failure. May be `nullptr`.

 

**Returns:** true when every setter in `update` is expected to succeed.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a2607dfb2e9eb34c51fe780e4d036548a"></a>

### `trigger_recalibration`


```cpp
bool espectre::RuntimeFrontendController::trigger_recalibration()
```

 

Restart startup calibration.

  

**Returns:** false before setup, or when the backend does not advertise [`RuntimeCapabilities::supports_manual_recalibration`](#structespectre_1_1_runtime_capabilities_1a1457a33557663be153d4472ac9192b20). Success only means calibration started; the outcome arrives through [`IRuntimeListener::on_calibration_finished()`](#classespectre_1_1_i_runtime_listener_1a27f8430a4a3b5b5dc6323765a2155e74).

  

<a id="classespectre_1_1_runtime_frontend_controller_1a4cdb8ac518bf507346f83b88cec6009e"></a>

### `is_calibrating`


```cpp
bool espectre::RuntimeFrontendController::is_calibrating() const
```

 

True while the backend is calibrating.

  

False before setup.

  

<a id="classespectre_1_1_runtime_frontend_controller_1a471ae93254ac292e6808dd04bddb4277"></a>

### `start_raw_collection`


```cpp
bool espectre::RuntimeFrontendController::start_raw_collection(raw_csi_packet_callback_t callback, void *context)
```

 

Enter transient raw collection through the active sensing backend.

  

The callback runs synchronously in the Wi-Fi CSI capture context, not from [`loop()`](#classespectre_1_1_runtime_frontend_controller_1aa66c6b1a1a453f9ef9b4dfd27768c6f1). It must remain bounded, non-blocking, and allocation-free. Copy any bytes needed after the callback returns; the packet view and its CSI buffer expire with the call. See [`raw_csi_packet_callback_t`](#namespaceespectre_1a7b0352147eec65c1f73a9d8714c4596d) for the return convention.

 

**Parameters**

- `callback`: Capture-context packet consumer. Must not be `nullptr`.
- `context`: Opaque caller-owned value passed to every callback. The caller must keep it valid until collection stops.

 

**Returns:** false before setup, without raw-CSI capability, with no Wi-Fi link, or when another transient operation is active.

  

<a id="classespectre_1_1_runtime_frontend_controller_1afe421ca5c348fe22cfa49461a24ecca0"></a>

### `stop_raw_collection`


```cpp
bool espectre::RuntimeFrontendController::stop_raw_collection(RawCsiStopReason reason=RawCsiStopReason::REQUESTED)
```

 

Leave transient raw collection and restore the prior armed state.

   

<a id="classespectre_1_1_runtime_frontend_controller_1ab81dbd7ee21318fd03015731064dc2df"></a>

### `operation_state`


```cpp
RuntimeOperationState espectre::RuntimeFrontendController::operation_state() const
```

 

Current transient backend operation.

   


<a id="structespectre_1_1_runtime_snapshot"></a>

## espectre::RuntimeSnapshot



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
struct espectre::RuntimeSnapshot
```

 

A consistent view of the sensing state at one instant.

  

Passed to every [`IRuntimeListener`](#classespectre_1_1_i_runtime_listener) callback and returned by [`RuntimeFrontendController::snapshot()`](#classespectre_1_1_runtime_frontend_controller_1abe9fba2fd299106438728026bc018888). It is a plain value type: copy it freely, and copy it if you need it past the callback that delivered it.

 

Read [`ready_to_publish`](#structespectre_1_1_runtime_snapshot_1a3e917a2d24bbe00e55416b9ddf3bffcd) before anything else. The runtime keeps emitting snapshots while it calibrates, and [`motion_state`](#structespectre_1_1_runtime_snapshot_1a39dbe81761f12a45799c1845d8d8f8af) is not meaningful until that flag is true.

 

<a id="structespectre_1_1_runtime_snapshot_1a39dbe81761f12a45799c1845d8d8f8af"></a>

### `motion_state`


```cpp
MotionState espectre::RuntimeSnapshot::motion_state {MotionState::IDLE}
```

 

Debounced motion state, after the `motion_on_hits` / `motion_off_hits` filter.

   

<a id="structespectre_1_1_runtime_snapshot_1a6844aeb15178c5088d4564c5719361c7"></a>

### `movement_metric`


```cpp
float espectre::RuntimeSnapshot::movement_metric {0.0f}
```

 

Current motion metric, on a 0..1 probability scale for both detectors.

  

Comparable to [`threshold`](#structespectre_1_1_runtime_snapshot_1ad26aab6b3715a69403a257668c6699c3), but not comparable across detectors: Lightweight and High Accuracy produce the number differently even though the scale matches.

  

<a id="structespectre_1_1_runtime_snapshot_1ad26aab6b3715a69403a257668c6699c3"></a>

### `threshold`


```cpp
float espectre::RuntimeSnapshot::threshold {RUNTIME_THRESHOLD_DEFAULT}
```

 

Threshold [`movement_metric`](#structespectre_1_1_runtime_snapshot_1a6844aeb15178c5088d4564c5719361c7) is compared against, on the same scale.

   

<a id="structespectre_1_1_runtime_snapshot_1a60ac8110de78ba7af0de788667e3702b"></a>

### `link_rssi_dbm`


```cpp
int8_t espectre::RuntimeSnapshot::link_rssi_dbm {INT8_MIN}
```

 

RSSI of the packets behind this metric.

  

`INT8_MIN` when unknown.

  

<a id="structespectre_1_1_runtime_snapshot_1a3b92bf25fed1f8f66d22ead1af2b7585"></a>

### `link_channel`


```cpp
uint8_t espectre::RuntimeSnapshot::link_channel {0}
```

 

Wi-Fi channel those packets arrived on.

  

Zero when unknown.

  

<a id="structespectre_1_1_runtime_snapshot_1a5d52ce9114fd4a374f93d26f6d6a4ab6"></a>

### `csi_capture_profile`


```cpp
CsiCaptureProfile espectre::RuntimeSnapshot::csi_capture_profile {CsiCaptureProfile::HT20}
```

 

Automatically selected CSI training-field and 20 MHz PHY profile.

   

<a id="structespectre_1_1_runtime_snapshot_1a83dbe442c55df68823a88b7270f3e5ab"></a>

### `calibrating`


```cpp
bool espectre::RuntimeSnapshot::calibrating {false}
```

 

Startup calibration is running; detection results are not valid yet.

   

<a id="structespectre_1_1_runtime_snapshot_1a334eddad66b0f849390574e3fef45400"></a>

### `calibration_packets`


```cpp
uint32_t espectre::RuntimeSnapshot::calibration_packets {0}
```

 

Packets observed by the current Lightweight startup calibrator.

  

Zero when calibration is not running. It returns to zero when motion restarts the calibration.

  

<a id="structespectre_1_1_runtime_snapshot_1a6c8c6bffd0f2903d6dd8b0dd656d30ee"></a>

### `calibration_target_packets`


```cpp
uint16_t espectre::RuntimeSnapshot::calibration_target_packets {0}
```

 

Packet budget for the current Lightweight startup calibrator.

  

Zero when calibration is not running. It grows in steps while the detector needs more evidence, up to three times its starting value.

  

<a id="structespectre_1_1_runtime_snapshot_1a3e917a2d24bbe00e55416b9ddf3bffcd"></a>

### `ready_to_publish`


```cpp
bool espectre::RuntimeSnapshot::ready_to_publish {false}
```

 

The runtime is calibrated, linked, and its output is safe to act on.

  

Gate every user-visible publication on this. It goes false again when the Wi-Fi link drops, while calibrating, and when detector input is one window old. Window coverage under the valid-slot floor clears it only after it lasts one detector window.

  

<a id="structespectre_1_1_runtime_snapshot_1a347d4e5da325362a17fa2d227fe3b900"></a>

### `startup_threshold`


```cpp
float espectre::RuntimeSnapshot::startup_threshold {0.0f}
```

 

Threshold startup calibration settled on.

  

Zero before it completes.

  

<a id="structespectre_1_1_runtime_snapshot_1a8839c547761d0f0f42121d48f48e34ee"></a>

### `detector_name`


```cpp
const char* espectre::RuntimeSnapshot::detector_name {"unknown"}
```

 

Active detector label: `"lightweight"` or `"high_accuracy"`.

  

Always a static string literal, so it stays valid for the process, but the pointer changes when the detector changes. [`parse_detection_algorithm()`](#namespaceespectre_1a58cce43945e826bdfe8db0e85cd5732c) turns it back into a [`DetectionAlgorithm`](#namespaceespectre_1ae6098340c58c0355e67beaa092880c6b). Note these are the protocol names, not [`BaseDetector::get_name()`](#classespectre_1_1_base_detector_1af1a3b2c9adb5ad7b550acfd7230a1503), which is capitalized for logs.

  


<a id="structespectre_1_1_standalone_wifi_access_point"></a>

## espectre::StandaloneWifiAccessPoint



```cpp
#include <runtime/esp_idf/standalone_wifi_service.h>
```



```cpp
struct espectre::StandaloneWifiAccessPoint
```

 

One access point reported by [StandaloneWifiService::request\_scan()](#classespectre_1_1_standalone_wifi_service_1a69941cd23b980c89c46985b87fddbbb1).

  

<a id="structespectre_1_1_standalone_wifi_access_point_1a4e5b5f856bdc024db112112b3278ef5d"></a>

### `ssid`


```cpp
std::string espectre::StandaloneWifiAccessPoint::ssid
```

   

<a id="structespectre_1_1_standalone_wifi_access_point_1a74bdab16629ec51c89eb5ca38affe56b"></a>

### `bssid`


```cpp
std::string espectre::StandaloneWifiAccessPoint::bssid
```

 

Upper-case, colon-separated MAC address.

   

<a id="structespectre_1_1_standalone_wifi_access_point_1a524b7b539a7ad9cb317565f80d956536"></a>

### `rssi_dbm`


```cpp
int8_t espectre::StandaloneWifiAccessPoint::rssi_dbm {0}
```

   

<a id="structespectre_1_1_standalone_wifi_access_point_1a2ea237c462588011a59460cc6da2bfb9"></a>

### `channel`


```cpp
uint8_t espectre::StandaloneWifiAccessPoint::channel {0U}
```

 

Primary channel.

   


<a id="structespectre_1_1_standalone_wifi_config"></a>

## espectre::StandaloneWifiConfig



```cpp
#include <runtime/esp_idf/standalone_wifi_service.h>
```



```cpp
struct espectre::StandaloneWifiConfig
```

 

Station settings for [StandaloneWifiService](#classespectre_1_1_standalone_wifi_service).

  

The strings are borrowed, null-terminated values. Keep them alive until shutdown or until update\_station\_config() replaces them.

 

<a id="structespectre_1_1_standalone_wifi_config_1a49bc4d2503cf2b54dc855c65e99ffd32"></a>

### `ssid`


```cpp
const char* espectre::StandaloneWifiConfig::ssid {""}
```

 

Network name, up to 32 bytes.

  

Empty leaves the station idle.

  

<a id="structespectre_1_1_standalone_wifi_config_1a957f816303c0875d685350c4d20e8604"></a>

### `password`


```cpp
const char* espectre::StandaloneWifiConfig::password {""}
```

 

Passphrase, up to 64 bytes.

  

Empty for open networks.

  

<a id="structespectre_1_1_standalone_wifi_config_1a66f2ee63c5333f92f34868c8b05bebac"></a>

### `bssid`


```cpp
const char* espectre::StandaloneWifiConfig::bssid {""}
```

 

Optional access point to pin, as `AA:BB:CC:DD:EE:FF`.

  

Empty lets the driver pick the strongest access point with this SSID.

  

<a id="structespectre_1_1_standalone_wifi_config_1a89507eb952f0bdbc814370e7d4735914"></a>

### `channel`


```cpp
uint8_t espectre::StandaloneWifiConfig::channel {0U}
```

 

Optional channel hint; [`WIFI_CHANNEL_AUTO`](#namespaceespectre_1ab18ef5b016f2a45b3e57911383e7a528) (0) scans every allowed channel.

   

<a id="structespectre_1_1_standalone_wifi_config_1a0dc87d4cf1fc77af1596e504cf0a1153"></a>

### `max_retry`


```cpp
int espectre::StandaloneWifiConfig::max_retry {8}
```

 

Immediate retries per burst; exhausted bursts restart after 30 seconds.

  

Zero skips immediate retries.

  

<a id="structespectre_1_1_standalone_wifi_config_1a1fa7c525d96db4d9729b0bc3be689ce2"></a>

### `manage_csi_lifecycle`


```cpp
bool espectre::StandaloneWifiConfig::manage_csi_lifecycle {false}
```

 

Register the [WiFiLifecycleManager](#classespectre_1_1_wi_fi_lifecycle_manager) handlers in this service.

  

Leave it false when [`RuntimeFrontendController`](#classespectre_1_1_runtime_frontend_controller) runs, because the runtime registers its own. Set it only when this service alone applies the CSI radio policy and delivers connection callbacks.

  

<a id="structespectre_1_1_standalone_wifi_config_1acefebff0c192715fe326af1e85878f66"></a>

### `band_policy`


```cpp
WifiBandPolicy espectre::StandaloneWifiConfig::band_policy {WifiBandPolicy::BAND_2G}
```

 

Band the station may use.

  

Fixed for the life of one setup().

  


<a id="structespectre_1_1_standalone_wifi_info"></a>

## espectre::StandaloneWifiInfo



```cpp
#include <runtime/esp_idf/standalone_wifi_service.h>
```



```cpp
struct espectre::StandaloneWifiInfo
```

 

Station state reported by [StandaloneWifiService::get\_info()](#classespectre_1_1_standalone_wifi_service_1a72c20691db34234a5984ac316b304141).

  

<a id="structespectre_1_1_standalone_wifi_info_1a7da10e8f5c15eee10602ee65e0b1fb4e"></a>

### `connected`


```cpp
bool espectre::StandaloneWifiInfo::connected {false}
```

 

True while associated with a cached IPv4 address.

   

<a id="structespectre_1_1_standalone_wifi_info_1ab82b00cba6e171807a274106a6129a17"></a>

### `ip_address`


```cpp
char espectre::StandaloneWifiInfo::ip_address[16][16] {}
```

 

Dotted IPv4 address, or empty without one.

   

<a id="structespectre_1_1_standalone_wifi_info_1ae54e242d978be13305357da7cdabfd77"></a>

### `mac_address`


```cpp
char espectre::StandaloneWifiInfo::mac_address[18][18] {}
```

 

Upper-case, colon-separated station MAC address.

   

<a id="structespectre_1_1_standalone_wifi_info_1a57fbee42754f9a27fac1a8f8e236f25e"></a>

### `channel`


```cpp
uint8_t espectre::StandaloneWifiInfo::channel {0U}
```

 

Primary channel of the association, or zero.

   


<a id="classespectre_1_1_standalone_wifi_service"></a>

## espectre::StandaloneWifiService



```cpp
#include <runtime/esp_idf/standalone_wifi_service.h>
```



```cpp
class espectre::StandaloneWifiService
```

 

Owns the ESP-IDF Wi-Fi station for firmware without its own Wi-Fi stack.

  

The service creates the station netif and driver, connects, retries in bounded bursts, and reports connection changes. Firmware that already owns Wi-Fi, such as ESPHome, does not use it.

 

```cpp
espectre::StandaloneWifiConfig wifi;
wifi.ssid = ssid;
wifi.password = password;
ESP_ERROR_CHECK(service.setup(wifi, on_connected, on_disconnected));
ESP_ERROR_CHECK(service.start());
// from the owner task's loop:
service.loop();
```

 

**Par:** Threading

Call every method from one owner task. Wi-Fi and IP events are queued by the event handlers, and callbacks run from [loop()](#classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c).

 


<a id="classespectre_1_1_standalone_wifi_service_1aef1b01da7ccaa70fa30c5a0622a8322f"></a>

### `~StandaloneWifiService`


```cpp
espectre::StandaloneWifiService::~StandaloneWifiService()
```

 

Release the station driver, netif, and registered handlers.

   

<a id="classespectre_1_1_standalone_wifi_service_1af6031ac873d13c5c31203be7a7b24db4"></a>

### `setup`


```cpp
esp_err_t espectre::StandaloneWifiService::setup(const StandaloneWifiConfig &config, standalone_wifi_callback_t connected_cb={}, standalone_wifi_callback_t disconnected_cb={})
```

 

Own a new station driver and netif; the application must not already own them.

  

Requires initialized NVS. The default event loop is created if needed and remains available after shutdown. Credentials are borrowed; SSIDs up to 32 bytes and passwords up to 64 bytes are preserved without truncation. Failure releases acquired resources so setup can be retried. Calling setup while active returns ESP\_ERR\_INVALID\_STATE. Use one owner task for all methods; callbacks run from [loop()](#classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c).

  

<a id="classespectre_1_1_standalone_wifi_service_1a533d0f1dec909d9ce1580c3d23395d07"></a>

### `start`


```cpp
esp_err_t espectre::StandaloneWifiService::start()
```

 

Start the station driver after [setup()](#classespectre_1_1_standalone_wifi_service_1af6031ac873d13c5c31203be7a7b24db4).

  

Connection proceeds asynchronously; the connected callback reports the IPv4 address. Returns `ESP_ERR_INVALID_STATE` before [setup()](#classespectre_1_1_standalone_wifi_service_1af6031ac873d13c5c31203be7a7b24db4).

  

<a id="classespectre_1_1_standalone_wifi_service_1ab8f6a62aafef564c0f4cd1ac1686ce4d"></a>

### `update_station_config`


```cpp
esp_err_t espectre::StandaloneWifiService::update_station_config(const StandaloneWifiConfig &config)
```

 

Replace the station settings while the service is set up.

  

An active connection is dropped and re-established with the new settings. Returns `ESP_ERR_INVALID_ARG` for oversized credentials, a negative retry count, or an unusable channel, and `ESP_ERR_INVALID_STATE` before [setup()](#classespectre_1_1_standalone_wifi_service_1af6031ac873d13c5c31203be7a7b24db4), while another reconfiguration is pending, or for a different band policy.

  

<a id="classespectre_1_1_standalone_wifi_service_1a69941cd23b980c89c46985b87fddbbb1"></a>

### `request_scan`


```cpp
esp_err_t espectre::StandaloneWifiService::request_scan(standalone_wifi_scan_callback_t callback)
```

 

Scan every allowed channel for the configured SSID and report its bounded snapshot from [loop()](#classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c).

   

<a id="classespectre_1_1_standalone_wifi_service_1ad1e165e7f0eb286a2c1b68b573cee60c"></a>

### `loop`


```cpp
void espectre::StandaloneWifiService::loop()
```

 

Deliver queued Wi-Fi events and callbacks, and drive reconnection.

   

<a id="classespectre_1_1_standalone_wifi_service_1a72c20691db34234a5984ac316b304141"></a>

### `get_info`


```cpp
bool espectre::StandaloneWifiService::get_info(StandaloneWifiInfo *info) const
```

 

Read the station MAC address and, while connected, its IPv4 address and channel.

  

Uses the cached address instead of querying an unassociated driver. Returns false for a null `info` or when nothing is known yet.

  

<a id="classespectre_1_1_standalone_wifi_service_1a1d8ca8218dc20f1007034de43983693d"></a>

### `shutdown`


```cpp
void espectre::StandaloneWifiService::shutdown()
```

 

Stop and release owned Wi-Fi resources.

  

Safe to repeat; setup can be called again.

  


<a id="structespectre_1_1_stored_wifi_config"></a>

## espectre::StoredWifiConfig



```cpp
#include <runtime/esp_idf/device_config_store.h>
```



```cpp
struct espectre::StoredWifiConfig
```

 

Wi-Fi station settings as persisted in NVS.

  

<a id="structespectre_1_1_stored_wifi_config_1a0962ca8aab4664861378f9a32e7bfbd8"></a>

### `ssid`


```cpp
std::string espectre::StoredWifiConfig::ssid
```

   

<a id="structespectre_1_1_stored_wifi_config_1a526e922f19f013af34d8340b7593bd4a"></a>

### `password`


```cpp
std::string espectre::StoredWifiConfig::password
```

   

<a id="structespectre_1_1_stored_wifi_config_1a6916305746a8f7b1a6583a48dc68da1a"></a>

### `bssid`


```cpp
std::string espectre::StoredWifiConfig::bssid
```

 

Optional pinned access point, as `AA:BB:CC:DD:EE:FF`; empty when unpinned.

   

<a id="structespectre_1_1_stored_wifi_config_1a6b11dd58df8efc4cf26dd01d1484734a"></a>

### `channel`


```cpp
uint8_t espectre::StoredWifiConfig::channel {0U}
```

 

Optional channel hint; zero means automatic.

   

<a id="structespectre_1_1_stored_wifi_config_1a59c1d0e8d1a9a1029eec2de177568353"></a>

### `band_policy`


```cpp
WifiBandPolicy espectre::StoredWifiConfig::band_policy {WifiBandPolicy::BAND_2G}
```

   

<a id="structespectre_1_1_stored_wifi_config_1a936af3c1785f5eed84182c66457a3ee9"></a>

### `has_saved_band_policy`


```cpp
bool espectre::StoredWifiConfig::has_saved_band_policy {false}
```

 

Whether [`band_policy`](#structespectre_1_1_stored_wifi_config_1a59c1d0e8d1a9a1029eec2de177568353) came from NVS rather than a build default.

   

<a id="structespectre_1_1_stored_wifi_config_1af2972a09f2650d2f0dc172e6990bb1d4"></a>

### `has_saved_config`


```cpp
bool espectre::StoredWifiConfig::has_saved_config {false}
```

 

Whether these settings came from NVS rather than build defaults.

   


<a id="classespectre_1_1_temporal_csi_sampler"></a>

## espectre::TemporalCsiSampler



```cpp
#include <core/temporal_csi_sampler.h>
```



```cpp
class espectre::TemporalCsiSampler
```

 

Admit timestamped CSI packets onto the production fixed-time grid.

  

The sampler retains at most one candidate per target-rate slot, preserves missing slots, rejects invalid timestamp progress, and reports when a gap requires detector history to be cleared. A core-only integration should apply its admission result before forwarding CSI to a detector.

 

The sampler stores timing and slot state, not CSI payloads. The caller keeps the currently selected payload. When [admit()](#classespectre_1_1_temporal_csi_sampler_1a1791e9ab49629b200e9273ae61ebd4aa) commits a prior slot, consume that retained payload before replacing it when [selected\_current()](#classespectre_1_1_temporal_csi_sampler_1ae1ec9c3c8e6f8989c600bab39e628c93) is true.

 

Not thread-safe. Construct, configure, admit, and read it from the task that owns the custom capture pipeline. Construction and [configure()](#classespectre_1_1_temporal_csi_sampler_1af439a77c9ee2831f65801d359ca6a995) use non-throwing storage allocation; check [is\_valid()](#classespectre_1_1_temporal_csi_sampler_1a6815a334d670439cd680f2bd156095d5) after construction and the [configure()](#classespectre_1_1_temporal_csi_sampler_1af439a77c9ee2831f65801d359ca6a995) result before consuming packets. The sampler is movable and intentionally non-copyable because the slot window owns live temporal state.

 

<a id="classespectre_1_1_temporal_csi_sampler_1a223fef3f5d5c971137c31cb937aef12e"></a>

### `TemporalCsiSampler`


```cpp
explicit espectre::TemporalCsiSampler::TemporalCsiSampler(uint32_t target_pps=100U, uint32_t window_size_ms=1000U)
```

 

Construct a sampler for the requested target rate and window duration.

   

<a id="classespectre_1_1_temporal_csi_sampler_1ae08dd76f204e50fa60c43c628a2bbbf2"></a>

### `TemporalCsiSampler`


```cpp
espectre::TemporalCsiSampler::TemporalCsiSampler(TemporalCsiSampler &&) noexcept=default
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ae0fdbbaa165cbd540a6cceae7ccee675"></a>

### `operator=`


```cpp
TemporalCsiSampler & espectre::TemporalCsiSampler::operator=(TemporalCsiSampler &&) noexcept=default
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a7ddc81d12caa7fc7ef9be73eb83db54d"></a>

### `TemporalCsiSampler`


```cpp
espectre::TemporalCsiSampler::TemporalCsiSampler(const TemporalCsiSampler &)=delete
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1af4d593a870758620ec7674408e19dcd7"></a>

### `operator=`


```cpp
TemporalCsiSampler & espectre::TemporalCsiSampler::operator=(const TemporalCsiSampler &)=delete
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1af439a77c9ee2831f65801d359ca6a995"></a>

### `configure`


```cpp
bool espectre::TemporalCsiSampler::configure(uint32_t target_pps, uint32_t window_size_ms)
```

 

Reconfigure the grid and clear its timestamp epoch and window state.

   

<a id="classespectre_1_1_temporal_csi_sampler_1a6815a334d670439cd680f2bd156095d5"></a>

### `is_valid`


```cpp
bool espectre::TemporalCsiSampler::is_valid() const
```

 

Return whether the active slot window owns complete storage.

   

<a id="classespectre_1_1_temporal_csi_sampler_1a2f519ceeb7c1948c6380e13db258376f"></a>

### `reset`


```cpp
void espectre::TemporalCsiSampler::reset()
```

 

Clear the timestamp epoch, window state, and lifetime counters.

   

<a id="classespectre_1_1_temporal_csi_sampler_1a711c178e7646d3e21cd7263c4f9fdfb0"></a>

### `clear_history`


```cpp
void espectre::TemporalCsiSampler::clear_history()
```

 

Clear the window and timestamp grid while retaining lifetime counters.

   

<a id="classespectre_1_1_temporal_csi_sampler_1ad40635b15a773affa083090355b87ee7"></a>

### `clear_window_preserving_phase`


```cpp
void espectre::TemporalCsiSampler::clear_window_preserving_phase()
```

 

Clear admitted window data while retaining the active timestamp grid.

   

<a id="classespectre_1_1_temporal_csi_sampler_1a1791e9ab49629b200e9273ae61ebd4aa"></a>

### `admit`


```cpp
bool espectre::TemporalCsiSampler::admit(uint32_t timestamp_us, bool has_timestamp=true, uint32_t now_us=0U, bool has_now=false)
```

 

Observe one candidate and report whether the retained payload was committed.

  

`now_us` is optional processing time on the same unsigned 32-bit clock as `timestamp_us`. Omit it when the clocks differ, including classic ESP32 Wi-Fi RX timestamps versus `esp_timer`.

  

<a id="classespectre_1_1_temporal_csi_sampler_1a20e40f1dff05429d21aa8a98adc1f45d"></a>

### `flush`


```cpp
bool espectre::TemporalCsiSampler::flush()
```

 

Commit the retained payload when the input stream ends.

   

<a id="classespectre_1_1_temporal_csi_sampler_1a8b8dae0e5fe5148b924e66af47cab22a"></a>

### `target_pps`


```cpp
uint32_t espectre::TemporalCsiSampler::target_pps() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a2b931007fb93c841a71fa7d23a463d62"></a>

### `window_size_ms`


```cpp
uint32_t espectre::TemporalCsiSampler::window_size_ms() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ae2c7518168da096d5fa018b095b9bfb1"></a>

### `window_slots`


```cpp
uint32_t espectre::TemporalCsiSampler::window_slots() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a7a3d5d2332ffa7d8a9f05704f412e5a7"></a>

### `minimum_valid_slots`


```cpp
uint32_t espectre::TemporalCsiSampler::minimum_valid_slots() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a5e631296ec639219dfc7c91eb8cc2928"></a>

### `minimum_sample_spacing_us`


```cpp
uint32_t espectre::TemporalCsiSampler::minimum_sample_spacing_us() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a193d03754a56bc4e09d2604a41aed345"></a>

### `occupancy_slots`


```cpp
uint32_t espectre::TemporalCsiSampler::occupancy_slots() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1adcc84addf47197494916c3f57884daf8"></a>

### `occupancy_ratio`


```cpp
float espectre::TemporalCsiSampler::occupancy_ratio() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a7fcea0bff326d0a049d9c9bb48eb265c"></a>

### `is_ready`


```cpp
bool espectre::TemporalCsiSampler::is_ready() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1afe7474e33d824553b2d33323597dc48a"></a>

### `accepted`


```cpp
bool espectre::TemporalCsiSampler::accepted() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ae1ec9c3c8e6f8989c600bab39e628c93"></a>

### `selected_current`


```cpp
bool espectre::TemporalCsiSampler::selected_current() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ab936c9db7ed7a1c0716272b7c2993933"></a>

### `has_pending_candidate`


```cpp
bool espectre::TemporalCsiSampler::has_pending_candidate() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a8cacc760d7b7599cc2233bde30c7350e"></a>

### `reset_required`


```cpp
bool espectre::TemporalCsiSampler::reset_required() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ac21e227f4e489f3586f13577a18ccc66"></a>

### `gap_reset_required`


```cpp
bool espectre::TemporalCsiSampler::gap_reset_required() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ace42717de24f9c381c0c85a728bcf069"></a>

### `current_slot`


```cpp
uint64_t espectre::TemporalCsiSampler::current_slot() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a32402864d8caa2f17d149cfe95b2caab"></a>

### `slots_advanced`


```cpp
uint64_t espectre::TemporalCsiSampler::slots_advanced() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a8956697103963cddff22fa05626053cc"></a>

### `missing_slots_before`


```cpp
uint64_t espectre::TemporalCsiSampler::missing_slots_before() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a6af061429ee800be178ae81db2141e6f"></a>

### `accepted_packets`


```cpp
uint64_t espectre::TemporalCsiSampler::accepted_packets() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a95f0c153916f097cdcae970f0a5fe322"></a>

### `excess_packets`


```cpp
uint64_t espectre::TemporalCsiSampler::excess_packets() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a49794045bc9b78765549614cfa82b6b2"></a>

### `out_of_order_packets`


```cpp
uint64_t espectre::TemporalCsiSampler::out_of_order_packets() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1ad73b99e1810a1e83292075ec34e34409"></a>

### `stale_packets`


```cpp
uint64_t espectre::TemporalCsiSampler::stale_packets() const
```

   

<a id="classespectre_1_1_temporal_csi_sampler_1a91fdaedfdbc09d6f74a4fec4d37544ae"></a>

### `missing_slots`


```cpp
uint64_t espectre::TemporalCsiSampler::missing_slots() const
```

   


<a id="classespectre_1_1_traffic_generator_manager"></a>

## espectre::TrafficGeneratorManager



```cpp
#include <runtime/esp_idf/traffic_generator_manager.h>
```



```cpp
class espectre::TrafficGeneratorManager : public espectre::ICsiTrafficGenerator
```

 

Paced ESP-IDF traffic generator with a firmware-owned lifecycle.

  [`espectre::ICsiTrafficGenerator`](#classespectre_1_1_i_csi_traffic_generator)



<a id="classespectre_1_1_traffic_generator_manager_1a1611ff5acf3063285af5e79a256d4bbb"></a>

### `init`


```cpp
void espectre::TrafficGeneratorManager::init(uint32_t target_pps, TrafficGeneratorMode mode=TrafficGeneratorMode::PING) override
```

 

Configure the send rate and backend while stopped.

   

<a id="classespectre_1_1_traffic_generator_manager_1a04d7c96a83f8cbf0a6244fcbe129619d"></a>

### `start`


```cpp
bool espectre::TrafficGeneratorManager::start(uint32_t target_addr) override
```

 

Start sending to an IPv4 address in network byte order; WIFI\_RAW ignores the address.

   

<a id="classespectre_1_1_traffic_generator_manager_1a71b888ef51013730d88e5d1c2554679f"></a>

### `loop`


```cpp
void espectre::TrafficGeneratorManager::loop() override
```

 

Check send progress and report a stalled generator from the owner task.

   

<a id="classespectre_1_1_traffic_generator_manager_1af5c7a6638c9d90e5d4aa289444cc9604"></a>

### `stop`


```cpp
void espectre::TrafficGeneratorManager::stop() override
```

 

Stop sending and release the sender.

   

<a id="classespectre_1_1_traffic_generator_manager_1aeb69bab1ad47e746c35ec76e879ffded"></a>

### `is_running`


```cpp
bool espectre::TrafficGeneratorManager::is_running() const override
```

   

<a id="classespectre_1_1_traffic_generator_manager_1ae96bf40e87baf67b98c77e937e40f6ef"></a>

### `pause`


```cpp
void espectre::TrafficGeneratorManager::pause()
```

 

Suspend sends without destroying the worker.

   

<a id="classespectre_1_1_traffic_generator_manager_1ac36d125fc2307d4f6122a9146ebb82e4"></a>

### `resume`


```cpp
void espectre::TrafficGeneratorManager::resume()
```

   

<a id="classespectre_1_1_traffic_generator_manager_1a829a2dbcac0ab4de35c0cd92e0681116"></a>

### `is_paused`


```cpp
bool espectre::TrafficGeneratorManager::is_paused() const
```

   

<a id="classespectre_1_1_traffic_generator_manager_1a94c6aa4e46b66482054d438b157938bd"></a>

### `target_rate_pps`


```cpp
uint32_t espectre::TrafficGeneratorManager::target_rate_pps() const
```

   

<a id="classespectre_1_1_traffic_generator_manager_1af37515bc464d44eac94d82db9b8e23c6"></a>

### `current_rate_pps`


```cpp
uint32_t espectre::TrafficGeneratorManager::current_rate_pps() const
```

 

Send rate used by the worker, in packets per second.

   

<a id="classespectre_1_1_traffic_generator_manager_1a05a24eb916d7ef9b4bb71999b08c8da4"></a>

### `send_success_count`


```cpp
uint32_t espectre::TrafficGeneratorManager::send_success_count() const override
```

 

Number of successful sends in the current session.

   

<a id="classespectre_1_1_traffic_generator_manager_1a234d3ce12e136fa717fb88979287c78e"></a>

### `send_error_count`


```cpp
uint32_t espectre::TrafficGeneratorManager::send_error_count() const
```

 

Number of failed sends in the current session.

   

<a id="classespectre_1_1_traffic_generator_manager_1ace20abf21cf500964cc91747c7423830"></a>

### `icmp_identifier`


```cpp
uint16_t espectre::TrafficGeneratorManager::icmp_identifier() const override
```

 

ICMP identifier used to recognize this generator's ping replies.

   


<a id="structespectre_1_1_udp_datagram_peer"></a>

## espectre::UdpDatagramPeer



```cpp
#include <runtime/udp_datagram_socket.h>
```



```cpp
struct espectre::UdpDatagramPeer
```

  

<a id="structespectre_1_1_udp_datagram_peer_1a8ad9fa7d60974939dd76d1a1eedc4c2d"></a>

### `ipv4_addr`


```cpp
uint32_t espectre::UdpDatagramPeer::ipv4_addr {0U}
```

   

<a id="structespectre_1_1_udp_datagram_peer_1aed7273d785b3417c4c2bdaa70bccc9be"></a>

### `port`


```cpp
uint16_t espectre::UdpDatagramPeer::port {0U}
```

   


<a id="classespectre_1_1_wi_fi_lifecycle_manager"></a>

## espectre::WiFiLifecycleManager



```cpp
#include <runtime/esp_idf/wifi_lifecycle.h>
```



```cpp
class espectre::WiFiLifecycleManager
```

 

Turns Wi-Fi and IP events into connect and disconnect callbacks.

  

The runtime starts and stops CSI capture, traffic, and calibration from those callbacks. The station TX rate policy is applied before the connected callbacks, whether sensing uses an internal generator or external traffic.

 

The STA-start handler applies the short radio policy synchronously, before association. Connect/disconnect callbacks run from [process\_pending\_events()](#classespectre_1_1_wi_fi_lifecycle_manager_1adc7ad4c05118e53e0767d4123f374517), which the runtime must call from its loop task. This keeps service startup and log formatting off the small default event loop task (sys\_evt) stack.

 

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a812e0a4f46c766d812658185aa933761"></a>

### `register_handlers`


```cpp
esp_err_t espectre::WiFiLifecycleManager::register_handlers(wifi_connected_callback_t connected_cb, wifi_disconnected_callback_t disconnected_cb, WifiBandPolicy band_policy=WifiBandPolicy::BAND_2G)
```

 

Register Wi-Fi event handlers.

  

**Parameters**

- `connected_cb`: Callback when Wi-Fi obtains or retains an IPv4 configuration; receives the address, netmask, and gateway after GOT\_IP or reassociation
- `disconnected_cb`: Callback when Wi-Fi disconnects
- `band_policy`: Station band policy used while applying connection settings

 

**Returns:** ESP\_OK on success. If the default station already has an IPv4 address, its current state is queued for [process\_pending\_events()](#classespectre_1_1_wi_fi_lifecycle_manager_1adc7ad4c05118e53e0767d4123f374517).

  

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1ae130fbbcc4833a424e4ad4488143c338"></a>

### `unregister_handlers`


```cpp
void espectre::WiFiLifecycleManager::unregister_handlers()
```

 

Unregister Wi-Fi event handlers.

   

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1adc7ad4c05118e53e0767d4123f374517"></a>

### `process_pending_events`


```cpp
esp_err_t espectre::WiFiLifecycleManager::process_pending_events()
```

 

Invoke the registered callbacks for events recorded by the handlers.

  

Must be called periodically from the runtime loop task. Events are processed in the same order in which the ESP event loop recorded them.

  

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a38826e392159833222339361036f6c26"></a>

### `refresh_csi_receive_path`


```cpp
esp_err_t espectre::WiFiLifecycleManager::refresh_csi_receive_path(wifi_csi_rx_refresh_callback_t callback, bool manage_scan_results=true)
```

 

Attempt an asynchronous scan on the associated channel to recover a silent CSI receive path.

  

Requires a current association with a nonzero channel. Busy drivers and unconsumed scan results return ESP\_ERR\_INVALID\_STATE. Completion, including a 30-second timeout, runs from [process\_pending\_events()](#classespectre_1_1_wi_fi_lifecycle_manager_1adc7ad4c05118e53e0767d4123f374517). Promiscuous mode stays disabled. With manage\_scan\_results enabled, callers must keep independent scanners idle until [csi\_receive\_path\_refresh\_active()](#classespectre_1_1_wi_fi_lifecycle_manager_1a6f3a5e218edd6ad77719ba2911947312) becomes false. Disable it when the Wi-Fi stack consumes all scan results; cleanup then leaves the driver's result list entirely to that stack.

  

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a1fe9bba1e6dd8c26acf37503fc3e80cc"></a>

### `cancel_csi_receive_path_refresh`


```cpp
void espectre::WiFiLifecycleManager::cancel_csi_receive_path_refresh()
```

 

Cancel an in-flight CSI receive-path refresh.

  

Late scan completion events are invalidated and cannot invoke the canceled callback.

  


<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a6f3a5e218edd6ad77719ba2911947312"></a>

### `csi_receive_path_refresh_active`


```cpp
static bool espectre::WiFiLifecycleManager::csi_receive_path_refresh_active()
```

 

Whether an SDK CSI refresh owns the scanner, including pending cleanup.

   

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a731bac4db6341b9069145f34197c4044"></a>

### `apply_started_csi_policy`


```cpp
static esp_err_t espectre::WiFiLifecycleManager::apply_started_csi_policy(WifiBandPolicy band_policy=WifiBandPolicy::BAND_2G)
```

 

Apply the short CSI radio policy that must run after WIFI\_EVENT\_STA\_START and before association.

  

Safe to call more than once; later calls are no-ops once protocol, bandwidth, and power-save already match.

  

<a id="classespectre_1_1_wi_fi_lifecycle_manager_1a9dc55a7bc08ab9e6c4a0dd9c315c52e7"></a>

### `reinitialize_stopped_station_driver`


```cpp
static esp_err_t espectre::WiFiLifecycleManager::reinitialize_stopped_station_driver(wifi_storage_t storage=WIFI_STORAGE_RAM)
```

 

Reinitialize an already-stopped station driver and restore the invariants required by every CSI frontend.

  

The caller remains responsible for applying its station configuration and starting the driver.

  


<a id="classespectre_1_1_wifi_bssid_pin_service"></a>

## espectre::WifiBssidPinService



```cpp
#include <runtime/esp_idf/wifi_bssid_pin_service.h>
```



```cpp
class espectre::WifiBssidPinService
```

 

Persists an access point pin for the provisioned SSID and applies it with verification and rollback.

  

For firmware whose Wi-Fi stack owns the credentials, such as Matter commissioning. The service stores only the SSID and BSSID pair in NVS. A pin takes effect through `apply_callback`, is saved after the station reconnects to that access point with an IPv4 address, and is rolled back when that does not happen within `candidate_timeout_ms`. At boot, a stored pin for the current SSID is reapplied when the station associates elsewhere.

 

**Par:** Threading

Call every method from one owner task, and call [loop()](#classespectre_1_1_wifi_bssid_pin_service_1a9ffdc9e9947edb8d41fd79f60c3afddd) from its loop.

 

<a id="classespectre_1_1_wifi_bssid_pin_service_1a4401cef436ec422e0f47bedc102832a0"></a>

### `setup`


```cpp
esp_err_t espectre::WifiBssidPinService::setup(WifiBssidPinServiceConfig config)
```

 

Install the hooks and load the stored pin.

  

**Returns:** `ESP_ERR_INVALID_ARG` when a required hook is missing or the timeout is zero, or the NVS error that prevented loading.

  

<a id="classespectre_1_1_wifi_bssid_pin_service_1a22c79734f4160237420aeb468627ca1b"></a>

### `request_update`


```cpp
bool espectre::WifiBssidPinService::request_update(const std::string &bssid, std::string *message, bool force=false)
```

 

Stage a pin update.

  

An empty BSSID clears the current override.

 

Pinning the access point already in use is saved directly unless `force` is set.

 

**Returns:** false before [setup()](#classespectre_1_1_wifi_bssid_pin_service_1a4401cef436ec422e0f47bedc102832a0), while another change is in progress, for a malformed BSSID, or without a provisioned SSID. `message` receives the outcome.

  

<a id="classespectre_1_1_wifi_bssid_pin_service_1aa335fdf5103c23d6baad549e4279ea37"></a>

### `notify_station_changed`


```cpp
void espectre::WifiBssidPinService::notify_station_changed()
```

 

Schedule a station snapshot refresh after a Wi-Fi or IP event.

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1a9ffdc9e9947edb8d41fd79f60c3afddd"></a>

### `loop`


```cpp
void espectre::WifiBssidPinService::loop()
```

 

Advance verification, rollback, and boot-time enforcement.

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1af64af02c4ef7cd53cd586b0d6f1969b1"></a>

### `apply_state`


```cpp
WifiBssidPinApplyState espectre::WifiBssidPinService::apply_state() const
```

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1acc0f42e341b2b5eee23c4eafebc50527"></a>

### `apply_message`


```cpp
const std::string & espectre::WifiBssidPinService::apply_message() const
```

 

Human-readable detail for [apply\_state()](#classespectre_1_1_wifi_bssid_pin_service_1af64af02c4ef7cd53cd586b0d6f1969b1).

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1accd04bb7d2f92f873918389af209e283"></a>

### `stored_ssid`


```cpp
const std::string & espectre::WifiBssidPinService::stored_ssid() const
```

 

SSID the stored pin belongs to; empty without a pin.

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1a73cf4b9405976db503875edf9fac3280"></a>

### `stored_bssid`


```cpp
const std::string & espectre::WifiBssidPinService::stored_bssid() const
```

 

Stored pin; empty without one.

   

<a id="classespectre_1_1_wifi_bssid_pin_service_1aa97db1ae127786e2db9204a8ba0bdbc3"></a>

### `apply_pending`


```cpp
bool espectre::WifiBssidPinService::apply_pending() const
```

 

True while a change is `VERIFYING` or `ROLLING_BACK`.

   


<a id="structespectre_1_1_wifi_bssid_pin_service_config"></a>

## espectre::WifiBssidPinServiceConfig



```cpp
#include <runtime/esp_idf/wifi_bssid_pin_service.h>
```



```cpp
struct espectre::WifiBssidPinServiceConfig
```

 

Hooks that connect [WifiBssidPinService](#classespectre_1_1_wifi_bssid_pin_service) to the firmware's Wi-Fi stack.

  

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1a43cf641913174835573ac08ef3b4d420"></a>

### `ApplyCallback`


```cpp
using espectre::WifiBssidPinServiceConfig::ApplyCallback = std::function<bool(const std::string &bssid,
                                          std::string *message,
                                          bool *station_transition_started)>
```

 

Apply a BSSID pin to the station, or clear it for an empty `bssid`.

  

Return false when the pin cannot be applied, with a reason in `message`. Set `*station_transition_started` when the failure happened after the station began reconnecting, so the service waits for the previous configuration to come back. The pointer is `nullptr` during rollback.

  

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1a307fa876d73c4361b58844f74a319044"></a>

### `StationStateGetter`


```cpp
using espectre::WifiBssidPinServiceConfig::StationStateGetter = std::function<WifiBssidPinStationState()>
```

 

Read the current station state.

   

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1aa9165f343c1ff8b0386a6aac8649ff84"></a>

### `ChangeCallback`


```cpp
using espectre::WifiBssidPinServiceConfig::ChangeCallback = std::function<void()>
```

 

Notification without arguments, delivered on the owner task.

   


<a id="structespectre_1_1_wifi_bssid_pin_service_config_1a3a678d1e92866b879c0a6fed14c0a0d1"></a>

### `apply_callback`


```cpp
ApplyCallback espectre::WifiBssidPinServiceConfig::apply_callback
```

 

Required.

   

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1a7dcbfda84aa709b87ab638c4c9b11257"></a>

### `station_state_getter`


```cpp
StationStateGetter espectre::WifiBssidPinServiceConfig::station_state_getter
```

 

Required.

   

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1ab6a059f017598440ed5f032098163e05"></a>

### `prepare_callback`


```cpp
ChangeCallback espectre::WifiBssidPinServiceConfig::prepare_callback
```

 

Optional; runs before the station is reconfigured, for example to quiesce sensing.

   

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1afecd3ee11a65e73e94ba868fe1849696"></a>

### `resume_callback`


```cpp
ChangeCallback espectre::WifiBssidPinServiceConfig::resume_callback
```

 

Optional; runs when a change ends, except in `RECOVERY_REQUIRED`.

   

<a id="structespectre_1_1_wifi_bssid_pin_service_config_1a997a6e6e9b0d3f9ae139b8b14c1f2383"></a>

### `candidate_timeout_ms`


```cpp
uint32_t espectre::WifiBssidPinServiceConfig::candidate_timeout_ms {60000U}
```

 

Time allowed for the station to verify a pin, and again for a rollback.

  

Must be nonzero.

  


<a id="structespectre_1_1_wifi_bssid_pin_station_state"></a>

## espectre::WifiBssidPinStationState



```cpp
#include <runtime/esp_idf/wifi_bssid_pin_service.h>
```



```cpp
struct espectre::WifiBssidPinStationState
```

 

Station state as reported by the firmware's Wi-Fi stack.

  

<a id="structespectre_1_1_wifi_bssid_pin_station_state_1a77a4ce1f6e06efd30575a0522e4c0b14"></a>

### `configured`


```cpp
bool espectre::WifiBssidPinStationState::configured {false}
```

 

Whether the station has credentials.

   

<a id="structespectre_1_1_wifi_bssid_pin_station_state_1a6dcf90c72c8d65cd7bcafef65ea5111f"></a>

### `connected`


```cpp
bool espectre::WifiBssidPinStationState::connected {false}
```

 

Whether the station is associated.

   

<a id="structespectre_1_1_wifi_bssid_pin_station_state_1ab3cb0d1e67769e8b613f2e33ea0991ad"></a>

### `has_ipv4`


```cpp
bool espectre::WifiBssidPinStationState::has_ipv4 {false}
```

 

Whether the station holds an IPv4 address.

   

<a id="structespectre_1_1_wifi_bssid_pin_station_state_1ab9820051700cf3b76fa5deff4234bab5"></a>

### `ssid`


```cpp
std::string espectre::WifiBssidPinStationState::ssid
```

 

Provisioned network name.

   

<a id="structespectre_1_1_wifi_bssid_pin_station_state_1a6a7257e881fe796a509c6a9c6ed0ae67"></a>

### `bssid`


```cpp
std::string espectre::WifiBssidPinStationState::bssid
```

 

Current access point, as upper-case `AA:BB:CC:DD:EE:FF`.

   


<a id="structespectre_1_1_wifi_provisioning_defaults"></a>

## espectre::WifiProvisioningDefaults



```cpp
#include <runtime/esp_idf/wifi_provisioning_service.h>
```



```cpp
struct espectre::WifiProvisioningDefaults
```

 

Build-time station settings used when nothing is saved in NVS.

  

The strings are copied by load\_or\_set\_defaults(); `nullptr` means empty.

 

<a id="structespectre_1_1_wifi_provisioning_defaults_1a3a22055cc0538d86ff249966a20b1e92"></a>

### `ssid`


```cpp
const char* espectre::WifiProvisioningDefaults::ssid {nullptr}
```

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1a707b4a5359b3c35e8dc9d7e80480148b"></a>

### `password`


```cpp
const char* espectre::WifiProvisioningDefaults::password {nullptr}
```

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1a83ebf67e6dad57074c647376bb5ae8e8"></a>

### `bssid`


```cpp
const char* espectre::WifiProvisioningDefaults::bssid {nullptr}
```

 

Optional access point to pin, as `AA:BB:CC:DD:EE:FF`.

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1a35539b167d170151e209d5143a358384"></a>

### `channel`


```cpp
uint8_t espectre::WifiProvisioningDefaults::channel {0U}
```

 

Optional channel hint; [`WIFI_CHANNEL_AUTO`](#namespaceespectre_1ab18ef5b016f2a45b3e57911383e7a528) (0) scans every allowed channel.

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1ae3233820bf084e6f88f7bf85dad3ea8f"></a>

### `max_retry`


```cpp
int espectre::WifiProvisioningDefaults::max_retry {8}
```

 

Forwarded to [`StandaloneWifiConfig::max_retry`](#structespectre_1_1_standalone_wifi_config_1a0dc87d4cf1fc77af1596e504cf0a1153).

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1aa1abbc62d0564095be5d628db8f093ad"></a>

### `manage_csi_lifecycle`


```cpp
bool espectre::WifiProvisioningDefaults::manage_csi_lifecycle {false}
```

 

Forwarded to [`StandaloneWifiConfig::manage_csi_lifecycle`](#structespectre_1_1_standalone_wifi_config_1a1fa7c525d96db4d9729b0bc3be689ce2).

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1ab55754dfbbfe2c004275d70cd749f735"></a>

### `band_policy`


```cpp
WifiBandPolicy espectre::WifiProvisioningDefaults::band_policy {WifiBandPolicy::BAND_2G}
```

 

Band policy used when no saved policy exists or the saved one is unsupported.

   

<a id="structespectre_1_1_wifi_provisioning_defaults_1aa473c6cdb212af5a5ae41b8bcdd4458d"></a>

### `candidate_timeout_ms`


```cpp
uint32_t espectre::WifiProvisioningDefaults::candidate_timeout_ms {30000U}
```

 

Time allowed for a staged candidate to associate and obtain an address, and again for the rollback that follows a failure.

   


<a id="classespectre_1_1_wifi_provisioning_service"></a>

## espectre::WifiProvisioningService



```cpp
#include <runtime/esp_idf/wifi_provisioning_service.h>
```



```cpp
class espectre::WifiProvisioningService
```

 

Stores Wi-Fi credentials and applies changes with verification and rollback.

  

New credentials are staged as a candidate in NVS, applied through [StandaloneWifiService](#classespectre_1_1_standalone_wifi_service), and saved as the station configuration only after the station associates and obtains an address. A candidate that does not connect within [`WifiProvisioningDefaults::candidate_timeout_ms`](#structespectre_1_1_wifi_provisioning_defaults_1aa473c6cdb212af5a5ae41b8bcdd4458d) is rolled back to the last-known-good settings. A candidate interrupted by a reboot resumes verification at the next [load\_or\_set\_defaults()](#classespectre_1_1_wifi_provisioning_service_1a83780a13c9467f636d6df89e02b7d327).

 

**Par:** Threading

Call every method from the task that owns the [StandaloneWifiService](#classespectre_1_1_standalone_wifi_service), and call [loop()](#classespectre_1_1_wifi_provisioning_service_1a8b8c00c288e12539a262cf41d4760c72) from that task's loop. Callbacks run on that task.

 

<a id="classespectre_1_1_wifi_provisioning_service_1a783569a1db3ddc367f220380b3d394e0"></a>

### `ChangeCallback`


```cpp
using espectre::WifiProvisioningService::ChangeCallback = std::function<void()>
```

 

Notification without arguments, delivered on the owner task.

   


<a id="classespectre_1_1_wifi_provisioning_service_1a00ae7a5deaa2fbf70206a118bd63e32f"></a>

### `WifiProvisioningService`


```cpp
explicit espectre::WifiProvisioningService::WifiProvisioningService(StandaloneWifiService *wifi_manager)
```

 

Bind the service to the station it configures.

  

Not owned; it must outlive this service.

  

<a id="classespectre_1_1_wifi_provisioning_service_1a3974e07bf87f9714e0733a0b0ac30477"></a>

### `set_change_callback`


```cpp
void espectre::WifiProvisioningService::set_change_callback(ChangeCallback callback)
```

 

Called whenever the configuration, apply state, or scan results change.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a74cc326ce0bdeb9da7ed6fa8e3c63237"></a>

### `set_reconfigure_callbacks`


```cpp
void espectre::WifiProvisioningService::set_reconfigure_callbacks(ChangeCallback prepare_callback, ChangeCallback resume_callback)
```

 

Bracket every live station reconfiguration.

  

`prepare_callback` runs before the station is reconfigured, for example to quiesce sensing, and `resume_callback` runs after the station reconnects or the reconfiguration fails.

  

<a id="classespectre_1_1_wifi_provisioning_service_1a19f93cc32488b559cfc50d8bf4798c2d"></a>

### `set_scan_callbacks`


```cpp
void espectre::WifiProvisioningService::set_scan_callbacks(ChangeCallback prepare_callback, ChangeCallback resume_callback)
```

 

Bracket every access point scan, like [set\_reconfigure\_callbacks()](#classespectre_1_1_wifi_provisioning_service_1a74cc326ce0bdeb9da7ed6fa8e3c63237).

   

<a id="classespectre_1_1_wifi_provisioning_service_1aa9ed3ddf8930c9c917e849dde72718c9"></a>

### `set_apply_completed_callback`


```cpp
void espectre::WifiProvisioningService::set_apply_completed_callback(ChangeCallback callback)
```

 

Called when a staged change ends as `APPLIED` or `ROLLED_BACK`.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a83780a13c9467f636d6df89e02b7d327"></a>

### `load_or_set_defaults`


```cpp
esp_err_t espectre::WifiProvisioningService::load_or_set_defaults(const WifiProvisioningDefaults &defaults)
```

 

Load the saved configuration, or adopt `defaults` when nothing is saved.

  

An unsupported saved band policy falls back to the default, and a channel that does not match the band becomes automatic. A pending candidate left by a reboot resumes in `VERIFYING`. Load errors fall back to the defaults and are reported by [last\_load\_result()](#classespectre_1_1_wifi_provisioning_service_1abf46e703d2106f21c5583050a3d8a66b); the call itself returns `ESP_OK`.

  

<a id="classespectre_1_1_wifi_provisioning_service_1a16a9ec64e656c3de1c1db41742892481"></a>

### `setup_station`


```cpp
esp_err_t espectre::WifiProvisioningService::setup_station(const WifiProvisioningDefaults &defaults, standalone_wifi_callback_t connected_cb={}, standalone_wifi_callback_t disconnected_cb={})
```

 

Load the configuration and set up the bound [StandaloneWifiService](#classespectre_1_1_standalone_wifi_service) with it.

  

The connected callback runs after the service has checked a pending candidate. Call [StandaloneWifiService::start()](#classespectre_1_1_standalone_wifi_service_1a533d0f1dec909d9ce1580c3d23395d07) afterwards.

 

**Returns:** `ESP_ERR_INVALID_STATE` without a bound station, otherwise the result of [StandaloneWifiService::setup()](#classespectre_1_1_standalone_wifi_service_1af6031ac873d13c5c31203be7a7b24db4).

  

<a id="classespectre_1_1_wifi_provisioning_service_1a1dbc037cfb93993188c2b7db33183a1a"></a>

### `handle_command`


```cpp
bool espectre::WifiProvisioningService::handle_command(const std::string &command, std::string *message)
```

 

Run a provisioning command: `SET_WIFI_BSSID:bssid=<mac>[&force=true]` or `CLEAR_WIFI`.

  

`SET_WIFI_BSSID` pins an access point of the provisioned SSID, taking its channel from the latest scan; an empty `bssid` removes the pin. Pinning the access point already in use is saved directly unless `force` is set. `CLEAR_WIFI` erases the saved and pending configuration and leaves the station unprovisioned.

 

**Returns:** false for an unknown or malformed command, or while another change or scan is in progress. `message` receives the outcome.

  

<a id="classespectre_1_1_wifi_provisioning_service_1aba5fb367940e5c866a4ae62ed0753dd2"></a>

### `request_access_point_scan`


```cpp
bool espectre::WifiProvisioningService::request_access_point_scan(std::string *message)
```

 

Start an asynchronous scan; results are limited to the provisioned SSID.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a56081293fee4af1ea5c849d0ce43b43d"></a>

### `begin_serial_provisioning`


```cpp
bool espectre::WifiProvisioningService::begin_serial_provisioning(const std::string &ssid, const std::string &password, std::string *message)
```

 

Stage credentials received through the standard Improv Serial RPC.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a8b8c00c288e12539a262cf41d4760c72"></a>

### `loop`


```cpp
void espectre::WifiProvisioningService::loop()
```

 

Advance candidate verification and bounded rollback after Wi-Fi events.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a79c35f784213d4c5ec03db18158e2aec"></a>

### `apply_live`


```cpp
bool espectre::WifiProvisioningService::apply_live(std::string *message)
```

 

Reapply the current configuration to the station without verification.

  

**Returns:** false when the station rejects the configuration; `message` receives the outcome.

  

<a id="classespectre_1_1_wifi_provisioning_service_1a966219c8a620bb247e791797f6685c0d"></a>

### `config`


```cpp
const StoredWifiConfig & espectre::WifiProvisioningService::config() const
```

 

Configuration the station currently uses, including its password.

   

<a id="classespectre_1_1_wifi_provisioning_service_1aa4bdfeaf9f64a161badbfad96051caf5"></a>

### `password_set`


```cpp
bool espectre::WifiProvisioningService::password_set() const
```

 

Whether a password is configured, for display without exposing it.

   

<a id="classespectre_1_1_wifi_provisioning_service_1abf46e703d2106f21c5583050a3d8a66b"></a>

### `last_load_result`


```cpp
esp_err_t espectre::WifiProvisioningService::last_load_result() const
```

 

Result of the last NVS load; not `ESP_OK` when defaults replaced unreadable data.

   

<a id="classespectre_1_1_wifi_provisioning_service_1aa2477794505d74aedc6e2869800d48a7"></a>

### `apply_state`


```cpp
WifiProvisioningApplyState espectre::WifiProvisioningService::apply_state() const
```

   

<a id="classespectre_1_1_wifi_provisioning_service_1a3fd2939db9ab7ad2430888b02517894e"></a>

### `apply_message`


```cpp
const std::string & espectre::WifiProvisioningService::apply_message() const
```

 

Human-readable detail for [apply\_state()](#classespectre_1_1_wifi_provisioning_service_1aa2477794505d74aedc6e2869800d48a7).

   

<a id="classespectre_1_1_wifi_provisioning_service_1a2bfc4c97846f8b70f24d3ed25bc25a8c"></a>

### `apply_pending`


```cpp
bool espectre::WifiProvisioningService::apply_pending() const
```

 

True while a change is `VERIFYING` or `ROLLING_BACK`.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a7d349ff6069f83f6f732092975e94a46"></a>

### `scan_pending`


```cpp
bool espectre::WifiProvisioningService::scan_pending() const
```

 

True while an access point scan runs.

   

<a id="classespectre_1_1_wifi_provisioning_service_1a32582a8a2a634e845bf09eca86f55522"></a>

### `access_points`


```cpp
const std::vector< StandaloneWifiAccessPoint > & espectre::WifiProvisioningService::access_points() const
```

 

Access points of the provisioned SSID from the latest scan, strongest first.

   

<a id="classespectre_1_1_wifi_provisioning_service_1acfc4a3b903d45ff9e465dfaed1991b88"></a>

### `scan_message`


```cpp
const std::string & espectre::WifiProvisioningService::scan_message() const
```

 

Human-readable outcome of the latest scan.

   


<a id="classespectre_1_1detail_1_1_pending_event_lock"></a>

## espectre::detail::PendingEventLock



```cpp
#include <runtime/pending_event.h>
```



```cpp
class espectre::detail::PendingEventLock
```

  

<a id="classespectre_1_1detail_1_1_pending_event_lock_1a9eb49c9d794fb2eeefc06280c2615bfa"></a>

### `lock`


```cpp
void espectre::detail::PendingEventLock::lock()
```

   

<a id="classespectre_1_1detail_1_1_pending_event_lock_1a0e36600a25f78a577863faf6cdbee145"></a>

### `unlock`


```cpp
void espectre::detail::PendingEventLock::unlock()
```

   


<a id="structespectre__diagnostic__field__t"></a>

## espectre\_diagnostic\_field\_t



```cpp
#include <runtime/diagnostic_fields.h>
```



```cpp
struct espectre_diagnostic_field_t
```

  

<a id="structespectre__diagnostic__field__t_1a408388c99ede059fe9ba5d59144b843f"></a>

### `name`


```cpp
const char* espectre_diagnostic_field_t::name
```

   

<a id="structespectre__diagnostic__field__t_1a72e7dedd3d33f32ac6c053ac2f68022f"></a>

### `type`


```cpp
const char* espectre_diagnostic_field_t::type
```

   

<a id="structespectre__diagnostic__field__t_1abe5eaa83e5e4261fbffdec2ee05d346b"></a>

### `unit`


```cpp
const char* espectre_diagnostic_field_t::unit
```

   

<a id="structespectre__diagnostic__field__t_1a96265d791a592d8cb009930e8f495761"></a>

### `profiles`


```cpp
unsigned espectre_diagnostic_field_t::profiles
```

   


<a id="base__detector_8h"></a>

## base\_detector.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <algorithm>
```



```cpp
#include <limits>
```



```cpp
#include <detector_types.h>
```



```cpp
#include <detector_limits.h>
```



```cpp
#include <filters.h>
```



```cpp
#include <utils.h>
```

  [`espectre::BaseDetector`](#classespectre_1_1_base_detector)

[`espectre`](#namespaceespectre)



<a id="csi__capture__profile_8h"></a>

## csi\_capture\_profile.h



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)



<a id="csi__format_8h"></a>

## csi\_format.h



```cpp
#include <array>
```



```cpp
#include <cmath>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <cstring>
```



```cpp
#include <csi_types.h>
```



```cpp
#include <utils.h>
```

  [`espectre`](#namespaceespectre)

[`espectre::detail`](#namespaceespectre_1_1detail)



<a id="csi__raw__record_8h"></a>

## csi\_raw\_record.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```

  [`espectre::RawCsiRecordHeaderV8`](#structespectre_1_1_raw_csi_record_header_v8)

[`espectre`](#namespaceespectre)



<a id="csi__traffic__service_8h"></a>

## csi\_traffic\_service.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <runtime_config.h>
```



```cpp
#include <udp_datagram_socket.h>
```

  [`espectre::CsiTrafficServiceConfig`](#structespectre_1_1_csi_traffic_service_config)

[`espectre::ICsiTrafficGenerator`](#classespectre_1_1_i_csi_traffic_generator)

[`espectre::ICsiTrafficIngress`](#classespectre_1_1_i_csi_traffic_ingress)

[`espectre::CsiTrafficService`](#classespectre_1_1_csi_traffic_service)

[`espectre`](#namespaceespectre)



<a id="csi__types_8h"></a>

## csi\_types.h



```cpp
#include <array>
```



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)



<a id="detector__limits_8h"></a>

## detector\_limits.h



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)



<a id="detector__types_8h"></a>

## detector\_types.h

  [`espectre`](#namespaceespectre)



<a id="device__config__store_8h"></a>

## device\_config\_store.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
#include <runtime/runtime_config.h>
```

  [`espectre::StoredWifiConfig`](#structespectre_1_1_stored_wifi_config)

[`espectre`](#namespaceespectre)



<a id="device__identity_8h"></a>

## device\_identity.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```

  [`espectre`](#namespaceespectre)



<a id="diagnostic__fields_8h"></a>

## diagnostic\_fields.h

 

C-compatible metadata for the canonical device diagnostic catalog.

  

Profiles are bitmasks of the `ESPECTRE_DIAGNOSTIC_PROFILE_*` constants. Dotted field names select leaves while protocol responses retain their nested objects.

 [`espectre_diagnostic_field_t`](#structespectre__diagnostic__field__t)



<a id="diagnostic__fields_8h_1aab4accacf85c5d9df1fe8881d3e90aa1"></a>

### `ESPECTRE_DIAGNOSTIC_FIELD_COUNT`


```cpp
#define ESPECTRE_DIAGNOSTIC_FIELD_COUNT (sizeof(espectre_diagnostic_fields) / sizeof(espectre_diagnostic_fields[0]))
```

   


<a id="diagnostic__fields_8h_1a32337afdea5d0f80b050b58e9cd0c170"></a>

### `@021375134171037300010122103026273353367327044052`


```cpp
enum @021375134171037300010122103026273353367327044052
```

 

Frontend profiles a diagnostic field belongs to.

   

<a id="diagnostic__fields_8h_1a32337afdea5d0f80b050b58e9cd0c170a12caf91251d0643715d941988a7380d1"></a>

`ESPECTRE_DIAGNOSTIC_PROFILE_NATIVE = 1U`

 

Native firmware.

  

<a id="diagnostic__fields_8h_1a32337afdea5d0f80b050b58e9cd0c170a088e89a650c801504bb1c06428ab20e2"></a>

`ESPECTRE_DIAGNOSTIC_PROFILE_BRIDGE = 2U`

 

Shared Direct HTTP bridge, used by ESPHome.

  

<a id="diagnostic__fields_8h_1a32337afdea5d0f80b050b58e9cd0c170aa71d2243c1354b5c2c7acbf988471854"></a>

`ESPECTRE_DIAGNOSTIC_PROFILE_MICRO = 4U`

 

Micro-ESPectre.

  

<a id="diagnostic__fields_8h_1a32337afdea5d0f80b050b58e9cd0c170aa8a9f4128bd81cbed4061ddd8698e9d7"></a>

`ESPECTRE_DIAGNOSTIC_PROFILE_ALL = 7U`

 

Every frontend.

  


<a id="diagnostic__fields_8h_1a08e8682b5949c9c4654abaabbf7bc6bc"></a>

### `espectre_diagnostic_fields`


```cpp
const espectre_diagnostic_field_t espectre_diagnostic_fields[][]
```

 

Canonical diagnostic fields; filter by profile before exposing a catalog.

   


<a id="direct__http__protocol_8h"></a>

## direct\_http\_protocol.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <espectre_protocol.h>
```

  [`espectre::DirectRequest`](#structespectre_1_1_direct_request)

[`espectre`](#namespaceespectre)



<a id="direct__http__service_8h"></a>

## direct\_http\_service.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <direct_http_protocol.h>
```



```cpp
#include <raw_csi.h>
```

  [`espectre::DirectHttpServiceConfig`](#structespectre_1_1_direct_http_service_config)

[`espectre::DirectHttpServiceDiagnostics`](#structespectre_1_1_direct_http_service_diagnostics)

[`espectre::IDirectHttpService`](#classespectre_1_1_i_direct_http_service)

[`espectre::IDirectHttpService::DeferredRequestResult`](#structespectre_1_1_i_direct_http_service_1_1_deferred_request_result)

[`espectre`](#namespaceespectre)



<a id="direct__http__service__esp__idf_8h"></a>

## direct\_http\_service\_esp\_idf.h



```cpp
#include <array>
```



```cpp
#include <atomic>
```



```cpp
#include <deque>
```



```cpp
#include <memory>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <freertos/FreeRTOS.h>
```



```cpp
#include <freertos/semphr.h>
```



```cpp
#include <freertos/task.h>
```



```cpp
#include <core/csi_types.h>
```



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
#include <runtime/pending_event.h>
```

  [`espectre::EspIdfDirectHttpService`](#classespectre_1_1_esp_idf_direct_http_service)

[`espectre`](#namespaceespectre)



<a id="direct__wifi__snapshot__esp__idf_8h"></a>

## direct\_wifi\_snapshot\_esp\_idf.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```

  [`espectre::DirectWifiSnapshot`](#structespectre_1_1_direct_wifi_snapshot)

[`espectre`](#namespaceespectre)



<a id="espectre__banner_8h"></a>

## espectre\_banner.h

  [`espectre`](#namespaceespectre)



<a id="espectre__core__sdk_8h"></a>

## espectre\_core\_sdk.h



```cpp
#include <runtime/espectre_sdk_version.h>
```



```cpp
#include <core/espectre_log.h>
```



```cpp
#include <core/base_detector.h>
```



```cpp
#include <core/csi_format.h>
```



```cpp
#include <core/high_accuracy_detector.h>
```



```cpp
#include <core/lightweight_detector.h>
```



```cpp
#include <core/temporal_csi_sampler.h>
```

 

Core-only detector API for custom CSI capture integrations.

  

Prefer [`espectre_sdk.h`](#espectre__sdk_8h) and `RuntimeFrontendController` when ESPectre should own CSI capture, temporal admission, calibration, and event delivery. Include this facade only when the embedding firmware already implements those parts.

 

<a id="espectre__log_8h"></a>

## espectre\_log.h



```cpp
#include <cstdarg>
```



```cpp
#include <cstdint>
```

  [`espectre::LogSink`](#structespectre_1_1_log_sink)

[`espectre`](#namespaceespectre)



<a id="espectre__log_8h_1a2452a301ac5b137469ae614b74ee149c"></a>

### `ESPECTRE_LOG_AT_LEVEL`


```cpp
#define ESPECTRE_LOG_AT_LEVEL(level, tag, format, ...) do {                                                                                            \
  const char *const espectre_log_tag__ = (tag);                                                 \
  if (::espectre::log_enabled((level), espectre_log_tag__)) {                                   \
    ::espectre::detail::log_printf((level), espectre_log_tag__, __LINE__, (format),             \
                                   ##__VA_ARGS__);                                               \
  }                                                                                             \
} while (false)
```

   

<a id="espectre__log_8h_1ab36e1f3068305cde3db4c480d2fa875d"></a>

### `ESPECTRE_LOGE`


```cpp
#define ESPECTRE_LOGE(tag, format, ...) ESPECTRE_LOG_AT_LEVEL(::espectre::LogLevel::ERROR, tag, format, ##__VA_ARGS__)
```

   

<a id="espectre__log_8h_1a68a060eeeeafdb7b959a76e2333e58a8"></a>

### `ESPECTRE_LOGW`


```cpp
#define ESPECTRE_LOGW(tag, format, ...) ESPECTRE_LOG_AT_LEVEL(::espectre::LogLevel::WARNING, tag, format, ##__VA_ARGS__)
```

   

<a id="espectre__log_8h_1a7d3ba0708ef9dd2a162c694d70648dd6"></a>

### `ESPECTRE_LOGI`


```cpp
#define ESPECTRE_LOGI(tag, format, ...) ESPECTRE_LOG_AT_LEVEL(::espectre::LogLevel::INFO, tag, format, ##__VA_ARGS__)
```

   

<a id="espectre__log_8h_1acd3d41a27469c25aa5a01f0f28859b10"></a>

### `ESPECTRE_LOGD`


```cpp
#define ESPECTRE_LOGD(tag, format, ...) ESPECTRE_LOG_AT_LEVEL(::espectre::LogLevel::DEBUG, tag, format, ##__VA_ARGS__)
```

   

<a id="espectre__log_8h_1a2f6d5220e8d4a419bec05dbaaebfcc25"></a>

### `ESPECTRE_LOGV`


```cpp
#define ESPECTRE_LOGV(tag, format, ...) ESPECTRE_LOG_AT_LEVEL(::espectre::LogLevel::VERBOSE, tag, format, ##__VA_ARGS__)
```

   


<a id="espectre__mqtt__sdk_8h"></a>

## espectre\_mqtt\_sdk.h



```cpp
#include <espectre_protocol_sdk.h>
```



```cpp
#include <runtime/esp_idf/mqtt_transport_esp_idf.h>
```

 

Opt-in ESP-IDF implementation of the public MQTT transport contract.

  

Requires ESP-IDF's mqtt component and ESPECTRE\_RUNTIME\_ESP\_IDF\_MQTT\_SOURCES (or CONFIG\_ESPECTRE\_SDK\_ENABLE\_MQTT). The integrating firmware owns the transport object and drives its lifecycle. Other services do not require this facade or the MQTT stack.

 

<a id="espectre__protocol_8h"></a>

## espectre\_protocol.h



```cpp
#include <array>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <runtime_snapshot.h>
```



```cpp
#include <protocol_json.h>
```

 

Wire types and payload builders for the ESPectre Protocol.

  

The protocol is the contract between a device and whatever consumes it: MQTT topics, Direct HTTP messages, JSON payloads, and frontend extensions. It is specified in [API.md](<https://github.com/francescopace/espectre/blob/main/docs/API.md>); this header is the C++ view of that specification.

 

Use it whenever your integration should stay interoperable with the shipped clients — the CLI, Home Assistant discovery, and the web portal all speak it. The builders take a `RuntimeSnapshot` and return a serialized payload, so your transport only moves bytes and never formats them.

 

The parsers never throw: they validate and report failure through an out parameter. On failure the command parsers reset their output, keeping at most the identifiers needed for the result payload. The device configuration parsers leave their output unchanged.

 [`espectre::EspectreApiRoute`](#structespectre_1_1_espectre_api_route)

[`espectre::EspectreApiEventDescriptor`](#structespectre_1_1_espectre_api_event_descriptor)

[`espectre::EspectreExtensionRoute`](#structespectre_1_1_espectre_extension_route)

[`espectre::EspectreProtocolExtension`](#structespectre_1_1_espectre_protocol_extension)

[`espectre::EspectreCapabilityProfile`](#structespectre_1_1_espectre_capability_profile)

[`espectre::EspectreDeviceConfig`](#structespectre_1_1_espectre_device_config)

[`espectre::EspectreNetworkInfo`](#structespectre_1_1_espectre_network_info)

[`espectre::EspectreDeviceInfo`](#structespectre_1_1_espectre_device_info)

[`espectre::EspectreCommand`](#structespectre_1_1_espectre_command)

[`espectre`](#namespaceespectre)



<a id="espectre__protocol__sdk_8h"></a>

## espectre\_protocol\_sdk.h



```cpp
#include <espectre_sdk.h>
```



```cpp
#include <runtime/diagnostic_fields.h>
```



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
#include <runtime/mqtt_transport.h>
```



```cpp
#include <runtime/protocol_json.h>
```



```cpp
#include <runtime/runtime_diagnostics_protocol.h>
```

 

The ESPectre Protocol: messages, JSON, diagnostics, and transports.

  

Includes the sensing SDK plus the canonical protocol messages, their JSON form, the diagnostic field catalog, and the Direct HTTP and MQTT transport contracts you implement to reach your own transports. Include it only when your firmware speaks the ESPectre Protocol; the services and MQTT facades include it for you.

 

<a id="espectre__sdk_8h"></a>

## espectre\_sdk.h



```cpp
#include <runtime/espectre_sdk_version.h>
```



```cpp
#include <core/espectre_log.h>
```



```cpp
#include <runtime/csi_capture_profile.h>
```



```cpp
#include <runtime/runtime_capabilities.h>
```



```cpp
#include <runtime/runtime_config_utils.h>
```



```cpp
#include <runtime/runtime_diagnostics.h>
```



```cpp
#include <runtime/runtime_events.h>
```



```cpp
#include <runtime/runtime_config.h>
```



```cpp
#include <runtime/raw_csi.h>
```



```cpp
#include <runtime/runtime_sensing_schema.h>
```



```cpp
#include <runtime/runtime_snapshot.h>
```



```cpp
#include <runtime/esp_idf/device_identity.h>
```



```cpp
#include <runtime/esp_idf/runtime_frontend_controller.h>
```



```cpp
#include <runtime/esp_idf/runtime_sensing_kconfig.h>
```

 

The public ESPectre integration surface, in one include.

  

ESPectre turns ordinary Wi-Fi traffic into a motion signal: it captures Channel State Information from the radio, extracts features, and reports a debounced motion state. This header is the supported entry point for firmware that embeds the sensing engine in its own application.

 

```cpp
#include "espectre_sdk.h"

class ProductFrontend : public espectre::IRuntimeListener {
 public:
  bool setup() {
    espectre::RuntimeConfig config;  // documented defaults, ready to use
    runtime_.set_config(config);
    return runtime_.setup(this);
  }

  void loop() { runtime_.loop(); }

  void on_motion_state_changed(const espectre::RuntimeSnapshot &snapshot) override {
    if (!snapshot.ready_to_publish) return;
    publish(snapshot.motion_state == espectre::MotionState::MOTION);
  }

 private:
  espectre::RuntimeFrontendController runtime_;
};
```

 

<a id="espectre__sdk_8h_1sdk_paths"></a>

### Two integration paths



- **Full runtime (recommended).** Your firmware owns boot, provisioning, networking, OTA, and the product surface. ESPectre owns Wi-Fi CSI capture, calibration, detection, and eventing behind [`espectre::RuntimeFrontendController`](#classespectre_1_1_runtime_frontend_controller) and [`espectre::IRuntimeListener`](#classespectre_1_1_i_runtime_listener). Requires ESP-IDF &gt;= 5.5.3.

- **Core-only.** Your firmware already captures CSI. Include [`espectre_core_sdk.h`](#espectre__core__sdk_8h) and drive [`espectre::LightweightDetector`](#classespectre_1_1_lightweight_detector) or [`espectre::HighAccuracyDetector`](#classespectre_1_1_high_accuracy_detector) directly. `runtime/esp_idf/csi_pipeline.cpp` is the reference for normalization, evaluation cadence, and hit filtering.

 

<a id="espectre__sdk_8h_1sdk_threading"></a>

### Threading contract



The control surface is single-owner. Internal bounded mailboxes protect callback-to-loop handoff, but they do not make control calls thread-safe.



- Run `setup()`, `loop()`, and `shutdown()` on one task. These are the calls that build and tear down runtime state, and they are not safe to race.

- Every `IRuntimeListener` callback is delivered on the caller's task: from `loop()` for sensing events, or inline on the task that invoked a control method. Work raised in the Wi-Fi CSI callback is deferred through an internal mailbox first, so no listener callback runs in interrupt or Wi-Fi driver context.

- Keep callbacks bounded and non-blocking. Slow work delays `loop()` and can fill the bounded CSI mailbox, dropping incoming frames. Queue network I/O, NVS writes, and other blocking work for another task.

- Call the controller setters only from the owner task. Queue commands received by network callbacks and apply them from that task's loop.

- Do not drive the controller from inside `on_runtime_fault()` beyond `shutdown()`.

- Raw CSI packet callbacks are the deliberate exception to listener delivery: they run synchronously in Wi-Fi capture context. Keep them bounded, non-blocking, and allocation-free; see `raw_csi_packet_callback_t`.

 

<a id="espectre__sdk_8h_1sdk_versioning"></a>

### Versioning



[`ESPECTRE_SDK_VERSION_STRING`](#espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74) and [`ESPECTRE_SDK_VERSION_AT_LEAST()`](#espectre__sdk__version_8h_1a84f438434c7a7b020e175e84ae3ca6e8) identify the SDK sources you compiled against. See [`runtime/espectre_sdk_version.h`](#espectre__sdk__version_8h) for how that differs from your firmware version.

 

<a id="espectre__sdk_8h_1sdk_stability"></a>

### Stability tiers



Everything reachable from this header is the stable runtime surface and follows the SDK version contract. The opt-in [`espectre_core_sdk.h`](#espectre__core__sdk_8h) facade is the lower-level detector extension. The opt-in [`espectre_protocol_sdk.h`](#espectre__protocol__sdk_8h) facade adds the protocol and transport contracts. The optional services and MQTT facades expose supported ESP-IDF integration contracts. Headers included only as implementation dependencies can change in any release. See [Versioning](#sdk_integration_1integration_versioning) for the exact guarantees.

 

<a id="espectre__sdk_8h_1sdk_licensing"></a>

### Licensing



ESPectre is dual-licensed: GPLv3, or a separately offered commercial license for proprietary firmware. See `LICENSING.md`.

 

<a id="espectre__sdk__version_8h"></a>

## espectre\_sdk\_version.h

 

Compile-time identity of the ESPectre SDK sources you compiled against.

  

This is the version of the *SDK*, not of your firmware. The two are deliberately separate:

 

- [`ESPECTRE_SDK_VERSION_STRING`](#espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74) is baked in at compile time and identifies the ESPectre sources in your build. Use it in diagnostics, bug reports, and to guard code against SDK releases.

- The *application* version is supplied to the runtime by the frontend or integrator. In an integration it is your product's version, not ESPectre's.

 

Published SDK bundles stamp their identity into this header. Integrators can supply all four version macros at compile time to override the package. The SDK does not inspect Git, environment variables, or firmware metadata. Missing or incomplete metadata defaults to 0.0.0, meaning an unknown SDK version. Its numeric macros are zero, so checks for newer releases are false.

 [`espectre`](#namespaceespectre)



<a id="espectre__sdk__version_8h_1a1c56ebb77dae087ea795df71afe1b36a"></a>

### `ESPECTRE_SDK_VERSION_MAJOR`


```cpp
#define ESPECTRE_SDK_VERSION_MAJOR 3
```

   

<a id="espectre__sdk__version_8h_1ab49f9a44dcd3be82d3b3e742d9334c23"></a>

### `ESPECTRE_SDK_VERSION_MINOR`


```cpp
#define ESPECTRE_SDK_VERSION_MINOR 0
```

   

<a id="espectre__sdk__version_8h_1a74f3ae0b42f726bf3302abae42655339"></a>

### `ESPECTRE_SDK_VERSION_PATCH`


```cpp
#define ESPECTRE_SDK_VERSION_PATCH 0
```

   

<a id="espectre__sdk__version_8h_1a63ca6448380d44c069980a49a9584c74"></a>

### `ESPECTRE_SDK_VERSION_STRING`


```cpp
#define ESPECTRE_SDK_VERSION_STRING "3.0.0-rc2-53-gbf4ad78.develop"
```

   

<a id="espectre__sdk__version_8h_1addabd247bcb8243d35a37657c029571b"></a>

### `ESPECTRE_SDK_VERSION_NUMBER`


```cpp
#define ESPECTRE_SDK_VERSION_NUMBER ((ESPECTRE_SDK_VERSION_MAJOR * 10000) + (ESPECTRE_SDK_VERSION_MINOR * 100) + ESPECTRE_SDK_VERSION_PATCH)
```

 

Legacy packed numeric identity for the SDK version, as `MMmmpp`.

  

Example: `3.0.0` becomes `30000`. Retained for compatibility and compact telemetry; do not use it for ordering because components are not limited to two digits. Use [`ESPECTRE_SDK_VERSION_AT_LEAST()`](#espectre__sdk__version_8h_1a84f438434c7a7b020e175e84ae3ca6e8) for feature guards.

  

<a id="espectre__sdk__version_8h_1a84f438434c7a7b020e175e84ae3ca6e8"></a>

### `ESPECTRE_SDK_VERSION_AT_LEAST`


```cpp
#define ESPECTRE_SDK_VERSION_AT_LEAST(major, minor, patch) ((ESPECTRE_SDK_VERSION_MAJOR > (major)) ||                               \
 (ESPECTRE_SDK_VERSION_MAJOR == (major) &&                              \
  (ESPECTRE_SDK_VERSION_MINOR > (minor) ||                              \
   (ESPECTRE_SDK_VERSION_MINOR == (minor) &&                            \
    ESPECTRE_SDK_VERSION_PATCH >= (patch)))))
```

 

Compile-time feature guard.

  

Use it to keep one integration compiling against several SDK releases:

 

```cpp
#if ESPECTRE_SDK_VERSION_AT_LEAST(3, 1, 0)
  // Use an API introduced in 3.1.0.
#else
  // Keep the equivalent behavior for earlier SDK releases.
#endif
```

  


<a id="espectre__services__sdk_8h"></a>

## espectre\_services\_sdk.h



```cpp
#include <espectre_protocol_sdk.h>
```



```cpp
#include <runtime/esp_idf/device_config_store.h>
```



```cpp
#include <runtime/esp_idf/direct_http_service_esp_idf.h>
```



```cpp
#include <runtime/esp_idf/direct_wifi_snapshot_esp_idf.h>
```



```cpp
#include <runtime/esp_idf/frontend_bootstrap_helpers.h>
```



```cpp
#include <runtime/esp_idf/frontend_ha_mqtt_helpers.h>
```



```cpp
#include <runtime/esp_idf/frontend_mqtt_helpers.h>
```



```cpp
#include <runtime/esp_idf/mdns_bootstrap_responder.h>
```



```cpp
#include <runtime/esp_idf/mdns_discovery_service.h>
```



```cpp
#include <runtime/esp_idf/network_traffic.h>
```



```cpp
#include <runtime/esp_idf/nvs_helpers.h>
```



```cpp
#include <runtime/esp_idf/peer_discovery_service_esp_idf.h>
```



```cpp
#include <runtime/esp_idf/raw_csi_session_controller.h>
```



```cpp
#include <runtime/esp_idf/runtime_direct_http_bridge.h>
```



```cpp
#include <runtime/esp_idf/standalone_wifi_service.h>
```



```cpp
#include <runtime/esp_idf/task_scheduling_config.h>
```



```cpp
#include <runtime/esp_idf/traffic_generator_manager.h>
```



```cpp
#include <runtime/esp_idf/wifi_band_helpers.h>
```



```cpp
#include <runtime/esp_idf/wifi_bssid_pin_service.h>
```



```cpp
#include <runtime/esp_idf/wifi_provisioning_service.h>
```



```cpp
#include <runtime/espectre_banner.h>
```



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
#include <runtime/peer_discovery.h>
```



```cpp
#include <runtime/pending_event.h>
```



```cpp
#include <runtime/pending_queue.h>
```



```cpp
#include <runtime/runtime_event_mailbox.h>
```



```cpp
#include <runtime/runtime_time.h>
```

 

Optional services for firmware integrating the ESPectre runtime.

  

Includes the sensing SDK and the supported command, transport, discovery, provisioning, and bootstrap services. Compile only the capability source groups that your firmware uses; including this facade does not enable them. Requires the ESP-IDF platform headers and declared component dependencies. Firmware owns networking, service lifetime, task policy, and the allocation of each service object.

 

<a id="filter__config_8h"></a>

## filter\_config.h



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)



<a id="frontend__bootstrap__helpers_8h"></a>

## frontend\_bootstrap\_helpers.h



```cpp
#include <cstdint>
```



```cpp
#include <device_identity.h>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <runtime/espectre_protocol.h>
```



```cpp
#include <standalone_wifi_service.h>
```



```cpp
#include <wifi_provisioning_service.h>
```

  [`espectre::FrontendDeviceConfigDefaults`](#structespectre_1_1_frontend_device_config_defaults)

[`espectre::FrontendWifiStationOptions`](#structespectre_1_1_frontend_wifi_station_options)

[`espectre`](#namespaceespectre)



<a id="frontend__command__engine_8h"></a>

## frontend\_command\_engine.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <espectre_protocol.h>
```



```cpp
#include <runtime_config_utils.h>
```

  [`espectre::FrontendCommandContext`](#structespectre_1_1_frontend_command_context)

[`espectre::FrontendCommandResult`](#structespectre_1_1_frontend_command_result)

[`espectre::FrontendCommandEngine`](#classespectre_1_1_frontend_command_engine)

[`espectre`](#namespaceespectre)



<a id="frontend__ha__mqtt__helpers_8h"></a>

## frontend\_ha\_mqtt\_helpers.h



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <runtime/espectre_protocol.h>
```

  [`espectre::FrontendHaDiagnosticSensor`](#structespectre_1_1_frontend_ha_diagnostic_sensor)

[`espectre::FrontendHaMqttSettings`](#structespectre_1_1_frontend_ha_mqtt_settings)

[`espectre::FrontendHaDiscoveryMessage`](#structespectre_1_1_frontend_ha_discovery_message)

[`espectre`](#namespaceespectre)



<a id="frontend__mqtt__helpers_8h"></a>

## frontend\_mqtt\_helpers.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
#include <runtime/mqtt_transport.h>
```

  [`espectre`](#namespaceespectre)



<a id="high__accuracy__detector_8h"></a>

## high\_accuracy\_detector.h



```cpp
#include <base_detector.h>
```



```cpp
#include <csi_format.h>
```



```cpp
#include <csi_features.h>
```



```cpp
#include <filtered_turbulence_ring.h>
```



```cpp
#include <l1_delta_tracker.h>
```



```cpp
#include <ml_feature_trackers.h>
```



```cpp
#include <cstdint>
```



```cpp
#include <cstddef>
```

  [`espectre::HighAccuracyDetector`](#classespectre_1_1_high_accuracy_detector)

[`espectre`](#namespaceespectre)



<a id="lightweight__detector_8h"></a>

## lightweight\_detector.h



```cpp
#include <base_detector.h>
```



```cpp
#include <csi_format.h>
```



```cpp
#include <csi_features.h>
```



```cpp
#include <filtered_turbulence_ring.h>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <memory>
```

  [`espectre::LightweightDetector`](#classespectre_1_1_lightweight_detector)

[`espectre`](#namespaceespectre)



<a id="mdns__bootstrap__responder_8h"></a>

## mdns\_bootstrap\_responder.h



```cpp
#include <array>
```



```cpp
#include <atomic>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```

  [`espectre::MdnsBootstrapResponder`](#classespectre_1_1_mdns_bootstrap_responder)

[`espectre`](#namespaceespectre)



<a id="mdns__discovery__service_8h"></a>

## mdns\_discovery\_service.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <utility>
```



```cpp
#include <vector>
```

  [`espectre::MdnsDiscoveryServiceConfig`](#structespectre_1_1_mdns_discovery_service_config)

[`espectre::MdnsDiscoveryService`](#classespectre_1_1_mdns_discovery_service)

[`espectre`](#namespaceespectre)



<a id="mqtt__payload__assembler_8h"></a>

## mqtt\_payload\_assembler.h



```cpp
#include <array>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstring>
```



```cpp
#include <string_view>
```



```cpp
#include <espectre_protocol.h>
```

  [`espectre::MqttPayloadAssembler`](#classespectre_1_1_mqtt_payload_assembler)

[`espectre`](#namespaceespectre)



<a id="mqtt__transport_8h"></a>

## mqtt\_transport.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <espectre_protocol.h>
```

  [`espectre::MqttTransportDiagnostics`](#structespectre_1_1_mqtt_transport_diagnostics)

[`espectre::IMqttTransport`](#classespectre_1_1_i_mqtt_transport)

[`espectre`](#namespaceespectre)



<a id="mqtt__transport__esp__idf_8h"></a>

## mqtt\_transport\_esp\_idf.h



```cpp
#include <array>
```



```cpp
#include <atomic>
```



```cpp
#include <deque>
```



```cpp
#include <memory>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <runtime/mqtt_transport.h>
```



```cpp
#include <runtime/mqtt_payload_assembler.h>
```



```cpp
#include <runtime/pending_event.h>
```



```cpp
#include <runtime/pending_queue.h>
```



```cpp
#include <mqtt_client.h>
```

  [`espectre::EspIdfMqttTransport`](#classespectre_1_1_esp_idf_mqtt_transport)

[`espectre`](#namespaceespectre)



<a id="network__traffic_8h"></a>

## network\_traffic.h



```cpp
#include <cstdint>
```



```cpp
#include <esp_err.h>
```

  [`espectre::NetworkTrafficSnapshot`](#structespectre_1_1_network_traffic_snapshot)

[`espectre`](#namespaceespectre)



<a id="nvs__helpers_8h"></a>

## nvs\_helpers.h



```cpp
#include <esp_err.h>
```

  [`espectre`](#namespaceespectre)



<a id="peer__discovery_8h"></a>

## peer\_discovery.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```

  [`espectre::PeerDiscoveryCandidate`](#structespectre_1_1_peer_discovery_candidate)

[`espectre::PeerDiscoverySnapshot`](#structespectre_1_1_peer_discovery_snapshot)

[`espectre::IPeerDiscoveryService`](#classespectre_1_1_i_peer_discovery_service)

[`espectre`](#namespaceespectre)



<a id="peer__discovery__service__esp__idf_8h"></a>

## peer\_discovery\_service\_esp\_idf.h



```cpp
#include <runtime/peer_discovery.h>
```

  [`espectre::EspIdfPeerDiscoveryService`](#classespectre_1_1_esp_idf_peer_discovery_service)

[`espectre`](#namespaceespectre)



<a id="peer__discovery__service__esp__idf_8h_1a117010e231eeb226e391046f9eb7d2b5"></a>

### `mdns_result_t`


```cpp
typedef struct mdns_result_s mdns_result_t
```

   

<a id="peer__discovery__service__esp__idf_8h_1a8815240672c5880e798ca6655309c589"></a>

### `mdns_search_once_t`


```cpp
typedef struct mdns_search_once_s mdns_search_once_t
```

   


<a id="pending__event_8h"></a>

## pending\_event.h



```cpp
#include <cstddef>
```



```cpp
#include <mutex>
```



```cpp
#include <freertos/FreeRTOS.h>
```



```cpp
#include <freertos/portmacro.h>
```



```cpp
#include <tuple>
```



```cpp
#include <utility>
```

  [`espectre::detail::PendingEventLock`](#classespectre_1_1detail_1_1_pending_event_lock)

[`espectre::PendingEvent`](#classespectre_1_1_pending_event)

[`espectre`](#namespaceespectre)

[`espectre::detail`](#namespaceespectre_1_1detail)



<a id="pending__queue_8h"></a>

## pending\_queue.h



```cpp
#include <array>
```



```cpp
#include <cstddef>
```



```cpp
#include <mutex>
```



```cpp
#include <type_traits>
```



```cpp
#include <pending_event.h>
```

  [`espectre::PendingQueue`](#classespectre_1_1_pending_queue)

[`espectre`](#namespaceespectre)



<a id="protocol__json_8h"></a>

## protocol\_json.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <utility>
```



```cpp
#include <vector>
```

  [`espectre::JsonObjectField`](#structespectre_1_1_json_object_field)

[`espectre::JsonInput`](#classespectre_1_1_json_input)

[`espectre::JsonFieldView`](#structespectre_1_1_json_field_view)

[`espectre`](#namespaceespectre)



<a id="raw__csi_8h"></a>

## raw\_csi.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <csi_raw_record.h>
```

  [`espectre::RawCsiPacketView`](#structespectre_1_1_raw_csi_packet_view)

[`espectre::RawCsiHttpFramePrefix`](#structespectre_1_1_raw_csi_http_frame_prefix)

[`espectre::RawCsiSessionConfig`](#structespectre_1_1_raw_csi_session_config)

[`espectre::RawCsiSessionDiagnostics`](#structespectre_1_1_raw_csi_session_diagnostics)

[`espectre`](#namespaceespectre)



<a id="raw__csi__session__controller_8h"></a>

## raw\_csi\_session\_controller.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
#include <runtime_frontend_controller.h>
```

  [`espectre::RawCsiSessionController`](#classespectre_1_1_raw_csi_session_controller)

[`espectre`](#namespaceespectre)



<a id="runtime__capabilities_8h"></a>

## runtime\_capabilities.h

  [`espectre::RuntimeCapabilities`](#structespectre_1_1_runtime_capabilities)

[`espectre`](#namespaceespectre)



<a id="runtime__config_8h"></a>

## runtime\_config.h



```cpp
#include <cstdint>
```



```cpp
#include <string>
```



```cpp
#include <csi_capture_profile.h>
```



```cpp
#include <runtime_sensing_schema.h>
```

 

Runtime configuration handed to `RuntimeFrontendController`.

  [`espectre::RuntimeConfig`](#structespectre_1_1_runtime_config)

[`espectre`](#namespaceespectre)



<a id="runtime__config__utils_8h"></a>

## runtime\_config\_utils.h



```cpp
#include <runtime_config.h>
```



```cpp
#include <runtime_snapshot.h>
```

  [`espectre::RuntimeControlUpdate`](#structespectre_1_1_runtime_control_update)

[`espectre`](#namespaceespectre)



<a id="runtime__diagnostics_8h"></a>

## runtime\_diagnostics.h



```cpp
#include <cstdint>
```



```cpp
#include <runtime_snapshot.h>
```

  [`espectre::RuntimeDiagnosticsSample`](#structespectre_1_1_runtime_diagnostics_sample)

[`espectre::RuntimeDiagnosticsSampler`](#classespectre_1_1_runtime_diagnostics_sampler)

[`espectre`](#namespaceespectre)



<a id="runtime__diagnostics__protocol_8h"></a>

## runtime\_diagnostics\_protocol.h



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <diagnostic_fields.h>
```



```cpp
#include <runtime_diagnostics.h>
```



```cpp
#include <runtime_snapshot.h>
```

 

Diagnostic field selection and JSON serialization for protocol responses.

  [`espectre`](#namespaceespectre)



<a id="runtime__direct__http__bridge_8h"></a>

## runtime\_direct\_http\_bridge.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <runtime/direct_http_service.h>
```



```cpp
#include <direct_wifi_snapshot_esp_idf.h>
```



```cpp
#include <runtime/frontend_command_engine.h>
```



```cpp
#include <runtime/peer_discovery.h>
```



```cpp
#include <raw_csi_session_controller.h>
```



```cpp
#include <runtime/runtime_diagnostics.h>
```



```cpp
#include <runtime/runtime_event_mailbox.h>
```



```cpp
#include <runtime_frontend_controller.h>
```



```cpp
#include <atomic>
```

  [`espectre::RuntimeDirectHttpBridgeConfig`](#structespectre_1_1_runtime_direct_http_bridge_config)

[`espectre::RuntimeDirectHttpBridge`](#classespectre_1_1_runtime_direct_http_bridge)

[`espectre`](#namespaceespectre)



<a id="runtime__event__mailbox_8h"></a>

## runtime\_event\_mailbox.h



```cpp
#include <array>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <mutex>
```



```cpp
#include <type_traits>
```



```cpp
#include <freertos/FreeRTOS.h>
```



```cpp
#include <freertos/portmacro.h>
```



```cpp
#include <runtime_snapshot.h>
```

  [`espectre::RuntimeEventMailbox`](#classespectre_1_1_runtime_event_mailbox)

[`espectre`](#namespaceespectre)



<a id="runtime__events_8h"></a>

## runtime\_events.h



```cpp
#include <cstdint>
```



```cpp
#include <runtime_snapshot.h>
```

  [`espectre::IRuntimeListener`](#classespectre_1_1_i_runtime_listener)

[`espectre`](#namespaceespectre)



<a id="runtime__frontend__controller_8h"></a>

## runtime\_frontend\_controller.h



```cpp
#include <memory>
```



```cpp
#include <string>
```



```cpp
#include <core/csi_types.h>
```



```cpp
#include <runtime/raw_csi.h>
```



```cpp
#include <runtime/runtime_capabilities.h>
```



```cpp
#include <runtime/runtime_events.h>
```



```cpp
#include <runtime/runtime_config.h>
```



```cpp
#include <runtime/runtime_config_utils.h>
```



```cpp
#include <runtime/runtime_snapshot.h>
```

  [`espectre::RuntimeFrontendController`](#classespectre_1_1_runtime_frontend_controller)

[`espectre`](#namespaceespectre)



<a id="runtime__sensing__kconfig_8h"></a>

## runtime\_sensing\_kconfig.h



```cpp
#include <runtime/runtime_config.h>
```

  [`espectre`](#namespaceespectre)



<a id="runtime__sensing__schema_8h"></a>

## runtime\_sensing\_schema.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <core/detector_limits.h>
```



```cpp
#include <core/detector_types.h>
```



```cpp
#include <core/filter_config.h>
```

 

The schema behind `RuntimeConfig`: enums, defaults, and valid ranges.

  

This is the single source of truth for what a sensing configuration may contain. Every tunable is declared as a `RUNTIME_<FIELD>_DEFAULT` plus, where a range applies, `_MIN` and `_MAX`. Read them instead of hardcoding limits, so a UI, a provisioning flow, or a config parser stays correct across SDK releases.

 [`espectre`](#namespaceespectre)



<a id="runtime__snapshot_8h"></a>

## runtime\_snapshot.h



```cpp
#include <cstdint>
```



```cpp
#include <csi_capture_profile.h>
```



```cpp
#include <core/csi_types.h>
```



```cpp
#include <core/detector_types.h>
```



```cpp
#include <runtime_sensing_schema.h>
```

  [`espectre::RuntimeDiagnosticsSnapshot`](#structespectre_1_1_runtime_diagnostics_snapshot)

[`espectre::RuntimeDiagnosticsSnapshot::Link`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_link)

[`espectre::RuntimeDiagnosticsSnapshot::Traffic`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_traffic)

[`espectre::RuntimeDiagnosticsSnapshot::Csi`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_csi)

[`espectre::RuntimeDiagnosticsSnapshot::Platform`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_platform)

[`espectre::RuntimeDiagnosticsSnapshot::Performance`](#structespectre_1_1_runtime_diagnostics_snapshot_1_1_performance)

[`espectre::RuntimeSnapshot`](#structespectre_1_1_runtime_snapshot)

[`espectre`](#namespaceespectre)



<a id="runtime__time_8h"></a>

## runtime\_time.h



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)



<a id="standalone__wifi__service_8h"></a>

## standalone\_wifi\_service.h



```cpp
#include <atomic>
```



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <vector>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <esp_event.h>
```



```cpp
#include <runtime/pending_queue.h>
```



```cpp
#include <wifi_lifecycle.h>
```

  [`espectre::StandaloneWifiAccessPoint`](#structespectre_1_1_standalone_wifi_access_point)

[`espectre::StandaloneWifiConfig`](#structespectre_1_1_standalone_wifi_config)

[`espectre::StandaloneWifiInfo`](#structespectre_1_1_standalone_wifi_info)

[`espectre::StandaloneWifiService`](#classespectre_1_1_standalone_wifi_service)

[`espectre`](#namespaceespectre)



<a id="task__scheduling__config_8h"></a>

## task\_scheduling\_config.h



```cpp
#include <cstdint>
```

  [`espectre`](#namespaceespectre)

[`espectre::task_scheduling`](#namespaceespectre_1_1task__scheduling)



<a id="task__scheduling__config_8h_1a1c07ae2423b6566d454316bfd9a8dcfa"></a>

### `CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITY`


```cpp
#define CONFIG_ESPECTRE_DIRECT_HTTPD_TASK_PRIORITY 1
```

   

<a id="task__scheduling__config_8h_1ab21ce3fdcc4837c2a0aecb8b3b58ca04"></a>

### `CONFIG_ESPECTRE_DIRECT_WORKER_TASK_PRIORITY`


```cpp
#define CONFIG_ESPECTRE_DIRECT_WORKER_TASK_PRIORITY 2
```

   

<a id="task__scheduling__config_8h_1ac541f938b4a9aee9eb3e7edc08296acd"></a>

### `CONFIG_ESPECTRE_RAW_WORKER_TASK_PRIORITY`


```cpp
#define CONFIG_ESPECTRE_RAW_WORKER_TASK_PRIORITY 3
```

   

<a id="task__scheduling__config_8h_1a89bc52af94882fc610139f6ac25a80c8"></a>

### `CONFIG_ESPECTRE_TRAFFIC_TASK_PRIORITY`


```cpp
#define CONFIG_ESPECTRE_TRAFFIC_TASK_PRIORITY 1
```

   

<a id="task__scheduling__config_8h_1a65ef855cbf111fd59288804c825dac19"></a>

### `CONFIG_ESPECTRE_NATIVE_LOOP_TASK_PRIORITY`


```cpp
#define CONFIG_ESPECTRE_NATIVE_LOOP_TASK_PRIORITY 5
```

   


<a id="temporal__csi__sampler_8h"></a>

## temporal\_csi\_sampler.h



```cpp
#include <cstdint>
```



```cpp
#include <memory>
```

  [`espectre::TemporalCsiSampler`](#classespectre_1_1_temporal_csi_sampler)

[`espectre`](#namespaceespectre)



<a id="traffic__generator__manager_8h"></a>

## traffic\_generator\_manager.h



```cpp
#include <atomic>
```



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```



```cpp
#include <sys/types.h>
```



```cpp
#include <freertos/FreeRTOS.h>
```



```cpp
#include <freertos/task.h>
```



```cpp
#include <runtime/csi_traffic_service.h>
```

 

ESP-IDF managed traffic for firmware that owns its CSI capture path.

  

Link ESPECTRE\_RUNTIME\_ESP\_IDF\_TRAFFIC\_SOURCES and its ESP-IDF dependencies. The firmware owns the object and calls stop() before destroying it or tearing down Wi-Fi. Call lifecycle and control methods from one owner task.

 [`espectre::TrafficGeneratorManager`](#classespectre_1_1_traffic_generator_manager)

[`espectre`](#namespaceespectre)



<a id="udp__datagram__socket_8h"></a>

## udp\_datagram\_socket.h



```cpp
#include <cstddef>
```



```cpp
#include <cstdint>
```

  [`espectre::UdpDatagramPeer`](#structespectre_1_1_udp_datagram_peer)

[`espectre::IUdpDatagramSocket`](#classespectre_1_1_i_udp_datagram_socket)

[`espectre`](#namespaceespectre)



<a id="wifi__band__helpers_8h"></a>

## wifi\_band\_helpers.h



```cpp
#include <sdkconfig.h>
```



```cpp
#include <runtime/runtime_config.h>
```

  [`espectre`](#namespaceespectre)



<a id="wifi__band__helpers_8h_1ae6a8d194706e2fb61b9b2eca0485388e"></a>

### `ESPECTRE_WIFI_DUAL_BAND`


```cpp
#define ESPECTRE_WIFI_DUAL_BAND 0
```

   


<a id="wifi__bssid__pin__service_8h"></a>

## wifi\_bssid\_pin\_service.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <esp_err.h>
```

  [`espectre::WifiBssidPinStationState`](#structespectre_1_1_wifi_bssid_pin_station_state)

[`espectre::WifiBssidPinServiceConfig`](#structespectre_1_1_wifi_bssid_pin_service_config)

[`espectre::WifiBssidPinService`](#classespectre_1_1_wifi_bssid_pin_service)

[`espectre`](#namespaceespectre)



<a id="wifi__lifecycle_8h"></a>

## wifi\_lifecycle.h



```cpp
#include <atomic>
```



```cpp
#include <cstdint>
```



```cpp
#include <esp_event.h>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <esp_netif.h>
```



```cpp
#include <esp_wifi.h>
```



```cpp
#include <functional>
```



```cpp
#include <runtime/pending_queue.h>
```



```cpp
#include <runtime/runtime_config.h>
```

  [`espectre::WiFiLifecycleManager`](#classespectre_1_1_wi_fi_lifecycle_manager)

[`espectre`](#namespaceespectre)



<a id="wifi__provisioning__service_8h"></a>

## wifi\_provisioning\_service.h



```cpp
#include <cstdint>
```



```cpp
#include <functional>
```



```cpp
#include <string>
```



```cpp
#include <device_config_store.h>
```



```cpp
#include <esp_err.h>
```



```cpp
#include <standalone_wifi_service.h>
```

  [`espectre::WifiProvisioningDefaults`](#structespectre_1_1_wifi_provisioning_defaults)

[`espectre::WifiProvisioningService`](#classespectre_1_1_wifi_provisioning_service)

[`espectre`](#namespaceespectre)

Links

Maintainer

  • Francesco Pace <francesco.pace@espectre.dev>
To add this component to your project, run:

idf.py add-dependency "francescopace/espectre^3.0.0-rc2-53-gbf4ad78.develop"

download archive

Stats

  • Archive size
    Archive size ~ 512.51 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

francescopace/espectre version: 3.0.0-rc2-53-gbf4ad78.develop
|