Custom Component: ENTSO-e Day Ahead Energy Prices

Has anyone built hourly cost “grid” for lovelace? It would be interesting to see not just the consumption per hour, but also the cost :thinking: Energy dashboard card does provide hourly consumption graph and grid for grid/gas/etc consumption per day, but not the hourly cost breakdown afaik.

Any thoughts?

Has anyone already made a template to show # of hours until the cheapest rate in the future?

So for example assuming it would be 10:00 now and at 14:00 it would be the lowest rate of ANY of the forecasted rates (ignoring date/today as at 12:00 the forecast will be updated with another batch of data which includes data of the next day), the outcome would be 4 (=4 hours from 10:00).

Use case: We delay the dishwasher manually and want to know how many hours I need to delay to get optimum price. I’m thinking of also adding a small ESP device with a display that shows that number.

1 Like

I have added a template for the prices:

{% set s = {"handling_fee": 0.0024793, "energie_belasting": 0.12599} %} {{(current_price + s.handling_fee + s.energie_belasting ) | float}}

And below settings, but price still shows the ‘bare’ price. Anything I’m missing in the setup?

Had the same, only thing that worked was remove integration, readd and rename to avoid entities with the same name. Don’t know why but that helped.

1 Like

Yes, there appears to be a bug in the integration that leads to old settings getting “stuck” unless you remove and re-add the integration.

I would love if you could rebuild that Template to work on the “4 Cheapest sequential” hours. That would be an immense help. I tried doing it myself, but my skills are woefully inadequate…

I have one for nordpool data, that one is static. Eg looks for x cheapest consecutive hours in a given range.

https://community.home-assistant.io/t/any-good-ideas-are-welcome-nordpool-energy-price-per-hour/34646/307

If you would want to make that dynamic it will become significantly more complex - after all, once the first hour of your range lapsed the averages change and everything would recalculate. Best to keep it static/ 1 calculation per period.


  cheapest_4_consecutive_hours:
    device_class: timestamp
    friendly_name:
      Cheapest 4 consecutive hours full day
      # Example configuration calculates three cheapest hours for the full next day (starting at 00:00 and ending 24 hours later at 00:00)
      # CHANGE-ME: numberOfSequentialHours = Number of sequential cheapest hours we are looking for
      # CHANGE-ME: lasthour = Final hour to do the calculation to (please note it's start of final hour e.g. 23:00-24:00)
      # CHANGE-ME: firstHour = First hour to do the calculation from
      # CHANGE-ME: change entity to your own sensor in the block below (TWO ENTRIES): sensor.nordpool_kwh_fi_eur_3_10_024
    value_template: >
      {%- set numberOfSequentialHours = 4 -%}
      {%- set lastHour = 23 -%}
      {%- set firstHour = 0 -%}
      {%- if state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', '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.nordpool_kwh_nl_eur_3_10_0', '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 -%}

  cheapest_4_hours_tomorrow_day_time:
    device_class: timestamp
    friendly_name:
      Cheapest 4 consecutive hours day time
      # Example configuration calculates three cheapest hours for the full next day (starting at 00:00 and ending 24 hours later at 00:00)
      # CHANGE-ME: numberOfSequentialHours = Number of sequential cheapest hours we are looking for
      # CHANGE-ME: lasthour = Final hour to do the calculation to (please note it's start of final hour e.g. 23:00-24:00)
      # CHANGE-ME: firstHour = First hour to do the calculation from
      # CHANGE-ME: change entity to your own sensor in the block below (TWO ENTRIES): sensor.nordpool_kwh_fi_eur_3_10_024
    value_template: >
      {%- set numberOfSequentialHours = 4 -%}
      {%- set lastHour = 22 -%}
      {%- set firstHour = 7 -%}
      {%- if state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', '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.nordpool_kwh_nl_eur_3_10_0', '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 -%}

For the record, I borrowed this from someone, did not make this myself!

2 Likes

Thanks.
I already have that Nordpool one, but it keeps getting stuck for me…it sometimes works perfectly, but if it sees the cheapest sequential hours in the “tomorrow” range, then it will forget them when tomorrow turns i to today. So this is not really reliable enough for what I have planned. Porting this over to use entso-e data was my first idea, but with the caveat above I don’t think it is really suitable.

My usecase for this would be to tell my (not yet installed) heat pump to go into overdrive via the SG Ready contact…
I guess I could try figuring out an “input number” helper and then feed that into some kind of scheduler automation…but right now I don’t know how that would work. It would be easier if I had ordered a heat pump from Nibe or Panasonic that has a functional HA integration or works directly with Tibber, but I went with what my local installer recommended and they only do Vaillant AFAIK and Vaillant unfortunately is not “Smart” at all.

