penguin/homekey-relay

homekey-relay

summary

default branchmaster
default commit99c8d479605491753640a0ea8f933a94008f29c8

recent commits

commitdateauthorsubject
99c8d472026-10-13T10:23:22Z斟酌 鵬兄Added wiring image
262a0782026-10-13T10:03:20Z斟酌 鵬兄default presence to GPIO1 instead
84e552c2026-10-13T09:55:12Z斟酌 鵬兄LD2410S: Wake up esp32!

files

pathsize
.gitignore100
README.md6876
custom_components/homekey_reader/__init__.py657
custom_components/homekey_reader/config_flow.py2986
custom_components/homekey_reader/const.py156
custom_components/homekey_reader/manifest.json345
custom_components/homekey_reader/sensor.py3354
custom_components/homekey_reader/strings.json497
custom_components/homekey_reader/translations/en.json497
esp32/CMakeLists.txt112
esp32/PROTOCOL.md4538
esp32/main/CMakeLists.txt577
esp32/main/Kconfig.projbuild1385
esp32/main/main.c8469
esp32/main/pin_test.c1804
esp32/main/pn532.c14334
esp32/main/pn532_test.c6460
esp32/main/presence.c2355
esp32/main/presence.h319
esp32/main/reader.h2444
esp32/main/relay.c6562
esp32/main/relay.h631
esp32/sdkconfig.defaults180
esp32/tools/ld2410s-c3-calib/.gitignore80
esp32/tools/ld2410s-c3-calib/CMakeLists.txt131
esp32/tools/ld2410s-c3-calib/README.md10302
esp32/tools/ld2410s-c3-calib/flash.py1571
esp32/tools/ld2410s-c3-calib/main/CMakeLists.txt444
esp32/tools/ld2410s-c3-calib/main/Kconfig.projbuild694
esp32/tools/ld2410s-c3-calib/main/idf_component.yml116
esp32/tools/ld2410s-c3-calib/main/main.c15973
esp32/tools/ld2410s-c3-calib/main/protocol.c3823
esp32/tools/ld2410s-c3-calib/main/protocol.h1269
esp32/tools/ld2410s-c3-calib/main/radar.c16093
esp32/tools/ld2410s-c3-calib/main/radar.h1364
esp32/tools/ld2410s-c3-calib/main/web.html12115
esp32/tools/ld2410s-c3-calib/sdkconfig.defaults233
esp32/tools/ld2410s-c3-calib/tests/test_protocol.c3354
esp32/tools/ld2410s-c3-calib/tests/test_ui.js2726
hacs.json56
images/wiring.webp70006
tests/include/driver/gpio.h495
tests/include/driver/uart.h18
tests/include/esp_err.h18
tests/include/esp_idf_version.h142
tests/include/esp_log.h18
tests/include/esp_random.h18
tests/include/esp_sleep.h303
tests/include/esp_timer.h18
tests/include/freertos/FreeRTOS.h85

HomeKey Reader Relay

PN532 -> | ESP32-C3 (this part) | -> Home Assistant
         |  ^                   |
         | HLK-LD2410S sensor   |

wiring

In development. NOT FOR USE!

Current firmware connects directly to homekey-go over BLE GATT and relays NFC APDUs. The HACS component and service-data examples below describe the earlier advertisement-based firmware; current firmware does not emit those UID advertisements. See the current relay protocol.

Workflow

LD2410S OT2 HIGH -> ESP32-C3 wakes/boots -> PN532 UART wake -> BLE reconnect and Home group configuration -> ECP + NFC polling.

OT2 LOW -> absence confirmation -> finish any active NFC session -> PN532 RF off + PowerDown -> stop BLE -> ESP32-C3 deep sleep until OT2 HIGH.

Presence wiring

Module pin ESP32-C3 / supply
LD2410S 3V3 Always-on regulated 3.3 V
LD2410S GND Common GND
LD2410S OT2 GPIO1 (HIGH = present)
LD2410S OT1/TX and RX Disconnected in relay firmware
PN532 RX GPIO3
PN532 TX GPIO4
PN532 supply / GND Existing regulated supply / common GND

Remove the calibration firmware's radar UART wiring from GPIO3/4 before reconnecting PN532. The relay uses OT2 only and does not change the radar's saved calibration/settings. Keep LD2410S powered during ESP sleep. PN532 also stays supplied: this is its software PowerDown mode, not a switched supply. Its UART TX drive from the ESP is held idle HIGH across sleep to avoid false wakes. Never connect battery voltage directly to 3.3 V power or GPIO pins.

