Cheapest Energy Hours - Jinja macro for dynamic energy prices

You need to have experimental features enabled in the HACS settings to install custom templates. The macro is already added to the HACS default repositories, so you don’t need to add it manually.

Hey, I wonder what is the best way to display selected split cheapest hours during the day.

Just to give a bit more context. I am using cheapest hours to heat my pool, I am using split mode there, in binary sensor it works fine, I have there {{ cheapest_energy_hours(sensor=sensor, hours=hours, split=true, mode='is_now') }}.
Basically when binary sensor changes on, then heating is started and turned off later.

I tried to create sensor with hourly attributes, but I got stuck with weird issue.
When I try to use mode=β€˜all’, then it returns list, but when I try to loop over the result then it is for some reason string.

Following works fine in developer template and looks like the result is list.

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set output = cheapest_energy_hours (
    sensor = 'sensor.nordpool_plus_grid',
    time_key = 'hour',
    value_key = 'price',
    hours = 5,
    mode = 'all',
    split=true) %}
{{ output  }}

but following

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set output = cheapest_energy_hours (
    sensor = 'sensor.nordpool_plus_grid',
    time_key = 'hour',
    value_key = 'price',
    hours = 5,
    mode = 'all',
    split=true) %}
{% for period in output %}
{{ period.start }}
{% endfor %}

gives me error str object' has no attribute 'start'.

Any idea what might be the issue? Or maybe there is a better how to visualize cheapest hours in UI. In my case those 5 hours that will be used for pool heating during the day (yes, I can eyeball the Nordpool graph, but this is annoying if differences are small).

That’s because the output of a macro is always a string. Use from_json to convert it to a list

You don’t need a for loop BTW

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set output = cheapest_energy_hours (
    sensor = 'sensor.nordpool_plus_grid',
    time_key = 'hour',
    value_key = 'price',
    hours = 5,
    mode = 'all',
    split=true) %}
{{ output | from_json | map(attribute='start') | list }}

I also tried to use from_json, but this raises JSONDecodeError: unexpected character: line 1 column 3 (char 2).

Can you show the output of the macro?


Can you share the output as text, I don’t want to type it all from your screenshot to be able to test with it

Sorry, sure:

[
  {
    "start": "2024-08-12T12:00:00+03:00",
    "end": "2024-08-12T17:00:00+03:00",
    "hours": 5,
    "prices": [
      0.0646,
      0.0573,
      0.0535,
      0.0614,
      0.063
    ],
    "is_now": false
  },
  {
    "total_hours": 5,
    "datapoints_per_hour": 1,
    "datapoints": 5
  }
]

what I don’t understand is that initially it looks like list and it says result type is list, but it is not possible to use it as list, OTOH, it is not json string either, although it looks like json.

The output of all templates is a string, however the Home Assistant template parser tries to convert that to a native Python object afterwards. The template editor in developer tools does the same, so you can see what the result of the template parser will be.

That will mean that the string which is outputted by the macro will be converted to a list if you would use it in an automation variable for example. However, in the template editor it is still a string.

However, that string was using single quotes where the output shows double quotes. And from_json requires proper JSON, which means it also needs double quotes around strings.

This was caused because I forgot to apply to to_json filter in the macro itself, which is now fixed in version 5.5.2

So if you update in HACS (you can first update information in HACS, and then the update should appear) this should work

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set output = cheapest_energy_hours (
    sensor = 'sensor.nordpool_plus_grid',
    time_key = 'hour',
    value_key = 'price',
    hours = 5,
    mode = 'all',
    split=true) %}
{{ output | from_json | map(attribute='start') | list }}

Yay, now it works as expected. Thank you for taking a look and fixing it so fast.

I want to see when is cheapest 2 hours interval today and tomorrow. I have done 2 sensors that showa when this intervat starts and when it stops.

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.nordpool_kwh_se4_sek_2_00_0', lowest=true, hours=3, start='00:00', end='23:59', include_tomorrow=false, mode='start') }}

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.nordpool_kwh_se4_sek_2_00_0', lowest=true, hours=3, start='00:00', end='23:59', include_tomorrow=false, mode='end') }}

The result is:
2024-08-21T01:00:00+02:00
2024-08-21T04:00:00+02:00

