Check if sensor is alive

Anyone has a handy script/automation/appdaemon to check if the sensor hasn’t updated it’s value for more than let’s say an hour?

I’m using this automation to check if the temperature and humidity of a DHT22 does not change for 2 hours.

  # Sonoff16A notify if no state change for 2 hours 
  - alias: sonoff16a_state_notifier_on
    #initial_state: True
    trigger:
      - platform: time
        minutes: '/5'
        seconds: 06
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: input_boolean.sonoff16a_alarm
          state: 'off'
        - condition: template
          value_template: >
            {{ (as_timestamp(now())-as_timestamp(states.sensor.sonoff16a_temp.last_updated)) > 7200 }}
        - condition: template
          value_template: >
            {{ (as_timestamp(now())-as_timestamp(states.sensor.sonoff16a_humi.last_updated)) > 7200 }}
    action:
      - service: homeassistant.turn_on
        entity_id: input_boolean.sonoff16a_alarm
      - service: persistent_notification.create
        data:
          title: "Sonoff16A"
          message: "Sensor Timeout"
1 Like

Thanks! But wonder if any wildcard can be used to check all of the sensors

Hi! Thanks to this community I have this app in AppDaemon:
File sensors_updates.py

import appdaemon.plugins.hass.hassapi as hass
import shelve
from datetime import datetime
#
# App to notify if a sensor/device_tracker is dead for check_interval seconds
# Source: https://community.home-assistant.io/t/app-to-monitor-sensors/22470/8
# Args:
#
#file: db file to save state and lastchanged to persist HA shutdown
#blacklist: list of sensors/device_trackers not to track.
#check_interval: time interval between check in seconds
# Release Notes
#
# Version 1.0:
#   Initial Version

class SaveSensorState(hass.Hass):
  
  def initialize(self):
    start_time = datetime.now()
    self.timeout_length = self.args["check_interval"]
    self.device_db = shelve.open(self.args["file"])
    self.listen_state(self.state_change, "sensor")
    #self.listen_state(self.state_change, "device_tracker")
    self.run_every(self.check_if_updated,start_time, self.timeout_length)
    self.blacklist = self.args["blacklist"].split(",")

  def state_change(self, entity, attribute, old, new, kwargs):
    if not entity in self.blacklist:
      #self.log("State change in {}: from {} to {}".format(entity, old, new))
      now = datetime.now()
      data = {'state': new, 'time': now}
      self.device_db[entity] = data
      #self.log("Sensor {} value changed to {} at {}".format(entity, new, now))
  
  def check_if_updated(self, kwargs):
    #self.log("Checking sensor health")
    message = ""
    state = self.get_state()
    for entity in state:
      if not entity in self.blacklist:
        type, id = entity.split(".")
        #if type == "sensor" or type == "device_tracker":
        if type == "sensor":
          if entity in self.device_db:
            oldState = self.device_db[entity]['state']
            oldTime = self.device_db[entity]['time']
            #self.log("Old state for {} was {} and old time was {}".format(entity, oldState, oldTime))
            if (self.device_db[entity]['state'] == state[entity]["state"]):
              now = datetime.now()
              elapsedTime = now - oldTime
              if elapsedTime.seconds > self.timeout_length:
                if message =="":
                  message = entity
                else:
                  message = message + ', ' + entity
                #self.log("Sensor {} is in {} state for 24 hours.".format(entity, oldState))
            else:
              now = datetime.now()
              data = {'state': state[entity]["state"], 'time': now}
              self.device_db[entity] = data
          else:
            self.log("Adding {}, setting value to current state ({})".format(entity, state[entity]["state"]))
            now = datetime.now()
            data = {'state': state[entity]["state"], 'time': now}
            self.device_db[entity] = data
    if message != "":
      self.log("Sensor {} has not changed for too much time. Consider reseting.".format(message))
      #self.notify("Sensors {} have not changed for 24 hours".format(message), name = "as_email", title = "Message from AppDaemon")
      tgmmessage = "{} has not changed for too much time. Consider reseting.".format(message)
      self.call_service("notify/telegram_dad",message = tgmmessage)

and the entry in apps.yaml

sensors_control:
  module: sensors_updates
  class: SaveSensorState
  file: /home/tim/.homeassistant
  check_interval: 21600
  blacklist: sensor.dark_sky_summary,sensor.dark_sky_icon,sensor.dark_sky_precip_probability

Good luck!

1 Like

Thanks that’s what i was looking for. Can you point me to the thread? Seems the code is for appdaemon 3 and i’m still on 2.4 (not ready to take the leap) so maybe be a 2.4 version is posted on the thread?

Yes, in fact you can find it in line 6 in my python file :wink: Anyway, here it is.

How to adopt this to discord notification?

I have tried as the following but get an error

if message != "":
  self.log("Sensor {} has not changed for too much time. Consider reseting.".format(message))
  #self.notify("Sensors {} have not changed for 24 hours".format(message), name = "as_email", title = "Message from AppDaemon")
  tgmmessage = "{} has not changed for too much time. Consider reseting.".format(message)
  self.call_service("notify.ha_discord",message = tgmmessage,target = "my chat id")

The error is like

2018-05-20 18:40:20.487898 WARNING Unexpected error in worker for App sensors_control:
2018-05-20 18:40:20.488590 WARNING Worker Ags: {'name': 'sensors_control', 'id': UUID('xxxxxx-6388-42d1-81df-xxxxx'), 'type': 'timer', 'function': <bound method SaveSensorState.check_if_updated of <sensors_updates.SaveSensorState object at 0x752596b0>>, 'kwargs': {'interval': 21600}}
2018-05-20 18:40:20.488986 WARNING ------------------------------------------------------------
2018-05-20 18:40:20.490007 WARNING Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 505, in worker
function(utils.sanitize_timer_kwargs(args["kwargs"]))
  File "/home/homeassistant/.homeassistant/appdaemon/apps/sensors_updates.py", line 73, in check_if_updated
self.call_service("notify.ha_discord",message = tgmmessage,target = "my chat id")
  File "/srv/homeassistant/lib/python3.6/site-packages/appdaemon/appapi.py", line 20, in func_wrapper
return(func(*args, **kwargs))
  File "/srv/homeassistant/lib/python3.6/site-packages/appdaemon/appapi.py", line 513, in call_service
return utils.call_service(service, **kwargs)
  File "/srv/homeassistant/lib/python3.6/site-packages/appdaemon/utils.py", line 411, in call_service
_check_service(service)
  File "/srv/homeassistant/lib/python3.6/site-packages/appdaemon/utils.py", line 407, in _check_service
raise ValueError("Invalid Service Name: {}".format(service))
ValueError: Invalid Service Name: notify.ha_discord

2018-05-20 18:40:20.490543 WARNING ------------------------------------------------------------

Since the log is giving this:

ValueError: Invalid Service Name: notify.ha_discord

I would use the Services tab in the Developer’s tool to find out potential errors. For instance, I would try the equivalent to this telegram notification (sorry, I don’t run the discord component):

notify_service

Hope this helps to narrow the issue.