ESPectre evaluation_interval vs publish_interval: Tuning Motion Detection and MQTT Reporting

The evaluation_interval controls how often the motion detector processes CSI packets to update its internal state, while publish_interval controls how frequently those detection results are transmitted via MQTT to Home Assistant.

The francescopace/espectre project implements Wi-Fi sensing-based presence detection for ESPHome, using these two independent parameters to decouple algorithmic responsiveness from network traffic. Understanding the distinction between evaluation_interval and publish_interval allows you to optimize detection latency without overwhelming your MQTT broker.

What Is evaluation_interval?

The evaluation_interval defines the cadence at which the motion detection algorithm recomputes variance and movement scores. In components/espectre/espectre.h, this value is stored as evaluation_interval_ with a default of 25 packets:

// components/espectre/espectre.h (lines 100-101)
uint32_t evaluation_interval_{25};   // default detector evaluation cadence
uint32_t publish_interval_{100};     // default MQTT publish cadence

The constructor in components/espectre/espectre.cpp propagates this value to the CSI manager at line 115:

this->csi_manager_.set_evaluation_interval(this->evaluation_interval_);

Inside components/espectre/csi_manager.cpp, the manager increments packets_since_evaluation_ on every received packet. When this counter meets or exceeds evaluation_interval_, the detector executes:

// components/espectre/csi_manager.cpp (line 198)
packets_since_evaluation_++;
bool should_evaluate = should_publish || packets_since_evaluation_ >= evaluation_interval_;

After evaluation completes, the counter resets to zero (line 206), and the cycle repeats. Lower values increase responsiveness to rapid movements but consume more CPU cycles per second.

What Is publish_interval?

The publish_interval governs how often the system emits MQTT messages containing the latest detection results. Stored as publish_interval_ in the same header class, this defaults to 100 packets—four times less frequent than evaluation by default—to prevent network congestion.

The Python MQTT command builder in micro-espectre/src/mqtt/commands.py explicitly includes both intervals in the payload dictionary (lines 69-71):

payload["evaluation_interval"] = config.EVALUATION_INTERVAL  # 25

payload["publish_interval"]    = config.PUBLISH_INTERVAL    # 100

Unlike evaluation_interval, which drives the motion detection logic, publish_interval only affects the transmission layer. The CSI manager maintains a separate counter for this value, allowing the system to evaluate motion frequently while consolidating multiple detection states into a single outbound MQTT message.

Why Decouple Evaluation from Publishing?

Separating these intervals provides architectural flexibility. You can maintain a tight evaluation_interval of 10-15 packets to catch quick movements while setting a relaxed publish_interval of 200-300 packets to minimize Wi-Fi airtime and MQTT broker load.

This decoupling is mirrored in the Python tooling at micro-espectre/src/runtime_policy.py (lines 17-25), which replicates the cadence logic for development and testing environments:


# micro-espectre/src/runtime_policy.py

def __init__(self, evaluation_interval=25, motion_on_hits=3, motion_off_hits=3):
    self.evaluation_interval = max(1, int(evaluation_interval))
    self.packets_since_evaluation = 0

Without this separation, every evaluation would trigger an MQTT publish, potentially flooding Home Assistant with redundant state updates when no motion has actually changed.

How to Configure evaluation_interval and publish_interval

You define both parameters in your ESPHome configuration.yaml under the espectre component. As documented in SETUP.md (lines 231-232), the standard configuration looks like this:


# configuration.yaml

espectre:
  evaluation_interval: 25   # detector runs every 25 packets

  publish_interval: 100     # MQTT publish every 100 packets

To reduce network traffic while maintaining detection quality, increase publish_interval independently:

espectre:
  evaluation_interval: 15   # evaluate more often → quicker motion detection

  publish_interval: 200     # publish less often → reduce network traffic

For dynamic adjustments at runtime via OTA or custom commands, use the setter methods declared in espectre.h:

// Runtime adjustment example
espectre.set_evaluation_interval(10);
espectre.set_publish_interval(300);

The default values originate in micro-espectre/src/config.py, where EVALUATION_INTERVAL = 25 and PUBLISH_INTERVAL = 100 serve as fallbacks for the Micro-ESPectre firmware build.

Summary

  • evaluation_interval governs how often the detector analyzes CSI data (default 25 packets), directly impacting motion detection latency and CPU usage.
  • publish_interval governs MQTT transmission frequency (default 100 packets), controlling network overhead and Home Assistant update rates.
  • Both parameters are declared in components/espectre/espectre.h, enforced in components/espectre/csi_manager.cpp, and exposed via micro-espectre/src/config.py.
  • Decoupling these values lets you optimize for fast detection in high-traffic environments without flooding your MQTT broker.

Frequently Asked Questions

What happens if I set publish_interval lower than evaluation_interval?

If publish_interval is smaller than evaluation_interval, the system will publish detection results more frequently than it calculates them. This causes redundant MQTT messages containing the same motion state, wasting bandwidth without improving detection accuracy. The CSI manager logic (should_publish || packets_since_evaluation_ >= evaluation_interval_) ensures evaluation still occurs at its own cadence regardless of publishing frequency.

Where are the default values defined in the ESPectre source code?

The defaults are defined in multiple locations for different build targets. In the C++ ESPHome component, components/espectre/espectre.h declares evaluation_interval_{25} and publish_interval_{100}. For the Micro-ESPectre Python firmware, micro-espectre/src/config.py sets EVALUATION_INTERVAL = 25 and PUBLISH_INTERVAL = 100. The Python runtime policy in micro-espectre/src/runtime_policy.py mirrors these defaults for consistency across testing tools.

Can I change these intervals dynamically without restarting the ESP32?

Yes. The ESpectre class exposes setter methods (set_evaluation_interval() and set_publish_interval()) that propagate new values to the csi_manager at runtime. You can invoke these via custom OTA commands or API calls without requiring a full device reboot, though the packet counters (packets_since_evaluation_) reset according to the new thresholds.

How does evaluation_interval affect motion detection latency?

A lower evaluation_interval reduces the time between CSI packet arrival and motion score calculation, decreasing latency for detecting movement onset or cessation. However, each evaluation consumes CPU cycles to compute variance and run the hit filter. Setting this value too low on congested networks may cause packet processing bottlenecks, whereas setting it too high (above 50-100 packets) may miss brief movements between evaluations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →