Arriving home - detecting phones which are arriving to Home

So here´s the rule i´m using to reverse lookup the coordinates to an address and changing the presence.

Items:

Location iPMichael_Location "Ort" <map> (iPhones, gPersist) {channel="icloud:device:openHAB:iPMichael:location"}
String iPMichael_Address "Ort [%s]" <map> (iPhones, gPersist)
Switch iPMichael_Home "Michael Home [%s]" (iPhones, gPersist)

Rule:

// Reverse address lookup with OpenStreetmap
// https://wiki.openstreetmap.org/wiki/Nominatim#Reverse_Geocoding
// Function called to lookup address from a Location type item
// It assumes that the item
val Functions$Function1<GenericItem, String> lookupAddress= [ iPMichael_Location |

    // get lat lon from item
    val PointType location = iPMichael_Location.state as PointType
    val String lat = location.latitude.toString
    val String lon = location.longitude.toString

    // build request
    val String endpoint = 'https://nominatim.openstreetmap.org/reverse'
    val String lang     = 'de-DE'
    val String query    = 'lat=' + lat + '&lon=' + lon + '&accept-language=' + lang + '&format=json&addressdetails=1'
    val String request  = endpoint + '?' + query

    // get result
    val String result  = sendHttpGetRequest(request)
    // logInfo("lookupAddress", result)
    var String road    = transform("JSONPATH", "$.address.road", result)
    var String house   = transform("JSONPATH", "$.address.house_number", result)
    var String city    = transform("JSONPATH", "$.address.city", result)
    var String town    = transform("JSONPATH", "$.address.town", result)
    var String country = transform("JSONPATH", "$.address.country", result)
    var String hide    = 'Deutschland' // in result language; hide your home country

    // Empty the Strings if they´re not part of the result and the full result was put into the Strings
    if(road.startsWith("{"))
    {
        road = ''
    }
    if(house.startsWith("{"))
    {
        house = ''
    }
    if(town.startsWith("{"))
    {
        town = ''
    }
    if(city.startsWith("{"))
    {
        city = ''
    }
    if(country.startsWith("{"))
    {
        country = ''
    }

    // Check if city is empty and fill in town
    if(city == '')
    {
        city = town
    }

    // Check if city is still empty and fill Unknown
    if(city == '')
    {
        city = 'Unknown'
    }

    var String address  = road + ' ' + house + ', ' + city

    // Check if the address starts with comma and only use the city
    if(address.startsWith(",") || address.startsWith(" ,"))
    {
        address = '' + city
    }

    if (country != hide) {
        address = address + ', ' + country
    }

    return address
]

rule "Michael Zuhause"

when

    Item iPMichael_Location changed

then

    // Definition von Zuhause und aktueller Standort
    val PointType homeLocation = new PointType(new DecimalType(<Latitude>), new DecimalType(<Longitude>))
    val PointType phoneLocation = iPMichael_Location.state as PointType
    val int distance = phoneLocation.distanceFrom(homeLocation).intValue()

    // Remove _Location from the triggering item and add _Address
    val String updateItem = triggeringItem.name.toString.split("_Location").get(0) + '_Address'

    // Fill in the address into the item
    postUpdate(updateItem, lookupAddress.apply(triggeringItem))

    if(distance < 150)
    {
        iPMichael_Home.postUpdate(ON)
        logDebug("MichaelHome", "Michael is at home")
    }
    else
    {
        iPMichael_Home.postUpdate(OFF)
        logDebug("MichaelHome", "Michael is gone")
    }

end

I´ve to correct this…
You´re right, the Location isn´t stored with persistence!
It´s because the Location consists of multiple strings (Latitude, Longitude, Altitude).
The only way is to write a rule to store them in parts and another rule to restore them if needed.

Just a quick rule to get the parts of an Location value:

rule "Michael Location split"

when

    Item iPMichael_Location changed

then

    val String Latitude = triggeringItem.state.toString.split(",").get(0)
    val String Longitude = triggeringItem.state.toString.split(",").get(1)
    val String Altitude = triggeringItem.state.toString.split(",").get(2)

    Michael_Latitude.postUpdate(Latitude)
    Michael_Longitude.postUpdate(Longitude)
    Michael_Altitude.postUpdate(Altitude)

    Thread::sleep(100)
    Michael_Latitude.persist
    Michael_Longitude.persist
    Michael_Altitude.persist

end

kind regards
Michael