Dantherm HCV 400

modbus:
  name: dantherm_hub
  type: tcp
  host: 192.168.0.43
  port: 502

sensor:
  platform: modbus
  registers:
    - name: dantherm_fan_state
      hub: dantherm_hub
      slave: 1
      register: 324
      data_type: int
  
    - name: dantherm_outdoor_temperature
      hub: dantherm_hub
      unit_of_measurement: °C
      slave: 1
      register: 132
      count: 2
      reverse_order: true
      data_type: float
      precision: 1
      
    - name: dantherm_supply_temperature
      hub: dantherm_hub
      unit_of_measurement: °C
      slave: 1
      register: 134
      count: 2
      reverse_order: true
      data_type: float
      precision: 1
      
    - name: dantherm_extract_temperature
      hub: dantherm_hub
      unit_of_measurement: °C
      slave: 1
      register: 136
      count: 2
      reverse_order: true
      data_type: float
      precision: 1
      
    - name: dantherm_exhaust_temperature
      hub: dantherm_hub
      unit_of_measurement: °C
      slave: 1
      register: 138
      count: 2
      reverse_order: true
      data_type: float
      precision: 1

    - name: dantherm_humidity
      hub: dantherm_hub
      unit_of_measurement: "%"
      slave: 1
      register: 196
2 Likes

Hello, does this work with Dantherm HCV 400 P2 ventilation? :slight_smile:

Hi Michael.
To be honest I wasn’t aware of the P2 and E1 designations. I’m actually not sure which one I have at home. I can try to find out. From Dantherms brochure the difference looks to be the number of squaremeters it covers. My guess is the electronics is the same.
/Thomas

Hi again, did you use modbus and/or Ethernet port? :slight_smile:

Hi Michael.
I connected my router to the ethernet port on the PCB inside the unit. You also need to change the ip-address in the above configuration to the ip-address given to the unit. You can find it with Dantherm own app or in your router.
/Thomas

1 Like

i got it up and running… Where did you get the registers from? :slight_smile:

Hi Michael,

I’ve got a M1 MacBook which means it can run the tablet version of Danterms own app. I used Wireshark (Packet Sniffer) alongside the Danterm app to lure the registers out I was interested in. Wireshark have a Modbus display filter, so it’s easy to interpret the Modbus packets send by the App.

I hope it makes sense :slight_smile:

/Thomas

Hi Thomas

I would like to use your great work to create an integration platform that can be installed via hacs, so that the values are shown in a climate control Lovelace card and so that the settings can also be altered from the HA user interface.

Could you check what registers and values are used when changing mode and fan speed? Also how to get the filter condition? And how the app finds the IP? Are there other info that would be interesting?

Hi Michael,
I will try to find the information you are looking for, but I’m not at home for the next week or so. I think I can get back to you in two weeks time. I need local network access to the Dantherm unit to find the information.
/Thomas

2 Likes

I would love to use your component :blush:

I have created a basic custom component and a card setup using the picture element card. There might be some modbus reading errors that I need to understand. Is it common to have reading errors with modbus via tcp?

When I have the remaining modbus addresses, I will implement the fan & mode control and the filter status.

Please give me input to the layout and features needed on the card?
image

Hi Michael,
Where do you see the reading errors?

I think the card looks fine, maybe I will come up with some comments when I get more registers from the unit.

I have the “operation mode” to you. You can play with Dantherm app to see how to interpret the value, but it is something like this:
Bit 0-4 Op/mode
2 = Auto
4 = Manuel
8 = Week program
16 = Travel/Vacation
Bit 5 Night mode
0 = off
1 = on

    - name: dantherm_op_mode
      hub: dantherm_hub
      slave: 1
      register: 168
      count: 2
      reverse_order: true
      data_type: uint

I’m not sure how to configure writing to the register. Looking in Wireshark the Dantherm app writes the “operation mode” by writing multiple registers in one writing (register 168 and 169). Register 168 is the desired value (like described above) and register 169 is just zero. See if you can get something out of it. Write back to me if you need more info.
I will of cause find you more registers but I would like to hear if you can get this into Home Assistent.

Let me know.

/Thomas

Hi again,
This sent the Dantherm Unit into Manuel mode. Changing the value to [2,0] will send it back into Auto.

Filter periode:

   - name: dantherm_filter_period
      hub: dantherm_hub
      slave: 1
      register: 556
      count: 2
      reverse_order: true
      data_type: uint

Filter status:

  - name: dantherm_filter_status
      hub: dantherm_hub
      slave: 1
      register: 554
      count: 2
      reverse_order: true
      data_type: uint

/Thomas

