Pull cheapest electricity price for template sensor - Solar

Hi all, I was hoping someone could help me with a bit of data sampling. I have a Huawei solar set up with a battery, and I’m investigating how I can charge the battery at the cheapest time (normally early in the morning), and sell back to the grid at the most expensive time (normally around 6-7am), but only if the electricity price is high enough at the most expensive time, so I can actually earn something from selling it. When I sell electricity back to the grid, I only get the raw electricity price (so not including taxes, transport etc).

For example, here in Denmark at the moment, it’s typically around 2dkk / kWh in the early hours of the morning, where about 1 dkk of that is taxes, transport of electricity etc. At the most expensive time, it can be around 4dkk / kWh, where it’s still about 1 dkk for taxes, transport of electricity etc. This means that there is a raw electricity price difference of 3 dkk, so I can in theory buy at the cheapest time (2 dkk) and sell back at the most expensive (4 dkk, or when I get 3 dkk / kWh). But this doesn’t happen everyday… Hence I would like to extract the prices, and create some automations to charge, and discharge the battery, only when it pays.

Currently I use the Energi data service integration, so I get the complete electricity price. This pulls in all the data, so I can calculate periods of where it’s cheap, expensive etc. But what I can’t figure out, is how to extract the price at a particular hour. For example, I have a template sensor that looks for the cheapest 3 hour in the morning, as described here (I assume everyone playing with the Nordpool integration has seen this).

But now I would like to extract a price at those cheapest hours, and so the same at the most expensive time. Here’s the code I use for extracting the cheapest period, just in case it helps someone.

#Cheapest energy prices at night
  - platform: template
    sensors:
      cheapest_electricity_at_night:
        device_class: timestamp
        friendly_name: Cheapest electricity at night
        value_template: >
          {%- set numberOfSequentialHours = 3 -%}
          {%- set lastHour = 7 -%}
          {%- set firstHour = 0 -%}

          {%- if state_attr('sensor.energi_data_service', 'tomorrow_valid') == true -%}
            {%- set ns = namespace(counter=0, list=[], cheapestHour=today_at("00:00") + timedelta( hours = (24)), cheapestPrice=999.00) -%}
            {%- for i in range(firstHour + numberOfSequentialHours, lastHour+1) -%}
              {%- set ns.counter = 0.0 -%}
              {%- for j in range(i-numberOfSequentialHours, i) -%}
                {%- set ns.counter = ns.counter + state_attr('sensor.energi_data_service', 'tomorrow')[j] -%}
              {%- endfor -%}
              {%- set ns.list = ns.list + [ns.counter] -%}
              {%- if ns.counter < ns.cheapestPrice -%}
                {%- set ns.cheapestPrice = ns.counter -%}
                {%- set ns.cheapestHour = today_at("00:00") + timedelta( hours = (24 + i - numberOfSequentialHours)) -%}
              {%- endif -%}
            {%- endfor -%}
            {{ ns.cheapestHour }}
            {%- set ns.cheapestPrice = ns.cheapestPrice / numberOfSequentialHours -%}
          {%- endif -%}

Any help would be msot appreciated :slight_smile:

Use @TheFes’s cheapest hour macro. No need for you to reinvent the wheel.

In case of questions, feel free to ask here

I do need to update that post though, it’s missing some updates.

Many thanks for sharing your cheapest hour macro.

I’ve installed it, and currently playing with it, but am not sure quite how to use it, or where I put the code…

If I try and explain an example, then perhaps you can help explain how to format the code, and where I need to place it (config??).

I have the following sensor -

sensor.energi_data_service

It has an attribute called ‘today’, with a list of all the prices for every hour (probably just like Nordpool).

If I know that the most expensive hour is at 07:00, how do I use your macro to extract the price at that hour (please explain for dummies)?

cheapest_energy_hours('your_entity_id', hours=1, lowest=False)

That will give the datetime string, for the price you can add mode='max' (or mode='min', or mode='average', as they are all the same in a 1 hour period)

