Any good ideas are welcome. Nordpool Energy Price per hour

Great and looking forward to your setup.

My small excercise targeted the delayed start of the dishwasher - HA now detects that it is powered on, turns off a socket switch and delays power on until lowest hour (lucklily the dishwasher just continous where it was interupted, as opposed to the washing machine that expects human operation in terms of pushing the power button once again :sob:

1 Like

I’m trying to understand what the low_price_cutoff do?

I have finally got this setup back up online again after the SD-corruption and the problems around daylight savings.
Lets see if I can manage to explain.

First off all. I have a batterypack without solar, wind or water. I have a charger/inverter and a grid-tie inverter. The intension is to charge the batteries with cheap power, and use that power when its more expensive. The way I have setup this to work the best is to adjust when to charge/discharge based on how much power I have stored. I also adjust the temperature of the waterheater to store more energy that way. It uses an external temp sensor, so when I set it to 60degrees, the water is in reality a bit warmer. Its based on trial and error during a lot of showers monitoring the temp sensor. I never want it too cold, but when the batteries is low on charge, I don’t want to use power on heating the water warmer then needed for a short shower.

I made this chart with the numbers I have set today. (this will most likely change based on use)


“Prosent” is the state of charge.
“Lav” is the percentage from the lowest price the batteries will charge.
“Høy” is the percentage from the highest price the grid-tie will activate if the usage is above 1600w (Inverter is 1000w).
“Temp” is the temperature setting for the waterheater.

The first thing to do then is to find out what the lowest and highest price is (today and tomorrow).

Finding tomorrows low/high:

  - platform: template
    sensors: 
      norpool_values_tomorrow_max:
        friendly_name: "Norpool tomorrow max"
        value_template: "{% set high=namespace(kr=-100.0) -%}
{% set time=namespace(hr=0) -%}
{%- for kr in states.sensor.nordpool_kwh_oslo_nok_3_10_025.attributes.tomorrow -%}
{%- if kr > high.kr|float -%}{%- set high.kr=kr|float -%}{%- endif -%}
{% endfor -%}
{% set hr=time.hr -1 -%}
{{ high.kr }}"
       
      norpool_values_tomorrow_min:
        friendly_name: "Norpool tomorrow min"
        value_template: "{% set low=namespace(kr=100.0) -%}
{% set time=namespace(hr=0) -%}
{%- for kr in states.sensor.nordpool_kwh_oslo_nok_3_10_025.attributes.tomorrow -%}
{%- if kr < low.kr|float -%}{%- set low.kr=kr|float -%}{%- endif -%}
{% endfor -%}
{% set hr=time.hr -1 -%}
{{ low.kr }}"

Then figuring out what the lowest/highest numbers are combining both today and tomorrow:

  - platform: template
    sensors:
      min_pris:
        value_template: >-
          {% set sensors = [ 
            state_attr('sensor.nordpool_kwh_oslo_nok_3_10_025', 'min')|float,
            states('sensor.norpool_values_tomorrow_min')|float,
            ]
          %}
  
          {{ sensors|min }}
        unit_of_measurement: 'kr'
        
  - platform: template
    sensors:
      max_pris:
        value_template: >-
          {% set sensors = [ 
            state_attr('sensor.nordpool_kwh_oslo_nok_3_10_025', 'max')|float,
            states('sensor.norpool_values_tomorrow_max')|float,
            ]
          %}
  
          {{ sensors|max }}
        unit_of_measurement: 'kr'

Then we need to figure out when to charge and discharge.
High price - Low price * percentage (one for the low, and one for the high):

  - platform: template
    sensors:
     prosent_lav:
       friendly_name: “prosentlav”
       value_template: "{{ ((states('sensor.max_pris') |float - (states('sensor.min_pris') |float)) * (states('input_number.lavprosent') |float))  }}"
  - platform: template
    sensors:
     prosent_hoy:
       friendly_name: “prosenthoy”
       value_template: "{{ ((states('sensor.max_pris') |float - (states('sensor.min_pris') |float)) * (states('input_number.hoyprosent') |float))  }}"

We now know how much to add and subtract from the lowest and highest price :

  - platform: template
    sensors:
      prosent_ned:
        friendly_name: “Prosentned”
        value_template: "{{ (states('sensor.max_pris') |float - states('sensor.prosent_hoy') |float) }}"        
        
  - platform: template
    sensors:
      prosent_opp:
        friendly_name: “Prosentopp”
        value_template: "{{ (states('sensor.min_pris') |float + states('sensor.prosent_lav') |float) }}"

Then its just another automation activating “cheap” and “expensive” if the current price is under or above the set “low” and “high” limits.
The automations activate a couple of boolean inputs, the charger or the grid-tie inverter.

This is also visually shown in a chart where the green line shows the “low” limit and the red line shows the “high” limit. When the price has been above or under the limits, it lights up in green og red:

Sorry for the long an confusing post. Feel free to ask, and Ill try to explain in better words :stuck_out_tongue: .
The next step will be to use “average price” . Now if we have 1 hour with extreme high or low price, the whole days limits will be based from that price. I would like to find a way to incorporate the avg price to get better use of the battery.

5 Likes

Today is a perfect example of why it would be great to figure out the best way to incorporate the average price into the equation.

Tomorrow has a few really expensive hours, but its not necessary to charge the batteries all other hours…

Hopefully not too off topic, but here’s my take on a binary sensor that is on during the cheapest three hour periods in the night/morning (starting from 00:00 to 06:00) and day (starting from 09:00 to 14:00). You can obviously change it to suit your needs. I use this to automate my water heater. Probably not the most elegant way to get this done, but it works :slight_smile:

template:
  - binary_sensor:
      - name: Lowest price period
        unique_id: electricty_lowest_price
        state: >-
          {% set interval_night_1 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').0 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').1 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').2) %}
          {% set interval_night_2 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').1 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').2 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').3) %}
          {% set interval_night_3 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').2 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').3 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').4) %}
          {% set interval_night_4 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').3 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').4 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').5) %}
          {% set interval_night_5 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').4 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').5 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').6) %}
          {% set interval_night_6 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').5 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').6 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').7) %}
          {% set interval_night_7 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').6 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').7 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').8) %}
          {% set lowest_price_night = [interval_night_1,interval_night_2,interval_night_3,interval_night_4,interval_night_5,interval_night_6,interval_night_7] | min %}
          {% if lowest_price_night == interval_night_1 %}
          {% set start_time_night = 0 %}
          {% elif lowest_price_night == interval_night_2 %}
          {% set start_time_night = 1 %}
          {% elif lowest_price_night == interval_night_3 %}
          {% set start_time_night = 2 %}
          {% elif lowest_price_night == interval_night_4 %}
          {% set start_time_night = 3 %}
          {% elif lowest_price_night == interval_night_5 %}
          {% set start_time_night = 4 %}
          {% elif lowest_price_night == interval_night_6 %}
          {% set start_time_night = 5 %}
          {% elif lowest_price_night == interval_night_7 %}
          {% set start_time_night = 6 %}
          {% endif %}
          {% set end_time_night = start_time_night | int + 3 %}
          {% set interval_day_1 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').9 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').10 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').11) %}
          {% set interval_day_2 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').10 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').11 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').12) %}
          {% set interval_day_3 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').11 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').12 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').13) %}
          {% set interval_day_4 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').12 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').13 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').14) %}
          {% set interval_day_5 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').13 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').14 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').15) %}
          {% set interval_day_6 = (state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').14 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').15 + state_attr('sensor.nordpool_kwh_krsand_nok_3_10_025', 'today').16) %}
          {% set lowest_price_day = [interval_day_1,interval_day_2,interval_day_3,interval_day_4,interval_day_5,interval_day_6] | min %}
          {% if lowest_price_day == interval_day_1 %}
          {% set start_time_day = 9 %}
          {% elif lowest_price_day == interval_day_2 %}
          {% set start_time_day = 10 %}
          {% elif lowest_price_day == interval_day_3 %}
          {% set start_time_day = 11 %}
          {% elif lowest_price_day == interval_day_4 %}
          {% set start_time_day = 12 %}
          {% elif lowest_price_day == interval_day_5 %}
          {% set start_time_day = 13 %}
          {% elif lowest_price_day == interval_day_6 %}
          {% set start_time_day = 14 %}
          {% endif %}
          {% set end_time_day = start_time_day | int + 3 %}
          {{ (now().hour | int >= start_time_night | int and now().hour | int < end_time_night) 
          or (now().hour | int >= start_time_day | int and now().hour | int < end_time_day) }}