Hey Thomas!
Managed to get my HCV 400 P2 working with your previous work. I had to change the syntax according to the Modbus documentation, but might have been me making an error in the original syntax.
For people interested, I’ve made an automation based on a button press from the IKEA Trådfri (IKEA E1812 control via MQTT | zigbee2mqtt.io) allowing the fan to run at 15 minutes, which is useful when showering or using the restroom. The automation also sets the fan back to auto mode, when the time has passed.

- id: '1629060094721'
  alias: Short Ventilation
  description: Sets ventilation to step 4 for 15 minutes
  trigger:
  - platform: device
    domain: mqtt
    type: action
    subtype: 'on'
    discovery_id: BathroomButton action_on
  condition: []
  action:
  - service: modbus.write_register
    data:
      hub: dantherm_hub
      address: 168
      unit: 0
      value:
      - 4
      - 0
  - service: modbus.write_register
    data:
      hub: dantherm_hub
      address: 324
      unit: 0
      value:
      - 4
      - 0
  - delay:
      hours: 0
      minutes: 15
      seconds: 0
      milliseconds: 0
  - service: modbus.write_register
    data:
      hub: dantherm_hub
      address: 168
      unit: 0
      value:
      - 2
      - 0
  mode: single
1 Like

Super. The Modbus syntax was changed if I am not mistaken in HA 2021.7. I actually first got to change my own configuration this weekend. I have a Philips Hue motion sensor laying around, maybe I should try your work letting motion in the bathroom trigger the higher ventilation stage. :slight_smile:

The ventilation is brand new for us, and just learned this morning that it actually increases the ventilation (when on automatic), when we shower, so depending on how fast your humidity sensor reacts, you might not need it for showering - only for certain other bathroom activities, where you’d like the smell to disappear quickly :wink:
Will you post your new config for others that might try replicating it will have the correct one for after 2021.7?
Additionally, are you getting meaningful data from all your temperature sensors? Most are giving me wrong numbers - which version of the ventilation did you have?

Hi Mettchen.
Maybe you mis byte swapping in your configuration?

This is my current configuration:

modbus:
  name: dantherm_hub
  type: tcp
  host: 192.168.0.43
  port: 502
  sensors:
    - name: dantherm_time
      scan_interval: 1
      slave: 1
      address: 108
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_fan_state
      scan_interval: 10
      slave: 1
      address: 324
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_op_mode
      scan_interval: 10
      slave: 1
      address: 472
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_bypass
      scan_interval: 10
      slave: 1
      address: 198
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_filter_remain
      scan_interval: 10
      unit_of_measurement: days
      slave: 1
      address: 554
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_filter_lifetime
      scan_interval: 10
      unit_of_measurement: days
      slave: 1
      address: 556
      count: 2
      swap: word
      data_type: uint
    - name: dantherm_outdoor_temperature
      scan_interval: 10
      unit_of_measurement: °C
      slave: 1
      address: 132
      count: 2
      swap: word
      data_type: float
      precision: 1
    - name: dantherm_supply_temperature
      scan_interval: 10
      unit_of_measurement: °C
      slave: 1
      address: 134
      count: 2
      swap: word
      data_type: float
      precision: 1
    - name: dantherm_extract_temperature
      scan_interval: 10
      unit_of_measurement: °C
      slave: 1
      address: 136
      count: 2
      swap: word
      data_type: float
      precision: 1
    - name: dantherm_exhaust_temperature
      scan_interval: 10
      unit_of_measurement: °C
      slave: 1
      address: 138
      count: 2
      swap: word
      data_type: float
      precision: 1
    - name: dantherm_humidity
      scan_interval: 10
      unit_of_measurement: "%"
      slave: 1
      address: 196
    - name: dantherm_fan1_rpm
      scan_interval: 10
      unit_of_measurement: "rpm"
      slave: 1
      address: 100
      count: 2
      swap: word
      data_type: float
      precision: 0
    - name: dantherm_fan2_rpm
      scan_interval: 10
      unit_of_measurement: "rpm"
      slave: 1
      address: 102
      count: 2
      swap: word
      data_type: float
      precision: 0
      
sensor:
  - platform: template
    sensors:
      dantherm_op_mode_template:
        value_template: >
         {% set op_mode = states("sensor.dantherm_op_mode") %}
         {% if (op_mode == "0") %}
            Standby
         {% elif (op_mode == "1") %}
            Manuel
         {% elif (op_mode == "2") %}
            Automatik
         {% elif (op_mode == "3") %}
            Uge program
         {% elif (op_mode == "5") %}
            Væk tilstand
         {% elif (op_mode == "6") %}
            Sommer tilstand
         {% elif (op_mode == "14") %}
            Afrimning slukket
         {% elif (op_mode == "15") %}
            Afrimning
         {% elif (op_mode == "16") %}
            Nattilstand
         {% else %}
            Ukendt
         {% endif %}
      dantherm_time_template:
        value_template: >
         {{ states.sensor.dantherm_time.state | int | timestamp_custom('%d.%m.%Y %H:%M', false)}}
      dantherm_bypass_template:
        value_template: >
         {% set bypass = states("sensor.dantherm_bypass") %}
         {% if (bypass == "0") %}
            Lukket
         {% elif (bypass == "1") %}
            Igang
         {% elif (bypass == "32") %}
            Lukker
         {% elif (bypass == "64") %}
            Åbner
         {% elif (bypass == "255") %}
            Åben
         {% else %}
            Ukendt
         {% endif %}