Edit: Although…now that I took a closer look, I can see that the Templates you posted look a bit different, so I will give them a try and see how they behave.

You can also try https://github.com/dala318/nordpool_planner

Not sure if it’s maintained but it does work.

1 Like

Thanks.That looks promising and I will see if/how well it works for me. There are so many projecs out there targeting this, but so far they all had some quirk or complication. I tried nordpool_diff but could not really figure it out at all…

Seems we are looking for the same use cases. Also tried that one but it’s not straightforward enough. My heatpump (hybrid) which will come only in Q3 has a smart grid function, boost, normal, eco, off. This can be regulated with a dry contact. Maybe check if yours has that as well. Could easily automated that in HA with a simple esphome relay switch (2 channels).

1 Like

Yeah, I plan on using the SG Ready contact as well. Vaillant apparently doesn’t offer much variation when it comes to using that though…it does hot water first when activated and if the signal is still active beyond that it heats the “buffer” to some predefined offset.
I would try working with that and additionally turning up all my room Thermostats to actually get the heat flowing into my rooms and heating up the floor.

That looks good; However, so you know if it is also possible to derive a time when that condition is true? There are quite a few things I cannot fully automate yet (eg dishwasher) so knowing how many hours it takes before the condition is true helps setting the delay on the machine manually.

I have now below manually configured (with help of others) but that is much more basic. ‘Hours low coming’ will show # of hours from now that cheapest period starts

- platform: template
  sensors:
    time_low_coming:
      friendly_name: Time lowest price
      unique_id: time_low_coming
      device_class: timestamp
      value_template: >
        {% set fclist = state_attr('sensor.zonneplan_current_electricity_tariff','forcast') %}
        {% set pmin = fclist|map(attribute='price')|list|min %}
        {{ (fclist|selectattr('price','eq',pmin)|first)['datetime'] }}

- platform: template
  sensors:
    hours_low_coming:
      friendly_name: Hours lowest price
      unique_id: hours_low_coming
      value_template: >
        {% set n = as_timestamp(now()) %}
        {% set x = as_timestamp( states('sensor.time_low_coming') ) %}
        {% set t = (x-n) |timestamp_custom('%H') %}
        {{ int(t) }}

For me re-downloading the integration in HACS and in integrations section seemed to be enough. Guess I was lucky

Hmm…is there some kind of issue with Nordpool? It doesn’t seem to be updating anymore for me. Tibber and entso-e already have the data for tomorrow, Nordpool seems to be stuck. I don’t think I changed anything about the Nordpool custom component…

Edit! Never mind. Nordpool Update was a bit late and also, I made a mistake in configuring the Nordpool Planner.

It has a couple of attributes, for my 4 hour run it contains the following:

Starts at 15 January 2023 at 04:00:00
Cost at 0.16
Now cost rate 1.7

This assumes continuous stable kWh usage of course to calculate the average cost per kWh and current cost multiple.

I have tested my current set of Templates and Sensors for a few days now and it is working reliably for now. My current objective is storing cheap energy from the grid in my Solar battery and then using it during the day when prices are higher.

To avoid conflict with solar energy, I have created a “Charge Required” template, and that’s where I now hit a bit of a snag:

My current calculation uses the “solar production remaining today” from Solcast to calculate how much charge my battery should have, and this worked well enough when the cheapest hours were after midnight, however, yesterday the prices were lowest before midnight, and during that time my battery charged to 100% (since the solcast forecast drops to 0 after the sund goes down). The sensor reported the correct forecast for the next day after midnight, but by that point the battery was almost full already and it is possible that I will “lose” some solar yield to the grid that could have gone to the battery

I am wondering now, if there is a way to switch Sensors (yield remaining today <> yield tomorrow) after the sund goes down to better calculate the charge_required?
Right now I can’t see an easy way of doing that, but I am sure that is just due to my incompetence at both math and yaml…:wink:

Update: I think I fixed it. I made a second template “charge required tomorrow” that uses the tomorrow forecast data. Then I duplicated my automation and added “before sunset” to one, and “after sunset” to the other as condition. Then set the charge to SoC calculation to work with either the Charge needed or charge needed tomorrow templates and now hope it will work as expected. I am sure there is a far more elegant way with if/then/else but this was the best I could come up with so far.

Hello,
I try to get Entso from HACS but i can’t find it. Is there a problem or what do i wrong? please can own of you help me. Thanks a lot

You need to add the github repository for the integration

After adding the price modifier there is no need to reinstall the entso-e integration.
Just wait ~3 hours, the entities will automatically be updated.
(Maybe it’s time dependent: I changed it at 14:20 and 17:30 entities were updated)

1 Like