Presence detection - are we nearly there yet?

5 minute read

Yes, yet another update. This is what comes from trying to refine things.

Bluetooth, bluetooth, everywhere

My Home Assistant system sits in the far corner of the house from the front door. As a result the Bluetooth tracker is a bit hit and miss for entry. There’s also a challenge that I’ve been finding that the Bluetooth devices seem to flip between home and away.

I’d already been pointed towards monitor by others, so I sat down and read the rather long thread on the forum. The only downside would be that I’d need to set up MQTT again, which took all of a couple of minutes.

Trying it out

I installed monitor on one of the other Pi’s, and tested it out. After a few false starts, both with the config for monitor and the config for HA, I got it working as I wanted and proceeded to deploy it.

Behaviour preferences

The key changes for me here were increasing the arrival scans, dropping the minimum time between scans, setting an arrival filter, dropping the RSSI level to -95 (I’ll explain that in the beacon section), and enabling the device tracker topic

#MAX RETRY ATTEMPTS FOR ARRIVAL  
PREF_ARRIVAL_SCAN_ATTEMPTS=2  
  
#MAX RETRY ATTEMPTS FOR DEPART  
PREF_DEPART_SCAN_ATTEMPTS=2  
  
#SECONDS UNTIL A BEACON IS CONSIDERED EXPIRED  
PREF_BEACON_EXPIRATION=240  
  
#MINIMUM TIME BEWTEEN THE SAME TYPE OF SCAN (ARRIVE SCAN, DEPART SCAN)  
PREF_MINIMUM_TIME_BETWEEN_SCANS=15  
  
#ARRIVE TRIGGER FILTER(S)  
PREF_PASS_FILTER_ADV_FLAGS_ARRIVE=".*"  
PREF_PASS_FILTER_MANUFACTURER_ARRIVE="Google|HTC Corporation|LG Electronics|Chipolo"  
  
PREF_FAIL_FILTER_ADV_FLAGS_ARRIVE="NONE"  
PREF_FAIL_FILTER_MANUFACTURER_ARRIVE="NONE"  
  
PREF_RSSI_IGNORE_BELOW=-95  
PREF_DEVICE_TRACKER_REPORT=true  

MQTT preferences

Here I’ve set the identity to be the location of the scanner, in this case they are first floor front and first floor rear.

Static addresses

A list of all the devices I want tracked

Beacon addresses

I bought a Chipolo classic beacon to track the presence of the car. Initially I was rather disappointed - I could trigger a beacon event by pushing the button, but then silence. However, having added it to their app, and then removing it, it beacons as expected.

The only downside is that in the garage the signal level is below the default RSSI threshold of -75. Watching the log I could see it normally floated around -80 to -90, so set it to -95.

Aliases

This ensures that the MQTT topics are human friendly.

Command line flags

I’m using -x -b -tdr as the flags, and these mean:

  • -x - retain mqtt status messages
  • -b - report bluetooth beacons
  • -tdr - only performs a departure scan when a message is published to the MQTT topic, and notifies other instances when it does a scan

How I’m using monitor

I’ve got two Pi Zeros set up, one upstairs at the front of the house, and one upstairs at the back of the house. These conduct arrival scans automatically, or when triggered by the front door opening. Their positioning provides complete coverage through the entire house.

Exit scans are run when the front door closes. And yes, scans plural - it waits half a minute, runs a scan. That’s just long enough that if we closed and walked away, we’ll be out of range. It then runs further scans at one minute, two minutes, and four minutes. This, should, cover it when we leave but stop for a brief chat. I’ll probably add another automation that is triggered when we’re over 100 meters away, the WiFi tracker shows us away, and yet monitor thinks we’re home. That should take care of when we end up chatting with the neighbours for some time.

With the two systems, things have proven totally reliable. I’ve had no false away, and so far no missed departures either. This means that I’ve been able to turn off the Bluetooth trackers built into Home Assistant.

Unexpected benefits

There’s been one unexpected benefit - my Home Assistant system starts faster. Disabling the Bluetooth trackers has cut five minutes off the startup time, which accounted for most of the startup time.

Changes to presence tracking

I know I’ve said don’t use groups, but I’m using groups again. All I’m putting in those groups though are the WiFi and Bluetooth trackers. I’m not using the GPS device tracker at all for home/away logic. This makes the groups safe here. Everything that follows is, of course, on my GitHub.

Home

There is now an automation, and a script, for each person.

Automation

initial_state: 'on'  
alias: 'person1 home'  
trigger:  
  - platform: state  
    entity_id:  
    - group.person_person1  
    to: 'home'  
  - platform: homeassistant  
    event: start  
condition:  
  - condition: state  
    entity_id: input_boolean.person1_home  
    state: 'off'  
  - condition: state  
    entity_id: group.person_person1  
    state: 'home'  
action:  
  - service: script.person1_home  

Script

alias: person1 home  
sequence:  
  - service: input_boolean.turn_off  
    entity_id: input_boolean.person1_travelling  
  - service: input_boolean.turn_on  
    entity_id: input_boolean.person1_home  
  - service: mqtt.publish  
    data:  
      topic: location/person1  
      payload: 'home'  
  - service: automation.turn_on  
    entity_id: automation.person1_at_work  
  - service: script.person1_traveltime  

That MQTT publish is for the new person component. Right now the logic of that component is purely that the most recent update wins, which is a step backwards. So I cheat.

The last script updates the Google and Waze travel time sensors. Those are both configured to update only a few times a day, and I update on demand from automations. The result is that on a typical day I’m using less than 10% of the daily quota, rather than hitting the quota limit before the day is over.

Away

Automation

alias: 'person1 away'  
initial_state: 'on'  
trigger:  
  - platform: state  
    entity_id:  
    - group.person_person1  
    to: 'not_home'  
  - platform: homeassistant  
    event: start  
condition:  
  - condition: state  
    entity_id: input_boolean.person1_home  
    state: 'on'  
  # Both BT and WiFi are away  
  - condition: state  
    entity_id: group.person_person1  
    state: 'not_home'  
action:  
  - service: script.person1_away  

Now that’s much simpler than before. Before I had to track if the front door had been opened recently. With monitor only scanning for departure if a door opens, that’s handled externally.

Script

alias: person1 away  
sequence:  
  - service: input_boolean.turn_off  
    entity_id: input_boolean.person1_home  
  - service: mqtt.publish  
    data:  
      topic: location/person1  
      payload: 'not_home'  

Again, updating the fake device tracker to keep the person component happy.

What’s next?

I don’t think there’s a lot more to do now to the logic. I can probably drop the use of the input boolean and start using the person component, but I’ll wait to see how that component shapes out first.

I may also deploy another Pi Zero W in or above the garage, to improve coverage there.