iPhone locator bridge/binding or however you like to call it

@peteraquino no, but it might not be a problem with pyicloud but a failure or blockage on apple’s side. To make sure, open an issue on the pyicloud’s github, maybe the guys have time to investigate.

It seems to be working quite nicely.
I have two questions

  1. how do I get the GPS coordinates into openhab? I only see support for geofencing.
  2. if I define a device in the geofencing part, I get a python error and it seems that iLocator is only working if I am using the default 1 device. Correct?
  1. I’ve been playing around with additional functionality like sending the coordinates to OpenHAB so that I can display everything on a map (POI, geofence, phone location, location accuracy, etc.). I’ve been testing it for the past couple weeks and haven’t had any problems so I’ll submit a pull request to see if @alex_bartis wants to include it in his project.

  2. Correction: Devices must be defined in the iCloud section and the current implementation only supports multiple devices that are on the same iCloud account.

hi Peter,
Thanks for your answer.
I would be interested in your extension. May you could share the code via ZIP file.

Actually it is supporting two devices if they belong to the same iCloud account.

Sure thing. Just remember to document it please. Thanks!

Hi Peter,
Thanks for providing the link.
Good enhancement!

A proposal for a small improvement.
If the user has different devices then it would be great if there are as many coordinates as there are devices. So for each device provide the ability to have distinct coordinates.
Use case: All device of my family can be tracked and they of course have different coordinates.

Also I have noticed that the algorithms is checking those devices sequentially.

Novice alert

I have installed pyicloud on RPI. Where do I place iLocatorBridge? Once that is done, do i set up the script to run at start? After that we set up items (any have sample)? …Thanks

ok, i am almost there. I have pyicloud working, and the iLocatorBridge configured. I get the following error when running [renamed] DodmanLocate.py [the numbers are not real, example only]. Nathan or anyone, any idea?

Traceback (most recent call last):
  File "DodmanLocate.py", line 205, in <module>
    deviceId = gConfigurationiCloud[device.lower()]
KeyError: '/zs5fegsgeytgd7drghdf0gd/ggg3fdeggd5eee24su51fw0vnawppuehyvnsuzmwv'

Nathan, once you got this running, did you end up needing a Binding? Did you get it onto a map?

Thanks

Is anyone able to help with this?

Traceback (most recent call last):
  File "DodmanLocate.py", line 205, in <module>
    deviceId = gConfigurationiCloud[device.lower()]
KeyError: 'MYiphoneID''

Here is my .ini file.

[iCloud]
#iCloud username
Username : email		
#iCloud Password
Password : PASSWORD
# start iLocator --list-devices to retrieve list of registered ID's
# you can supply multiple Devices .. just start with DeviceID
DeviceID1 : ID...
#(Optional) a second device may be provided, to be used for additional geofences
#DeviceID2 : another deviceID

# you can have multiple geo fences .. just start the section with Geofence
[GeofenceHome]
Latitude : 48.198197
Longitude : -76.459330
# Enter your preferred unit of distance using m, km, ft, mi or nm
# for meters, kilometers, feet, miles or nautical miles
DistanceUnit : ft
#Radius for the geofence.
GeofenceRadius : 500
# for which device to check .. if this is not supplied the first device will be checked
Device: ID
#Dynamic polling map.  A comma-seperated key-value pair in the format dist=interval, shortest distance first.
#Ex: 100=300,1000=10,1001=60 (within 100 ft poll @ 300 sec, else within 1000ft poll @ 10 sec, else poll at 60 sec)
#Ex2: 200=300, 201=60 (If you wanted to poll at 300 seconds while inside geofence, but 60 seconds outside of fence (assuming fence is set to 200 ft)).
#Ex3  0=60 (if you always want to poll at 60 seconds)
PollingMap: 100=300,1000=100,1001=120
#OpenHAB item (usually a switch) to hold the presence value (ON = inside geofence, OFF = outside geofence...
OHItem_Presence: TestHome
#OpenHAB item to hold the current distance from this POI
OHItem_Distance: TestHomeDistance

#example of second geo fence...
[GeofenceWork]
#Latitude : work latitude
#Longitude : work longitude
#DistanceUnit : ft
#GeofenceRadius : 100
#Device: DeviceID2
#PollingMap: 100=300,1000=300,1001=60
#OHItem_Presence: UserPresenceWork
#OHItem_Distance: UserPresenceWorkDistance

[OpenHab]
#Server Address
OHServer : http://192.168.1.X:8080
#OH User with which to connect
OHUsername : username
#OH Password
OHPassword : pw
#Default interval for when a retry needs to occur (i.e. iCloud was unable to return your location during a poll)
RetryInterval : 60
#(Optional) An OpenHAB item to hold the current polling rate
OHItem_PollingRate : TestPollRate
#(Optional) An OpenHAB item to hold the time that represents when the next poll will occur
OHItem_NextPollTime : TestNextPollTime

Thanks

You’ve defined the device’s iCloud ID in the [iCloud] section (which is correct) so there’s no need to define the ID again in the [GeofenceHome] section. Instead, just reference “DeviceID1”.

