Find My iPhone implementation in LUA script

Moderator: leecollings

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 »

Ahh I had the same issue with mine:

"Ben's iPhone"

in my case changing the single quotes to " allowed it to accept the single ' in my name.
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 »

I don't think it's that there's " " around either side

I think It's the fact I physically can't get a ’ into my Raspberry Pi.
I've just tried changing locale's UTF8, en_GB.ISO-8859-15 to no effect.

I could recall the iPhones and change there name but it's bugging me now :)
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 »

SSH into the Pi and use nano?
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 »

Actually you know you can just use the script editor in Domoticz right?

Mine is setup like this:
Screen Shot 2017-01-16 at 5.58.36 am.png
Screen Shot 2017-01-16 at 5.58.36 am.png (70.32 KiB) Viewed 4348 times
You don't actually have to put the script in the lua scripts folder of Domoticz, it can run from the web interface scripts UI just fine.
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 »

I was using nano via SSH and no I didn't know you could edit LUA scripts on the webpage gui.
/long breath, AHHHHHHHhhhhhh! , and smile :)
It seems to be working now as expected, thanks for your help.

I've deleted the old .lua script from the folder and rebooted but it does still seem to be running it as I'm seeing all the print commands I added still appear... How do I remove it?
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 »

Think I've sorted extra script now as well :)
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 »

And battery details logging as well, awesome :)
blindlight
Posts: 4
Joined: Wednesday 11 January 2017 16:00
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Find My iPhone implementation in LUA script

Post by blindlight »

ben53252642 wrote: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 3.14.44 am.png

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
getlocation works, but my battery level is still 0.0.
maybe some region problem. i'm in Shanghai.
aleguid
Posts: 3
Joined: Wednesday 08 February 2017 17:18
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.6653
Location: Italy
Contact:

Re: Find My iPhone implementation in LUA script

Post by aleguid »

are a new user, I followed the instructions but in the end the result is null. I have no errors in the logs and the dummy created are unchanged. you have any idea?

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 = 1
local m = os.date('%M')
if (m % interval == 0) then

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

  -- Array of users to be checked
  users = {
            Alessio = {username = "mailmyaccount" ; password = "passwordmyaccount" ; devicename = "iPhone Alessio"};
                      }
  -- The latitude and longitude of your house (use Google Maps or similar to find this)
  homelongitude = 11.868779
  homelatitude = 43.566226
  -- Radius (in km) which will be used to determine if a device is at home
  radius = 0.1

  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, ', Italia', '') .. ' (' .. (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
thx
dvangulik
Posts: 1
Joined: Tuesday 21 February 2017 22:57
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Find My iPhone implementation in LUA script

Post by dvangulik »

Hi guys, I am using Ben's implementation of the LUA script and it is working great. Thanks for that it would not have worked for me without your guidance. What leads me to my question. In my log it prints the power status; not charging or charging. I would like to use this data for some automation. Can you please help me to either create a virtual switch (charging; on, not charging: off) or a way to use the printed information in events? Thanks in advance for your support, it will be much appreciated.
cattoo
Posts: 60
Joined: Sunday 20 September 2015 17:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2.3072
Location: Sweden
Contact:

Re: Find My iPhone implementation in LUA script

Post by cattoo »

Now I got this error, don't know why. Anyone?

Code: Select all

Error: EventSystem: in Check_iphone: [string "-- Script to check the location of multiple i..."]:10: attempt to call a nil value
rjblake
Posts: 142
Joined: Friday 21 October 2016 9:25
Target OS: NAS (Synology & others)
Domoticz version:
Location: Netherlands
Contact:

Re: Find My iPhone implementation in LUA script

Post by rjblake »

I used this for a while and while it worked mostly, there were times where it didn't update battery, or returned battery as 0%. No idea why, perhaps it was picking up other devices (e.g. iMac) for some reason, or perhaps Apple didn't feel like responding everytime.
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 »

cattoo wrote:Now I got this error, don't know why. Anyone?

Code: Select all

Error: EventSystem: in Check_iphone: [string "-- Script to check the location of multiple i..."]:10: attempt to call a nil value
It would help to know what is line 10 in your script :) The error could e.g. relate to a variable that is not given any value ( = nil).
rjblake wrote:I used this for a while and while it worked mostly, there were times where it didn't update battery, or returned battery as 0%. No idea why, perhaps it was picking up other devices (e.g. iMac) for some reason, or perhaps Apple didn't feel like responding everytime.
I've noticed that the battery level is quite often empty or 0%. I've chosen to ignore these in the script. As a presence detection method (that is based on the location of iPhone), this has been the most reliable so far. All geofence apps, pinging / arp scanning etc. have more or less failed or have been unreliable...:)
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 »

