Control Nibe heat pump using Shelly and SG ready based on Nordpool price

This is my take on controlling the heat and warm water.
My conditions:

  • NIBE 1126 Heatpump without internet connection, not compatible to nibepi or other modbusbased controllers.
  • Electricity billed by the our.

My nibe heat pump is prepared to take advantage of the SG-ready standard(not implemented in the Swedish grid) its controlled by connecting two potential free relays to the aux input according to the installer manual.(google it)
I use two shelly 1.


I use the Nordpool integration to get the prices then I calculate the median and based on that get a price level 1-5 depending on the current price.

- platform: template
  sensors:
    pricelevel_median_today:
      friendly_name: "ElprisnivÄ_median_today"
      unique_id: 95789542
      unit_of_measurement: "Level"
      value_template: >-
        {% set today=states.sensor.nordpool_kwh_se3_sek_3_10_025.attributes.raw_today| sort(attribute='value')-%}
        {%set median= (today[11].value+today[12].value)/2%}
        {% if states('sensor.nordpool_kwh_se3_sek_3_10_025')|float(0.5) >= median|float(0.5) *0.9
            and states('sensor.nordpool_kwh_se3_sek_3_10_025')|float(0.5) < median|float(0.5) *1.15 %}
            {{3}}
        {% elif states('sensor.nordpool_kwh_se3_sek_3_10_025')|float >= median|float *0.6
            and states('sensor.nordpool_kwh_se3_sek_3_10_025')|float < median|float *0.9 %}
            {{2}}
        {% elif states('sensor.nordpool_kwh_se3_sek_3_10_025')|float < median|float *0.6 %}
            {{1}}
        {% elif states('sensor.nordpool_kwh_se3_sek_3_10_025')|float >= median|float *1.15
            and states('sensor.nordpool_kwh_se3_sek_3_10_025')|float < median|float *1.4 %}
            {{4}}
        {% elif states('sensor.nordpool_kwh_se3_sek_3_10_025')|float >= median|float *1.4 %}
            {{5}}
        {% endif %}

based on the level I control the two shelly according to the manual I also included a condition that the house temperature must exceed 18,5 degrees to turn off the heat pump during the expensive ours.

This automation was made in the UI:

- id: '1662724568508'
  alias: SG-ready styrning
  description: ''
  trigger:
  - platform: state
    entity_id:
    - sensor.pricelevel_median_today_2
  condition: []
  action:
  - choose:
    - conditions:
      - condition: state
        entity_id: sensor.pricelevel_median_today_2
        state: '5'
      - condition: numeric_state
        entity_id: sensor.erikslund_medeltemperatur
        above: 18.5
      sequence:
      - service: switch.turn_on
        data: {}
        target:
          entity_id:
          - switch.shelly_aux1
      - service: switch.turn_off
        data: {}
        target:
          entity_id: switch.shelly_aux2
    - conditions:
      - condition: state
        entity_id: sensor.pricelevel_median_today_2
        state: '4'
      - condition: numeric_state
        entity_id: sensor.erikslund_medeltemperatur
        above: 18.5
      sequence:
      - service: switch.turn_off
        data: {}
        target:
          entity_id:
          - switch.shelly_aux2
      - service: switch.turn_on
        data: {}
        target:
          entity_id: switch.shelly_aux1
    - conditions:
      - condition: state
        entity_id: sensor.pricelevel_median_today_2
        state: '3'
      sequence:
      - service: switch.turn_off
        data: {}
        target:
          entity_id:
          - switch.shelly_aux1
          - switch.shelly_aux2
    - conditions:
      - condition: state
        entity_id: sensor.pricelevel_median_today_2
        state: '1'
      sequence:
      - service: switch.turn_on
        data: {}
        target:
          entity_id:
          - switch.shelly_aux1
          - switch.shelly_aux2
    - conditions:
      - condition: state
        entity_id: sensor.pricelevel_median_today_2
        state: '2'
      sequence:
      - type: turn_off
        device_id: eea66e1bcde095dcb077f74acaa8280a
        entity_id: switch.shelly_aux1
        domain: switch
      - type: turn_on
        device_id: 9004079f98be9e2e33b853aadd4dae81
        entity_id: switch.shelly_aux2
        domain: switch
    default:
    - service: switch.turn_off
      data: {}
      target:
        entity_id:
        - switch.shelly_aux1
        - switch.shelly_aux2
  mode: single
4 Likes

