Help me with HVAC MQTT Climate component:/

Hi. We have an ventilation system in our house under the Danish Brand name Nilan.

A danish guy have made som code for an esp8266 , which can be connected to the system. Then it can be controlled over MQTT.

I would very much like to have the modes - Off, Heat, Cool and Auto set up and maybe also a possibility for adjusting the temperature.

I have looked at the HVAC climate MQTT component, but I am getting frustrated with the setup ( templating and so on:/)

Can someone help me getting a functional setup (configuration?)

The code with the state topics, command topics and so on is on this link:

/ Jacob

1 Like

I’ve looked at the openHAB example for creating Items:

Openhab items:

Switch nilanrun {mqtt=">[my:ventilation/RunSet:command:ON:1],>[my:ventilation/RunSet:command:OFF:0]"}
Number nilanrunstate {mqtt="<[my:ventilation/control/RunSet:state:REGEX(([0-9-]+))]"}
Number nilanmode {mqtt=">[my:ventilation/ModeSet:state::default]"}
Number nilanmodestate {mqtt="<[my:ventilation/control/ModeSet:state:REGEX(([0-9-]+))]"}
Number nilanvent {mqtt=">[my:ventilation/VentSet:state::default]"}
Number nilanventstate {mqtt="<[my:ventilation/control/VentSet:state:REGEX(([0-9-]+))]"}
Number nilantemp {mqtt=">[my:ventilation/TempSet:state::REGEX(([0-9-]+))]"}
Number nilantempstate {mqtt="<[my:ventilation/control/TempSet:state:REGEX(([0-9-]+))]"}
Number nilaninlet "Ventilation indgang temp [%s]" {mqtt="<[my:temp/T7_Inlet:state:REGEX(.?([0-9.]+).]"}
Number nilanoutside "Ventilation ude temp [%s]" {mqtt="<[my:temp/T8_Outdoor:state:REGEX(.?([0-9.]+).*]"}

Many of the Items use REGEX to extract the numeric portion of the topic’s message. That means the topic’s message might not be just a numeric value but also includes other characters. In order to help you, I would need to see examples of these messages.

I suggest you use MQTT Explorer, or some other MQTT client, to subscribe to all the thermostat’s topics and examine their messages.

I don’t mean to discourage you but I see some things that the existing MQTT HVAC platform can’t handle (like send a numeric command to specify an operating mode like the nilan thermostat does for RunSet). There are ways around these limitations.

Thanks forbruge response :slight_smile: i Will try to make some screenshots of the messages in MQTT explorer :slight_smile: hmmm regarding the numbers (payloads) they are as stated in the bottom of the readme on github - below the openhab sitemap . If I publish those values to the topics then the system reacts like it should :slight_smile:

If you are certain that the values shown at the bottom of the readme are precisely what’s in the messages then the author did not need to use REGEX in the Items. If the message contains nothing more than a numeric string, you don’t need REGEX to parse it. So I don’t understand why the author included it in the example.

Here’s another thing I don’t understand in the example. In openHAB’s MQTT binding, this > means to publish (transmit) and this < means to subscribe (receive). So the following means subscribe to the topic my:ventilation/control/VentSet

{mqtt="<[my:ventilation/control/VentSet:state:REGEX(([0-9-]+))]"}

However, the topic contains the word control which implies it is used to control the thermostat (i.e. transmit commands to the thermostat). Synonyms for control are command and set which are often used to identify topics that publish (transmit) a command to the thermostat. Yet here the author is using this topic to subscribe (receive). That doesn’t seem right to me.

Based on the symbols > and < here are the state topics (subscribe/receive) and the command topics (publish/transmit). Like I said, the topics containing the word control are used to receive state information which seems odd to me.

State topics
my:ventilation/control/RunSet
my:ventilation/control/ModeSet
my:ventilation/control/VentSet
my:ventilation/control/TempSet
my:temp/T7_Inlet
my:temp/T8_Outdoor

Command topics
my:ventilation/RunSet
my:ventilation/ModeSet
my:ventilation/VentSet
my:ventilation/TempSet

I suggest you use an MQTT client to confirm which topics are used to receive messages (state topics) and which ones are used to transmit messages (command topics). After you have clarified their purpose, we can proceed to use them with MQTT HVAC.

