Value_template on optional JSON parameter

Hi,

I have a question on how to handle sensors with optional data. Right now I have a lot of errors in my log because of the fact that the messages received do not always contain the elements in the JSON.

My config contains the following:

- name: "Apartment Current L3"
  state_topic: "application/+/device/102ceffffe0103bc/event/up"
  unique_id: "102ceffffe0103bc_current_l3"
  value_template: "{{ value_json.object['Current L3'].value }}"
  unit_of_measurement: "mA"
  device_class: current
  force_update: true
  device:
    identifiers:
      - "apartment_energy_meter"
    name: "Apartment Energy Meter"

- name: "Apartment Voltage L1-N"
  state_topic: "application/+/device/102ceffffe0103bc/event/up"
  unique_id: "102ceffffe0103bc_voltage_l1"
  value_template: "{{ value_json.object['Voltage L1-N'].value }}"
  unit_of_measurement: "V"
  device_class: voltage
  force_update: true
  device:
    identifiers:
      - "apartment_energy_meter"
    name: "Apartment Energy Meter"

The problem is that the energy meter sends the currents and the voltages in different messages. The message is then translated by the gateway (LoRa → MQTT) to the same topic. That means that the received JSON on the topic contains either the currents or the voltages.

I know how I can test if the value is present in the template. But what should I return in the case the value is not present? I don’t want Home Assistant to create a datapoint in the case the data is not present. Right now it behaves correctly in that regard but I get an error log entry with every message transmission and for each entity.

Hope somebody has some idea. I could not find anything in this regard.

Unless something has changed recently this template shouldn’t work:

value_template: "{{ value_json.object['Voltage L1-N'].value }}"

As value represents the entire raw unserialised message, just the same way as value_json represents the entire json serialised version. It is a reserved word so you need to use square bracket notation for a key called “value”. As to your other problem you can do this:


value_template: > 
  {% if value_json.object['Voltage L1-N']['value'] is defined %}
    {{ value_json.object['Voltage L1-N'].value }}
  {% else %}
    {{ this.state }}
  {% endif %}

This retains the previous state if the message does not contain your voltage.

The other option is to set the sensor unavailable with an availability topic and template:

- name: "Apartment Voltage L1-N"
  state_topic: "application/+/device/102ceffffe0103bc/event/up"
  availability_topic: "application/+/device/102ceffffe0103bc/event/up"
  availability_template: "{{ value_json.object['Voltage L1-N']['value'] is defined }}"
  unique_id: "102ceffffe0103bc_voltage_l1"
  value_template: "{{ value_json.object['Voltage L1-N']['value'] }}"
  unit_of_measurement: "V"
  device_class: voltage
  force_update: true
  device:
    identifiers:
      - "apartment_energy_meter"
    name: "Apartment Energy Meter"

This will result in a lot of gaps in your data.

Thank you for your fast response I will test your suggestion.
It will probably cause problems if I additionally set the force_update: true parameter in the config. Which I was planning to do. But it will work otherwise. It would be nice if I could somehow tell the system that there is not the old value present, but no new value at all. Returning the old value feels a bit like a workaround. Like returning some nullptr. (I’m a C/C++ developer mostly :stuck_out_tongue: )

The value seems to be parsed quite correctly in this case, but I will change it to be future proof.

You are the second person to say that this week. I think perhaps the devs have fixed this common issue.

You really only have three options, as the state value must update when a message is received on the topic:

  1. Set the date to some other value, like 0
  2. Retain the existing state
  3. Set the state to unavailable/unknown

I’ve given you options 2 & 3 and you can convert option 2 to 1 easily enough, just replace {{ this.state }} with the number you want.

Or I just leave it like it is now. It currently stops parsing the received message for this value and does not update anything. This is exactly what I want. I just want to get rid of the error message in the logs. Set the state to unavailable or unknown is also no solution I think as that will display in the dashboard. The messages are received roughly at the same time only a couple of milliseconds from each other.

Maybe I look at some point to figure this out and maybe do a feature request. I think this should be common issue and not just some corner case.

You can change the logging level for the mqtt integration to “critical” rather than “error”. You may miss a few important errors though. So change it back if ever needing to debug.

Seems I was wrong about this. It’s a key called “values” that is problematic. So no square bracket required in your case. Other key names (that match methods) that can cause issues:

'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'

items and values are the most common issues I’ve seen.