Hi.
Thank you for sharing.
I tired your code creating the 5-step sensor.
Thing is, i get Level 0 sometimes. Looking in my history the sensor never say Level 3.
Looking at the code but can’t really say what is wrong here.

  - platform: template
    sensors:
      pricelevel_median_today:
        friendly_name: "ElprisnivÄ_median_today_2"
        unit_of_measurement: "Level"
        value_template: >-
          {% set today=states.sensor.elpris_inkl_moms.attributes.raw_today| sort(attribute='value')-%}
          {%set median= (today[11].value+today[12].value)/2%}
          {% if states('sensor.sensor.elpris_inkl_moms')|float(0.5) >= median|float(0.5) *0.9
              and states('sensor.elpris_inkl_moms')|float(0.5) < median|float(0.5) *1.15 %}
              {{3}}
          {% elif states('sensor.elpris_inkl_moms')|float >= median|float *0.6
              and states('sensor.elpris_inkl_moms')|float < median|float *0.9 %}
              {{2}}
          {% elif states('sensor.elpris_inkl_moms')|float < median|float *0.6 %}
              {{1}}
          {% elif states('sensor.elpris_inkl_moms')|float >= median|float *1.15
              and states('sensor.elpris_inkl_moms')|float < median|float *1.4 %}
              {{4}}
          {% elif states('sensor.elpris_inkl_moms')|float >= median|float *1.4 %}
              {{5}}
          {% endif %}

I copied your code straight off and just replaced the nordpool sensor.
I even get wired readings like 4,25.


I have 2 sensors right now because I tried change the code i little bit but I can’t get it working.
ElprisnivÄ_median_today_2 is the sensor in the code above

I found the problem.
Took me a while to see it but I think I was too fast during the copy paste.

