Weishaupt Heatpump integration via modbus

Dear Weishaupt Users,

today i would like to share with you how i have integrated my Weishaupt Biblock Heat pump via modbus in Homeassistant.
I was in touch with some Weishaupt employees and happy that they have shared a List of Datapoints for modbus connectivity. Other ways of integrating were not 100% stable & i have now tested modbus through the last months & it works really great! It is even possible to set e.g. Operating mode or Target warmwater temperature.
Here is how it currently looks like:

Here are the steps to follow:

  1. Configure Modbus with static IP on your Weishaupt Device (not possible in WEMPortal - you need to configure it on the device)
  2. Configure modbus connectivity - here is my sample yaml:
Modbus YAML config
- name: wpump
  type: tcp
  host: 192.168.X.X
  port: 502
  climates:
      - name: "WP_Warmwasser"
        address: 42103
        input_type: holding
        count: 1
        data_type: int16
        max_temp: 50
        min_temp: 15
        offset: 0
        precision: 1
        scale: 0.1
        target_temp_register: 42103
        temp_step: 1
        temperature_unit: C
  sensors:
#Warmwasser
    - name: WP_Warmwassersolltemperatur
      slave: 1
      address: 32101
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
      unique_id: wpump.wwsolltemp
    - name: WP_Warmwassertemperatur
      slave: 1
      address: 32102
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
      unique_id: wpump.wwtemp
#System
    - name: WP_Betrieb
      slave: 1
      address: 30006
      input_type: input
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
      unique_id: wpump.betrieb
    - name: WP_Stoerungsfrei
      slave: 1
      address: 30005
      input_type: input
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
    - name: WP_AuĂźentemperatur
      slave: 1
      address: 30001
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
#Heizkreis
    - name: WP_Raumsolltemperatur
      slave: 1
      address: 31101
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
    - name: WP_Vorlaufsolltemperatur
      slave: 1
      address: 31104
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
    - name: WP_Vorlauftemperatur
      slave: 1
      address: 33104
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
    - name: WP_RĂĽcklauftemperatur
      slave: 1
      address: 33105
      input_type: input
      unit_of_measurement: °C
      state_class: measurement
      count: 1
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
    - name: WP_Leistungsanforderung
      slave: 1
      address: 33103
      input_type: input
      unit_of_measurement: '%'
      state_class: measurement
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WP_Heizkurve
      slave: 1
      address: 41108
      input_type: holding
      state_class: measurement
      count: 1
      scale: 0.01
      offset: 0
      precision: 2
      data_type: int16
# 2. WEZ
    - name: WP_E1_Status
      slave: 1
      address: 34104
      input_type: input
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
    - name: WP_E2_Status
      slave: 1
      address: 34105
      input_type: input
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
    - name: WP_E1_Stunden
      slave: 1
      address: 34106
      input_type: input
      unit_of_measurement: h
      state_class: measurement
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
    - name: WP_E2_Stunden
      slave: 1
      address: 34107
      input_type: input
      unit_of_measurement: h
      state_class: measurement
      count: 1
      scale: 1
      offset: 0
      precision: 0
      data_type: int16
#Stats
    - name: WPST_Gesamt_Tag
      slave: 1
      address: 36101
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_Gesamt_Monat
      slave: 1
      address: 36103
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_Gesamt_Jahr
      slave: 1
      address: 36104
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_Heizen_Tag
      slave: 1
      address: 36201
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_Heizen_Monat
      slave: 1
      address: 36203
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_Heizen_Jahr
      slave: 1
      address: 36204
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_WW_Tag
      slave: 1
      address: 36301
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_WW_Monat
      slave: 1
      address: 36303
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
    - name: WPST_WW_Jahr
      slave: 1
      address: 36304
      input_type: input
      unit_of_measurement: kWh
      state_class: measurement
      device_class: energy
      count: 1
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
  1. To make Status & Errormessage more readable, i have additionally added two template sensors in my config.yaml:
Template Sensors
- platform: template
    sensors:
            wp_betrieb_txt:
        value_template: >
          {% if is_state('sensor.betrieb', '19') %}
            Heizbetrieb
          {% elif is_state('sensor.betrieb', '20') %}
            Warmwasserbetrieb
          {% elif is_state('sensor.betrieb', '8') %}
            Abtauen
          {% elif is_state('sensor.betrieb', '15') %}
            Standzeit
          {% elif is_state('sensor.betrieb', '25') %}
            Sommer
          {% else %}
            {{ states('sensor.betrieb') }}       
          {% endif %}
        friendly_name: "WP Betrieb"
      wp_stoerung_txt:
        value_template: >
          {% if is_state('sensor.wp_stoerungsfrei', '1') %}
            keine Störung
          {% elif is_state('sensor.betrieb', '0') %}
            Störung
          {% else %}
            ERROR           
          {% endif %}
        friendly_name: "WP Störung"

