Advice on app design please

please dont apologise for simple coding. thats the best there is :wink:
and dont forget, i love helping people improve but i am not even close to being an expert (but in the land of the blinds oneeye is king)

i would probably write the app the same when i start writing it.
then i would start optimising for readability.

i would place the devices in a list in the yaml and then use this:

  def initialize(self):
    for device in self.args["devices"]:
        self.listen_state(self.change_boolean, device)
    self.log("Hello from person_presence", level='DEBUG')

in change_boolean then you could use

Person_present = False
for device in self.arg["devices"]:
    if self.get_state(device) == self.args["home_state"]: 
        Person_present = True
if Person_present:
    self.person_present(self)
else:
    self.person_poss_absent(self)

the big advantage is that you now can easy add or delete devices in the yaml without changing the code.
which also would make the code more sharable.

about the MQTT part: i havent played around with it enough to be able to get into it.
i have a working mqtt app, but not based on the pluging, but just with:

import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import paho.mqtt.subscribe as subscribe

i also have the plugin (same way as @Odianosen25 ) and an app based on that but i created it a while ago and dont know for sure if it is working :wink:

1 Like

@ReneTode,

Thanks for the input. The plugin works really great as my system is like 60% MQTT especially considering I use Snips and Zigbee2mqtt.

It makes it easier for me to manage things, and I connect to two different brokers at the same time. That’s why I have different “namespaces”, snipsmqtt and mqtt. And I am in the process of adding a third cloud based on.

Regards

2 Likes

Thanks @ReneTode - much more elegant and efficient. I knew your insight would be valuable. (In spite of what @Odianosen25 thinks :grin: )

I hadn’t realised that the MQTT stuff was in a custom component. I try to avoid these, as it’s yet another thing to make sure continues working over time. My current method - cumbersome though it is - at least is based on core functionality. Hopefully AD will natively include MQTT functionality at some stage, because - like @Odianosen25 - virtually all of my IoT devices are MQTT-based .

2 Likes

My plan is not to integrate the MQTT plugin, not because I don’t see the value - I totally do and Ilove the plugin. Problem is as I integrate more and more 3rd party stuff (I don’t even use MQTT) it becomes harder to maintain, and there is only one of me.

So, for Skins, plugins etc. all third part addons to MQTT my preference is to have them owned by someone that uses them who will commit to keeping it up to date over time - I was planning on asking @Odianosen25 if he would be interested in doing this :slight_smile:

What do you think @Odianosen25?

Hello @aimc,

I am totally cool with it, as it is my life blood and I am working on a product I plan giving users based on it, I will be glad to take it up to be honest.

regards

1 Like

I get your point @PianSom, but in the event you still interested, I have just put together this app.

Now its totally untested as I will look into it when I get home, but what it does it thus:

  1. it will check for users based on location
  2. create confidence sensors in HA per user, per device, per location.
  3. This way, no need to modify your sensors.yaml as AppD does it for you
  4. Based on the confidence reading it gets, per device per location, it will determine if the user in home or not
  5. A sensor created to indicate the user is home or not is available.

My idea is that the only thing one should modify is the owner_devices or guest_devices files and you should be good to go.

To do:
Test for bugs (of course :roll_eyes:)
This only works on a per user per device, as one might have multiple devices. So I will work on modifying the code later, so devices can be grouped together for a single user.

See blow for updated code

1 Like

Excellent and thanks :slight_smile: I need to finalize and debug the custom_plugin stuff, I havent looked at it for a while. When we have that sorted out, I’ll Message you about how we can set this up.

Thanks again!

1 Like

Well @Odianosen25 - I certainly feel chastened now! :slight_smile:

I will study your code and put a cold towel on my head.

@PianSom I am sorry bro :wink:, I didn’t mean to

1 Like

@PianSom, here is the debugged version, as I had some time to test it out. If you don’t mind, I will delete the previous one in the other comment, so others don’t use it.

apps.yaml

