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?
You could use a template sensor (for each sensor you want to monitor):
trigger:
platform: template
value_template: "{{ (as_timestamp(strptime(states('sensor.date_time'),'%Y-%m-%d, %H:%M')) - as_timestamp(states.sensor.living_room_temperature_1.last_changed) ) > 600 }}"
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:
OK, I have this code now:
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'
Reply to myself, the above error is solved by adding a time_date sensor as follows:
sensor:
- platform: time_date
display_options:
- "date_time"
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?
Use the last_updated instead of last_changed attribute.
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.
Jhh
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:
{{ ( as_timestamp(now()) - state_attr('sensor.living_room_temperature_1', 'LastUpdated') ) > 600 }}
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:
{{ ( as_timestamp(now()) - state_attr('sensor.living_room_temperature_1', 'LastUpdated') ) > 600 }}
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()
Hello together,
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.
If you paste this into the Template Editor, does it report a numeric value?
{{ as_timestamp(now()) - state_attr('sensor.sensor_wohnzimmer_temp', 'LastUpdated') }}
It just says:
Unknown error rendering template
That’s the same template used in your automation’s condition
and probably explains why the automation doesn’t work.
Paste this into the Template Editor and confirm it returns a valid timestamp:
{{ state_attr('sensor.sensor_wohnzimmer_temp', 'LastUpdated') }}
If it does not report a timestamp then you need to re-design your template.
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
Yes I would be interested! If you can share that would be great!
Take a moment to think about what you have created:
-
The trigger occurs only when
sensor_wohnzimmer_temp
changes state (or one of its attributes changes). -
The condition is looking for the situation when the sensor has not changed its state for over 30 minutes.
The automation’s condition is evaluated only when the sensor changes state (so your value_template will never produce a true
result).
I suggest you create a Template Binary Sensor. Set its entity_id to sensor.time
so that the Template Binary Sensor is evaluated every minute. If you are not already using sensor.time
you will need to define it in your configuration.yaml file.
- platform: template
sensors:
wohnzimmer_no_activity:
entity_id: sensor.time
value_template: >
{{ (utcnow() - states.sensor.sensor_wohnzimmer_temp.last_updated).seconds // 60 > 30 }}
Use the Template Binary Sensor to trigger your automation.
- id: sensor_warning_test
alias: Sensor Warning Test
trigger:
- entity_id: sensor.wohnzimmer_no_activity
platform: state
to: 'on'
action:
- data:
message: Sensor Wohnzimmer has not been updated for 30 Minutes!
title: Sensor-Warning!
service: notify.alles
EDIT
Simplified the template.
That’s it, thanks a lot!
Very interested in seeing what you developed. Thanks