So I have been working on the same issue for about a year now. I got it to work on my mac fairly quickly, but had a lot of trouble getting it to work right on my PC. I have tried many many different approaches. I have a home automation system that turns on the heating and hot water (via an arduino and RF module) when I or my partner are home (that is our iPhones are detectable on the home WiFi). In the end I used 'nslookup' to find the IP address for the iPhones (in case the IP address did change as they are dynamic (but they actually never do on my router)) and 'nmap' to detect if the iPhone is on the network. If the iPhone is in very deep sleep 'nmap' does not always find the phone, so I have made it check 10 times before it says the phone is not home. Below is part of my home automation code in python. I have used threading. Any questions with the below code let me know.
# Dictionary to store variables to reuse on program restart
v = {
'boilerControlCH' : 'HIH', # 'scheduled' or 'HIH' (Honey I'm Home)
'boilerControlHW' : 'scheduled',
'thermostatSetPoint' : 20.8,
'thermostatVariance' : 0.1,
'morningTime' : datetime(1970,1,1,6,0,0),
'nightTime' : datetime(1970,1,1,23,0,0),
'someOneHome' : False,
'guest' : False,
'minimumTemperatureOO' : False,
'minimumTemperature' : 4.0,
'iPhoneMark' : {'iPhoneHostname' : 'marks-iphone', 'home' : False},
'iPhoneJessica' : {'iPhoneHostname' :'jessicaesiphone', 'home' : False}
}
and
[code] # Check if anyone at home def occupancyStatus(person, Bol = False): with lockOccupancyStatus: someOneHome = False
if 'iPhone' in person:
v[person]['home'] = Bol
elif 'retest' in person:
pass
else:
v[person] = Bol
if v['guest'] == True:
someOneHome = True
for key in v:
if 'iPhone' in key:
if v[key]['home'] == True:
someOneHome = True
v['someOneHome'] = someOneHome
variablesToFile()
return
[/code] and the main code
[code] # iPhone home status threading code class nmapClass(threading.Thread): def init(self): threading.Thread.init(self) def run(self): global exitCounter
nmapThread()
msg.log('Exited nmapThread')
waitEvent.set()
waitEventAdjustable.set()
serialDataWaiting.set()
exitCounter += 1
def nmapThread():
iPhone = {}
maxCounts = 10
for phone in v:
if 'iPhone' in phone:
iPhone[phone] = {}
iPhone[phone]['hostname'] = v[phone]['iPhoneHostname']
iPhone[phone]['count'] = maxCounts
#msg.log(iPhone)
while exitFlag[0] == 0:
for phone in iPhone:
if iPhone[phone]['count'] > 0:
phoneFound = False
IPAddress = '0.0.0.0'
# Find iPhones IP address using its hostname
commandNsloolup = 'nslookup %s' %iPhone[phone]['hostname']
childNslookup = pexpect.popen_spawn.PopenSpawn(commandNsloolup, timeout = None)
output = childNslookup.readline()
while '\r\n' in output:
#msg.log(output)
if 'Name:' in output:
output = childNslookup.readline()
if 'Address:' in output:
tempStr = output
startPoint = tempStr.find('192')
tempStr = tempStr[startPoint:]
IPAddress = tempStr.replace('\r\n', '')
#msg.log(IPAddress)
output = childNslookup.readline()
if IPAddress == '0.0.0.0':
pass
#msg.error('Error finding IP address for %s' %iPhone[phone]['hostname'], GFI(CF()).lineno)
else:
#commandNmap = 'nmap -PR -sn %s' %IPAddress
#commandNmap = 'nmap -p 62078 -Pn %s' %IPAddress # -p specifies ports to try and access, -Pn removes pinging
commandNmap = 'nmap -p 62078 --max-rate 100 %s' %IPAddress
childNmap = pexpect.popen_spawn.PopenSpawn(commandNmap, timeout = None)
output = childNmap.readline()
while '\r\n' in output:
if 'Host is up' in output:
phoneFound = True
break
output = childNmap.readline()
#if phoneFound:
# break
if phoneFound:
iPhone[phone]['count'] = 0
if v[phone]['home'] == False:
msg.log('%s\'s iPhone has returned home' %phone)
occupancyStatus(phone, True)
waitEventAdjustable.set()
#else:
#msg.log('%s\'s iPhone still at home' %phone)
else:
iPhone[phone]['count'] -= 1
if v[phone]['home'] == True and iPhone[phone]['count'] == 0:
msg.log('%s\'s iPhone has left home' %phone)
occupancyStatus(phone, False)
waitEventAdjustable.set()
#else:
#msg.log('%s\'s iPhone still away from home' %phone)
elif iPhone[phone]['count'] < 0:
msg.error('Error with count variable in iPhone dictionary', GFI(CF()).lineno)
longWait = True
for phone in iPhone:
if iPhone[phone]['count'] > 0:
longWait = False
#msg.log('%s: %s' %(phone, iPhone[phone]['count']))
if longWait:
#msg.log('wait long')
# 600 = run every 10 minutes
waitEvent.wait(timeout=600)
for phone in iPhone:
iPhone[phone]['count'] = maxCounts
else:
#msg.log('wait short')
waitEvent.wait(timeout=60)
return[/code]
The code may not work if you copy it straight into your own script, as there are some parts missing which I have not copied to try and keep things simple and easy to read, but hopefully the above code gives everyone a sense of how I did things.