Turning on/off a device when the average price is .90% or 1.05% of the daily energy price

If you look at the Nordpool attributes, it provides a mean of the day, and a current percent compared to average.

average: 3.280333333333333
off_peak_1: 2.5096249999999998
off_peak_2: 3.01725
peak: 3.8818333333333332
min: 2.236
max: 7.603
mean: 2.8345000000000002
unit: kWh
currency: DKK
country: Denmark
region: DK2
low_price: false
price_percent_to_average: 1.4559495986180266
today: 2.302, 2.295, 2.261, 2.265, 2.268, 2.236, 2.776, 3.674, 3.481, 2.98, 2.893, 2.797, 2.797, 2.819, 2.948, 3.437, 4.45, 7.603, 5.601, 4.776, 3.978, 2.85, 2.701, 2.54
tomorrow: 2.21, 2.199, 2.187, 2.182, 2.007, 2.22, 2.598, 3.26, 3.428, 3.074, 3.036, 2.905, 2.907, 2.887, 2.952, 3.331, 3.912, 5.938, 5.067, 4.082, 3.687, 2.71, 2.688, 2.579

@khvej8

You are certainly right with the averages here, but how to make a script that looks at the current price in comparison to the average and act on it. that is the big question.

Thanks for your reply :slight_smile:

@complex1

I’m gonna dive in to it. At least it has an ‘installer’. Thanks for the tip :slight_smile:

1 Like

@Boilerplate4u

So an ‘helper’ could help?:face_holding_back_tears: Let’s hope somebody can do something with it.

@OldSurferDude
Thanks for saying it is not (only) me. Sometimes I feel really stupid while struggling with YAML etc.:+1:t2:

1 Like

Yeah, I’ve tried a few times (most recently this summer) but gave up because of inconsistent handling of entities and attributes for different HVAC integrations, which means you have to account for tons of exceptions. It always ends up as this incomprehensible and unmanageable spaghetti code that doesn’t work, and the whole thing just crashes due to my frustration (WTF PITA! :smiley: ).

In my opinion, the current solution with templates/helpers works pretty well for small fixes. But if you want to do something more complex, you need a better solution. Why not just allow Python or another real and structured scripting language???

This is just a very small example how it might look like:

- sensor:
  - name: PT HVAC Activity
    state: "{{ state_attr('climate.tstat_4590be_lyric_t6_pro_thermostat', 'hvac_action') }}"
  - name: PP HVAC Activity
    state: "{{ state_attr('climate.tstat_8bf055_t6_pro_thermostat', 'hvac_action') }}"
  - name: Flex Room HVAC Activity
    state: "{{ state_attr('climate.tstat_899b8c_t6_pro_thermostat', 'hvac_action') }}"

  - name: HVAC Activity
    state: >
      {% set hvac = [ states('sensor.pt_hvac_activity'), states('sensor.pp_hvac_activity'), states('sensor.flex_room_hvac_activity') ] %}
      {% if hvac | select('eq', 'heating') | list | count > 0 %}
        heating
      {% elif hvac | select('eq', 'cooling') | list | count > 0 %}
        cooling
      {% elif hvac | select('eq', 'idle') | list | count == 3 %}
        idle
      {% else %}
        off
      {% endif %}
# HVAC Stats
- platform: history_stats
  name: HVAC Heating Today
  entity_id: sensor.hvac_activity
  state: 'heating'
  type: time
  start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
  end: '{{ now() }}'
   
- platform: history_stats
  name: HVAC Cooling Today
  entity_id: sensor.hvac_activity
  state: 'cooling'
  type: time
  start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
  end: '{{ now() }}'

views:
  - title: Home
    cards:
      - type: vertical-stack
          - type: history-graph
            entities:
              - entity: sensor.pp_hvac_activity
              - entity: sensor.pt_hvac_activity
              - entity: sensor.flex_room_hvac_activity
              - entity: sensor.hvac_activity
            title: HVAC Activity
            logarithmic_scale: false
      - type: vertical-stack
        cards:
          - type: gauge
            entity: sensor.heating_time_daily
            max: 24
          - type: gauge
            entity: sensor.heating_time_weekly
            max: 168
          - type: gauge
            entity: sensor.heating_time_monthly
            max: 720
          - type: gauge
            entity: sensor.heating_time_yearly
            max: 8760
      - type: vertical-stack
        cards:
          - type: gauge
            entity: sensor.cooling_time_daily
            max: 24
          - type: gauge
            entity: sensor.cooling_time_weekly
            max: 168
          - type: gauge
            entity: sensor.cooling_time_monthly
            max: 720
          - type: gauge
            entity: sensor.cooling_time_yearly
            max: 8760
title: Temperature

A template trigger. Here a example with 95%, using the mean value. There is also the average value you can use.

{{ states('sensor.nordpool_kwh_dk2_dkk_3_095_025') < (state_attr('sensor.nordpool_kwh_dk2_dkk_3_095_025',"mean")*0.95) }}

But how do I use this? How to create a trigger? and how to read it?

Ewout

@Boilerplate4u

In my case not Hvac complexity. Just a YAML (copied from an automation) should do the trick. But somehow it often fails to activate again after prices a nice again.

