i cannot get the blueprint device selection to work.
It seems it is looking for a manufacturer ‘espressif’, while the tagreader has the manufacturing field as ‘by adonno’
How to fix?
Try this until luka6000 changes the original:
import the link as blueprint
EDIT: After playing with it one question:
Ist possible to use URI instead of URLs?
Like spotify:album:EGEGEFEFE
instead of https://open.spotify.com/album etc…?
This would open the spotify app on my phone when scanning the nfc chip, instead of opening the browser.
Thanks for your script!
I’ve deleted manufacturer selector so now it should work with tag readers by adonno and any other.
how does scanning of URL works on Android? On iOS when I scan URL of the music service, usually the app has registered it’s urls so the browser instantly switches to the app. That’s the whole point of this URL tag - it will work on every setup so you can give the tag card to a friend and it will work with his/her phone and tag reader
have you tried? I don’t think it will work right now. To do this you should introduce another tag type source and a variable to be populated as a template from tag data. It sounds a bit complicated but I think it is possible.
yeah, its not the same with android (at least with my motorola defy)…
It opens the default browser with the spotify album/playlist and there is a button to open spotify app
Thats true, seems i need to change the script for that.
Yes, it just does not work with URI
I Love all of what I see so far, only issue I am having is that my HA doesn’t seem to see any of the esphome.music_tag events. When I watch for tag_scanned, I see those, but not when I watch for music_tag (or esphome.music_tag). Any idea what is wrong with my setup? I’ve also confirmed the music url on the tag works for launching the music directly on my android phone.
Can you send tagreader console output? I think you’re not using tag writer service correctly.
Yes, here is what I am getting:
[09:16:06][D][pn532:280]: Mifare classic
[09:16:07][D][light:035]: 'TagReader LED' Setting:
[09:16:07][D][light:046]: State: ON
[09:16:07][D][light:050]: Brightness: 100%
[09:16:07][D][light:057]: Red: 0%, Green: 100%, Blue: 0%
[09:16:07][D][light:077]: Flash length: 0.5s
[09:16:07][D][pn532:162]: Found new tag '8A-7D-7D-82'
[09:16:07][D][pn532:166]: NDEF formatted records:
[09:16:07][D][pn532:168]: U - http://listen.plex.tv/player/playback/playMedia?uri=server[...]
[09:16:07][D][pn532:168]: T - Testing
[09:16:07][D][pn532:295]: Waiting to read next tag
[09:16:07][D][tagreader:292]: Found music info tag NDEF
[09:16:07][D][tagreader:309]: No HA NDEF, using UID
[09:16:07][D][rtttl:038]: Playing song success
[09:16:08][D][rtttl:094]: Playback finished
where “[…]” is the rest of the url that works when read with my phone’s NFC tag.
I know this isn’t going to work with the standard blueprint, so I’ve already started creating my own blueprint and system to have home assistant trigger playback another way, but what I realized is that my automation based on my new blueprint doesn’t triggered if I listen for esphome.music_tag and doesn’t have the data (of course) when I listen for tag_scanned. That is when I started to listen directly with developer tools event listening to see if it was an automation problem or an event problem, or something else.
Also, if it can help, this is the config I used to call the tag_writer service (from the dev tools)
service: esphome.tagreader_dc64ac_write_music_tag
data:
music_url: >-
http://listen.plex.tv/player/playback/playMedia?uri=server[...]
music_info: Testing
ok, it’s clear now. This is not working with any URL. Currently firmware can recognize only these services
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://");
and if URL is not recognized, it falls back to hass tag. That’s why you see tag_scanned events.
I think it could be done completely different meaning any URL on the card could be pushed as dedicated event and all url parsing could be done in automation. I don’t have much time now to do this. Do you think it’s worth it? I must say after all this time I see limitations of my previous work. On the other hand it is purpose build (Spotify, Apple Music, Sonos) and works seamlessly.
Ahhh, that makes sense! I do think it would be worth adding a custom option, that can be used by people, like me, who want to do more.
If I wanted to do it, (I used to be a programmer), would it be as simple as or branching/forking tagreader/tagreader.yaml at 7bc9ec90bf8976eb9e5b85a720ef046a64ab5d03 · adonno/tagreader · GitHub and telling my reader to download from my fork/branch?
try using this one
If you can test it, I can make pull request to Adonno. This yaml was already on the verge of 8266 memory capabilities so we need to be careful with new code
First off, thank you so much for your help with this and fast response times! I am stoked to get this working!
Is this how I would install your branch?
substitutions:
name: tagreader-dc64ac
packages:
adonno.tag_reader: github://luka6000/tagreader/blob/luka6000-patch-anyurl/tagreader.yaml
esphome:
name: ${name}
name_add_mac_suffix: false
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
If so I am running into an issue when I click install:
INFO Reading configuration /config/esphome/tagreader-dc64ac.yaml...
ERROR Unexpected exception while reading configuration:
Traceback (most recent call last):
File "/usr/local/bin/esphome", line 33, in <module>
sys.exit(load_entry_point('esphome', 'console_scripts', 'esphome')())
File "/esphome/esphome/__main__.py", line 960, in main
return run_esphome(sys.argv)
File "/esphome/esphome/__main__.py", line 938, in run_esphome
config = read_config(dict(args.substitution) if args.substitution else {})
File "/esphome/esphome/config.py", line 977, in read_config
res = load_config(command_line_substitutions)
File "/esphome/esphome/config.py", line 831, in load_config
return _load_config(command_line_substitutions)
File "/esphome/esphome/config.py", line 819, in _load_config
result = validate_config(config, command_line_substitutions)
File "/esphome/esphome/config.py", line 681, in validate_config
substitutions.do_substitution_pass(config, command_line_substitutions)
File "/esphome/esphome/components/substitutions/__init__.py", line 154, in do_substitution_pass
config.move_to_end(CONF_SUBSTITUTIONS, False)
AttributeError: 'dict' object has no attribute 'move_to_end'
Apologies if this is a noob mistake. I am extremely new to ESPhome devices.
I am using the ESPHome addon in HomeAssistant, fyi.
sorry, my mistake. That’s what happens when you try to change code you haven seen for a long time.
Try again - this compiled for my tag reader now.
If you will still have errors, try using your working configuration and add this changes
I think I am doing something wrong with the package section, I’ve tried different things, and I can get this to work, but can’t figure out how to specify with the branch in a way that works:
packages:
adonno.tag_reader: github://luka6000/tagreader/tagreader.yaml
I am honestly not sure how to edit my working config…
Just copy-paste whole yaml and comment out this package statement
If you saw my previous version(s) of this message, I got past where I was stuck. Will post more updates as I learn/test.
It works!
This is exactly what I finally got to flash and successfully tested minus my specific IP addresses (for you to use with beyond compare or similar, to make sure I didn’t make other changes I forgot about to get it working)
# Insert your SSID and Your PWD after initial setup
wifi:
ssid: [redacted]
password: [redacted]
manual_ip:
static_ip: [redacted]
gateway: [redacted]
subnet: [redacted]
# Enable the captive portal for initial WiFi setup
captive_portal:
improv_serial:
substitutions:
name: tagreader-dc64ac
friendly_name: TagReader
# packages:
# adonno.tag_reader: github://adonno/tagreader/tagreader.yaml
esphome:
name: $name
platform: ESP8266
board: d1_mini
# Automatically add the mac address to the name
# so you can use a single firmware for all devices
name_add_mac_suffix: true
# 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
# 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
# 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
# Enable logging
logger:
# level: VERY_VERBOSE
# level: VERBOSE
# Enable Home Assistant API
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:
- 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"
# Enable OTA upgrade
ota:
i2c:
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 uri = payload.find("https://");
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 == "U" and uri != std::string::npos ) {
ESP_LOGD("tagreader", "Found other URL tag NDEF");
id(source)="uri";
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
# Define the buzzer output
output:
- platform: esp8266_pwm
pin: D7
id: buzzer
binary_sensor:
- platform: status
name: "${friendly_name} Status"
entity_category: diagnostic
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
# Define buzzer as output for RTTTL
rtttl:
output: buzzer
# 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
I’ll get a litle further with the HA side of parsing and using and if you are interested, I can share it as an example. Currently, it involves HA and Tasker and AutoRemote and Plex and AirMusic There are probably a lot of simpler use cases for this new option.
Looking forward to the patch getting applied and upgrading 8 of my tag readers
Thank you so much again for being so responsive and awesome to work with. At some point, I’ll try to look at the code and try to think if there is a way to trim it down to help out… (and have some fun).
Finished testing and shared back what exactly I used. All looks good! Would you mind letting me know when you are able to submit the pull request so that I can apply the updates as soon as they are available? Let me know if I can help!