I should point out that these openHAB mappings mean we will definitely have to use templates to convert the received operating mode and temperature values:

Selection item=nilanmode label="Funktion" mappings=[0= "Off", "1"="Heat", "2" = "Cool", 3 = "Auto", 4 = "Service"]
Selection item=nilantemp label="Temperatur" mappings=[1900="19", 2200="22", 2500="25"]

The operating mode called “Service” does not exist in MQTT HVAC. This mode will have to be mapped to one of the defined modes.

Hi again :slight_smile: you are right - the command and state topics look like they should have been the opposite of each other . But the command topics you have specified is the command topics and the other ones are state topics . It is kinda weird how it is maked .

Can yo help me what I should write in the config then ?

The thing I need is the modes - but not the service - never mind about that .

It would then be nice to control the heat but I can see the mappings are a little strange :confused:

Then the fan speed would also be nice to control

I’m glad for your help - it seems you have great knowledge :slight_smile:

Here is a first attempt to configure MQTT HVAC for your thermostat. I can guarantee that it will fail to control the thermostat (I’ll explain why later). I probably got a few things wrong so your first goal is to simply make it display your thermostat’s operating mode, current temperature, and target temperature.

climate:
 - platform: mqtt
   name: "Thermostat"
   optimistic: false
   retain: false
   qos: 0
   payload_on: 1
   payload_off: 0
   modes:
     - auto
     - heat
     - cool
     - 'off'
   mode_state_topic: "my:ventilation/control/ModeSet" 
   mode_state_template: >-
     {% set modes = { '0':'off', '1':'heat',  '2':'cool', '3':'auto'} %}
     {{ modes[value] if value in modes.keys() else 'off' }}
   mode_command_topic: "my:ventilation/ModeSet"
   current_temperature_topic: "my:temp/T7_Inlet"
   current_temperature_template: >-
   {{ value | float | multiply(0.01) | round(1) }}
   min_temp: 16
   max_temp: 28
   temp_step: 0.5
   temperature_state_topic: "my:ventilation/control/TempSet"
   temperature_state_template: >-
   {{ value | float | multiply(0.01) | round(1) }}
   temperature_command_topic: "my:ventilation/TempSet"

Now why it will fail to control your thermostat:

  • You’ll notice that mode_state_topic has an associated mode_state_template to convert the thermostat’s numeric operating modes (0, 1, 2, 3) into Home Assistant’s text operating modes (off, heat, cool, auto). However, mode_command_topic does not have an associated template (because MQTT HVAC does not support it). That means you can’t convert from off/heat/cool/auto to 0/1/2/3. Without the ability to perform this conversion, Home Assistant will send “heat” to your thermostat instead of “1” (and that will obviously fail to control the thermostat).

  • temperature_state_topic has an associated temperature_state_template to convert the received numeric text (“2200”) into a numeric value (22.0). The template converts the text string to a floating point number then multiplies it by 0.01 and finally rounds it to 1 decimal place. However, temperature_command_topic does not have an associated template (MQTT HVAC does not support it). Therefore Home Assistant cannot convert from 22.0 to “2200”. It will send “22.0” to your thermostat instead of “2200” (and, again, it will fail to control your thermostat).

There are ways to circumvent these two limitations and make it control your thermostat. However, before we explore those options, your first step is to confirm the configuration I have provided you can receive and display the thermostat’s operating mode, current temperature, and target temperature.

I again:) Im so much appreciated for your help and all your writing. I have now tried to put in the climate yam code you provided. It failed to validate the code at first (I had to move the 2 last line with the Curley brackets one step in) Then I deleted the “my:” in front of the MQTT topics. I don’t know why they are there - think it has something to do with openhab.

Well I got I in the UI, but nothing actually works. I can’t control anything. I cannot so well write why it doesn’t work, but it looks like if I change the states and look at the MQTT payloads, it just sends the payload (setting) it is already on.

Would it be better to go away from the climate option?

I tried to make a “Fan” control over MQTT. This I actually got to work. I used this to make it:

fan:
  - platform: mqtt
    name: "Nilan"
    state_topic: "ventilation/control/RunSet"
    command_topic: "ventilation/runset"
    speed_state_topic: "ventilation/control/VentSet"
    speed_command_topic: "ventilation/ventset"
    qos: 0
    payload_on: "1"
    payload_off: "0"
    payload_low_speed: "1"
    payload_medium_speed: "3"
    payload_high_speed: "4"
    speeds:
      - low
      - medium
      - high

