Parsing an MQTT message

Until today I have been monitoring an oil tank’s quantity using a RaspberryPi, which sends an MQTT message to my broker, ie .

rtl_433 = {“time" : "2022-01-01 11:06:25”, "model" : “Oil-SonicSmart", "id" : 138603545, "flags" : 128, “maybetemp" : 21, "temperature C” : 13.333, “binding_countdown” : 0, “depth_cm” : 32}

HA then fetches the data & I have the following in my config.yaml & I then display the data in a Lovelace card. Works well.

sensor:
  - platform: mqtt
    name: "Oil Percent"
    state_topic: "home/rtl_433"
    value_template: "{{ ((173 - (value_json.depth_cm)) * 21.34 / 3500 * 100) | int }}"
    unit_of_measurement: '%'

I now want to also monitor another oil tank. It also sends a MQTT message to the same broker, with a very similar message - the key difference being the tank "id" is different on the second oil tank (136628653).

Question: How can I get HA to distinguish which feed is which - very ideally without changing the MQTT topic name as to do so would make it much harder to programme the RPi than I am comfortable with just now.

Perhaps it is some form of IF or CHOOSE or similar, but I am not sure where to start?

TIA

  - platform: mqtt
    name: "Oil Percent"
    state_topic: "home/rtl_433"
    value_template: >
      {% if value_json is defined and value_json.message.id == 138603545 %}
        {{ ((173 - (value_json.depth_cm)) * 21.34 / 3500 * 100) | int }}
      {% else %}
        {{ states('sensor.oil_percent') }}
      {% endif %}
    unit_of_measurement: '%'

Try this.

1 Like

Many thanks @Spiro

Just so I fully understand that, I think it is saying

"if the json message contains “138603545” then apply the calculation to the depth_cm figure, but if not “do nothing (/ end / stop)”.

If so, should I repeat the code for the other (Red Diesel) tank also, ie …

  - platform: mqtt
    name: "Red Diesel Percent"
    state_topic: "home/rtl_433"
    value_template: >
      {% if value_json is defined and value_json.message.id == 136628653 %}
        {{ ((173 - (value_json.depth_cm)) * 21.34 / 3500 * 100) | int }}
      {% else %}
        {{ states('sensor.red_diesel_percent') }}
      {% endif %}
    unit_of_measurement: '%'

Or have I misunderstood?

TIA

I have a device that reports in a similar way by 433mhz and without narrowing it down to the id then from time to time it would get readings from somewhere else. With the id then no stray messages. Yes, put the individual id for each in their respective Red diesel percent sensors. My device has the problem if you remove the battery and reinsert the id changes and I have to go back and change it in the config. Battery lasts >1 year , so not a big problem. I did a fair bit of digging on various forums to find it. Modified the code to suit me ,but could not have written it myself.

Thanks again. The Watchman Oil Sensor only reports once every 17 minutes, so the battery lasts for years which is good news.

I now have three entries in my configuration.yaml file, but only the first one (the original) reports data through to Developer Tools > States. This suggests to me that the data is being received by HA, but the two new calculations are not happening. But I am not sure why …

#2022-01-03:This one can be removed when the next two work
  - platform: mqtt
    name: "Oil Percent_Original"
    state_topic: "home/rtl_433"
    value_template: "{{ ((173 - (value_json.depth_cm)) * 21.34 / 3500 * 100) | int }}"
    unit_of_measurement: '%'
#2022-01-03: This section replaces the one above due to two tanks
  - platform: mqtt
    name: "Oil Percent"
    state_topic: "home/rtl_433"
    value_template: >
      {% if value_json is defined and value_json.message.id == 138603545 %}
        {{ ((173 - (value_json.depth_cm)) * 21.34 / 3500 * 100) | int }}
      {% else %}
        {{ states('sensor.oil_percent') }}
      {% endif %}
    unit_of_measurement: '%'
#2022-01-03: Red Diesel tank is approx 1.75m long and 0.90m diameter. Nominal capacity = 1,135 L
  - platform: mqtt
    name: "Red Diesel Percent"
    state_topic: "home/rtl_433"
    value_template: >
      {% if value_json is defined and value_json.message.id == 136628653 %}
        {{ ((90 - (value_json.depth_cm)) * 12.61 / 1135 * 100) | int }}
      {% else %}
        {{ states('sensor.red_diesel_percent') }}
      {% endif %}
    unit_of_measurement: '%'

Ha. Simple mistake on my part. Delete the word message from your 2 sensors… I had added that as the id was within a message in my json.

{"message":{"id":107,"channel":0,"battery":1,"temperature":5.9,"humidity":80},"protocol":"nexus","length":"107","value":"107","repeats":2,"status":2}	

rtl_433 = {“time" : "2022-01-01 11:06:25”, "model" : “Oil-SonicSmart", "id" : 138603545, "flags" : 128, “maybetemp" : 21, "temperature C” : 13.333, “binding_countdown” : 0, “depth_cm” : 32}

1 Like

Almost but not quite.

It must report a value so if the received payload doesn’t contain 138603545 it cannot simply “do nothing”, it’s obligated to report something. The obvious choice in this case is to simply report its existing state value.

1 Like

Thanks for answering the question the way I should have. Yes , you don’t want messy gaps on your graphs.

1 Like