Wiegand Keypad and MH-ET ESP32 Dev

Hi All –

I wanted to connect a Wiegand reader from Hikvision (DS-K1802MK) to a MH-ET ESP32 Dev Kit Board, however I am unsure to which GPIOs I should connect the D0 and D1 from the Reader. Here’s the code below but I receive nothing when it’s all connected.

esphome:
  name: wiegand-keypad
  friendly_name: wiegand-keypad
  platform: ESP32
  board: mhetesp32devkit

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Wiegand-Keypad Fallback Hotspot"
    password: "xxxxxxxxxx"

captive_portal:

wiegand:
  - id: reader
    d0: GPIO25
    d1: GPIO26
    on_key:
            - lambda: ESP_LOGI("KEY", "received key %d", x);        
    on_tag:
            - lambda: ESP_LOGI("TAG", "received tag %s", x.c_str());
    on_raw:
            - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);  

I have one connected on WT32-ETH01 board and it works very good.
If my code can help you, here it is.

# wgtgrdr1.yaml
#
# Wiegand RFID čitač namijenjen za garažu
# radi s 13.56 MHz i 125khz wiegand čitaćem
#
# Detaljniji opis u readme.txt
#

globals:
  - id: led_status
    type: int
    restore_value: no
    initial_value: '0'
  - id: reboot_counter
    type: int
    restore_value: no
    initial_value: '0'
  - id: api_was_connected
    type: int
    restore_value: no
    initial_value: '0'
  - id: buzzer_status
    type: int
    restore_value: no
    initial_value: '0'

  - id: kHz125
    type: bool
    restore_value: false
    initial_value: "false"
  - id: tag_ena
    type: bool
    restore_value: false
    initial_value: "true"
  - id: hass_init_executed_state
    type: bool
    restore_value: false
    initial_value: "false"
  - id: sound_ena
    type: bool
    restore_value: false
    initial_value: "true"
  - id: heart_b
    type: bool
    restore_value: false
    initial_value: "true"

substitutions:
  $esphome_name: "wgtgrdr1"
  $tagreader_name: "WGTagreader1"


esphome:
  name: $esphome_name
  platform: ESP32
  board: esp-wrover-kit
  on_boot:
    - priority: 600
      then:
        - script.execute: online_light_set
        - light.turn_on:
            id: led
            effect: blink_very_fast
        - light.turn_on:
            id: status_led
            effect: strobe_unknown_state
    - priority: -100.0
      then:
        - delay: 5s
        - wait_until:
            api.connected
        - script.execute: online_light_set
        - lambda: |-
            id(api_was_connected) = 1;
        - light.turn_off:
            id: led
        - script.execute: set_buzzer_busy
        - script.execute: beep_short_twice
        - delay: 200ms
        - output.turn_off: buzzer_output
        - delay: 2000ms
        - script.execute: set_buzzer_not_busy
        - homeassistant.service:
            service: script.${esphome_name}_init
            data: {}
        - script.execute: beep_short_twice
        - lambda: ESP_LOGD("TEST", "boot finished");
        - lambda: id(raw_value).publish_state("");
        - binary_sensor.template.publish:
            id: heart_beat
            state: !lambda 'return id(heart_b);'


ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

logger:
  #level: DEBUG
  level: INFO

# Enable Home Assistant API
api:
  password: !secret api_password
  services:
    - service: hass_init_executed_set
      then:
        - lambda: |-
            id(hass_init_executed_state) = true;
        - binary_sensor.template.publish:
            id: hass_init_executed
            state: ON
    - service: beep_short
      then:
        - script.execute: beep_short
    - service: beep_short_twice
      then:
        - script.execute: beep_short_twice
    - service: beep_dee_dah
      then:
        - script.execute: beep_dee_dah
    - service: beep_dah_dee
      then:
        - script.execute: beep_dah_dee

    - service: external_buzzer_off
      then:
        - script.execute: script_external_buzzer_off

    - service: external_buzzer_beep_fast
      then:
        - script.execute: script_external_buzzer_beep_fast
    - service: external_buzzer_beep_very_fast
      then:
        - script.execute: script_external_buzzer_beep_very_fast
    - service: external_buzzer_beep_slow
      then:
        - script.execute: script_external_buzzer_beep_slow
    - service: external_buzzer_beep_very_slow
      then:
        - script.execute: script_external_buzzer_beep_very_slow

ota:
  password: !secret ota_password

script: !include scripts.yaml

wiegand:
  - id: reader
    d0: 36
    d1: 39
    on_raw:
      - script.execute: raw_value_wipe
      - lambda: |-
          std::string val =  str_sprintf("(%dbits) %x",bits,value);
          id(raw_value).publish_state(val);
      - script.execute: raw_value_wipe
      - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);

    on_tag:
      - if:
          condition:
            lambda: 'return id(tag_ena) == true;'
          then:
            - if:
                condition:
                  lambda: 'return id(kHz125) == true;'
                then:
                  - homeassistant.tag_scanned: !lambda |-
                      char buf[128];
                      sprintf(buf, "%s", x.c_str());
                      std::string s = buf;
                      std::string s1 = "ID_";
                      s.insert(s.begin(), 10 - s.size(), '0');
                      s1+=s;
                      return s1;
                  - script.execute: beep_dee_dah
                  - lambda: ESP_LOGD("TEST", "received tag %s", x.c_str());
                else:
                  - homeassistant.tag_scanned: !lambda |-
                      char buf[128];
                      sprintf(buf, "%s", x.c_str());
                      std::string s = buf;
                      std::string s1 = "IC_";
                      s.insert(s.begin(), 10 - s.size(), '0');
                      s1+=s;
                      return s1;
                  - script.execute: beep_dee_dah
                  - lambda: ESP_LOGD("TEST", "received tag %s", x.c_str());
          else:
            - script.execute: beep_short_four_times