2 Likes

I use this
> Blockquote

It could be done with less code if you sort the table with prices

unique_id: billigste_timer_1_3
name: billigste_timer_1_3
state: >-
  {% set l=state_attr('sensor.nordpool', 'raw_today')|sort(attribute='value') %}
  {% set t = now() %}
  {{  (t >= l[0].start and t <= l[0].end)
    or (t >= l[1].start and t <= l[1].end)
    or (t >= l[2].start and t <= l[2].end) }}

And if you want time intervals you could use selectattr

unique_id: billigere_etter_midnatt
name: billigere_etter_midnatt
state: >-
  {% set l1=state_attr('sensor.nordpool', 'raw_today')|selectattr('start', '>=', now().replace(hour=18,minute=0,second=0,microsecond=0))|sort(attribute='value') %}
  {% set l2=state_attr('sensor.nordpool', 'raw_tomorrow')|selectattr('start', '<', (now()+timedelta(days=1)).replace(hour=6,minute=0,second=0,microsecond=0))|sort(attribute='value') %}
  {% set l3=state_attr('sensor.nordpool', 'raw_tomorrow')|selectattr('start', '>=', (now()+timedelta(days=1)).replace(hour=6,minute=0,second=0,microsecond=0))|sort(attribute='value') %}
  {% if now().hour>=18 and l3|length>0 and l2|length>0 and l1|length>0 %}
  {{ float(l2[0].value)<float(l1[0].value) and float(l2[0].value)<float(l3[0].value)}}
  {% else %}
  false
  {% endif %}
