AppDaemon Q&A

Is it possible to get this line in the log file

2016-12-13 10:43:56.009874 WARNING Logged an error to /var/tmp/ha_apps_error.log

to print out the app that the error occurred in?

cant you see in the log which app gives the error?

I think the log just tells you there was an error and to look in the .err file.

yeah oke, but if you have an error in your error log, you need to check that out anyway.
so then you will know where the problem is.

but i think that @gpbenton has a point.
in the errorlog it would be nice to see in a second from which app the error originates.

The app is automatically logged in the error file - just go look there.

The way this is meant to work is as follows:

  • System reboots
  • HA and AppDaemon Come Up
  • AppDaemon re-runs the initialize() function for every app
  • Your app needs to have the smarts to figure out what to do in terms of re-registering callbacks etc in the initialize() fuinction
1 Like

i mean with errors like this:

2016-12-09 12:51:40.011471 WARNING ------------------------------------------------------------
2016-12-09 12:51:40.012435 WARNING Unexpected error during do_every_second()
2016-12-09 12:51:40.013073 WARNING ------------------------------------------------------------
2016-12-09 12:51:40.014500 WARNING Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 374, in do_every_second
    exec_schedule(name, entry, conf.schedule[name][entry])
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 278, in exec_schedule
    dispatch_worker(name, {"name": name, "id": conf.objects[name]["id"], "type": "timer", "function": args["callback"], "kwargs": args["kwargs"], })
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 245, in dispatch_worker
    if not check_constraint(arg, args["kwargs"][arg]):
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 209, in check_constraint
    if today_is_constrained(value):
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 255, in today_is_constrained
    daylist = [ha.day_of_week(day) for day in days.split(",")]
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 255, in <listcomp>
    daylist = [ha.day_of_week(day) for day in days.split(",")]
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/homeassistant.py", line 58, in day_of_week
    return days[day]
KeyError: '0'