Sleep behavior and settings

idf.py menuconfig -> Home Key presence / sleep:

Deep sleep disconnects BLE and wake starts a new boot. The configured reader address remains the same, but homekey-go must reconnect and resend its Home group before polling resumes. Approach-to-ready time therefore includes boot and BLE reconnect, not just PN532 wake. No ECP/credential data is cached across sleep, and there are no periodic timer wakes.

An active NFC callback finishes (or hits its existing session timeout) before the owner task considers sleep. Absence may therefore take longer during an authentication. PN532 PowerDown must return a complete success response; a failure keeps ESP awake, wakes/reinitializes PN532, and retries. A returning HIGH during shutdown triggers an immediate GPIO wake after sleep entry.

The implementation selects the renamed wake API on ESP-IDF 6.x and the older API on 5.x. It needs no automatic light-sleep or Bluetooth sleep configuration. The standalone pin/PN532 test builds do not use presence control.

Build and verify on hardware

cd esp32
idf.py menuconfig
idf.py build
idf.py -p /dev/cu.usbmodem101 flash monitor
  1. Keep someone in range. Expect the OT2 GPIO log, PN532 firmware log, BLE connection, Home Key ECP configuration, and normal phone authentication.
  2. Leave the area. After OT2 goes LOW and the confirmation interval passes, expect Absent: PN532 asleep, BLE stopped; ESP32 deep sleep.
  3. Approach again. Expect a new boot and BLE/ECP setup, then test Home Key.
  4. Repeat several cycles; also test presence returning during shutdown and leaving during authentication. Compare supply current awake/asleep.

Native USB can disappear in deep sleep. Approach the sensor to wake it, or hold BOOT and tap RESET to enter the ROM downloader if flashing cannot connect. Development-board LEDs/regulators and PN532 board circuitry can dominate sleep current; chip sleep does not guarantee a particular battery life.

Host tests cover absence timing, cold/GPIO wake policy, disabled presence, PN532 wake delay, confirmed/rejected/truncated/missing PowerDown responses, the polling-to-sleep transition, and existing APDU/ECP behavior. This change has not been compiled with a full ESP-IDF toolchain or tested on physical hardware in the development environment.

Protocol references: LD2410S OT2 definition, PN532 user manual, section 7.2.11, ESP32-C3 sleep modes.

Legacy Home Assistant UI setup

HACS

  1. Settings -> Devices & services -> Add Integration.
  2. Search for HomeKey Reader.
  3. Pick the advertising ESP32-C3 reader.

Because the manifest also contains a Bluetooth matcher, Home Assistant can offer the reader automatically when it sees the service-data advertisement.

Install toolchain

brew install libgcrypt glib pixman sdl2 libslirp dfu-util cmake python

brew tap espressif/eim
brew install eim

eim install

source "$HOME/.espressif/tools/activate_idf_v6.x.x.sh"

Flash the firmware

cd esp32
idf.py set-target esp32c3
idf.py -p /dev/cu.usbmodem101 flash monitor

Service UUID:

7b1e0001-7b1e-4a11-9abc-0123456789ab

Advertisement payload after the UUID:

byte 0	  protocol version = 1
byte 1	  message type = 1 (mock PN532 tag)
byte 2..3   sequence, uint16 little-endian
byte 4..7   mock UID = DE AD BE EF

Testing the PN532

LIBNFC_DEVICE=pn532_uart:/dev/cu.usbserial-8310 nfc-list
LIBNFC_DEVICE=pn532_uart:/dev/cu.usbserial-8310 nfc-poll

Test pins

idf.py -B build-pin-test -D PIN_TEST=ON build flash monitor

Test pn532

idf.py -B build-pn532-test -D PNC532_TEST=ON build flash monitor

NFC APDU relay

The firmware now exposes session status and an APDU mailbox for homekey-go 0.0.5. Deploy the matching firmware and Go service together. NFC runs in one UART owner task; the RF field stays on throughout authentication.

Go now supplies the provisioned Home group identifier over BLE. The reader emits Home Key ECP before activation so iOS can select the key automatically. Polling waits for this configuration on every connection. FAST authentication and unknown-device attestation remain follow-up work. homekey-go verifies the key; UID detection alone never unlocks. See esp32/PROTOCOL.md for the mailbox format and tests/run.sh for host tests.