Hi everybody,
this is also somewhat being discussed in this thread, but I would like to find an all-appdaemon solution for this (and in general).
Since I am still learning AppDaemon, I don’t quite understand how to do certain things, so it’d be really nice if you could help me write this app.
apps.yaml
entity_timer:
module: entity_timer
class: EntityTimer
# entity to observe
trigger_entity: vacuum.medusa
# which state triggers the entity
trigger_state: cleaning
# interval in which to update the sensor (in seconds)
interval: 30
# output current runtime to Home Assistant sensor
output: sensor.ad_medusa_times
So what this ought to do is do something when vacuum.medusa
changes it’s state to cleaning
. It should set the attribute started
to time.time()
when triggered. Then, every seconds, it should set the attribute running
to time.time() - <attribute.started>
.
I am trying to improve on my initial approach as I am writing this. I don’t know how to implement certain things, for example
- how to update the
running
attribute every seconds - how to determine that the entity is done without having to manually define all possible states that it could change to (in this case
idle
,docked
,error
, but depending on other trigger entities, there might be much different numbers of states, which one might not want to manually define)¹ - how to keep the
start_time
attribute, when we update the entity and write therunning_time
attribute²
entity_timer/entity_timer.py
import appdaemon.plugins.hass.hassapi as hass
import time
import datetime
class EntityTimer(hass.Hass):
def initialize(self):
trigger_entity = self.args['trigger_entity']
trigger_state = self.args['trigger_state']
interval = self.args['interval']
output = self.args['output']
# trigger when state changes to defined value
self.listen_state(self.my_action, trigger_entity, state=trigger_state)
def my_action(attribute, entity, kwargs, new, old, self):
# is there a way to use these variable generated in initialize(self) for this? They will always be the same, anyway
# But when I try using them without defining them here again, they will not be found
trigger_entity = self.args['trigger_entity']
trigger_state = self.args['trigger_state']
interval = self.args['interval']
output = self.args['output']
start_time = self.get_state(output, attribute="start_time")
current_state = self.get_state(trigger_entity)
# do this when entity state changes to defined value
if ( current_state == trigger_state ):
self.log("Started.")
_now = time.time() # current time as timestamp
self.set_state(output, state=trigger_state, attributes={"start_time": _jetzt, "running_time": 0, "stop_time": 0}
# this needs to be continued to
# calculate and write "running_time" every <interval> seconds
else:
pass
So this should simple write the current timestamp when the entity changes it’s state to whatever we defined in apps.yaml
. So far, so good.
As I wrote above, I re-wrote my original approach while typing here, so there might be an error, but I believe it should work like this.
¹ could this be achieved by putting this in place of pass
self.log("Not running.")
_now = time.time() # current time as timestamp
self.set_state(output, state=trigger_state, attributes={"start_time": <what goes here?), "running_time": <what goes here>, "stop_time": _now}
² I believe I have found the answer to this… Instead of just updating, for example, running_time
, we always have to update every single attribute when using self.set_state
.
I’ll keep working on this and updating the code here. However, since I have not yet found a solution to update the output every seconds, can you please help me out there?
Thank you for your help
UPDATE 1:
Added start_time = self.get_state(output, attribute="start_time")
so that we can calculate the time like this
running_time = (_now - start_time)
running_time = running-time.strftime("%H:%M:%S") # perhaps even just "%M:%S"
So then we can self.set_state(output, state=trigger_state, attributes={"start_time": start_time, "running_time": running_time, "stop_time": 0}
. So we should be able to query this in Home Assistant via {{ state_attr("sensor.ad_medusa_times", "running_time") }}
.