cheapest_energy_hours('your_entity_id', hours=1, lowest=False, mode='max')```

Sorry guys, thanks for trying to help out but I really need a dummies explanation of how to use this macro.

I have the following sensor -

sensor.energi_data_service

It has an attribute called ‘today’, with a list of all the prices for every hour (probably just like Nordpool).

If I know that the most expensive hour is at 07:00, how do I use your macro to extract the price at that hour? Where do I place this code to create a sensor?

cheapest_energy_hours('sensor.energi_data_service', attr_today='today', hours=1, lowest=False, mode='max')

So you installed the custom template in HACS right?

Does that sensor also provide a raw_today attribute? Can you show the attribute data from devtools > states?

Are you using this integration? In that case you should have all the data needed for the macro

Assuming you installed the macro from HACS, try this in developer tools > templates

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.energi_data_service', attr_today='today', hours=1, lowest=False, mode='max') }}

@celodnb
I had a closer look at the code you provided, and read your post a bit better.

This should give the same 7:00 timestamp (as a full datetime isoformat string) as you already had. Note that I have it end at “10:00”. My macro will take the end provided as the end of the 3 hour period, so if you provide end='07:00' the start of the 3 hour period will be 04:00 latest

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.energi_data_service', hours=3, end='10:00') }}

Then this (with the same import above it) will give the lowest price in that 3 hour period:

{{ cheapest_energy_hours('sensor.energi_data_service', hours=3, end='10:00', mode='min') }}

And this will return the highest price

{{ cheapest_energy_hours('sensor.energi_data_service', hours=3, end='10:00', mode='max') }}

@celodnb did you get it working?

Hi, really sorry for the late reply! Thanks for your efforts, but so far I’ve not got it working (but I also haven’t spent much time on it so far). Time’s limited these days, so right now I’m prioritising a couple of other HA projects when time between kids allows :rofl:

Hello TheFes,

I am trying to get your template sensor going.

I installed it thru HACS (Experimental Features enabled) and can see the jinja file in /config/custom_templates/cheapest_energy_hours.jinja.

I reloaded the Home Assistant Core Integration: Reload custom Jinja2 templates service call.

The integration I am using to pull the energy data from is EntsoE;
I use sensor “sensor.dynamische_prijzen_elektriciteit_average_electricity_price_today”; attribute is “prices_today”.

Attributes for above sensor look like this:
state_class: measurement
prices_today:

  • time: ‘2023-10-17 00:00:00+02:00’
    price: 0.12758
  • time: ‘2023-10-17 01:00:00+02:00’
    price: 0.11404
  • time: ‘2023-10-17 02:00:00+02:00’
    price: 0.1084
  • time: ‘2023-10-17 03:00:00+02:00’
    price: 0.10636
  • time: ‘2023-10-17 04:00:00+02:00’
    price: 0.1021
  • time: ‘2023-10-17 05:00:00+02:00’
    price: 0.10899
  • time: ‘2023-10-17 06:00:00+02:00’
    price: 0.11876
  • time: ‘2023-10-17 07:00:00+02:00’
    price: 0.14877
  • time: ‘2023-10-17 08:00:00+02:00’
    price: 0.17582
  • time: ‘2023-10-17 09:00:00+02:00’
    price: 0.15948
  • time: ‘2023-10-17 10:00:00+02:00’
    price: 0.135
  • time: ‘2023-10-17 11:00:00+02:00’
    price: 0.11376
  • time: ‘2023-10-17 12:00:00+02:00’
    price: 0.10552
  • time: ‘2023-10-17 13:00:00+02:00’
    price: 0.08933
  • time: ‘2023-10-17 14:00:00+02:00’
    price: 0.07948
  • time: ‘2023-10-17 15:00:00+02:00’
    price: 0.09
  • time: ‘2023-10-17 16:00:00+02:00’
    price: 0.10203
  • time: ‘2023-10-17 17:00:00+02:00’
    price: 0.11396
  • time: ‘2023-10-17 18:00:00+02:00’
    price: 0.13865
  • time: ‘2023-10-17 19:00:00+02:00’
    price: 0.15225
  • time: ‘2023-10-17 20:00:00+02:00’
    price: 0.12848
  • time: ‘2023-10-17 21:00:00+02:00’
    price: 0.10776
  • time: ‘2023-10-17 22:00:00+02:00’
    price: 0.09651
  • time: ‘2023-10-17 23:00:00+02:00’
    price: 0.08731

I try the following code in Template:

{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.dynamische_prijzen_elektriciteit_average_electricity_price_today', attr_today='prices_today', hours=1, lowest=False, mode='max') }}

I get error “UndefinedError: ‘dph’ is undefined”

Could you help me out?

Thanks for your work and your support!

Best regards,

Rogy

This has been solved, thanks to TheFes.

See this thread:
Cheapest Energy Hours - Jinja macro for dynamic energy prices - Share your Projects! - Home Assistant Community (home-assistant.io)

1 Like

I am using the energy provider Tibber that provides the prices like this (see picture).
Is there a way to use the macro for this sensor format as well? If I try to apply the macro it always complains “UndefinedError: ‘h’ is undefined”. Any thoughts here that could help?

The macro expects a datetime (string) with the time the price is valid. I could add support for the list you now have, assuming the first item is the price at midnight.

Don’t know when I will find some time for that. You could also create a template sensor to transform your data to the expected format

You can try with this

template:
  - sensor:
      - unique_id: 9706c04c-7f21-492f-851f-4f854eaaa7ae
        state: "{{ states('sensor.tibber_prices') }}"
        name: Tibber prices for macro
        attributes:
          today: >
            {% set source = state_attr('sensor.tibber_prices', 'today') | default([], true)%}
            {% set ns = namespace(new=[]) %}
            {% for i in source %}
              {% set td = timedelta(hours=24/source|count) %}
              {% set ns.new = ns.new + [dict(datetime=(today_at()+loop.index0*td).isoformat(), value=i.total)] %}
            {% endfor %}
            {{ ns.new }}
          tomorrow: >
            {% set source = state_attr('sensor.tibber_prices', 'tomorrow') | default([], true)%}
            {% set ns = namespace(new=[]) %}
            {% for i in source %}
              {% set td = timedelta(hours=24/source|count) %}
              {% set ns.new = ns.new + [dict(datetime=(today_at()+loop.index0*td).isoformat(), value=i.total)] %}
            {% endfor %}
            {{ ns.new }}

That should give you a new sensor with entity_id sensor.tibber_prices_for_macro which you can use in the macro

1 Like

many thanks for the quick solution idea. I will test it soon :slight_smile:

The new sensor is created like the attached picture.


Unfortunately, if I tested it, it still creates an error message:

It seems that I used a wrong macro logic. With
“{{ cheapest_energy_hours(‘sensor.tibber_prices_for_macro’, attr_today=‘today’, hours=1, lowest=True, mode=‘max’) }}”
it worked now. Many Thanks :slight_smile: