Nilan heatpump cts 700

Have you, or anyone else managed to get this working with OpenHAB 3.x? I have added a Modbus TCP “thing”, but cannot figure out how to move on with my configuration?

Thanks in advance

UID: modbus:tcp:c8e7ef3a03
label: Nilan CTS700
thingTypeUID: modbus:tcp
configuration:
timeBetweenTransactionsMillis: 60
connectMaxTries: 1
reconnectAfterMillis: 0
port: 502
timeBetweenReconnectMillis: 0
host: 192.168.5.107
connectTimeoutMillis: 10000
id: 1
enableDiscovery: false

I realized that I had to do the configuration without the GUI and now OpenHAB is actually pulling data from the Nilan CTS700, thanks to the code from @spiff42 and @GuidoDirkes

The Nilan_T3_Extract temperature is not right though, it is reporting 225 degrees celcius, but I hope I will be able to solve this myself. :slight_smile:

Hi Jelle. Would you mind sharing your code for setting registers back to the CTS700? I would really like to be able to set “fan speed” from OpenHAB and when I see your sitemap screenshot it seems like you managed to make that work?

Thanks in advance

Here is how I have it configured (note: I am still on OH2, but I think it will work on OH3 as well):
things/nilan.things:

Bridge modbus:tcp:nilan [ host="10.0.0.107", port=502 ] {
    Bridge poller NilanTemperatures [ start=5152, length=12, refresh=10000, type="input" ] {
        Thing data Nilan_Temp_T1_Outdoor        [ readStart="5152", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T2_Supply         [ readStart="5153", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T3_Extract        [ readStart="5154", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T4_Discharge      [ readStart="5155", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T5_Condenser      [ readStart="5156", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T6_Evaporator     [ readStart="5157", readValueType="int16", readTransform="JS(divide10.js)" ]
        //Thing data Nilan_Temp_T7_AfterHeat      [ readStart="5158", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T11_HotWaterTop   [ readStart="5162", readValueType="int16", readTransform="JS(divide10.js)" ]
        Thing data Nilan_Temp_T12_HotWaterBot   [ readStart="5163", readValueType="int16", readTransform="JS(divide10.js)" ]
    }

    Bridge poller NilanDHWSetpoint [ start=5548, length=1, refresh=10000, type="input" ] {
        Thing data Nilan_Temp_DWH_Setpoint      [ readStart="5548", readValueType="int16", readTransform="JS(divide10.js)" ]
    }

    Bridge poller NilanRegulationMode [ start=5432, length=1, refresh=10000, type="input" ] {
        Thing data Nilan_Enum_RegulationMode    [ readStart="5432", readValueType="uint16" ]
    }

    Bridge poller NilanHumiditySensor [ start=4716, length=1, refresh=10000, type="input" ] {
        Thing data Nilan_Humidity_Sensor [ readStart="4716", readValueType="uint16" ]
    }

    Bridge poller NilanFilterMonitor [ start=1326, length=4, refresh=10000, type="input" ] {
        Thing data Nilan_Filter_InletInterval           [ readStart="1326", readValueType="uint16" ]
        Thing data Nilan_Filter_OutletInterval          [ readStart="1327", readValueType="uint16" ]
        Thing data Nilan_Filter_InletDaysLeft           [ readStart="1328", readValueType="uint16" ]
        Thing data Nilan_Filter_OutletDaysLeft          [ readStart="1329", readValueType="uint16" ]
    }

    Bridge poller Nilan_reg_4692 [ start=4692, length=2, refresh=10000, type="input" ] {
        Thing data NilanThing_Inlet_Filter              [ readStart="4692", readValueType="uint16" ]
        Thing data NilanThing_Outlet_Filter             [ readStart="4693", readValueType="uint16" ]
    }

    Bridge poller Nilan_DHW_Settings [ start=3938, length=1, refresh=10000, type="holding" ] {
        //Thing data Nilan_DHW_ElectricHeaterSetpoint     [ readStart="3935", readValueType="int16", readTransform="JS(divide10.js)", writeStart="3935", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data Nilan_DHW_ElectricHeaterEnable       [ readStart="3938", readValueType="int16", writeStart="3938", writeValueType="int16", writeType="holding" ]
    }

    Bridge poller Nilan_reg_2402 [ start=2402, length=6, refresh=20000, type="holding" ] {
        Thing data NilanThing_Operation_Mode                 [ readStart="2402", readValueType="int16", writeStart="2402", writeValueType="int16", writeType="holding" ]
        Thing data NilanThing_Inlet_Temperature_Max          [ readStart="2403", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2403", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_Temp_Min_Summer_Inlet          [ readStart="2404", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2404", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_Temp_Min_Winter_Inlet          [ readStart="2405", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2405", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_Temp_Summer_Winter_Threshold   [ readStart="2406", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2406", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_Temp_Summer_Winter_Offset      [ readStart="2407", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2407", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
    }

    Bridge poller Nilan_reg_2832 [ start=2832, length=5, refresh=10000, type="holding" ] {
        Thing data NilanThing_ExtOp1_AirTemp                    [ readStart="2832", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2832", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_ExtOp1_DWHTemp                    [ readStart="2833", readValueType="int16", readTransform="JS(divide10.js)", writeStart="2833", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data NilanThing_ExtOp1_Flags                      [ readStart="2834.0", readValueType="uint8" ]
        Thing data NilanThing_ExtOp1_ExhaustSpeed               [ readStart="2834.1", readValueType="uint8" ]
        Thing data NilanThing_ExtOp1_SupplySpeed                [ readStart="2835.0", readValueType="uint8" ]
        Thing data NilanThing_ExtOp1_Duration                   [ readStart="2836", readValueType="int16", writeStart="2833", writeValueType="int16", writeType="holding" ]
    }

    Bridge poller Nilan_reg_4746 [ start=4746, length=2, refresh=11000, type="holding" ] {
        Thing data Nilan_Temp_User_Setpoint             [ readStart="4746", readValueType="int16", readTransform="JS(divide10.js)", writeStart="4746", writeValueType="int16", writeType="holding", writeTransform="JS(multiply10.js)" ]
        Thing data Nilan_User_Fan_Speed                 [ readStart="4747", readValueType="int16", writeStart="4747", writeValueType="int16", writeType="holding" ]
    }

    Bridge poller Nilan_reg_4999 [ start=4699, length=3, refresh=10000, type="input" ] {
        Thing data NilanThing_Inlet_Fan_Speed                   [ readStart="4699", readValueType="uint16" ]
        Thing data NilanThing_Outlet_Fan_Speed                  [ readStart="4700", readValueType="uint16" ]
        Thing data NilanThing_Heater_Device                     [ readStart="4701", readValueType="uint16" ]
    }
}

transform/divide10.js:

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 10;
    return parseFloat(inputData) / DIVIDE_BY;
})(input)

transform/multiply10.js:

// Wrap everything in a function
(function(i) {
    return Math.round(parseFloat(i, 10) * 10);
})(input)
// input variable contains data passed by openhab

items/nilan.items:

Group gNilanLog

Number Nilan_T1_Outdoor	        "Udeluft [%.1f °C]"         (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T1_Outdoor:number" }
Number Nilan_T2_Supply          "Tilluft [%.1f °C]"         (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T2_Supply:number" }
Number Nilan_T3_Extract         "Fraluft [%.1f °C]"         (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T3_Extract:number" }
Number Nilan_T4_Discharge       "Afkastluft [%.1f °C]"      (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T4_Discharge:number" }
Number Nilan_T5_Condenser       "Kondensator [%.1f °C]"     (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T5_Condenser:number" }
Number Nilan_T6_Evaporator      "Fordamper [%.1f °C]"       (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T6_Evaporator:number" }

Number Nilan_T11_HotWaterTop    "Vandvarmer Top [%.1f °C]"  (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T11_HotWaterTop:number" }
Number Nilan_T12_HotWaterBot    "Vandvarmer Bund [%.1f °C]" (gNilanLog)     { channel="modbus:data:nilan:NilanTemperatures:Nilan_Temp_T12_HotWaterBot:number" }

Number Nilan_DHW_Setpoint       "Vandtemperatur setpunkt [%.0f °C]"   { channel="modbus:data:nilan:NilanDHWSetpoint:Nilan_Temp_DWH_Setpoint:number" }

Number Nilan_RegulationMode     "Regulation mode [%d]"      { channel="modbus:data:nilan:NilanRegulationMode:Nilan_Enum_RegulationMode:number" }

Number Nilan_InletFilter_ChangeInterval     "Filter interval ind [%d d]"                { channel="modbus:data:nilan:NilanFilterMonitor:Nilan_Filter_InletInterval:number" }
Number Nilan_OutletFilter_ChangeInterval    "Filter interval ud [%d d]"                 { channel="modbus:data:nilan:NilanFilterMonitor:Nilan_Filter_OutletInterval:number" }
Number Nilan_InletFilter_DaysLeft           "Filterkapacitet tilbage ind [%d d]"        { channel="modbus:data:nilan:NilanFilterMonitor:Nilan_Filter_InletDaysLeft:number" }
Number Nilan_OutletFilter_DaysLeft          "Filterkapacitet tilbage ud [%d d]"         { channel="modbus:data:nilan:NilanFilterMonitor:Nilan_Filter_OutletDaysLeft:number" }

Number Nilan_Inlet_Filter                   "Filterkapacitet ind [%d %%]"               { channel="modbus:data:nilan:Nilan_reg_4692:NilanThing_Inlet_Filter:number" }
Number Nilan_Outlet_Filter                  "Filterkapacitet ud [%d %%]"                { channel="modbus:data:nilan:Nilan_reg_4692:NilanThing_Outlet_Filter:number" }

Number Nilan_Operation_Mode                 "Driftstilstand [MAP(nilan_opmode.map):%s]" { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Operation_Mode:number" }
Number Nilan_Inlet_Temperature_Max          "Inlet temp max [%.1f °C]"                  { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Inlet_Temperature_Max:number" }
Number Nilan_Temp_Min_Summer_Inlet          "Summer inlet min [%.1f °C]"                { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Temp_Min_Summer_Inlet:number" }
Number Nilan_Temp_Min_Winter_Inlet          "Winter inlet min [%.1f °C]"                { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Temp_Min_Winter_Inlet:number" }
Number Nilan_Temp_Summer_Winter_Threshold   "Sommer/Vinter threshold [%.1f °C]"         { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Temp_Summer_Winter_Threshold:number" }
Number Nilan_Temp_Summer_Winter_Offset      "Sommer/Vinter offset [%.1f °C]"            { channel="modbus:data:nilan:Nilan_reg_2402:NilanThing_Temp_Summer_Winter_Offset:number" }

Number Nilan_ExtOp1_AirTemp                 "ExtOp1 lufttemp [%.1f °C]"                 { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_AirTemp:number" }
Number Nilan_ExtOp1_DWHTemp                 "ExtOp1 DWH temp [%.1f °C]"                 { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_DWHTemp:number" }
Number Nilan_ExtOp1_Flags                   "ExtOp1 flags    [%x]"                      { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_Flags:number" }
Number Nilan_ExtOp1_ExhaustSpeed            "ExtOp1 Exhaust speed [%d]"                 { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_ExhaustSpeed:number" }
Number Nilan_ExtOp1_SupplySpeed             "ExtOp1 Supply  speed [%d]"                 { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_SupplySpeed:number" }
Number Nilan_ExtOp1_Duration                "ExtOp1 Supply  speed [%d]"                 { channel="modbus:data:nilan:Nilan_reg_2832:NilanThing_ExtOp1_Duration:number" }

Number Nilan_Inlet_Fan_Speed                "Inlet fan speed [%d %%]"                   (gNilanLog)     { channel="modbus:data:nilan:Nilan_reg_4999:NilanThing_Inlet_Fan_Speed:number" }
Number Nilan_Outlet_Fan_Speed               "Outlet fan speed [%d %%]"                  (gNilanLog)     { channel="modbus:data:nilan:Nilan_reg_4999:NilanThing_Outlet_Fan_Speed:number" }
Number Nilan_Heater_Device                  "Heater device [%d %%]"                     { channel="modbus:data:nilan:Nilan_reg_4999:NilanThing_Heater_Device:number" }

Number Nilan_Humidity_Average               "Average humidity [RH %d%%]"                (gNilanLog)     { channel="modbus:data:nilan:NilanHumiditySensor:Nilan_Humidity_Sensor:number" }

Switch Nilan_DHW_Electric_Heater            "DHW Elsupplering"                          { channel="modbus:data:nilan:Nilan_DHW_Settings:Nilan_DHW_ElectricHeaterEnable:switch" }

Number Nilan_User_Temperature_Setpoint      "Temperature setpoint"                      { channel="modbus:data:nilan:Nilan_reg_4746:Nilan_Temp_User_Setpoint:number" }
Number Nilan_User_Fan_speed                 "Fan speed [%d %%]"                         { channel="modbus:data:nilan:Nilan_reg_4746:Nilan_User_Fan_Speed:number" }

And a snippet from the sitemap, although not fully implemented, but can read out temperatures, and change a few parameters, e.g. the fan speed:

            Frame label="Nilan" {
                Default item=Nilan_T1_Outdoor icon="temperature"
                Default item=Nilan_T2_Supply icon="temperature"
                Default item=Nilan_T3_Extract icon="temperature"
                Default item=Nilan_T4_Discharge icon="temperature"
                Default item=Nilan_T5_Condenser icon="temperature"
                Default item=Nilan_T6_Evaporator icon="temperature"
                Default item=Nilan_T11_HotWaterTop icon="temperature"
                Default item=Nilan_T12_HotWaterBot icon="temperature"
                Default item=Nilan_DHW_Setpoint icon="heating"
                Default item=Nilan_RegulationMode icon="text"

                Text    item=Nilan_InletFilter_ChangeInterval icon="settings"
                Text    item=Nilan_OutletFilter_ChangeInterval icon="settings"
                Text    item=Nilan_InletFilter_DaysLeft icon="shield"
                Text    item=Nilan_OutletFilter_DaysLeft icon="shield"
                Default item=Nilan_Humidity_Average icon="humidity"
                Default item=Nilan_DHW_Electric_Heater

                Setpoint item=Nilan_User_Temperature_Setpoint icon="heating" minValue=15 maxValue=28 step=1
                Switch  item=Nilan_User_Fan_speed icon="fan" mappings=[ 101="1", 102="2", 103="3", 104="4"]
            }

Hi Jelle,

Which registers did you use for populating the “geo” info of your sitemap? According to the documentation the registers should be located under “slave id 4”. How are you addressing that from OpenHAB?

Do you mind sharing that part of your configuration?

Thanks in advance,

Thank you for sharing the config! It’s very useful, I have one question: have you found which register shows of the electrical heater is turned on? I know the registers to enable it, set threshold, but I haven’t found how to know if the electrical heat is in use. There must be a flag indicating this because I see a red dot on the display when the electrical heater is on.

Today i was finally able to connect to the nilan cts700 via modbus

Hello Splif42,

you manage to open the admin register with your python scipt:

# Use the admin password "6699" for authentication.
if not modbus.write_multiple_registers(7777, [0x3636, 0x3939, 0, 0, 0, 0, 0, 0]):
  print("Error auth");
  exit(0)

I try to gain admin access with a line in my nilan.thing file but it is not successfull (my posting here).

Do you know, how to convert your python command to a “thing line”?

Your help would be great :slight_smile:

Thanks and greeting

Rai

1 Like

I have a Nilan Compact PC GEO, and started to experiment with Modbus TCP. I’m rather new in home automation in general, but managed to access the registers. I could not find any documentation of GEO registers, and noticed your post of accessing these, apparently on slave ID 4. Are there any documentation of the registers available? Thanks!

the geo module is another board with another modbus connector. so there its registered as a different slave, no 4.
You’ll notice you cant read the sensors through slave 1 because its the compact p board, not the geo board

ps. haven’t checked here for a while, since I’m using Home assistant for a few years now…

Thanks Jelle. I also moved to Home Assistant, experimenting with both now. But still have the same problem of lacking register numbers for GEO board (on slave no 4).

what are you missing?

Hi @Jelle_Victoor :
Do you happen to know the register for the following data (I tried everything I could find the user guide without luck).

  • Compressor status: on display it can one of the value “Off, Defrosting, Hot water production, Heat”. The closest thing I find is prmRegulationMode but it only changes between value 2 (HEATING_MODE) and 3 (VENTILATION_MODE).
  • Flag indicating if electrical heater is working. I found the flag to turn on/off electrical heater and set temperature when the heater should be turned on. However I couldn’t find any register that tells if the electrical heater is currently on.

Many thanks in advance