Moving over from a Smart Things system, I have struggled a little getting reliable presence tracking (about the only thing I regret so far!). All the various methods seem to have some fatal flaw:
- iCloud is easy to set up and gives location info but is only polled every 5 minutes, and may or may not have an update for that poll. As such it is not usable to trigger actions like switching on lights when arriving home
- NMAP just plain didn’t work for my iDevices
- I don’t have a supported router (I may take a look at adding EdgeOS Support at some stage)
- OwnTracks requires an MQTT server and I have struggled getting one setup and working (I’ll keep trying)
- Locative looks promising but as the support is currently coded it doesn’t support location info, and it will only report when a geo fence is entered or exited, meaning that a user will show as away after a restart until they leave or enter a fence
I am hopeful that the pending iPhone app will have really good presence, but until then I needed something simple and reliable. I still have my Smart Things hub setup with the presence apps hooked in so I reverse engineered the Locative support in HA and wrote a ST SmartApp that would report presence back to HA.
- Updates when leaving home
- Updates when arriving home
- Forces an update every 5 minutes to initialize a restarted HA system with correct location.
I suspect there are maybe a couple of other ST users out there that may be able to use this, so here is the SmartApp source (below). I have been testing it for several days, I hope it can help someone!
In addition, one thing I found useful was the ability to arbitrarily set people home and away when I was testing my automation. I wrote a simple shell command that would do this. Copy the command below into a script called “setpresence” or similar (as below this needs locative support setup):
wget -O /dev/null "<path to ha>?api_password=<password>&device=$1&id=$2&latitude=0&longitude=0&trigger=$3" > /dev/null 2>&1
Replace <path to ha>
and <password>
with appropriate values then you can force someone to leave with:
setpresence <tracker_id> Home exit
and to return with:
setpresence <tracker_id> Home enter
Here is the App, all you need to do is enable locative support.
definition(
name: "HA Presence",
namespace: "aimc",
author: "[email protected]",
description: "Report ST Presence Updates to Home Assistant",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
)
section ("URL (No parameters)")
{
input "url", "text", required: true
}
section ("API Key")
{
input "apikey", "text", required: true
}
section ("People")
{
input "people", "capability.presenceSensor", multiple: true
}
def installed()
{
subscribe(people, "presence", presence)
runEvery5Minutes(forceUpdate)
forceUpdate()
}
def updated()
{
subscribe(people, "presence", presence)
runEvery5Minutes(forceUpdate)
forceUpdate()
}
private getPerson(evt)
{
people.find{evt.deviceId == it.id}
}
def presence(evt)
{
// log.debug "evt.name: $evt.value"
def person = getPerson(evt)
def value = evt.value
updatePresence(person, value)
}
private updatePresence(person, value)
{
def direction = ""
if (value == "present")
{
direction = "enter"
}
else
{
direction = "exit"
}
def query=
[
api_password: apikey,
device: person.displayName.replaceAll("\\s","").replaceAll("'",""),
id: "Home",
latitude: 0,
longitude: 0,
trigger: direction
]
def params =
[
uri: url,
path: "/api/locative",
query: query
]
try
{
httpGet(params)
{
//resp ->
//resp.headers.each
//{
// log.debug "${it.name} : ${it.value}"
//
//}
//log.debug "response contentType: ${resp.contentType}"
//log.debug "response data: ${resp.data}"
}
}
catch (e)
{
// HA always closes the connection and ST doens't like it and logas a harmless exception - remove comments for testing!
//log.error "something went wrong: $e"
}
}
def forceUpdate()
{
// iterate over our people variable that we defined
// in the preferences method
// log.debug "Forcing Update"
for (person in people)
{
//log.debug person
updatePresence(person, person.currentPresence)
}
}