Tibber price level to turn on heating?

I’m using tibber as my electricity provider and it’s nicely integrated into home-assistant. The component have an attribute with price level that looks like this:

I have a spare heater that I want to run but only when the price is cheap or very_cheap and it’s plugged into a shelly switch.

Whats the best way to do an automation for this, make a trigger for every 1 minute past the hour and check the price level? If it’s cheap or very_cheap turn on the outlet?
If so I guess I need a new automation to turn it off for all the other levels or can I do that in the same automation somehow?

1 Like

I think it would be better to use the state trigger to trigger the automation when your electricity cost sensor changes state instead of periodically checking it.

You can do that in a single automation using templates. (You could also use the choose action, but it is easier to do with a template.)

trigger:
  - platform: state
    entity_id: sensor.your_sensor
    # trigger on all changes of the attribute
    attribute: PriceLevel
action:
  - service: >-
      {% set is_cheap = is_state_attr('sensor.your_sensor', 'PriceLevel', 'CHEAP') or
                        is_state_attr('sensor.your_sensor', 'PriceLevel', 'VERY_CHEAP') %}
      switch.turn_{{ 'on' if is_cheap else 'off' }}
    target:
      entity_id: switch.your_switch
2 Likes

I have the same set as you Näsström!
Would u mind share your price index script for tibber?

With today’s price it would be nice to have more options to choose from 😵‍💫

If you are a tibber user i think the tibber integration will provide the pricelevel sensor. Otherwise you can find useful information in this thread: Any good ideas are welcome. Nordpool Energy Price per hour - #126 by vilhelm.carlsson

Edit:
The price level is set as an attribute in the price sensor provided by the Tibber integration

2 Likes

Yeah Im a Tibber user.

Have set to “very_cheap” as you may understand :rofl:

But it’s not enough, price to high.

I use the code that Ondras posted. Wonder if it’s possible to use attri. “very_cheap” then add som kind of calc in the code just fine tuning?

It’s only me or somebody else is also getting incorrect state for price level from the API?

The price is 22.5% above avarage and it is returning “VERY_CHEAP”. It should be returning “EXPENSIVE” instead.

Ok, my fault… it’s no based on today’s average, but on the 3 days average (in my case, or 30 days average for daily values), so it might be correct.

So, now I’ve created my own template sensor doing the same calculation but with 1-day average and realized the values for price level can diverge a lot:

image

I will wait a few days to compare those values over time, but looks like I will have to rethink some of my automations.

This is how my 1-day sensor is set:

    - name: Electricity price - Price level (1-day)
      icon: mdi:currency-usd
      state: >-
        {% set price_cur = states('sensor.electricity_price_tibber') | float(0) %}
        {% set price_avg = state_attr('sensor.electricity_price_tibber', 'avg_price') | float(0) %}
        {% if price_cur == 0 or price_avg == 0 %}
          unknown
        {% else %}
          {% set price_ratio = (price_cur / price_avg) %}
          {% if price_ratio >= 1.4 %}
            VERY_EXPENSIVE
          {% elif price_ratio >= 1.15 %}
            EXPENSIVE
          {% elif price_ratio <= 0.6 %}
            VERY_CHEAP
          {% elif price_ratio <= 0.9 %}
            CHEAP
          {% else %}
            NORMAL
          {% endif %}
        {% endif %}
5 Likes

Trying to understand these concepts as I have the same need.
So is this a sensor that goes into configuration.yaml? The configuration validator complains about required key not provided @ data[‘platform’]. What platform should be provided for this?

My configuration.yaml looks like this Invalid config for [sensor]: required key not provided @ data['platform']. Got None. · GitHub

It have to be under Template > Sensor on your configuration.yaml.
Try this: (please remember to rename the entity_id of Tibber sensor for the name your integration is using)

