sometimes a sensor stops updating.
it could be that the sensor is in error and should be resetted.
in the frontend there is no easy way to see if how long ago a sensor was updated.
off course you could search in the logbook, but then you could search a long time.
through appdaemon there is an easy way.
i made an app like this:
###########################################################################################
# #
# Rene Tode ( [email protected] ) #
# ( with a lot off help from andrew cockburn (aimc) ) #
# 2016/08/16 Germany #
# #
###########################################################################################
import appapi
import datetime
class sensorcontrole(appapi.AppDaemon):
def initialize(self):
self.listen_state(self.sensor_controle, "sensor")
def sensor_controle(self, entity, attribute, old, new, kwargs):
set_sensor_time = open("C:\\Users\\rene\\AppData\\Roaming\\.homeassistant\\controle\\laatste_controle.py", "w")
runtime = datetime.datetime.now().strftime("%H:%M:%S")
set_sensor_time.write('print("' + runtime+'")')
set_sensor_time.close()
for counter in range(1,int(self.args["total_sensors"])+1):
device, entity_name = self.split_entity(entity)
sensor_name=self.args["sensor" + str(counter)]
if entity_name == sensor_name:
set_sensor_time = open("C:\\Users\\rene\\AppData\\Roaming\\.homeassistant\\controle\\" + sensor_name + ".py", "w")
runtime = datetime.datetime.now().strftime("%H:%M:%S")
set_sensor_time.write('print("' + runtime+'")')
set_sensor_time.close()
this creates a file with the name āentity_id.pyā in the dir controle.
it also creates a file laatste_controle.py (last_control)
in de config i give the sensors i like to track like this:
next step:
in the app a control function for how long the sensor not has been updated.
and if the time is longer then the amount off time given in the config, it gives a notify that the sensor is in error.
i have chosen to calculate the timestring 2 times, to be able to manipulate the control sensor different then the others,
but the second 1 also could be deleted.
by the way, i also am going to make a group with sensors for controlling when automations have fired the last time (with date) and when switches are switched for the last time, thats why the group is called sensors.
it took me some figuring out, but its going well.
right now i have:
1 app which can be reused to make checksensors for:
sensors (last change time for any sensor you like)
switches (last change time for any switch you like)
devices (last change time for any device you like)
input_booleans (last change time for any boolean you like)
actually you can track everything you like in HA and give the last change at the frontend.
i think i already have parts from my wished automation fired functions.
for those who have hoped to check if an yaml automation is fired, i must say that that is not coming directly.
for the simple reason that i dont have yaml automations anymore.
all my automations are through apps and what i will create is a general function which updates a commandline sensor.
i would have released my updates now i am so far, but in appdaemon there is a small bug. @aimc has found a workaround for me, but i dont want to release untill i have taken out the workaround.
that also gives me the time to see if it keeps satisfying me.
already build in option:
setting time format in the configuration file
windows and Linux dir formats automatic (only windows tested)
setting name from controle object in the configuration file
chosing if you like last updated time or time gone by since in the confuguration file
setting dir for saving the commandline sensors in the configuration file
chosing the object_type in the configuration file (sensor, switch, input_boolean, etc.)
I had a similar need, wanting to look for sensors that stopped updating. Iām not sure if last_updated is the last time the value changed or the last time it was polled/return value. I think this problem may arise with either solution. The app will create a new sensor in HA with the number past a given age with the details in the attributes.
All you need is this app:
sensorcheck:
module: sensorage
class: SensorAge
Code
import appdaemon.appapi as appapi
from datetime import timezone
# {'entity_id': 'sensor.dark_sky_precip_probability', 'last_updated': '2017-11-28T16:20:39.397961+00:00', 'attributes': {'attribution': 'Powered by Dark Sky', 'friendly_name': 'Precip Probability', 'unit_of_measurement': '%', 'icon': 'mdi:water-percent'}, 'state': '0', 'last_changed': '2017-11-28T16:20:39.397961+00:00'},
# Length of time that is too long...20 minutes
error_time = 60 * 20
# Exclude sensors
black_list = ['sensor.dark_sky_daily_high_temperature', 'sensor.dark_sky_daily_low_temperature', 'sensor.feels_like_temp', 'sensor.temp']
#Broad whitelist / String that must appear in sensor name. Use '' to disable
must_contain = 'temp'
#Return attributes
attributes = {'icon': 'mdi:alarm', 'friendly_name': 'Sensor Age', 'unit_of_measurement': 'sensors'}
class SensorAge(appapi.AppDaemon):
def initialize(self):
self.handle = self.run_every(self.age_check, self.datetime(), 5 * 60)
def age_check(self, kwargs):
state = self.get_state("sensor")
# self.log('Dump: {}'.format(state))
problems = []
for name, attrs in state.items():
if name in black_list:
continue
if (len(must_contain)) and (must_contain not in name):
continue
age = (self.datetime().replace(tzinfo=timezone.utc) - self.convert_utc(attrs['last_updated'])).seconds
if age > error_time:
try:
self.log("Sensor {}({}) is {}m behind".format(attrs['attributes']['friendly_name'], name, round(age/60)))
problems.append(attrs['attributes']['friendly_name'] + " ({}m)".format(round(age/60)))
except KeyError:
self.log("Sensor {} is {}m behind".format(name, round(age/60)))
problems.append(name + " ({}m)".format(round(age/60)))
attributes['problem_sensors'] = problems
self.set_state('sensor.sensorages', state=len(problems), attributes=attributes)
it also depends on how you have configured your device.
a good start would be to log the last updated and see what output that gives.
it will probably give a local time string and not an ISO 8601 UTC string.
so it will probably convert to an utc time without the timedifference.
so i think you want this:
age = self.datetime() - datetime.datetime.strptime(attrs[ālast_updatedā],"%Y/%m/%d %H:%M:%S")
where i did a guess for the timeformat you get from last updated, so you might need to change that.