Integration of Heatpump Ochsner Tronic Smart Services (OTS) via Modbus

Ochsner support for Smart Home Integration is very poor, at least they are providing a modbus document “ZBH-Modbus OTS-EN03” for the Ochsner Tronic Smart Services (OTS) for eg. “AIR HAWK 208”.

Originally I was expecting to be able to have full functionality of the OTS-App via modbus. In reality only a very limited subset of read-only registers is provided. No possibility to set parameters like in the app are provided at all (there is very limited functionality to transfer info to the heatpump or control the heatpump via building management system).

The heatpump “AIR HAWK 208” supports Modbus TCP. Utilizing Home Assistant Modbus integration and Ochsner document “ZBH-Modbus OTS-EN03” I was able to setup all defined sensors.

In the energy power card plus I did split up the total house-consumption into the amount used by the heatpump and the remaining amount used by the house otherwise.

Based on the defined modbus sensors and some thermometer and a shelly PM I did create a view which might be of interest for others as well. It includes several 24 h graphs and a more detailed view on current values of sensors.

See following posts for the yaml code for Ochsner Modbus. You need to containt Ochsner support in order to unlock modbus for your system.

Please let me know your ideas how this view could be improved.

Hi Alfred99
That’s what I call a coincidence. On Friday I received the activation for the modbus interface for my airhawk 518 from Ochsner. My next step is to integrate the heat pump into Home Assistant. I would therefore be very interested in the yaml listing. Would be nice if you could publish it.
Many thanks in advance.
Mackenheimer

Hello,

find below my YAML code. Updated 20240309 to Version 0.91!
V0.91 in particular overcomes the precision problem which was a consequence of HA Release 2024.2

V0.9:
The updated version has fixed the previous uint32 workaround. The version is fully compatible to the initial version. Please update in case you downloaded the intial version.

Please share your experience, suggestions, …
Good luck!
Alfred

# Configuraton according OTS MODBUS INTERFACE (document ZBH-Modbus OTS-EN03.pdf)
# e.g. Ochsner Air Hawk 208
# Version: 0.91
# Changes:
# - device_class defined for most entities (temperature, power, energy, ...)
# - unique_id: change to full name (incompatible with <=V0.9)
# - scale combined with precision since it was broken in 2024.2 if used without precicion
# Version: 0.9
# Changes:
# - uint32 now correctly specified (using swap: word), change is compatible to previous version
# Comments and conventions used
# - sensors are named:
#     'OTS_'<register-address>'_'<designation>
#     Values representing text are appended by '_number'
#     'DHW' (domestic hot water) represented as "hot water"
#     Sensor templates are defined for each value representing text
# - unit_of_measurement and scale are defined where specified
# - unique_id assigned in order to assign friendly name via UI  
# - some sensors not present in all configurations are commented
# Known issues:
# - some entities should be defined as input_type: holding in order to be able
#   to write values (addr 1-5 and 149-162)



# Ochsner Air Hawk 208 Modbus TCP Configuration
modbus:
  - name: ots_hub
    type: tcp
    host: 192.168.0.3   #Replace with your IP-Addr
    port: 502           # Usually Port 502, otherwise replace with your Port
    delay: 0
    message_wait_milliseconds: 30
    timeout: 5


# Ochsner Air Hawk 208 sensors
# Configuration of sensors according Data Point List
    sensors:
#**** Begin Write-Only Registers
      - name: OTS_001_target_operating_mode_heating_circuit_number
        slave: 1
        address: 1
        unique_id: ots_001_target_operating_mode_heating_circuit_number
        
      - name: OTS_002_target_heating_cooling
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 2
        unique_id: ots_002_target_heating_cooling
        
      - name: OTS_003_target_operation_mode_hot_water_number
        slave: 1
        address: 3
        unique_id: ots_003_target_operation_mode_hot_water_number
        
      - name: OTS_004_target_hot-water_temperature
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 4
        unique_id: ots_004_target_hot-water_temperature
        
      - name: OTS_005_switch-ON_hot-water_temperature_differential
        unit_of_measurement: K
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 5
        unique_id: ots_005_switch-ON_hot-water_temperature_differential
        
      - name: OTS_011_target_operating_mode_heating_circuit_number
        slave: 1
        address: 11
        unique_id: ots_011_target_operating_mode_heating_circuit_number
