Some listen_state events getting missed in ad4

Hey all wondering if anyone has some advice. After updating to app daemon 4 I have noticed some listen_state events getting missed. Namely those in a presence detection system I have. I have a system that listens for changes in life 360 integrations. This system has worked almost perfectly for about a year and I have not changed anything however after I updated I would say 50% of the state changes now get missed. I believe there might be some kind of timing/race condition issue going on as it seems mostly to happen when two people arrive home at or close to the same time. I have tried to put some time.sleep functions in to see if that would help but it doesn’t seem to. I can confirm the 360 tracking is working as expected as that always updates just app daemon doesn’t always pick it up. Any ideas?

Can you please share the code? You get any errors in the log?

No problem at all. And no I do not get any errors in the log what so ever. So you can see in the code below I set up a few listen_states that listen to device trackers and when those change it should call the callback there but like I said the callback never gets called. I think this happens when two people arrive home and the device trackers updates at almost the same time AD doesn’t get called twice. But whats weird is this code has not been updated in like I said about a year and the only change I have made was to update to AD4 which is when the issue started.

class PresenceTrigger(hass.Hass):
    """
    Class to call input bools based on presence detection.
    """
    def initialize(self):
        """
        Main initializer.
        """
        self.utils = self.get_app('utils')
        self.get_global_dicts()
        for key, value in STATE_ENTITIES.items():
            self.listen_state(self.presence_trigger_cb, entity=value, 
                              person=key)

    def get_global_dicts(self):
        """
        Method to get the track dict information as expected.
        """
        tracker_dict_list = self.utils.get_tracker_dict_list()
        for tracker in tracker_dict_list:
            STATE_ENTITIES[tracker['name']] = tracker['status_dropdown']

    def presence_trigger_cb(self, *args, **kwargs):
        """
        Method to run when presence changes.
        """
        self.turn_off('input_boolean.home')
        self.turn_off('input_boolean.away')
        self.turn_off('input_boolean.stay')
        presence_state = self.get_state('input_boolean.presence_detection')
        if presence_state == 'on':
            person = args[-1]['person']
            should_track = self.utils.get_should_track_state(person)
            if should_track == 'off':
                self.log('Tracking for {0} if off skipping presence '
                         'trigger.'.format(person))
                return
            value = self.get_state(STATE_ENTITIES[person])

            # Home.
            if value == 'home':
                self.turn_on('input_boolean.home')

            # Away.
            if value == 'away':
                if self.utils.anyone_home():
                    if self.now_is_between('2:30:00', '5:30:00'):
                        self.log('Someone is home and it\'s late performing night routine.')
                        self.utils.lock_all_doors()
                        home_mode = self.get_state('input_select.house_mode')
                        if home_mode != 'Night':
                            self.select_option('input_select.house_mode', 'Night')
                    else:
                        self.log('Someone is home performing stay routine.')
                        self.turn_on('input_boolean.stay')
                if self.utils.noone_home():
                    self.log('No one is home performing away routine.')
                    self.turn_on('input_boolean.away')
        else:
            self.log('Presence detection currently turned off.')

Anyone have some thoughts on this?

Can you try putting a log at the beginning of the presence_trigger_cb method to see if the app gets there or it doesn’t even trigger the callback?

That’s exactly what I tried it doesn’t trigger the callback. When there are consecutive calls close together it seems like one just gets missed.

Could you share your appdaemon.yaml as well as all the logs from appdaemon addon until the apps are initialized? Maybe we are missing something in there.

