ESPhome: Help Parsing a MQTT JSON

Greetings
It’s me again, feels like it at least. I just cannot wrap my head around the more advanced lamda stuff.
This time I’m trying to have ESPhome parse the below MQTT message from a temperature sensor sent by node-red and set the value of a global variable to “temperature.value” from the message.

{
  "temperature": {
    "value": 12.3,
    "unit": "degC"
  },
  "humidity": {
    "value": 67,
    "unit": "%",
    "status": "NORMAL"
  }
}

I just cannot understand how to get to the specific value. For another project I managed to parse an MQTT value that wasn’t “hidden” in a JSON but this time I’m lost.
What I want to achieve as a first step is something below, at least have the logger print the temperature value when there is a change but the output is empty.

mqtt:
  broker: x.x.x.x
  username: !secret mqttlogin
  password: !secret mqttpass
  topic_prefix: homeassistant/esp/heating
  discovery_prefix: homeassistant
  birth_message:
  will_message:
    
  on_json_message:
    topic: rfxcom/sensor/entren
    then:
      - lambda: |-
          ESP_LOGI("main", "value is:", x["temperature"]);

Frustrated but grateful for any pointers
/Fredrik

https://jsonpathfinder.com/

Replace the x with the topic for the sensor.

Hi
Useful site but how would that translate to my logging lambda? I have tried

  on_json_message:
    topic: rfxcom/sensor/entren
    then:
      - lambda: |-
          ESP_LOGI("main", "value is:", x["temperature.value"]);

Without any luck.

It looks like you need mqtt subscribe. To create a sensor that you can then use in automations in esphome?

sensor:
  - platform: mqtt_subscribe
    name: "Data from topic"
    id: name_to_reference_in_automations
    topic: rfxcom/sensor/entren/temperature/value

If you don’t add name: the sensor will be internal only and won’t show in HA.

I’ve tried that approach, to set up an MQTT subscribe sensor and if I use the topic
topic: rfxcom/sensor/entren I get the log error message

[12:18:22][W][mqtt_subscribe.sensor:015]: Can't convert '{
  "temperature": {
    "value": 15,
    "unit": "degC"
  },
  "humidity": {
    "value": 67,
    "unit": "%",
    "status": "NORMAL"
  }
}' to number!

If I use the topic topic: rfxcom/sensor/entren/temperature/value, like below, the sensor never triggers a detection.

  - platform: mqtt_subscribe
    id: entre_temperature
    topic: rfxcom/sensor/entren/temperature/value
    on_value:
      then:
        - logger.log: "Entretrigger"

/Fredrik

It’s coming in as a string. If you use a text_sensor it all comes in but it still needs to be converted for it to be usable as a number.

text_sensor:
  - platform: mqtt_subscribe
    name: "Data from topic"
    id: name_to_reference_in_automations
    topic: rfxcom/sensor/entren

This is proving to be pretty convoluted, I found this thread maybe you’ll see something I didn’t

I set this up on my system and was trying the following but something is off an it wont compile



globals:
  - id: temperature
    type: float

  - id: humidity
    type: float



# Enable Home Assistant API
mqtt:
  broker: 192.168.0.101

  
  on_json_message:
    topic: test/temp
    then:
      - lambda: |-
          if (x.containsKey("temperature")){
            if (x["temperature"] == 25) {
            ESP_LOGD("on_json_message", "Found");
            float temperature = x["temperature.value"];
            float humidity = x["humidity.value"];
            id(temperature) = temperature;
            id(humidity) = humidity;
            }
          }
/config/esphome/fan-controller.yaml: In lambda function:
/config/esphome/fan-controller.yaml:34:20: error: base operand of '->' is not a pointer
             id(temperature) = temperature;
                    ^
/config/esphome/fan-controller.yaml:35:17: error: base operand of '->' is not a pointer
             id(humidity) = humidity;
                 ^
Compiling /data/fan-controller/.pioenvs/fan-controller/lib790/FS/vfs_api.cpp.o
*** [/data/fan-controller/.pioenvs/fan-controller/src/main.cpp.o] Error 1

Hi
Convoluted indeed. Thank you for your time. I was under the impression the process of extracting a nested JSON in an MQTT message was common practice and it was just me not understanding things.
Anyway in the meantime I have made a workaround where I set node-red, who is sending the MQTT in the first place, to also send the temperature value as a simple value which is working with the below ESP code.

/Fredrik

  - platform: mqtt_subscribe
    id: entre_temperature
    topic: rfxcom/sensor/entren_enkel
    on_value:
      then:
        - lambda: |-
            id(entretemperatur) = id(entre_temperature).state;

In HA it is. I have a lot of mqtt sensors in HA from nested JSON and it was straight forward setting them up. Lambda’s are C++ which is a traditional programming language unlike yaml that uses “human readable” commands.

I just want to mention that they have made it really easy to bring in values from HA with the api. For example I use an input_number to adjust a delay in esphome.

First bring the sensor into the sketch with:

sensor:
  - platform: homeassistant
    name: "Grow Pump Interval"
    id: grow_pump_interval
    internal: true
    accuracy_decimals: 0
    entity_id: input_number.grow_pump_interval

then to us the id where you need it.

- platform: gpio
    pin: GPIO12
    id: relay
    name: "grow-temp-pump-switch"
    on_turn_on:
    - delay: !lambda 'return id(grow_pump_interval).state * 1000;'
    - switch.turn_off: relay