template:
  sensor:
    - name: Electricity price - Price level (1-day)
      icon: mdi:currency-usd
      state: >-
        {% set price_cur = states('sensor.electricity_price_tibber') | float(0) %}
        {% set price_avg = state_attr('sensor.electricity_price_tibber', 'avg_price') | float(0) %}
        {% if price_cur == 0 or price_avg == 0 %}
          unknown
        {% else %}
          {% set price_ratio = (price_cur / price_avg) %}
          {% if price_ratio >= 1.4 %}
            VERY_EXPENSIVE
          {% elif price_ratio >= 1.15 %}
            EXPENSIVE
          {% elif price_ratio <= 0.6 %}
            VERY_CHEAP
          {% elif price_ratio <= 0.9 %}
            CHEAP
          {% else %}
            NORMAL
          {% endif %}
        {% endif %}
    - name: Electricity price - Price level (3-days)
      icon: mdi:currency-usd 
      state: "{{ state_attr('sensor.electricity_price_tibber', 'price_level') }}"
    - name: Electricity price - Price level (combined)
      icon: mdi:currency-usd
      state: >-
        {% set level1 = states('sensor.electricity_price_price_level_1_day') %}
        {% set level3 = states('sensor.electricity_price_price_level_3_days') %}
        {% if level1 == level3 %}
          {{ level1 }}
        {% elif level1 in ['unknown','undefined','none'] or level3 in ['unknown','undefined','none'] %}
          unknown
        {% elif level1 == "VERY_CHEAP" %}
          {{ level3 }}
        {% elif level3 == "VERY_CHEAP" %}
          {{ level1 }}
        {% elif level1 == "CHEAP" %}
          {{ level3 }}
        {% elif level3 == "CHEAP" %}
          {{ level1 }}
        {% elif level1 == "NORMAL" %}
          {{ level3 }}
        {% elif level3 == "NORMAL" %}
          {{ level1 }}
        {% elif level1 == "EXPENSIVE" %}
          {{ level3 }}
        {% else %}
          {{ level1 }}
        {% endif %}
3 Likes

Thanks a lot for sharing!
I am in need for a smarter control of my air-to-water heat pump and have just started to learn Home Assistant.
I first ran the code as is and it works fine.

I have modified the code a bit for my needs, but it does not work as intended… Maybe something with me not defining data types correctly?

My intention is to get rid of the enums (EXPENSIVE, NORMAL, etc) and instead use numbers (integer) so that I can print graphs for easier evaluation. Something like this:

Right now it looks like this in HA dashboard:


And as you can see the “History graph card configuration” seems to interpret my numbers as text…?
Please help me out!

Also, please explain the use of “combined” :confused:

I’ve included the following to my configuration.yaml:

template:
  - sensor:
      - name: Electricity Price - 5 Levels (24h)
        icon: mdi:currency-usd
        state: >-
          {% set price_cur = states('sensor.electricity_price_majbosv6') | float(0) %}
          {% set price_avg = state_attr('sensor.electricity_price_majbosv6', 'avg_price') | float(0) %}
          {% if price_cur == 0 or price_avg == 0 %}
            unknown
          {% else %}
            {% set price_ratio = (price_cur / price_avg) %}
            {% if price_ratio >= 1.4 %}
              5
            {% elif price_ratio >= 1.15 %}
              4
            {% elif price_ratio <= 0.6 %}
              1
            {% elif price_ratio <= 0.9 %}
              2
            {% else %}
              3
            {% endif %}
          {% endif %}
      - name: Electricity Price - 5 Levels (Tibber 3-days)
        icon: mdi:currency-usd
        state: >-
          {% set enum_lvl = state_attr('sensor.electricity_price_majbosv6', 'price_level') %}
          {% if enum_lvl == "VERY_CHEAP" %}
            1
          {% elif enum_lvl == "CHEAP" %}
            2
          {% elif enum_lvl == "NORMAL" %}
            3
          {% elif enum_lvl == "EXPENSIVE" %}
            4
          {% else %} # enum_lvl == "VERY_EXPENSIVE"
            5
          {% endif %}
      - name: Electricity Price - 5 Levels (combined)
        icon: mdi:currency-usd
        state: >-
          {% set level1 = states('sensor.electricity_price_5_levels_24h') %}
          {% set level3 = states('sensor.electricity_price_5_levels_tibber_3_days') %}
          {% if level1 == level3 %}
            {{ level1 }}
          {% elif level1 in ['unknown','undefined','none'] or level3 in ['unknown','undefined','none'] %}
            unknown
          {% elif level1 == "1" %}
            {{ level3 }}
          {% elif level3 == "1" %}
            {{ level1 }}
          {% elif level1 == "2" %}
            {{ level3 }}
          {% elif level3 == "2" %}
            {{ level1 }}
          {% elif level1 == "3" %}
            {{ level3 }}
          {% elif level3 == "3" %}
            {{ level1 }}
          {% elif level1 == "4" %}
            {{ level3 }}
          {% else %}
            {{ level1 }}
          {% endif %}