button:
  - platform: restart
    name: "${tagreader_name} Restart button"
switch:
  - platform: restart
    name: "${tagreader_name} Restart"
    id: rst_switch
    internal: true
  - platform: template
    id: khz_125
    name: "${tagreader_name} 125 kHz"
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - lambda: |-
          id(kHz125) = true;
    turn_off_action:
      - lambda: |-
          id(kHz125) = false;
    lambda: return id(kHz125);
  - platform: template
    id: tag_enable
    name: "${tagreader_name} Tag Enable"
    restore_mode: RESTORE_DEFAULT_ON
    turn_on_action:
      - lambda: |-
          id(tag_ena) = true;
    turn_off_action:
      - lambda: |-
          id(tag_ena) = false;
    lambda: return id(tag_ena);
  - platform: template
    id: sound_enable
    name: "${tagreader_name} Sound Enable"
    restore_mode: RESTORE_DEFAULT_ON
    lambda: |-
      lambda: return id(sound_ena);
    turn_on_action:
      - lambda: |-
          id(sound_ena) = true;
    turn_off_action:
      - lambda: |-
          id(sound_ena) = false;


output:
  - id: led_output
    platform: gpio
    inverted: true
    pin: 4

  - id: buzzer_output
    platform: gpio
    inverted: true
    pin:
      number: 2

  - id: online_led_output
    platform: gpio
    inverted: false
    pin: GPIO14

  - id: external_buzzer_output
    platform: gpio
    inverted: false
    pin: GPIO15

light:
  - platform: binary
    id: led
    name: "${tagreader_name} LED"
    output: led_output
    effects: !include light_effects.yaml

  - platform: binary
    id: online_led
    name: "${tagreader_name} Online LED"
    output: online_led_output
    restore_mode: ALWAYS_OFF

  - platform: neopixelbus
    variant: APA106
    pin: GPIO12
    num_leds: 1
    default_transition_length: 10ms
    flash_transition_length: 10ms
    method:
      type: esp32_rmt
      channel: 0
    type: RGB
    id: status_led
    name: "${tagreader_name} Status LED"
    restore_mode: ALWAYS_OFF
    effects: !include rgb_light_effects.yaml

  - platform: binary
    id: external_buzzer
    name: "${tagreader_name} External Buzzer"
    internal: true
    output: external_buzzer_output
    effects: !include buzzer_effects.yaml

binary_sensor:
  - platform: status
    name: "${tagreader_name} Status"

  - platform: template
    name: "${tagreader_name} Buzzer busy"
    id: buzzer_busy

  - platform: template
    name: "${tagreader_name} Hass init executed"
    id: hass_init_executed
    publish_initial_state: true
    lambda: return id(hass_init_executed_state);

  - platform: gpio
    id: online_status
    pin:
      number: GPIO35
      inverted: true
    name: "${tagreader_name} Online status"
    internal: true
    on_state:
      then:
        - script.execute: online_light_set

  - platform: template
    name: "${tagreader_name} Heartbeat"
    id: heart_beat

text_sensor:
  - platform: version
    name: "${tagreader_name} ESPHome Version"

  - name: "${tagreader_name} Raw value"
    platform: template
    icon: mdi:raw
    id: raw_value
    #lambda: |-
    #  return {""};
    #update_interval: 60s
  - platform: ethernet_info
    ip_address:
      name: "${tagreader_name} IP address"

sensor:
  - platform: uptime
    name: "${tagreader_name} uptime"
    id: up_time
    update_interval: 10s

