WTH underfloor heating UMR2 regulator integration

In this topic we can build together upon a Home Assistant integration with the UMR2 regulator for your underfloor heating installation. These are products of the Dutch company called WTH. The UMR2 regulator together with the C820S1 thermostat provides bidirectional communication.

Hereby a first example in a .yaml file. Of course, names of thermostats, values and IP address has to be adjusted to your own situation.

Configuration.yaml
climate:
  - platform: generic_thermostat
    name: Woonkamer Vloerverwarming
    heater: sensor.SetpointWoonkamer
    target_sensor: sensor.nodered_5a4501dfcbd92b7c
    min_temp: 16
    max_temp: 22
    ac_mode: false
    target_temp: 17
    cold_tolerance: 0.3
    hot_tolerance: 0
    min_cycle_duration:
      seconds: 5
    keep_alive:
      minutes: 3
    initial_hvac_mode: "off"
    away_temp: 16
    precision: 0.1
    
shell_command:
  set_setpoint_woonkamer: 'curl -X POST -d "{\"status\": { \"process\": { \"thermostats\": [ {\"index\": 6, \"setpoint\": {{ data }}} ] } } }" 192.168.16.8/set_config.cgi'  

Below the automation to run the shell_command after a change in temperature:

Automation:
alias: Set woonkamer setpoint
description: ""
trigger:
  - platform: state
    entity_id:
      - climate.woonkamer_vloerverwarming
    attribute: temperature
condition: []
action:
  - service: shell_command.set_setpoint_woonkamer
    data_template:
      data: "{{ states.climate.woonkamer_vloerverwarming.attributes.temperature }}"
mode: single   

Via the Homekit bridge, for example, you can forward the data to Homekit.

1 Like

When using an older bus-thermostat (D9386) or power stealing thermostat, you can only read the state (on / off).

The mode of the the UMR2 can be read back (and probably controlled) as well.

configuration.yaml

rest:
  - resource: "http://<IP_ADDRESS>/get.json?f=$.status.*"
    scan_interval: 10
    sensor:
      - name: "UMR2 Mode"
        value_template: >
          {% set umr = value_json.status.main.mode %}
          {% if umr == 'heating' %}
            Verwarmen
          {% elif umr == 'cooling' %}
            Koelen
          {% elif umr == 'switchover' %}
            Omschakelen
          {% elif umr == 'on' %}
            Aan
          {% elif umr == 'off' %}
            Uit
          {% else %}
            Niet Aangesloten
          {% endif %}
        unique_id: "0_UMR2_Mode"
        icon: mdi:sun-snowflake-variant
      - name: "Thermostaat Woonkamer"
        value_template: "{% if value_json.status.process.thermostats[0].isOn == true %}Actief{% else %}Uit{% endif %}"
        unique_id: "0_UMR2_Thermostat0_Demand"
        icon: mdi:thermostat

# Control valves
shell_command:
  set_umr2_openvalve: 'curl -X POST -d "{\"settings\": { \"outputs\": { \"valves\": [ {\"index\": {{ (valve - 1) }}, \"mode\": \"{% if state == true %}on{% else %}auto{% endif %}\"} ] } } }" {{ ipaddress }}/set_config.cgi'

Switch between Open and Auto valves with a shell command.
This can be used to force valves open when you have a heat-pump with smart-grid support and you don’t have a thermostat with two way communication (C820S1).

service: shell_command.set_umr2_openvalve
data:
  ipaddress: <IP ADDRESS>
  valve: 1 - 10
  state:  true (= open ) / false (= automatic)

Doest this only work with the C820S1 thermostat? Or is the older D9386 also supported?

As far as I know, there is no way to read back and set the temperature from a D9386. It only returns the state (on / off) and mode (heat / cool).

The data on the bus (observed using an oscilloscope) does not change when the ambiant temperature or setpoint change.

the C820S1 thermostat provides bidirectional communication.

Do you have a specification of the C820S1 communication protocol?
The datasheet only mentions the basic parameters: 9600bps - 8N1
Which is useless information without the data protocol.

Not directly the same integration. But I created a python script to connect to the UMR2 and read out values and publish those on MQTT. in HA I then collect these sensor readings.
Link: GitHub - Sir-Bacon/UMR2toMQTT: Python routine to read out UMR2 floorheating controller and publish values to MQTT

I am currently still working on optimising the central heating installation in my home, trying to reduce gas consumption and be ready for a transition to a heat pump.

Bump. I reconfigured my setup to use a rest call to read out sensor. In that way there is no need to run a script and uyse a MQTT server. Details here:

@SirBacon Thanks for the example. Based on your example I added my power stealing thermostats, valves and cooling/heating. Next step is trying to add more control than the basic thermostats can give. I would like to heat based on some sensors like heat outside, cost of kwh, etc. I see some examples that try using api post. Anyone have any examples/experiences?

rest:
  - resource: 'http://192.168.2.201/get.json?f=$.status.*'
    scan_interval: 60
    sensor:
      - name: "Vloerverwarming modus"
        unique_id: 'vloerverwarming_modus'
        value_template: '{{ value_json.status.outputs.heater.mode }}'
      - name: "Vloerverkoeling modus"
        unique_id: 'vloerverkoeling_modus'
        value_template: '{{ value_json.status.outputs.cooler.mode }}'
      - name: "Vloerverwarming pomp"
        unique_id: 'vloerverwarming_pomp'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.pump.speed }}'
      - name: "Vloerverwarming klep"
        unique_id: 'vloerverwarming_klep'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.8.state }}'
      - name: "Vloerverkoeling klep"
        unique_id: 'vloerverkoeling_klep'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.9.state }}'
      - name: "Vloerverwarming klep 1"
        unique_id: 'vloerverwarming_klep_1'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.0.state }}'
      - name: "Vloerverwarming klep 2"
        unique_id: 'vloerverwarming_klep_2'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.1.state }}'
      - name: "Vloerverwarming klep 3"
        unique_id: 'vloerverwarming_klep_3'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.2.state }}'
      - name: "Vloerverwarming klep 4"
        unique_id: 'vloerverwarming_klep_4'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.3.state }}'
      - name: "Vloerverwarming klep 5"
        unique_id: 'vloerverwarming_klep_5'
        unit_of_measurement: "%"
        value_template: '{{ value_json.status.outputs.valves.4.state }}'
      - name: "Thermostaat 1"
        unique_id: 'thermostaat_1'
        value_template: '{{ value_json.status.inputs.thermostats.0.isOn }}'
      - name: "Thermostaat 2"
        unique_id: 'thermostaat_2'
        value_template: '{{ value_json.status.inputs.thermostats.1.isOn }}'
      - name: "Thermostaat 3"
        unique_id: 'thermostaat_3'
        value_template: '{{ value_json.status.inputs.thermostats.2.isOn }}'
      - name: "Thermostaat 4"
        unique_id: 'thermostaat_4'
        value_template: '{{ value_json.status.inputs.thermostats.3.isOn }}'
      - name: "Thermostaat 5"
        unique_id: 'thermostaat_5'
        value_template: '{{ value_json.status.inputs.thermostats.4.isOn }}'