In other words… in your [GeofenceHome] section, replace
Device: ID
with
Device: DeviceID1

You probably should also comment out the line [GeofenceWork] since you aren’t using it. Just to be safe.

Spot on, thank you Peter!

I will tinker around some more. But assume for OH2, I then use the exec command to run the python script? I see in the log file that the data is being populated. Just need to display that and try to get it on a map etc… Thanks again.

no, the script is designed to run all the time. Set it to run at system startup.

Thank you again. I will add to startup.

I saw above that you were working on sending coordinates to OH and using on a map. Any chance to give that a try? Exactly what i am looking for.

Best,
Tim

@Sabre66 -
Yes, I’ve been testing my modified version of the script that includes coordinates and gps accuracy. The mapping stuff runs outside of this script. In order to get that working, I had to create a webpage that displays the map and shows the POI and geofence. Then it dynamically displays the phone location (w/ accuracy ring) by pulling that info through openHAB REST. The webpage is then served to openHAB via Apache that I have installed on the Raspberry Pi, through an openHAB ‘webview’ item in my sitemap.

It works fairly well but was a bit of a pain to setup. I’m still testing the code because I’m having issues with my script losing connection to iCloud, erroring out and shutting down about once a week. So I’m now testing out some error handling that restarts the script for me. It’s not quite ready to push out yet.

Peter,

Sounds very good, albeit quite involved. Once you are comfortable with it, I would love to try it out. I will keep an eye on this thread. And thanks for all the help already.
Tim

Hi Peter, just curious to see how you are getting on with this? Hope all is well.

Hi all,

to get rid of my last vera dependency I´ve created a rule to query an iPhone´s location:

rule GetiPhoneLocation
  when
   Time cron "0 0/5 * 1/1 * ? *"
 then
   val appleId = ""
   val password = ""
  
   println("Get iPhone location ...")

   val iCloudUrl = "https://www.icloud.com"
   val iCloudLoginUrl = "https://fmipmobile.icloud.com/fmipservice/device/" + appleId + "/initClient"
   
   val loginUrl = new URL(iCloudLoginUrl);
   val HttpsURLConnection connection = loginUrl.openConnection() as HttpsURLConnection
   val request =  "{\"clientContext\":{\"appName\":\"iCloud Find (Web)\",\"appVersion\":\"2.0\"," 
                + "\"timezone\":\"US/Eastern\",\"inactiveTime\":2255,\"apiVersion\":\"3.0\",\"webStats\":\"0:15\"}}"
   val byte[] postData = request.getBytes(StandardCharsets.UTF_8)
   
   var String userpass = appleId + ":" + password;
   var String basicAuth = "Basic " + Base64.encode(userpass.getBytes());

   // prepare post request headers for login ...
   connection.setRequestProperty("Authorization", basicAuth);
   connection.requestMethod = "POST"
   connection.setRequestProperty("User-Agent", "Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)")
   connection.setRequestProperty("Origin", iCloudUrl)
   connection.setRequestProperty("Content-Type", "application/json")
   connection.setRequestProperty("charset", "utf-8")
   connection.setRequestProperty("Accept-language", "en-us");
   connection.setRequestProperty("Connection", "keep-alive");
   
   connection.setRequestProperty("X-Apple-Find-Api-Ver", "2.0")
   connection.setRequestProperty("X-Apple-Authscheme", "UserIdGuest")
   connection.setRequestProperty("X-Apple-Realm-Support", "1.0")
   connection.setRequestProperty("X-Client-Name", "iPad")
   connection.setRequestProperty("Content-Length", Integer.toString( postData.length ))
   
   connection.doOutput = true
   connection.setDoInput = true
   connection.outputStream.write(postData)
   
   val responseCode = connection.responseCode
   
   println("HTTP Code: " + responseCode)
   println("Message: " + connection.responseMessage)
   
   var StringBuffer sb = new StringBuffer();
   var inputStream = new BufferedInputStream(connection.getInputStream());
   var BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
   var String inputLine = "";
   while ((inputLine = br.readLine()) != null) {
     sb.append(inputLine);
   }
   
   // println(sb.toString())
   
   var String _longitude = transform("JSONPATH", "$..longitude", sb.toString())
   var String _latitude = transform("JSONPATH", "$..latitude", sb.toString())
   var String _positionString = _latitude + "," + _longitude
   
   _positionString = _positionString.replace("[","")
   _positionString = _positionString.replace("]","")
   
   val _location = new PointType(_positionString)  
   println(_location)
  
   ItemLocation.postUpdate(_location)
 end

… hope it is of use.

with kind regards,
Patrik

@patrik_gfeller -

Is your binding compatible with OH 1.8.3 or is it OH2 specific?

Also, are there any plans to add functionality for dynamic polling? I used to use a Vera for the iPhoneLocator plugin and the dynamic polling piece was a requirement for me as I do things like open the garage door as I’m approaching. This requires a very fast poll rate the closer I get to home, but I don’t want it always checking every 10 seconds (obviously). That is the main reason I started messing around with and modifying this Locator Bridge.