2 Likes

If there are Estonian users, I share the tariffs and total electricity price including VAT.

Tariffs:

  - platform: template
    sensors:
      el_tariff:
        friendly_name: "Electricity Tariffs"
        unit_of_measurement: '€/kWh'
        value_template: >-
          {% macro calc(v) -%}
            {%set d = {"operator_margin": 0.001,
                      "electricity_excise": 0.001,
                      "renewable_tariff": 0.0113,
                      "nw_fee_night": 0.0162,
                      "nw_fee_day": 0.0283

           } %}
          {%set day_price = v + ((d.operator_margin + d.renewable_tariff + d.electricity_excise + d.nw_fee_day) * 1.2 | float ) | round(4)%}
          {%set night_price = v + ((d.operator_margin + d.renewable_tariff + d.electricity_excise + d.nw_fee_night) * 1.2 | float ) | round(4)%}
          {% if now().weekday() in (5,6) %}
           {{night_price}}
          {% else %}
            {% if now().hour >= 7 and now().hour < 22%}
              {{day_price}}
            {% else %}
              {{night_price}}
            {% endif %}
          {% endif %}
          {%- endmacro %}

          {{calc(0)}}

Total electorcity price

  - platform: template
    sensors:
      total_el_price:
        friendly_name: "Total Electicity Price"
        unit_of_measurement: '€/kWh'
        value_template: "{{ (states('sensor.nordpool_kwh_ee_eur_3_05_02')  | float
                            + states('sensor.el_tariff') | float) | round (2) }}"

Nordpool integration conf as well

  - platform: nordpool
    VAT: True
    currency: "EUR"
    low_price_cutoff: 0.5
    region: "EE"
    precision: 3
    price_type: kWh
6 Likes

Do you happen to have the code for retrieving the current price from nordpool? Seems useful for the energy monitoring tab.

I’m using the “Total Electicity Price” in energy management, because this is what te exact cost is.

1 Like

And intervals could be easier like this:

unique_id: billigere_etter_midnatt
name: billigere_etter_midnatt
state: >-
  {% set l1=state_attr('sensor.nordpool', 'raw_today')[18:]|sort(attribute='value') %}
  {% set l2=state_attr('sensor.nordpool', 'raw_tomorrow')[:6]|sort(attribute='value') %}
  {% set l3=state_attr('sensor.nordpool', 'raw_tomorrow')[6:]|sort(attribute='value') %}
  {% if now().hour>=18 and l3|length>0 and l2|length>0 and l1|length>0 %}
  {{ float(l2[0].value)<float(l1[0].value) and float(l2[0].value)<float(l3[0].value)}}
  {% else %}
  false
  {% endif %}