alias: Tibber price control test
description: “this should activate the heat in high when prices are average or cheaper”
use_blueprint:
path: komakino/tibber-electricity-price-threshold-trigger.yaml
input:
tibber_price_sensor: sensor.reinemoen_electricity_price
below_actions:
- device_id: ab9403f812c3a908d274da81523cd43f
domain: mobile_app
type: notify
message: Stroomprijs ‘cheap’
- device_id: 3bccf98a2ad4367f1afde032e93b7aad
domain: select
entity_id: adc4be8a516fc3a0ed5c0f42d31ffac0
type: select_option
option: high
above_actions:
- device_id: ab9403f812c3a908d274da81523cd43f
domain: mobile_app
type: notify
message: Stroomprijs ‘expensive’
- device_id: 3bccf98a2ad4367f1afde032e93b7aad
domain: select
entity_id: adc4be8a516fc3a0ed5c0f42d31ffac0
type: select_option
option: low
threshold: NORMAL

In the GUI, create an automation. Press “add trigger”, choose “template” and paste the template.

The YAML version will look like this.

alias: 0 test tmp
description: ""
triggers:
  - trigger: template
    value_template: >-
      {{ states('sensor.nordpool_kwh_dk2_dkk_3_095_025') <
      (state_attr('sensor.nordpool_kwh_dk2_dkk_3_095_025',"mean")*0.95) }}
conditions: []
actions: []
mode: single

Thanks a lot!

If you need two different actions depending on whether the mean value is below 0.90% or above 1.05%, can that be done in the same template like a binary template or similar? Also, is it possible to calculate the mean value over a certain period, like 3 hours?

The easy way to get different values as automation triggers, is to create different automations. then it is also easy to have different actions.

Not sure how to create a mean over a shorter period, however all the information is in the nordpool sensor. Might be easier to use some of the many blueprints providing similar options… Like this one : Nordpool price cheap/expensive actions

1 Like

@EwoutSchalkwijk, if you’re planning to try fixing this with your own code or by using a blueprint, I’d really appreciate it if you could let me know how it goes.

I’ve given up for now and just don’t have the energy to deal with HA anymore. It’s like taking over an object-oriented development project where the internal classes have zero documentation. :wink:

@Boilerplate4u , you know what? since today my Nordpool integration stopped working, my Balboa spa stopped as well. I’m getting sick and tired of this ‘geek’ toys.

It’s time to make HA available and understandable to the ordinary people or get glue a big warning on it. This is plain rubbish.

Suddenly entities are missing or no longer supported, I’m getting more and more sick of it.

But I’m not giving up yet.:rage:

there should be some sort of platform that works, and better yet, survives an update…

1 Like

This is a fix you can do.

1 Like

@mhoogenbosch,

dankjewel voor je tip,

I think I have something else going on since I already ‘quick and dirty’ fixed the error, but still it is not working.

the Balboa, Zigbee and Netatmo errors (all came up today) I fixed by deleting the integration and adding it again.

The Nordpool integration I cannot remove it and therefore install it again. It is complaining about an old entity that no longer exists, but it seems no option to delete it is offered as well.

I made some screenshots.



You have a typo. It’s "nordpool==0.4.2", notice the missing >

@EwoutSchalkwijk;

I came across this incredibly simple sensor, ‘billigaste_energi_hushallsmaskiner’ designed to run the washing machine at the absolute lowest cost. The algorithm is, of course, well-documented and so easy to understand that even a toddler could code it blindfolded.

This also demonstrates just how incredibly well-structured and purposeful YAML is for the development of ‘templates,’ especially when dealing with complex algorimts. :wink:

sensors:
billigaste_energi_hushallsmaskiner:
device_class: timestamp
friendly_name: billigaste energi hushallsmaskiner

value_template: >
{%- set numberOfSequentialHours = states(‘input_number.num_timmar_till_hushallsmaskiner’) | int() -%}
{%- set lastHour = 24 -%}
{%- set firstHour = ((as_timestamp(now() ) | timestamp_custom(‘%H’)) | int() ) -%}
{%- if state_attr(‘sensor.el_spotpris’, ‘tomorrow_valid’) == true and now().hour >=13-%}
{%- set ns = namespace(counter=0, list=[], cheapestHour=today_at(“00:00”) + timedelta( hours = (24)), cheapestPrice=999.00) -%}
{%- for i in range(firstHour + numberOfSequentialHours, lastHour +9 ) -%}
{%- set ns.counter = 0.0 -%}
{%- for j in range(i-numberOfSequentialHours, i) -%}
{%- if j < 24 -%}
{%- set ns.counter = ns.counter + state_attr('sensor.el_spotpris', 'today')[j] -%}
{%- else -%}
{%- set ns.counter = ns.counter + state_attr('sensor.el_spotpris', 'tomorrow')[j-24] -%}
{%- endif -%}
{%- 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 = (i – numberOfSequentialHours )) -%}
{%- endif -%}
{%- endfor -%}
{{ ns.cheapestHour }}
{%- set ns.cheapestPrice = (ns.cheapestPrice / numberOfSequentialHours) -%}
{%- else -%}
{%- 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.el_spotpris', 'today')[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 = (i – numberOfSequentialHours )) -%}
{%- endif -%}
{%- endfor -%}
{{ ns.cheapestHour }}
{%- set ns.cheapestPrice = (ns.cheapestPrice / numberOfSequentialHours) -%}
{%- endif -%}

leskefjesRegular

3h

You have a typo. It’s "nordpool==0.4.2", notice the missing >

It works!:heart_eyes:

How easy to oversee if you don’t know syntaxis🫣

Thank you very much. (taking my hat off for you)

1 Like

:joy: I like your sarcasm. I read it like a bed time story.:lying_face::rofl:

The thing I’m most happy with is that I’m not alone. I thought all these ‘automations’ were far more ‘fool proof’, but this fool proves it is not.

1 Like

image