interval:
  - interval: 20sec
    then:
      - if:
          condition:
            api.connected:
          then:
            - lambda: |-
                id(heart_b) = !id(heart_b);
            - binary_sensor.template.publish:
                id: heart_beat
                state: !lambda 'return id(heart_b);'

      - if:
          condition:
            lambda: 'return id(api_was_connected) > 0;'
          then:
            - if:
                condition:
                  not:
                    api.connected:
                then:
                  - if:
                      condition:
                        lambda: 'return id(reboot_counter) == 0;'
                      then:
                        - light.turn_on:
                            id: led
                            effect: blink_very_fast
                        - light.turn_on:
                            id: status_led
                            effect: strobe_unknown_state
                  # Reboot after 20 cycles (20 * 20sec = 5min)
                  - if:
                      condition:
                        lambda: 'return id(reboot_counter) > 20;'
                      then:
                        - switch.turn_on: rst_switch
                        - lambda: |-
                            id(reboot_counter) = 0;
                  - lambda: |-
                      id(reboot_counter) += 1;
                  - script.execute: beep_short
                  #-
                else:
                  - if:
                      condition:
                        lambda: 'return id(reboot_counter) > 0;'
                      then:
                        - lambda: |-
                            id(reboot_counter) = 0;

                        - light.turn_off:
                            id: led
                        - light.turn_off:
                            id: status_led

                        - light.turn_on:
                            id: led
                            effect: "None"
                        - light.turn_on:
                            id: status_led
                            effect: "None"

                        - light.turn_off:
                            id: led
                        - light.turn_off:
                            id: status_led

                        - delay: 2000ms
                        - homeassistant.service:
                            service: script.${esphome_name}_init
                            data: {}
                        - script.execute: beep_short_twice
          # Should be impossible to come here, but is not.
          # It looks, firs intervall pass is called right after boot,
          # so it need more time to complete on_boot routines
          # (Learned this in harder way, briked device in endless reboot loop)
          else:
            - if:
                condition:
                  lambda: 'return id(reboot_counter) == 0;'
                then:
                  - light.turn_on:
                      id: led
                      effect: blink_very_fast
                  - light.turn_on:
                      id: status_led
                      effect: strobe_unknown_state
            # Reboot after 20 cycles (20 * 20sec = 5min)
            - if:
                condition:
                  lambda: 'return id(reboot_counter) > 20;'
                then:
                  - switch.turn_on: rst_switch
                  - lambda: |-
                      id(reboot_counter) = 0;
            - lambda: |-
                id(reboot_counter) += 1;
# EOF

Thanks @IgorZg –very helpful code. I was wondering if I need to connect the D0 and D1 output to specific pins… Do they need to be Serial, Analog, Control, etc.? Thanks

1 Like

Required reading. Probably most GPIOs are ok.

Any regular gpio will work. You gotta check though, a lot of those readers output 5v on their data lines. I tried looking in the data sheet but i didn’t see it mentioned or missed it completely. On mine keypad/rfid reader, it outputs 5v and likewise most of the ones ive seen people in use are 5v.

If you dont actually need an esp32, you can use an esp8266 NodeMCU which will handle 5v just fine or you’ll need to either buy or make a logic level shifter to drop that 5v to 3.3v.

Obviously check it with a multimeter first but, my money is on it being 5v.

I did see this in the data sheet if it helps. This is how you put it in Wiegand26 or Wiegand34 output mode, grounding the blue wire.

Thanks for this, indeed the output is at 5V –should I prefer certain GPIOs given this?

Hi folks –

Here’s my entire code, however I received nothing on the logs:

esphome:
  name: wiegand-keypad
  friendly_name: wiegand-keypad
  platform: ESP32
  board: mhetesp32devkit

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Wiegand-Keypad Fallback Hotspot"
    password: "xxxxxxxxxxxxxxxxxxx"

captive_portal:

wiegand:
  - id: reader
    d0: GPIO34
    d1: GPIO35
    on_key:
      - lambda: ESP_LOGI("KEY", "received key %d", x);        
    on_tag:
      - lambda: ESP_LOGI("TAG", "received tag %s", x.c_str());
    on_raw:
      - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);  

key_collector:
  - id: pincode_reader
    source_id: reader
    min_length: 4
    max_length: 4
    end_keys: "#"
    end_key_required: true
    back_keys: "*"
    clear_keys: "C"
    allowed_keys: "0123456789"
    timeout: 5s
    on_progress:
      - logger.log:
          format: "input progress: '%s', started by '%c'"
          args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ]
    on_result:
      - logger.log:
          format: "input result: '%s', started by '%c', ended by '%c'"
          args: [ 'x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)" ]
    on_timeout:
      - logger.log:
          format: "input timeout: '%s', started by '%c'"
          args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ]

The Wiegand reader is at Wiegand26 output with the blue wire connected to the ground.

Any advice? Thank you!

i also have one connected to a WT32-ETH01 board and it works well very simple setup on my end to just get the tag string.

esphome:
  name: esphome-front-door
  friendly_name: ESPHome Front Door
  platform: ESP32
  board: esp-wrover-kit


ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16
  manual_ip:
    static_ip: xxxxxxxxxx
    gateway: xxxxxxxxxx
    subnet: xxxxxxxxx

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxx"

web_server:
  auth:
    username: !secret web_server_username
    password: !secret web_server_password
  include_internal: true

ota:
  - platform: esphome

wiegand:
  - id: reader
    d0: GPIO4
    d1: GPIO2
    on_tag:
      then:
        - lambda: ESP_LOGD("TAG", "received tag %s", x.c_str());
        - logger.log: "Triggered"
        - homeassistant.tag_scanned: !lambda 'return x;'
        - lambda: |-
            std::string str = esphome::to_string(x);
            id(toggleBit) = true;
            id(tag_id).publish_state(str.c_str());
        - lambda: |-
            std::string str = esphome::to_string(x);
            id(readerBit) = true;
            id(alarm_reader).publish_state("Scanned");
    on_raw:
      - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);


globals:
  - id: toggleBit
    type: bool
    initial_value: 'false'
  - id: readerBit
    type: bool
    initial_value: 'false'

interval:
  - interval: 3000ms
    then:
      - lambda: |-
          if ((!id(toggleBit)) && (id(tag_id).state != "N/A")){
            id(tag_id).publish_state("N/A");
          }
          if(id(toggleBit)){
            id(toggleBit) = false;
          }
  - interval: 3000ms
    then:
      - lambda: |-
          if ((!id(readerBit)) && (id(alarm_reader).state != "Waiting")){
            id(alarm_reader).publish_state("Waiting");
          }
          if(id(readerBit)){
            id(readerBit) = false;
          }