home_presence_app:
  module: home_presence_app
  class: HomePresenceApp
  plugin: HASS
  presence_topic: presence
  database: /home/pi/.appdaemon/conf/apps/settings/database
  minimum_confidence: 100
  not_home_timeout: 60

home_presence_app.py

import appdaemon.plugins.mqtt.mqttapi as mqtt
import json
import shelve

class HomePresenceApp(mqtt.Mqtt):

    def initialize(self):
        self.set_namespace('mqtt')
        self.hass_namespace = self.args.get('hass_namespace', 'default')
        self.presence_topic = self.args.get('presence_topic', 'presence')
        self.db_file = self.args['database']
        self.listen_event(self.presence_message, 'MQTT')
        self.not_home_timers = dict()
        self.timeout = self.args.get('not_home_timeout', 120) #time interval before declaring not home
        self.minimum_conf = self.args.get('minimum_confidence', 90)

        with shelve.open(self.db_file) as db: #check sensors
            remove_sensors = []

            try:
                sensors = db[self.presence_topic]
            except:
                sensors = {}

            if isinstance(sensors, str):
                sensors = json.loads(db[self.presence_topic])

            for conf_ha_sensor, user_state_entity in sensors.items():
                if self.entity_exists(conf_ha_sensor, namespace = self.hass_namespace): #confirm the entity still in HA and if not remove it
                    self.listen_state(self.confidence_updated, conf_ha_sensor, user_state_entity = user_state_entity, namespace = self.hass_namespace)
                else:
                    remove_sensors.append(conf_ha_sensor)

            if remove_sensors != []:
                for sensor in remove_sensors:
                    sensors.pop(sensor)

            db[self.presence_topic] = json.dumps(sensors) #reload new data
        
    def presence_message(self, event_name, data, kwargs):
        topic = data['topic']
        if topic.split('/')[0] != self.presence_topic: #only interested in the presence topics
            return

        payload = json.loads(data['payload'])

        location_Id = topic.split('/')[2]
        location = location_Id.replace('_', ' ').title()
        device_name = payload['name']
        user_name = payload['name'].lower().replace('’', '').replace(' ', '_')
        mac_address = topic.split('/')[3]
        confidence = int(payload['confidence'])
        user_conf_entity = '{}_{}'.format(user_name, location_Id)
        conf_ha_sensor = 'sensor.{}'.format(user_conf_entity)
        user_state_entity = '{}_home_state'.format(user_name)
        user_sensor = 'binary_sensor.{}'.format(user_state_entity)
        if user_state_entity not in self.not_home_timers: 
            self.not_home_timers[user_state_entity] = None #used to store the handle for the timer

        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)

        if not self.entity_exists(conf_ha_sensor, namespace = self.hass_namespace): #meaning it doesn't exist
            self.log('Creating sensor {!r} for Confidence'.format(conf_ha_sensor), level='INFO')
            topic =  'homeassistant/sensor/{}/{}/config'.format(self.presence_topic, user_conf_entity)
            payload = {"name": "{} {}".format(device_name, location), 
                        "state_topic":"homeassistant/sensor/{}/{}/state".format(self.presence_topic, user_conf_entity)}
            self.mqtt_send(topic, json.dumps(payload)) #send to homeassistant to create sensor for confidence

            '''create user home state sensor'''
            if not self.entity_exists(user_sensor, namespace = self.hass_namespace): #meaning it doesn't exist.
                                                                                    # it could be assumed it doesn't exist anyway
                self.log('Creating sensor {!r} for Home State'.format(user_sensor), level='INFO')
                topic =  'homeassistant/binary_sensor/{}/config'.format(user_state_entity)
                payload = {"name": "{} Home State".format(device_name), "device_class" : "presence",
                            "state_topic":"homeassistant/binary_sensor/{}/state".format(user_state_entity)}
                self.mqtt_send(topic, json.dumps(payload)) #send to homeassistant to create binary sensor sensor for home state

                '''create app states for mapping user sensors to confidence to store and can be picked up by other apps if needed'''
                if not self.entity_exists(appdaemon_entity):
                    self.set_app_state(appdaemon_entity, state = 'Initializing', attributes = {'Confidence Sensors': {conf_ha_sensor: confidence}, 'MAC Address' : [mac_address]})
            else:
                user_attributes = self.get_state(appdaemon_entity, attribute = 'all')['attributes']
                user_attributes['Confidence Sensors'].update({conf_ha_sensor: confidence})
                if mac_address not in user_attributes['MAC Address']:
                    user_attributes['MAC Address'].append(mac_address)
                self.set_app_state(appdaemon_entity, state = 'Updated', attributes = user_attributes)

            self.listen_state(self.confidence_updated, conf_ha_sensor, user_state_entity = user_state_entity, namespace = self.hass_namespace)

            with shelve.open(self.db_file) as db: #store sensors
                try:
                    sensors = json.loads(db[self.presence_topic])
                except:
                    sensors = {}
                sensors[conf_ha_sensor] = user_state_entity
                db[self.presence_topic] = json.dumps(sensors)
            

        else:
            sensor_reading = self.get_state(conf_ha_sensor, namespace = self.hass_namespace)
            if sensor_reading == 'unknown': #this will happen if HA was to restart
                sensor_reading = 0
            if int(sensor_reading) != confidence: 
                topic = "homeassistant/sensor/{}/{}/state".format(self.presence_topic, user_conf_entity)
                payload = confidence
                self.mqtt_send(topic, payload) #send to homeassistant to update sensor for confidence

                if not self.entity_exists(appdaemon_entity): #in the event AppD restarts and not HA
                    self.set_app_state(appdaemon_entity, state = 'Initializing', attributes = {'Confidence Sensors': {}, 'MAC Address' : []})
                user_attributes = self.get_state(appdaemon_entity, attribute = 'all')['attributes']
                user_attributes['Confidence Sensors'].update({conf_ha_sensor: confidence})
                if mac_address not in user_attributes['MAC Address']:
                    user_attributes['MAC Address'].append(mac_address)
                self.set_app_state(appdaemon_entity, state = 'Updated', attributes = user_attributes)


    def confidence_updated(self, entity, attribute, old, new, kwargs):
        confidence = new
        user_state_entity = kwargs['user_state_entity']
        user_sensor = 'binary_sensor.' + user_state_entity
        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)
        user_conf_sensors = self.get_state(appdaemon_entity, attribute = 'all')['attributes']['Confidence Sensors']
        if max(user_conf_sensors.values()) >= self.minimum_conf: #meaning at least one of them states is greater than the minimum so person definitely home
            if self.not_home_timers[user_state_entity] != None: #cancel timer if running
                self.cancel_timer(self.not_home_timers[user_state_entity])
                self.not_home_timers[user_state_entity] = None

            topic = "homeassistant/binary_sensor/{}/state".format(user_state_entity)
            payload = 'ON'
            self.mqtt_send(topic, payload) #send to homeassistant to update sensor that user home
            self.set_app_state(appdaemon_entity, state = 'Home') #not needed but one may as well for other apps

        else:
            if self.not_home_timers[user_state_entity] == None: #run the timer
                self.not_home_timers[user_state_entity] = self.run_in(self.not_home_func, self.timeout, user_state_entity = user_state_entity)

    def not_home_func(self, kwargs):
        user_state_entity = kwargs['user_state_entity']
        user_sensor = 'binary_sensor.' + user_state_entity
        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)
        user_conf_sensors = self.get_state(appdaemon_entity, attribute = 'all')['attributes']['Confidence Sensors']
        self.not_home_timers[user_state_entity] = None
        if max(user_conf_sensors.values()) < self.minimum_conf: #still confirm for the last time
            topic = "homeassistant/binary_sensor/{}/state".format(user_state_entity)
            payload = 'OFF'
            self.mqtt_send(topic, payload) #send to homeassistant to update sensor that user home
            self.set_app_state(appdaemon_entity, state = 'Not Home') #not needed but one may as well for other apps        