This requires that the values for tomorrow are already available, and will give an error if not.
With that said, I really like your approach!

I dont get any data. Just copy and paste into configuration.yaml? Changed sensor to sensor.nordpool_kwh_se3_sek_3_095_025 according to my sensor. Where in your yaml do you add the code?

Does anyone know a way to create a copy of the nordpool sensor with tariff added to the values in the raw_today and raw_tomorrow attributes? The tariff varies during the day.

I want to make an automation which triggers at midnight and 2pm to create (update) a new sensor with nordpool values + tariff. The format of the sensor should be equal to the nordpool sensor.

The script works fully.

1 Like

This is very interesting.
Any idea on how to turn this around and select the two most expensive hours before and after midd day (12:00)?
I am tryin to do some peak shaving, and want to turn off some of the the equipment during the most expensive hours. Since we normally see a morning peak and an afternoon peak I want a sensor that goes high in the peak hours.

Hi

Love the idea of getting this integrated, but i am a terrible noob, that can only right now do integration for stuff already in the HASS “store”

My dream scenario would be to be able to pull data like “Current price” and “tendency”

If i could do this, i could do some IFTTT integration to say “Start washing machine if price is below X and the tendency is falling ot stable”

This to be able to do washing and tumbling of clothes when the price is the lowest…

Would be great to save a bit of money on electricity, while at the same time use electricity when there is most surplus.

In summer it’s the other way around, i have solar panels and a battery pack, so there i will want to start the machine if production is above a certain wattage, and the battery pack is atleast 50% full, to maximise the own-use of electricity that i produce.

Here i get paid for what i produce right now, and pay for what i use right nok, and the difference is that i get 1/6 for what i sell, compared to what i must pay, so it is a very good deal to use my own power when i make it, because it will only cost about 1/6 of what i must pay if i have to buy the electricity to run the machines

1 Like

Comparing current price with future average/media/lowpass values would seem to be a good indicator. You problably need to modify the nordpool custom component, or make a separate script/component to which you feed the nordpool raw data and do the processing.

Yeah, i am nowhere near bright enough to do that.

I will just have to hope someone else, with enough intelligence needs these figures and makes this integration.

I can do basic linux stuff, and all of the automated stuff.

I also have a Roth Touchline controller that i wanted to integrate, but i can not even get that to work, so i am pretty “useless” unless someone else does the genious stuff, and i can just “copy” or install it.

I use the code below to use Nordpool prices to calculate a price level indicator (same as Tibber), just replaced the text output with numeric values for simple use in automations (level 1-5, 5 most expensive). This works very well and allows me to for ex. set a savings program when price level is 5. The code only calculates the current price level. It would be very useful to calculate this value for all values in the Nordpool sensor, both today and tomorrow.

This could be developed further to indicate how long a level 5 savings program will be active etc, and eventually users could input the max length the program should be active and normal program should be re-instated.

Any idea how the future price levels can be calculated?

Code for average price last 72 hours:

sensor:
  - platform: nordpool
    region: "Oslo"
  - platform: statistics
    name: "Strompris_3d_snitt"
    entity_id: sensor.nordpool_kwh_oslo_nok_3_10_025
    precision: 4
    sampling_size: 144
    max_age:
      hours: 72

Code to set price level:

  - platform: template
    sensors:
      pricelevel2:
        friendly_name: "Strømprisnivå"
        unit_of_measurement: 'Level'
        value_template: >-
            {% if states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float(0.5) >= states('sensor.strompris_3d_snitt')|float(0.5) *0.9
                and states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float(0.5) < states('sensor.strompris_3d_snitt')|float(0.5) *1.15 %}
                {{3}}
            {% elif states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float >= states('sensor.strompris_3d_snitt')|float *0.6
                and states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float < states('sensor.strompris_3d_snitt')|float *0.9 %}
                {{2}}
            {% elif states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float < states('sensor.strompris_3d_snitt')|float *0.6 %}
                {{1}}
            {% elif states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float >= states('sensor.strompris_3d_snitt')|float *1.15
                and states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float < states('sensor.strompris_3d_snitt')|float *1.4 %}
                {{4}}
            {% elif states('sensor.nordpool_kwh_oslo_nok_3_10_025')|float >= states('sensor.strompris_3d_snitt')|float *1.4 %}
                {{5}}
            {% endif %}
4 Likes