MQTT - topic - help

Sorry to dredge an old topic, I am trying to use the demuxing logic, but this time for Z2T (tasmota zigbee). The sensor sends 2 messages. the json I am trying to parse into a topic from the sensor looks like this:

MQT: tele/zigbee/SENSOR = {"ZigbeeReceived":{"0xB9D8":{"Occupancy":1,"LinkQuality":101}}}
MQT: tele/zigbee/SENSOR = {"ZigbeeReceived":{"0xB9D8":{"Illuminance":2,"LinkQuality":101}}}

The unique ID of the zigbee sensor is: “0xB9D8”. How can I format my data template to create a mqtt topic like home/zigbee/0xB9D8. I want to create a sensor that checks for Occupancy = 1.

Many thanks
Trux

This automation monitors the topic tele/zigbee/SENSOR. If the received payload is regarding device 0xB9D8 and contains Occupancy data, it proceeds to publish that data to home/zigbee/0xB9D8.

- alias: 'example 1'
  trigger:
    platform: mqtt
    topic: tele/zigbee/SENSOR
  condition:
    condition: template
    value_template: >
      {{ trigger.payload_json.ZigbeeReceived['0xB9D8'] is defined 
        and trigger.payload_json.ZigbeeReceived['0xB9D8'].Occupancy is defined }}
  action:
    service: mqtt.publish
    data_template:
      topic: home/zigbee/0xB9D8
      payload: "{{trigger.payload_json.ZigbeeReceived['0xB9D8'].Occupancy}}"
1 Like

Thanks. I would never have figured this out.

Really appreciate your help.

Trux

Now I am stuck again! I have added a new sensor to the zigbee receiver, it is exactly the same as the original sensor but has a different “code”. I have 5 of these, adding them slowley to ensure stability. So this second sensor produces exactly the same outputs when it is trigger except it has the code ‘0x333D’.

How can I change my yaml to also demux this sensor?

Many thanks again!

John

The easiest way is to create a new automation by replacing all 0xB9D8 with 0x333D in ‘example 1’ and to create automation/sensor that monitors home/zigbee/0x333D.
However, in a long run it’s more beneficial to stick to one demux automation that handles multiple codes.

I cannot properly test the following code, but here it is:

- alias: 'example 1'
  trigger:
    platform: mqtt
    topic: tele/zigbee/SENSOR
  condition:
    condition: template
    value_template: >
    {% set known_codes=['0xB9D8', '0x333D'] %}
    {% for code in known_codes %}
      {% if trigger.payload_json.ZigbeeReceived[code] is defined
          and trigger.payload_json.ZigbeeReceived[code].Occupancy is defined %}
        {{ True }}
      {% endif %}
    {% endfor %}
  action:
    service: mqtt.publish
    data_template:
      topic: home/zigbee/0xB9D8
      payload: >
        {%- set known_codes=['0xB9D8', '0x333D'] -%}
        {%- for code in known_codes -%}
          {%- if trigger.payload_json.ZigbeeReceived[code] is defined -%}
            {{ trigger.payload_json.ZigbeeReceived[code].Occupancy }}
          {%- endif -%}
        {%- endfor -%}

That’s not the most efficient example but it does the trick.

The payload’s structure made this a bit more challenging but I believe the following automation will do the trick. I tested it and, at least as far as my results show, it will work per your requirements. This automation will work with all 5 of your sensors (and more).

- alias: 'example 1'
  trigger:
    platform: mqtt
    topic: tele/zigbee/SENSOR
  condition:
    condition: template
    value_template: >
      {{ ((trigger.payload_json.ZigbeeReceived.values() | list)[0].keys() | list)[0] == 'Occupancy' }}
  action:
    service: mqtt.publish
    data_template:
      topic: >
        home/zigbee/{{ (trigger.payload_json.ZigbeeReceived.keys() | list)[0] }}
      payload: >
        {% set code = (trigger.payload_json.ZigbeeReceived.keys() | list)[0] %}
        {{ trigger.payload_json.ZigbeeReceived[code].Occupancy }}
  • The condition confirms the payload contains an Occupancy key. If it doesn’t (i.e. it contains something else like Illuminance) then the action is not executed.

  • For topic, the template extracts the sensor’s code from the payload.

  • For payload, the template extracts the sensor’s code from the payload then uses that to get Occupancy’s value.

Thank you so much for this. High level “Fu”.

John

Many thanks for that. NodeRed was my option B so I will forward the granula information to diferent MQTT topics. Thougth to ask for good ideas.

Fantastic, this is demultiplexer just works great with my NRF24L01 network!

@123 Thank you for your demultiplexer insight. @VDRainer approach is the one that I was using so far. Now, I am testing yours, and need advice on how to create a condition in the automation.

Using the demultiplexer approach…

