I need help dealing with mqtt json data

My json string as appears in mqtt explorer is like so:

{"channel":0,"from":1129875684,"hop_start":3,"hops_away":0,"id":1696352969,"payload":{"hardware":43,"id":"!435888e4","longname":"WarmCat Loft Station","shortname":"CAT"},"sender":"!435888e4","timestamp":1722286203,"to":862545120,"type":"nodeinfo"}

Within a file mqtt.yaml I have the following:

sensor:
  - name: "Node Info Log"
    unique_id: "node_info_log"
    state_topic: "msh/EU_868/2/json/LongFast/!435888e4"
    value_template: >-
      {% if value_json.type == 'nodeinfo' %}
        {{ value_json.payload.shortname }}
      {% else %}
        {{ this.state }}
      {% endif %}
    json_attributes_template: >-
      {% if value_json.type == 'nodeinfo' %}
        {
          "channel": {{ value_json.channel | default('None') }},
          "from": {{ value_json.from | default('None') }},
          "hop_start": {{ value_json.hop_start | default('None') }},
          "hops_away": {{ value_json.hops_away | default('None') }},
          "id": {{ value_json.id | default('None') }},
          "hardware": {{ value_json.payload.hardware | default('None') }},
          "node_id": "{{ value_json.payload.id | default('None') }}",
          "longname": "{{ value_json.payload.longname | default('None') }}",
          "shortname": "{{ value_json.payload.shortname | default('None') }}",
          "rssi": {{ value_json.rssi | default('None') }},
          "sender": "{{ value_json.sender | default('None') }}",
          "snr": {{ value_json.snr | default('None') }},
          "timestamp": {{ value_json.timestamp | default('None') }},
          "to": {{ value_json.to | default('None') }}
        }
      {% else %}
        {}
      {% endif %}

What is it that I’m doing wrong? When I look in developer tools, States, and then look for sensor.node_info_log, I see under ‘State’ the correct value_json.payload.shortname, but the only attribute I see is friendly_name: Node Info Log.

I have a lot of programming experience, alas none of it in yaml.
Thanks in advance if anyone can show me where I’ve went wrong here.

According to the documents, if you want to extract JSON from MQTT, then you need to use json_attributes_template and json_attributes_topic together. Right now you have a state topic, so that’s putting everything into a string and then the value template is used with that string, which means value_json.payload.shortname probably doesn’t work because the state is a string, not an object.

I think you can have both a string state and a JSON payload, but they have to be on different topics. The state topic would get used with the value template and the JSON topic would be used with the JSON template.

see:

1 Like

Wow thanks Kyle, you’re awesome, and correct!
Here is the updated code which works:

- name: "Node Info Log"
  unique_id: "node_info_log"
  state_topic: "msh/EU_868/2/json/LongFast/!435888e4"
  value_template: >-
    {% if value_json.type == 'nodeinfo' %}
      {{ value_json.payload.shortname }}
    {% else %}
      {{ this.state }}
    {% endif %}
  json_attributes_topic: "msh/EU_868/2/json/LongFast/!435888e4"
  json_attributes_template: >-
    {% if value_json.type == 'nodeinfo' %}
      {
        "channel": {{ value_json.channel | default('None') }},
        "from": {{ value_json.from | default('None') }},
        "id": {{ value_json.id | default('None') }},
        "hardware": {{ value_json.payload.hardware | default('None') }},
        "node_id": "{{ value_json.payload.id | default('None') }}",
        "longname": "{{ value_json.payload.longname | default('None') }}",
        "shortname": "{{ value_json.payload.shortname | default('None') }}",
        "rssi": {{ value_json.rssi | default('None') }},
        "sender": "{{ value_json.sender | default('None') }}",
        "snr": {{ value_json.snr | default('None') }},
        "timestamp": {{ value_json.timestamp | default('None') }},
        "to": {{ value_json.to | default('None') }}
      }
    {% else %}
      {}
    {% endif %}

Ah, it worked once, but stopped working. Why oh why.