As stated above, all that is required is to make the changes to the owner_devices and guest_devices files, and AppD will populate the rest.

This is what AppD does

  1. Create sensors in HA based on each device per location sensor.<device name>_location (like in your case, you said you got 3). So each device will basically have 3 of these sensors and it multiplies like that
  2. These sensors are used to keep the confidence reading from the presence sensor.
  3. A binary sensor is then created in HA, per device binary_sensor.<device name>_home_state. So regardless of which location it is sensed, only one is created. So even though you have 3 presence system running, only a single binary sensor is created for each device. This is a presence sensor, so on HA it will show as presence (home/away).
  4. Based on the reading of each of the confidence sensors, AppD checks across all of them if anyone is more than the configured minimum_confidence. if any, it will set the binary sensor to home for that device
  5. If the user is no detected after the not_home_timeout, the binary sensor is then set for not home
  6. The created sensors are stored in a database as set in the apps.yaml file, so if there is a restart, it will reload the listen_state() functions
  7. If for any reason a sensor no longer exist (HA restarts, and maybe the user no longer around like a guest), AppD will remove the user from the database on next restart

To Do:
As stated earlier, modify app so a single user can be detected from multiple devices at the same time.

It is possible to do all these without involving HA, but as @ReneTode once commented, it is actually a good thing to have history of these detection and so necessary to have it added.

