Push-based, local-first bridge between ESPEasy & RPiEasy nodes and Home Assistant — no MQTT, no cloud, no polling.
Drop your ESP8266/ESP32 or Raspberry Pi sensors on the LAN, set them to C013 (ESPEasy/RPiEasy P2P) controller, and they show up in Home Assistant on their own. Every value is pushed the moment it changes. Every relay can be switched back from Lovelace.
Quick Start · How it works · Switching · Reference · Troubleshooting
MQTT is great. Until you don't want to run a broker. Until you don't want to flash credentials. Until you just want a sensor on the wall to show up in Home Assistant — and stay there.
ESPEasy and RPiEasy already speak C013 — a tiny UDP broadcast protocol made for ESPEasy/RPiEasy nodes to gossip with each other. This integration teaches Home Assistant to listen on the same wire. That's it. That's the whole trick.
|
No MQTT, no Mosquitto, no auth headers. Plain UDP on your LAN. |
Values arrive at HA the moment ESPEasy reads them. Sub-second freshness, no API hammering. |
Set the controller, save, done. Nodes auto-register. New tasks become new entities. |
|
📥 Auto-discovery New ESPEasy units appear in HA the moment they send their first packet. |
🌡️ All sensor types Temperature, humidity, pressure, lux, switches, analog, counters — anything ESPEasy can read. |
|
🔁 Persistent state Last values survive HA restarts. No "unknown" after a reboot. |
🎚️ Two-way switching Toggle relays, GPIOs and PWM from Lovelace — outgoing C013 packets, just like ESPEasy peers. |
|
🧭 Unit-aware HA picks the right device class and unit (°C, %, hPa, lx) from the ESPEasy plugin ID. |
🇩🇪 🇬🇧 Bilingual UI Config flow, options, repair issues — fully translated DE + EN. |
|
🩺 Health watchdog
Per-node |
🪛 HACS-ready Drop the repo into HACS, restart, add the integration. No YAML. |
┌──────────────────┐ UDP :8266 ┌──────────────────────┐
│ ESPEasy node │ ───── C013 broadcast ──▶│ Home Assistant │
│ ESP8266/ESP32 │ (sensor frame) │ espeasy_p2p │
│ + DHT/BMP/… │ │ ├─ discovery │
└──────────────────┘ │ ├─ entity registry │
│ └─ state machine │
▲ └──────────┬───────────┘
│ UDP :8266 │
└────── C013 unicast ◀───── relay / pwm / gpio ──┘
(switch frame)
What's actually in the packet?
A C013 frame is a small fixed-layout struct with:
- Header — protocol version + packet type (
SENSOR_DATA_PACKETor similar) - Source unit — the ESPEasy unit ID (1–255)
- Task index — which task on the node fired this
- Plugin ID — DHT, BMP280, switch, analog, …
- Values 1–4 — up to four
float32slots per task
espeasy_p2p binds each (unit, task, value-index) triple to one Home Assistant entity and feeds new floats straight into its state.
HACS → ⋮ → Custom repositories
URL: https://github.com/Chance-Konstruktion/ha-espeasy-p2p
Type: Integration
Then search "ESPEasy P2P" in HACS, install, and restart Home Assistant.
Settings → Devices & Services → + Add Integration → "ESPEasy P2P"
Pick the UDP port (default 8266) and an optional unit number for HA itself. Confirm.
On every ESPEasy or RPiEasy unit, in Controllers → Add → ESPEasy P2P (C013):
Controller IP: <your Home Assistant IP>
Controller Port: 8266
Unit Number: <unique 1–255 per node>
Enabled: ✓Save. Within seconds the device shows up under Settings → Devices & Services → ESPEasy P2P.
💡 Non-tech check — if the ESPEasy Tools → Log shows
C013: send to <HA-IP>and you don't see the device in HA, jump to Troubleshooting. 9 out of 10 times it's a firewall on the HA host.
Two-way control is supported for tasks that map to writable GPIOs.
Supported output kinds
| ESPEasy plugin | HA platform | Notes |
|---|---|---|
| GPIO Switch (P001) | switch |
On/off, retained |
| Relay / Bistable | switch |
Mirrored locally on the node |
| PWM Output (P019) | light (brightness) |
0–1023 mapped to 0–255 |
| GPIO Pulse | button |
Fires a one-shot C013 frame |
How HA → node packets are addressed
When you flip a switch in Lovelace, espeasy_p2p sends a unicast C013 frame to the node's last-seen IP with the target task index and the new value. The node executes the command locally — no acknowledgement is required because the next sensor broadcast confirms the new state.
If the node is offline, the packet is silently dropped. HA marks the entity unavailable after the per-node last_seen timeout (default 5 min).
Known limitations
- No encryption. C013 is plain UDP — keep it on a trusted VLAN.
- No retries. One packet per click. Use HA automations +
last_seenif you need delivery guarantees. - Unit numbers must be unique across your LAN. Duplicate IDs = entity collisions.
Entities created per node
| Entity | Type | Source |
|---|---|---|
sensor.<name>_<task>_<value> |
sensor |
each value slot of each task |
binary_sensor.<name>_<task> |
binary_sensor |
switch/PIR tasks |
switch.<name>_<task> |
switch |
writable GPIO tasks |
sensor.<name>_last_seen |
sensor (timestamp) |
per-node watchdog |
binary_sensor.<name>_available |
binary_sensor |
derived from last_seen |
Services
| Service | Fields | What it does |
|---|---|---|
espeasy_p2p.send_command |
unit, task, value |
Send a raw C013 command frame |
espeasy_p2p.reload_unit |
unit |
Drop cached entities + rediscover |
espeasy_p2p.rename_unit |
unit, new_name |
Persist a friendly name |
Configuration options
| Option | Default | Description |
|---|---|---|
| UDP port | 8266 |
Must match the controller settings on every node |
| HA unit number | 250 |
Unit ID Home Assistant uses in its own announce packets |
| HA peer name | Home Assistant |
Name HA advertises to the C013 mesh |
| Decimal precision | 3 |
Decimal places shown for sensor values (0–6) |
Per-switch GPIO pins and command templates are configured later via the integration's Configure (options) dialog. The stale/offline timeout (120 s) is fixed.
Networking: the integration receives UDP broadcasts on port 8266. This only works when Home Assistant can see them on the LAN — i.e. HA OS, Supervised, or a container started with host networking (
--network=host). In a bridged Docker network broadcasts never arrive and no nodes will be discovered.
❌ No devices show up after I set the controller
- On the node: Tools → Log — do you see
C013: send to <HA-IP>:8266? - On HA host:
sudo ufw status/ firewall — UDP 8266 inbound must be open. - Same subnet? C013 broadcasts don't cross routers without a relay.
- HA log:
Settings → System → Logs— filter forespeasy_p2p.
⚠️ Entities exist but values stay at "unknown"
- Plugin ID may be unknown to the integration. Open an issue with the Devices → device info screenshot and a log line containing the packet.
- Task values 2–4 are only populated by multi-value plugins (e.g. DHT22 = temp + hum). Single-value plugins leave them empty.
🔌 Switching a relay does nothing
- The node's controller must have Send to controller enabled and at least one Controller entry pointing at HA.
- Confirm the task is bound to a writable GPIO (not a read-only sensor).
- Watch the node log while flipping the switch — you should see a
C013: recvline.
⏱️ A switch flips back / state lags on short intervals
Switch state in HA is confirmed three ways: a C013 push from the node
when the value changes, a 30 s /json poll as a safety net, and — right
after HA itself toggles a switch on — a short targeted re-read burst
(~3 s / 8 s / 20 s, that one node only). So a relay that auto-switches off a
few seconds later (internal timer/pulse) is caught quickly, with no
steady-state overhead.
The remaining limit: on/off cycles faster than ~3 s that HA can't observe
in between may be missed (HA might only ever see one of the two states). For
accurate state on very fast-cycling outputs, make the node broadcast on
every change (Send to controller so each transition is pushed) rather
than relying on HA to catch it.
🌀 Duplicate entities after a unit-number change
Use espeasy_p2p.reload_unit or remove the device under Settings → Devices & Services and let it rediscover.
PRs and issues welcome. Especially:
- New plugin mappings — if your sensor's plugin ID isn't recognised, send a packet capture + the ESPEasy plugin name.
- Translations — DE and EN are in
translations/. Add axx.jsonand open a PR. - Tests —
pytestlives undertests/. Runpytest -qbefore pushing.
git clone https://github.com/Chance-Konstruktion/ha-espeasy-p2p
cd ha-espeasy-p2p
pip install -r requirements_test.txt
pytest -qMIT © Chance-Konstruktion. See LICENSE.
ESPEasy is © letscontrolit · Home Assistant is © Nabu Casa · this integration is unaffiliated.