Currently I have some rest sensors which I’m using to work out the currently playing internet ratio station on my Volumio radios. Example of the code is below:
It works beautifully for Heart 80s as the URI doesn’t change, but the issue is recently Absolute/Bauer have introduced their new premium service, and as part of that they are using the keys which expire after a day or two (even on the non-premium streams like above).
Hence whist the above used to work fine, once the key changes of course the station is no longer recognised from the URI (and just return the default “Internet Radio”). And as that is the only thing that can be reliably used from the API to tell what station you’re listening to (the metadata isn’t routinely shared in any other key all the time), I’m a bit stuck.
In Python I can quite easily do it by checking for the presence of “absolute80s”, “absoluteclassicrock” etc in the string, but I’m not sure if/how something similar could be done in yaml to assign the sensor properly based on the presence in the URI without comparing the full URI like above.
Can anyone give me a suggestion? I’m searching the web in parallel for yaml tutorial sites, but coming up blank so far…
In lovelace cards you can use for loops. maybe it works in sensor templates too.
{% for station in stations %}
{% if 'absolute80s' in station %}
...
{% endif %}
{% endfor %}
Beware of variables in loops.
A variable created in a loop is not accessible outside of the loop, so use namespace to get them accessble.
{% set nss = namespace(stationlist="") %}
{% for station in stations %}
{% if 'absolute80s' in station %}
{%- set nss.stationlist=nss.stationlist+station %}
{% endif %}
{% endfor %}
{{ nss.stationlist }}
Thanks - gave it a blind go but I’m not really sure what I’m doing here.
I tried this:
# Volumio sensors
- resource: http://192.168.0.220/api/v1/getState
scan_interval: 10
sensor:
- name: rpizero.station
value_template: >-
{% set nss = namespace(stations="") %}
{% for station in stations %}
{% if 'absolute80s' in station %}
set stations = "Absolute 80s"
{% endif %}
{% if 'absoluteclassicrock' in station %}
set stations = "Absolute Classic Rock"
{% endif %}
{% if 'absoluteradio' in station %}
set stations = "Absolute Radio"
{% endif %}
{% if 'absolutecountry' in station %}
set stations = "Absolute Country"
{% endif %}
{% if 'Heart80s' in station %}
set stations = "Heart 80s"
{% endif %}
{% endfor %}
{{ nss.stations.get(value_json.uri, 'Playlist') }}
- name: rpizero.status
value_template: "{{ value_json.status }}"
But it gives an unknown value, and this in the log:
Logger: homeassistant.helpers.template
Source: helpers/template.py:583
First occurred: 11:09:27 (20 occurrences)
Last logged: 11:11:05
Template variable warning: 'stations' is undefined when rendering '{% set nss = namespace(stations="") %} {% for station in stations %} {% if 'absolute80s' in station %} set stations = "Absolute 80s" {% endif %} {% if 'absoluteclassicrock' in station %} set stations = "Absolute Classic Rock" {% endif %} {% if 'absoluteradio' in station %} set stations = "Absolute Radio" {% endif %} {% if 'absolutecountry' in station %} set stations = "Absolute Country" {% endif %} {% if 'Heart80s' in station %} set stations = "Heart 80s" {% endif %} {% endfor %} {{ nss.stations.get(value_json.uri, 'Playlist') }}'
Template variable error: 'str object' has no attribute 'get' when rendering '{% set nss = namespace(stations="") %} {% for station in stations %} {% if 'absolute80s' in station %} set stations = "Absolute 80s" {% endif %} {% if 'absoluteclassicrock' in station %} set stations = "Absolute Classic Rock" {% endif %} {% if 'absoluteradio' in station %} set stations = "Absolute Radio" {% endif %} {% if 'absolutecountry' in station %} set stations = "Absolute Country" {% endif %} {% if 'Heart80s' in station %} set stations = "Heart 80s" {% endif %} {% endfor %} {{ nss.stations.get(value_json.uri, 'Playlist') }}'
{% set nss = namespace(stations="") %} is just creating a string variable called nss.stations that can be accessed in loops and survive outside the loops. The nss.stations is here also set to be empty.
{% for station in stations %} is running a loop for every station in the list called stations, but you have not defined that list, so it is null.
You need to make or extract your stations variable as a list before the for loop, which is the reason for the first error message.
Your loop contains a lot of set stations lines, but stations is a new variable that will exist only in the loop.
You should here probably use nss.stations or better you call the namespace variable a different name, so you do not get stations and nss.stations mixed up.
Next assigning a value to stations with set stations=“xxx” just set stations to that exact value, but it happens by overwriting the old value, so you will end up with only the last of your findings.
The better way would probably be something like set stations=stations+“xxx”
The second error message is because the variable nss.stations is defined as a string and a string variable have no function get. You have to change it to a variable type that support that function to use it.
I can more or less follow @123 solution in relation to the description of @WallyR , but I would have had a hope of creating it myself!
Time to go dive into Google and find some suitable pages to help understand more deeply how to write such code, but it goes without saying that the above works perfectly.
The for-loop steps through the keys of the stations dictionary, testing if a given key exists within the received URI. If it finds a match it stores the key’s associated value in ns.station. The last line reports the value of ns.station but only if it’s not blank otherwise no match was found so it reports 'Internet Radio '.