Ethernet (PoE) variant of HLK-LD2412-security — standalone intrusion detection system built on ESP32 + HLK-LD2412 24 GHz mmWave radar over wired Ethernet with Power over Ethernet. Full alarm state machine, zone management, Home Assistant integration, Telegram bot, and a dark-mode web dashboard. No cloud, no WiFi — one cable for power and data.
Tip
New in v4.3 -- Bilingual CZ/EN web UI, HomeMode (arm_home/arm_away) for HA alarm panel, config export/import with GUI. See CHANGELOG.
- In 3 Points
- Why PoE?
- Who Is This For
- What You Need
- Quick Start (~10 min)
- How It Works
- Features
- System Architecture
- Web Dashboard
- Telegram Bot
- API Reference
- Differences from WiFi Variant
- Sensor Firmware Quirks
- Known Issues & Limitations
- Troubleshooting
- Roadmap
- FAQ
- Development History
- Acknowledgments
- License
- It's a security system, not a smart home gadget. No light automations, no room tracking. Every feature answers one question: does this help detect an intruder?
- It runs over Ethernet. No wireless signal to jam, no WiFi interference, no dead zones. PoE means one cable for power and data — ideal for ceiling or wall-mounted sensors.
- It's battle-tested. Forked from the WiFi variant (50+ versions, 13 security bugs found and fixed through formal audit). All security features carry over, plus Ethernet-specific hardening.
| WiFi | PoE (this project) | |
|---|---|---|
| Cabling | Power + WiFi (2 things to maintain) | Single Ethernet cable |
| Reliability | Signal drops, interference, dead zones | Rock-solid wired connection |
| Security | Wireless signal can be jammed | No wireless attack surface |
| Mounting | Near outlet + good WiFi coverage | Anywhere you can run a cable |
| Power | USB / external 5V adapter | 802.3af/at PoE — no separate PSU |
All features from the WiFi variant are preserved: alarm state machine, zones, MQTT auto-discovery, Telegram, web dashboard, OTA with rollback. Plus PoE-specific extras: chip temperature monitoring, heap watchdog, ETH link watchdog.
- DIY security enthusiasts who want wired reliability without cloud subscriptions
- Home Assistant users looking for a hardwired radar node with proper alarm state management
- Vacation home / garage / warehouse owners who need unattended PoE-powered monitoring
- PoE infrastructure users who already have a PoE switch and want to add security nodes with zero extra wiring
| Part | Description | ~Cost |
|---|---|---|
| Prokyber ESP32-STICK-PoE-P | ESP32 + LAN8720A RMII Ethernet, active PoE | ~$15--25 |
| HLK-LD2412 | 24 GHz FMCW mmWave radar (UART) | $4--6 |
| PoE switch or injector | 802.3af/at compliant | $15--30 (or existing) |
| Ethernet cable | Cat5e or better | $1--5 |
| Total | ~$35--65 |
Any ESP32 board with LAN8720A RMII Ethernet should work with pin adjustments in
platformio.ini. The Prokyber ESP32-STICK-PoE-P is the tested reference board.
- PlatformIO (VS Code extension or CLI)
- Home Assistant (optional, for MQTT integration)
- Telegram (optional, for mobile alerts)
- Basic soldering (4 wires: VCC, GND, TX, RX from ESP32 to radar)
- Editing a config file (MQTT server)
- Flashing an ESP32 via USB (first time only — OTA after that)
~10 minutes from clone to working alarm.
Don't want to build from source? Download the pre-built binary from the Releases page and follow the Flashing Guide — no PlatformIO needed.
Building from source:
# 1. Clone
git clone https://github.com/PeterkoCZ91/HLK-LD2412-POE-security.git
cd HLK-LD2412-POE-security
# 2. Edit include/secrets.h — set your MQTT broker IP
# (Telegram is optional — leave defaults to skip)
# 3. Wire the radar (see pin table below) and connect ESP32 via USB
# 4. Build and flash
pio run -e esp32_poe --target uploadAfter flashing, the device:
- Initializes Ethernet (LAN8720A RMII)
- Waits for link (cable connected to PoE switch)
- Obtains IP via DHCP (or uses static IP if configured)
- Connects to MQTT broker (if configured)
- Starts web dashboard + radar processing
Open the web dashboard:
- URL:
http://<device-ip>/orhttp://<hostname>.local/ - Default login:
admin/admin(change it in Network & Cloud tab!)
Note
Don't know your device's IP? Check your PoE switch/router DHCP leases, or open the serial monitor (pio device monitor) and look for [ETH] IP: x.x.x.x.
| ESP32 GPIO | LD2412 Pin | Function | Note |
|---|---|---|---|
| GPIO 33 | TX | UART RX | ESP32 receives radar data |
| GPIO 32 | RX | UART TX | ESP32 sends commands |
| GPIO 4 | OUT | Digital output | Optional presence signal |
| 5V | VCC | Power | From ESP32 5V rail (PoE powered) |
| GND | GND | Ground |
Important: GPIO 18, 19, 21, 22, 23, 25, 26, 27 are reserved for Ethernet (LAN8720A RMII) and cannot be used for anything else. This is why the radar uses GPIO 32/33 instead of the WiFi variant's GPIO 18/19.
Full Prokyber ESP32-STICK-PoE-P pin map
| Pin | Function | Note |
|---|---|---|
| GPIO 0 | ETH CLK IN | EMAC_TX_CLK (LAN8720A → ESP32) |
| GPIO 2 | USER LED | Status LED |
| GPIO 4 | RADAR_OUT_PIN | Digital presence output |
| GPIO 17 | ETH CLK OUT | Clock output to LAN8720A |
| GPIO 18 | ETH_MDIO | RESERVED for LAN8720A |
| GPIO 19 | EMAC_TXD0 | RESERVED for LAN8720A |
| GPIO 21 | EMAC_TX_EN | RESERVED for LAN8720A |
| GPIO 22 | EMAC_TXD1 | RESERVED for LAN8720A |
| GPIO 23 | ETH_MDC | RESERVED for LAN8720A |
| GPIO 25 | EMAC_RXD0 | RESERVED for LAN8720A |
| GPIO 26 | EMAC_RXD1 | RESERVED for LAN8720A |
| GPIO 27 | EMAC_CRS_DV | RESERVED for LAN8720A |
| GPIO 32 | RADAR_RX | ← LD2412 TX |
| GPIO 33 | RADAR_TX | → LD2412 RX |
The LD2412 radar continuously scans a 60-degree cone at 24 GHz, reporting distance (0--9 m), motion energy, and static energy for each of its 14 detection gates (0.75 m per gate). The ESP32 reads these frames over UART, runs them through a security-focused processing pipeline, and makes alarm decisions.
LD2412 Radar ESP32 Processing Pipeline Outputs
+-----------+ +-------------------------------+ +-----------+
| 24 GHz | UART| Frame Parser (state machine) | | MQTT/HA |
| FMCW |---->| Pet Immunity Filter | | Telegram |
| Scanner | | Zone Classifier |--->| Webhook |
| 14 gates | | Alarm State Machine | | Siren |
| ~5 Hz | | Approach Tracker | | Web UI |
+-----------+ +-------------------------------+ +-----------+
|
[Ethernet/PoE]
No WiFi. No wireless.
arm (with delay)
DISARMED ──────────────────────> ARMING
^ |
| disarm | exit delay expires
| v
+<─────── TRIGGERED <──── ARMED
^ |
| | detection in zone
| entry delay v
+────────── PENDING
States: DISARMED -> ARMING (exit delay) -> ARMED -> PENDING (entry delay) -> TRIGGERED -> auto-rearm or disarm.
| Feature | Description |
|---|---|
| Alarm state machine | 5 states with configurable transitions |
| Detection zones | Up to 16 zones with min/max range, per-zone behavior (entry delay / immediate / ignore) |
| Entry & exit delays | Default 30 s each, configurable per-zone |
| Approach tracker | Circular buffer of last 16 armed detections for forensic review |
| Auto-rearm | Re-arms after trigger timeout (default 15 min) |
| Anti-masking | Detects prolonged zero-energy (sensor obstruction or tampering) |
| Pet immunity | Configurable energy threshold filter |
| Loitering detection | Alert when target lingers in close zone beyond timeout |
| Siren/strobe output | Optional GPIO for audible/visual alarm |
| Alarm energy threshold | Minimum energy + debounce before alarm transition |
| Feature | Description |
|---|---|
| Ethernet (PoE) | LAN8720A RMII, 100 Mbps, 802.3af/at |
| MQTT + Home Assistant | Auto-discovery, all entities created automatically |
| MQTT offline buffer | Queues messages to LittleFS when broker unreachable |
| MQTTS (TLS) | Optional encrypted MQTT |
| Telegram bot | 12 commands: arm, disarm, status, learn, mute, restart... |
| Discord / webhook | Generic HTTP POST notifications |
| ETH link watchdog | Auto-reboot after 5 min link down |
| Scheduled arm/disarm | Cron-like scheduling with timezone support |
| Auto-arm | Arms automatically after configurable idle period |
| Feature | Description |
|---|---|
| UART health monitoring | Frame rate, error count, resync stats |
| Radar health score | 0--100 composite score |
| Chip temperature | Configurable warning/critical thresholds with Telegram alerts |
| Heap watchdog | Low/critical RAM alerts with auto-recovery |
| Dead Man's Switch | Auto-restart if no MQTT publish in 30 min |
| Event log | 100 events on LittleFS with CSV export |
| Heap monitoring | Free/min/max-alloc with low-memory warnings |
| Feature | Description |
|---|---|
| Web dashboard | Responsive dark-mode UI with real-time SSE |
| REST API | /api/health, /api/telemetry, /api/config + 50 more |
| Engineering mode | Per-gate energy visualization via MQTT |
| mDNS | http://hostname.local/ access |
| Feature | Description |
|---|---|
| OTA updates | With automatic rollback (60 s validation) |
| Watchdog | 60 s hardware WDT |
| NVS persistence | All config, uptime, alarm state survives reboot |
| Gate config verification | Post-boot check to catch firmware config reverts |
| Config snapshot | Auto-backup NVS config to LittleFS before OTA |
Dark-mode responsive web UI accessible at http://<device-ip>/. Tabs for:
- Status -- real-time distance, energy, alarm state, radar health, chip temperature
- Security -- zones, delays, anti-masking, loitering, pet immunity
- Gates -- per-gate sensitivity with presets (indoor/outdoor/pet)
- Network -- MQTT, Telegram, webhook config (no WiFi section)
- Zones -- visual zone editor with distance map
- History -- event log with CSV export
The entire UI is embedded as a single PROGMEM string (~50 KB). No external files, no SD card needed.
Create a bot via @BotFather, add token and chat ID to secrets.h.
| Command | Description |
|---|---|
/start |
Welcome + quick command list |
/arm |
Arm with exit delay |
/arm_now |
Arm immediately |
/disarm |
Disarm |
/status |
State, distance, energy, uptime, heap, chip temp |
/light |
Ambient light reading (eng mode required) |
/learn |
Start static reflector learning (3 min) |
/eng_on /eng_off |
Toggle engineering mode |
/mute /unmute |
Notification control |
/restart |
Restart ESP32 |
All endpoints from the WiFi variant are available.
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Uptime, Ethernet info, MQTT, heap, hostname, reset history, chip temp |
/api/telemetry |
GET | Radar state, distance, energy, direction, UART stats |
/api/config |
GET/POST | Full configuration read/write |
/api/preset?name=indoor |
POST | Apply sensitivity preset |
/api/zones |
GET/POST | Zone configuration |
/api/events |
GET | Event log (JSON) |
/api/events/csv |
GET | Event log export (CSV) |
/api/schedule |
GET/POST | Scheduled arm/disarm times |
/api/timezone |
GET/POST | Timezone and DST offsets |
/api/arm |
POST | Arm the system |
/api/disarm |
POST | Disarm the system |
PoE-specific in /api/health:
{
"ethernet": {
"link_up": true,
"ip": "192.168.1.100",
"mac": "AA:BB:CC:DD:EE:FF",
"speed": 100
},
"chip_temp": 52.3
}Removed:
/api/wifi/config(no WiFi on this board)
Prefix: security/<device_id>/
| Topic | Direction | Description |
|---|---|---|
presence/state |
publish | IDLE / DETECTED / HOLDING / TAMPER |
presence/distance |
publish | Distance in cm |
presence/energy_mov |
publish | Moving energy (0--100) |
presence/energy_stat |
publish | Static energy (0--100) |
presence/direction |
publish | approaching / receding / static |
alarm/state |
publish | DISARMED / ARMING / ARMED / PENDING / TRIGGERED |
alarm/set |
subscribe | arm / disarm / arm_now |
alarm/event |
publish | JSON alarm trigger event |
alert/tamper |
publish | Tamper/anti-masking alert |
alert/loitering |
publish | Loitering alert |
diag/health_score |
publish | Radar health 0--100 |
diag/heap_free |
publish | Free heap KB |
diag/chip_temp |
publish | Chip temperature °C |
diag/eth_link |
publish | Ethernet link status |
availability |
publish | online / offline (LWT) |
| Area | WiFi variant | PoE variant |
|---|---|---|
| Connectivity | WiFi + backup SSID + AP portal | Ethernet (LAN8720A RMII) |
| Power | USB / external 5V | PoE (802.3af/at) via Ethernet |
| UART pins | GPIO 16/17 or 18/19 | GPIO 32/33 (ETH occupies 18/19) |
| RSSI monitoring | WiFi signal + jamming detection | N/A (wired) |
| Provisioning | WiFiManager AP portal + BLE fallback | Static config in secrets.h |
/api/health |
wifi.rssi, wifi.ssid |
ethernet.link_up/ip/mac/speed |
| STAB log | RSSI value | ETH:UP/DOWN |
| SSE telemetry | rssi field |
eth_link field |
| Chip temp monitoring | Not included | Warning + critical Telegram alerts |
| Heap watchdog | Not included | Low/critical RAM Telegram alerts |
| ETH link watchdog | N/A | Auto-reboot after 5 min link down |
| Flash size | 4 MB | 16 MB |
| Version scheme | v3.x.x | v4.x.x-poe |
Everything else is identical: alarm state machine, detection zones, MQTT auto-discovery, Telegram bot, web dashboard, event logging, OTA with rollback.
src/
+-- main.cpp Main loop, Ethernet, OTA, telemetry publishing
+-- WebRoutes.cpp REST API + SSE endpoints
+-- ConfigManager.cpp NVS persistence layer
+-- services/
+-- LD2412Service.cpp Radar driver (UART, state machine, recovery)
+-- SecurityMonitor.cpp Alarm logic, zones, anti-masking, approach tracker
+-- MQTTService.cpp HA auto-discovery, publish/subscribe
+-- MQTTOfflineBuffer.cpp Flash-backed message queue
+-- TelegramService.cpp Bot polling + command handler
+-- NotificationService.cpp Webhook + Discord dispatcher
+-- EventLog.cpp LittleFS ring buffer (100 events)
+-- LogService.cpp In-memory system log
+-- ConfigSnapshot.cpp Auto-backup NVS before OTA
+-- BluetoothService.cpp Emergency BLE provisioning
lib/
+-- LD2412_Extended/ Low-level UART protocol driver
+-- LD2412.cpp Frame parser, command interface, ACK verification
+-- LD2412.h Protocol constants, buffer management
include/
+-- constants.h All timing, thresholds, deadbands
+-- web_interface.h Embedded HTML/CSS/JS dashboard (~50 KB)
+-- secrets.h Credential configuration
+-- known_devices.h Multi-device MAC mapping
UART RX (5 Hz)
|
[LD2412.cpp] Frame parser with state machine + length validation
|
[LD2412Service.cpp] State tracking, direction inference, health monitoring
|
[SecurityMonitor.cpp] Zone classification -> alarm state machine -> event queue
|
[main.cpp] Dispatches to:
+-- MQTTService (HA auto-discovery, deadband publish)
+-- TelegramService (bot commands)
+-- NotificationService (webhooks)
+-- EventLog (LittleFS persistence)
+-- WebRoutes (SSE real-time stream)
|
[Ethernet/PoE] All network traffic over wired connection
Warning
The HLK-LD2412 has significant firmware-dependent behavior. V1.26 is the most common version shipped on new modules, and it has multiple UART command bugs.
| Feature | V1.24 | V1.26 | V1.36 |
|---|---|---|---|
| Basic frame output | ✅ | ✅ | ✅ |
| Engineering mode (UART) | ❌ ACKs, doesn't switch | ❌ ACKs, doesn't switch | ✅ |
| setBaudRate (UART) | ❌ ACKs, doesn't switch | ❌ ACKs, doesn't switch | ? |
| setResolution (UART) | ❌ Breaks radar | ❌ Breaks radar | ? |
| FW query (0xA0) | ❌ Returns 0 | ✅ | ✅ |
| Gate config persistence | ✅ |
Built-in workarounds:
- Baud rate upgrade skipped on V1.26
- Engineering mode auto-disabled on V1.26
- Gate config verified 40s post-boot (catches silent reverts, see ESPHome #13366)
- Resolution changes: use HLKRadarTool Bluetooth app (code: NUNIXB)
- Install HLKRadarTool -- Android / iOS
- Power cycle the LD2412 module (BLE only activates for ~30s after power-on)
- Connect via Bluetooth in HLKRadarTool (device:
HLK-LD2412_XXXX) - Enter firmware code:
NUNIXB - Select version and flash (~30s, do not power off)
- Power cycle and verify via
GET /api/health→fw_version
Hardware / Firmware (won't fix)
- Engineering mode over UART broken on V1.24 and V1.26 -- use HLKRadarTool Bluetooth app
setResolution()can brick radar detection on some FW -- only change via Bluetooth- Radar may not start when powered simultaneously with ESP32 -- power cycle the radar module
- V1.36 (only FW with working eng mode) not available via standard update channel
- GPIO 18/19/21/22/23/25/26/27 are reserved for Ethernet and cannot be repurposed
Software limitations
- No WiFi fallback -- if Ethernet cable is disconnected, device is unreachable until reconnected
- MQTT offline buffer limited to ~20 messages (LittleFS constraint)
- Web UI is a ~50 KB PROGMEM string -- editing requires firmware rebuild
- Scheduled arm/disarm requires NTP sync (no internet = no schedule)
- Multi-sensor supervision heartbeat and mesh alarm verification via MQTT (zero-config, auto-discovery)
resync_countin diagnostics looks alarming but ~20 resyncs/frame is normal parser behavior
No radar detection after flashing
Symptoms: Web dashboard shows distance 0, energy 0. Serial monitor shows [RADAR] Failed to init LD2412.
Causes & fixes:
- Wiring error -- RX/TX are crossed: ESP32 GPIO 33 connects to LD2412 TX, GPIO 32 to LD2412 RX
- Power issue -- LD2412 needs stable 5V; verify PoE supply is sufficient
- Radar not starting -- power cycle the radar module (disconnect 5V briefly)
No Ethernet connection
Check:
- Ethernet cable is firmly connected to both ESP32 board and PoE switch
- PoE switch/injector is providing power (check LED indicators)
- Serial monitor shows
[ETH] Link UP-- if not, check cable and switch port - DHCP server is running on your network
If using static IP: Configure via web dashboard or secrets.h.
MQTT not connecting / no Home Assistant entities
Check:
- MQTT server IP is correct in
secrets.hor web dashboard (Network & Cloud tab) - MQTT broker is running and reachable from device's network
- Serial monitor shows
[MQTT] Connected-- if not, check broker logs
Note: The device works fully standalone without MQTT. Events are buffered to flash and replayed when MQTT reconnects.
Telegram bot not sending messages
If the Telegram token in secrets.h is empty, the bot is silently disabled. To verify:
- Serial monitor at boot:
[Telegram] Bot initialized= working, no message = disabled GET /api/health-- checktelegram_enabled- Verify token from @BotFather and chat ID from @userinfobot
False alarms / too sensitive
- Apply a sensitivity preset: Indoor / Outdoor / Pet (Gates tab or
POST /api/preset?name=indoor) - Increase pet immunity threshold (Security tab)
- Use static zone learning (
/learnvia Telegram) to identify furniture reflectors - Adjust zone ranges to exclude areas outside your space
Chip temperature warnings
The PoE variant monitors ESP32 chip temperature. If you receive temperature alerts:
- Check ventilation around the device
- Verify PoE voltage is within spec (48V nominal)
- Thresholds are configurable via web dashboard (default: warn 70°C, critical 85°C)
| Feature | Status | Description |
|---|---|---|
| Multi-sensor mesh | ✅ v4.2.0 | Nodes cross-verify alarms via MQTT. On trigger, peers confirm presence within 5s. Alarm event includes mesh_verified field |
| Supervision heartbeat | ✅ v4.2.0 | Nodes publish alive signal every 60s. If a peer goes silent for 3 min, tamper alert is sent. Auto-discovery of up to 8 peers |
| Entry/exit path logic | ✅ v4.3.0 | Define valid entry paths (door → hallway → room). Entry delay only on correct sequence; wrong path (e.g. window) = immediate trigger |
| Static IP via web UI | ✅ v4.1.0 | Configure static IP via Settings tab — no reflashing needed |
| Event timeline UI | 💡 Planned | Visual timeline in web dashboard replacing the table view — easier forensic review of detection events |
| Camera trigger | 💡 Planned | Snapshot IP camera on alarm event via MQTT/HTTP |
| WiFi variant sync | 🔄 Ongoing | Port new features from WiFi v3.x to PoE v4.x |
| ESP32Async libraries | ✅ Done | Replaced abandoned me-no-dev/* with community ESP32Async/* (v4.1.3) |
| Chip temp monitoring | ✅ Done | Warning/critical alerts via MQTT + Telegram (v4.0.2) |
| Heap watchdog | ✅ Done | Low/critical RAM alerts (v4.0.5) |
| OTA rollback | ✅ Done | 60s validation with auto-revert (v4.0.2) |
| Scheduled arm/disarm | ✅ Done | Cron-like with timezone (v4.1.0) |
| MQTT offline buffer | ✅ Done | LittleFS message queue (v3.9.8-poe) |
| ETH link watchdog | ✅ Done | Auto-reboot after 5 min link down |
Do I need Home Assistant?
No. The system works fully standalone with the web dashboard and Telegram bot. Home Assistant adds remote control via MQTT and nice dashboards, but it's optional.
Can I use a regular ESP32 board with an Ethernet module?
Potentially yes, if your board uses LAN8720A with RMII interface. You'll need to adjust the ETH pin definitions in platformio.ini. The Prokyber ESP32-STICK-PoE-P is the tested reference, but any ESP32 + LAN8720A combo should work with correct pin mapping.
What happens when the Ethernet cable is disconnected?
The alarm keeps running locally. Events are logged to flash (EventLog) and MQTT messages are queued in the offline buffer. The ETH link watchdog auto-reboots after 5 minutes of link down to attempt recovery. When connectivity returns, buffered messages are replayed.
Can I use multiple PoE sensors?
Yes. Flash the same firmware to multiple boards — each identifies itself by MAC address (via known_devices.h) and gets its own MQTT topics. Add OTA environments per device in platformio.ini. Since v4.2.0, nodes automatically discover each other via MQTT, monitor peer health (supervision heartbeat), and cross-verify alarms (mesh verification).
How much power does it draw?
The ESP32 + LD2412 combination draws roughly 2--3W. Well within 802.3af limits (12.95W per port). A typical 8-port PoE switch can power dozens of these nodes.
Why v4.x instead of v3.x?
The PoE variant uses v4.x versioning to clearly distinguish it from the WiFi variant (v3.x). The feature set is kept in sync, with PoE-specific additions (chip temp, heap watchdog, ETH link monitoring) layered on top.
Forked from the WiFi variant at v3.6.8, then evolved independently with Ethernet-specific features.
| Phase | Versions | Focus |
|---|---|---|
| Fork & Port | v3.6.8--3.9.x-poe | WiFi → Ethernet, pin remapping, ETH link watchdog |
| PoE Hardening | v4.0.x-poe | OTA rollback, chip temp monitoring, heap watchdog, config snapshot |
| Feature Sync | v4.1.x-poe | Scheduled arm/disarm, auto-arm, ESPHome hardening, ESP32Async libs |
- multi-sensor-fusion -- Python service that fuses this node's MQTT output with LD2450 2D radar, WiFi CSI (ESPectre), and Home Assistant sensors into a single weighted-average presence confidence per room. Ships with data-driven weight tuning tools.
- HLK-LD2412-security -- The WiFi variant this project is forked from.
- HLK-LD2412-POE-WiFi-CSI-security -- PoE variant with WiFi CSI passive motion detection added alongside the radar.
- HLK-LD2450-security -- Sister project using the 2D LD2450 radar.
- HLK-LD2412-security -- the WiFi variant this project is forked from
- HLK-LD2412 Protocol V1.05 -- official serial protocol documentation
- tobiastl/LD2412 -- Arduino library (base for our extended driver)
- ESP32Async -- maintained community fork of AsyncTCP + ESPAsyncWebServer
- ESPHome community -- protocol insights, firmware compatibility testing, security audit patterns
MIT License. See LICENSE for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Keep commits focused and test your changes
- Open a pull request with a clear description
Bug reports and feature requests are welcome via GitHub Issues.