Multi sensor using same MQTT topic

I’m having trouble setting up two sensors which read the value from same MQTT topic.
Data must be interpreted based on a parameter, e.g type
The HW sensor/device provides temperature and humidity on the same topic, something like:

type=0x01 unit=0 valueF=24.75

If type is 1 => valueF is the temperature, if type is 0x05 => valueF is the humidity
In my configuration.yaml I tried the following, but with no success:

sensor:
  - platform: mqtt
    state_topic: "/response/node/7/class/sensor/status"
    name: "Temp"
    unit_of_measurement: '°C'
    value_template: "{% if value.split(' ')[0] == \"type=0x01\" %}{{ value.split(' ')[2].split('=')[1]  }}{% else %}{{ states('sensor.laststate') }}{% endif %}"
  
- platform: mqtt
    state_topic: "/response/node/7/class/sensor/status"
    name: "Humidity"
    value_template: "{% if value.split(' ')[0] == \"type=0x05\" %}{{ value.split(' ')[2].split('=')[1]}}{% endif %}"

Neither of the above is working correctly.
I tried with an else branch in order to keep the last value, because it was not working correctly without it, e.g. empty value in the UI

Pretty sure the escape character is wrong. Either use single quotes and remove the escape char, or use yaml line syntax so you can keep them both.

sensor:
  - platform: mqtt
    state_topic: "/response/node/7/class/sensor/status"
    name: "Temp"
    unit_of_measurement: '°C'
    value_template: >-
      {% if value.split(' ')[0] == "type=0x01" %}
        {{ value.split(' ')[2].split('=')[1]  }}
      {% else %}
        {{ states('sensor.laststate') }}
      {% endif %}

Here are two ways to accomplish what you want.

In the first approach, each sensor uses a template to extract the desired information. Both sensors are subscribed to the same topic so each sensor’s template must extract the data intended for it. If the received data is not intended for it (i.e. temperature sensor receives humidity data) then the template reports the sensor’s existing state.

- platform: mqtt
  name: Temp
  device_class: temperature
  state_topic: '/response/node/7/class/sensor/status'
  value_template: >-
    {% if '0x01' in value %}
      {{value.split('=')[3] }}
    {% else %}
      {{states('sensor.temp')}}
    {% endif %}

- platform: mqtt
  name: Humidity
  device_class: humidity
  state_topic: '/response/node/7/class/sensor/status'
  value_template: >-
    {% if '0x05' in value %}
      {{value.split('=')[3] }}
    {% else %}
      {{states('sensor.humidity')}}
    {% endif %}

The second approach demultiplexes the data found in the single topic. An automation is used to extract and forward temperature data to a dedicated temperature topic. It forwards humidity data to a separate, dedicated humidity topic. The two sensors simply subscribe to the appropriate topic.

- alias: 'data demultiplexer'
  trigger:
    platform: mqtt
    topic: '/response/node/7/class/sensor/status'
  action:
    service: mqtt.publish
    data_template:
      payload: "{{trigger.payload.split('=')[3] }}"
      topic: >
        {% if '0x01' in trigger.payload %}
          sensor/temp
        {% else if '0x05' in trigger.payload %}
          sensor/humidity
        {% else %}
          sensor/error
        {% endif %}
  - platform: mqtt
    name: Temp
    device_class: temperature
    state_topic: sensor/temp


  - platform: mqtt
    name: Humidity
    device_class: humidity
    state_topic: sensor/humidity

3 Likes

Thanks for the help, guys.
I updated my configuration using @123 's first approach. The Temperature sensor shows the temperature as expected when a new temperature value pops up.
But it seems that when it receives the value that it’s not meant for it(e.g humidity), instead of keeping the old value it resets it. The UI shows “-” instead of the value.

This is the history:
image

This is how the temperature sensor looks like, after receiving a new value for the humidity:
image

This is my current configuration:

  - platform: mqtt
    state_topic: "/response/node/7/class/sensor/status"
    name: "Temp"
    device_class: temperature
    unit_of_measurement: '°C'
    value_template: >-
      {% if value.split(' ')[0] == "type=0x01" %}
        {{ value.split(' ')[2].split('=')[1]  }}
      {% else %}
        {{ states('sensor.temp') }}
      {% endif %}

The second approach is also interesting, will also explore with it, but I would prefer the first one, as it doesn’t create additional artifacts/logic in the system.

I just tested the following using version 0.105.1. The only difference from what I originally posted is the inclusion of unit_of_measurement (to get a line graph) and a simplified MQTT topic.

  - platform: mqtt
    name: Temp
    device_class: temperature
    unit_of_measurement: '°C'
    state_topic: sensor/status
    value_template: >-
      {% if '0x01' in value %}
        {{value.split('=')[3] }}
      {% else %}
        {{states('sensor.temp')}}
      {% endif %}

I published data containing 0x01 and 0x05. Whenever the sensor received 0x05 it used its existing value (i.e. it worked as intended).

Screenshot from 2020-02-18 08-16-57

The gaps you do see in this graph are when I restarted Home Assistant. The data I published to the MQTT topic was not published as a retained value (i.e. it was not stored by the MQTT Broker). When Home Assistant restarts, it re-subscribes to the MQTT topic and initially receives no data (because none was retained by the MQTT Broker). It represents this initial value as unknown which will appears as a gap in the graph. If I choose to publish the data as a retained value, it will be read by Home Assistant on restart.

Your situation is puzzling. Initially the temperature sensor’s value will be unknown until it receives its first temperature value. Afterwards, any humidity data it receives will be ignored and substituted with the temperature sensor’s existing state-value using {{ states('sensor.temp') }}. The only reason it would fail (report a value of unknown) is if sensor.temp doesn’t exist. Yet, that shouldn’t be possible because the configuration has clearly assigned it the name “Temp” (which becomes sensor.temp).

1 Like

Thank you for this remark, this pointed me in the right direction…
PEBCAK: the example I gave here is slightly different that the actual configuration, as in the name was “Temperatura”, and for the sake of translation I used in the above example only “Temp” and I didn’t see the connection between the name Temp and sensor.temp

So now it works, thank you for your time !

1 Like

Glad to hear you found the source of the problem (misnamed sensor entity).

Regarding the second approach, it is more efficient when a single MQTT topic is used by many sensors. Imagine you have 20 sensors, all using the same topic:

  • In the first approach, the incoming payload is processed 20 times, once by each of the 20 sensors.
  • In the second approach, the incoming payload is processed twice, first by the automation and then by just one of the 20 sensors.

The second approach also centralizes all processing/reformatting of the incoming data (as opposed to the first approach where each sensors has its own separate template).

I described the two approaches in the following topic. Although it refers to the Sonoff RF Bridge, it applies to any source that uses one MQTT topic to transmit data from multiple devices (and/or parameters).

3 Likes