How can I get the result like this:
01:00 – 4:00

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{% set start = cheapest_energy_hours('sensor.nordpool_kwh_se4_sek_2_00_0', hours=3, time_format='time 24') %}
{% set end = cheapest_energy_hours('sensor.nordpool_kwh_se4_sek_2_00_0', hours=3, mode='end',  time_format='time 24') %}
{{ start }} - {{ end }}

Like this?

I removed some parameters which were not needed as you were using the defaults

Hi TheFes,
I am using Tibber. I have set up a sensor called sensor.tibber_forecast which will give me:

prices:

  • start_time: β€˜2024-09-07T00:00:00+02:00’
    price: 0.2802
  • start_time: β€˜2024-09-07T01:00:00+02:00’
    price: 0.2736
  • start_time: β€˜2024-09-07T02:00:00+02:00’
    price: 0.2729
  • start_time: β€˜2024-09-07T03:00:00+02:00’
    price: 0.2717
  • start_time: β€˜2024-09-07T04:00:00+02:00’
    price: 0.2752
  • start_time: β€˜2024-09-07T05:00:00+02:00’
    price: 0.2785
  • start_time: β€˜2024-09-07T06:00:00+02:00’
    price: 0.2819
  • start_time: β€˜2024-09-07T07:00:00+02:00’
    price: 0.2829
  • start_time: β€˜2024-09-07T08:00:00+02:00’
    price: 0.2719
  • start_time: β€˜2024-09-07T09:00:00+02:00’
    price: 0.2585
  • start_time: β€˜2024-09-07T10:00:00+02:00’
    price: 0.2196
  • start_time: β€˜2024-09-07T11:00:00+02:00’
    price: 0.1751
  • start_time: β€˜2024-09-07T12:00:00+02:00’
    price: 0.1648
  • start_time: β€˜2024-09-07T13:00:00+02:00’
    price: 0.1595
  • start_time: β€˜2024-09-07T14:00:00+02:00’
    price: 0.1588
  • start_time: β€˜2024-09-07T15:00:00+02:00’
    price: 0.1683
  • start_time: β€˜2024-09-07T16:00:00+02:00’
    price: 0.2173
  • start_time: β€˜2024-09-07T17:00:00+02:00’
    price: 0.2789
  • start_time: β€˜2024-09-07T18:00:00+02:00’
    price: 0.3113
  • start_time: β€˜2024-09-07T19:00:00+02:00’
    price: 0.3373
  • start_time: β€˜2024-09-07T20:00:00+02:00’
    price: 0.3166
  • start_time: β€˜2024-09-07T21:00:00+02:00’
    price: 0.2795
  • start_time: β€˜2024-09-07T22:00:00+02:00’
    price: 0.2681
  • start_time: β€˜2024-09-07T23:00:00+02:00’
    price: 0.2645

friendly_name: Tibber Forecast

When I use the Template-Editor I do not get any result… what do I wrong?

{% from β€˜cheapest_energy_hours.jinja’ import cheapest_energy_hours %}
{% set output = cheapest_energy_hours(sensor=β€˜sensor.tibber_forecast’, attr_today=β€˜forecast_today’, attr_tomorrow=β€˜prices_tomorrow’, time_key=β€˜datetime’, value_key=β€˜value’) %}

Hope you can help.

You are not outputting anything, you are only creating a variable called output

Add {{ output }} to actually return the variable

:grinning: ThatΒ΄s it. Sorry I am new to Jinja templates

No worries, happy to help!

Hi TheFes,

I am using this macro for a few days now and i made some helpers with templates i found in this topic.

