Find My iPhone implementation in LUA script

Moderator: leecollings

ropske
Posts: 483
Joined: Tuesday 12 August 2014 5:37
Target OS: Raspberry Pi / ODroid
Domoticz version: V3_8394
Location: Rumbeke,Belgium
Contact:

Re: Find My iPhone implementation in LUA script

Post by ropske »

Hi,
sorry, i was indeed not really clear :p
i have indeed a print(position_text) so it shows up in my domoticz log
here i see a link that i can press and it opens a popup with visible location from google maps

but in in device with text sensor, i can see the string location, but it's not a link there, so i does not open a popup

thank you
Nautilus
Posts: 722
Joined: Friday 02 October 2015 12:12
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Finland
Contact:

Re: Find My iPhone implementation in LUA script

Post by Nautilus »

And you are updating the text sensor with exactly the same "position text"? The position changes correctly in the text sensor? Do you see the link text (beginning with "<a") or just the location. If not, are you sure you cannot click it?

Maybe some screenshots and code snippets would be in order to troubleshoot further...:)
ropske
Posts: 483
Joined: Tuesday 12 August 2014 5:37
Target OS: Raspberry Pi / ODroid
Domoticz version: V3_8394
Location: Rumbeke,Belgium
Contact:

Re: Find My iPhone implementation in LUA script

Post by ropske »

hmm, now it's suddenly working, seems i forgot to do a 'refresh' of the page lol
sorry to disturb ;)
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

I can't seem to get this working but have no visible errors...

The script is in place and no errors on system log for Domoticz, I know it's running as if I edit it to say blah somewhere then every minute it complains in the log about 'blah'

I created a hardware device called Freds iPhone, then two dummy devices off this a text one for "Position Fred" and a switch "iPhone Fred".

Code: Select all

-- Array of users to be checked
  users = {
        Fred = {username = "[email protected]" ; password = "fred" ; devicename = "Fred's iPhone"};
          }
  -- The latitude and longitude of your house (use Google Maps or similar to find this)
  homelongitude = -121.886329
  homelatitude = 37.338208
  -- Radius (in km) which will be used to determine if a device is at home
  radius = 1
The Device name in the script matches how it's presented in iCloud, it doesn't match the dummy hardware device in Domoticz as it seems you can't have ' in the name, maybe a bug in Domoticz?
The long/latitude are San Jose so it should trigger :)
The switch is permanently off, the text field just has hello world from when I created it.

What can I do to check it's running/working etc?
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

Mine just stopped working with no changes to the script, is anyone else having issues?

Code: Select all

