Problem understanding MQTT value templates

Hi all.
I’m exploring MQTT sensor integrations, and I’m stumped in acquiring data from json payload.

I have this esp32 device that simply sends out this json

{
    "ID": "testgen",
    "SigStr": "-49",
    "uptime": "124610"
}

on MQTT_Test/testgen/status topic; broker sees it with no problem and I can parse it from NodeRed.

so I try to add an integration to show the “uptime” value.

First try, I tried to use MQTT discover:

 char jsonString[2048];
 char discoveryTopic[50];
 JsonDocument dataPacket;

  MQTT.setServer(mqttBroker, 1883);
  MQTT.connect(hostname,MQTT_User,MQTT_PW);
  while (millis()-BeginConnect<timeout && !MQTT.connected()) {};
  if (!MQTT.connected()) {
    ESP_LOGE("MQTTConnect","Connection attempt timed out");
    return false;
  } else {
    dataPacket["dev"]["ids"]="testgen";
    dataPacket["dev"]["name"]="Uptime test";
    dataPacket["o"]["name"]="MQTT uptime test";

    dataPacket["cmps"]["testgen_T"]["p"]="sensor";
    dataPacket["cmps"]["testgen_T"]["unit_of_measurement"]="ms";
    dataPacket["cmps"]["testgen_T"]["value_template"]="{{ value_json.uptime }}";
    dataPacket["cmps"]["testgen_T"]["unique_id"]="testgen_T";

    dataPacket["state_topic"]="MQTT_Test/testgen/status";
    dataPacket["qos"]= "0";
    serializeJson(dataPacket,jsonString);
    
    sprintf(discoveryTopic,"homeassistant/device/testgen/config");
    MQTT.publish(discoveryTopic,jsonString);

this built a discover json

{
  "dev": {
    "ids": "testgen",
    "name": "Uptime test"
  },
  "o": {
    "name": "MQTT uptime test"
  },
  "cmps": {
    "testgen_T": {
      "p": "sensor",
      "unit_of_measurement": "ms",
      "value_template": "{{ value_json.uptime }}",
      "unique_id": "testgen_T"
    }
  },
  "state_topic": "MQTT_Test/testgen/status",
  "qos": "0"
}

but apparently it could not be published; tried to push it through with the MQTT broker, but apparently it did not like the “{{ value_json.uptime }}” part.

So I tried adding manually a MQTT device, but still, did not like “value_json” in the template.

What am I missing?

If you mean a sensor then it would be something like this in yaml

 mqtt:
   sensor:
     - name: "Testuptime"
       device_class: "uptime"
       state_topic: "MQTT_Test/testgen/status"
       value_template: "{{value_json.uptime }}"
       unit_of_measurement: 's'
       unique_id: test_uptime 

Yes, did that, but I get… a sensor that gets no value ever.

.

Also, I don’t understand why I can’t get a working MQTT discovery packet, I copied the routine almost verbatim from several tutorials I found around…

 mqtt:
   sensor:
     - name: "Testuptime"
       state_topic: "MQTT_Test/testgen/status"
       value_template: "{{value_json.uptime }}"
       unit_of_measurement: 's'
       unique_id: test_uptime 

Remove the device class. I looked again “uptime”: “124610”. The “” round the number I think means its a string. It’s better to view in a card like entity rather than a graph.

also have a look into the HA log, if the payload cannot be rendered as valid JSON, value_json will be undefined

That’s because Home Assistant attempted to evaluate the template before publishing the payload. You want it to publish the payload without first evaluating the template.

Here is how I do it. The following example worked for me. Notice the use of {%raw%} and {%endraw%} tags surrounding the template. It ensures the template is not evaluated before publishing the payload.

{
  "dev": {
    "ids": "testgen",
    "name": "Uptime test"
  },
  "o": {
    "name": "MQTT uptime test"
  },
  "cmps": {
    "testgen_T": {
      "p": "sensor",
      "unit_of_measurement": "ms",
      "value_template": {%raw%}"{{value_json.uptime}}"{%endraw%},
      "unique_id": "testgen_T"
    }
  },
  "state_topic": "MQTT_Test/testgen/status",
  "qos": "0"
}

I then published a value of {"uptime": 100} to MQTT_Test/testgen/status and confirmed the sensor reports 100.