text_sensor:
  - platform: template
    name: "Read ID"
    id: tag_id
  - platform: template
    name: "Alarm Reader"
    id: alarm_reader

Thanks, I don’t really understand what I am doing wrong…

Thanks for this @IgorZg –I found the issue, which was NOT grounding the ESP32 GND with the one on the Weigand keypad’s side.

I was wondering if you could also share your scripts, as the code you shared can be very useful to me. Thanks in advance!

Sure I can. This is content of scripts.yaml:

- id: beep_short
    then:
      - if:
          condition:
            lambda: 'return id(sound_ena) == true;'
          then:
            - script.execute: set_buzzer_busy
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 150ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - script.execute: set_buzzer_not_busy

  - id: beep_short_twice
    then:
      - if:
          condition:
            lambda: 'return id(sound_ena) == true;'
          then:
            - script.execute: set_buzzer_busy
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 150ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - script.execute: set_buzzer_not_busy

  - id: beep_short_four_times
    then:
      - if:
          condition:
            lambda: 'return id(sound_ena) == true;'
          then:
            - script.execute: set_buzzer_busy
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 150ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 150ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 150ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 75ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - script.execute: set_buzzer_not_busy

  - id: beep_dah_dee
    then:
      - if:
          condition:
            lambda: 'return id(sound_ena) == true;'
          then:
            - script.execute: set_buzzer_busy
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 350ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 100ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 100ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - script.execute: set_buzzer_not_busy

  - id: beep_dee_dah
    then:
      - if:
          condition:
            lambda: 'return id(sound_ena) == true;'
          then:
            - script.execute: set_buzzer_busy
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 100ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - delay: 100ms
            - output.turn_on: buzzer_output
            - output.turn_on: external_buzzer_output
            - delay: 350ms
            - output.turn_off: buzzer_output
            - output.turn_off: external_buzzer_output
            - script.execute: set_buzzer_not_busy

  - id: set_buzzer_busy
    then:
        - binary_sensor.template.publish:
           id: buzzer_busy
           state: ON

  - id: set_buzzer_not_busy
    then:
        - binary_sensor.template.publish:
           id: buzzer_busy
           state: OFF

  - id: raw_value_wipe
    mode: restart
    then:
      - delay: 60sec
      - lambda: id(raw_value).publish_state("");

  - id: online_light_set
    then:
      - if:
          condition:
            lambda: 'return id(online_status).state;'
          then:
            - logger.log: "True"
            - light.turn_on: online_led
          else:
            - logger.log: "False"
            - light.turn_off: online_led

  - id: script_external_buzzer_off
    then:
      - light.turn_off: external_buzzer

  - id: script_external_buzzer_beep_fast
    then:
      - light.turn_off: external_buzzer
      - light.turn_on:
          id: external_buzzer
          effect: beep_fast
  - id: script_external_buzzer_beep_very_fast
    then:
      - light.turn_off: external_buzzer
      - light.turn_on:
          id: external_buzzer
          effect: beep_very_fast
  - id: script_external_buzzer_beep_slow
    then:
      - light.turn_off: external_buzzer
      - light.turn_on:
          id: external_buzzer
          effect: beep_slow
  - id: script_external_buzzer_beep_very_slow
    then:
      - light.turn_off: external_buzzer
      - light.turn_on:
          id: external_buzzer
          effect: beep_very_slow

Also, light_effects.yaml:

