MQTT filter out sublevel from json data

I have a MQTT sensor on my energy converter to my solarcells on the roof of the house that publish the data below regarding temperature of the solar string optimisers (SSO)
when I listen to the topic “extapi/data/sso” in HA I get these results below.
I have 3 SSO units that is publishing the same data on the MQTT topic with different ID:s

{
    "relaystatus": {
        "val": "0"
    },
    "temp": {
        "val": "39.770"
    },
    "wpv": {
        "val": "7770674028014"
    },
    "ts": {
        "val": "2020-06-20T13:20:34UTC"
    },
    "udc": {
        "val": "767.102"
    },
    "faultcode": {
        "val": "0"
    },
    "ipv": {
        "val": "1.534"
    },
    "upv": {
        "val": "439.185"
    },
    "id": {
        "val": "19110206"
    }
}
{
    "relaystatus": {
        "val": "0"
    },
    "temp": {
        "val": "37.249"
    },
    "wpv": {
        "val": "5393140186776"
    },
    "ts": {
        "val": "2020-06-20T13:20:34UTC"
    },
    "udc": {
        "val": "766.891"
    },
    "faultcode": {
        "val": "0"
    },
    "ipv": {
        "val": "1.252"
    },
    "upv": {
        "val": "375.293"
    },
    "id": {
        "val": "19110137"
    }
}
{
    "relaystatus": {
        "val": "0"
    },
    "temp": {
        "val": "39.119"
    },
    "wpv": {
        "val": "9179570957817"
    },
    "ts": {
        "val": "2020-06-20T13:20:34UTC"
    },
    "udc": {
        "val": "765.222"
    },
    "faultcode": {
        "val": "0"
    },
    "ipv": {
        "val": "1.471"
    },
    "upv": {
        "val": "501.961"
    },
    "id": {
        "val": "19110205"
    }
}

I am trying to get the individual temp values into different sensors but it don’t work
The configuration.yaml code that I am fighting with looks like this.

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110205'
    unique_id: '19110205'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == 19110205 %}
        {{ (value_json.temp.val) | round(1) }}
      {% endif %}

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110206'
    unique_id: '19110206'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == 19110206 %}
        {{ (value_json.temp.val) | round(1) }}
      {% endif %}

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110137'
    unique_id: '19110137'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == 19110137 %}
        {{ (value_json.temp.val) | round(1) }}
      {% endif %}

Any suggestions of how to filter out this ?

The key named id has a string value (not an integer) so the template’s test must compare it to a string.

      {% if value_json.id.val == '19110205' %}

If the received id does not match what the sensor wants, the template still needs to supply a value so we add an {% else %} that simply returns the sensor’s current value.

      {% else %}
        {{ states('sensor.sso_19110205') }}

Here are the three sensors incorporating the suggested changes:

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110205'
    unique_id: '19110205'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == '19110205' %}
        {{ (value_json.temp.val) | round(1) }}
      {% else %}
        {{ states('sensor.sso_19110205') }}
      {% endif %}

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110206'
    unique_id: '19110206'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == '19110206' %}
        {{ (value_json.temp.val) | round(1) }}
      {% else %}
        {{ states('sensor.sso_19110206') }}
      {% endif %}

  - platform: mqtt
    state_topic: 'extapi/data/sso'
    name: 'SSO 19110137'
    unique_id: '19110137'
    unit_of_measurement: '°C'
    value_template: >
      {% if value_json.id.val == '19110137' %}
        {{ (value_json.temp.val) | round(1) }}
      {% else %}
        {{ states('sensor.sso_19110137') }}
      {% endif %}

Another way to do this is to create an automation that subscribes to extapi/data/sso and re-publishes the received values to separate topics, one unique topic for each temperature sensor. This automation also rounds the temperature value before publishing it. Personally, I believe this is the superior solution.

- alias: 'Sensor Demux'
  trigger:
  - platform: mqtt
    topic: extapi/data/sso
  action:
  - service: mqtt.publish
    data_template:
      topic: 'sensor/{{trigger.payload_json.id.val}}'
      payload: '{{ trigger.payload_json.temp.val | round(1) }}'

Then the configuration of each sensor is simplified to this:

  - platform: mqtt
    state_topic: sensor/19110205
    name: 'SSO 19110205'
    unique_id: '19110205'
    unit_of_measurement: '°C'

  - platform: mqtt
    state_topic: sensor/19110206
    name: 'SSO 19110206'
    unique_id: '19110206'
    unit_of_measurement: '°C'

  - platform: mqtt
    state_topic: sensor/19110137
    name: 'SSO 19110137'
    unique_id: '19110137'
    unit_of_measurement: '°C'

1 Like

Thanx for quick reply!
So it was related to the data type INT vs string :slight_smile:
I have tested the example code that you sent and it seems to have done the trick.
I really liked the idea to simplify the code by republish the data but I have not tested that case but it seems to be more clean.