It took me ages to figure this out by digging through the forums.
So I thought I’d leave this here for anyone else who might need it.
This does a few location type things in one go:
Sets an Address item to HOME, or to a Google GeoCode address. I’ve made it so there are only API requests when away from home and moving at least 450m since the last update.
Sets Address to OFFLINE when phone is offline, to avoid thinking data is upto date when the phone might be dead.
Sets a Distance to Home item. Useful for other rules and automations.
I still need some help with adding a GPS Speed calulation.
I have written the code below into a single .rules file in the rules folder.
You will also need to create a few items. I put them in my iPhone group.
You will need the Network binding to get the Network Presence bit to work.
You will need to setup a Google GeoCode API to make the street address bit work.
Use a change in iCloud Location to trigger the rule.
//Run GeoCode API and other geo calculations when Away from home
rule "location_dad-GEO"
when
Item MartinsiPhone_Location changed
then
logInfo("Location - Dad", "Location has changed. Checking iCloud Thing Status and Home Network Presence")
var iPhoneThingStatus = getThingStatusInfo("icloud:device:bc3dd7b8fb:3dfa568e").toString
if (iPhoneThingStatus == "ONLINE" && MartinsiPhone_NetworkPresence_Online.state == OFF) {
logInfo("Location - Dad", "iPhone is " + iPhoneThingStatus + " and Home Network Presence is " + MartinsiPhone_NetworkPresence_Online.state + ". Running GeoCode API script")
val currentLocation = newState as PointType
val lastLocation = previousState as PointType
val distanceTraveled = currentLocation.distanceFrom(lastLocation) as Number
logInfo("Location - Dad", "Distance from Last Location: " + distanceTraveled + " m")
//Set Address to GeoCode if location has changed by x meters
if(distanceTraveled > 450) {
val String GoogleAPIKey = "fjdkDSFG567FGhydfRbH8mfgkdhl98sS1U-N8"
val geocodeURL = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + currentLocation.latitude + "," + currentLocation.longitude + "&sensor=true&key=" + GoogleAPIKey
val String gecodeResponse = sendHttpGetRequest(geocodeURL)
val String formattedAddress = transform("JSONPATH", "$.results[3].formatted_address", gecodeResponse)
MartinsiPhone_Address.postUpdate(formattedAddress)
logInfo("Location - Dad", "GeoCode Address: " + formattedAddress.toString())
} else {
logInfo("Location - Dad", "GeoCode didn't run. Too close to last location.")
}
//Distance from Home
val homeLocation = new PointType(
new DecimalType(53.5648957206535),
new DecimalType(-6.4856214463804)
)
val distanceFromHome = (currentLocation.distanceFrom(homeLocation) * 0.001) as Number
MartinsiPhone_DistanceFromHome.postUpdate(distanceFromHome)
logInfo("Location - Dad", "Distance from home: " + distanceFromHome + " km")
} else {
logInfo("Location - Dad", "iPhone is " + getThingStatusInfo("icloud:device:bc3dd7b8fb:3dfa568e").toString + " and Home Network Presence is " + MartinsiPhone_NetworkPresence_Online.state + ", so GEO rule didn't run.")
}
end
//Set to OFFLINE when device Thing is OFFLINE
rule "location_dad-Set OFFLINE"
when
Thing "icloud:device:bc3dd7b8fb:3dfa568e" changed from ONLINE
then
if (MartinsiPhone_NetworkPresence_Online.state == OFF) {
MartinsiPhone_Address.postUpdate("OFFLINE")
logInfo("Location - Dad", "iPhone is " + getThingStatusInfo("icloud:device:bc3dd7b8fb:3dfa568e").toString + ". Address set to OFFLINE")
}
end
//Set to ON when device is connected to home network
rule "location_dad-Set to HOME"
when
Item MartinsiPhone_NetworkPresence_Online changed to ON
then
MartinsiPhone_Address.postUpdate("HOME")
MartinsiPhone_DistanceFromHome.postUpdate(0)
logInfo("Location - Dad", "Home Network Presence " + newState + ". Address set to HOME")
end
I have made a UI that looks like this
type: script.ScriptAction
component: oh-list-item
config:
icon: oh:man_2
item: iPhone_Location
title: Dad
footer: '=(items.iPhone_Address.state != "OFFLINE" &&
items.iPhone_Address.state != "HOME") ?
items.iPhone_Address.state: " "'
badge: '=(items.iPhone_NetworkPresence_Online.state == "ON") ? "HOME":
(items.iPhone_DistanceFromHome.state < 1 &&
items.iPhone_NetworkPresence_Online.state == "OFF" &&
items.iPhone_Address.state != "OFFLINE") ? "< 1km AWAY":
(items.iPhone_Address.state == "OFFLINE") ? "OFFLINE":
items.iPhone_DistanceFromHome.displayState + " AWAY"'
badge-color: '=(items.iPhone_NetworkPresence_Online.state == "ON") ?
"green": (items.iPhone_Address.state == "OFFLINE") ? "black": "red"'
action: analyzer
actionAnalyzerItems:
- iPhone_DistanceFromHome
- iPhone_NetworkPresence_Online
actionAnalyzerCoordSystem: time