- lambda:
          name: blink_very_slow
          update_interval: 4s
          lambda: |-
            if (id(led_status) == 0) {
              id(led_output).turn_on();
              id(led_status) = 1;
            } else {
              id(led_output).turn_off();
              id(led_status) = 0;
            }
      - lambda:
          name: blink_slow
          update_interval: 1s
          lambda: |-
            if (id(led_status) == 0) {
              id(led_output).turn_on();
              id(led_status) = 1;
            } else {
              id(led_output).turn_off();
              id(led_status) = 0;
            }
      - lambda:
          name: blink_fast
          update_interval: 100ms
          lambda: |-
            if (id(led_status) == 0) {
              id(led_output).turn_on();
              id(led_status) = 1;
            } else {
              id(led_output).turn_off();
              id(led_status) = 0;
            }
      - lambda:
          name: blink_very_fast
          update_interval: 50ms
          lambda: |-
            if (id(led_status) == 0) {
              id(led_output).turn_on();
              id(led_status) = 1;
            } else {
              id(led_output).turn_off();
              id(led_status) = 0;
            }
      - lambda:
          name: sos
          update_interval: 200ms
          lambda: |-
            // SOS ...---...
            id(led_status) = id(led_status) + 1;
            switch (id(led_status)){
              case 1:
              case 3:
              case 5:
              case 7:
              case 10:
              case 13:
              case 16:
              case 18:
              case 20:
                id(led_output).turn_on();
                break;
              case 2:
              case 4:
              case 6:
              case 9:
              case 12:
              case 15:
              case 17:
              case 19:
              case 21:
                id(led_output).turn_off();
                break;
              case 8:
              case 11:
              case 14:
              case 22:
              case 23:
              case 24:
              case 25:
              case 26:
                // do nothing
                break;
              default:
                id(led_status) = 0;
                break;
            }
      - lambda:
          name: very_short_blink
          update_interval: 250ms
          lambda: |-
            id(led_status) = id(led_status) + 1;
            switch (id(led_status)){
              case 1:
                id(led_output).turn_on();
                break;
              case 2:
                id(led_output).turn_off();
                break;
              case 3:
              case 4:
              case 5:
              case 6:
              case 7:
              case 8:
              case 9:
              case 10:
              case 11:
              case 12:
              case 13:
              case 14:
              case 15:
              case 16:
              case 17:
              case 18:
              case 19:
              case 20:
              case 21:
              case 22:
              case 23:
                // do nothing
                break;
              default:
                id(led_status) = 0;
                break;
            }
      - lambda:
          name: very_short_red
          update_interval: 250ms
          lambda: |-
            id(led_status) = id(led_status) + 1;
            switch (id(led_status)){
              case 1:
                id(led_output).turn_off();
                break;
              case 2:
                id(led_output).turn_on();
                break;
              case 3:
              case 4:
              case 5:
              case 6:
              case 7:
              case 8:
              case 9:
              case 10:
              case 11:
              case 12:
              case 13:
              case 14:
              case 15:
                // do nothing
                break;
              default:
                id(led_status) = 0;
                break;
            }

      - lambda:
          name: very_short_green
          update_interval: 250ms
          lambda: |-
            id(led_status) = id(led_status) + 1;
            switch (id(led_status)){
              case 1:
                id(led_output).turn_on();
                break;
              case 2:
                id(led_output).turn_off();
                break;
              case 3:
              case 4:
              case 5:
              case 6:
              case 7:
              case 8:
              case 9:
              case 10:
              case 11:
              case 12:
              case 13:
              case 14:
              case 15:
                // do nothing
                break;
              default:
                id(led_status) = 0;
                break;
            }

and rgb_light_effects.yaml:

#   effects:
      - strobe:
          name: strobe_alarm_disarmed
          colors:
            - state: True
              brightness: 10%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 20%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 30%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 40%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 50%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 40%
              red: 0%
              green: 100%
              blue: 0%                                                                             duration: 100ms
            - state: True
              brightness: 30%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 20%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 10%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: True
              brightness: 0%
              red: 0%
              green: 100%
              blue: 0%
              #duration: 4s
              duration: 2s
      - strobe:
          name: strobe_alarm_arming
          colors:
            - state: True
              brightness: 50%
              red: 0%
              green: 100%
              blue: 0%
              duration: 250ms
            - state: True
              brightness: 50%
              red: 100%
              green: 100%
              blue: 0%
              duration: 250ms
      - strobe:
          name: strobe_alarm_away_armed
          colors:
            - state: True
              brightness: 50%
              red: 100%
              green: 0%
              blue: 0%
              duration: 500ms
            - state: False
              duration: 4s
      - strobe:
          name: strobe_alarm_home_armed
          colors:
            - state: True
              brightness: 30%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 40%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 50%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 60%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 50%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 40%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: True
              brightness: 30%
              red: 0%
              green: 0%
              blue: 100%
              duration: 2s
      - strobe:
          name: strobe_alarm_tripping
          colors:
            - state: True
              brightness: 50%
              red: 100%
              green: 0%
              blue: 0%
              duration: 250ms
            - state: True
              brightness: 50%
              red: 0%
              green: 100%
              blue: 0%
              duration: 250ms
      - strobe:
          name: strobe_alarm_tripped
          colors:
            - state: True
              brightness: 50%
              red: 100%
              green: 0%
              blue: 0%
              duration: 250ms
            - state: True
              brightness: 50%
              red: 0%
              green: 0%
              blue: 100%
              duration: 250ms
      - strobe:
          name: strobe_input_expected
          colors:
            - state: True
              brightness: 20%
              red: 100%
              green: 80%
              blue: 0%
              duration: 100ms
            - state: False
              duration: 100ms
      - strobe:
          name: strobe_function_expected
          colors:
            - state: True
              brightness: 38%
              red: 0%
              green: 0%
              blue: 38%
              duration: 100ms
            - state: False
              duration: 100ms
      - strobe:
          name: strobe_unknown_state
          colors:
            - state: True
              brightness: 38%
              red: 100%
              green: 0%
              blue: 0%
              duration: 100ms
            - state: False
              duration: 500ms
            - state: True
              brightness: 38%
              red: 0%
              green: 100%
              blue: 0%
              duration: 100ms
            - state: False
              duration: 500ms
            - state: True
              brightness: 38%
              red: 0%
              green: 0%
              blue: 100%
              duration: 100ms
            - state: False
              duration: 500ms

Best regards!

1 Like

Here’s mine if it helps. Unlike the other example posted, I don’t send the Pin codes or Tag’s scanned to HA so they can be checked or whatever is done with them. I read the Pin/Tag on the Esp, compare it against known user’s pin/tag and everything is processed on the board first and then second sent to HA.

################ Guest Mode Timers  #############
# 
# Use both Start and Stop timers to specify which times of the day are allowed for the guest.
# 
# Example: Start Time 08:00:00Am - Stop Time 05:00:00Pm Will Only Allow Access between Those Times (9 Hours)