I will try… :smiley:

The original Tibber API have this “Price Level” comparing the current value with the average value in the past 3 days. I like that, but for some devices I’d like the same levels, but compared only with the current day, so you will find the 2 sensors with “(1-day)” or “(3-days)” in the name.
The “Combined” will result the worse case between those 2 sensors. Let’s say the price now is “VERY_CHEAP” in the 3-days sensor, but it’s “NORMAL” in the 1-day (this will happen in a day where electricity is cheaper than the previous 2 days). The result of the combined sensor will be “NORMAL”, as this is the worse case between those two.
In the same way, it can be that today is way more expensive than the previous days, so it can happy that at certain time, the 1-day sensor will result in “CHEAP”, but when comparing to the 3-days, that would be “EXPENSIVE”, to the combine will return “EXPENSIVE” (the worse between the 2 other sensors). It will be rarer to have “VERY_CHEAP” in the combined sensor.

I have some devices where I don’t have to turn on every day… let’s say, I have a bench with lots of battery chargers where my electric screwdriver, a AAA-battery charger, my camera’s charger, etc. are all connected to a switch. I wanna those devices to be charging only when the price is really cheap, so I use the combined sensor to find when it was “VERY_CHEAP” on both the 1-day and the 3-day sensors.

Did I succeeded in explaining this? :smiley:

Yes, I believe to have numbers as results you should have something like this (it’s ugly, maybe we should hve the values into a variable and then convert to int later):

template:
  - sensor:
      - name: Electricity Price - 5 Levels (24h)
        icon: mdi:currency-usd
        state: >-
          {% set price_cur = states('sensor.electricity_price_majbosv6') | float(0) %}
          {% set price_avg = state_attr('sensor.electricity_price_majbosv6', 'avg_price') | float(0) %}
          {% if price_cur == 0 or price_avg == 0 %}
            -1 | int(0)
          {% else %}
            {% set price_ratio = (price_cur / price_avg) %}
            {% if price_ratio >= 1.4 %}
              5 | int(0)
            {% elif price_ratio >= 1.15 %}
              4 | int(0)
            {% elif price_ratio <= 0.6 %}
              1 | int(0)
            {% elif price_ratio <= 0.9 %}
              2 | int(0)
            {% else %}
              3 | int(0)
            {% endif %}
          {% endif %}
      - name: Electricity Price - 5 Levels (Tibber 3-days)
        icon: mdi:currency-usd
        state: >-
          {% set enum_lvl = state_attr('sensor.electricity_price_majbosv6', 'price_level') %}
          {% if enum_lvl == "VERY_CHEAP" %}
            1 | int(0)
          {% elif enum_lvl == "CHEAP" %}
            2 | int(0)
          {% elif enum_lvl == "NORMAL" %}
            3 | int(0)
          {% elif enum_lvl == "EXPENSIVE" %}
            4 | int(0)
          {% else %} # enum_lvl == "VERY_EXPENSIVE"
            5 | int(0)
          {% endif %}
      - name: Electricity Price - 5 Levels (combined)
        icon: mdi:currency-usd
        state: >-
          {% set level1 = states('sensor.electricity_price_5_levels_24h') %}
          {% set level3 = states('sensor.electricity_price_5_levels_tibber_3_days') %}
          {% if level1 == level3 %}
            {{ level1 }}
          {% elif level1 in ['unknown','undefined','none'] or level3 in ['unknown','undefined','none'] %}
           -1  | int(0)
          {% elif level1 == "1" %}
            {{ level3 }} | int(0)
          {% elif level3 == "1" %}
            {{ level1 }} | int(0)
          {% elif level1 == "2" %}
            {{ level3 }} | int(0)
          {% elif level3 == "2" %}
            {{ level1 }} | int(0)
          {% elif level1 == "3" %}
            {{ level3 }} | int(0)
          {% elif level3 == "3" %}
            {{ level1 }} | int(0)
          {% elif level1 == "4" %}
            {{ level3 }} | int(0)
          {% else %}
            {{ level1 }} | int(0)
          {% endif %}