Here is the log:

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 00-banner.sh: executing... 
-----------------------------------------------------------
 Hass.io Add-on: AppDaemon 4
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.1.2
 You are running the latest version of this add-on.
 System: HassOS 3.9  (amd64 / qemux86-64)
 Home Assistant version: 0.105.1
 Supervisor version: 198
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
[cont-init.d] 00-banner.sh: exited 0.
[cont-init.d] 01-log-level.sh: executing... 
[cont-init.d] 01-log-level.sh: exited 0.
[cont-init.d] appdaemon.sh: executing... 
[cont-init.d] appdaemon.sh: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[10:50:47] INFO: Starting AppDaemon...
2020-02-18 10:50:48.810544 INFO AppDaemon: AppDaemon Version 4.0.1 starting
2020-02-18 10:50:48.810727 INFO AppDaemon: Python version is 3.8.1
2020-02-18 10:50:48.811082 INFO AppDaemon: Configuration read from: /config/appdaemon/appdaemon.yaml
2020-02-18 10:50:48.811280 INFO AppDaemon: Added log: AppDaemon
2020-02-18 10:50:48.811465 INFO AppDaemon: Added log: Error
2020-02-18 10:50:48.811562 INFO AppDaemon: Added log: Access
2020-02-18 10:50:48.811653 INFO AppDaemon: Added log: Diag
2020-02-18 10:50:48.829171 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2020-02-18 10:50:48.861310 INFO HASS: HASS Plugin Initializing
2020-02-18 10:50:48.861510 INFO HASS: HASS Plugin initialization complete
2020-02-18 10:50:48.861789 INFO AppDaemon: Initializing HTTP
2020-02-18 10:50:48.862047 INFO AppDaemon: Using 'ws' for event stream
2020-02-18 10:50:48.870495 INFO AppDaemon: Starting API
2020-02-18 10:50:48.873758 INFO AppDaemon: Starting Admin Interface
2020-02-18 10:50:48.874001 INFO AppDaemon: Starting Dashboards
2020-02-18 10:50:48.883773 INFO HASS: Connected to Home Assistant 0.105.1
2020-02-18 10:50:48.969377 INFO AppDaemon: App 'alarm_clock' added
2020-02-18 10:50:48.970018 INFO AppDaemon: App 'auto_night_lock' added
2020-02-18 10:50:48.970477 INFO AppDaemon: App 'away_routine' added
2020-02-18 10:50:48.975835 INFO AppDaemon: App 'fan_cooling' added
2020-02-18 10:50:48.976433 INFO AppDaemon: App 'good_morning_routine' added
2020-02-18 10:50:48.976868 INFO AppDaemon: App 'good_night_routine' added
2020-02-18 10:50:48.977241 INFO AppDaemon: App 'home_routine' added
2020-02-18 10:50:48.977619 INFO AppDaemon: App 'interior_door_notifier' added
2020-02-18 10:50:48.978022 INFO AppDaemon: App 'kids_good_morning_routine' added
2020-02-18 10:50:48.978404 INFO AppDaemon: App 'kids_good_night_routine' added
2020-02-18 10:50:48.978825 INFO AppDaemon: App 'kids_inactive_lights' added
2020-02-18 10:50:48.979189 INFO AppDaemon: App 'kids_weekday_evening' added
2020-02-18 10:50:48.979574 INFO AppDaemon: App 'konnected_alarm' added
2020-02-18 10:50:48.979953 INFO AppDaemon: App 'Occupancy Simulator' added
2020-02-18 10:50:48.980675 INFO AppDaemon: App 'open_zone' added
2020-02-18 10:50:48.981056 INFO AppDaemon: App 'pantry_light' added
2020-02-18 10:50:48.981422 INFO AppDaemon: App 'presence_trigger' added
2020-02-18 10:50:48.981835 INFO AppDaemon: App 'ring_doorbell' added
2020-02-18 10:50:48.982203 INFO AppDaemon: App 'set_person_state' added
2020-02-18 10:50:48.982607 INFO AppDaemon: App 'stay_routine' added
2020-02-18 10:50:48.982978 INFO AppDaemon: App 'test_routine' added
2020-02-18 10:50:48.983346 INFO AppDaemon: App 'theater_fan_routine' added
2020-02-18 10:50:48.983750 INFO AppDaemon: App 'theater_lights_routine' added
2020-02-18 10:50:48.984061 INFO AppDaemon: App 'timed_announcements' added
2020-02-18 10:50:48.984422 INFO AppDaemon: App 'timed_routines' added
2020-02-18 10:50:48.984745 INFO AppDaemon: App 'timed_lights' added
2020-02-18 10:50:48.985060 INFO AppDaemon: App 'update_blink_images' added
2020-02-18 10:50:48.985375 INFO AppDaemon: App 'welcome_message' added
2020-02-18 10:50:48.985749 INFO AppDaemon: App 'just_arrived_var' added
2020-02-18 10:50:48.986130 INFO AppDaemon: App 'sound' added
2020-02-18 10:50:48.986564 INFO AppDaemon: App 'utils' added
2020-02-18 10:50:48.987271 INFO AppDaemon: Found 31 total apps
2020-02-18 10:50:48.987906 INFO AppDaemon: Starting Apps with 31 workers and 31 pins
2020-02-18 10:50:48.996554 INFO AppDaemon: Running on port 5050
2020-02-18 10:50:49.019443 INFO HASS: Evaluating startup conditions
2020-02-18 10:50:49.040437 INFO AppDaemon: Got initial state from namespace default
2020-02-18 10:52:29.130465 INFO AppDaemon: Scheduler running in realtime
2020-02-18 10:52:29.135901 INFO AppDaemon: Adding /config/appdaemon/apps to module import path
2020-02-18 10:52:29.137027 INFO AppDaemon: Adding /config/appdaemon/apps/app_configs to module import path
2020-02-18 10:52:29.165739 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/alarm_clock.py
2020-02-18 10:52:29.169318 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/kids_inactive_lights.py
2020-02-18 10:52:29.170523 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/sprinkler_routine.py - ignoring
2020-02-18 10:52:29.171336 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/roomba.py - ignoring
2020-02-18 10:52:29.172102 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/kids_weekday_evening.py
2020-02-18 10:52:29.173139 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/update_blink_images.py
2020-02-18 10:52:29.174063 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/occusim.py
2020-02-18 10:52:29.175098 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/timed_routines.py
2020-02-18 10:52:29.176075 INFO AppDaemon: Loading Global Module: /config/appdaemon/apps/globals.py
2020-02-18 10:52:29.177079 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/timed_scenes.py - ignoring
2020-02-18 10:52:29.177837 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/just_arrived_var.py
2020-02-18 10:52:29.178837 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/auto_night_lock.py
2020-02-18 10:52:29.179854 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/welcome_message.py
2020-02-18 10:52:29.180851 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/good_night_routine.py
2020-02-18 10:52:29.181838 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/kids_good_night_routine.py
2020-02-18 10:52:29.182833 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/theater_fan_routine.py
2020-02-18 10:52:29.183734 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/stay_routine.py
2020-02-18 10:52:29.184702 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/sound.py
2020-02-18 10:52:29.185740 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/away_routine.py
2020-02-18 10:52:29.186734 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/konnected_alarm.py
2020-02-18 10:52:29.187696 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/pantry_light.py
2020-02-18 10:52:29.188597 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/presence_trigger.py
2020-02-18 10:52:29.190226 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/test_routine.py
2020-02-18 10:52:29.191278 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/interior_door_notifier.py
2020-02-18 10:52:29.192187 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/good_morning_routine.py
2020-02-18 10:52:29.193130 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/home_routine.py
2020-02-18 10:52:29.194122 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/open_zone.py
2020-02-18 10:52:29.195154 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/utils.py
2020-02-18 10:50:51.085529 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/fan_cooling.py
2020-02-18 10:50:51.087053 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/kids_good_morning_routine.py
2020-02-18 10:50:51.088706 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/timed_lights.py
2020-02-18 10:50:51.090073 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/theater_lights_routine.py
2020-02-18 10:50:51.091589 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/front_door_cam_stream.py - ignoring
2020-02-18 10:50:51.092342 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/set_person_state.py
2020-02-18 10:50:51.093832 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/timed_announcements.py
2020-02-18 10:50:51.096601 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/ring_doorbell.py
2020-02-18 10:50:51.102212 INFO AppDaemon: Initializing app kids_inactive_lights using class KidsInactiveLights from module kids_inactive_lights
2020-02-18 10:50:51.104633 INFO AppDaemon: Initializing app Occupancy Simulator using class OccuSim from module occusim
2020-02-18 10:50:51.107971 INFO AppDaemon: Initializing app pantry_light using class PantryLight from module pantry_light
2020-02-18 10:50:51.109041 INFO AppDaemon: Initializing app theater_fan_routine using class TheaterFanRoutine from module theater_fan_routine
2020-02-18 10:50:51.110041 INFO AppDaemon: Initializing app theater_lights_routine using class TheaterLightsRoutine from module theater_lights_routine
2020-02-18 10:50:51.111536 INFO AppDaemon: Initializing app timed_lights using class TimedLights from module timed_lights
2020-02-18 10:50:51.112996 INFO AppDaemon: Initializing app sound using class Sound from module sound
2020-02-18 10:50:51.114258 INFO AppDaemon: Initializing app utils using class utils from module utils
2020-02-18 10:50:51.115491 INFO AppDaemon: Initializing app alarm_clock using class AlarmClock from module alarm_clock
2020-02-18 10:50:51.116418 INFO AppDaemon: Initializing app auto_night_lock using class AutoNightLock from module auto_night_lock
2020-02-18 10:50:51.117434 INFO AppDaemon: Initializing app away_routine using class AwayRoutine from module away_routine
2020-02-18 10:50:51.118485 INFO AppDaemon: Initializing app fan_cooling using class FanCooling from module fan_cooling
2020-02-18 10:50:51.119488 INFO AppDaemon: Initializing app good_morning_routine using class GoodMorningRoutine from module good_morning_routine
2020-02-18 10:50:51.120496 INFO AppDaemon: Initializing app good_night_routine using class GoodNightRoutine from module good_night_routine
2020-02-18 10:50:51.121474 INFO AppDaemon: Initializing app home_routine using class HomeRoutine from module home_routine
2020-02-18 10:50:51.122526 INFO AppDaemon: Initializing app interior_door_notifier using class InteriorDoorNotifier from module interior_door_notifier
2020-02-18 10:50:51.123595 INFO AppDaemon: Initializing app kids_good_morning_routine using class KidsGoodMorningRoutine from module kids_good_morning_routine
2020-02-18 10:50:51.124659 INFO AppDaemon: Initializing app kids_good_night_routine using class KidsGoodNightRoutine from module kids_good_night_routine
2020-02-18 10:50:51.125685 INFO AppDaemon: Initializing app kids_weekday_evening using class KidsWeekdayEvening from module kids_weekday_evening
2020-02-18 10:50:51.126522 INFO AppDaemon: Initializing app konnected_alarm using class KonnectedAlarm from module konnected_alarm
2020-02-18 10:50:51.127532 INFO AppDaemon: Initializing app open_zone using class OpenZone from module open_zone
2020-02-18 10:50:51.128652 INFO AppDaemon: Initializing app presence_trigger using class PresenceTrigger from module presence_trigger
2020-02-18 10:50:51.129677 INFO AppDaemon: Initializing app ring_doorbell using class RingDoorbell from module ring_doorbell
2020-02-18 10:50:51.130792 INFO AppDaemon: Initializing app set_person_state using class SetPersonState from module set_person_state
2020-02-18 10:50:51.131964 INFO AppDaemon: Initializing app stay_routine using class StayRoutine from module stay_routine
2020-02-18 10:50:51.132992 INFO AppDaemon: Initializing app test_routine using class TestRoutine from module test_routine
2020-02-18 10:50:51.134016 INFO AppDaemon: Initializing app timed_announcements using class TimedAnnouncements from module timed_announcements
2020-02-18 10:50:51.135088 INFO AppDaemon: Initializing app timed_routines using class TimedRoutines from module timed_routines
2020-02-18 10:50:51.136042 INFO AppDaemon: Initializing app update_blink_images using class UpdateBlinkImages from module update_blink_images
2020-02-18 10:50:51.137004 INFO AppDaemon: Initializing app welcome_message using class WelcomeMessage from module welcome_message
2020-02-18 10:50:51.138107 INFO AppDaemon: Initializing app just_arrived_var using class JustArrivedVar from module just_arrived_var
2020-02-18 10:50:51.451100 INFO AppDaemon: App initialization complete

Interesting… Logs and configuration are correct. I know that you said that the code worked before but why are you adding the value variable (initialize function) as a entity and not the key?

Shouldn’t it be like this?

for key, value in STATE_ENTITIES.items():
    self.listen_state(self.presence_trigger_cb, entity=key, person=key)

You are passing now the value of the state (tracker['status_dropdown']) instead of the entityt which is the person.

I will double check the code but no I do not believe there is an issue. In this instance the “tracker” is a dictionary with a key of “name” which is the name of a person and a key “status dropdown” which is the entity (input_select._status_dropdown). This dictionary comes from a list of dictionaries. One for each person in the home and their corresponding entities that all make the system function (the persons name, a person entity, device tracker entity, status drop down entity, and an input boolean that is used to check if the person should be tracked). See the example below.

personA_presence_dict = {'name':'PersonA', 
                        'device_tracker':'device_tracker.life360_personA',
                        'person_tracker':'person.personA',
                        'status_dropdown':'input_select.personA_status_dropdown',
                        'tracker':'input_boolean.track_personA'}

personB_presence_dict = {'name':'PersonB', 
                        'device_tracker':'device_tracker.life360_personB',
                        'person_tracker':'person.personB',
                        'status_dropdown':'input_select.personB_status_dropdown',
                        'tracker':'input_boolean.track_personB'}