#**** End Write-Only Registers

#**** Begin Read-Back Registers (feedback for corresponding write register)
      - name: OTS_012_target_heating_cooling
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 12
        unique_id: ots_012_target_heating_cooling
        
      - name: OTS_013_target_operation_mode_hot_water_number
        slave: 1
        address: 13
        unique_id: ots_013_target_operation_mode_hot_water_number
        
      - name: OTS_014_target_hot-water_temperature
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 14
        unique_id: ots_014_target_hot-water_temperature4
        
      - name: OTS_015_switch-ON_hot-water_temperature_differential
        unit_of_measurement: K
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 15
        unique_id: ots_015_switch-ON_hot-water_temperature_differential
#**** End Read-Back Registers (feedback for corresponding write register)

#**** Begin Read-Only Registers
      - name: OTS_029_hot_water_temperature
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 1
        slave: 1
        address: 29
        unique_id: ots_029_hot_water_temperature
        
      - name: OTS_034_heatpump_flow_temperature
        unit_of_measurement: °C
        precision: 1
        scale: 0.1
        device_class: temperature
        slave: 1
        address: 34
        unique_id: ots_034_heatpump_flow_temperature
        
      - name: OTS_035_heatpump_return_temperature
        unit_of_measurement: °C 
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 35
        unique_id: ots_035_heatpump_return_temperature
        
      - name: OTS_036_flow_rate_heat_sink_system
        unit_of_measurement: 'm³/h'
        device_class: volume_flow_rate 
        precision: 2
        scale: 0.01
        slave: 1
        address: 36
        unique_id: ots_036_flow_rate_heat_sink_system
        
      - name: OTS_037_buffer_temperature_top
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 37
        unique_id: ots_037_buffer_temperature_top
        
      - name: OTS_038_buffer_temperature_bottom
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 38
        unique_id: ots_038_buffer_temperature_bottom
        
      - name: OTS_039_flow_temperature_auxiliary heater 
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 39
        unique_id: ots_039_flow_temperature_auxiliary
        
      - name: OTS_040_system_pressure_heat_sink_system
        unit_of_measurement: bar
        device_class: pressure
        precision: 2
        scale: 0.01
        slave: 1
        address: 40
        unique_id: ots_040_system_pressure_heat_sink_system

      - name: OTS_041_evaporator_intake_air_temperature
        unit_of_measurement:  °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 41
        unique_id: ots_041_evaporator_intake_air_temperature
        
      - name: OTS_042_evaporator_discharge_air_temperature
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 42
        unique_id: ots_042_evaporator_discharge_air_temperature
        
      - name: OTS_043_Reserved
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 43
        unique_id: ots_043_Reserved

      - name: OTS_044_Reserved
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 44
        unique_id: ots_044_Reserved
        
      - name: OTS_048_outdoor_temperature
        unit_of_measurement: °C
        device_class: temperature
        precision: 1
        scale: 0.1
        slave: 1
        address: 48
        unique_id: ots_048_outdoor_temperature
        
      - name: OTS_049_system_operating_status_number
        slave: 1
        address: 49
        unique_id: ots_049_system_operating_status_number

      - name: OTS_050_heatpump_operating_status_number
        slave: 1
        address: 50
        unique_id: ots_050_heatpump_operating_status_number
        
      - name: OTS_059_auxilary_heater_operating_status_heatpump_number
        slave: 1
        address: 59
        unique_id: ots_059_auxilary_heater_operating_status_heatpump_number
        
      - name: OTS_060_auxilary_heater_operating_status_tank
        slave: 1
        address: 60
        unique_id: ots_060_auxilary_heater_operating_status_tank
        
      - name: OTS_079_hours_of_operation_compressor
        data_type: uint32
        swap: word
        unit_of_measurement: h
        scale: 1    
        #device_class: duration - not set due to formating x:00:00
        slave: 1
        address: 79
        unique_id: ots_079_hours_of_operation_compressor
        
      - name: OTS_081_switching_cycles_compressor
        data_type: uint32
        swap: word
        slave: 1
        address: 81
        unique_id: ots_081_switching_cycles_compressor
        
      - name: OTS_083_hours_of_operations_auxiliary heater
        data_type: uint32
        swap: word
        #device_class: duration - not set due to formating x:00:00
        scale: 1
        device_class: duration
        slave: 1
        address: 83
        unique_id: ots_083_hours_of_operations_auxiliary
        
      - name: OTS_085_switching_cycles_auxiliary heater
        data_type: uint32
        swap: word
        slave: 1
        address: 85
        unique_id: OTS_085
        
      - name: OTS_089_heating_energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 89
        unique_id: ots_089_heating_energy
        
      - name: OTS_091_cooling_energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 91
        unique_id: ots_091_cooling_energy
        
      - name: OTS_093_hot_water_energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 93
        unique_id: ots_093_hot_water_energy
        
      - name: OTS_095_defrosting energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 95
        unique_id: ots_095_defrosting
        
      - name: OTS_097_power_demand_heating
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 97
        unique_id: ots_097_power_demand_heating
        
      - name: OTS_099_power_demand_cooling
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 99
        unique_id: ots_099_power_demand_cooling
        
      - name: OTS_101_power_demand_hot_water
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 101
        unique_id: ots_101_power_demand_hot_water
        
      - name: OTS_103_power_demand_defrosting
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 103
        unique_id: ots_103_power_demand_defrosting
        
      - name: OTS_119_auxiliary_heater_heating_energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 119
        unique_id: ots_119_auxiliary_heater_heating_energy
        
      - name: OTS_121_auxiliary_heater_hot_water_energy
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 121
        unique_id: ots_121_auxiliary_heater_hot_water_energy
        
      - name: OTS_123_auxiliary_heater_defrosting
        data_type: uint32
        swap: word
        unit_of_measurement: kWh
        device_class: energy
        slave: 1
        address: 123
        unique_id: ots_123_auxiliary_heater_defrosting
