There were couple of bugfixes in this area recently - what version of AppDaemon are you using?
Im using the latest version of add on from frank that is 1.1.0.
What version of AppDaemon is showing in your logs?
you are trying to cancel a none existing timer and catch the error.
but the error catching doesnt work.
try changing your cancel_tracker to something like this:
def cancel_tracker (self):
self.message="cancelling tracker now"
logger(self)
if self.handler != None:
self.cancel_timer(self.handler)
self.handler =None
self.message="done"
logger(self)
else:
self.message='Tried to cancel a timer for {}, but none existed!'.format(self.tracker)
logger(self)
Ok will try this way and update accordingly. Hope it solves the oneshot error because it’s when im trying to use the oneshot im getting this error otherwise cancle tracker works fine.
Tried using if and else in cancel_tracker but still the keyerror is there the moment i add oneshot into state listener…
The updated cancel_tracker
def cancel_tracker (self):
self.message="cancelling tracker now"
logger(self)
if self.handler != None:
self.cancel_timer(self.handler)
self.handler =None
self.message="done"
logger(self)
else:
self.message='Tried to cancel a timer for {}, but none existed!'.format(self.tracker)
logger(self)
2018-05-21 21:34:05.408516 WARNING AppDaemon: ------------------------------------------------------------
2018-05-21 21:34:05.410545 WARNING AppDaemon: Unexpected error during state_update()
2018-05-21 21:34:05.412382 WARNING AppDaemon: ------------------------------------------------------------
2018-05-21 21:34:05.416629 WARNING AppDaemon: Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 2333, in state_update
self.process_state_change(namespace, data)
File "/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 2309, in process_state_change
removes.append({"name": callback["name"], "uuid": callback["kwargs"]["handle"]})
KeyError: 'handle'
as highlighted earlier, this keyerror is only apprearing when i try to add oneshot parameter into listen_state call as below
self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, oneshot=True, to="home")
2018-05-21 22:25:22.206591 INFO AppDaemon Version 3.0.1 starting
I have hassio appdaemon add on set to auto update and as stated earlier 1.1.0 is the latest one that Frenck has published yet.
so you say that this:
self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, to="home")
doesnt give an error, but this:
self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, oneshot=True, to="home")
does give an error?
then you might want to try this
self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, oneshot="True", to="home")
or this
self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, justaname=True, to="home")
maybe the word oneshot is used somewhere or the kwargs cant handle booleans, giving you an error
the part ‘to=“home”’ after the oneshot could also give trouble, so try to change that name or turn “to” and “oneshot” around.
oneshot=“True” doesnt help… same error
> self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, oneshot="True", to="home")
however
> self.listen_state(self.traveling_towards, self.home_towards, old="off", new="on", duration=60, somename=True, to="home")
doesn’t give error as expected cause it treats it as kwargs… but doesn’t solve the problem as well
that means looks like kwargs accepts or supports booleans
hmm, sorry, i didnt even know about the oneshot option, i did think it was a kwarg from you
but i think that using it in your case in the way you do will not result in what you want anyway.
you have a listen_state in your initialise.
using one_shot results in that the listen_state gets canceled after you have 1 callback.
so from that moment on that listen_state isnt working anymore untill you restart the app.
you want the listen_state to function untill a callback is generated, then hold for a while untill another state is reached (you dont want to restart the app every day)
so in your case i would create an input_boolean that you use as constraint for the listen_state and that you set to off in the towards_callback.
at some point (when the person is home or when its 0:00 you set the boolean to on again. and then the listen_state starts listening again.
understood, thanks for the explanation. yes i don’t want to restart the app everyday. I’m relatively new to both HA as well Python and even newer in AD. still trying to learn it’s bits and pieces putting some efforts and spending time as and when i get a chance.
though I understand the logic behind using the input_boolean, I, personally will prefer to avoid it and use class level variables such as other boolean Flag to control the subsequent callbacks to my handler…so that everything resides inside 1 module in terms of programming logic, of course all devices are there in HA only.
any other thoughts on how can i optimize this code, i know it’s messy at the moment as i’m still doing the checks and logging to fine tune the logic…
any feedback and suggestions are most welcome!
i wouldnt point 4 listen_states towards 1 callback if you want different actions for the listen_states anyway
so instead of 1 callback with ifstatements i would just create 4 callbacks.
i try to create booleans or sensors for all variables i use in AD.
the reason for that is that you can easy see the state from the app without a lot of logging and looking through logfiles.
creating a boolean that works as a constraint voor the listen_state has the advantage that you also have a manual override option.
i see this and then i think: why this way?
> if old == "home" and new == "not_home":
> self._left_home = True
> elif old == self.work_zone and new == "not_home":
> self._left_work = True
> elif old == "not_home" and new == self.work_zone:
> self._reached_work = True
> elif old == "not_home" and new == "home":
> self._reached_home = True
if the devicetracker you use isnt giving enough states i can understand something like that, but i would then do it like:
> device, entity_id = self.split_entity(entity)
> if old == "home" and new == "not_home":
> self.set_state("sensor." + entity_id, state = "left_home")
> elif old == self.work_zone and new == "not_home":
> self.set_state("sensor." + entity_id, state = "left_work")
> elif old == "not_home" and new == self.work_zone:
> self.set_state("sensor." + entity_id, state = "at_work")
> elif old == "not_home" and new == "home":
> self.set_state("sensor." + entity_id, state = "home")
now you have 1 variabele that tells the same as your 4 variables, you can see it in your frontend and you can use it in any other app.
Great suggestions… Let me rework on this. Absolutely agree that having booleans and sensor in HA GUI will make it much more visible than the console logs and provide greater flexibility as well in terms of manual control in case something needs a overriding value. I can then also group all related entities into a group which can then show all activities happening behind the scene on screen in a fluid manner.