Created
March 18, 2026 22:50
-
-
Save mpflaga/4e57101bfbf8f8bc80156b2886df9f1e to your computer and use it in GitHub Desktop.
ESPHome Wiegand Pin Pad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Garage Door Keypad - ESPHome Wiegand Reader | |
| # | |
| # A "thin edge" device that reads input from a Wiegand keypad/RFID reader | |
| # and relays it to Home Assistant via a text_sensor. No PIN validation, | |
| # secret storage, or access-control logic runs on the device itself — | |
| # all authorization decisions live in Home Assistant automations. | |
| # | |
| # How it works: | |
| # - Wiegand component reads key presses, tag scans, and raw data on D0/D1 | |
| # - key_collector assembles presses into a 4-digit PIN (# to enter, *# to clear) | |
| # - Completed PINs and scanned tags are published to the "Keypad Code" sensor | |
| # - Sensor clears after 500ms to prevent duplicate processing | |
| # | |
| # Network config is included from .network.yaml to keep credentials | |
| # out of version control. | |
| substitutions: | |
| esphome_name: garage-door-keypad | |
| friendly_name: Garage Door Keypad | |
| # Pin definitions | |
| wiegand_d0_pin: GPIO33 | |
| wiegand_d1_pin: GPIO35 | |
| # Keypad configuration | |
| pin_length: "4" | |
| pin_timeout: 4s | |
| packages: | |
| network: !include .network.yaml | |
| esphome: | |
| name: ${esphome_name} | |
| friendly_name: ${friendly_name} | |
| platformio_options: | |
| board_build.f_cpu: 160000000L | |
| logger: | |
| level: INFO # Changed from DEBUG for production use | |
| esp32: | |
| board: esp32dev | |
| framework: | |
| type: arduino | |
| wiegand: | |
| - id: mykeypad | |
| d0: ${wiegand_d0_pin} | |
| d1: ${wiegand_d1_pin} | |
| on_key: | |
| - logger.log: | |
| format: "Received key: %d" | |
| args: ['x'] | |
| level: DEBUG | |
| on_tag: | |
| - logger.log: | |
| format: "Received tag: %s" | |
| args: ['x.c_str()'] | |
| level: INFO | |
| - text_sensor.template.publish: | |
| id: keypad_code | |
| state: !lambda |- | |
| return x; | |
| on_raw: | |
| - logger.log: | |
| format: "Received raw: %d bits, value %llx" | |
| args: ['bits', 'value'] | |
| level: DEBUG | |
| key_collector: | |
| - id: pincode_reader | |
| source_id: mykeypad | |
| min_length: ${pin_length} | |
| max_length: ${pin_length} | |
| end_keys: "#" | |
| clear_keys: "*#" | |
| allowed_keys: "0123456789" | |
| timeout: ${pin_timeout} | |
| on_progress: | |
| - logger.log: | |
| format: "PIN progress: '%s', started by '%c'" | |
| args: ['x.c_str()', "(start == 0 ? '~' : start)"] | |
| level: DEBUG | |
| on_result: | |
| - logger.log: | |
| format: "PIN entered: '%s', started by '%c', ended by '%c'" | |
| args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] | |
| level: INFO | |
| - text_sensor.template.publish: | |
| id: keypad_code | |
| state: !lambda |- | |
| return x; | |
| # Allow time for value to be transmitted before clearing | |
| - delay: 500ms | |
| # Clear the sensor to prevent retransmission | |
| - text_sensor.template.publish: | |
| id: keypad_code | |
| state: "0" | |
| on_timeout: | |
| - logger.log: | |
| format: "PIN timeout: '%s', started by '%c'" | |
| args: ['x.c_str()', "(start == 0 ? '~' : start)"] | |
| level: WARN | |
| text_sensor: | |
| - platform: template | |
| name: "Keypad Code" | |
| id: keypad_code | |
| icon: mdi:dialpad |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment