Help converting a time difference into percentage (template_sensor)

Hello everyone!

I wonder if someone could help me out: I need to create a template_sensor that calculates a percentage number by retrieving information from a timer entity and showing the percentage of the current timer that is active.

For example: a timer duration of 01:00:00, when it has passed 00:30:00 the sensor will show as 50%.

I’ve tried retrieving the timer attributes but no luck since the time left is static, it only shows how many time left (dynamically) on the entity card.

So this are the attributes that I have on a timer entity set to 00:03:30:

duration: 0:03:30
remaining: 0:03:30
friendly_name: Tempo restante
icon: mdi:camera-timer

This is what the UI shows:

image

Not sure how to do it…

Thanks a lot!

Maybe this could work:

sensor:
  - platform: template
    sensors:
      xxx_timer_percent:
        unit_of_measurement: %
        entity_id: sensor.time
        value_template: >
          {% set timer = 'xxx' %}
          {% if is_state('timer.'~timer,'active') %}
            {% set state = states.timer[timer] %}
            {% set dur = state.attributes.duration.split(':') %}
            {% set dur = ((dur[0]|int)*60+dur[1]|int)*60+dur[2]|int %}
            {{ ((dur - (now() - state.last_changed).total_seconds())/dur*100)|int }}
          {% else %}
            100
          {% endif %}
1 Like

Perhaps you could use the ‘last triggered’ attribute of the timer. Then calculate the time difference between between then and now. This could go in a sensor template.

It’s just an idea, I haven’t checked its viability…

1 Like

Amazing job @pnbruckner! I’ve tested using templates and it seems to be working, just a minor problem: the percentage is backwards haha :slight_smile:

It starts with 100% and gets lower by the time… I’ve tried to figure it out but no luck. Any idea where I should change to make it start with 0%?

Thanks a lot my friend!

Well, it wasn’t clear whether you wanted it to show the percentage of time remaining, or the percentage of time elapsed. And your example (50%) didn’t help. :wink: And since you mentioned how a timer is shown in the frontend (counting down), I thought you wanted % of time remaining.

If you want percentage of time elapsed, try this:

 sensor:
  - platform: template
    sensors:
      xxx_timer_percent:
        unit_of_measurement: %
        entity_id: sensor.time
        value_template: >
          {% set timer = 'xxx' %}
          {% if is_state('timer.'~timer,'active') %}
            {% set state = states.timer[timer] %}
            {% set dur = state.attributes.duration.split(':') %}
            {% set dur = ((dur[0]|int)*60+dur[1]|int)*60+dur[2]|int %}
            {{ ((now() - state.last_changed).total_seconds()/dur*100)|int }}
          {% else %}
            0
          {% endif %}
3 Likes

You are definitely right sir, I’m sorry: reading my firs post again, I can see that I was not clear enough.

I’ve tested your code and works like a charm, you are a PRO!

That is why I love Home Assistant and its community… A random guy like me can post an idea and great people like you take their time to help and share knowledge.

Have a great day my friend! You have helped me a lot.

1 Like

Hello again @pnbruckner! Sorry to bother you…

It seems that template_sensor does not like the use of now(), I believe I’ve read it somewhere here. The template works but does not update when the sensor is created.

I have a couple of wait_template that I have to use sensor.date_time instead of now() in order to the template work in real-time. Here it is:

((((as_timestamp(strptime(states.sensor.date_time.state, '%Y-%m-%d, %H:%M')) - as_timestamp(states.binary_sensor.movimento_banheiro_suite.last_updated) ) / 60) | int)

Do you think now() can be changed to use sensor.date_time? I think it might work…

Thanks again!

This is why I had this in the template sensor configuration:

        entity_id: sensor.time

That will cause the template sensor to update whenever sensor.time updates (i.e., once a minute.) If you don’t have sensor.time defined, then use any entity that updates often (such as sensor.date_time, which also updates once a minute.)

As long as the template sensor uses the entity_id option using now() is fine.

1 Like

Ok, got it. I’ve tested this new sensor and it was stuck on 1% after the timer is started. Maybe it will take 1 minute to update since it waiting for the sensor.time to update.

I will test and let you know if it works.

Thanks!

Yes, using that technique it will only update when sensor.time updates.

Alternatively, you could use an automation that runs more often that causes the template sensor to update by using the homeassistant.update_entity service.

1 Like

Thanks, I’ve noticed that the sensor indeed updated every 1 minute. Since most of my timers will run for at least 1 hour, I do not think that this would be a problem.

Thanks again, have a great day!

1 Like

Can you explain the function of the tilde in this snippet?

is_state('timer.'~timer,'active')

http://jinja.pocoo.org/docs/dev/templates/#other-operators

1 Like

Thanks! I didn’t know that.

I have used the + operator and then found this important statement in its description:

+
Adds two objects together. Usually the objects are numbers, but if both are strings or lists, you can concatenate them this way. This, however, is not the preferred way to concatenate strings! For string concatenation, have a look-see at the ~ operator. {{ 1 + 1 }} is 2 .

Oops! Now I know better.

1 Like

Hello @pnbruckner! How are you sir? Sorry to bother you…

I’ve noticed that after this template sensor was added, the CPU usage of my Raspberry Pi 3B have gone significantly up, here is a graph:

image

This shows a patter of about 5 mins for each “spike”. Before that the average CPU usage was about 6 to 8 percent. If I take this template sensor out, the CPU usage goes down again, just like before.

Do you think there is a workaround this problem? The temps are getting high too…

Like I’ve said before, I’ve read somewhere that the use of now() is not recommended and that is why the time_date sensor was created.

This is weird since an entity_id is set in order to update the template sensor upon its update but the thing is it does not match those spikes of 5 minutes each shown on the graph.

Thanks a lot!

No idea. Have you looked in home-assistant.log (with debug enabled) to see what activity corresponds to the spikes?

Yes, there are no errors that I could relate to. As Hassio gets updated, less and less errors are shown on my logs :slight_smile:

Just for a quick test: could you please help me on changing the now() for the time_date component? I’ve tried myself with no luck…

Maybe use a service (script or automation) to update de sensor just when it is active?

The moment I took out this template sensor, the average load on the CPU goes to normal (about 6%).

Thanks a lot!

I wasn’t referring to errors. I was asking about activity. By enabling debug in the logger you should be able to see what’s happening at the times where the CPU usage is spiking.

Why would you want to do that? There’s absolutely nothing wrong with using now(). The issue many people have is they don’t understand that that in itself will not cause an event when time changes, so relying on now() in a template sensor by itself can mean the sensor doesn’t update as you’d like. But by using sensor.time in the entity_id option, that takes care of that problem. now() is much more versatile, and much easier to use, than sensor.time when it comes to templates in many situations.

I suppose you could do that, but to me that’s just going to cause more processing to happen, not less.

1 Like

Ok! Got it, I really appreciate your feedback, it helps a lot.

I will investigate what is going on here, not really sure why this template sensor is causing these spikes every 5 minutes.

Thanks again my friend! have a great day!

1 Like