- id: '1234567890123'
  alias: OpenMQTTGateway demultiplexer
  description: ''
  trigger:
  - platform: mqtt
    topic: home/OpenMQTTGateway/PilighttoMQTT
  action:
  - data_template:
      payload: '{{trigger.payload}}'
      topic: '{{ ''home/sensor'' + trigger.payload_json.message.channel|string }}'
    service: mqtt.publish

new topics are created as eg.

home/sensor3 {"message":{"id":145,"temperature":26.10,"humidity":10.00,"battery":1,"channel":3},"protocol":"tfa","length":"145","repeats":2,"status":2}                 
home/sensor {"message":{"id":153.0,"temperature":52.8,"humidity":40.0,"battery":0.0},"protocol":"teknihall","length":"153","repeats":2,"status":2}                      
home/sensor2 {"message":{"id":174,"temperature":25.70,"humidity":74.00,"battery":1,"channel":2},"protocol":"tfa","length":"174","repeats":2,"status":2}                 
home/sensor {"message":{"id":154.0,"temperature":27.2,"humidity":10.0,"battery":1.0},"protocol":"teknihall","length":"154","repeats":2,"status":2}                      
home/sensor1 {"message":{"id":88,"temperature":27.60,"humidity":75.00,"battery":1,"channel":1},"protocol":"tfa","length":"88","repeats":2,"status":2}                   
home/sensor {"message":{"id":149.0,"temperature":1.7,"humidity":34.0,"battery":1.0},"protocol":"teknihall","length":"149","repeats":2,"status":2}

This way there is no need to update the automation.yaml script everytime id value changes. Topics home/sensor1 home/sensor2 home/sensor3 are the sensors I am interesed in. However, messages that do not have a channel value result in the creation of an unneeded topic home/sensor

I am interested only in “protocol”:“tfa” readings (my devices are listed under that protocol and all have a channel value) but a condition such as:

  condition:
  - condition: template
    value_template: "{{ value_json.protocol == 'tfa' }}"

results in no messages posted for the different demultiplexed sensors under their respective topics home/sensor1 home/sensor2 home/sensor3

Suggestions are welcome and appreciated in advance.

You can do it like this:

  condition:
    condition: template
    value_template: "{{ trigger.payload_json.protocol == 'tfa' }}"

or even like this because only payloads that use protocol tfa have channel:

  condition:
    condition: template
    value_template: "{{ trigger.payload_json.message.channel is defined }}"

You can also streamline the topic template:

- id: '1234567890123'
  alias: OpenMQTTGateway demultiplexer
  description: ''
  trigger:
    platform: mqtt
    topic: home/OpenMQTTGateway/PilighttoMQTT
  condition:
    condition: template
    value_template: "{{ trigger.payload_json.message.channel is defined }}"
  action:
    service: mqtt.publish
    data_template:
      payload: '{{trigger.payload}}'
      topic: 'home/sensor{{ trigger.payload_json.message.channel }}'

I tested the automation using your sample data and it published to the following topics (it publishes nothing if the payload doesn’t contain channel):

@123 Thank you much for your accurate and detailed reply. :+1: :+1: :+1: Now it’s working as expected :smiley: I have tested both conditions and decided to implement the second one (hadn’t thought about that possibility). Thank you for your code about streamlining the the topic template in the automation. I’ve made good use of it too.

the way I did it was simply adding [/id] or [/channel] into your MQTT rtl_433 command

rtl_433 -F "mqtt://myrouter.local:1883,retain=0,events=rtl_433[/model][/id][/channel]

then you will get individual copics for each ID and Channel, creating sensor for each is simple as adding the id or channel to the end of the sensor setting e.g.

  - platform: mqtt
    state_topic: 'rtl_433/model/id/channel'
    name: 'Outside Temperature °C Oregon'
    unit_of_measurement: '°C'
    value_template: '{{ value_json.temperature_C }}'

recommend using MQTT Explorer to see how the JSON flows on your network and confirm you are getting expected information out of rtl_433

1 Like

Did that option exist 6 months ago?

it seems it has been there for a while ( more than a year ) but that would be question for rtl_433 dev team.

I just did the adjustment today because my “neighbor” added another sensor for indoor and my sensor in HA would jump from -5C to +18C ( :smile: )

This topic started nearly two years ago (Feb '19). Glad to hear they added an option that makes it easier to identify which device’s data is in the payload.

I would like to use Taras solution but the data coming from my bridge has additional data which I think is mucking up the trigger.

My data is
tele/zigbee/SENSOR = {"ZbReceived":{"0x838C":{"Device":"0x838C","0500<00":"010000010000","ZoneStatusChange":1,"ZoneStatusChangeZone":1,"Occupancy":1,"Endpoint":1,"LinkQuality":154}}}

The trigger I am using from Trais post is
{{ ((trigger.payload_json.ZbReceived.values() | list)[0].keys() | list)[0] == 'Occupancy' }}

Any help would be appreciated! J

Any one have an idea of how I need to form my trigger? TX, J