Sorry for the delayed response.
That was exactly it!
Tak! :slight_smile:

Hi all,
Playing around with my new Dantherm HCV400 unit. All above works perfectly well, but when I try to change op_mode on address 472, it seems not working. Tried on address 168 as Mettchen mentioned, but this send op_mode (on address 472) into 10 - which is unknown state, and cannot change it back into mode 1 or 2. Right now the unit only work manually with fan speed adjustments.

How to change it back?

My configuration:

modbus:
name: dantherm_hub
type: tcp
host: 192.168.0.236
port: 502
sensors:
- name: dantherm_fan_state
scan_interval: 10
slave: 1
address: 324
count: 2
swap: word
data_type: uint
- name: dantherm_op_mode
scan_interval: 10
slave: 1
address: 472
count: 2
swap: word
data_type: uint
- name: dantherm_bypass
scan_interval: 10
slave: 1
address: 198
count: 2
swap: word
data_type: uint
- name: dantherm_filter_remain
scan_interval: 10
unit_of_measurement: days
slave: 1
address: 554
count: 2
swap: word
data_type: uint
- name: dantherm_filter_lifetime
scan_interval: 10
unit_of_measurement: days
slave: 1
address: 556
count: 2
swap: word
data_type: uint
- name: dantherm_outdoor_temperature
scan_interval: 10
unit_of_measurement: °C
slave: 1
address: 132
count: 2
swap: word
data_type: float
precision: 1
- name: dantherm_supply_temperature
scan_interval: 10
unit_of_measurement: °C
slave: 1
address: 134
count: 2
swap: word
data_type: float
precision: 1
- name: dantherm_extract_temperature
scan_interval: 10
unit_of_measurement: °C
slave: 1
address: 136
count: 2
swap: word
data_type: float
precision: 1
- name: dantherm_exhaust_temperature
scan_interval: 10
unit_of_measurement: °C
slave: 1
address: 138
count: 2
swap: word
data_type: float
precision: 1
- name: dantherm_humidity
scan_interval: 10
unit_of_measurement: “%”
slave: 1
address: 196
- name: dantherm_fan1_rpm
scan_interval: 10
unit_of_measurement: “rpm”
slave: 1
address: 100
count: 2
swap: word
data_type: float
precision: 0
- name: dantherm_fan2_rpm
scan_interval: 10
unit_of_measurement: “rpm”
slave: 1
address: 102
count: 2
swap: word
data_type: float
precision: 0

sensor:

  • platform: template
    sensors:
    dantherm_op_mode_template:
    value_template: >
    {% set op_mode = states(“sensor.dantherm_op_mode”) %}
    {% if (op_mode == “0”) %}
    Standby
    {% elif (op_mode == “1”) %}
    Manuel
    {% elif (op_mode == “2”) %}
    Automatik
    {% elif (op_mode == “3”) %}
    Uge program
    {% elif (op_mode == “5”) %}
    Væk tilstand
    {% elif (op_mode == “6”) %}
    Sommer tilstand
    {% elif (op_mode == “14”) %}
    Afrimning slukket
    {% elif (op_mode == “15”) %}
    Afrimning
    {% elif (op_mode == “16”) %}
    Nattilstand
    {% else %}
    Ukendt
    {% endif %}
    dantherm_time_template:
    value_template: >
    {{ states.sensor.dantherm_time.state | int | timestamp_custom(’%d.%m.%Y %H:%M’, false)}}
    dantherm_bypass_template:
    value_template: >
    {% set bypass = states(“sensor.dantherm_bypass”) %}
    {% if (bypass == “0”) %}
    Lukket
    {% elif (bypass == “1”) %}
    Igang
    {% elif (bypass == “32”) %}
    Lukker
    {% elif (bypass == “64”) %}
    Åbner
    {% elif (bypass == “255”) %}
    Åben
    {% else %}
    Ukendt
    {% endif %}

Hi,
It seems your unit is in some “Installer Mode”.

Have you tried changing the state of the unit with Dantherms own app from your phone? Maybe it can bring the unit out of it? Or tell you something else?