ESPHome Wiegand to Home Assistant

My ESPHome device can successfully decode an RFID tag. The ESPHome device has been added to HA. However, I don’t see any entities in this device. Other ESPHome devices do have entities that can be used to create Automations. Below is the ESPHome yaml code and the serial output of the device. I’m new to HA and sure that it’s something obvious. Any hints would be appreciated.

wiegand-reader.yaml

esphome:
  name: wiegand-reader
  friendly_name: Wiegand Reader

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

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

ota:
  password: "xxxxxxxxxxxx"

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

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

captive_portal:

wiegand:
  - id: frontdoor
    d0: 33
    d1: 27
    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);

Serial Output:

[C][wiegand:121]: Wiegand reader:
[C][wiegand:122]:   D0 pin: GPIO33
[C][wiegand:123]:   D1 pin: GPIO27
[C][captive_portal:088]: Captive Portal:
[C][mdns:115]: mDNS:
[C][mdns:116]:   Hostname: wiegand-reader
[C][ota:097]: Over-The-Air Updates:
[C][ota:098]:   Address: wiegand-reader.local:3232
[C][ota:101]:   Using Password.
[C][api:138]: API Server:
[C][api:139]:   Address: wiegand-reader.local:6053
[C][api:141]:   Using noise encryption: YES
[D][api:102]: Accepted 192.168.1.72
[D][api.connection:1031]: Home Assistant 2023.9.3 (192.168.1.72): Connected successfully
[D][wiegand:073]: received 26-bit tag: 12345678
[D][wiegand:073]: received 26-bit tag: 12345678
[D][wiegand:073]: received 26-bit tag: 12345678

I think a template text sensor Template Text Sensor — ESPHome updated by wiegand’s on_tag.

The wiegand component doesn’t create any entities, it reads a tag or keypad and decodes it. If you want sensors or entities then you need to create them. For mine, I assigned a name to each code and tag. On a code or tag scan if it matches a user, a sensor is “last user” sensor is updated. If it doesn’t match then it’s an invalid user. There’s a ton of stuff you can do here, it depends on what you want and your willingness to read the documentation.

switch:
  platform: template  
  id: OvrHead
  optimistic: true 
  on_turn_on:
      - homeassistant.service:
          service: switch.toggle
          data: 
           entity_id: switch.overhead_door_barn_overhead 


button:
  - platform: restart
    name: "Keypad Restart"
  - platform: safe_mode
    name: "Keypad (Safe Mode)"  


binary_sensor:  

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

text_sensor:  

  - 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    
    
    scan_results:
      name: Keypad Latest Scan Results    

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

  
  

sensor:

  - platform: template
    name: Keypad Code
    id: keyCode    
    on_value:
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 6722842;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Mike's Tag"
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 1050;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Justin's Code"          

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 6422842;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Paula's Tag"
      - if:
          condition:
            - lambda: 'return id(keyCode).state == 1955;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Paula's Code"    

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 5553549;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Golf Cart Tag"                

      - if:
          condition:
            - lambda: 'return id(keyCode).state == 6491970;' 
          then:  
            - switch.toggle: OvrHead
            - text_sensor.template.publish:
                id: last_user
                state: "Mike's Tag"
         
      - if:
          condition:
            - lambda: 'return id(keyCode).state != 5553549;' 
            - lambda: 'return id(keyCode).state != 6422842;' 
            - lambda: 'return id(keyCode).state != 6722842;'
            - lambda: 'return id(keyCode).state != 6491970;'
            - lambda: 'return id(keyCode).state != 6753957;'
            - lambda: 'return id(keyCode).state != 1050;'
            - lambda: 'return id(keyCode).state != 1955;'
          then:
            - text_sensor.template.publish:
                id: last_user
                state: "Invalid User Access"



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

  - 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: D7
    d1: D6
    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();"        
          
    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)" ]  

This guy made a whole program to add users or codes from the HA font end, he also made it so you can reset codes from the keypad itself. It’s kind of overkill IMO and takes some time to understand the program flow but, you might find it useful or find inspiration by looking through his code.

Thanks to both. I have the basic communication working now!

1 Like

Just out of curiosity, which one did you go with? As far as which keypad/tag scanner. There are so many on the market, I’m just curious which ones people have good results with.

I got a cheap Wiegand 12V reader only. I’m using a logic level converter to bring down the levels.
This was the Amazon listing ($CAD20):

“EVTSCAN Security RFID Card Access Control Reader 125KHz Wiegand 26/34 Waterproof(Black ID 125Khz)”

In the end I found this easy one liner:
homeassistant.tag_scanned: !lambda 'return x.c_str();'

Here is the full yaml file:

esphome:
  name: wiegand-reader
  friendly_name: Wiegand Reader

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxx="

ota:
  password: "xxxxxxxxxxxxxxx"

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

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

captive_portal:

wiegand:
  - id: frontdoor
    d0: 33
    d1: 27
    on_key:
      - lambda: ESP_LOGI("KEY", "received key %d", x);
    on_tag:
      - lambda: ESP_LOGI("TAG", "received tag %s", x.c_str());
      - homeassistant.tag_scanned: !lambda 'return x.c_str();'
    on_raw:
      - lambda: ESP_LOGI("RAW", "received raw %d bits, value %llx", bits, value);

In HA go to Settings → Tags. When you scan a new tag it automatically shows up in the list and you can add a friendly name and then add an automation if you like.

1 Like

You know the same automations can be done right there in esphome? The problem with your “easy” one liner is its going to be useless in the event there’s a breakdown in communication between the node and HA or HA is down. You could have used an esp8266 and wouldn’t have needed logic shifting too. Rfid reader straight to esp board and done.

Yes, for a small static use case that would probably be better.

I didn’t know the ESP8266 supported 12V logic. The datasheet says 3.6V max. Edit: It looks like wiegand uses 3-5v logic…I’ll check it out on a scope. It would be great to remove the logic level converter.

They don’t.

Every Wiegand tag reader/keypad I’ve seen, they output roughly 4.96v. The gpios on the esp8266 are indeed 5v tolerant and is exactly how mine and many others are wired. 12v is the operating voltage of the keypad, not the data output.

It’s not static? The tag reader is portable?

There is some debate about 5v. The docs say 3.3v but there was some comment once from the manufacturer that 5v is fine.

Hi

I would like to add a RFID/Keypad to Home Assistant but have no clue what hardware is required.

I have looked on esphome and there is a devise listed

but how do you connect the Wiegand out put to home assistant to get the tag info into HA

Thanks

An esp board… Esphome is for esp boards… to make things simple id recommend an esp8266 NodeMCU. That board you can wire the keypad directly to it because its 5v tolerant whereas the esp32 isnt and you’d also need a logic level converter.

Once you hook up the keypad the esp board sends the tags scanned and keys pressed to HA. The instruction book will tell you what wires are for what. You will likely need a 12v power supply to power the keypad and you need a 5v power supply for the esp board. The keypad will have 2 data wires, those go to the esp board and you will need a common ground so the 5v and 12v grounds need connected together.

Depending on the keypad it may or may not come in Wiegand26 output by default, mine didnt but, the manual tells you how to do it, you gotta read it, you gotta make an effort.

i see a lot of people using esp32 boards.
will this work with a D1 mini 8266?

Have connected Dahua card reader (12V powered) to D1 mini - directly to GPIO.
Working with no issues.

Try it… this is how the learning process works.