Hello, I would like to create an automation that alerts me when any of my sensors stop updating (i.e. I do not need to be alerted if they report unchanged values, only in case they disappear completely). I am trying the following code but I still get notifications about unchanged values. N.b. all my sensors report in via MQTT.
OK, I get it, in this case the original approach is completely wrong. Could you give me any other pointers on how I can achieve the goal above? I have seen some threads on this but nothing very straightforward and all requires a lot of copy-pasting around if I want to monitor multiple sensors. Should I go appdaemon instead?
Restating home assistant will update the last_changed attribute though. So if your sensor hasnāt changed for 500 seconds then you restart, it will take another 600 seconds of no updates after the restart for it to trigger.
If thatās important there are ways to rectify it:
automation:
- trigger:
platform: template
value_template: >
{{ (as_timestamp(strptime(states('sensor.date_time'),'%Y-%m-%d, %H:%M')) - as_timestamp(states.sensor.bedroom_temperature.last_changed) ) > 600 }}
action:
service: notify.telegram
data_template:
message: "Bedroom temperature has not updated since 10 min"
And I still get this error:
2019-07-12 18:18:02 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback <function async_track_state_change.<locals>.state_change_listener at 0x7fdfac1d29d8>
Traceback (most recent call last):
File "uvloop/cbhandles.pyx", line 68, in uvloop.loop.Handle._run
File "/usr/src/app/homeassistant/helpers/event.py", line 85, in state_change_listener
event.data.get('new_state'))
File "/usr/src/app/homeassistant/core.py", line 342, in async_run_job
target(*args)
File "/usr/src/app/homeassistant/helpers/event.py", line 106, in template_condition_listener
template_result = condition.async_template(hass, template, variables)
File "/usr/src/app/homeassistant/helpers/condition.py", line 331, in async_template
value = value_template.async_render(variables)
File "/usr/src/app/homeassistant/helpers/template.py", line 191, in async_render
return self._compiled.render(kwargs).strip()
File "/usr/local/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "<template>", line 1, in top-level template code
TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'
Now it works fine, apart from the fact that contrary to the initial expectation, it DOES notify also in cases where the sensor publishes data but that data is unchanged from the previously published data. How to solve this?
You need to monitor mqtt messages, not the sensor. If you get the same value your sensor will say: 19Ā°c 1 hour ago or 6 hours ago if itās stable - even if it got a temperature update every minute.
This topic has special interest to me, as I have a couple sensors which are locking-up every now and then and stop sending updates, and so Iām setting up an automation to send me a message when that happens - a precursor to a fully-automated restart.
My minor contribution is this: if you use ānow()ā on your template expression, you donāt need to define a date_time sensor at all - which seems silly. Also, at least here (0.100.3), LastUpdated is already a timestamp (at least when queried with state_attr), so no need to convert. The final template expression looks like this:
What kind of temperature sensor are you using? Specifically, which integration?
Iām asking because LastUpdated is not an attribute of Home Assistantās sensor entity. There is last_updated and itās a property of the entityās State Object. The State Object also supports attributes but LastUpdated is not one of them.
LastUpdated must be unique to the sensor platform you are using and the clue is that its name is in propercase. All of Home Assistantās nomenclature (entity names, properties, options, etc) is expressed in lowercase. The other clue is that you stated its value is a timestamp whereas Home Assistant stores datetime values as a datetime object (or a string).
if you use ānow()ā on your template expression, you donāt need to define a date_time sensor at all - which seems silly.
now() is a function. If used in a Template Sensor, it is evaluated when Home Assistant starts and never again (until the next restart). That means if you use this template in a Template Sensor:
after startup, the template will be evaluated only when the value of LastUpdated changes. If there is a need for this template to be evaluated periodically, like when the time changes from one minute to the next, this template will fail to do that. Thatās because Home Assistant only monitors the changes of entities (that it can identify within the template) and not functions such as now().
Thatās why a date_time sensor is often employed in Template Sensors when thereās a need to have the template evaluated periodically. For example, sensor.time changes every minute whereas sensor.date changes once every day.
Interesting, I just went poking around and noticed that this is indeed not common on most integrations - I was so accustomed to seeing it with the entities Iām monitoring that I assumed it to be standard.
The particular integration Iām pulling this attribute from is an Open Energy Monitor integration using the emoncms platform. It exposes a rather rich set of attributes for each entity:
- FeedId
- Tag
- FeedName
- Size
- UserId
- LastUpdated (in epoch format)
- LastUpdatedStr (in datetime format)
- unit_of_measurement
- friendly_name
With regards to the usage of the now() function:
Ouch, that explains what I observed when I put this in practice and was not seeing the automation trigger once the condition was met. My bad and thanks a lot for pointing this newbie mistake!
Conclusion?
Huge thanks to Taras for correcting my mistakes! And to everyone looking at this thread for advice on watchdog automations for sensors prone to freezing, disregard what I said earlier, especially the bit about now()
I am currently facing a similar challange. I have about 10 Aqara Temperature Sensors and I control our heating system with them. For security reasons, I would like to get a notification when a sensor is not working anymore, so I would like to get notified when a sensor has not changed its state for ~2 hour.
Iāve been trying to figure out your solutions and I have created the following automation, but itās not working.
Any idea whatās wrong?
Thank you!
- id: sensor_warning_test
alias: Sensor Warning Test
trigger:
platform: state
entity_id: sensor.sensor_wohnzimmer_temp
condition:
condition: template
value_template: "{{ ( as_timestamp(now()) - state_attr('sensor.sensor_wohnzimmer_temp', 'LastUpdated') ) > 10 }}"
action:
service: notify.alles
data:
title: Sensor-Warning!
message: 'Sensor Wohnzimmer has not been updated for 10 Seconds!'
I have put together a standalone application for this purpose meanwhile. It is one single binary (written in Go) which subscribes to specified MQTT topics, monitors incoming messages and alerts via Telegram in case a topic stops receiving messages (time threshold is calculated automatically based on past transmission frequency). It also supports pinging hosts and alerting in case of no reply. It has a simple web ui (see screenshot below) for viewing status and reloading configuration.
I use it now to monitor all my home automation devices, it does this task only but reliably. Let me know if this is of any interest - if so, I can upload the source code to github.
Thanks for this hint, I have now changed the template to the following:
{{ (as_timestamp(now())-as_timestamp(states.sensor.sensor_wohnzimmer_temp.last_updated))
| int //60}}
Returns: 27
{{ (as_timestamp(now())-as_timestamp(states.sensor.sensor_wohnzimmer_temp.last_updated))
| int //60 > 30}}
Returns: False / True
The whole automation now looks like this, but it seems like there is something wrong with the trigger - it doesnāt get triggered when the ālast_updatedā value gets over 30 Minutes.
Any ideas?
- id: sensor_warning_test
alias: Sensor Warning Test
trigger:
- entity_id: sensor.sensor_wohnzimmer_temp
platform: state
condition:
- condition: template
value_template: '{{ (as_timestamp(now())-as_timestamp(states.sensor.sensor_wohnzimmer_temp.last_updated))
| int //60 > 30}}'
action:
- data:
message: Sensor Wohnzimmer has not been updated for 30 Minutes!
title: Sensor-Warning!
service: notify.alles