Wi-Fi CSI sensing in Home Assistant: ESPHome, MQTT and router REST
By Wu Jun · Updated 2026-10-29 · 7 min read
Home Assistant needs entities, not a raw CSI byte stream. The important question is not "how do I put 256 subcarriers into HA?" but which device captures, which device classifies, and what an entity actually means.
As of 2026-10-29 there are two mature ways to obtain ready-made entities:
- ESPectre + ESPHome: an ESP32 computes motion/movement locally and HA discovers ESPHome entities;
- ESPectre Native + MQTT Discovery: the device publishes entities to MQTT without an ESPHome build.
This project's MT6000 platform/ is a third route. It exposes REST/WebSocket, but its current source has no
built-in MQTT. Use its REST API first; an MQTT bridge would be a separate implementation, not an existing topic.
0. Choose the integration layer
| Your situation | Recommended route | Main cost |
|---|---|---|
| Fastest "living room has motion" entity | ESPectre + ESPHome | one supported ESP32, one area |
| Do not want to maintain an ESPHome build | ESPectre Native + MQTT Discovery | Mosquitto broker required |
| Already run this router platform | HA REST against /api/stations |
maintain the platform and room thresholds |
| Want one router to cover the whole home | MT6000 capture + custom analysis | most engineering; no built-in MQTT today |
ESPectre's official project supports ESP32-C6/C5/C3/S3/S2 and classic ESP32 on a normal 2.4 GHz Wi-Fi 4 network. One board covers one area and does not identify people or count occupants [1]. The underlying capture API comes from ESP-IDF [2].
1. Define entity semantics first
| Entity | Meaning | Do not interpret it as |
|---|---|---|
motion binary_sensor |
a detected motion edge | confirmed occupancy; no motion is not proof of an empty room |
| movement score | a 0–1 movement score | position, identity or a medical measurement |
| threshold | the current detector threshold | a universal constant for every room |
| availability | device online and data fresh | sensor accuracy |
The field survey by Ma et al. gives a broader account of CSI sensing limits [3]. Before automating lights, HVAC or security, add hold times, human confirmation or an independent sensor; do not treat one CSI stream as safety certification.
2. Route A: ESPectre + ESPHome (the easiest first deployment)
The current ESPectre ESPHome frontend is not the old platform: espectre style. It requires an
external_components entry pointing at the component directory; declaring top-level espectre: creates the
motion, movement, threshold and diagnostic entities.
Merge this component block into the official complete example for your chip; do not copy a fragment without the board configuration:
external_components:
- source:
type: git
url: https://github.com/francescopace/espectre
path: src/cpp/frontend/esphome/components
components: [espectre]
espectre:
detection_algorithm: lightweight
csi_capture_profile: lltf
csi_target_pps: 100
traffic_generator_mode: ping
motion_sensor:
name: "Living Room Motion"
movement_sensor:
name: "Living Room Movement"
internal: true
Notes:
csi_capture_profileacceptsauto,lltforht-vht; changing it requires a rebuild;- keep the default
csi_target_ppsand traffic mode until the HA entity is visible; internal: truereduces high-rate movement-score history in the HA recorder while keeping the binary motion entity for automations;- do not put the real SSID, password or BSSID in a public YAML. Use the official Improv Serial or captive portal provisioning path.
ESPHome deployment order
- Start from the complete official YAML for the exact chip; do not mix chip examples;
- flash over USB, provision Wi-Fi, and verify the serial log;
- confirm the device is discovered by Home Assistant's ESPHome integration;
- inspect the motion binary sensor, threshold and diagnostics;
- observe for 24 hours before connecting lights or HVAC;
- recalibrate after moving the board, its access point or large furniture.
3. Route B: ESPectre Native + MQTT Discovery
Native can publish Home Assistant entities through MQTT Discovery. The official Mosquitto broker is the simplest local choice; Home Assistant documents MQTT 5 support and discovery on by default [4].
Configure the device settings with:
scheme: mqtt
host: homeassistant.local
port: 1883
Confirm that the device reports configured: true. Use mqtts and the broker's TLS port, usually 8883, for a
public certificate. The host field must not contain mqtt://, credentials, a port or a path. Native's entities
should appear automatically; do not create a second manually configured duplicate.
Only when discovery is disabled, create a manual entity. The Native motion topic carries a JSON event:
mqtt:
binary_sensor:
- name: "Living Room CSI Motion"
unique_id: living_room_csi_motion
state_topic: "espectre/v1/devices/<device_id>/motion"
value_template: "{{ value_json.state }}"
payload_on: "motion"
payload_off: "idle"
availability_topic: "espectre/v1/devices/<device_id>/health"
availability_template: "{{ 'online' if value_json.online else 'offline' }}"
payload_available: "online"
payload_not_available: "offline"
The motion event topic is not retained. After an HA restart, the entity may be unavailable until the next
event. For a long-running installation, prefer MQTT Discovery and verify the health/availability topic.
4. Route C: this project's router platform + REST
The platform/ in this repository actually provides:
GET /api/health;GET /api/stations;GET /api/stats;- WebSocket
/ws; - session recording and export routes.
It does not provide /api/csi/status, and it does not currently provide an MQTT publisher. The old example
with that path and topic is not a working configuration.
Test on the machine running the platform:
curl -fsS http://csi-platform.local:8080/api/health
curl -fsS http://csi-platform.local:8080/api/stations
/api/stations returns a stations array. Each item includes alias, online, present, motion_db and
last_seen_ago. This current-style REST integration selects one alias:
rest:
- resource: "http://csi-platform.local:8080/api/stations"
scan_interval: 2
timeout: 5
binary_sensor:
- name: "Living Room CSI Presence"
unique_id: living_room_csi_presence
value_template: >-
{% set s = value_json.stations
| selectattr("alias", "equalto", "living-room")
| list | first %}
{{ (s.online and s.present) if s else false }}
sensor:
- name: "Living Room CSI Motion dB"
unique_id: living_room_csi_motion_db
unit_of_measurement: "dB"
state_class: measurement
value_template: >-
{% set s = value_json.stations
| selectattr("alias", "equalto", "living-room")
| list | first %}
{{ s.motion_db if s else none }}
Match the fields to the actual platform response. If the platform sits behind nginx, keep /api/stations in the
resource path. The REST integration's resource, interval and binary-sensor schema are documented by Home Assistant
[5].
Calibrate and automate the REST route
- record at least 10 quiet minutes and inspect
motion_db; - record 10 active minutes and compare the distributions;
- choose a high quiet percentile and a low active percentile as references;
- apply hysteresis and a hold time; do not trigger every curve wiggle;
- observe 24 hours and count false positives, misses and unavailable time;
- recalibrate after moving the router, access point, furniture or room.
automation:
- alias: "Turn off living-room light after ten quiet minutes"
mode: single
trigger:
- platform: state
entity_id: binary_sensor.living_room_csi_presence
to: "off"
for: "00:10:00"
condition:
- condition: state
entity_id: binary_sensor.living_room_csi_presence
state: "off"
action:
- service: light.turn_off
target:
area_id: living_room
Do not connect a door lock, emergency alarm or medical alert directly. CSI is a low-rate, environment-dependent sensor; a safety function needs independent certification and a fail-safe design.
5. MQTT vs REST
| Dimension | ESPectre ESPHome | Native MQTT Discovery | Router platform REST |
|---|---|---|---|
| HA discovery | native integration | MQTT discovery | manual templates |
| Latency | device-side events | MQTT push | polling |
| Coverage | one room per board | one room per board | depends on router placement |
| Maintenance | ESPHome/component releases | broker and device settings | service, proxy and thresholds |
| Failure recovery | ESPHome reconnect | LWT/availability | REST timeout and template null handling |
Start with one ESPHome room, move to Native MQTT if you do not want an ESPHome build, and use REST only when a router platform already exists. Do not run all three for the same sensor.
6. Common failures
| Symptom | Check first |
|---|---|
| ESPHome creates no entities | complete chip example, external_components path, USB flash log |
| MQTT entity is missing | MQTT 5 broker, discovery enabled, device reports configured: true |
| Entity remains unavailable | health/availability topic, Last Will, Wi-Fi and device time |
| REST timeout | platform health, nginx /api proxy, firewall and DNS name |
| REST template errors | curl the stations array and verify the exact alias |
| Frequent false triggers | threshold, on/off hold, curtains, HVAC and pets |
| Still person is missed | insufficient CSI micro-motion; add another sensor or extend release time, do not invent accuracy |
7. Privacy and deployment boundaries
- deploy only in a space you own or are authorised to monitor;
- inform household members; do not turn CSI into covert surveillance;
- use a dedicated MQTT account and local broker; never expose port 1883 to the internet;
- do not expose the REST or ESPHome API directly to the internet; use a VPN or authenticated reverse proxy;
- treat raw CSI, movement scores and HA history as sensitive data and set retention limits;
- recalibrate and record firmware, model, placement and thresholds after every material change.
Continue with ESP32 CSI introduction, ESP32 human detection, Raspberry Pi roles or MT6000 reproduction.
References and data sources
Every external claim carries a source and an evidence grade (grading scheme). Grade E marks first-party, reproducible measurements from this project.
- Grade C · official docs
francescopace/espectre — Wi-Fi CSI motion sensing for ESP32 (ESPHome)
F. Pace
github.com/francescopace/espectre · verified: GitHub API and official README fetched 2026-10-29 (stars 9,700; GPLv3; ESPHome source path, Direct API port 62587 and supported chips documented) · The official project provides ESPHome, native MQTT, Matter and browser flashing paths; one ESP32 covers one area and does not identify people or count occupants. - Grade C · official docs
espressif/esp-csi — Applications based on Wi-Fi CSI
Espressif Systems
github.com/espressif/esp-csi · verified: GitHub API 2026-10-29 (stars 1,723; README confirms the complete ESP32 series list and three sender/receiver routes) · The official README states: "All ESP32 series support CSI, including ESP32 / ESP32-S2 / ESP32-C3 / ESP32-S3 / ESP32-C5 / ESP32-C6 / ESP32-C61." - Grade A · standard/review
WiFi Sensing with Channel State Information: A Survey
W. Ma, W. Zhou, X. Wang · ACM Computing Surveys · 2019
doi:10.1145/3310194 · citations 857 · verified: CrossRef API, 2026-10-11 · The field's most-cited CSI sensing survey (857 citations, verified via CrossRef). - Grade C · official docs
Home Assistant — MQTT integration and discovery
Home Assistant
www.home-assistant.io/integrations/mqtt/ · verified: Official documentation fetched 2026-10-29 (broker setup, MQTT discovery, availability and manual binary sensors) - Grade C · official docs
Home Assistant — RESTful integration
Home Assistant
www.home-assistant.io/integrations/rest/ · verified: Official documentation fetched 2026-10-29 (resource, authentication, scan interval, sensor and binary_sensor schema)