If there are questions, i am happy to share more details.
Hope this helps:)

BR,
Tobias

9 Likes

For your template sensor, you can use elif (or is it elseif? idk) so you don’t need the nested if else.

1 Like

Thanks for that proposal, cleaner code is always a good thing. Tested it and works like a charm.
Updated my coding above.
BR,
Tobias

Hi,
just seeing your Post.
I did something similar with my KNV Heatpump via Modbus.
I’ve done all Modbus Communication via NodeRED since i switched my Home Automation from NR to HA. I only have a “Base Profile” on my Heatpump and change everthing via HA (HotWater, Roomtemp etc.) eg. iv there is enough PV Energy i boost the Hot Water…
Here what it look like.

greets from Austria. :wink:

3 Likes

Very nice,.thanks.
I used your code and it worked straight as a base for me.
Until now I used the wem Plugin from erickastelic and it worked fine for me too with the drawback that it works via Cloud.

I have one question: Did you already figure out how one can change the Values for the WP via Modbus TCP. For example if i want to set the Warmwasser Temperature or the Betriebsart to specific value
In your code you only read the values with sensors.

Thanks
Steffen

Great news:)
Yes, i expose Room Target Temp, WarmWatertemp and Operating Modes like Summer, Heat, Standby to my Dashboard.
The code for the template buttons for the operating modes:

Operating Modes YAML config
template:
  - button:
      - name: "WP_Mode_Summer"
        unique_id: WP_MODE_SUMMER
        press:
          service: modbus.write_register
          data:
            unit: 1
            address: 40001
            value: 3
            hub: wpump
      - name: "WP_Mode_Heat"
        unique_id: WP_MODE_HEAT
        press:
          service: modbus.write_register
          data:
            unit: 1
            address: 40001
            value: 1
            hub: wpump
      - name: "WP_Mode_Standby"
        unique_id: WP_MODE_STANDBY
        press:
          service: modbus.write_register
          data:
            unit: 1
            address: 40001
            value: 4
            hub: wpump

For the rest i did it with automations and input selects

Automations
- id: '1644268424637'
  alias: WPump_Raumsoll
  description: ''
  trigger:
  - platform: state
    entity_id: input_select.raumsoll
  condition: []
  action:
  - service: modbus.write_register
    data:
      address: 41105
      unit: 1
      hub: wpump
      value: '{% set state = states("input_select.raumsoll") | float * 10 -%}    {{
        state | int }}

        '
  mode: single
- id: '1644270205343'
  alias: WPump_Wassertemp
  description: ''
  trigger:
  - platform: state
    entity_id: input_select.warmwasser
  condition: []
  action:
  - service: modbus.write_register
    data:
      address: 42103
      unit: 1
      hub: wpump
      value: '{% set state = states("input_select.warmwasser") | float * 10 -%}    {{
        state | int }}

        '
  mode: single

Here is the List of datapoints i got from Weishaupt and are allowed to share with the community:

BR,
Tobias

3 Likes

Thanks for your info,

unfortunately I miss some register info for thinks like:
Weichentemperatur
Soll-Leistung Wärmepumpe
Ist Leistung Wärmepumpe
Stellung Heizkreisventil
…
With the old Implementation via wem Portal i got this information. I think the document is not complete because there are also values in other registers which are not mentioned in the document.

But for me it is difficult to figure out the meaning of this values.

LG Steffen

Hi Steffen,

not all values of wemportal are yet exposed via modbus. My Heatpump got a recent Software update this week (v 5.30) and there should be more datapoints exposed now. Still waiting for a new List of datapoints.
I will keep you updated as soon as i have it. Maybe there is more datapoints documented that are available in older versions as well.
For what reason you are using these values? Just for interest:)

BR,
Tobias

1 Like

I don’t really need the values. The IST-Leistung is interesting if I compare it to the power consumption.

I have one strange problem. If I read the registers for th. Energie Heizen/KĂĽhlen/Warmwasser/Gesamt I get values for the Day and Yesterday Values. But I always get the value 0 for all Month/Year statistic despite there are value in the heat pump.

Any idee what the problem could be:

Example:
Register 36101 - correct value
Register 36102 - correct value
Register 36103 - incorrect value: 0
Register 36104 - incorrect value: 0