Hope this helps, and to be honest, I kind of like the speed of detection and away mode. The script really cool.

Regards

2 Likes

Hello @PianSom,

When I wrote this app, I hadn’t realised that @andrewjfreyer had two versions of the presence system. The presence.sh and monitor.sh. Over the weekend, I migrated to the monitor.sh, and due to how different its message structure is, it broke the app above. I have rewritten the app to function with the monitor.sh version, and it is below.

I must say one very good thing about the monitor.sh version is that its easier to anticipate a few things. Like in the config, if I name a particular MAC, its easy to tell what sensors will be generated for it, instead of seeking out device name. Like if I write in known_static_addresses xx:xx:xx:xx:xx:xx Odianosen's Iphone, I can easily expect sensors called sensor.odianosens_iphone_living_room for confidence (that is if my presence system is in the Living Room) and binary_sensor.odianosens_iphone_home_state for if the device is in the house.

Based on the above, automation can then be built in anticipation of these. Think about those running stuffs like AirBnB or if one was to have guests around and need some special automation for them in anticipation. I have also made the system a bit more reliant on the data generated in HA, instead of basing it on what is stored in AppD.

Lastly I do understand that some might prefer to be able to use this app, without needing to bring in the mqtt plugin as you mentioned earlier. If that is the case, there is a way to still achieve it using events. But as I don’t use it, working on it will be a well difficult and maintaining it will be a drag. I can assist if you need it, and as usual just holla.

import appdaemon.plugins.mqtt.mqttapi as mqtt
import json
import shelve

class HomePresenceApp(mqtt.Mqtt):

    def initialize(self):
        self.set_namespace('mqtt')
        self.hass_namespace = self.args.get('hass_namespace', 'default')
        self.presence_topic = self.args.get('presence_topic', 'presence')
        self.db_file = self.args['database']
        self.listen_event(self.presence_message, 'MQTT')
        self.not_home_timers = dict()
        self.timeout = self.args.get('not_home_timeout', 120) #time interval before declaring not home
        self.minimum_conf = self.args.get('minimum_confidence', 90)
        self.home_state_entities = dict()

        with shelve.open(self.db_file) as db: #check sensors
            remove_sensors = []

            try:
                sensors = db[self.presence_topic]
            except:
                sensors = {}

            if isinstance(sensors, str):
                sensors = json.loads(db[self.presence_topic])

            for conf_ha_sensor, user_state_entity in sensors.items():
                '''confirm the entity still in HA if not remove it'''
                if self.entity_exists(conf_ha_sensor, namespace = self.hass_namespace):
                    self.listen_state(self.confidence_updated, conf_ha_sensor, user_state_entity = user_state_entity, namespace = self.hass_namespace)
                else:
                    remove_sensors.append(conf_ha_sensor)

                if user_state_entity  not in self.home_state_entities:
                    self.home_state_entities[user_state_entity ] = list()

                if conf_ha_sensor not in remove_sensors and self.get_state(conf_ha_sensor, namespace = self.hass_namespace) != 'unknown': #meaning its not been scheduled to be removed
                    self.home_state_entities[user_state_entity].append(conf_ha_sensor)

            if remove_sensors != []:
                for sensor in remove_sensors:
                    sensors.pop(sensor)

            db[self.presence_topic] = json.dumps(sensors) #reload new data
        
    def presence_message(self, event_name, data, kwargs):
        topic = data['topic']
        if topic.split('/')[0] != self.presence_topic: #only interested in the presence topics
            return 

        elif topic.split('/')[1] != 'owner':
            return

        payload = json.loads(data['payload'])

        if payload.get('status', None) != None: #meaning its a message on the presence system
            location = topic.split('/')[2].replace('_',' ').title()
            self.log('The Presence System in the {} is {}'.format(location, payload.get('status').title()))

        if payload.get('type', None) != 'Known Static MAC' or payload.get('name', None) == 'Unknown Name': #confirm its for a known MAC address
            return

        location = topic.split('/')[2].replace('_',' ').title()
        location_Id = location.replace(' ', '_').lower()
        device_name = payload['name']
        user_name = payload['name'].lower().replace('’', '').replace(' ', '_').replace("'", "")
        mac_address = topic.split('/')[3]
        confidence = int(payload['confidence'])
        user_conf_entity = '{}_{}'.format(user_name, location_Id)
        conf_ha_sensor = 'sensor.{}'.format(user_conf_entity)
        user_state_entity = '{}_home_state'.format(user_name)
        user_sensor = 'binary_sensor.{}'.format(user_state_entity)
        if user_state_entity not in self.not_home_timers: 
            self.not_home_timers[user_state_entity] = None #used to store the handle for the timer

        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)

        if not self.entity_exists(conf_ha_sensor, namespace = self.hass_namespace): #meaning it doesn't exist
            self.log('Creating sensor {!r} for Confidence'.format(conf_ha_sensor), level='INFO')
            topic =  'homeassistant/sensor/{}/{}/config'.format(self.presence_topic, user_conf_entity)
            state_topic = "homeassistant/sensor/{}/{}/state".format(self.presence_topic, user_conf_entity)
            payload = {"name": "{} {}".format(device_name, location), "state_topic": state_topic}
            self.mqtt_send(topic, json.dumps(payload)) #send to homeassistant to create sensor for confidence

            '''create user home state sensor'''
            if not self.entity_exists(user_sensor, namespace = self.hass_namespace): #meaning it doesn't exist.
                                                                                    # it could be assumed it doesn't exist anyway
                self.log('Creating sensor {!r} for Home State'.format(user_sensor), level='INFO')
                topic =  'homeassistant/binary_sensor/{}/config'.format(user_state_entity)
                payload = {"name": "{} Home State".format(device_name), "device_class" : "presence", 
                            "state_topic": "homeassistant/binary_sensor/{}/state".format(user_state_entity)}
                self.mqtt_send(topic, json.dumps(payload)) #send to homeassistant to create binary sensor sensor for home state

                '''create app states for mapping user sensors to confidence to store and can be picked up by other apps if needed'''
                if not self.entity_exists(appdaemon_entity):
                    self.set_app_state(appdaemon_entity, state = 'Initializing', attributes = {'Confidence' : confidence})

            else:
                user_attributes = self.get_state(appdaemon_entity, attribute = 'all')['attributes']
                user_attributes['Confidence'] = confidence
                self.set_app_state(appdaemon_entity, state = 'Updated', attributes = user_attributes)

            self.listen_state(self.confidence_updated, conf_ha_sensor, user_state_entity = user_state_entity, namespace = self.hass_namespace)

            if user_state_entity not in self.home_state_entities:
                self.home_state_entities[user_state_entity] = list()

            if conf_ha_sensor not in self.home_state_entities[user_state_entity]: #not really needed, but noting wrong in being extra careful
                self.home_state_entities[user_state_entity].append(conf_ha_sensor)

            self.run_in(self.update_sensor, 3, topic = state_topic, payload = confidence) #use delay so HA has time to setup sensor first before updating

            with shelve.open(self.db_file) as db: #store sensors
                try:
                    sensors = json.loads(db[self.presence_topic])
                except:
                    sensors = {}
                sensors[conf_ha_sensor] = user_state_entity
                db[self.presence_topic] = json.dumps(sensors)

        else:
            if user_state_entity not in self.home_state_entities:
                self.home_state_entities[user_state_entity] = list()

            if conf_ha_sensor not in self.home_state_entities[user_state_entity]:
                self.home_state_entities[user_state_entity].append(conf_ha_sensor)
                self.listen_state(self.confidence_updated, conf_ha_sensor, user_state_entity = user_state_entity, namespace = self.hass_namespace)
                with shelve.open(self.db_file) as db: #store sensors
                    try:
                        sensors = json.loads(db[self.presence_topic])
                    except:
                        sensors = {}
                    sensors[conf_ha_sensor] = user_state_entity
                    db[self.presence_topic] = json.dumps(sensors)
                
            sensor_reading = self.get_state(conf_ha_sensor, namespace = self.hass_namespace)
            if sensor_reading == 'unknown': #this will happen if HA was to restart
                sensor_reading = 0
            if int(sensor_reading) != confidence: 
                topic = "homeassistant/sensor/{}/{}/state".format(self.presence_topic, user_conf_entity)
                payload = confidence
                self.mqtt_send(topic, payload) #send to homeassistant to update sensor for confidence

                if not self.entity_exists(appdaemon_entity): #in the event AppD restarts and not HA
                    self.set_app_state(appdaemon_entity, state = 'Initializing', attributes = {'Confidence' : confidence})
                user_attributes = self.get_state(appdaemon_entity, attribute = 'all')['attributes']
                user_attributes['Confidence'] = confidence
                self.set_app_state(appdaemon_entity, state = 'Updated', attributes = user_attributes)


    def confidence_updated(self, entity, attribute, old, new, kwargs):
        user_state_entity = kwargs['user_state_entity']
        user_sensor = 'binary_sensor.' + user_state_entity
        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)
        user_conf_sensors = self.home_state_entities.get(user_state_entity, None)
        #self.log('__function__, __line__, user_conf_sensors: {}'.format(user_conf_sensors))
        if user_conf_sensors != None:
            sensor_res = list(map(lambda x: self.get_state(x, namespace = self.hass_namespace), user_conf_sensors))
            sensor_res = [i for i in sensor_res if i != 'unknown'] # remove unknown vales from list
            if  sensor_res != [] and any(list(map(lambda x: int(x) >= self.minimum_conf, sensor_res))): #meaning at least one of them states is greater than the minimum so device definitely home
                if self.not_home_timers[user_state_entity] != None: #cancel timer if running
                    self.cancel_timer(self.not_home_timers[user_state_entity])
                    self.not_home_timers[user_state_entity] = None

                topic = "homeassistant/binary_sensor/{}/state".format(user_state_entity)
                payload = 'ON'
                self.mqtt_send(topic, payload) #send to homeassistant to update sensor that user home
                self.set_app_state(appdaemon_entity, state = 'Home') #not needed but one may as well for other apps

            else:
                if self.not_home_timers[user_state_entity] == None and self.get_state(user_sensor, namespace = self.hass_namespace) != 'off': #run the timer
                    self.not_home_timers[user_state_entity] = self.run_in(self.not_home_func, self.timeout, user_state_entity = user_state_entity)

    def not_home_func(self, kwargs):
        user_state_entity = kwargs['user_state_entity']
        user_sensor = 'binary_sensor.' + user_state_entity
        appdaemon_entity = '{}.{}'.format(self.presence_topic, user_state_entity)
        user_conf_sensors = self.home_state_entities[user_state_entity]
        sensor_res = list(map(lambda x: self.get_state(x, namespace = self.hass_namespace), user_conf_sensors))
        sensor_res = [i for i in sensor_res if i != 'unknown'] # remove unknown vales from list
        if  all(list(map(lambda x: int(x) < self.minimum_conf, sensor_res))): #still confirm for the last time
            topic = "homeassistant/binary_sensor/{}/state".format(user_state_entity)
            payload = 'OFF'
            self.mqtt_send(topic, payload) #send to homeassistant to update sensor that user home
            self.set_app_state(appdaemon_entity, state = 'Not Home') #not needed but one may as well for other apps    

    def update_sensor(self, kwargs):
        topic = kwargs['topic']
        payload = kwargs['payload']
        self.mqtt_send(topic, payload) #send to homeassistant to update sensor for confidence
1 Like

Fantastic work @Odianosen25!

I had been trying to find the time this week to understand your coding and investigate the MQTT plugin - sounds like I was lucky to delay. I will hopefully spend some time on it in the next few days.

:facepunch:t5:

Does this app save the state after a restart or HASS. Right now if I need to restart hass I have to reboot all of my pi zeros to get the last state

Hello @benjimatt,

Well it doesn’t as I use the -r flag in my monitor.service as shown below. This way the system keeps checking and even if HA restarts, it repopulates everything as the zeros send their readings.


[Unit]
Description=Monitor Service
After=network.target

[Service]
User=root
ExecStart=/bin/bash /home/pi/monitor/monitor.sh -r  &
WorkingDirectory=/home/pi/monitor
Restart=always
RestartSec=10
ExecStop=pkill -f monitor.sh

[Install]
WantedBy=multi-user.target network.target

Another reason I went via this route is that I wouldn’t want my database filling up, when for example I have guest left (not that its a large file anyway :smirk:). And lastly, it could lead to a false state. Like if HA was to reboot and one leaves at that point in time. Now if the monitor doesn’t send anything, one could have a false state in HA.

So in all, I felt this was a more reliable way to do things.

Regards

I think I have it figured out now, but just so you know I dont think that is what -r is designed to do… -r is “repeatedly scan for arrival & departure of known devices
Using -r makes the script act like the Presence script vs the Monitor script

I am now using the -a which is “report all scan results, not just presence changes
this seems to refresh the data even after I restart HASS.

BTW I will eventually try out the app you have made, seems to do everything that my instance is doing but all in one package which would be really nice.

Thanks for the update bro,

I didn’t want to do all scan results, as it might pick up what I am not interested in, but I will see what it gives me and look into using it if I need such amount of data.

Well that was the plan. As I had said in earlier comments, I am really too lazy to create such number of files just for detecting presence so that is what motivated me to find an easier solution. The permutations of having a lot of presence systems, then devices was just too many for me. Though my house is tiny for now :stuck_out_tongue_winking_eye:.

Give it a try and let me know what you think.

Kind regards

@Odianosen25
Could something like this be possible for quicker detection times. If there was a way you could essentially link two RPI Zero’s (ssh maybe?) so that one side always checks for depart and the other side always checks for Arrive.

so in a scenario with 3 bluetooth devices.
two people away and one at home
PI A (should be scanning for Arrive for the two people that arent at home)
PI B (Should be scanning for Depart for the person that is at home)

If all three Users are home or away then PI A and/or PI B can scan for arrival.

Hello @benjimatt,

Apologies for the delay.

Yeah it is possible, and I think its essentially a feature of the monitor script using the the -t flag to run it.

So if the app notices that at least one person is not home, it triggers one of the zeros to scan for arrival while the other keeps scanning for departure.

When it then finds out all are not home, it triggers both to scan for arrival. And when all are at home, it triggers both to scan for departure.

That’s pretty neat and yeah I will make the modes to the app to support this.

Unfortunately I won’t be able to test it very well as I said earlier, I got just one but I am sure it shouldn’t be too much of a biggy.

Regards