Access control with ESPHome, Home Assistant and Node Red


I have three garage doors I needed RFID access control for. All of them are already controlled by Home Assistant using ESP8266’s and ESPHome. So what I needed was a simple RFID reader that could send tag ID to Home Assistant for processing. Home Assistant will check if the tag is valid and if so, which door to open. The tag reader is relatively cheap one from Ali Express combined with an Wemos D1 mini running ESPHome, which is natively supported in Home Assistant.

I have two different kind of readers, one simple for my workshop door, and one more complex for the dual garage doors. The latter one features two wiegand readers as seen in the video, one for each door. In addition it has two physical buttons on the inside for controlling the doors from inside. Both of the readers feature a buzzer.

The code for the simple one is here:

esphome:
  includes:
    - wiegand_device.h
  name: rfid-verksted
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "your_ssid"
  password: "your_pwd"

captive_portal:
logger:
api:
ota:

light:
  - platform: status_led
    name: "LED"
    pin:
      number: D4
      #inverted: true
    internal: true
    
sensor:
- platform: custom
  lambda: |-
    auto wiegand = new WiegandReader(D1, D2);
    App.register_component(wiegand);
    return {wiegand};
  sensors:
    name: "RFID Verksted"
    on_value:
      then:
        - homeassistant.tag_scanned: !lambda |-
            char buf[16];
            sprintf(buf, "%.0f", x);
            std::string s = buf;
            std::string y = "Verksted: " + s;
            return y;        


   

switch:
- platform: gpio
  id: "beep"
  pin: D3
  inverted: yes
  internal: true
  
- platform: template 
  name: "Denied beep Verksted"
  icon: "mdi:bell-alert"
  id: long_beep
  turn_on_action:
    - switch.turn_on: beep
    - delay: 100ms 
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - switch.turn_off: long_beep

- platform: template 
  name: "Granted beep Verksted"
  icon: "mdi:bell-alert-outline" 
  id: two_beep
  turn_on_action:
    - switch.turn_on: beep
    - delay: 100ms 
    - switch.turn_off: beep
    - switch.turn_off: two_beep               

Code for the more complex one is here:

esphome:
  includes:
    - wiegand_device.h
    - wiegand_device2.h
  name: rfid-garasje
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "your_ssid"
  password: "your_pwd"

captive_portal:
logger:
api:
ota:

light:
  - platform: status_led
    name: "LED"
    pin:
      number: D4
      #inverted: true
    internal: true
    
sensor:
- platform: custom
  lambda: |-
    auto wiegand = new WiegandReader(D1, D2);
    App.register_component(wiegand);
    return {wiegand};
  sensors:
    name: "RFID Garasje Høyre"
    on_value:
      then:
        - homeassistant.tag_scanned: !lambda |-
            char buf[16];
            sprintf(buf, "%.0f", x);
            std::string s = buf;
            std::string y = "GarasjeH: " + s;
            return y;        

- platform: custom
  lambda: |-
    auto wiegand = new WiegandReader2(D7, D8);
    App.register_component(wiegand);
    return {wiegand};
  sensors:
    name: "RFID Garasje Venstre"
    on_value:
      then:
        - homeassistant.tag_scanned: !lambda |-
            char buf[16];
            sprintf(buf, "%.0f", x);
            std::string u = buf;
            std::string t = "GarasjeV: " + u;
            return t;        
   
binary_sensor:
- platform: gpio
  pin:
    number: D6
    inverted: true
    mode:
      input: true
      pullup: true
  name: RFID knapp høyre port
  filters:
    - delayed_on: 20ms
    - delayed_off: 100ms
- platform: gpio
  pin:
    number: D5
    inverted: true
    mode:
      input: true
      pullup: true
  name: RFID knapp venstre port
  filters:
    - delayed_on: 20ms      
    - delayed_off: 100ms  
switch:
- platform: gpio
  id: "beep"
  pin: D3
  inverted: yes
  internal: true
  
- platform: template 
  name: "Denied beep Garasje"
  icon: "mdi:bell-alert"
  id: long_beep
  turn_on_action:
    - switch.turn_on: beep
    - delay: 100ms 
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - delay: 100ms
    - switch.turn_on: beep
    - delay: 100ms
    - switch.turn_off: beep
    - switch.turn_off: long_beep

- platform: template 
  name: "Granted beep Garasje"
  icon: "mdi:bell-alert-outline" 
  id: two_beep
  turn_on_action:
    - switch.turn_on: beep
    - delay: 100ms 
    - switch.turn_off: beep
    - switch.turn_off: two_beep               

Wiring is easy, just read the code. As wiegand protocol is not natively supported in ESPHome, you also need to put the file “wiegand_device.h” in the esphome folder in Home Asssistant.

When everything is set up correctly, scanned tags are sent to Home Assistant as “tag_scanned” events, and will also show up in the native Home Assistant “Tags” section. The format tags are sent in is [reader_name]: [tag_id]. This can of course easily be changed in the code to e.g. just send the tag ID.

I use node red to listen to tag_scanned events, and when discovered, it splits the response in two, checks latter part (tag_id), if approved, checks first part (which reader), sends beeps to the reader buzzer, and then opens the door. If tag is invalid a rapid series of beeps is played in the reader buzzer.

Probably forgot a lot, if anyone is interrested in building something similar, I’d be happy to help.

10 Likes