Am in the process of setting up an RFID access door for my pets. Picked up one of these of AliExpress for about $50. I thought I had seen someone who had made it work, but it turns out that was for a different board. So I whipped up this piece of garbage and figured I would share it for anyone who was looking for it. It’s reliably reading tags from about 10-20 inches for me.
The module has the antenna and a built in serial connection that can interface with an ESP32 via UART. Commands and responses can be found HERE
The code below does a few things as proof of concept more than anything usable just yet. It will read the firmware and serial of the antenna and is setup to be able to send debug commands from the web interface. There is a very rudimentary polling setup, but I haven’t put it into production so it needs refinement.
Hope it helps someone!
esphome:
name: rfid-sensor
friendly_name: rfid-sensor
# Get initial information from RFID board
on_boot:
- priority: -100
then:
- delay: 3s
- uart.write: "N0,00\r\n"
- delay: 1s
- uart.write: "V\r\n"
- delay: 1s
- uart.write: "S\r\n"
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
baud_rate: 115200
# Enable Home Assistant API
api:
encryption:
key:
ota:
- platform: esphome
password:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Rfid-Sensor Fallback Hotspot"
password:
captive_portal:
web_server:
# Set Allowed RFID Tags Here
globals:
- id: tags
type: std::vector<std::string>
restore_value: no
initial_value: '{"3000E28011606000020786EDD9E6D3E0",
"3000E28011606000020786EE223B5F5B",
"3000E28011606000020786EDF0ECCED4",
"3000E28011606000020786EE0BE8183B",
"3000E28011606000020786EDE0853028"}'
# Setup RFID Polling
interval:
- interval: .25s
then:
- if:
condition:
- switch.is_on: rfid_poll_enable
then:
- uart.write: "Q\r\n"
# Configure UART Debugging Sensor
uart:
baud_rate: 38400
tx_pin: 17
rx_pin: 16
id: UART3
debug:
direction: BOTH
dummy_receiver: true
after:
delimiter: "\r\n"
sequence:
- lambda: |-
UARTDebug::log_string(direction, bytes); //Still log the data
std::string str(bytes.begin(), bytes.end());
str.erase(std::remove(str.begin(), str.end(), '\n'), str.cend());
str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend());
if (direction == UART_DIRECTION_TX) //Store the Last Sent Command To Interpret Results
{
id(uart_tx_command).publish_state(str.c_str());
}
else // Process Results
{
std::string prefix_code = str.substr(0, 1);
str = str.erase(0,1);
if (prefix_code[0] == 'Q')
{
bool found = std::find(id(tags).begin(), id(tags).end(), str) != id(tags).end();
if (found)
{
id(rfid_access_granted).publish_state(true);
id(rfid_last_access).publish_state(str.c_str());
}
}
else if (prefix_code[0] == 'V') // Major Minor Version
{
id(info_firmware).publish_state(str.c_str());
}
else if (prefix_code[0] == 'S') // Reader ID
{
id(info_receiver_id).publish_state(str.c_str());
}
else if (prefix_code[0] == 'N')
{
if (id(uart_tx_command).state == "N0,00")
{
int decimalValue = ((std::stoi(str, nullptr, 16)) - 2);
id(info_receiver_gain).publish_state(decimalValue);
}
else
{
id(uart_rx_response).publish_state(str.c_str());
}
}
else
{
if (str.length() > 1)
{
id(uart_rx_response).publish_state(str.c_str());
}
}
}
text_sensor:
- platform: template
id: "info_firmware"
name: "info_firmware"
- platform: template
id: "info_receiver_id"
name: "info_receiver_id"
- platform: template
id: "rfid_last_access"
name: "rfid_last_access"
- platform: template
id: "uart_rx_response"
name: "uart_rx_response"
- platform: template
id: "uart_tx_command"
name: "uart_tx_command"
text:
- platform: template
name: "uart_tx_debug"
id: "uart_tx_debug"
mode: text
optimistic: true
on_value:
then:
- uart.write:
data: !lambda |-
std::string str = ("\n" + id(uart_tx_debug).state + "\r\n");
std::vector<uint8_t> vec(str.begin(), str.end());
return vec;
sensor:
- platform: template
id: "info_receiver_gain"
name: "info_receiver_gain"
unit_of_measurement: "dB"
accuracy_decimals: 0
button:
- platform: template
name: "button_scan_tag"
id: "button_scan_tag"
on_press:
- uart.write: "Q\r\n"
- platform: template
name: "button_resend_tx_debug"
id: "button_resend_tx_debug"
on_press:
then:
- uart.write:
data: !lambda |-
std::string str = ("\n" + id(uart_tx_debug).state + "\r\n");
std::vector<uint8_t> vec(str.begin(), str.end());
return vec;
switch:
- platform: template
name: "rfid_poll_enable"
id: "rfid_poll_enable"
optimistic: True
on_turn_on:
then:
- switch.turn_off: rfid_access_granted
- platform: template
name: "rfid_access_granted"
id: "rfid_access_granted"
optimistic: True
on_turn_on:
then:
- if:
condition:
- switch.is_on: rfid_poll_enable
then:
- delay:
seconds: 3
- switch.turn_off: rfid_access_granted