datetime:
 - platform: template
   id: guest_mode_start_time
   type: time
   name: "Guest Mode Time On"
   optimistic: yes
   initial_value: "08:00:00"
   restore_value: true
   on_time:
     - if:
        condition:
          - switch.is_on: guest_active     
        then:
          - switch.turn_on: guest_active

 - platform: template
   id: guest_mode_off_time
   type: time
   name: "Guest Mode Time Off"
   optimistic: yes
   initial_value: "05:00:00"
   restore_value: true
   on_time:
     - if:     
        condition:
          and:
            - text_sensor.state:
                id: ha_cover_state
                state: open

            - switch.is_on: guest_active
        then:
          - button.press: transmit_rf
        else:
          - switch.turn_off: guest_active

number:
  - platform: template
    name: "Set New Code"  
    id: new_keypad_code
    min_value: 0
    max_value: 9999
    step: 1
    mode: box
    restore_value: false
    optimistic: true
    on_value: 
      if:
        condition:
          - switch.is_on: guest_active
        then:
          - globals.set:
              id: temp_code
              value: !lambda 'return x;'
    




sun:
   latitude: 40.173568
   longitude: -86.0225536
   on_sunset:

    - light.turn_on:
        id: barn_overhead_led
        brightness: 50%
        white: 100% 
    - switch.turn_on:
        id: outside_barn_lights
     
       
   on_sunrise:
    - light.turn_off:
        id: barn_overhead_led
      
    - switch.turn_off:
        id: outside_barn_lights
  
time:
  - platform: homeassistant  
    id: homeassistant_time 

                                            
remote_transmitter:
  pin: 4
  carrier_duty_percent: 100%  

###########  Send Test Code + "#" key  to Keypad  #######

button:
  - platform: template
    name: "test send number"
    id: test_keysend
    on_press: 
      then:
        - lambda: |-
            id(pincode_reader).send_key('1');
        - delay: 250ms
      
        - lambda: |-
            id(pincode_reader).send_key('2');
        - delay: 250ms
    
        - lambda: |-
            id(pincode_reader).send_key('3');
        - delay: 250ms

        - lambda: |-
            id(pincode_reader).send_key('4');
        - delay: 50ms
          
        - lambda: |-
            id(pincode_reader).send_key('#');

  - platform: template
    id: transmit_rf
    name: "Overhead Door RF"
    on_press: 
      then:
        - remote_transmitter.transmit_rc_switch_raw:
            code: '00101001100111110101101'          ####  Test Code Only  '00100100100001'  #######      
            protocol: 1  
            repeat:
              times: 1
              wait_time: 0ms  

  - platform: restart
    id: keypad_restart 
    name: "Keypad Restart"

  - platform: safe_mode
    id: keypad_safemode 
    name: "Keypad (Safe Mode)"          






switch:

  - platform: template 
    name: "Auto-Restart 2x"
    id: auto_restart_keypad 
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON


###############  Enable/Disable Guest Mode for use with Keypad  #######
  - platform: template
    id: guest_active
    name: "Guest Mode"
    optimistic: True  
    restore_mode: DISABLED       
    on_turn_off: 
      then:
        - number.set:
            id: new_keypad_code
            value: 0

  - platform: template  
    id: ovrhead
    optimistic: true 
    on_turn_on:
      - homeassistant.service:
          service: switch.toggle
          data: 
           entity_id: switch.overhead_door_rf_barn_overhead_door 

  - platform: gpio
    pin:       
      number: 25
    #mode:
      inverted: true 
    name: 'Barn Door Lights'
    id: outside_barn_lights
    #optimistic: true

  - platform: gpio
    name: "Barn Switch 1"
    id: barn_switch1
    pin:     
      number: 15
      inverted: false 
    device_class: switch 

  

  - platform: gpio
    name: "Barn Switch 2"
    id: barn_switch2
    pin:      
      number: 5
      inverted: false 
    device_class: switch 

  - platform: template 
    name: "Barn Lights"
    id: barn_inside_lights
    optimistic: true 
    restore_mode: RESTORE_DEFAULT_OFF
    
    turn_on_action:  
       - switch.turn_on: barn_switch1
       - switch.turn_on: barn_switch2

    turn_off_action:
       - switch.turn_off: barn_switch1
       - switch.turn_off: barn_switch2
      
              
   

      
        
        


    
      





binary_sensor:       

  - platform: gpio 
    name: "Small Barn Door"
    pin:     
      number: 12      
      mode:
        input: true
        pullup: true
      inverted: true 
    id: barn_door_small 
    device_class: door   

#  - platform: gpio 
#    name: "Light Switch1"
#    id: barn_switch_sensor1 
#    pin:      
#      number: 23
#      mode:
#        input: true 
#        pullup: true 
#      inverted: False
#    filters:
#      - settle: 1.5s
#      - delayed_on_off: 1.5s           
#    on_state:          
#      - if:
#          condition:          
#            - switch.is_off: 
#                id: barn_switch1           
#          then:
#            - switch.turn_on:
#                id: barn_switch1
#          else:                         
#            - switch.turn_off: barn_switch1
              
             

          #      - switch.template.publish:
          #          id: barn_inside_lights
          #          state: OFF
          
          
          


  - platform: gpio 
    name: "Light Switch2"
    id: barn_switch_sensor2 
    pin:       
      number: 14
      mode:
        input: true 
        pullup: true 
      inverted: true 
    filters:
      - settle: 1.5s
      - delayed_on_off: 1.5s 
    on_state:         
      then:
        - switch.toggle: barn_switch1
        - switch.toggle: barn_switch2

  - platform: status
    id: keypad_status
    name: Barn Keypad Status  



