diff --git a/tagreader/tagreader.yaml b/tagreader/tagreader.yaml new file mode 100644 index 0000000..3b1baf7 --- /dev/null +++ b/tagreader/tagreader.yaml @@ -0,0 +1,418 @@ +substitutions: + name: "tagreader" + friendly_name: "Tagreader" + device_description: NFC/RFID Tag reader + factory_reset_disabled: "true" + log_level: "INFO" + + project_name: "thethomaas.tagreader" + project_version: dev + +esphome: + name: ${name} + friendly_name: ${friendly_name} + comment: "${device_description}" + name_add_mac_suffix: true + project: + name: "${project_name}" + version: "${project_version}" + on_boot: + priority: -10 + then: + - wait_until: + api.connected: + - rtttl.play: "success:d=24,o=5,b=100:c,g,b" + +esp32: + variant: ESP32 + framework: + type: arduino + +dashboard_import: + package_import_url: github://TheThomaas/esphome-device-configs/tagreader/tagreader.yaml@main + import_full_config: false + +ota: + - platform: esphome + id: ota_esphome + # - platform: http_request + # id: ota_managed + +http_request: + verify_ssl: true + +# update: +# - platform: http_request +# id: firmware_update +# name: Firmware Update +# source: https://apolloautomation.github.io/H-2/firmware/manifest.json + +wifi: + ap: {} # This spawns an AP with the device name and mac address with no password. + +# Enable logging +logger: + level: ${log_level} + +captive_portal: + +api: + 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: + - 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: + - rtttl.play: "write:d=24,o=5,b=100:b,b" + + - service: write_music_tag + variables: + music_url: string + music_info: string + then: + - 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: + - rtttl.play: "write:d=24,o=5,b=100:b,b" + +button: + - platform: restart + id: restart_button + name: "Restart" + entity_category: config + disabled_by_default: true + icon: "mdi:restart" + - platform: safe_mode + internal: false + name: Safe mode + entity_category: config + disabled_by_default: true + - platform: factory_reset + name: "Factory Reset" + entity_category: diagnostic + internal: true + + - platform: template + name: Write Tag Random + id: write_tag_random + # Optional variables: + icon: "mdi:pencil-box" + on_press: + then: + - 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: + - 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: + - lambda: 'id(pn532_board).clean_mode();' + - rtttl.play: "write:d=24,o=5,b=100:b" + - wait_until: + not: + pn532.is_writing: + - 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();' + - rtttl.play: "write:d=24,o=5,b=100:b,b" + +text_sensor: + - platform: version + hide_timestamp: true + name: ESPHome Version + entity_category: diagnostic + - platform: wifi_info + ip_address: + name: IP Address + entity_category: diagnostic + ssid: + name: Connected SSID + entity_category: diagnostic + mac_address: + name: MAC Address + entity_category: diagnostic + +# Define the buzzer output +output: + - platform: ledc + pin: GPIO14 + id: buzzer + max_power: 50% + +# Define buzzer as output for RTTTL +rtttl: + id: rtttl_buzzer + output: buzzer + +switch: + - platform: factory_reset + id: factory_reset_switch + internal: true + +binary_sensor: + - platform: status + name: Status + + - platform: gpio + pin: + number: GPIO12 + mode: + input: true + pullup: true + inverted: true + id: main_button + name: Main button + on_press: + then: + - rtttl.play: "star_wars:d=16,o=5,b=100:4e,4e,4e,8c,p,g,4e,8c,p,g,4e,4p,4b,4b,4b,8c6,p,g,4d#,8c,p,g,4e,8p" + + - platform: template + name: "=Tag=" + id: is_tag + device_class: vibration + entity_category: DIAGNOSTIC + disabled_by_default: true + - platform: template + name: "=Reading=" + id: txt_reading + device_class: running + entity_category: DIAGNOSTIC + lambda: |- + if ( !id(pn532_board).is_writing() ) { + return true; + } else { + return false; + } + - platform: template + name: "=Writing=" + id: txt_writing + device_class: running + entity_category: DIAGNOSTIC + lambda: |- + if ( id(pn532_board).is_writing() ) { + return true; + } else { + return false; + } + +sensor: + - platform: wifi_signal + name: RSSI + id: wifi_signal_db + update_interval: 60s + entity_category: diagnostic + - platform: uptime + name: Uptime + id: sys_uptime + update_interval: 60s + +i2c: + id: bus_i2c + sda: GPIO22 + scl: GPIO21 + # scan: False + # frequency: 400kHz + +globals: + - id: source + type: std::string + - id: url + type: std::string + - id: info + type: std::string + +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://"); + + size_t mass_deezer = payload.find("deezer://"); + size_t mass_filesystem_local = payload.find("filesystem_local://"); + size_t mass_filesystem_smb = payload.find("filesystem_smb://"); + size_t mass_plex = payload.find("plex://"); + size_t mass_qobuz = payload.find("qobuz://"); + size_t mass_radiobrowser = payload.find("radiobrowser://"); + size_t mass_soundcloud = payload.find("soundcloud://"); + size_t mass_spotify = payload.find("spotify://"); + size_t mass_tidal = payload.find("tidal://"); + size_t mass_tunein = payload.find("tunein://"); + size_t mass_ytmusic = payload.find("ytmusic://"); + + 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 == "U" && (mass_deezer != std::string::npos || + mass_filesystem_local != std::string::npos || + mass_filesystem_smb != std::string::npos || + mass_plex != std::string::npos || + mass_qobuz != std::string::npos || + mass_radiobrowser != std::string::npos || + mass_soundcloud != std::string::npos || + mass_spotify != std::string::npos || + mass_tidal != std::string::npos || + mass_tunein != std::string::npos || + mass_ytmusic != std::string::npos)) { + ESP_LOGD("tagreader", "Found Music Assistant tag NDEF"); + id(source) = "mass"; + 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); + - rtttl.play: "success:d=24,o=5,b=100:c,g,b" + on_tag_removed: + then: + - homeassistant.event: + event: esphome.tag_removed + +# Sets up Bluetooth LE (Only on ESP32) to allow the user +# to provision wifi credentials to the device. +esp32_improv: + authorizer: main_button + +# Sets up the improv via serial client for Wi-Fi provisioning +improv_serial: