I am unable to get “run_in” working as I expect from the documentation.
As background, I have Appdaemon successfully running lights with different behaviours at different times of the day. I am moving on to having sensor modulating the brightness of the lights depending on presence of people. The modulation envelope has an up-ramp, a dwell time and a down ramp. I have cut the code down to the minimum which still produces the problem behaviour.
Also as background, I am a beginner with Python, struggling with args, kwargs, locals, globals, selfs, etc!
When I trigger the sensor I expect the up-ramp function to run 5 times over 5 minutes. The log shows that the code runs 5 times but it all happens within 1 second. I am hoping that this may be my error in using Python or understanding the callback function. Help would be appreciated.
My cutdown code and Appdaemon log follows:
import appdaemon.appapi as appapi
import datetime
class MotionLights(appapi.AppDaemon):
def initialize(self):
#initialise motion detection
self.log("***** initialise office sensor cb*****")
global on_ramp_et
on_ramp_et = 0
self.listen_state(self.motion, "sensor.aeotec_zw100_multisensor_6_burglar", old = "0", new = "8")
def motion(self, entity, attribute, old, new, kwargs):
global br_fac, on_ramp_dur, on_ramp_et
self.log("**mot A, on-ramp_et={}".format(on_ramp_et))
on_ramp_et = 0
self.on_ramp()
self.log("**mot B on-ramp_et={}".format(on_ramp_et))
def on_ramp(self):
#generates the leading edge of the brightness factor
global on_ramp_et
self.log("**on_ramp A on-ramp_et={}".format(on_ramp_et))
on_ramp_et += 1
if on_ramp_et < 5:
self.log("**on_ramp B on-ramp_et={}".format(on_ramp_et))
self.run_in(self.on_ramp(), 60)
return
Appdaemon.log
2017-12-16 14:28:08.031321 INFO office_lights: ***** initialise office sensor cb*****
2017-12-16 14:28:17.633232 INFO office_lights: **mot A, on-ramp_et=0
2017-12-16 14:28:17.640720 INFO office_lights: **on_ramp A on-ramp_et=0
2017-12-16 14:28:17.648811 INFO office_lights: **on_ramp B on-ramp_et=1
2017-12-16 14:28:17.663357 INFO office_lights: **on_ramp A on-ramp_et=1
2017-12-16 14:28:17.671847 INFO office_lights: **on_ramp B on-ramp_et=2
2017-12-16 14:28:17.684753 INFO office_lights: **on_ramp A on-ramp_et=2
2017-12-16 14:28:17.689744 INFO office_lights: **on_ramp B on-ramp_et=3
2017-12-16 14:28:17.694601 INFO office_lights: **on_ramp A on-ramp_et=3
2017-12-16 14:28:17.699500 INFO office_lights: **on_ramp B on-ramp_et=4
2017-12-16 14:28:17.705270 INFO office_lights: **on_ramp A on-ramp_et=4
2017-12-16 14:28:17.709970 INFO office_lights: **mot B on-ramp_et=5
like @gpbenton says:
a run_in expects a def with like:
def on_ramp(self, kwargs):
so probably you have an error in your errorlog.
it can be that because your callback isnt setup right that the function still is called, but without any delay.
Thanks gpbenton. I am so appreciative of your quick response and particularly your example.
You were spot on. That problem is solved. Clearly I need to do more work in learning Python.
I set it up as:
AppDaemon:
logfile: /config/appdaemon.log
errorfile: /config/appdaemon.err
As you know, when there are error messages in the error log there is a reference in the appdaemon log. The log I posted was unedited by me.
believe me, but 90% from the errors dont show up in the appdaemon.log
or at least not my errors.
and i expect at least an error that the expected amount of args is wrong.
if there is no error at all, i should test that and inform andrew, because its very unexpected behaviour.
Rene, I have rerun the test code as supplied at the start of this topic and got the following appdaemon log:
2017-12-17 14:47:51.012311 INFO /config/appdaemon/apps.yaml modified
2017-12-17 14:48:21.095249 INFO office_lights: **mot A, on-ramp_et=0
2017-12-17 14:48:21.102686 INFO office_lights: **on_ramp A on-ramp_et=0
2017-12-17 14:48:21.110105 INFO office_lights: **on_ramp B on-ramp_et=1
2017-12-17 14:48:21.118861 INFO office_lights: **on_ramp A on-ramp_et=1
2017-12-17 14:48:21.127673 INFO office_lights: **on_ramp B on-ramp_et=2
2017-12-17 14:48:21.136768 INFO office_lights: **on_ramp A on-ramp_et=2
2017-12-17 14:48:21.155071 INFO office_lights: **on_ramp B on-ramp_et=3
2017-12-17 14:48:21.165011 INFO office_lights: **on_ramp A on-ramp_et=3
2017-12-17 14:48:21.174826 INFO office_lights: **on_ramp B on-ramp_et=4
2017-12-17 14:48:21.185100 INFO office_lights: **on_ramp A on-ramp_et=4
2017-12-17 14:48:21.193633 INFO office_lights: **mot B on-ramp_et=5
2017-12-17 14:49:21.041951 WARNING Logged an error to /config/appdaemon.err
2017-12-17 14:49:21.043439 WARNING Logged an error to /config/appdaemon.err
2017-12-17 14:49:21.044914 WARNING Logged an error to /config/appdaemon.err
2017-12-17 14:49:21.046340 WARNING Logged an error to /config/appdaemon.err
The warnings at the end of the log came through some brief time after the other messages and I may have missed them previously or possibly dismissed them as not relevant to the problem at hand. It seems that the code with errors at three locations looped at sub-second speed five times before an error message was reported. To complete the record the error log is provided below.
2017-12-17 14:49:21.016467 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.017651 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.018413 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.019080 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.019644 WARNING Unexpected error in worker for App office_lights:
2017-12-17 14:49:21.020629 WARNING Unexpected error in worker for App office_lights:
2017-12-17 14:49:21.021649 WARNING Unexpected error in worker for App office_lights:
2017-12-17 14:49:21.022560 WARNING Unexpected error in worker for App office_lights:
2017-12-17 14:49:21.023577 WARNING Worker Ags: {‘name’: ‘office_lights’, ‘id’: UUID(‘7daa9a52-1e9c-4eac-a6a9-9f5016eb30fd’), ‘type’: ‘timer’, ‘function’: None, ‘kwargs’: {}}
2017-12-17 14:49:21.024648 WARNING Worker Ags: {‘name’: ‘office_lights’, ‘id’: UUID(‘7daa9a52-1e9c-4eac-a6a9-9f5016eb30fd’), ‘type’: ‘timer’, ‘function’: None, ‘kwargs’: {}}
2017-12-17 14:49:21.025657 WARNING Worker Ags: {‘name’: ‘office_lights’, ‘id’: UUID(‘7daa9a52-1e9c-4eac-a6a9-9f5016eb30fd’), ‘type’: ‘timer’, ‘function’: None, ‘kwargs’: {}}
2017-12-17 14:49:21.026650 WARNING Worker Ags: {‘name’: ‘office_lights’, ‘id’: UUID(‘7daa9a52-1e9c-4eac-a6a9-9f5016eb30fd’), ‘type’: ‘timer’, ‘function’: None, ‘kwargs’: {}}
2017-12-17 14:49:21.027513 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.028373 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.029248 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.030112 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.031915 WARNING Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 505, in worker
function(utils.sanitize_timer_kwargs(args[“kwargs”]))
TypeError: ‘NoneType’ object is not callable
2017-12-17 14:49:21.033754 WARNING Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 505, in worker
function(utils.sanitize_timer_kwargs(args["kwargs"]))
TypeError: 'NoneType' object is not callable
2017-12-17 14:49:21.036136 WARNING Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 505, in worker
function(utils.sanitize_timer_kwargs(args["kwargs"]))
TypeError: 'NoneType' object is not callable
2017-12-17 14:49:21.037645 WARNING Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 505, in worker
function(utils.sanitize_timer_kwargs(args["kwargs"]))
TypeError: 'NoneType' object is not callable
2017-12-17 14:49:21.038221 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.039168 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.040053 WARNING ------------------------------------------------------------
2017-12-17 14:49:21.040927 WARNING ------------------------------------------------------------
thanks. i suspected right, that it couldnt be without errors
i made mistakes like that more then enough
and allthough its not the most explainatory error, it still is an error, so you know you have something wrong.
and when there is an error, you always can suspect unexpected behavior
If you are starting appdaemon as a systemd service you can just set the logs to STDOUT and STDERR and view them with journalctl. I do something like this to get just the hass and appdeamon errors
journalctl -xef | sed 's/^.*mythtv.tschmidt.homeip.net //' | egrep 'appdaemon|hass'
The sed in the middle is just to get rid of the extraneous date/time and hostname fields at the beginning of the log to keep word wrap to a minimum. That way I can view all relevant logs in one window. And use tmux so you can have different consoles open.
i guess we all have our different ways.
i always have the log to the screen (i have a monitor on my pi) and view the error log every time i changed something in my apps or config.
tschmidty, Thanks for your tip. I recognise the command line as unix like and am aware of systemd services. Unfortunately, I am not only struggling with Python but also with Unix and flakey hardware. So after multiple attempts to get a functioning platform for Appdaemon I have converted to Hassio. Its working well and I seldom need a command line, but the downside is that I have lost insight into what is going on under the bonnet. I have saved your post for likely use down the track.
Rene, I’ve got lots to learn. At present I am using notepad++ with the NPPFTP plugin. This is currently my sole window into the Pi. Whenever I make a change to source code I press ctl+s to upload the changed file to the Pi and then double click on the log and error files to see the effect. Not perfect but it is working. Currently I rarely go near putty. The recent updates to home assistant and appdaemon have been marvellous for the access they provide to the Pi without command line requirements.