presence_list = [personA_presence_dict, personB_presence_dict]

Ah yes, I see, I thought it was the state. I don’t see any other problem on it, sorry :confused:

How does the input_select for the status_dropdown change? Do you have another app for this?

So I am thinking (only thing I can see) is that life 360 might update the status of a device tracker for two different people at the same time (or super close to it) and in doing so AD just doesn’t see both events. I am going to try and change the life360 integration “interval_seconds” setting for each person to be a different number of seconds. Perhaps that will cause each update call to be spaced enough that AD will pick it up. That’s about the last of my ideas here. I will update with the results.

From your app code I see that you are not listening to the Life360 state changes, you are listening for the state changes of the input_select._status_dropdown. So how do you set these input_selects and why don’t you directly listen to the life360 device tracker states?

1 Like

You are correct I am listening to the status drop down and those updates are based on a different app. Before life360 I was using a series of trackers to check for someone to be home or not (had reliability issues) so in the end based on all the different trackers the drop down was updated appropriately. Since going with life360, reliability got way better and I only needed the one system anymore. Sadly I did not fully update my code to simply. You are getting to a good point here though I should probably simplify the system now and just update based on life360 and get rid of anything else (fewer points of failure). I will start working on that after testing the life360 update interval change. Just smart house keeping and could help eliminate things I am not considering.

Then it could probably be that the other app is not changing the input_select? Did you check this?

Just my opinion, but your code looks way too complex for what you want to achieve with involving other apps etc.

Auhh dang looks like the life360 interval change setting can’t be set on a per person basis. I read it wrong. So that’s out. I am going to try and set a time.sleep call in the app for updating the drop downs and see if that helps.

You are correct the original design needed a bit more logic then I am using anymore. However I will say I do check that every time there is an issue and can confirm 100% of the time the status drop down is in the correct and expected state. I am going to try to reconfigure the system a bit here and simplify. It could be that because of the number of listen events being triggered things get dropped (listen for the tracker to change and change the drop down, listen for the drop down to change and trigger the presence system. times those by the number of people arriving home at one time and you can easily be triggering up to 16 events at a time and yeah that is excessive and unnecessary.)