Cheapest Energy Hours - Jinja macro for dynamic energy prices

Just an idea. What if you use the macro with lowest set to false and hours set to 1 hour. That way you will find the most expensive hour of the day. Then you can use that as input for end in your actual macro.

So I can use the sensor for most expensive hour as end time instead of the number value? That should accomplish what i’m after. I will try that, thank you!

Good suggestion, looks like exactly what @lemehavit needs

Can confirm that it worked just as intended. Thanks again for the assistance, greatly appreciated!

Hi @TheFes , first of all thanks for this macro. It was a bit difficult to make sense how to use it but it’s working :slight_smile: However,…

I created a helper in the GUI to calculate the best charge time, which is now continuously updated during the charge. (Focus on last cycle around 03:00)

I already avoided the use of now() and use a separate helper to calculate the required duration, which is NOT updated during the charge. (The current unknown is fine as the battery is full)

{% set chargeduration = states('input_number.carcharge_timeremain')|float(0) %}
{% if chargeduration > 0.1 %}
  {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
  {% set output = cheapest_energy_hours
  (sensor='sensor.average_electricity_price',
   attr_today='prices_today', 
   attr_tomorrow='prices_tomorrow', 
   time_key='time', 
   value_key='price', 
   hours=chargeduration, 
   look_ahead=true, 
   include_tomorrow=true) %}
  {{ output }}
{% else %}
  NA
{% endif %}

Helper CargeTime Remain is NOT updated during charge

Hi,

The problem here is that you’ve used look_ahead=true.
The macro is built to always produce a time in the future when that parameter is set.
As the macro itself uses now() as well (when look_ahead=true is used) it will evaluate on every minute anyway, and will find the best start time in the future. It is built this way, so the result can be used in a time trigger, as the time trigger would not fire if the time is already in the past.

To avoid this, you should create a trigger based template sensor, which can only be done in YAML. Then you can trigger on the moment your car is ready to be charged (eg when the car is plugged in to the charger) and use that to determine the best time to charge it.

There is an example for this specific use case in the documentation.

BTW, you could also use start_time=now(), remove look_ahead=true and use mode='is_now' and then create a template binary sensor. That will result in a sensor which is on when you should charge the car. It will be re-evaluated every minute (because it uses now()) and on every state change of the sensor indicating the charging time, but, as it is a binary_sensor this will nog result in a state change, as it will just remain on. But in that case you should make sure the helper is actually updated while charging, as otherwise it will keep trying to charge it 4 hours. If that isn’t possible, you should go for the trigger based approach. in that case the example for the dishwasher is actually more relevant for you.

Thanks for the fast reply. I was trying to avoid the trigger based template as I’m trying to move as much a possible to GUI helpers. But okay, if needed I will try it. For my understanding, even if I use now() or look_ahead=true in a trigger based template, it will only re-evaluate after a set trigger, right? So, it will also not update automatically when the price info is updated.

The mode='is_now" option is also a good alternative and that value can be used to trigger the charge automation. But as I understand correctly I need to keep updating the charge time in this case as it will otherwise never go to “off”-state, or worse, keep “re-calculating” a new best 4-hour window. Charging is stopped when ready. However, when for example after 2 hours of charging a new best 4-hour might be a completely different as originally planned. Am I getting this right? So, that why we need a trigger based template.

I will give it another try :slight_smile:

Correct :slight_smile:

You can add multiple triggers, so you can also add a trigger when the prices become available

I have a weird problem with my sensors. This is a screenshot of my dashboard. I asked this question a month ago, but i got no response, because there were making my reply “dissapear”. This problems is not always there, and the example is from the below row sensors. But it happens also on the first and second row. Those rows do have the same template.

If you look at the time it is at the moment of the screenshot 20:43. The row on the bottom is from 21:00 - 00:00. But it says true. But it is still not 21:00.

The template i use is as follows:

{% from ‘cheapest_energy_hours.jinja’ import cheapest_energy_hours %}
{{ cheapest_energy_hours(‘sensor.frank_average_electricity_price_today’, attr_today=‘prices_today’, hours=3, start=‘08:00’, end=‘23:59’, lowest=True, mode=‘average’, value_key=‘price’, precision=2) }}

{% from ‘cheapest_energy_hours.jinja’ import cheapest_energy_hours %}
{% set start = cheapest_energy_hours(‘sensor.frank_average_electricity_price_today’, attr_today=‘prices_today’, hours=3, start=‘08:00’, end=‘23:59’, lowest=‘true’, value_key=‘price’, mode=‘start’, time_format=‘time24’) %}
{% set end = cheapest_energy_hours(‘sensor.frank_average_electricity_price_today’, attr_today=‘prices_today’, hours=3, start=‘08:00’, end=‘23:59’, lowest=‘true’, value_key=‘price’, mode=‘end’, time_format=‘time24’) %}
{{ start }} - {{ end }}

{% from ‘cheapest_energy_hours.jinja’ import cheapest_energy_hours %}
{{ cheapest_energy_hours(‘sensor.frank_average_electricity_price_today’, attr_today=‘prices_today’, value_key=‘price’, time_key=‘readingDate’, hours=3, start=‘08:00’, end=‘23:59’, lowest=‘true’, mode=‘is_now’) }}

Maybe you could point me the fault in the template?
And here is the sensors data, from today:

Prices today
- time: '2024-11-28 00:00:00+01:00'
price: 0.21423
- time: '2024-11-28 01:00:00+01:00'
price: 0.20347
- time: '2024-11-28 02:00:00+01:00'
price: 0.19612
- time: '2024-11-28 03:00:00+01:00'
price: 0.19959
- time: '2024-11-28 04:00:00+01:00'
price: 0.22609
- time: '2024-11-28 05:00:00+01:00'
price: 0.26498
- time: '2024-11-28 06:00:00+01:00'
price: 0.27473
- time: '2024-11-28 07:00:00+01:00'
price: 0.31345
- time: '2024-11-28 08:00:00+01:00'
price: 0.33304
- time: '2024-11-28 09:00:00+01:00'
price: 0.32345
- time: '2024-11-28 10:00:00+01:00'
price: 0.27341
- time: '2024-11-28 11:00:00+01:00'
price: 0.27304
- time: '2024-11-28 12:00:00+01:00'
price: 0.26996
- time: '2024-11-28 13:00:00+01:00'
price: 0.27339
- time: '2024-11-28 14:00:00+01:00'
price: 0.29203
- time: '2024-11-28 15:00:00+01:00'
price: 0.29736
- time: '2024-11-28 16:00:00+01:00'
price: 0.31566
- time: '2024-11-28 17:00:00+01:00'
price: 0.33632
- time: '2024-11-28 18:00:00+01:00'
price: 0.34508
- time: '2024-11-28 19:00:00+01:00'
price: 0.34
- time: '2024-11-28 20:00:00+01:00'
price: 0.32711
- time: '2024-11-28 21:00:00+01:00'
price: 0.31243
- time: '2024-11-28 22:00:00+01:00'
price: 0.30142
- time: '2024-11-28 23:00:00+01:00'
price: 0.28986
Prices tomorrow
- time: '2024-11-29 00:00:00+01:00'
price: 0.28707
- time: '2024-11-29 01:00:00+01:00'
price: 0.28309
- time: '2024-11-29 02:00:00+01:00'
price: 0.27881
- time: '2024-11-29 03:00:00+01:00'
price: 0.27645
- time: '2024-11-29 04:00:00+01:00'
price: 0.27803
- time: '2024-11-29 05:00:00+01:00'
price: 0.28946
- time: '2024-11-29 06:00:00+01:00'
price: 0.31171
- time: '2024-11-29 07:00:00+01:00'
price: 0.34809
- time: '2024-11-29 08:00:00+01:00'
price: 0.36362
- time: '2024-11-29 09:00:00+01:00'
price: 0.34403
- time: '2024-11-29 10:00:00+01:00'
price: 0.32101
- time: '2024-11-29 11:00:00+01:00'
price: 0.29888
- time: '2024-11-29 12:00:00+01:00'
price: 0.28677
- time: '2024-11-29 13:00:00+01:00'
price: 0.29186
- time: '2024-11-29 14:00:00+01:00'
price: 0.28586
- time: '2024-11-29 15:00:00+01:00'
price: 0.30389
- time: '2024-11-29 16:00:00+01:00'
price: 0.33054
- time: '2024-11-29 17:00:00+01:00'
price: 0.33432
- time: '2024-11-29 18:00:00+01:00'
price: 0.32547
- time: '2024-11-29 19:00:00+01:00'
price: 0.31317
- time: '2024-11-29 20:00:00+01:00'
price: 0.29869
- time: '2024-11-29 21:00:00+01:00'
price: 0.28925
- time: '2024-11-29 22:00:00+01:00'
price: 0.29146
- time: '2024-11-29 23:00:00+01:00'
price: 0.27858
Prices
- time: '2024-11-28 00:00:00+01:00'
price: 0.21423
- time: '2024-11-28 01:00:00+01:00'
price: 0.20347
- time: '2024-11-28 02:00:00+01:00'
price: 0.19612
- time: '2024-11-28 03:00:00+01:00'
price: 0.19959
- time: '2024-11-28 04:00:00+01:00'
price: 0.22609
- time: '2024-11-28 05:00:00+01:00'
price: 0.26498
- time: '2024-11-28 06:00:00+01:00'
price: 0.27473
- time: '2024-11-28 07:00:00+01:00'
price: 0.31345
- time: '2024-11-28 08:00:00+01:00'
price: 0.33304
- time: '2024-11-28 09:00:00+01:00'
price: 0.32345
- time: '2024-11-28 10:00:00+01:00'
price: 0.27341
- time: '2024-11-28 11:00:00+01:00'
price: 0.27304
- time: '2024-11-28 12:00:00+01:00'
price: 0.26996
- time: '2024-11-28 13:00:00+01:00'
price: 0.27339
- time: '2024-11-28 14:00:00+01:00'
price: 0.29203
- time: '2024-11-28 15:00:00+01:00'
price: 0.29736
- time: '2024-11-28 16:00:00+01:00'
price: 0.31566
- time: '2024-11-28 17:00:00+01:00'
price: 0.33632
- time: '2024-11-28 18:00:00+01:00'
price: 0.34508
- time: '2024-11-28 19:00:00+01:00'
price: 0.34
- time: '2024-11-28 20:00:00+01:00'
price: 0.32711
- time: '2024-11-28 21:00:00+01:00'
price: 0.31243
- time: '2024-11-28 22:00:00+01:00'
price: 0.30142
- time: '2024-11-28 23:00:00+01:00'
price: 0.28986
- time: '2024-11-29 00:00:00+01:00'
price: 0.28707
- time: '2024-11-29 01:00:00+01:00'
price: 0.28309
- time: '2024-11-29 02:00:00+01:00'
price: 0.27881
- time: '2024-11-29 03:00:00+01:00'
price: 0.27645
- time: '2024-11-29 04:00:00+01:00'
price: 0.27803
- time: '2024-11-29 05:00:00+01:00'
price: 0.28946
- time: '2024-11-29 06:00:00+01:00'
price: 0.31171
- time: '2024-11-29 07:00:00+01:00'
price: 0.34809
- time: '2024-11-29 08:00:00+01:00'
price: 0.36362
- time: '2024-11-29 09:00:00+01:00'
price: 0.34403
- time: '2024-11-29 10:00:00+01:00'
price: 0.32101
- time: '2024-11-29 11:00:00+01:00'
price: 0.29888
- time: '2024-11-29 12:00:00+01:00'
price: 0.28677
- time: '2024-11-29 13:00:00+01:00'
price: 0.29186
- time: '2024-11-29 14:00:00+01:00'
price: 0.28586
- time: '2024-11-29 15:00:00+01:00'
price: 0.30389
- time: '2024-11-29 16:00:00+01:00'
price: 0.33054
- time: '2024-11-29 17:00:00+01:00'
price: 0.33432
- time: '2024-11-29 18:00:00+01:00'
price: 0.32547
- time: '2024-11-29 19:00:00+01:00'
price: 0.31317
- time: '2024-11-29 20:00:00+01:00'
price: 0.29869
- time: '2024-11-29 21:00:00+01:00'
price: 0.28925
- time: '2024-11-29 22:00:00+01:00'
price: 0.29146
- time: '2024-11-29 23:00:00+01:00'
price: 0.27858

The is_now binary sensor is the only one where you have defined a time_key.

Does that mean it is not necessary in the template? Or is it needed additional in the first two templates? I read the documentation many times and i can’t get clear what kind of settings it needed.

EDIT: deleting that in the last template does not change it. I think it is only when we talk about times with half an hour.

So, what you are saying is that the is_now mode is triggered too soon, before the actual start time of the cheapest time block.

I will look into this. Sorry for not replying earlier on your previous post

First comment:
your time_key should be time, it would be best to include that in all templates, as the default is start. It should not affect the timing of in_now returning true though, but it will increase the response speed of the template.

Just to be sure, you are on the latest version right?

Can you try like this? I removed some unneeded parameter, added the time_key
PS I don’t know where you copied the template from, but those fancy quotes are a bit annoying, had to correct all of them

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.frank_average_electricity_price_today', attr_today='prices_today', value_key='price', time_key='time', hours=3, start='08:00', mode='average', precision=2) }}

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set start = cheapest_energy_hours('sensor.frank_average_electricity_price_today', attr_today='prices_today', value_key='price', time_key='time', hours=3, start='08:00', time_format='time24') %}
{% set end = cheapest_energy_hours('sensor.frank_average_electricity_price_today', attr_today='prices_today', value_key='price', time_key='time', hours=3, start='08:00', mode='end', time_format='time24') %}
{{ start }} - {{ end }}

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.frank_average_electricity_price_today', attr_today='prices_today', value_key='price', time_key='time', hours=3, start='08:00', mode='is_now') }}

Thank you for your reply. I am on the latest version 5.5.4. No problem that you didn’t reply on my earlier post. I tried your templates, waiting for the time, so i can test it. Haha what kinda of fancy quotes do you mean? I copied the template from a post somewhere in this thread. Thank you for you help.

Edit: looks like it is solved now.