The problem with a full IP stack per node
A relay does one job: switch a load in under a few hundred milliseconds, reliably, for years. Putting a full Wi-Fi + TCP/IP stack behind that switch buys you a router dependency, a DHCP lease, association timeouts, and a reconnect storm every time the AP reboots.
For a local-first platform, the network is the product. If a node can't reach the gateway because the router is rebooting, the automation is broken — and that is exactly the failure mode we set out to eliminate.
What ESP-NOW gives us
ESP-NOW is a connectionless link layer built on the Wi-Fi PHY. No association, no IP, no DHCP. A node wakes, sends a framed message straight to the gateway's MAC, and sleeps.
- Latency: single-digit milliseconds, gateway-to-node, no AP in the path.
- Resilience: the gateway can run its own AP-less mesh. Router down? Automations still fire.
- Power: a battery sensor can transmit and return to deep sleep in a few milliseconds.
The trade-offs we accepted
ESP-NOW has no built-in reliability or ordering. So the gateway maintains a live node registry and a replay guard: every frame carries a monotonic counter, and the registry rejects anything it has already seen. That single mechanism gives us de-duplication and replay-attack protection for free.
// registry rejects stale or replayed frames
if (frame.counter <= node.last_counter) {
reject(REPLAY);
return;
}
node.last_counter = frame.counter;
The result is a link that behaves like a light-switch should: instant, offline-capable, and boring in the best way.