#**** End Read-Only Registers
        
#**** Begin Write/Read Registers
      - name: OTS_149_room_temperature_heating_circuit_1
        unit_of_measurement: °C
        device_class: temperature
        slave: 1
        address: 149
        unique_id: ots_149_room_temperature_heating_circuit_1


      - name: OTS_150_room_temperature_heating_circuit_2
        unit_of_measurement: °C
        device_class: temperature
        slave: 1
        address: 150
        unique_id: ots_150_room_temperature_heating_circuit_2
        
      - name: OTS_151_room_temperature_heating_circuit_3
        unit_of_measurement: °C
        device_class: temperature
        slave: 1
        address: 151
        unique_id: ots_151_room_temperature_heating_circuit_3

      - name: OTS_152_room_temperature_heating_circuit_4
        unit_of_measurement: °C
        device_class: temperature
        slave: 1
        address: 152
        unique_id: ots_152_room_temperature_heating_circuit_4

      - name: OTS_159_relative_humidity_heating_circuit_1
        unit_of_measurement: '%'
        device_class: humidity
        slave: 1
        address: 159
        unique_id: ots_159_relative_humidity_heating_circuit_1

      - name: OTS_160_relative_humidity_heating_circuit_2
        unit_of_measurement: '%'
        device_class: humidity
        slave: 1
        address: 160
        unique_id: ots_160_relative_humidity_heating_circuit_2

      - name: OTS_161_relative_humidity_heating_circuit_3
        unit_of_measurement: '%'
        device_class: humidity
        slave: 1
        address: 161
        unique_id: ots_161_relative_humidity_heating_circuit_3

      - name: OTS_162_relative_humidity_heating_circuit_4
        unit_of_measurement: '%'
        device_class: humidity
        slave: 1
        address: 162
        unique_id: ots_162_relative_humidity_heating_circuit_4
