Thermia Genesis

Thermia Genesis is the platform used by several heat-pump models produced by Thermia. I have a Thermia Calibra Cool 7 on which I have tested all of this.

Thermia Heatpump

Official website:

Used versions of the specification can be found here.

Official Modbus mappings:

  • I have 3 versions of the Thermia Genesis modbus schema definitions.

    • Platform versions 10, 12 and 13
  • There were some fields added and removed between those versions.

    • I have chosen to include all of them.
  • There are many fields that only work

    • on specific heat pump models
    • if specific modules have been installed (you’ll see for example (EM) or (EM3 only) in the description of a Field).
    • if specific functionality is used (like swimming pool)
  • Status: All registers in the documentation have been put into the schema definition.

  • Schema as Yaml: ThermiaGenesis101213.yaml

Warning

The Coils and Discrete Inputs (i.e. binary values) are not yet available because I have not yet implemented these at all in this Toolkit

The schema is also available as pre generated Kotlin code.

<dependency>
  <groupId>nl.basjes.modbus.devices</groupId>
  <artifactId>modbus-device-thermia-genesis</artifactId>
  <version>0.3.0</version>
</dependency>

With that the code to use the values can be as simple as this Kotlin Script:

GetThermia.main.kts
#!/usr/bin/env kotlin

@file:DependsOn("nl.basjes.modbus:modbus-api-plc4j:0.6.0")
@file:DependsOn("nl.basjes.modbus:modbus-schema-device:0.6.0")
@file:DependsOn("nl.basjes.modbus.devices:modbus-device-thermia-genesis:0.3.0")

import nl.basjes.modbus.device.api.MODBUS_STANDARD_TCP_PORT
import nl.basjes.modbus.device.plc4j.ModbusDevicePlc4j
import nl.basjes.modbus.thermia.ThermiaGenesis

val hostname = "thermia.iot.basjes.nl"
val port = MODBUS_STANDARD_TCP_PORT
val unitId = 1

val connectionString =
    "modbus-tcp:tcp://$hostname:$port?unit-identifier=$unitId"

print("Connecting...")
ModbusDevicePlc4j(connectionString).use { modbusDevice ->
    println(" done")

    val thermia = ThermiaGenesis()
    thermia.connect(modbusDevice)

    val outdoorTemp     = thermia.inputRegisters.outdoorTemperature
    val roomTemp        = thermia.inputRegisters.roomTemperature
    val roomTempSetting = thermia.holdingRegisters.comfortWheelSetting
    val tapWaterTemp    = thermia.inputRegisters.tapWaterWeightedTemperature

    outdoorTemp     .need()
    roomTemp        .need()
    tapWaterTemp    .need()
    roomTempSetting .need()

    thermia.update(1000)

    println("Outdoor Temperature            : ${outdoorTemp    .value} ${outdoorTemp    .unit} ")
    println("Room Temperature               : ${roomTemp       .value} ${roomTemp       .unit} ")
    println("Comfort Wheel Setting          : ${roomTempSetting.value} ${roomTempSetting.unit} ")
    println("Tap Water Weighted Temperature : ${tapWaterTemp   .value} ${tapWaterTemp   .unit} ")
}

This script produced this output:

Outdoor Temperature            : 22.83 °C
Room Temperature               : 22.5 °C
Tap Water Weighted Temperature : 53.2 °C
Comfort Wheel Setting          : 20.5 °C

Repo location of this Schema: https://github.com/nielsbasjes/modbus-devices/tree/main/modbus-device-thermia-genesis