This is my Climate code (changed a bit apart from yours.)

climate:
 - platform: mqtt
   name: "Nilan Genvex"
   optimistic: false
   retain: false
   qos: 0
   payload_on: 1
   payload_off: 0
   modes:
     - auto
     - heat
     - cool
     - 'off'
   mode_state_topic: "ventilation/control/ModeSet" 
   mode_state_template: >-
     {% set modes = { '0':'off', '1':'heat',  '2':'cool', '3':'auto'} %}
     {{ modes[value] if value in modes.keys() else 'off' }}
   mode_command_topic: "ventilation/modeset"
   current_temperature_topic: "temp/T7_Inlet"
   current_temperature_template: >-
    {{ value | float | multiply(0.01) | round(1) }}
   min_temp: 16
   max_temp: 28
   temp_step: 0.5
   temperature_state_topic: "ventilation/control/TempSet"
   temperature_state_template: >-
    {{ value | float | multiply(0.01) | round(1) }}
   temperature_command_topic: "ventilation/tempset"

OpenHAB doesn’t need that either.

You can appreciate how difficult it is to assist you when the available information is incorrect … and I don’t even have the device to test it and offer you the best guidance.

I explained in great deal that it would not control the thermostat and why it would not control it. I also explained that this was just the first step, to establish communications with the device and to display the received data from the device. The second step will be to use automations to control the thermostat and get around the limitations I had described.

You appear to have already given up on the second step and moved on to exploring another strategy. Good luck, I hope it works for you.

Should you wish to continue with my suggestion, here is the second step.

1 - Modify climate configuration
You must make two minor modifications to the configuration of the climate component.

  • mode_command_topic: "convert/modeset"
  • temperature_command_topic: "convert/tempset"
climate:
 - platform: mqtt
   name: "Nilan Genvex"
   optimistic: false
   retain: false
   qos: 0
   payload_on: 1
   payload_off: 0
   modes:
     - auto
     - heat
     - cool
     - 'off'
   mode_state_topic: "ventilation/control/ModeSet" 
   mode_state_template: >-
     {% set modes = { '0':'off', '1':'heat',  '2':'cool', '3':'auto'} %}
     {{ modes[value] if value in modes.keys() else 'off' }}
   mode_command_topic: "convert/modeset"
   current_temperature_topic: "temp/T7_Inlet"
   current_temperature_template: >-
    {{ value | float | multiply(0.01) | round(1) }}
   min_temp: 16
   max_temp: 28
   temp_step: 0.5
   temperature_state_topic: "ventilation/control/TempSet"
   temperature_state_template: >-
    {{ value | float | multiply(0.01) | round(1) }}
   temperature_command_topic: "convert/tempset"

2 - Add two automations
You must add two automations. They convert mode and temperature from Home Assistant format to Nilan format.

- alias: 'Convert HVAC Mode'
  hide_entity: true
  trigger:
    platform: mqtt
    topic: convert/modeset
  action:
    service: mqtt.publish
    data_template:
      topic: "ventilation/modeset"
      payload: >-
        {% set mode_name = trigger.payload %}
        {% set modes = { 'off':'0', 'heat':'1', 'cool':'2', 'auto':'3' } %}
        {{ modes[mode_name] if mode_name in modes.keys() else '0' }}

- alias: 'Convert HVAC Temperature'
  hide_entity: true
  trigger:
    platform: mqtt
    topic: convert/tempset
  action:
    service: mqtt.publish
    data_template:
      topic: "ventilation/tempset"
      payload: "{{ trigger.payload | float | multiply(100) | round }}"

Be advised I have not tested this so it may require further adjustments.

Wow - you are an absolute genius:D It actually works quite well now! Im impressed how you did this without actually have the hardware in your hands:)

I made a correction to the template for the temperature (i deleted the template) - because it messed up the inlet temp for the climate component. It was showing 0.2 as value, which afterwards showed up like it should be.

I have trying to set up the fan speed option under the yaml code, but this also frustrates me, as i cant get this to work. Do you have any clue on this?

The off switch in the climate component does not do anything - should it power the HVAC off - or do i have to point out some topics in the code for this purpose?