2016-12-09 12:51:40.015788 WARNING ------------------------------------------------------------
2016-12-11 17:08:20.028918 WARNING ------------------------------------------------------------
2016-12-11 17:08:20.036432 WARNING Unexpected error:
2016-12-11 17:08:20.055571 WARNING ------------------------------------------------------------
2016-12-11 17:08:20.214320 WARNING Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 415, in worker
    function(entity, attr, old_state, new_state, ha.sanitize_state_kwargs(args["kwargs"]))
  File "/home/pi/.homeassistant/apps/motion_lights.py", line 59, in motion
    self.handle = self.run_in(self.light_off, delay)
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/appapi.py", line 326, in run_in
    handle = ha.insert_schedule(name, exec_time, callback, False, None, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/appdaemon/homeassistant.py", line 187, in insert_schedule
    conf.schedule[name][handle] = {"name": name, "id": conf.objects[name]["id"], "callback": callback, "timestamp": ts, "interval": interval, "basetime": utc, "repeat": repeat, "offset": c_offset, "type": type, "kwargs": kwargs}
KeyError: 'bewegingssensorkeuken'

2016-12-11 17:08:20.220857 WARNING ------------------------------------------------------------

i have to find the app that causes the error myself.
it would be nice if it didnt say unexpected error, but unexpected error in app…
if it is like the first error that would really be helpfull

if it is possible off course.

I would like to hijack this thread for a moment and ask what I hope is a simple python question. Below is my callback function for input sliders. Right now all my input sliders are tied with alarm clock systems. Everything works fine (to my suprise) down to the last two lines. I am trying to parse out the entity so I can tell which room was associated with the input slider triggering the callback. Apparently python uses find to do string processing. I am trying to find the first period in the entity name (should be the period between the device and the device name). I’m not getting any errors, just no output from the last line. Not even the “room=”.

  def alarm_time_change(self, entity, attribute, old, new, kwargs):
     self.log("In Alarm_time_change")
     self.log("entity={}".format(entity))
     self.log("new state={}".format(new))
     room=entity.find(".")
     print("room={}".format(room))

I now return you to your current thread already in progress. :slight_smile:

I needed to be more specific in my request - I needed to find the instance of the app that was causing the error.

In the error log was

2016-12-13 16:32:21.148627 WARNING ------------------------------------------------------------
2016-12-13 16:32:21.160181 WARNING Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.4/site-packages/appdaemon/appdaemon.py", line 418, in worker
    function(ha.sanitize_timer_kwargs(args["kwargs"]))
  File "/home/homeassistant/.homeassistant/apps/etrv.py", line 64, in target_resend
    current_temp = float(current_temp_str)
ValueError: could not convert string to float: 'unknown'

2016-12-13 16:32:21.167663 WARNING ------------------------------------------------------------

Which said the problem was in etrv.py. The trouble was I have two instances, one for each of my trvs, and the error kept being logged immediately after some debug from one instance, so I thought the error was coming from that instance. In fact it was from the other instance, and it took a while too find.

Which made me late. Which made my previous request rather terse. Sorry. :disappointed:

to split up devices and entities Andrew provided a function for us.

device, entity_name = self.split_entity(entity)

and try to keep it with self.log in stead off print :wink:

that’s what I get for copying the documentation without thinking… LOL

1 Like

ok, this may be another instance of me not seeing the forest for the trees, but I’m having trouble with this section of code not pre-processing correctly. I am getting an error that name ‘alarms’ is not defined. Keep in mind I’m just learning. What I’m trying to do is I have 4 or 5 rooms and in HA I have an two sliders to set the hour and minute. I wanted to use a list to store the name,time of each room,alarm time combination. My initial efforts were hard coded and worked fine. Now, I’m handling the sliders in a callback farther down and want to start updating the list with the new values. So I’m making the list “alarms” global so that it can be seen in both the initialize function and the callback function. But as soon as I exit the editor, the message log sends me to the error log looking at this error.

Question 1: How do make a global list and reference it from functions below where it was defined.
Question 2: Am I approaching this the wrong way entirely?
I would like question 1 answered even if the answer to #2 is I’m doing it wrong, so that I can learn how to do it in case I ever need it.

class testclass(appapi.AppDaemon):
  alarms = ["0"]

  def initialize(self):
     global alarms
     self.log("starting testapp")
     self.listen_state(self.alarm_time_change,"input_slider")
     roomalarm=[]
     room="MBR"
     time="5:30"
     roomalarm=[room,time]
     alarms=alarms+[roomalarm]

that’s where self.var comes in most off the times in my case`.

but i guess you try to count how many times the alarm is triggered.
and that wouldn’t work like this anyway, because the initialize is called only 1 time after starting the app.

if you use:

class testclass(appapi.AppDaemon):


  def initialize(self):
     self.alarms = [] #for a list
    self.alarms2 = {} #for a dictionairy

you can call self.alarms in the entire class.

and i think it is wise to read up about lists and dictionaries in python.

Hi Rene -

It is a work in progress :wink: The idea is that any app errors should come out in the error log. If it is in the main log it is because I didn’t check something right or I have a problem with my code - that is the intention anyway.

the errors show up in the error log. thats oke.
but most of the time i have to start searching from that moment on.
i had a few keyerrors coming by.
they where set in a complicated initialize.
and all they show was a key error in do_every_second.
before i had figured out what caused the problem there were 2 days gone :wink:

Let me know which AppDaemon call had the problem and I can add some checking so you get a more informative error next time :slight_smile:

in this initialize i had 1 line in the configfile where there was no constaintdays set.


class switches(appapi.AppDaemon):

  def initialize(self):
    file_name = self.args["settingsfile"]
    sunriseon = False
    sunseton = False
    sunriseoff = False
    sunsetoff = False
    try:
      settings_file = open(file_name, "r")
      for line in settings_file:
        splitline = line.split(";")
        if not "#" in splitline[0]:
          switch = splitline[0]
          constraindays = splitline[3].rstrip('\n')
          sunseton = False
          sunriseon = False
          sunriseoff = False
          sunsetoff = False
          ontime = ""
          if splitline[1]!="":
            if "sunset" in splitline[1]:
              sunsetparts =splitline[1].split(":")
              offset1 = int(sunsetparts[1])
              sunseton = True
            elif "sunrise" in splitline[1]:
              sunsetparts =splitline[1].split(":")
              offset1 = int(sunsetparts[1])
              sunriseon = True
            else:
              ontime = self.parse_time(splitline[1])             
          else:
            ontime = ""
          if splitline[2]!="":
            if "sunset" in splitline[2]:
              sunsetparts =splitline[2].split(":")
              offset2 = int(sunsetparts[1])
              sunsetoff = True
            elif "sunrise" in splitline[2]:
              sunsetparts =splitline[2].split(":")
              offset2 = int(sunsetparts[1])
              sunriseoff = True
            else:
              offtime = self.parse_time(splitline[2])
          else:
            offtime = ""

          if sunriseon:
            self.log(switch + " tijd: sunrise " + str(offset1) + " dag: " + constraindays + " aan")
            self.run_at_sunrise(self.set_lights_on,offset=offset1,constrain_days=constraindays,switch=switch)
          if sunriseoff:
            self.log(switch + " tijd: sunrise " + str(offset2) + " dag: " + constraindays + " uit")
            self.run_at_sunrise(self.set_lights_off,offset=offset2,constrain_days=constraindays,switch=switch)
          if sunseton:
            self.log(switch + " tijd: sunset " + str(offset1) + " dag: " + constraindays + " aan")
            self.run_at_sunset(self.set_lights_on,offset=offset1,constrain_days=constraindays,switch=switch)
          if sunsetoff:
            self.log(switch + " tijd: sunset " + str(offset2) + " dag: " + constraindays + " uit")
            self.run_at_sunset(self.set_lights_off,offset=offset2,constrain_days=constraindays,switch=switch)            
          if type(ontime) is datetime.time:
            self.log(switch + " tijd: " + ontime.strftime("%H:%M:%S") + " dag: " + constraindays + " aan")
            self.run_daily(self.set_lights_on,ontime,constrain_days=constraindays,switch=switch)
          if type(offtime) is datetime.time:
            self.log(switch + " tijd: " + offtime.strftime("%H:%M:%S") + " dag: " + constraindays + " uit")
            self.run_daily(self.set_lights_off,offtime,constrain_days=constraindays,switch=switch)            
    except:
      self.log( "fout in lezen van verlichtingsfile")

it made me crazy before i found it out.

Hi Rene!

Just a suggestion of a more condensed way of achieving

In my scheduling I’ve set it up like this:

config: time = 06:00:00 on, sunrise+00:45:00 off, sunset-00:45:00 on, 23:00:00 off

  def initialize(self):
    self.populate_schedules()
    self.schedule_callback()

  def populate_schedules(self):
      for schedule in self.args["time"].split(", "):
        time, action = schedule.split(" ")
        self.schedules[time] = action

  def schedule_callback(self):
    for time, action in self.schedules.items():
      time = self.parse_time(time)
      self.run_daily(self.run_daily_callback, time, action = action)

  def run_daily_callback(self, kwargs):
    for light in self.lights:
      self.call_service("light/turn_"+action, entity_id = light)

I think this would simplify your initialisation a lot. I have removed all but the core that was relevant in my example to you.

you have a few problems in that.

  1. your sunset/sunrise are wrong if you havent initialized your app for a longer period of time.
  2. you have no possibility to contrain a single light.
  3. i dont see self.lights get filled.
  4. the light get all set at the same time.

take a look at my schedule:

#verlichting;#aan;#uit;#dagen
################################ buitenverlichting ##################################;;;
switch.waterloop;sunset:10;00:00:05;mon,tue,wed,thu,fri
switch.waterloop;sunset:10;01:45:00;sat,sun
switch.jacuzzi;sunset:20;00:00:10;mon,tue,wed,thu,fri
switch.jacuzzi;sunset:20;01:45:05;sat,sun
switch.aquariums;;01:30:00;mon,tue,wed,thu,fri,sat,sun
################################ leefruimtes ##################################;;;
switch.hboog;sunset:-3600;;mon,tue,wed,thu,fri,sat,sun
switch.hboog;;20:25:00;fri,sat
switch.hboog;00:30:00;;sat,sun
switch.hbank;sunset:-3605;;mon,tue,wed,thu,fri,sat,sun
switch.hbank;;20:25:05;fri,sat
switch.hbank;00:30:05;;sat,sun
switch.hrozenhoek;sunset:-3610;;mon,tue,wed,thu,fri,sat,sun
switch.hrozenhoek;;20:25:10;fri,sat
switch.hrozenhoek;00:30:10;;sat,sun
switch.eraamhoek;sunset:-3615;;mon,tue,wed,thu,fri,sat,sun
switch.eraamhoek;;20:25:15;fri,sat
switch.eraamhoek;00:30:15;;sat,sun
switch.epchoek;sunset:-3620;;mon,tue,wed,thu,fri,sat,sun
switch.epchoek;;20:25:20;fri,sat
switch.epchoek;00:30:20;;sat,sun
switch.ewandmeubel;sunset:-3625;;mon,tue,wed,thu,fri,sat,sun
switch.ewandmeubel;;20:25:25;fri,sat
switch.ewandmeubel;00:30:25;;sat,sun
switch.kachel_9_1;sunset:-3630;;mon,tue,wed,thu,fri,sat,sun
switch.kachel_9_1;;20:25:30;fri,sat
switch.kachel_9_1;00:30:30;;sat,sun
################################ slaapkamer ##################################;;;
switch.dekkieolinde;23:30:00;07:00:00;mon,tue,wed,thu,sun
switch.dekkieolinde;;07:00:00;fri,sat
switch.dekkieolinde;00:30:00;;sat,sun
################################ weergave switches ##################################;;;
input_boolean.donkeredag;;sunset:-3600;mon,tue,wed,thu,fri,sat,sun
input_boolean.avondverlichting;sunset:-3600;;mon,tue,wed,thu,fri,sat,sun
switch.kerstboom;sunrise:10;;mon,tue,wed,thu,fri,sat,sun
switch.kerstboom;;20:25:00;fri,sat

and you can read that a lot better if you use a spreadsheet.

Thanks for the tip on the problem with sunset/sunrise, my thought was on how Openhab was working, will look into solving that further down the line.

It was mostly suggestions to simplify that large stack of ifs at the end taken directly from my code, changes would be necessary. To add the constraints wouldn’t be much work.

I can do a full third party post with my implementation if you want that instead. Didn’t want to bloat the post with unnecessary details.

Anyway, my intent was to give you a suggestion on how to make the code easier to debug by minimising duplication, instead I got some ideas on how to solve future problems for me. Look how that turned out, thanks! :wink:

/R