#**** End Write/Read Registers

# Configuration of sensors according Data Point List
# Additionally Sensor templates are defined for each "*operating_mode" and
# "operating_status" as well.
# They represent the value in human readable text instead of a number
# e.g.: for System operating status: "defrost" for number 4
sensor:
  - platform: template
    sensors:
      #Convert OTS_001_target_operating_mode_heating_circuit_number to text
      ots001targetoperatingmodeheatingcircuittext:
        friendly_name: "Target operating mode heating circuit (Write)"
        unique_id: ots001targetoperatingmodeheatingcircuittext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Standby',
              '1' : 'Heating',
              '2' : 'Standby' } %}
          {% set state =  states.sensor.OTS_001_target_operating_mode_heating_circuit_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
          
      #Convert OTS_003_target_operation_mode_hot_water_number to text
      ots003targetoperationmodehotwatertext:
        friendly_name: "Target operation mode hot water (Write)"
        unique_id: ots003targetoperationmodehotwatertext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Off',
              '1' : 'On' } %}
          {% set state =  states.sensor.OTS_003_target_operation_mode_hot_water_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
          
      #Convert OTS_013_target_operation_mode_hot_water_number to text
      ots013targetoperationmodehotwatertext:
        friendly_name: "Target operation mode hot water (Read back)"
        unique_id: ots013targetoperationmodehotwatertext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Off',
              '1' : 'On' } %}
          {% set state =  states.sensor.OTS_013_target_operation_mode_hot_water_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
          
      #Convert OTS_011_target_operating_mode_heating_circuit_number to text
      ots011targetoperatingmodeheatingcircuittext:
        friendly_name: "Target operating mode heating circuit (Read back)"
        unique_id: ots011targetoperatingmodeheatingcircuittext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Standby',
              '1' : 'Heating',
              '2' : 'Standby' } %}
          {% set state =  states.sensor.OTS_011_target_operating_mode_heating_circuit_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}

      #Convert OTS_049_system_operating_status_number to text
      ots049systemoperatingstatustext:
        friendly_name: "System operating status"
        unique_id: ots049systemoperatingstatustext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Off',
              '1' : 'Heating',
              '2' : 'Hot Water',
              '3' : 'Cooling',
              '4' : 'Defrost',
              '5' : 'Defrost' } %}
          {% set state =  states.sensor.OTS_049_system_operating_status_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
          
      #Convert OTS_050_heatpump_operating_status_number to text
      ots050heatpumpoperatingstatustext:
        friendly_name: "Heatpump operating status"
        unique_id: ots050heatpumpoperatingstatustext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Off',
              '1' : 'Heating',
              '2' : 'Cooling',
              '3' : 'Hot water',
              '4' : 'Defrost',
              '5' : 'PSU outage (EVU Sperre)',
              '6' : 'Manual heating',
              '7' : 'Manual cooling',
              '8' : 'Bivalent interlock',
              '9' : 'Operating mode changeover',
              '10' : 'Operating mode changeover',
              '11' : 'Pump pre-run time',
              '12' : 'Standby',
              '13' : 'Pump run-on time',
              '14' : 'Fault',
              '15' : 'Current limitation',
              '16' : 'Standby',
              '17' : 'Operating program switched off',
              '18' : 'Minimum time off',
              '19' : 'Minimum time on',
              '20' : 'Minimalum system pressure' } %}
          {% set state =  states.sensor.OTS_050_heatpump_operating_status_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
          
      #Convert OTS_059_auxilary_heater_operating_status_heatpump_number to text
      ots059auxilaryheateroperatingstatusheatpumptext:
        friendly_name: "Auxilary heater operating status (heatpump)"
        unique_id: ots059auxilaryheateroperatingstatusheatpumptext
        device_class: enum
        value_template: >-
          {% set mapper =  {
              '0' : 'Standby',
              '1' : 'Heating',
              '2' : 'Standby',
              '3' : 'Hot water',
              '4' : 'Bivalent interlock',
              '5' : 'Fault',
              '6' : 'Frost protection mode',
              '7' : 'Maximum temperatur shutdown',
              '8' : 'PSU outage (EVU-Sperre)',
              '9' : 'Hot water',
              '10' : 'Operating program switched off',
              '11' : 'Minimalum system pressure',
              '12' : 'Pump pre-run time',
              '13' : 'Pump run-on time' } %}
          {% set state =  states.sensor.OTS_059_auxilary_heater_operating_status_heatpump_number.state %}
          {{ mapper[state] if state in mapper else 'Unknown' }}

Hello Alfred,
Thanks for the OTS_Modbus.yaml. I have also a AirHawk 208 and try to user your Configuraton. But I am a absolut beginne. Can you please Show me the include Statement in the Conficuration.yaml, because I didn’t know the Syntax and all my test failed.
Best regards,
Harald

Hello Harald,

the easiest way would be to copy everthing and the end directly into the configuration.yaml file. The only thing to adapt is the “host:” to your tcp-address - you should see it in your router (and you should assign as a static address in order to make sure it always stays the same).

Furthermore I don’t remember on whether I had to contact Ochsner in order to make modbus accessible in your Ochsner setup. You might want to ask Ochsner Support or use a modbus Scanner on your PC to check availability of modbus.

Later on you might want to split the config file.

BTW: I now have setup a card showing the Power factor (JAZ, Jahresarbeitszahl).
It shows the performace of the heatpump (Relation of produced thermal energy and demand of electrical energy).
JAZ

Good Luck
Alfred

Hello Alfred,
thanks for the hints. I just send a eMail to [email protected] and after 2h the Modbus-Interface was activated. I just set your code productive and the first view is very positive. Thanks a lot.
But one question. Is it possible that you post the code for the dashboard? That would be great.
Best regards,
Harald

Hello Harald,

I am still experimenting as time and my knowledge allow. Thus don’r expect to much on the one hand and on the other hand I am interested in our feedback and ideas.
Also as stated before I think the provided modbus registers are missing a lot of information which might be of interest, This is e.g., all the settings one can do via the OTS App - at least to read, better also to write. Beeing able to read those values would allow to optimize the heating-curve based on data from the past such as outside temperature, room-termperature, …

Furthermore for my cards I am using also other devices/entities such as:

  • room and outside temperature form XIAOMI and netatmo sensors
  • shelly 4PM Pro for measuirng the real energy consumption
    -. template helpers to add values e.g. for overall thermal energy and electric energy
  • utitlity helpers e.g.for daily, weekly, monthly, yearly energy value

Those entities are used in some cards and you will have to delete or adapt.them.

I will provide some cards in seperate replies each with screenshot and yaml.
Good luck for your intergration and let me know your feedback and ideas.
BR
Alfred

A card with some details of interest

type: vertical-stack
title: Temperature (24 h)
cards:
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    points_per_hour: 24
    entities:
      - entity: sensor.temperature_humidity_wohnzimmer_temperature
        name: Living-room
      - entity: sensor.temperature_humidity_schlafzimmer_temperature
        name: Bedroom
      - entity: sensor.temperature_humidity_badezimmer_temperature
        name: Bathroom
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    line_color: blue
    points_per_hour: 24
    entities:
      - entity: sensor.temperature_humidity_outdoor_temperature
        name: Outside
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    line_color: blue
    points_per_hour: 24
    entities:
      - entity: sensor.ots_041_evaporator_intake_air_temperature
        name: Evaporator intake air temperature
      - entity: sensor.ots_042_evaporator_discharge_air_temperature
        name: Evaporator discharge air temperature
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
    hour24: true
    line_color: red
    points_per_hour: 24
    entities:
      - entity: sensor.ots_029_hot_water_temperature
        name: Hot water

two cards showing states over last 24 hours and actual values. Uses temperatures and energy sensor not provided by the OTS modbus.

card “Temperature (24h)”

type: vertical-stack
title: Temperature (24 h)
cards:
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    points_per_hour: 24
    entities:
      - entity: sensor.temperature_humidity_wohnzimmer_temperature
        name: Living-room
      - entity: sensor.temperature_humidity_schlafzimmer_temperature
        name: Bedroom
      - entity: sensor.temperature_humidity_badezimmer_temperature
        name: Bathroom
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    line_color: blue
    points_per_hour: 24
    entities:
      - entity: sensor.temperature_humidity_outdoor_temperature
        name: Outside
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
      average: true
    hour24: true
    line_color: blue
    points_per_hour: 24
    entities:
      - entity: sensor.ots_041_evaporator_intake_air_temperature
        name: Evaporator intake air temperature
      - entity: sensor.ots_042_evaporator_discharge_air_temperature
        name: Evaporator discharge air temperature
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
    hour24: true
    line_color: red
    points_per_hour: 24
    entities:
      - entity: sensor.ots_029_hot_water_temperature
        name: Hot water

card “Heatpump (24h)”

type: vertical-stack
title: Heatpump (24 h)
cards:
  - type: entity
    entity: sensor.ots049systemoperatingstatustext
    name: Heatpump operating status
  - type: entity
    entity: sensor.ots059auxilaryheateroperatingstatusheatpumptext
    name: Auxiliary heater operating status
  - type: history-graph
    title: Heatpump and auxiliary heater
    entities:
      - entity: sensor.ots049systemoperatingstatustext
      - entity: sensor.ots059auxilaryheateroperatingstatusheatpumptext
    hours_to_show: 24
  - type: custom:mini-graph-card
    show:
      fill: false
      extrema: true
    hour24: true
    points_per_hour: 24
    entities:
      - entity: sensor.ots_034_heatpump_flow_temperature
        name: Heat pump flow temperature
      - entity: sensor.ots_035_heatpump_return_temperature
        name: Heat pump return temperature
  - type: custom:mini-graph-card
    show:
      extrema: true
      average: true
    hour24: true
    line_color: red
    points_per_hour: 24
    entities:
      - entity: sensor.heatpump_total_active_power
        name: Heatpump power
  - show_name: true
    show_icon: false
    show_state: true
    type: glance
    entities:
      - entity: sensor.ots_079_hours_of_operation_compressor
        name: Total
      - entity: sensor.hours_of_operation_compressor_daily
        name: Today
    title: Compressor hours of operation
  - show_icon: false
    type: glance
    entities:
      - entity: sensor.ots_081_switching_cycles_compressor
        name: Total
      - entity: sensor.switching_cycles_compressor_daily
        name: Today
    title: Compressor switching cycles

All screenshots and yaml in this post have been updated.
Modbus yaml update has fixed the previous uint32 workaround. The version is fully compatible to the initial version.

Screenshots and yaml of cards have been updated to english

1 Like

Hello Alfred,

thank you very much for your efforts. I like it very much and it’s working great.
Unfortunately, my sensor data has no decimal place. For example your temperatures are accurate to tenths. How do you do that?

I am glad to hear, that it works fine for you.
As you mentioned, unfortunately some temperatures have no decimal. This is in particular room temperature and hot water as well. This actually makes no sense, but that’s the way it is.

Actually in my dashboard I use additional sensors as well. For the room temperature I am using a Xiaomi Mi 2 Thermometer (about 10 €), which is originally Bluetooth, but flashed to zigbee. Furthermore a use shelly for power/energy

  • Report actual Power (current W) not just Energy (kWh)
  • Differentiate the three phases covering different usage such as auxilary heater, …
  • covers complete demand of energy, not just what is reported by Ochsner modbus, which is slightly less than real.
  • Allows to split my overall energy consumption in heatpump and house (without heatpump).
    image

image

Furthermore I try to compute the performance factor. However it seems this is still unrealistic high.

Thank you very much for your quick reply. Very interesting how your dashboard is developing. I already have a Shelly ready to determine the real energy consumption of the heat pump. For the JAZ, however, I will prefer to use the values via modbus because they sound much more realistic.

In my case, all the values from the heat pump are of the integer type. You can see this well here at Outside (see also the zoom) and Evaporator Temperatures on the left side. You can also see it clearly on the right-hand side with the temperature values and the system pressure, which should actually have 2 decimal places.


In the meantime, I have already tried to define the Modbus sensors slightly differently. Precision to 1 for the one decimal place and the data type to float16. Unfortunately, none of this has helped.

    - name: ots_048_outdoor_temperature
      unit_of_measurement: °C
      precision: 1
      data_type: float16
      slave: 1
      address: 48
      unique_id: ots_048
      scan_interval: 1

On your screenshots and in the Ochsner app, however, you can see that there are more decimal places.
I’m also confused by the data refresh rate. The scan_interval setting doesn’t seem to matter either.
Do you have any idea what could be causing both of these?

I got it finally. :slight_smile:

    - name: ots_048_outdoor_temperature
      unit_of_measurement: °C
      scale: 0.1
      precision: 1
      slave: 1
      address: 48
      scan_interval: 150
      unique_id: ots_048

You have to define both scale and precision. The definition of data_type doesn’t work and gives only zero values.
Scan interval is also working now after a new start of the system.

Fine you found out. Actually I did find out already a month ago - it was a consequence of changes in modbus made in HA Release 2024.2. I fixed it throughout all relevant entities, but forgot to publish the updated version V0.91. I now have updated in my original post. Also I did not remember when you asked avout presison, only now when you mentioned scale.

Regarding scan intervall I never defined anything. Do you know what is the default ?

For the JAZ my statement was a bit bit measleading. Actually I also use the modbus values for computing JAZ for heating, cooling, hotwater separately. Additionally It turned out, that energy sum of electric energy reported from OTS is less than real consumption. Furthermore the temperature sensor was broken reporting wrong temperature and as a consequence complete weird JAZ. Now I “started all over” computing the JAZ from February 1st when the temperature sensor has been fixed.

I also tried to compute a “daily” Performance index and look into how Performance relates to outside temperature, … however since kWh without decimal are reported does not work well.


I am interested in any ideas you have on analyzing data.
Also I was looking on how to define all OZS modbus entities as a device, but was not successful so far. I found GitHub - EuleMitKeule/device-tools: Device Tools: Create, modify and merge your Home Assistant devices., but since has a warning “potential to permanently modify your configuration in a bad way” I did not use it.

I also bought a Xiaomi Mi 2 thermometer and flashed it to Zigbee. Now I also get the temperature and humidity for the desired room. Unfortunately, the transmission to the heat pump doesn’t work for me. I suspect that it has something to do with the data format. The temperature sensor outputs a float for the temperature and humidity with 2 decimal places. If I understand the Modbus file from Ochsner correctly, only an integer can be read in on OTS_149 and 159. Is that correct?
Could you please show how you did the automation?

Actually I also did expect to be able to set temperature and other entities of the headpump. However this interface provides almost only reading values. See my very first statement in this topic:

“Originally I was expecting to be able to have full functionality of the OTS-App via modbus. In reality only a very limited subset of read-only registers is provided. No possibility to set parameters like in the app are provided at all (there is very limited functionality to transfer info to the heatpump or control the heatpump via building management system).”

I would like to have all the functionality of the OTS app - reading and writing -available in HA either modbus or some other means.

Thus I have no automation, I just build dashboard combining read values from ots-sensore with values from other sensor and have some templates for measuring daily, monthly, total values and compute performance factor, …