dvangulik wrote:Hi guys, I am using Ben's implementation of the LUA script and it is working great. Thanks for that it would not have worked for me without your guidance. What leads me to my question. In my log it prints the power status; not charging or charging. I would like to use this data for some automation. Can you please help me to either create a virtual switch (charging; on, not charging: off) or a way to use the printed information in events? Thanks in advance for your support, it will be much appreciated.
In the script, you need a new variable (similar to lon / lat / batterystatus )and then store the charging status to it, the json output tells you how you need to define it, comapre to e.g. batterystatus:

Code: Select all

powerstateval = value.batteryStatus
(hint: look vor value and batteryStatus in the json output)

Then just create a virtual on / off switch and check it's current status and update it whether it is different than it is supposed to be :)
cattoo
Posts: 60
Joined: Sunday 20 September 2015 17:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2.3072
Location: Sweden
Contact:

Re: Find My iPhone implementation in LUA script

Post by cattoo »

Nautilus wrote:
cattoo wrote:Now I got this error, don't know why. Anyone?

Code: Select all

Error: EventSystem: in Check_iphone: [string "-- Script to check the location of multiple i..."]:10: attempt to call a nil value
It would help to know what is line 10 in your script :) The error could e.g. relate to a variable that is not given any value ( = nil).
rjblake wrote:I used this for a while and while it worked mostly, there were times where it didn't update battery, or returned battery as 0%. No idea why, perhaps it was picking up other devices (e.g. iMac) for some reason, or perhaps Apple didn't feel like responding everytime.
I've noticed that the battery level is quite often empty or 0%. I've chosen to ignore these in the script. As a presence detection method (that is based on the location of iPhone), this has been the most reliable so far. All geofence apps, pinging / arp scanning etc. have more or less failed or have been unreliable...:)
It was the JSON script placement thats was wrong. But now I have a other issue
Error: EventSystem: in Check_iphone: [string "-- Script to check the location of multiple i..."]:38: bad argument #1 to 'pairs' (table expected, got nil)
Line 38 is the "for key" part

Code: Select all

output = json:decode(result)
    for key,value in pairs(output.content) do
      if value.name == credentials.devicename then
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 »

I would add some print statements to see if you are getting the expected responses from the curl fetches. Check previous page in this thread and what ben... suggests :) Now it seems you are not getting the expected response. You can also try the curl from command line to make sure it works. One reason could be exotic iPhone name or password that contain some lua magic characters.
Last edited by Nautilus on Wednesday 01 March 2017 13:13, edited 1 time in total.
cattoo
Posts: 60
Joined: Sunday 20 September 2015 17:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2.3072
Location: Sweden
Contact:

Re: Find My iPhone implementation in LUA script

Post by cattoo »

Well I added this print (result) above handle:close() but under getlocation
and got my user info, token, current timezone and stuff like that. So it seems that I get logged in.
But when when ill add print (getlocation)
I get

Code: Select all

 LUA: 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: DELETED' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' 'https://fmipmobile.icloud.com/fmipservice/device/USERNAME/initClient'
why is it like this?
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 »

cattoo wrote:Well I added this print (result) above handle:close() but under getlocation
and got my user info, token, current timezone and stuff like that. So it seems that I get logged in.
But when when ill add print (getlocation)
I get

Code: Select all

 LUA: 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: DELETED' -H 'Accept-Language: en-us' -H 'Connection: keep-alive' 'https://fmipmobile.icloud.com/fmipservice/device/USERNAME/initClient'
why is it like this?
That is just printing just the curl command. It is used in the next line (io.popen). Then the interesting stuff after this is json decoding which I guess is not working as expected. The result of "output = json:decode(result)" is something faulty. How did you define the json file location, are you sure you have it there? Is it spelled correctly in your script?
cattoo
Posts: 60
Joined: Sunday 20 September 2015 17:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2.3072
Location: Sweden
Contact:

Re: Find My iPhone implementation in LUA script

Post by cattoo »

The file is located here
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")(
And I've checked and the JSON file is there.
rjblake
Posts: 142
Joined: Friday 21 October 2016 9:25
Target OS: NAS (Synology & others)
Domoticz version:
Location: Netherlands
Contact:

Re: Find My iPhone implementation in LUA script

Post by rjblake »

Nautilus wrote:...
I've noticed that the battery level is quite often empty or 0%. I've chosen to ignore these in the script. As a presence detection method (that is based on the location of iPhone), this has been the most reliable so far. All geofence apps, pinging / arp scanning etc. have more or less failed or have been unreliable...:)
Indeed - I do really like the functionality being able to log location and for the rest worked well. Wish my code was half as useful or tidy. Battery drain seemed a bit high if polled too often. I am experimenting with an app 'Locative' that I have found works really well too and only needs config on the phone. Also trying to work out how to exploit my Tado app and perhaps just use that, as it does its job just fine for the Thermostat
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest