How to find the sensor most frequently updated

trying something lik this:

{% for state in states.sensor| selectattr('last_changed') | sort(attribute='last_changed', reverse=true) -%}
{{ state.last_changed.timestamp() | timestamp_local }} : {{ state.entity_id }}
{% endfor %}

renders a list of the sensors last updated. this is a snapshot though, and we can hit the enter key, to see if there’s a sensor in the top 10 or so that stays there, indicating its frequent updating.

I was hoping this could be made more intelligent, and have the jinja select that for us.

reason I ask is that for several sensors, I need more frequent updating than is possible now.

      - wait_template: >
          {% set updater = states('sensors_huidig_verbruik_summed') %}
          {{(now() - state_attr('script.play_sleep_radio','last_triggered')|default(0)).total_seconds()
             > states('input_number.sleep_delay')|int * 60}}

in the above, we normally enter sensor.time for the update trigger, but in this case once a minute is way behind the needs for this situation. the sensor.time could cause a max delay of 59 seconds :wink: So, in order to get a more precise template, I now use a sensor that is connected to my smart meters updating, which is rather more frequent. But still not each second.

What I am really looking for, is for this specific template, to update each second.
I can of course, and have, create an automation triggering each second, but I don’t want to overload the full system with the need for this 1 template (well, 2 actually)

Was hoping to find the sensor in the system that updates most frequently, and use that as trigger here, so no extra overhead was created.

Of course, if we could simply use the heartbeat of the state machine, that would be even better…

Not at all what you are asking about but would a delay work here?

      - delay: {{ states('input_number.sleep_delay')|int * 60 }}

No not really.

this is a script which starts playing a radio, lowers the volume in a while loop, and, after that loop, if there’s time remaining, waits for the max playing time (input_number.sleep_delay) and then stops the media_player.

I can do this with sensor.time, or even a sensor as explained above, but I really need a second precision here. I have another thread how to stop a script from within the script with the complete code if you’re willing to look.

We’ve tried it with a variable in the loop, but, since the variable would be referenced outside the loop, that won’t go.

Would really appreciate if some trigger would become available, to use in a template like that. It would make life that much easier…

and on the question in the thread here. how to find the must frequently updated sensor (or state for that matter)? Would know of a way to check that?

To find the most active sensor, I would query the recorder database (I would do it with the sqlite3 command-line tool since that’s all I know).

For your actual issue though, if you can calculate the delay once it will be much more efficient than checking every second whether you have arrived; it will use no CPU at all until the delay expires. Maybe something like this?

- delay: >
    {% set delay = states('input_number.sleep_delay')|int * 60 %}
    {% set spent = now() - state_attr('script.play_sleep_radio','last_triggered')|default(0)).total_seconds() %}
    {{ [0, delay-spent] | max }}

Here is an example:

amelchio@nuc:~$ sqlite3 home-assistant_v2.db <<<"select entity_id,count(1) as count from states where last_updated >= date('now','-1 day') and last_updated < date('now') group by entity_id order by count desc limit 10"
sensor.netgear_lte_radio_quality|4676
[...]

thank you Amelchio.
the template has a little typo but this works:

    {% set delay = states('input_number.sleep_delay')|int * 60 %}
    {% set spent = (now() - state_attr('script.play_sleep_radio','last_triggered')|default(0)).total_seconds() %}
    {{ [0, delay-spent] | max }}
    

still, how does this update without an entity to trigger from? If the while loop has finished (and no trigger is done to the script) and the sleep delay still has 10 minutes left? Nothing is updating that template, so it will never expire? Or the newly builtin update per time , but that has the issue of lagging up to a minute.

check:

which has been like that for over 4 minutes now :wink:

(btw, I added the |default(0) to prevent the errors in the log upon updating scripts, as mentioned in the other thread, but this doesnt work unfortunately. Still seeing this:

TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'NoneType'

It does not update, that is the point ;-). The delay: reads its argument (i.e. the time left) just once and then uses the internal timer to sleep until the time is up.

Try |default(0, True).

I see… I think. It does work :wink: Cool! It even continues to exist after expiration …


Can I also use this in an automation with this as template_trigger:

 - alias: Sleep radio off
   id: Sleep radio off
   trigger:
     - platform: template
       value_template: >
         {% set delay = states('input_number.sleep_delay')|int * 60 %}
         {% set spent = (now() - state_attr('script.play_sleep_radio','last_triggered')|default(0)).total_seconds() %}
         {{ [0, delay-spent] | max }}
#          {% set trigger = states('sensor.time')%}
#          {{(now() - state_attr('script.play_sleep_radio','last_triggered')|default(0,True)).total_seconds()
#             > states('input_number.sleep_delay')|int * 60}}
     - platform: state
       entity_id:
         - input_boolean.sleep_radio
         - input_boolean.sleepclock_enabled
         - script.play_sleep_radio
       to: 'off'
   action:
     - service: script.turn_off
       entity_id: script.play_sleep_radio
     - service: media_player.turn_off
       data:
         entity_id: >
           {{states('sensor.sleep_radio')}}

yeah, I can’t run that. sqlite3 is an unrecognized command… think I need a jinja trick to find it, though hitting the enter key every second on that template above makes things clear too. Just would have hoped an automatic and auto-updating template would have been possible.

It now fails because the zero is used but it is not actually valid to subtract an integer from now() so I guess you need a bigger rework.

It cannot be used as a trigger since it does not update.

Do you even need that trigger?

I’ve taken it out now, as the delay you suggested works fine. I had the wait_tempate code there (with the sensor-most-frequently-updated as trigger) Hence the title for this thread…

Reason I have the automation is because I want to be able to manually stop the script/media_player (as in hit the snooze button physically :wink: )
Thought that since I had that automation for that, I could just as well add an extra trigger, and dispense with it in the script.