text_sensor:  

  - platform: sun 
    name: Next Sunrise 
    type: sunrise 
    id: next_sunrise1 

  - platform: sun 
    name: Next Sunset 
    type: sunset
    id: next_sunset 

  - platform: template
    name: "Current Time"
    id: current_time
    update_interval: 5s
    lambda: return  id(homeassistant_time).utcnow();             # .now();           #######  .now().strftime("%I%M%p");  #######

  - platform: homeassistant
    entity_id: cover.overhead_door_rf_overhead
    id: ha_cover_state
    name: "Overhead Door"
    internal: false                    
               

  - platform: template
    name: Uptime Wg26
    id: uptime_human_wg26
    icon: mdi:clock-start

  - platform: wifi_info
    ip_address:
      name: Keypad IP Address
    ssid:
      name: Keypad Connected SSID    
   # mac_address:
    #  name: Keypad Mac Address
    scan_results:
      name: Keypad Latest Scan Results    
    dns_address:
      name: "dns used"
        

 

  - platform: template
    name: "Door Access Method"
    id: door_access_method                         

  - platform: template
    name: "Alarm State"
    id: alarm_state
    icon: mdi:account-multiple 

  - platform: template
    name: Last User
    id: last_user
    icon: mdi:clock-start   
    
         
      
  


globals:
  - id: method
    type: std::string
    restore_value: yes
    max_restore_data_length: 13
    initial_value: ""

  # Example for global string variable

  - id: last_user_access
    type: std::string
    restore_value: yes
    max_restore_data_length: 13
    initial_value: ""

  - id: temp_code
    type: int
    restore_value: yes
    max_restore_data_length: 4
    initial_value: ""
  


sensor:  
 
  - platform: duty_time
    id: small_door_open 
    name: "Door Open Time"
    # Support logical sources (optional): 'binary_sensor'
    sensor: barn_door_small        
    restore: true                                      # Sensor for last turn-on time (optional)
    last_time: 
      name: "Last Time Door Open"

  - platform: template
    name: Keypad Code
    id: keyCode    
    on_value:    
      - if:
         condition:
           - lambda: 'return id(keyCode).state == 1050;' 
         then:
           - lambda: |-
                  {         
                  id(ovrhead).toggle();
                  id(last_user).publish_state("Justin");   
                  id(door_access_method ).publish_state("Pin Code");
                  }                     
                     
      - if:
          condition:
            
              - lambda: 'return id(keyCode).state != 1050;'
              - lambda: 'return id(keyCode).state != 1955;'
              - lambda: 'return id(keyCode).state != 6800;'
              - lambda: 'return id(keyCode).state != 2014;'
              - lambda: 'return id(keyCode).state != id(temp_code);'
          then:
             - text_sensor.template.publish:     
                id: last_user
                state: "Invalid Code"

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 6800;' 
          then: 
            - lambda: |-
                  {            
                  id(ovrhead).toggle();
                  id(last_user).publish_state("Paula");
                  id(door_access_method ).publish_state("Pin Code");
                  }
              
                    
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 1955;' 
          then: 
             - lambda: |-
                  {            
                  id(ovrhead).toggle();
                  id(last_user).publish_state("Mike");
                  id(door_access_method ).publish_state("Pin Code");
                  }

              
                   
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 2014;'
          then:
             - lambda: |-
                  {            
                  id(ovrhead).toggle();
                  id(last_user).publish_state("Olive");
                  id(door_access_method ).publish_state("Pin Code");
                  }

      - if:
          condition:
            and:
              - switch.is_on: guest_active
              - lambda: 'return id(keyCode).state == id(temp_code);' 
          then: 
            - logger.log: "KeyCode equals temp code!"      
            - text_sensor.template.publish:
               id: last_user
               state: "Temp. Code"                 

                
           #  - lambda: |-
            #     if (x == "6789"); {            
             #     id(ovrhead).toggle();
              #    id(last_user).publish_state("Temp. Code");
               #   }
                 # id(last_user_access) = "Temp Code";
                                                      
     
      - if:
          condition:
            and:
             # - alarm_control_panel.is_armed: acp1
              - lambda: 'return id(keyCode).state == 6753957;' 
          then: 
           # - alarm_control_panel.disarm:
            #    id: acp1
             #   code: "2014" 
            - delay: 1s    
            - switch.toggle: ovrhead

            - text_sensor.template.publish:
                id: last_user
                state: "Justin Tag"
           

            - text_sensor.template.publish:     
                id: alarm_state
                state: "Disarmed By Justin"
                
            
          else:
         #   if:
          #    condition:
           #     not:
            #      - alarm_control_panel.is_armed: acp1
             # then:
                if:
                  condition:                    
                      - lambda: 'return id(keyCode).state == 6753957;' 
                  then:    
                     - lambda: |-
                              {         
                              id(ovrhead).toggle();
                              id(last_user).publish_state("Justin");   
                              id(door_access_method).publish_state("RFID Tag");
                              }                           
                             
                                                 



      - if:
            condition:
            - lambda: 'return id(keyCode).state == 6422842;' 
            then:    
                     - lambda: |-
                              {         
                              id(ovrhead).toggle();
                              id(last_user).publish_state("Paula");
                              id(door_access_method ).publish_state("RFID Tag");
                              }                          

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 6491970;' 
          then:    
                     - lambda: |-
                              {         
                              id(ovrhead).toggle();
                              id(last_user).publish_state("Mike");
                              id(door_access_method ).publish_state("RFID Tag");
                              }
                                                   

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 5553549;' 
          then:    
                     - lambda: |-
                               {         
                               id(ovrhead).toggle();
                               id(last_user).publish_state("Golf Cart Key1");

                               }
                                     
         
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 5627758;'
          then:
                     - lambda: |-
                               {
                               id(ovrhead).toggle();
                               id(last_user).publish_state("Golf Cart Key2");
                               }
     
         
      

     



  - platform: wifi_signal    
    id: wifi_signal_db
    update_interval: 300s
    entity_category: "diagnostic"
    internal: true 

  - platform: copy 
    source_id: wifi_signal_db
    name: "WiFi Signal Keypad"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "Signal %"
    entity_category: "diagnostic"
    id: wifiSignalWG26

  - platform: uptime #Uptime in Seconds
    name: Barn Keypad Uptime
    id: uptime_sensor_wiegand
    update_interval: 240s
    internal: True
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human_wg26
            state: !lambda |-
              int seconds = round(id(uptime_sensor_wiegand).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();

wiegand:
  - id: mykeypad
    d0: 21 ## Grn 
    d1: 19 ## Wht 
    on_key:
      - lambda: ESP_LOGI("KEY", "received key %d", x);
    on_tag:
      - lambda: ESP_LOGI("TAG", "received tag %s", x.c_str());
      - sensor.template.publish:
         id: keyCode
         state: !lambda "return parse_number<float>(x).value();"   
      - if:
          condition:      
            and:
              - lambda: 'return id(keyCode).state != 5553549;'
              - lambda: 'return id(keyCode).state != 6422842;' 
              - lambda: 'return id(keyCode).state != 6491970;'
              - lambda: 'return id(keyCode).state != 6753957;'
   #          - lambda: 'return id(keyCode).state != #######;'
   #          - lambda: 'return id(keyCode).state != #######;'
   #          - lambda: 'return id(keyCode).state != #######;'
                
          then:
            - text_sensor.template.publish:
                id: last_user
                state: "Invalid Tag Scanned"
     

     
          
    on_raw:
      - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);

