Page 1 of 14

Find My iPhone implementation in LUA script

Posted: Monday 12 September 2016 15:37
by mvzut
UPDATE 14-09-2016 13:30 - Changed part that takes distance from text device to be robust against (new) text devices that don't contain distance info yet. Please update your script if you are struggling with "nil" problems in the log.

Hi all,

In another topic I have been reporting on an implementation of the Find My iPhone service in LUA. I have improved it a bit further, and thought it deserved a separate topic.

What does it do?
This script checks the location of one or more iPhones using Apples Find My iPhone service. This funtion first has to be enabled on each phone (if this has not already been done). You have to put the iCloud credentials of every user in the script. Don't worry, the information is sent over the internet using a secure https connection, so your credentials are not out in the open. You can do several things with the location info. At the moment, I have implemented two functions:
  • Activate a presence switch if the phone is within a certain radius from your home
  • Do a reverse address lookup and log the current whereabouts (address) of each phone in a dummy tect device, along with the distance from home
More functions can be added of course, such as tracking of disctance, travelling speed & direction (to or from home) to predict the time when someone comes home, allowing you to switch on the microwave automatically ;-).
The default polling time is 5 minutes. If you feel this is draining your battery (I'm still investigating this myself) you can easily increase this. We could even make this into a dynamic value, i.e. different polling times depending on location or time.

Where does this come from? (And where could it lead to...?)
I wasn't happy with the existing presence awareness techniques described around here, such as WiFi or Bluetooth detection scripts. I simply had too many false positives or negatives, usually a couple a day. I started to look for alternatives, and since we all have iPhones at home, the Find My iPhone service had my special attention. It didn't take long before I found a basic LUA script from Jason Gill on the MiCasaVerde forum. I created my own implementation based on this code, including multiple accounts functionality and switching of Domoticz devices. Interesting note: At MiCasaVerde, Jason's original idea eventually resulted in a very nice plugin, complete with UI to fill in user data, set options and show locations on a map. Wouldn't it be great if we could one day create our own Domoticz plugin based on this?

How to install
There are four steps:
  1. Activate Find My iPhone on all phones you want to keep track of (usually this is already standard on)
  2. Download a lua JSON decoder, e.g. this one: http://regex.info/blog/lua/json and copy the file (json.lua) somewhere where it can be found (in my case this was /usr/local/share/lua/5.2/). I think you can also append a path after the "require" command in the script below.
  3. Create a dummy switch named "iPhone Person1" for each iPhone you want to track (where "Person1" is replaced with the name of the person). Also create a dummy text device for each iPhone named "Position Person1" (again replacing "Person1" with the person's name). If you want (and haven't already done so), configure one or more notification services, then you will be informed when someone leaves the house or comes home.
  4. Create the following script and put this e.g. in "~/domoticz/scripts/lua/script_time_checkphones.lua"

    Code: Select all

    -- Script to check the location of multiple iPhones every X minutes,
    -- test if they are "home" and represent this using virtual switches
    
    commandArray = {}
    -- polling interval in minutes (1-59), setting this too low may drain the phones' batteries
    interval = 5
    local m = os.date('%M')
    if (m % interval == 0) then
    
      json = require('json')
    
      -- Array of users to be checked
      users = {
                Person1 = {username = "[email protected]" ; password = "password1" ; devicename = "iPhone Person1"};
                Person2 = {username = "[email protected]" ; password = "password2" ; devicename = "iPhone Person2"};
                Person3 = {username = "[email protected]" ; password = "password3" ; devicename = "iPhone Person3"}
              }
      -- The latitude and longitude of your house (use Google Maps or similar to find this)
      homelongitude = 1.23456789
      homelatitude = 9.87654321
      -- Radius (in km) which will be used to determine if a device is at home
      radius = 0.5
    
      function address(longitude, latitude)
        command = "curl -s https://maps.googleapis.com/maps/api/geocode/json?latlng=" .. latitude .. "," .. longitude .. "&sensor=false"
        local handle = io.popen(command)
        local result = handle:read("*a")
        handle:close()
        output = json:decode(result)
        return output.results[1].formatted_address
      end
    
      for user,credentials in pairs(users) do
        stage1command = "curl -s -X POST -D - -o /dev/null -L -u '" .. credentials.username .. ":" .. credentials.password .. "' -H 'Content-Type: application/json; charset=utf-8' -H 'X-Apple-Find-Api-Ver: 2.0' -H 'X-Apple-Authscheme: UserIdGuest' -H 'X-Apple-Realm-Support: 1.0' -H 'User-agent: Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)' -H 'X-Client-Name: iPad' -H 'X-Client-UUID: 0cf3dc501ff812adb0b202baed4f37274b210853' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' https://fmipmobile.icloud.com/fmipservice/device/" .. credentials.username .."/initClient"
        local handle = io.popen(stage1command)
        local result = handle:read("*a")
        handle:close()
    
        stage2server = string.match(result, "X%-Apple%-MMe%-Host%:%s(.*%.icloud%.com)")
        stage2command = "curl -s -X POST -L -u '" .. credentials.username .. ":" .. credentials.password .. "' -H 'Content-Type: application/json; charset=utf-8' -H 'X-Apple-Find-Api-Ver: 2.0' -H 'X-Apple-Authscheme: UserIdGuest' -H 'X-Apple-Realm-Support: 1.0' -H 'User-agent: Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)' -H 'X-Client-Name: iPad' -H 'X-Client-UUID: 0cf3dc501ff812adb0b202baed4f37274b210853' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' https://" .. stage2server .. "/fmipservice/device/" .. credentials.username .."/initClient"
        local handle = io.popen(stage2command)
        local result = handle:read("*a")
        handle:close()
    
        output = json:decode(result)
        for key,value in pairs(output.content) do
          if value.name == credentials.devicename then
            lon = value.location.longitude
            lat = value.location.latitude
            distance = math.sqrt(((lon - homelongitude) * 111.320 * math.cos(math.rad(lat)))^2 + ((lat - homelatitude) * 110.547)^2)  -- approximation
            position = address(lon,lat)
            position_text = string.gsub(position, ', Netherlands', '') .. ' (' .. (math.floor(distance*10+0.5)/10) .. ' km)'
            prev_distance_str = string.match(otherdevices['Position ' .. user], '%(.*%)') or '(1000 km)'
            prev_distance = tonumber(string.sub(prev_distance_str, 2,-5))
            -- update text device, but only if postion has changed more than defined in "radius" to reduce log size
            if math.abs(prev_distance - distance) > radius then  
              table.insert(commandArray,{['UpdateDevice'] = otherdevices_idx['Position ' .. user] .. '|0|' .. position_text})
            end
            --print('iPhone ' .. user .. ': ' .. math.floor(distance*100+0.5)/100 .. ' km from home')
            if distance < radius  then
              if otherdevices['iPhone ' .. user] == 'Off' then
                commandArray['iPhone ' .. user] = 'On'
                table.insert(commandArray, {['SendNotification'] = 'Presence update#' .. user .. ' came home'})
              end
            else
              if otherdevices['iPhone ' .. user] == 'On' then
                commandArray['iPhone ' .. user] = 'Off'
                table.insert(commandArray, {['SendNotification'] = 'Presence update#' .. user .. ' left home'})
              end
            end
          end
        end
      end
    
    end
    
    return commandArray
    Replace the following data with your own:
    • The value of "interval" (number of minutes between polls)
    • The values in the "users" array. Replace "Person1" etc. with the name(s) of the person(s) and fill in the credentials. The device name is the name you gave each iPhone during its configuration. This name has to be filled in exactly right (note the use of capitals etc.). You can add as many users as you want in new lines (pay attention to the correct placement of brackets, parentheses etc.).
    • The "homelongitude" and "homelatitude" values (the position of your house)
    • The value of "radius". This is the radius around your house (in km) to call something "at home". Don't choose this value too low, this could lead to intermittent "left home" - "came home" events since the GPS accuracy is sometimes limited.
    • (optional) I put some code in the script to remove the text "Netherlands" from the address to keep it compact. Change this into your own country if you want.
And that's it! Hope you find this useful. Let me know your findings! Is it draining your battery? And are there more experienced programmers who could further extend the functionality, or even start the creation of a real plugin?

Re: Find My iPhone implementation in LUA script

Posted: Monday 12 September 2016 19:27
by steef84
Wow,

impressive! Its working for me since tonight for 4 iPhones.
Thanks for your comprehensive guide. It's probably Wiki material :D .

Will test this on the four iPhones the upcoming days, and as already mentioned in the other topic I will report back about the possible battery consumption. My interval is also 5 minutes.

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 12:35
by Nautilus
Hi,

this is just the thing I've been looking for, thanks! All apps I've tested that use a geofence have been so far very unreliable, I hope this approach solves it! Set it up yesterday and seems to work well for one of our phones, for some reason the other reports currently "offline" in Find my iPhone app and thus the script also gives an error:

Code: Select all

2016-09-13 13:20:07.859 Error: EventSystem: in PresenceDetection: [string "commandArray = {}..."]:51: attempt to index field 'location' (a nil value)
This got me thinking that what would be the best way to build some error checking to the script? Maybe even something to keep track when was the last successful update, what do you think?

I agree the interval could be dynamic if it really has a battery life impact to poll this (does it actually request the location from the phone and that drains the battery? I thought the phone periodically just updates the location). E.g. during night time if the phone is at home location, the script could be stopped altogether (for that phone) until the first door opening etc. Need to look into this.

Once the "offline" phone arrives back home I'll be looking into the reason why it is offline. Though I thought that as long as "find my iPhone" is enabled, the phone should never be "offline", at least as long as it is not turned off...

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 13:02
by mvzut
Nautilus wrote:Hi,

this is just the thing I've been looking for, thanks! All apps I've tested that use a geofence have been so far very unreliable, I hope this approach solves it! Set it up yesterday and seems to work well for one of our phones, for some reason the other reports currently "offline" in Find my iPhone app and thus the script also gives an error:

Code: Select all

2016-09-13 13:20:07.859 Error: EventSystem: in PresenceDetection: [string "commandArray = {}..."]:51: attempt to index field 'location' (a nil value)
This got me thinking that what would be the best way to build some error checking to the script? Maybe even something to keep track when was the last successful update, what do you think?
Indeed, error checking is something that should definitely be added, especially if we want to roll this out to a larger audience. Checking for nil values before continuing with the rest of the script is of course easy to do, but that doesn't give a lot of info about where it went wrong. It also shouldn't be too difficult to better analyse the response from the two curl commands, and give more relevant feedback on errors. I'll give it some thought, and if you have ideas yourself let me know.

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 13:35
by cattoo

Code: Select all

2016-09-13 13:30:03.439 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:52: attempt to concatenate field '?' (a nil value)
Thats the error i got, it seems to be the first row. What to do?

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 15:16
by mvzut
cattoo wrote:

Code: Select all

2016-09-13 13:30:03.439 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:52: attempt to concatenate field '?' (a nil value)
Thats the error i got, it seems to be the first row. What to do?
Your error seems to be in line 52, if you didn't add or remove any lines from the script that is where the string is constructed to put into the dummy text devices:

Code: Select all

position_text = string.gsub(position, ', Netherlands', '') .. ' (' .. (math.floor(distance*10+0.5)/10) .. ' km)'
Can you confirm this? The error message suggests that there is a nil value in this formula. I don't understand why it says "?", but it can only be the "position" variable or the "distance" variable.

Please add a line between line 51 and 52:

Code: Select all

print(position)
Does it print the address(es) of your devices in the Domoticz log every 5 minutes? (You can temporary set the interval to 1 minute to speed up the debugging process)
If not, add two lines between line 49 and 50:

Code: Select all

print(lon)
print(lat)
Does it print the coordinates of every phone?

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 15:50
by cattoo
mvzut wrote:
cattoo wrote:

Code: Select all

2016-09-13 13:30:03.439 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:52: attempt to concatenate field '?' (a nil value)
Thats the error i got, it seems to be the first row. What to do?
Your error seems to be in line 52, if you didn't add or remove any lines from the script that is where the string is constructed to put into the dummy text devices:

Code: Select all

position_text = string.gsub(position, ', Netherlands', '') .. ' (' .. (math.floor(distance*10+0.5)/10) .. ' km)'
Can you confirm this?

Please add a line between line 51 and 52:

Code: Select all

print(position)
Does it print the address(es) of your devices in the Domoticz log every 5 minutes? (You can temporary set the interval to 1 minute to speed up the debugging process)
If not, add two lines between line 49 and 50:

Code: Select all

print(lon)
print(lat)
Does it print the coordinates of every phone?
Ill changed to Sweden instead of Netherlands.
And now added the position and lon/lat print option. And it gave me:

Code: Select all

2016-09-13 15:43:02.818 LUA: 11.945440638822
2016-09-13 15:43:02.819 LUA: 57.665579812655
2016-09-13 15:43:02.819 LUA: Gruvgatan 39A, 421 30 Västra Frölunda, Sweden
(and that is my current location)

Code: Select all

2016-09-13 15:43:02.820 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:55: attempt to concatenate field '?' (a nil value)

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:06
by mvzut
cattoo wrote:Ill changed to Sweden instead of Netherlands.
And now added the position and lon/lat print option. And it gave me:

Code: Select all

2016-09-13 15:43:02.818 LUA: 11.945440638822
2016-09-13 15:43:02.819 LUA: 57.665579812655
2016-09-13 15:43:02.819 LUA: Gruvgatan 39A, 421 30 Västra Frölunda, Sweden
2016-09-13 15:43:02.820 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:55: attempt to concatenate field '?' (a nil value)
Can you confirm that line 52 (now line 55) is indeed the line I mentioned above (starting with "position_text = ...")?
Please also add a line after th eline starting with "distance = ...":

Code: Select all

print(distance)
Does it print the distance? If not the error could be in this formula. If the distance is nicely printed, you could replace

Code: Select all

position_text = string.gsub(position, ', Sweden', '') .. ' (' .. (math.floor(distance*10+0.5)/10) .. ' km)'
with

Code: Select all

position_text = position
Just to check if the error is in that line.

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:21
by cattoo
mvzut wrote:
cattoo wrote:Ill changed to Sweden instead of Netherlands.
And now added the position and lon/lat print option. And it gave me:

Code: Select all

2016-09-13 15:43:02.818 LUA: 11.945440638822
2016-09-13 15:43:02.819 LUA: 57.665579812655
2016-09-13 15:43:02.819 LUA: Gruvgatan 39A, 421 30 Västra Frölunda, Sweden
2016-09-13 15:43:02.820 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:55: attempt to concatenate field '?' (a nil value)
Can you confirm that line 52 (now line 55) is indeed the line I mentioned above (starting with "position_text = ...")?
Please also add a line after th eline starting with "distance = ...":

Code: Select all

print(distance)
Does it print the distance? If not the error could be in this formula. If the distance is nicely printed, you could replace

Code: Select all

position_text = string.gsub(position, ', Netherlands', '') .. ' (' .. (math.floor(distance*10+0.5)/10) .. ' km)'
with

Code: Select all

position_text = position
Just to check if the error is in that line.
So this is how how line 43 - 63 looks like

Code: Select all

 output = json:decode(result)
    for key,value in pairs(output.content) do
      if value.name == credentials.devicename then
        lon = value.location.longitude
        lat = value.location.latitude
        distance = math.sqrt(((lon - homelongitude) * 111.320 * math.cos(math.rad(lat)))^2 + ((lat - homelatitude) * 110.547)^2)  -- approximation
        print(distance)
        position = address(lon,lat)
        print(lon)
        print(lat)
        position_text = position
        if otherdevices['Positie ' .. user] ~= position_text then
        print(position)
          table.insert(commandArray,{['UpdateDevice'] = otherdevices_idx['Position' .. user] .. '|0|' .. position_text})
        end
        --print('iPhone ' .. user .. ': ' .. math.floor(distance*100+0.5)/100 .. ' km van huis')
        if distance < radius  then
          if otherdevices['iPhone ' .. user] == 'Off' then
            commandArray['iPhone ' .. user] = 'On'
            table.insert(commandArray, {['SendNotification'] = 'Presence update#' .. user .. ' came home'})
          end
And this is what the log gave me

Code: Select all

2016-09-13 16:20:02.705 LUA: 7.0290946470269
2016-09-13 16:20:03.110 LUA: 11.945359166723
2016-09-13 16:20:03.111 LUA: 57.665628427693
2016-09-13 16:20:03.111 LUA: Gruvgatan 39A, 421 30 Västra Frölunda, Sweden
2016-09-13 16:20:03.111 Error: EventSystem: in Iphone: [string "-- Script to check the location of multiple i..."]:56: attempt to concatenate field '?' (a nil value)

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:26
by mcmikev
Tried this as well on my RPI2b but no luck.
Placed the json.lua file in /home/pi folder and placed that patch in the line json = require('/home/pi/json.lua')

Followed the instuctions but get error :

Code: Select all

2016-09-13 16:23:00.503 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_checkphones.lua: /home/pi/domoticz/scripts/lua/script_time_checkphones.lua:10: module '/home/pi/json.lua' not found:
no field package.preload['/home/pi/json.lua']
no file '/usr/local/share/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/share/lua/5.2//home/pi/json/lua/init.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua/init.lua'
no file './/home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2//home/pi/json.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json.so'
Any pointers for me to point me in the right direction?

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:31
by cattoo
mcmikev wrote:Tried this as well on my RPI2b but no luck.
Placed the json.lua file in /home/pi folder and placed that patch in the line json = require('/home/pi/json.lua')

Followed the instuctions but get error :

Code: Select all

2016-09-13 16:23:00.503 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_checkphones.lua: /home/pi/domoticz/scripts/lua/script_time_checkphones.lua:10: module '/home/pi/json.lua' not found:
no field package.preload['/home/pi/json.lua']
no file '/usr/local/share/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/share/lua/5.2//home/pi/json/lua/init.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua/init.lua'
no file './/home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2//home/pi/json.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json.so'
Any pointers for me to point me in the right direction?

Try this

Code: Select all

json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:31
by cattoo
cattoo wrote:
mcmikev wrote:Tried this as well on my RPI2b but no luck.
Placed the json.lua file in /home/pi folder and placed that patch in the line json = require('/home/pi/json.lua')

Followed the instuctions but get error :

Code: Select all

2016-09-13 16:23:00.503 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_checkphones.lua: /home/pi/domoticz/scripts/lua/script_time_checkphones.lua:10: module '/home/pi/json.lua' not found:
no field package.preload['/home/pi/json.lua']
no file '/usr/local/share/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/share/lua/5.2//home/pi/json/lua/init.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua/init.lua'
no file './/home/pi/json/lua.lua'
no file '/usr/local/lib/lua/5.2//home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json/lua.so'
no file '/usr/local/lib/lua/5.2//home/pi/json.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './/home/pi/json.so'
Any pointers for me to point me in the right direction?

Try this

Code: Select all

json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
and put the JSON file in the same folder

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 16:52
by mcmikev
Thx for the quick response. No error anymore.

But I cannot see if it works either.

I am at home and the virutal switch is off and stays off. When I turn it ON then it remains on.
The virtual text switch also stays at Hello WORLD.
I named the switch iPhone Mike and that is also what is in the script.
Should the text dummy alsy be named Position Mike or iPhone Mike or remain it as Position Person1 ?

PS: Not sure if it matters but I have no icloud email but my own personal email but I guess that this is not the reason why.

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 17:04
by mvzut
mcmikev wrote:Thx for the quick response. No error anymore.

But I cannot see if it works either.

I am at home and the virutal switch is off and stays off. When I turn it ON then it remains on.
The virtual text switch also stays at Hello WORLD.
I named the switch iPhone Mike and that is also what is in the script.
Should the text dummy alsy be named Position Mike or iPhone Mike or remain it as Position Person1 ?

PS: Not sure if it matters but I have no icloud email but my own personal email but I guess that this is not the reason why.
The text dummy should be called "Position Mike". In the "users" array, you should also replace "Person1" with "Mike".
It shouldn't matter that you don't have an icloud email address, I don't use one either.

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 17:05
by mvzut
Lisa wrote:
mvzut wrote:Download a lua JSON decoder, e.g. this one: http://regex.info/blog/lua/json
What's wrong with this one? https://www.domoticz.com/wiki/Lua_-_json.lua
You're right, that one can probably also perfectly be used. I just happened to find the other one first ;-)

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 18:02
by Egregius
Could it be that you need to manually update the text sensor once it a text like "Westlaan 401-407, 8800 Roeselare (6.7 km)"?

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 18:23
by joto
Hi
Nice script but I'm stuck in my troubleshooting...
I get this error:

Code: Select all

2016-09-13 18:10:01.237 Error: EventSystem: in C:\Program Files\Domoticz\scripts\lua\script_time_checkphones.lua: ...m Files\Domoticz\scripts\lua\script_time_checkphones.lua:40: attempt to concatenate global 'stage2server' (a nil value)
I've tried debugging and it seems like the result in line 37 is empty.

Code: Select all

 -- Array of users to be checked
  users = {
            Tobbe = {username = 'myUser' ; password = 'MyPass' ; devicename = 'MyDevice'};
          }--  Person2  = {username = '[email protected]' ; password = 'password2' ; devicename = 'iPhone Person2'}
          --  Person3  = {username = '[email protected]' ; password = 'password3' ; devicename = 'iPhone Person3'}
          
  -- The latitude and longitude of your house (use Google Maps or similar to find this)
   
  homelongitude = 57.625103
  homelatitude = 11.892845
  -- Radius (in km) which will be used to determine if a device is at home
  radius = 0.3

  function address(longitude, latitude)
    command = "curl -s https://maps.googleapis.com/maps/api/geocode/json?latlng=" .. latitude .. "," .. longitude .. "&sensor=false"
    local handle = io.popen(command)
    local result = handle:read("*a")
    handle:close()
    output = json:decode(result)
    return output.results[1].formatted_address
  end

  for user,credentials in pairs(users) do
    stage1command = "curl -s -X POST -D - -o /dev/null -L -u '" .. credentials.username .. ":" .. credentials.password .. "' -H 'Content-Type: application/json; charset=utf-8' -H 'X-Apple-Find-Api-Ver: 2.0' -H 'X-Apple-Authscheme: UserIdGuest' -H 'X-Apple-Realm-Support: 1.0' -H 'User-agent: Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)' -H 'X-Client-Name: iPad' -H 'X-Client-UUID: 0cf3dc501ff812adb0b202baed4f37274b210853' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' https://fmipmobile.icloud.com/fmipservice/device/" .. credentials.username .."/initClient"
    local handle = io.popen(stage1command)
    local result = handle:read("*a")   --!! result is empty???
    handle:close()
    stage2server = string.match(result, "X%-Apple%-MMe%-Host%:%s(.*%.icloud%.com)")
    stage2command = "curl -s -X POST -L -u '" .. credentials.username .. ":" .. credentials.password .. "' -H 'Content-Type: application/json; charset=utf-8' -H 'X-Apple-Find-Api-Ver: 2.0' -H 'X-Apple-Authscheme: UserIdGuest' -H 'X-Apple-Realm-Support: 1.0' -H 'User-agent: Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)' -H 'X-Client-Name: iPad' -H 'X-Client-UUID: 0cf3dc501ff812adb0b202baed4f37274b210853' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' https://" .. stage2server .. "/fmipservice/device/" .. credentials.username .."/initClient"
    local handle = io.popen(stage2command)
    local result = handle:read("*a")
	handle:close()

    output = json:decode(result)
Any Ideas where to go next...

Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 18:27
by mvzut
Egregius wrote:Could it be that you need to manually update the text sensor once it a text like "Westlaan 401-407, 8800 Roeselare (6.7 km)"?
I guess you could be right! At first, I didn't have the check that it was only updated when the difference with the previous position was large enough. I get the previous distance from the contents of the text field, so when that doesn't contain "(x.x km)" it will never be updated. I have added a line in the script

Code: Select all

if prev_distance == nil then prev_distance = 1000 end
See original post where it needs to be placed. Can you let me know if this helps?

Re: Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 19:26
by mcmikev
Well there are no errors visible and It looks like it is running but the switches are not updates , and the position is also not changing.

How can I check to make sure the script is working really as it should?

Find My iPhone implementation in LUA script

Posted: Tuesday 13 September 2016 19:46
by mvzut
joto wrote:Hi
Nice script but I'm stuck in my troubleshooting...
I get this error:

Code: Select all

2016-09-13 18:10:01.237 Error: EventSystem: in C:\Program Files\Domoticz\scripts\lua\script_time_checkphones.lua: ...m Files\Domoticz\scripts\lua\script_time_checkphones.lua:40: attempt to concatenate global 'stage2server' (a nil value)
I've tried debugging and it seems like the result in line 37 is empty.

[...]

Any Ideas where to go next...
If stage 1 doesn't result in a value for stage2server that can, I think, only mean that either you didn't activate Find My iPhone on your phone, or your credentials are not filled in correctly in the script. Do you have exotic characters in your password?