Last active
November 4, 2023 18:59
-
-
Save Resinchem/f832d8e7305730cc0af8932d51f22335 to your computer and use it in GitHub Desktop.
ESPHome code for a Home Assistant DIY tag reader
This file contains 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
# ========================================================= | |
# This code is a slightly modified version of the original | |
# by Adonno and contains the modifications for some hardware | |
# changes. | |
# | |
# See the following for build details and use: | |
# YouTube Video: https://youtu.be/5Xo8yc4tQYc | |
# Written Blog: https://resinchemtech.blogspot.com/2023/07/nfc-tag-reader.html | |
# ========================================================= | |
esphome: | |
name: tagreader-basement # <========= Optionally rename | |
platform: ESP8266 | |
board: d1_mini | |
on_boot: | |
priority: -10 | |
then: | |
- wait_until: | |
api.connected: | |
- logger.log: API is connected! | |
- switch.turn_on: vibra | |
- light.turn_on: | |
id: activity_led | |
brightness: 100% | |
red: 0% | |
green: 0% | |
blue: 100% | |
flash_length: 500ms | |
- switch.turn_on: buzzer_enabled | |
- switch.turn_on: led_enabled | |
ota: | |
password: !secret ota_password # <======= CHANGE THIS OR ASSURE YOU HAVE AN OTA PASSWORD IN SECRETS | |
wifi: | |
ssid: !secret wifi_ssid # <======= CHANGE THIS OR ASSURE YOU HAVE A WIFI_SSID IN SECRETS | |
password: !secret wifi_password # <======= CHANGE THIS OR ASSURE YOU HAVE A WIFI PASSWORD IN SECRETS | |
# Enable fallback hotspot (captive portal) in case wifi connection fails | |
ap: | |
ssid: "Tagreader" | |
password: !secret ap_password | |
# Enable Home Assistant API | |
api: | |
encryption: | |
key: "qImmVdjxe45eqioCF6s8AxK200/yyr68tDYva9H/L34=" #your auto-generated key will be different | |
services: | |
- service: rfidreader_tag_ok | |
then: | |
- switch.turn_on: vibra | |
- service: rfidreader_tag_ko | |
then: | |
- switch.turn_on: vibra | |
- service: write_tag_id | |
variables: | |
tag_id: string | |
then: | |
- light.turn_on: | |
id: activity_led | |
brightness: 100% | |
red: 100% | |
green: 0% | |
blue: 0% | |
- lambda: |- | |
auto message = new nfc::NdefMessage(); | |
std::string uri = "https://www.home-assistant.io/tag/"; | |
uri += tag_id; | |
message->add_uri_record(uri); | |
id(pn532_board).write_mode(message); | |
- switch.turn_on: vibra | |
- wait_until: | |
not: | |
pn532.is_writing: | |
- light.turn_off: | |
id: activity_led | |
- switch.turn_on: vibra | |
- service: write_music_tag | |
variables: | |
music_url: string | |
music_info: string | |
then: | |
- light.turn_on: | |
id: activity_led | |
brightness: 100% | |
red: 100% | |
green: 0% | |
blue: 0% | |
- lambda: |- | |
auto message = new nfc::NdefMessage(); | |
std::string uri = ""; | |
std::string text = ""; | |
uri += music_url; | |
text += music_info; | |
if ( music_url != "" ) { | |
message->add_uri_record(uri); | |
} | |
if ( music_info != "" ) { | |
message->add_text_record(text); | |
} | |
id(pn532_board).write_mode(message); | |
- switch.turn_on: vibra | |
- wait_until: | |
not: | |
pn532.is_writing: | |
- light.turn_off: | |
id: activity_led | |
- switch.turn_on: vibra | |
# Enable logging | |
logger: | |
substitutions: | |
name: tagreader_basement # <========= Optionally rename | |
friendly_name: TagReader Basement # <========= Optionally rename | |
globals: | |
- id: source | |
type: std::string | |
- id: url | |
type: std::string | |
- id: info | |
type: std::string | |
captive_portal: | |
i2c: | |
scan: False | |
frequency: 400kHz | |
# Define switches to control LED and buzzer from HA | |
switch: | |
- platform: template | |
name: "${friendly_name} Buzzer Enabled" | |
id: buzzer_enabled | |
icon: mdi:volume-high | |
optimistic: true | |
restore_state: true | |
entity_category: config | |
- platform: template | |
name: "${friendly_name} LED enabled" | |
id: led_enabled | |
icon: mdi:alarm-light-outline | |
optimistic: true | |
restore_state: true | |
entity_category: config | |
# Vibration Motor - replaces original piezo buzzer | |
- platform: gpio | |
id: vibra | |
pin: GPIO15 | |
name: "Vibration" | |
restore_mode: ALWAYS_OFF | |
on_turn_on: | |
- delay: 500ms | |
- switch.turn_off: vibra | |
# Define buttons for writing tags via HA | |
button: | |
- platform: template | |
name: Write Tag Random | |
id: write_tag_random | |
# Optional variables: | |
icon: "mdi:pencil-box" | |
on_press: | |
then: | |
- light.turn_on: | |
id: activity_led | |
red: 100% | |
green: 0% | |
blue: 100% | |
- lambda: |- | |
static const char alphanum[] = "0123456789abcdef"; | |
std::string uri = "https://www.home-assistant.io/tag/"; | |
for (int i = 0; i < 8; i++) | |
uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; | |
uri += "-"; | |
for (int j = 0; j < 3; j++) { | |
for (int i = 0; i < 4; i++) | |
uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; | |
uri += "-"; | |
} | |
for (int i = 0; i < 12; i++) | |
uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; | |
auto message = new nfc::NdefMessage(); | |
message->add_uri_record(uri); | |
ESP_LOGD("tagreader", "Writing payload: %s", uri.c_str()); | |
id(pn532_board).write_mode(message); | |
- switch.turn_on: vibra | |
- wait_until: | |
not: | |
pn532.is_writing: | |
- light.turn_off: | |
id: activity_led | |
- switch.turn_on: vibra | |
- platform: template | |
name: Clean Tag | |
id: clean_tag | |
icon: "mdi:nfc-variant-off" | |
on_press: | |
then: | |
- light.turn_on: | |
id: activity_led | |
brightness: 100% | |
red: 100% | |
green: 100% | |
blue: 0% | |
- lambda: 'id(pn532_board).clean_mode();' | |
- switch.turn_on: vibra | |
- wait_until: | |
not: | |
pn532.is_writing: | |
- light.turn_off: | |
id: activity_led | |
- switch.turn_on: vibra | |
- platform: template | |
name: Cancel writing | |
id: cancel_writing | |
icon: "mdi:pencil-off" | |
on_press: | |
then: | |
- lambda: 'id(pn532_board).read_mode();' | |
- light.turn_off: | |
id: activity_led | |
- switch.turn_on: vibra | |
- platform: restart | |
name: "${friendly_name} Restart" | |
entity_category: config | |
pn532_i2c: | |
id: pn532_board | |
on_tag: | |
then: | |
- if: | |
condition: | |
switch.is_on: led_enabled | |
then: | |
- light.turn_on: | |
id: activity_led | |
brightness: 100% | |
red: 0% | |
green: 100% | |
blue: 0% | |
flash_length: 500ms | |
- delay: 0.15s #to fix slow component | |
- lambda: |- | |
id(source)=""; | |
id(url)=""; | |
id(info)=""; | |
if (tag.has_ndef_message()) { | |
auto message = tag.get_ndef_message(); | |
auto records = message->get_records(); | |
for (auto &record : records) { | |
std::string payload = record->get_payload(); | |
std::string type = record->get_type(); | |
size_t hass = payload.find("https://www.home-assistant.io/tag/"); | |
size_t applemusic = payload.find("https://music.apple.com"); | |
size_t spotify = payload.find("https://open.spotify.com"); | |
size_t sonos = payload.find("sonos-2://"); | |
if (type == "U" and hass != std::string::npos ) { | |
ESP_LOGD("tagreader", "Found Home Assistant tag NDEF"); | |
id(source)="hass"; | |
id(url)=payload; | |
id(info)=payload.substr(hass + 34); | |
} | |
else if (type == "U" and applemusic != std::string::npos ) { | |
ESP_LOGD("tagreader", "Found Apple Music tag NDEF"); | |
id(source)="amusic"; | |
id(url)=payload; | |
} | |
else if (type == "U" and spotify != std::string::npos ) { | |
ESP_LOGD("tagreader", "Found Spotify tag NDEF"); | |
id(source)="spotify"; | |
id(url)=payload; | |
} | |
else if (type == "U" and sonos != std::string::npos ) { | |
ESP_LOGD("tagreader", "Found Sonos app tag NDEF"); | |
id(source)="sonos"; | |
id(url)=payload; | |
} | |
else if (type == "T" ) { | |
ESP_LOGD("tagreader", "Found music info tag NDEF"); | |
id(info)=payload; | |
} | |
else if ( id(source)=="" ) { | |
id(source)="uid"; | |
} | |
} | |
} | |
else { | |
id(source)="uid"; | |
} | |
- if: | |
condition: | |
lambda: 'return ( id(source)=="uid" );' | |
then: | |
- homeassistant.tag_scanned: !lambda |- | |
ESP_LOGD("tagreader", "No HA NDEF, using UID"); | |
return x; | |
else: | |
- if: | |
condition: | |
lambda: 'return ( id(source)=="hass" );' | |
then: | |
- homeassistant.tag_scanned: !lambda 'return id(info);' | |
else: | |
- homeassistant.event: | |
event: esphome.music_tag | |
data: | |
reader: !lambda |- | |
return App.get_name().c_str(); | |
source: !lambda |- | |
return id(source); | |
url: !lambda |- | |
return id(url); | |
info: !lambda |- | |
return id(info); | |
- if: | |
condition: | |
switch.is_on: buzzer_enabled | |
then: | |
- switch.turn_on: vibra | |
on_tag_removed: | |
then: | |
- homeassistant.event: | |
event: esphome.tag_removed | |
# LED Indicator (replaces original WS2812b pixel) | |
light: | |
- platform: rgb | |
id: activity_led | |
name: "RGB LED" | |
red: output_red | |
green: output_green | |
blue: output_blue | |
output: | |
- platform: esp8266_pwm | |
id: output_red | |
pin: GPIO2 | |
inverted: true | |
- platform: esp8266_pwm | |
id: output_green | |
pin: GPIO14 | |
inverted: true | |
- platform: esp8266_pwm | |
id: output_blue | |
pin: GPIO12 | |
inverted: true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment