The JSON payload sent to this topic is not consistent. On some messages it contains the JSON field tem on the rest it does not.
From my understanding using the is_defined filter causes the sensor to report the last known value if the payload does not contain the tem field. This is good because it stops the sensor flipping from the actual value to zero every time a message is received without the tem field. This gives a constant view in any dashboard.
The expire_after: 120 only triggers an Unavailable status if no message is received to this topic after 120 seconds rather than if no message containing the field tem is received within 120 seconds. I believe this is because if a message to this topic is received within the 120 that does not contain the tem field the is_defined filter is substituting the past value which is in turn is satisfying the expire_after check.
I would like to know how to rewrite this config to show an Unavailable value if no message is received containing the field tem within the time frame set by expire_after. This must not be at the expense of setting the sensor value to zero if a message is received which does not contain the required field.
expire_after isn’t concerned with what is in the received payload only if a payload is received (within the 120 sec interval).
The fact that the received payload lacks a tem key is of no concern to expire_after. It received a payload within 120 seconds (with or without a tem key) and that’s sufficient for it to reset its countdown.
You want expire_after to report Unavailable if the payload lacks the tem key (and 120s have passed). I don’t know of any configuration option to change the behavior of expire_after.
The only way I know how to achieve your goal is to duplicate the functionality of expire_after using a timer and automations. The automation serves as a middleman, receiving the payload directly from OMG. If the payload contains the tem key, it resets the 120-second timer and publishes the value to a topic subscribed by sensor.temp_sensor. I won’t explain the rest because I suspect you probably don’t want this complicated proposal.
Question: where did you see the is_defined filter documented? I wasn’t able to find it either Jinja2’s or Home Assistant’s documentation. It behaves as you described but I’d like to read its official description.