Note that I’ve converted “unknown” to “-1”, just because I don’t know how the “unknown” will affect your plot.
Try it and let me know. I can play a bit with this later.

Very much - thank you :smiley:

Thanks for your edited code! :sunflower: I tried your new code and now it looks like this:
image

Need to feed the family now. Will tinker more later. :canned_food:

Eureka! :dizzy:
https://www.home-assistant.io/dashboards/history-graph/ says that when a unit_of_measurement is defined it presents a graph.
So now it looks like I want it to:

And the code got reverted and unit_of_measurement added:

template:
  - sensor:
      - name: Electricity Price Level (24h)
        unit_of_measurement: ""
        icon: mdi:currency-usd
        state: >-
          {% set price_cur = states('sensor.electricity_price_majbosv6') | float(0) %}
          {% set price_avg = state_attr('sensor.electricity_price_majbosv6', 'avg_price') | float(0) %}
          {% if price_cur == 0 or price_avg == 0 %}
            -1
          {% else %}
            {% set price_ratio = (price_cur / price_avg) %}
            {% if price_ratio >= 1.4 %}
              5
            {% elif price_ratio >= 1.15 %}
              4
            {% elif price_ratio <= 0.6 %}
              1
            {% elif price_ratio <= 0.9 %}
              2
            {% else %}
              3
            {% endif %}
          {% endif %}
      - name: Electricity Price Level (Tibber 3-days)
        unit_of_measurement: ""
        icon: mdi:currency-usd
        state: >-
          {% set enum_lvl = state_attr('sensor.electricity_price_majbosv6', 'price_level') %}
          {% if enum_lvl == "VERY_CHEAP" %}
            1
          {% elif enum_lvl == "CHEAP" %}
            2
          {% elif enum_lvl == "NORMAL" %}
            3
          {% elif enum_lvl == "EXPENSIVE" %}
            4
          {% else %} # enum_lvl == "VERY_EXPENSIVE"
            5
          {% endif %}
      - name: Electricity Price Level (combined)
        unit_of_measurement: ""
        icon: mdi:currency-usd
        state: >-
          {% set level1 = states('sensor.electricity_price_level_24h') %}
          {% set level3 = states('sensor.electricity_price_level_tibber_3_days') %}
          {% if level1 == level3 %}
            {{ level1 }}
          {% elif level1 in ['unknown','undefined','none'] or level3 in ['unknown','undefined','none'] %}
            -1
          {% elif level1 == "1" %}
            {{ level3 }}
          {% elif level3 == "1" %}
            {{ level1 }}
          {% elif level1 == "2" %}
            {{ level3 }}
          {% elif level3 == "2" %}
            {{ level1 }}
          {% elif level1 == "3" %}
            {{ level3 }}
          {% elif level3 == "3" %}
            {{ level1 }}
          {% elif level1 == "4" %}
            {{ level3 }}
          {% else %}
            {{ level1 }}
          {% endif %}
1 Like

My next steps will be to adapt the code to my CTC heater, which only takes 4 levels as input. Also, I want to add variables so it’s easier to adjust each levels threshold. Something like this in dashboard:
image
“Entities Card Configuration”

1 Like

Cant get this to work… How do you add this to HA ?

Create a new automation in the UI. In the top right corner, click the overflow menu and select “Edit in YAML”. Now paste the example code I provided, replacing existing trigger: and action:. You should then be able to switch back to UI mode.

1 Like