A Better Device Tracker

There I was lying in bed in the middle of the night only to wake up to the house fully lite up. It was then that I knew what I had to do something about my device tracking to make it more reliable.

A bit of background about my installation and how we use HA. I have an OpenWrt router and I have been using the Luci tracker for a while now. We use presence detection in automations dealing with lighting and also security warnings. I had a node red script that monitored both my wife and I telephones if they were home and update a input boolean to show if either one of us was home. The automations then used this boolean. The issue I found out was my wife’s new android phone was very aggressive with shutting off wifi and ultimately this led HA to think she wasn’t home whenever her phone was idle for more than a few minutes.

Of course I could have added a consider_home value but that didn’t seem to have any effect and it would also make detection take longer when we left in the mornings.

My solution was to add a few new ways of tracking. Both of us got a ping tracker and another tracker based on SQL. The SQL tracker helps to smooth out when the ping misses a few times in a row. Right now I have ping set up for every 5 minutes so the SQL tracker is set to mark us at home if we were pingable within the last 16 minutes (3 attempts) and the time is between 1930 and 0600. If it is outside of that time it doesn’t return anything and if there was no ping in 16 min it will return not_home.

 - name: robb_eve_tracker
        query: >-
                    when time('now','localtime') between '06:00' and '19:30' then null
                    when count(*) > 0 then 'home'
                    else 'not_home'
                  end as state
                  from (select
                  from states
                    entity_id = 'binary_sensor.robb_ping' and
                    state = 'on' and
                    created > DATETIME('now', '-16 minutes')
                    limit 1
                  ) home_events
                  order by created desc
        column: 'state'

The real change has been by combining my normal device tracker, ping and SQL using a Bayesian binary input. The bayesian sensor is based on the probabilty that an event is true. By combining different sensors we make several not very accurate sensor better at predicting if we are actually home.

  - platform: bayesian
    prior: 0.65  #Chance I am home before reading any sensors. 65%
    name: robb_bayesian
    probability_threshold: 0.88 #Average of sensors must be above .88 for it to register I am home
    device_class: presence
      - entity_id: 'device_tracker.robb'
        prob_given_true: 0.8 #If you are home percentage device tracker will get it right
        prob_given_false: 0.1 #If you aren't home percentage device tracker will get it wrong
        platform: 'state'
        to_state: 'home'  #presence detection so values are home and not_home
      - entity_id: 'sensor.robb_eve_tracker'
        prob_given_true: 0.75
        prob_given_false: 0.25
        platform: 'state'
        to_state: 'home'
      - entity_id: 'binary_sensor.robb_ping'
        prob_given_true: 0.8
        prob_given_false: 0.1
        platform: 'state'
        to_state: 'on' #binary sensor so values are on and off

I have tweaked these settings quite a bit but now I am pretty happy with the way things are working. When we get home the Openwrt - luci component picks us up almost right away, and when we are home for a while the ping and SQL components show keep us as home better than Openwrt can.

The last bit of my changes was to scrap the Node red automation that tries to keep track if someone is home and just add all of our bayesian sensors to a group. This way if one of the bayesians is on so is the state of the group.

This site will help you calculate the values for each individual observation. http://psych.fullerton.edu/mbirnbaum/bayes/bayescalc.htm
The values top down are prior, prob_given_true, and prob_given_false.