key_collector:
  - id: pincode_reader
    source_id: mykeypad
    min_length: 4
    max_length: 5
    end_keys: "#"
    end_key_required: true
    clear_keys: "*"
    allowed_keys: "0123456789"
    timeout: 5s
    on_progress:
      - logger.log:
          format: "input progress: '%s', started by '%c'"
          args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ]
    on_result:      
      then:
        - sensor.template.publish:
            id: keyCode
            state: !lambda "return parse_number<float>(x).value();" 

       
    on_timeout:
      - logger.log:
          format: "input timeout: '%s', started by '%c'"
          args: [ 'x.c_str()', "(start == 0 ? '~' : start)" ]    



# D1


light:
  - platform: neopixelbus
    type: RGB 
    variant: WS2811
    pin: 17
    num_leds: 20
    id: barn_overhead_led
    name: "Barn Door LED Strip"
    
    
select:
  - platform: template
    id: barn_led_effect
    name: "Barn Light Effect"
    options: 
      - "R/W/B"
      - "B/R/W"
      - ""
    initial_option: ""
    optimistic: True
    on_value: 
      then:
        if:
          condition:
            - lambda: 'return id(barn_led_effect).state == "R/W/B";'
          then:
            - light.addressable_set: 
                id: barn_overhead_led
                range_from: 0
                range_to: 7
                red: 100%
                green: 0%
                blue: 0%
                color_brightness: 100%

            - light.addressable_set: 
                id: barn_overhead_led
                range_from: 8
                range_to: 14
                red: 0%
                green: 0%
                blue: 0%
                white: 100%
                color_brightness: 100%

            - light.addressable_set: 
                id: barn_overhead_led
                range_from: 15
                range_to: 20
                red: 0%
                green: 0%
                blue: 100%
                color_brightness: 100%
                

               


interval:
 - interval: 1min
   then:
     - if:
         condition:
           and:
             - sun.is_below_horizon: 
             - light.is_off: 
                 id: barn_overhead_led 
         then:
           - light.turn_on:
               id: barn_overhead_led
               brightness: 75%
               red: 0%
               green: 0%
               blue: 100%

     - if:
         condition:
           and:          
             - sun.is_above_horizon: 
             - light.is_on: 
                 id: barn_overhead_led 
         then:
           - light.turn_off:  
               id: barn_overhead_led     

     - if:
         condition:
           and:          
             - sun.is_above_horizon: 
             - switch.is_on: 
                 id: outside_barn_lights 
         then:
           - switch.turn_off:  
               id: outside_barn_lights