############################################# ############################################# # # ESP Home # NFC Tag Reader for Home Assistant # ############################################# ############################################# # Project Link: # https://github.com/adonno/tagreader ############################################# # Remember to set the switches on the PN532 # for i2C, Switch1: On (up), Switch2: Off (down) ############################################# ############################################# # Substitution Text ############################################# substitutions: name: esp-nfcaccess1-33ad74 friendly_name: TagReader ############################################# # Inport the project from Github ############################################# #dashboard_import: # package_import_url: github://adonno/tagreader/tagreader.yaml ############################################# # Use Wifi ############################################# wifi: ssid: !secret wifi_ssid password: !secret wifi_password # Details for fallback hotspot (captive portal) # in case wifi connection fails ap: ssid: "${name} Hotspot" password: !secret fallback_ap_password ############################################# # Improv # Use the open Improv standard for configuring Wi-Fi on the # device by using a serial connection to the device, eg. USB. ############################################# improv_serial: ############################################# # Fallback captive portal # Enable the captive portal for inital WiFi setup ############################################# captive_portal: ############################################# # Enable Over the Air Update Capability # Safe mode will detect boot loops ############################################# ota: safe_mode: true # Avoid boot loops password: !secret esp-nfcaccess1-33ad74_ota_pass ############################################# # ESPHome Logging Enable ############################################# logger: # baud_rate: 0 # Set baud rate to 0 if using the UART for soething else # level: VERY_VERBOSE # level: VERBOSE ############################################# # Web Portal for display and monitoring ############################################# #web_server: # port: 80 # auth: # username: !secret web_server_username # password: !secret web_server_password ######################################## # Specific board for ESPHome device ######################################## esp8266: board: d1_mini ############################################# # ESPHome ############################################# esphome: name: ${name} # Automatically add the mac address to the name # so you can use a single firmware for all devices name_add_mac_suffix: false # This will allow for (future) project identification, # configuration and updates. project: name: adonno.tag_reader version: "1.4" # If buzzer is enabled, notify on api connection success on_boot: priority: -10 then: - wait_until: api.connected: - logger.log: API is connected! - rtttl.play: "success:d=24,o=5,b=100:c,g,b" - 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 ############################################# # Global variables ############################################# globals: - id: source type: std::string - id: url type: std::string - id: info type: std::string ############################################# ############################################# # MAIN SENSORS ############################################# ############################################# ############################################# # Switches # 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 ############################################# # Buttons # 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 brightness: 100% 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); - rtttl.play: "write:d=24,o=5,b=100:b" - wait_until: not: pn532.is_writing: - light.turn_off: id: activity_led - rtttl.play: "write:d=24,o=5,b=100:b,b" - 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: 64.7% blue: 0% - lambda: 'id(pn532_board).clean_mode();' - rtttl.play: "write:d=24,o=5,b=100:b" - wait_until: not: pn532.is_writing: - light.turn_off: id: activity_led - rtttl.play: "write:d=24,o=5,b=100:b,b" - 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 - rtttl.play: "write:d=24,o=5,b=100:b,b" - platform: restart name: "${friendly_name} Restart" entity_category: config ############################################# # HA API # Enable Home Assistant API ############################################# api: encryption: key: "K2H5vBNv8NLegc3RmwTQVFV7ULtba2DWDOlABmXmGBM=" services: - service: rfidreader_tag_ok then: - rtttl.play: "beep:d=16,o=5,b=100:b" - service: rfidreader_tag_ko then: - rtttl.play: "beep:d=8,o=5,b=100:b" - service: play_rtttl variables: song_str: string then: - rtttl.play: !lambda 'return song_str;' - 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); - rtttl.play: "write:d=24,o=5,b=100:b" - wait_until: not: pn532.is_writing: - light.turn_off: id: activity_led - rtttl.play: "write:d=24,o=5,b=100:b,b" - 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); - rtttl.play: "write:d=24,o=5,b=100:b" - wait_until: not: pn532.is_writing: - light.turn_off: id: activity_led - rtttl.play: "write:d=24,o=5,b=100:b,b" ############################################# # i2C bus ############################################# i2c: scan: False frequency: 400kHz ############################################# # NFC Reader ############################################# 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: - rtttl.play: "success:d=24,o=5,b=100:c,g,b" on_tag_removed: then: - homeassistant.event: event: esphome.tag_removed ############################################# # OUTPUTS ############################################# # Define the buzzer output output: - platform: esp8266_pwm pin: D7 id: buzzer ############################################# # BINARY SENSORS ############################################# binary_sensor: - platform: status name: "${friendly_name} Status" entity_category: diagnostic ############################################# # TEXT SENSORS ############################################# text_sensor: - platform: version hide_timestamp: true name: "${friendly_name} ESPHome Version" entity_category: diagnostic - platform: wifi_info ip_address: name: "${friendly_name} IP Address" icon: mdi:wifi entity_category: diagnostic ssid: name: "${friendly_name} Connected SSID" icon: mdi:wifi-strength-2 entity_category: diagnostic ############################################# # Ring Tone Text Transfer Language for melody ############################################# # Define buzzer as output for RTTTL rtttl: output: buzzer ############################################# # LED ############################################# # Configure LED light: - platform: neopixelbus variant: WS2812 pin: D8 num_leds: 1 flash_transition_length: 500ms type: GRB id: activity_led name: "${friendly_name} LED" restore_mode: ALWAYS_OFF