2017-01-15 14:54:01.970 Error: EventSystem: in iPhoneLocation: [string "-- Script to check the location of multiple i..."]:38: attempt to concatenate global 'stage2server' (a nil value)
Tried PHP-FindMyiPhone (https://github.com/albeebe/PHP-FindMyiPhone) as well which I previously used for testing but getting:

Code: Select all

* Could not resolve host: https
Wondering if Apple have changed the API in some way?
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
User avatar
Egregius
Posts: 2592
Joined: Thursday 09 April 2015 12:19
Target OS: Linux
Domoticz version: v2024.7
Location: Beitem, BE
Contact:

Re: Find My iPhone implementation in LUA script

Post by Egregius »

The PHP implementation works fine here.
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

This is a more efficient version of the script which also solved the below error message RE stage2server that I was receiving:

Code: Select all

2017-01-15 14:54:01.970 Error: EventSystem: in iPhoneLocation: [string "-- Script to check the location of multiple i..."]:38: attempt to concatenate global 'stage2server' (a nil value)
New code:

Code: Select all

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 = (loadfile "/root/domoticz/scripts/lua/JSON.lua")()

  -- Array of users to be checked
  users = {
            Ben = {username = "USERNAME" ; password = "PASSWORD" ; devicename = "Ben's iPhone"};
                      }
  -- 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
    getlocation = "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://fmipmobile.icloud.com/fmipservice/device/" .. credentials.username .."/initClient"
    local handle = io.popen(getlocation)
    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, ', Australia', '') .. ' (' .. (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
It's possible to get all the information needed from iCloud without the stage1 / stage2 servers in the original script. This curl command can get everything:

curl -s -X POST -L -u 'USERNAME: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/fmipservi ... initClient'

Simply change the two USERNAME and one PASSWORD fields to get all the data.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Tried code above, again no errors but I'm seeing nothing written to me Switch or Text sensor.

I'm assuming you just need to match the "users = { Ben " bit from the script to your "iPhone Ben" and "Ben Position" devices?
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

Yes it should just map to those devices in Domoticz,

You should see it updating in the status log tab:
Screen Shot 2017-01-16 at 2.46.35 am.png
Screen Shot 2017-01-16 at 2.46.35 am.png (173.4 KiB) Viewed 3670 times
Remember the Position text string will only update if you go outside the set area.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Nothing in my log :(
Can I try print(variable) in my script to see it's connecting properly to something and getting data?
BTW I set the long/latitude to no where near I live so it should trigger.
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

Try adding

print (getlocation) under getlocation, see what that shows.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

This version also gets the iPhone battery level, which is really cool cause Domoticz can chart how long my iPhone lasts on battery power. :D

Just add a percentage sensor device called: iPhone Battery USER (in my case USER is Ben)
Screen Shot 2017-01-16 at 6.31.49 am.png
Screen Shot 2017-01-16 at 6.31.49 am.png (23.93 KiB) Viewed 3600 times
Screen Shot 2017-01-16 at 3.14.44 am.png
Screen Shot 2017-01-16 at 3.14.44 am.png (79.77 KiB) Viewed 3665 times

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 = (loadfile "/root/domoticz/scripts/lua/JSON.lua")()

  -- Array of users to be checked
  users = {
            Ben = {username = "USERNAME" ; password = "PASSWORD" ; devicename = "Ben's iPhone"};
                      }
  -- 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
    getlocation = "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: d98c8ae0db3311e687b92890643032df' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' https://fmipmobile.icloud.com/fmipservice/device/" .. credentials.username .."/initClient"
    local handle = io.popen(getlocation)
    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
        bat = value.batteryLevel * 100 / 1
        powerstateval = value.batteryStatus
        table.insert(commandArray,{['UpdateDevice'] = otherdevices_idx['iPhone Battery ' .. user] .. '|0|' .. bat})
        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, ', Australia', '') .. ' (' .. (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, ' .. bat .. '% battery remaining. PowerState: '.. powerstateval ..' ')
        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
Last edited by ben53252642 on Sunday 15 January 2017 20:33, edited 2 times in total.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Ok with print (getlocation) I get.

Code: Select all

2017-01-15 16:33:00.105 LUA: curl -s -X POST -L -u '[email protected]:pass' -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/[email protected]/initClient
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

Calzor Suzay wrote:Ok with print (getlocation) I get.

Code: Select all

2017-01-15 16:33:00.105 LUA: curl -s -X POST -L -u '[email protected]:pass' -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/[email protected]/initClient
Try print (result) above handle:close() but under getlocation
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Well that gives me a whole bunch of stuff so looks like it's logging on ok

Code: Select all

2017-01-15 17:13:01.948 LUA: {"userInfo":{"firstName":"Fred","lastName":"Bloggs","membersInfo":null,"hasMembers":false},"serverContext":{"minCallbackIntervalInMS":5000,"enable2FAFamilyActions":false,"preferredLanguage":"en-gb","lastSessionExtensionTime":null,"enableMapStats":true,"callbackIntervalInMS":2000,"validRegion":true,"timezone":{"currentOffset":0,"previousTransition":1477789199999,"previousOffset":3600000,"tzCurrentName":"+00:00","tzName":"Europe/London"},"authToken":"AQAAAABYZAStk2LWr-potc~","maxCallbackIntervalInMS":60000,"classicUser":false,"isHSA":false,"trackInfoCacheDurationInSecs":86400,"imageBaseUrl":"https://statici.icloud.com","minTrackLocThresholdInMts":100,"maxLocatingTime":90000,"sessionLifespan":900000,"info":"Bh7nojqtLwCe6rDjgkpwtvlxJrjwoU8eu6iFQUgrSWh","prefsUpdateTime":1416502995675,"useAuthWidget":false,"clientId":"ZGV8xNDg0NTAwMzgxODc4","enable2FAFamilyRemove":false,"serverTimestamp":1484500381884,"macCount":0,"deviceLoadStatus":"200","maxDeviceLoadTime":60000,"prsId":616046716,"showSllNow":false,"cloudUser":true,"enable2FAErase":false},"alert":null,"userPreferences":{"touchPrefs":{}},"content":[{"msg":null,"canWipeAfterLock":true,"wipeInProgress":false,"lostModeEnabled":false,"activationLocked":true,"passcodeLength":6,"deviceStatus":"200","deviceColor":"3b3b3c-b4b5b9","features":{"MSG":true,"LOC":true,"LLC":false,"CLK":false,"TEU":true,"LMG":false,"SND":true,"CLT":false,"LKL":false,"SVP":false,"LST":true,"LKM":false,"WMG":true,"XRM":false,"PIN":false,"LCK":true,"REM":false,"CWP":false,"KEY":false,"KPD":false,"WIP":true},"lowPowerMode":false,"rawDeviceModel":"iPhone7,2","id":"pDHwh4/AuHYVNSUzmWV","remoteLock":null,"isLocating":true,"modelDisplayName":"iPhone","lostTimestamp":"","batteryLevel":0.55,"mesg":null,"locationEnabled":true,"lockedTimestamp":null,"locFoundEnabled":false,"snd":null,"fmlyShare":false,"lostDevice":null,"lostModeCapable":true,"wipedTimestamp":null,"deviceDisplayName":"iPhone 6","prsI
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

It's probably not having a JSON.lua in the location that's specified in the path:

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

Read the first post, download the JSON.lua and specify the path to it.
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Mine is json = (loadfile "/home/osmc/domoticz/scripts/lua/JSON.lua")()
and it works as when I didn't have it I got loads or errors in the log appear, I downloaded the one mentioned in the link and then chown the script and JSON.lua file to OSMC:OSMC as that's the OS I run.

osmc@osmc:~/domoticz/scripts/lua$ ls -l
total 68
-rw-r--r-- 1 osmc osmc 55197 Jan 15 17:28 JSON.lua
-rw-r--r-- 1 osmc osmc 1870 Oct 19 15:11 script_device_demo.lua
-rw-r--r-- 1 osmc osmc 3535 Jan 15 17:33 script_time_checkphones.lua
-rw-r--r-- 1 osmc osmc 1932 Oct 19 15:11 script_time_demo.lua

I re downloaded to it to check.
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

Ok with this in the code

Code: Select all

    output = json:decode(result)
   for key,value in pairs(output.content) do
print ("Before If")
print (value.name)
print (credentials.devicename)
print (value.location.longitude)
print (value.location.latitude)
      if value.name == credentials.devicename then
        lon = value.location.longitude
        lat = value.location.latitude
print (lon)
print ("after if")
I get

Code: Select all

2017-01-15 17:47:01.878 LUA: Before If
2017-01-15 17:47:01.878 LUA: Fred’s iPhone
2017-01-15 17:47:01.878 LUA: Fred's iPhone
2017-01-15 17:47:01.878 LUA: 0.25754617542079
2017-01-15 17:47:01.878 LUA: 50.837107226956
*Name & location tweaked :)

Edit just noticed the different apostrophe... :)
ben53252642
Posts: 543
Joined: Saturday 02 July 2016 5:17
Target OS: Linux
Domoticz version: Beta
Contact:

Re: Find My iPhone implementation in LUA script

Post by ben53252642 »

So is it working now? It's got to be something simple, your previous post showed an iPhone battery level (0.55 translates to 55%) so it's getting the data...

You sure you named the devices right? "iPhone Fred" etc...
Unless otherwise stated, all my code is released under GPL 3 license: https://www.gnu.org/licenses/gpl-3.0.en.html
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Find My iPhone implementation in LUA script

Post by Calzor Suzay »

No I can't match the apostrophe it's using in the name of the phone.

It wants this which I copied pasted from the log ’
The only two I have are '` which don't match.
I thought I'd copy from the log into Putty directly but it translates it to a .

So then I thought I'd FTP the file off, edit in to Notepad++ which worked and Ftp'd back but then it changes it to "Freds ^ ^ s iPhone"

Do I have sort of language, keyboard mapping weirdness?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 1 guest