No, no idea.
I have experienced that the statistics of the heatpump are anyhow not precise.
They are far different than the values i measure with our external heat meter.
What i know for sure is, that these statistics do not measure the additional electric heater (even if that has not been much in usage last winter)
Recently a temperature sensor was not working well and the result was, that Rücklauf appeared warmer than Vorlauf. The result was completely messed up statistics…
PLUS: statistics gets erased everytime a software update comes in. For me they are useless and i don’t trust them.

Hi Tobias,

we are currently installing the Biblock due to switching from Gas to Heat Pump.
Modbus-Integration is already on my ToDo-List, everything is prepared and once the installation is finalized i hope that the integration runs smothly.

Do you have a idea how to measure the heating cycles (Heiztakte)? My idea is to monitor in addition to the COP the amount of cycles per day to have a early warning in case they are too many (which will result in a reduced lifetime).

You said that you have a external heat meter? Which one is it - and is it also integrateable into home-assistant?

Last question which is slightly offtopic: You said you have updated the firmware to 5.3x. According to our label we have a 4.x installed. Was there any reason for the update? This was done by a Weishaupt technican, right?

BR,
Markus

Measuring heating cycles is quite straightforward, you need to define history_stats:

- platform: history_stats
    name: Heat pump cycles per hour
    entity_id: binary_sensor.heat_pump_is_on
    state: "on"
    type: count
    start: "{{ now().replace(hour=now().hour - 1) }}"
    end: "{{ now() }}"

Replace heat_pump_is_on with your actual sensor.

Cheers,
Kiri

Hi Markus,

Regarding the external heat meter - it is the typical Allmess Integral Ultra MK - i think there are options to integrate into HA, but i did not integrate them as of now…
Regarding the software update - we had problems when biblock changes its mode from e.g. Warmwater to Summer or so. This should now be solved with the new firmware and yes - the only way to update the firmware is to have a technician with a USB stick…
@kirimeister thank you for that example, will enhance my stats here as well:)

BR,
Tobias

By the way, is this all about the Biblock or some of you also made it work with the WWP LS? For me
the two look very similar, the Biblock starting at 12 kW, the WWP LS at 8 kW. The modbus part could be the same…

Hi @tobiasm

Muss man den Code einfach in die configuration.yaml packen und die IP der Heizung angeben? Ich komme irgendwie nicht weiter …

Eine kleine Anleitung wäre super, danke!!!

Edit:

In der configuration.yaml → modbus: !include Name der Datei.

Leider kann man die Werte so noch nicht fürs Energie Dashboard verwenden…

Im log habe ich folgende Fehler:
Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)


Hi Tobias,

I have noticed that in my system the values for “Raumsolltemperature” via the modbus query are different from the WEM portal.
For example, the modbus register for HK1 (31101) returns a value of 18.0 degrees, whereas the value from the WEM portal only shows 16.0 degrees.
Does anyone else have this problem?

I would also like to query the current values for “Ausgänge” via modbus, e.g. “Ausgang VA1” or “Zirkulationspumpe An/Aus”.
Is there already a documentation of more datapoints for this?

Thanks in advance
rainer

Hi all,

i am facing the same issue - the read-out data seems to be the old initial / factory values.
The same issue occurs with “Vorlaufsolltemperatur”, “Vorlauftemperatur” and all Temperature-Settings (Absenk, Normal, Komfort) for all heating circuits (Heizkreise).

For me it seems like an Bug in the firmware (my new unit as still the “old” V4), i don’t think that the registers are wrong because we are able to read them out… so in general they seem to be valid but with data-mess in it.

@Tobiasm:
Do you see the same issue with V5.x firmware?

BR,
Markus

Hi all,

another modbus related issue: the statistic values seems to be integer values (complete kwh), but in the WEM portal i can see up to 3 digits.
e.g register 36104 (Gesamt Energie Jahr): Modbus 151 KWh, WEM Portal 151.989 KWh.

Do you see the same - or do i have a mistake in my modbus configuration?

BR,
Markus

Hi Rainer

No solution for your question but maybe a valid work-around.
I had a similar challenge - and therefore i decided to use the Biblock Output for the “Zirkulationspumpe” as an input for the Shelly pro 2 (Switch-Input). One of the two Outputs is used for the Zirkulationspumpe, the other output is connected with the SG Ready Input of the Biblock.

The benefit is now that i can choose within the smarthome if i use the Biblock Zirkulationssteuerung or if i turn on the pump via motion control in the bathrooms.

The SG Ready is switched by OpenWB which I also use to manage the wallbox for the Battery electric vehicle. Within OpenWB you can configure if charging the PV battery or charging the vehicle has a higher priority - or if you prefer power2heat and switch the SG Ready instead / in addition dependent on the PV situation.

BR,
Markus