MQTT sensor, how to use with attributes?

Where did you add double quotes? What you posted looks identical to what I had suggested.

This is what you gave me as code

    json_attributes_template: >
      { "string_state": {{ 'on' if true else 'off' }} }

And this is where I added

    json_attributes_template: >
      { "string_state": "{{ 'on' if true else 'off' }}" }

Strange again… take a look


This is the result of:

    json_attributes_template: >
      { "string_state": "{{ value_json.ZbReceived.Computer_Air_Quality['EF00/0212'] }}" }

And this:


is the result of:

    json_attributes_template: >
      { "string_state": "{{ 'on' if value_json.ZbReceived.Computer_Air_Quality['EF00/0212'] < 1000 }}" }

And it is going through all the details (temperature, humidity and so on…)

You’re trying to confuse me, right? :slightly_smiling_face:

The single-line template you just posted isn’t the multi-line template you had posted in the message where you first said you added double-quotes.

OK, understood. The result of the template isn’t automatically interpreted to be a string so, to create a valid JSON string value, we must explicitly wrap the template’s result in double-quotes.

Based on that information, try the original suggestion with the addition of double-quotes.

    json_attributes_template: >
      { "string_state": 
        "{{ 'very low' if this.state | float(0) <= 13 else
            'low' if 15 <= this.state | float(0) <= 18 else
            'normal' if 20 <= this.state | float(0) <= 25 else
            'high' if 27 <= this.state | float(0) <= 30 else
            'very high' if this.state | float(0) >= 32 else
            this.attributes.string_state | default('unknown') }}" }
1 Like

It is working :partying_face: :partying_face:

But still, how this “this.state” knows that it is about the state of ['EF00/0212'] ?

Edit: I am stupid, don’t mind me :))) I understood now

1 Like

Whew! Glad to hear it’s working now because I was running out of ideas. :slightly_smiling_face:

1 Like

I can’t thank you enough.

I am now trying to understand how to modify this, in order to have the same last result after the HA restarts. Because if I restart HA, for just a second, the state of the sensor will be unknown, then the value it will be shown… and so on… :slight_smile:

Is the device that publishes this payload:

{
  "ZbReceived": {
    "Computer_Air_Quality": {
      "Device": "0x545C",
      "Name": "Computer_Air_Quality",
      "EF00/0212": 243,
      "Endpoint": 1,
      "LinkQuality": 107
    }
  }
}

publishing it as a retained message?

Oh ok, I think that this should be done from Tasmota, per device.

I wanted to ask you… what this " | default(‘unknown’)" is doing? I dont understand, can you please explain to me?

If this.attributes.string_state doesn’t exist then the default filter reports unknown.

1 Like

Thank you. I can sleep well tonight :smiley:

Hi again @123

I have a small issue on the same subject… maybe you know what is happening.

I have this sensor which you helped me with:

  - name: Bedroom Minibar Ambient Battery
    state_topic: "tele/ZigBee_Bridge/0253/SENSOR"
    unit_of_measurement: "%"
    device_class: battery
    value_template: >
      {% if is_number(value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0)) %}
      {{ value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0) }}
      {% else %}
      {{ states('sensor.bedroom_minibar_ambient_battery') }}
      {% endif %}
    json_attributes_topic: tele/ZigBee_Bridge/0253/SENSOR
    json_attributes_template: >
      { "string_state": 
        "{{ 'low' if this.state | float(0) <= 30 else
            'normal' if this.state | float(0) > 30 else
            this.attributes.string_state | default('unknown') }}" }

The problem is that the attribute will only change it’s state if the sensor state changes the second time… So, if I will receive a lower value than 30, the attribute state will change only if the sensor will receive another lower value… Same for higher than 30… I don’t understand why is like this…

Any idea?

Thank you in advance!

- name: Bedroom Minibar Ambient Battery
    state_topic: "tele/ZigBee_Bridge/0253/SENSOR"
    unit_of_measurement: "%"
    device_class: battery
    value_template: >
      {% if is_number(value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0)) %}
      {{ value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0) }}
      {% else %}
      {{ states('sensor.bedroom_minibar_ambient_battery') }}
      {% endif %}
    json_attributes_topic: tele/ZigBee_Bridge/0253/SENSOR
    json_attributes_template: >
      {% if is_number(value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0)) %}
      {% set t = value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0) %}
      {% else %}
      {% set t = states('sensor.bedroom_minibar_ambient_battery') %}
      {% endif %}
      { "string_state": 
        "{{ 'low' if t <= 30 else
            'normal' if t > 30 else
            this.attributes.string_state | default('unknown') }}" }

This is what it shows

Edit: I think it is working, but it should first receive a value, than the state will show up :smiley:

Thanks!

I didn’t change anything in value_template. It’s probably reporting unknown because it hasn’t received a payload yet.

1 Like

Exactly!

And, can I do something to show a value if no payload received yet? Maybe show the last known value?

Edit: I have solved it by making the device publish the value sensor as retained. It is a good solution or I can do something from this code?

The MQTT Sensor’s value_template is processed only when a payload is received.

1 Like

I still got some issues, because if I would receive a different sensor’s value from the same device, the BatteryPercentage would act like it had no payload… so i did this to solve it:

  - name: Bedroom Minibar Ambient Battery
    state_topic: "tele/ZigBee_Bridge/0253/SENSOR"
    unit_of_measurement: "%"
    device_class: battery
    value_template: >
      {% if value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] %}
      {% if is_number(value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0)) %}
      {% set var = value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0) %}
      {% else %}
      {% set var = states('sensor.bedroom_minibar_ambient_battery') %}
      {% endif %}
      {{ var }}
      {% endif %}
    json_attributes_topic: tele/ZigBee_Bridge/0253/SENSOR
    json_attributes_template: >
      {% if value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] %}
      {% if is_number(value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0)) %}
      {% set var = value_json['ZbReceived']['Bedroom_Minibar_TempHum_Sensor']['BatteryPercentage'] | float | round(0) %}
      {% else %}
      {% set var = states('sensor.bedroom_minibar_ambient_battery') %}
      {% endif %}
      { "string_state": 
        "{{ 'low' if var <= 30 else
            'normal' if var > 30 else
            this.attributes.string_state | default('unknown') }}" }
      {% else %}
      { "string_state": "{{this.attributes.string_state}}" }
      {% endif %}

Kinda a big code for just a sensor :frowning: Do you know any other solution, with a smaller code? :smiley: I want to optimize how the code looks and make it smaller

If the state_topic can receive payloads meant for more than one sensor, you should consider implementing Strategy #2 described in the following topic: