Sensor Template leverage the Media Player "last changed" Attribute

I am making a senosor template to determine which Media Player has the latest time stamp as defined by the atribute “Last Changed” I wrote the following Template Sensor

 - platform: template
    sensors:
      latest_sonos_timestamp:
        value_template: |
          {% set latest_timestamp = 0 %}
          {% for media_player in states.media_player %}
            {% if media_player.last_updated %}
              {% set timestamp = state_attr(media_player.entity_id, 'last_updated') %}
              {% if timestamp > latest_timestamp %}
                {% set latest_timestamp = timestamp %}
              {% endif %}
            {% endif %}
          {% endfor %}
          {{ latest_timestamp }}

the response I get from the developer tool (template) is:
TypeError: ‘>’ not supported between instances of ‘NoneType’ and ‘int’

I am guessing the issue is a string-integer mismatch with this line of my code:
{% set timestamp = state_attr(media_player.entity_id, ‘last_updated’) %}

Is there a built string-integer mismatch issue that is causing the error? if so how do I fix it? I have read references to mismatching strings to integers, but I have been unable to relocate them

Apologies for my lack of knowledge. I am self taught and learning jinja/python from the internet is a little like trying to learn English from watching reruns of “Gilligan’s Island”

You are using the “old” template style. New format is recommended.
Your entire template can be replaced with this.

template:
  - sensor:
      - name: "Latest Sonos Timestamp"
        unique_id: latest_sonos_timestamp
        device_class: timestamp
        state: "{{ states.media_player|map(attribute='last_updated')|max|as_timestamp|as_datetime }}"

Edit: Rereading your comment, it looks like you want the entity id of the latest updated player and not the timestamp? There is probably a more elegant method to do it, but this will work.

template:
  - sensor:
      - name: "Latest Updated Sonos"
        unique_id: latest_updated_sonos
        state: >
          {% set mcount = states.media_player|list|count %}
          {% set mplayers = states.media_player|sort(attribute='last_updated')|map(attribute='entity_id')|list %}
          {{ mplayers[mcount-1] }}

@Descartes your template has a few issues…

  1. last_changed is not an attribute, so it cannot be retrieved using the state_attr() function. This is the cause of the error you posted.

  2. The last_changed property is a datetime object, not a timestamp. If you were going to compare it to an integer/timestamp you would need to use a conversion filter.

  3. You haven’t provided a means for the variable latest_timestamp to be available outside the loop. You would need to use a namespace.

  4. At the end you’re still left with a timestamp that you would have to re-compare to the timestamps of all the entities, which have possibly changed, leaving you with another possible None error.

How to fix those issues (not recommended for this case)
{% set ns = namespace( latest_timestamp = 0, entity = '' ) %}
{% for player in states.media_player %}
  {% set timestamp = player.last_changed | as_timestamp %}
  {% if timestamp > ns.latest_timestamp %}
    {% set ns.latest_timestamp = timestamp %}
    {% set ns.entity = player.entity_id %}
  {% endif %}
{% endfor %}
{{ ns.entity }}

As Jason pointed out, the loop is not necessary. What you are trying to do is possible just using existing filters.

template:
  - sensor:
      - name: "Latest Updated Sonos"
        unique_id: latest_updated_sonos
        state: >
          {{ states.media_player | sort(attribute='last_changed', reverse=1)
          | map(attribute='entity_id') | first }}

FWIW, you may need further filtering to get a useful sensor. The state of media players can be very “bouncy”, so you may need to select for specific state values. Also, keep in mind that both this template and the one you posted are not currently limited Sonos devices. If you currently have or add other media player entities in the future, they will be included.

2 Likes

Nice! You learnt me sumptin!

I was able to easily create template on my end. thanks for the help. This is basic building block snippet I really needed for my application. T

As you probably guessed, my template is used to establish the target speaker to be used in a mediaplayer. “join”. thanks for solving to the actual entity and not stopping at time stamp.
howos speaker called “cooking” the template captures the specific speaker that received the alexa command so it can become the “target speaker” in a media player join.
it works adequately. I found the described “bouncing issue”. It is a little limiting, but the project is still worth while.

Anyways thanks, very helpful,

Craig