This line:
{% if states('sensor.sensor.elpris_inkl_moms')|float(0.5) >= median|float(0.5) *0.9
Shound be:
{% if states('sensor.elpris_inkl_moms')|float(0.5) >= median|float(0.5) *0.9

Thank you for a great pice of code.

Glad to hear it worked!

Hi,
I would like to calculate the median of prices, not by today or tomorrow but the median from 13.00 today to 13.00 tomorrow.
Is there a way to combine the attributes of today from 13.00 to tomorrow 13.00 and sort them, then calculate the average of attribute (12+ 13+13)/2?
Any ideas how to fix this?
//Erik

That should be possible, unfortunately i don’t have much time to look in to it at the moment due to Christmas coming up.
If you find a solution before i do please feel free to share it.

I do like your code, but I feel like I would like to be able to predict the outcome for the day, so including the value 1-5 into price chart (prefer Apex) would be optimal.

Any ideas from vilhelm or anyone else how could it be implemented.

At the moment my chart looks like this:

With the 7days average line (stroke width 0) the chart will autoscale it to that max value so I found it more informative, additionally blue line is the 7 day average line.

What i’m looking for is the price level median for each hour. Now I can see only the ongoing one.

Any ideas?

Nice to see this thread.

I am looking to do something similar with my ordered but not yet delivered Vaillant Heat Pump. Sadly Vaillant doesn’t offer much in terms of “smart features” so I am thinking about using the SG Ready approach with either Shelly or a Homematic IP multi-io box.

So I have done some more “thinking” on this topic and since I don’t have my heat pump yet I would like to put my current ideas out there and see what you think.

From what I understand, the PV Ready contact on Vaillant Heat Pumps does the following:

  1. It does a quick heat up of the hot water tank
  2. if the contact is still active after that, it heats the “buffer” for the heater to +X Kelvin above what is normally set.

My idea is to use Solar excess energy in Summer by enabling the relay through a Home Assistant binary sensor. This should put the excess into the hot water tank and hopefully use the remaining energy to run the “cooling” mode of the heat pump.
In Winter I would like to use the “cheapest hours” from entso/tibber/nordpool (whatever works best) to activate the same program, but what I am wondering is how many hours are best. Since I never owned a heat pump so far I have no experience with this
my gut feeling tells me 4 hours should work, but that is a very unprofessional way of planning.
At the same time I would set all my room Thermostats to “boost mode” so that the warm water actually gets circulated around the house.

Does anyone have and thoughts or insight to share concerning this?

Hey. I get this error from this code, can anybody help me with correct code: Message malformed: extra keys not allowed @ data[‘0’]

Hi,
I’m doing the same with my Nibe F1145-10 PC heat pump. The two potential free SG ready contacts are activated based upon availability of my solar energy. However the impact on my Nibe heatpump is pretty low. I see it rises the “S1 supply target temperature”, however the “hot water high target temperature” is not rised.
How is this working for you? Do you see an immediate reaction of the heatpump when activating the relais? And did you use any specific settings in Nibe?

Many thanks!

That would indeed be a nice feature, unfortunately i don’t know how to achieve it.

I think the best approach is trail and error, i dont have any statistics from my heatpumt so can’t really help.

Hi!
What part of the code is generating that fault?

Interesting, at the moment I don’t have any way to monitor the heatpump, i’m thinking about adding a couple of thermometers and monitoring the energy to better understand how to optimize it accordingly to electricity price.
Accordingly to my manual (nibe1126) it should rice the warm-water.
“ HĂ€r vĂ€ljer du om temperaturen pĂ„ varmvattnet fĂ„r pĂ„verkas vid aktivering av “SG Ready”.
Vid lĂ„gprislĂ€ge pĂ„ “SG Ready” sĂ€tts stopptemperaturen pĂ„ varmvattnet sĂ„ högt som möjligt vid enbart kompressordrift (elpatron tillĂ„ts ej).
Vid överkapacitetslĂ€ge pĂ„ “SG Ready” sĂ€tts varmvattnet i “lyx” (elpatron tillĂ„ts).”

Maybe it needs to reach the low threshold temp before it starts producing water and only then allows it to get extra hot?
In that case a bit poor design by nibe in my opinion.

Nice post, I was actually thinking of doing this myself and wanted to check if anyone in home assistant community done this before, surprise surprise there is always someone, so thanks for posting your findings and approach!

For my SMO20 I cant seem to get a straight answer if it can support local control via RS485, but I do have AUX inputs which can be used to trigger SG actions, so going to start thinking about how I can use this along with my variable Octopus tariff to control the heat pump operation more efficiently to my wallet!

Hope to help with the water situation, @tvds - my understanding is that S1 is responsible for climate only not water, so this won’t change the Target and the lows of hot water.

The water high target is effectively set by the Lux/Normal/Economy modes which can be changed in the Water settings which are only accessible via the Advanced config menu (holding back for a few seconds on my unit, yours might be different).

So if you want your Target water temperature to change you would have to setup something like this example:

  1. Standard operating hot water behaviour = Economy Target 40C - Low 38
  2. Create your desired Lux targets = Lux Target 60C - Low 57C
  3. When you fire an SG event also fire a Lux (boost) event so that temporarily affects your Hot water target temps, then when SG event is off also turn off the Lux (boost) event

In my example and use case, I will need to wire in 3 x Potential Free Shelly Plus 1’s into my AUX inputs:

  • 1 x to trigger Temporary Lux
  • 2 x to trigger the SG events i.e. “SG Ready A” and “SG Ready B” as listed in the manual.

Again just thoughts, Ive yet to do this at my place but this is my current thinking to the problem.

Hardware: ESP32 Built-in OLED Board (Wemos Lolin32): Pinout, Libraries and OLED Control | Random Nerd Tutorials
Software: GitHub - velvet-jones/sgready

I just finished code for an ESP32 smart switch that integrates with Home Assistant to switch my Nibe F-1155 into and out of SG Ready mode 1. It obeys the 10 minute state transition rule and it also falls back to normal operating mode if the MQTT broker is unresponsive. It’s not clear what an effect this will have but I will watch it over a few days. I did notice that mode 2 (Over capacity) turned the pump on immediately and it used a huge amount of power, but I am not sure it’s a good idea to force the pump to turn on. My idea is to push the pump to use excess solar, reducing the nighttime consumption. My carrier fees are substantial, so even if the price of electricity itself is low I still incur cost from the carrier.

1 Like

What is really the diffrence on mode 5 and 4 ? Looks like both do the same “Blocked operation” and temperature above 18.5

Correct, since my nibe SG only have 4 positions i went that way, however i use the 5 levels to control other automations around the house.

The 5 levels are a copy of Tibbers price levels.

1 Like

Awesome @vilhelm.carlsson ! I’m thinking about doing this myself. I have a f1226. Probably using esphome.
I also was a bit interested on utilizing the usb-service port, but that feels like a huge project.
I do have a question, maybe you have no knowledge about this, my heater has a indoor thermometer connected to aux 2, can I use sg ready with this or is that a nogo :sweat_smile:

Edit: Instructions say sg ready needs 2 ports, so probably not possible.