I made three helpers, but the data is not consistent, with what i expect.

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.entsoezonneplan_average_electricity_price_today', attr_today='prices_today', value_key='price', time_key='readingDate', hours=2.5, lowest='true', mode='is_now') }}
{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.entsoezonneplan_average_electricity_price_today', attr_today='prices_today', hours=2.5, lowest='true', value_key='price', mode='time_min', time_format='time24') }}
{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.entsoezonneplan_average_electricity_price_today', attr_today='prices_today', hours=2.5, lowest=True, mode='min', value_key='price', precision=5) }}

All fine i get some data. For the first template, the true starts from 13:00 - 15:30. When i look in the energy prices that’s right.
For the second template is the start of the timeslot 14:00, where I expect 13:00. And the third template states 0.16063, if i look to the data, it’s the prices of tomorrow, and not exactly. I think it’s an average, divided to 2,5? Do you have any idea what i am doing wrong in my template sensors? I hope you can help me.

  • time: β€˜2024-09-17 00:00:00+02:00’ price: 0.25512 - time: β€˜2024-09-17 01:00:00+02:00’ price: 0.2512 - time: β€˜2024-09-17 02:00:00+02:00’ price: 0.24684 - time: β€˜2024-09-17 03:00:00+02:00’ price: 0.24503 - time: β€˜2024-09-17 04:00:00+02:00’ price: 0.23994 - time: β€˜2024-09-17 05:00:00+02:00’ price: 0.2447 - time: β€˜2024-09-17 06:00:00+02:00’ price: 0.26643 - time: β€˜2024-09-17 07:00:00+02:00’ price: 0.30582 - time: β€˜2024-09-17 08:00:00+02:00’ price: 0.30793 - time: β€˜2024-09-17 09:00:00+02:00’ price: 0.27042 - time: β€˜2024-09-17 10:00:00+02:00’ price: 0.24829 - time: β€˜2024-09-17 11:00:00+02:00’ price: 0.23324 - time: β€˜2024-09-17 12:00:00+02:00’ price: 0.2105 - time: β€˜2024-09-17 13:00:00+02:00’ price: 0.18549 - time: β€˜2024-09-17 14:00:00+02:00’ price: 0.16063 - time: β€˜2024-09-17 15:00:00+02:00’ price: 0.18622 - time: β€˜2024-09-17 16:00:00+02:00’ price: 0.22419 - time: β€˜2024-09-17 17:00:00+02:00’ price: 0.24703 - time: β€˜2024-09-17 18:00:00+02:00’ price: 0.28641 - time: β€˜2024-09-17 19:00:00+02:00’ price: 0.30959 - time: β€˜2024-09-17 20:00:00+02:00’ price: 0.28459 - time: β€˜2024-09-17 21:00:00+02:00’ price: 0.26644 - time: β€˜2024-09-17 22:00:00+02:00’ price: 0.25711 - time: β€˜2024-09-17 23:00:00+02:00’ price: 0.2516
    Prices tomorrow - time: β€˜2024-09-18 00:00:00+02:00’ price: 0.24605 - time: β€˜2024-09-18 01:00:00+02:00’ price: 0.24517 - time: β€˜2024-09-18 02:00:00+02:00’ price: 0.24605 - time: β€˜2024-09-18 03:00:00+02:00’ price: 0.2448 - time: β€˜2024-09-18 04:00:00+02:00’ price: 0.24194 - time: β€˜2024-09-18 05:00:00+02:00’ price: 0.25231 - time: β€˜2024-09-18 06:00:00+02:00’ price: 0.27249 - time: β€˜2024-09-18 07:00:00+02:00’ price: 0.31971 - time: β€˜2024-09-18 08:00:00+02:00’ price: 0.31107 - time: β€˜2024-09-18 09:00:00+02:00’ price: 0.27086 - time: β€˜2024-09-18 10:00:00+02:00’ price: 0.24574 - time: β€˜2024-09-18 11:00:00+02:00’ price: 0.20948 - time: β€˜2024-09-18 12:00:00+02:00’ price: 0.15826 - time: β€˜2024-09-18 13:00:00+02:00’ price: 0.15161 - time: β€˜2024-09-18 14:00:00+02:00’ price: 0.15153 - time: β€˜2024-09-18 15:00:00+02:00’ price: 0.15245 - time: β€˜2024-09-18 16:00:00+02:00’ price: 0.19381 - time: β€˜2024-09-18 17:00:00+02:00’ price: 0.24735 - time: β€˜2024-09-18 18:00:00+02:00’ price: 0.28431 - time: β€˜2024-09-18 19:00:00+02:00’ price: 0.30882 - time: β€˜2024-09-18 20:00:00+02:00’ price: 0.28258 - time: β€˜2024-09-18 21:00:00+02:00’ price: 0.25896 - time: β€˜2024-09-18 22:00:00+02:00’ price: 0.25147 - time: β€˜2024-09-18 23:00:00+02:00’ price: 0.2409
    Prices - time: β€˜2024-09-17 00:00:00+02:00’ price: 0.25512 - time: β€˜2024-09-17 01:00:00+02:00’ price: 0.2512 - time: β€˜2024-09-17 02:00:00+02:00’ price: 0.24684 - time: β€˜2024-09-17 03:00:00+02:00’ price: 0.24503 - time: β€˜2024-09-17 04:00:00+02:00’ price: 0.23994 - time: β€˜2024-09-17 05:00:00+02:00’ price: 0.2447 - time: β€˜2024-09-17 06:00:00+02:00’ price: 0.26643 - time: β€˜2024-09-17 07:00:00+02:00’ price: 0.30582 - time: β€˜2024-09-17 08:00:00+02:00’ price: 0.30793 - time: β€˜2024-09-17 09:00:00+02:00’ price: 0.27042 - time: β€˜2024-09-17 10:00:00+02:00’ price: 0.24829 - time: β€˜2024-09-17 11:00:00+02:00’ price: 0.23324 - time: β€˜2024-09-17 12:00:00+02:00’ price: 0.2105 - time: β€˜2024-09-17 13:00:00+02:00’ price: 0.18549 - time: β€˜2024-09-17 14:00:00+02:00’ price: 0.16063 - time: β€˜2024-09-17 15:00:00+02:00’ price: 0.18622 - time: β€˜2024-09-17 16:00:00+02:00’ price: 0.22419 - time: β€˜2024-09-17 17:00:00+02:00’ price: 0.24703 - time: β€˜2024-09-17 18:00:00+02:00’ price: 0.28641 - time: β€˜2024-09-17 19:00:00+02:00’ price: 0.30959 - time: β€˜2024-09-17 20:00:00+02:00’ price: 0.28459 - time: β€˜2024-09-17 21:00:00+02:00’ price: 0.26644 - time: β€˜2024-09-17 22:00:00+02:00’ price: 0.25711 - time: β€˜2024-09-17 23:00:00+02:00’ price: 0.2516 - time: β€˜2024-09-18 00:00:00+02:00’ price: 0.24605 - time: β€˜2024-09-18 01:00:00+02:00’ price: 0.24517 - time: β€˜2024-09-18 02:00:00+02:00’ price: 0.24605 - time: β€˜2024-09-18 03:00:00+02:00’ price: 0.2448 - time: β€˜2024-09-18 04:00:00+02:00’ price: 0.24194 - time: β€˜2024-09-18 05:00:00+02:00’ price: 0.25231 - time: β€˜2024-09-18 06:00:00+02:00’ price: 0.27249 - time: β€˜2024-09-18 07:00:00+02:00’ price: 0.31971 - time: β€˜2024-09-18 08:00:00+02:00’ price: 0.31107 - time: β€˜2024-09-18 09:00:00+02:00’ price: 0.27086 - time: β€˜2024-09-18 10:00:00+02:00’ price: 0.24574 - time: β€˜2024-09-18 11:00:00+02:00’ price: 0.20948 - time: β€˜2024-09-18 12:00:00+02:00’ price: 0.15826 - time: β€˜2024-09-18 13:00:00+02:00’ price: 0.15161 - time: β€˜2024-09-18 14:00:00+02:00’ price: 0.15153 - time: β€˜2024-09-18 15:00:00+02:00’ price: 0.15245 - time: β€˜2024-09-18 16:00:00+02:00’ price: 0.19381 - time: β€˜2024-09-18 17:00:00+02:00’ price: 0.24735 - time: β€˜2024-09-18 18:00:00+02:00’ price: 0.28431 - time: β€˜2024-09-18 19:00:00+02:00’ price: 0.30882 - time: β€˜2024-09-18 20:00:00+02:00’ price: 0.28258 - time: β€˜2024-09-18 21:00:00+02:00’ price: 0.25896 - time: β€˜2024-09-18 22:00:00+02:00’ price: 0.25147 - time: β€˜2024-09-18 23:00:00+02:00’ price: 0.2409

The second template doesn’t show the start of the timeslot, that would be mode='start' which is the default mode.
It now shows the time within the timeslot which has the cheapest price. And the price of 14:00 is lower that the price of 13:00 and 15:00

The third template shows the lowest price in the timeslot, which is the price at 14:00

1 Like

Okay that looks good for the second template. Thank you for your help. For the price is it possible to get the average or something like that?

That would be mode='average'

1 Like