10

I'm working remotely and it would be handy to know when someone has gone out for a meeting / lunch in my office.

I thought I might be able to passively detect what phones near the raspberry pi (and then publish them to the web / dropbox / whatever)

What would be the easiest way to do this? MAC address detection? Bluetooth?

10

Much hunting - learned quite a bit - no luck detecting other peoples devices without much of a low level wireless scan - Bluetooth works for iphone if both are your own devices:

  1. Wifi scan might work for some devices, but iOS ones do not connect when screen is off! My iphone 6 could be detected with simple arp command (gives table of ip and mac numbers of connected devices on the same subnet) but this would happen only when phone screen is lighted up. Once the phone screen sleeps - it is out of bounds on wifi! I bet this is in the interest of battery life.

  2. Bluetooth dongle worked. No distance computation unlike some fancy algorithms out there - just present/absent can be done with very little power consumption on rPi and iPhone. Install bluetooth dongle on rPi as: (sudo aptitude install bluetooth bluez-utils bluez-compat). Figure out mac of your phone device by making it searchable and then do (hcitool scan) on rPi. Then connect to your device (make sure its searchable) as: sudo bluez-simple-agent hci0 mac_of_your_device and say yes on both sides. Then sudo bluez-test-device trusted mac_of_your_device. Now they both "know" each other. Then do sudo hcitool name mac_of_your_device in your favourite script to figure out if the iphone is nearby. This will not create a connection - but just say hi to it. If it returns a name, phone is nearby. If it returns nothing - phone is not nearby or bluetooth is switched off. Compared to creating connections or other distance computation methods out there - this method conserves battery on both sides and keeps airwave pollution to a minimum.

9

Me and some friends of mine have been developing a bluetooth-proximity scanner to open our front door lock of our hackerspace.

We've paired all allowed devices and essentially used hcitool to test if one of the paired device is nearby. As an example, if the paired device has the adress "00:00:00:00:00:00", you would do this on the command line console:

hcitool cc 00:00:00:00:00:00 && hcitool auth 00:00:00:00:00:00 && hcitool dc 00:00:00:00:00:00;

If this returns zero, the device is in proximity.

One downside is that this will take ~5 seconds to time-out if the device isn't nearby.

We have published the source-code on Github under the apache open-source licence.

  • 2
    I can confirm that this is working using hcitool .... However, you have to chain the commands like in the example given above. The connection is only active for a very short amount of time. You can add proximity into the mix by doing hcitool rssi .... – Gunnar Nov 21 '16 at 9:16
2

I have seen some setups using bluetooth for similar use cases, but it will probably involve some hacking. The phones you want to detect are typically not in discoverable mode.

If the phones use wifi, you can probably detect some proximity, but this will also probably mean you will have to scan for them at a rather low layer, since they will not access your wifi antenna, and they will probably connect encrypted. Have a look at kismet for some low level wireless bonanza.

The easiest way to detect whether someone is in a room or not, though, I would guess, would be to use the camera module and a panaramic mirror.

1

If you have a WiFi network that they connect to when they are in the office, you could have the PI scan for MAC addresses every x period of time, and update a web page (dropbox, whatever) with current status. Probably the most reliable route.

You might be able to do something with bluetooth, and a USB Bluetooth adapter, but I have no experience with that.

Without them connected to the pi, or the network the pi is on, I don't think you will have much success.

  • Nice. So what tech/app/platform were you thinking I would use to scan the MAC addresses? – ACooleman Apr 26 '14 at 6:52
  • The way I would do it is with nmap, the command line version, and a little custom python code (I'm sure there is a python api), do a quick ping sweep/MAC query, compare that to a pre built list, use that to build a php(HTML?) page and serve it up using lightppd(Apache?) web server. Set the python job to run ever x period of time, and have the web page auto refresh every y period. It's a cool project idea... I might have to give it a shot after i finish up all the other projects that are on my plate. – Butters Apr 27 '14 at 15:24
  • You might be able to query your router for the ARP table, or you DHCP server as well... Might make it a little quicker.. – Butters Apr 27 '14 at 15:25
1

Reading the above answers also triggered me into thinking about the following possiblity:

use airmon-ng to continuously scan the network for client devices on wifi. The output can be written to a file, so if the file changes either a client has entered or left the range of the pi. Having a list of known mac addresses allows you to identify the user and due to the file changing you could trigger some actions....

it is quite an interesting idea! Thanks!

Arjen

  • Large stores use this technique to monitor how shoppers browse their goods, which rayon they skip etc. But due to privacy laws it's not always legal to link a mac address to a person in every country. – Havnar Oct 20 '14 at 11:59
1

As long as the devices are all on the same network, you can easily use a Raspberry Pi to do this.. Here's a complete project with all the code you need...

http://www.element14.com/community/people/mcollinge/blog/2014/09/12/raspberry-pi-network-spy--part-1

  • There is interesting information in the link you provide, however you could improve your answer including what answer to the question. – mpromonet Apr 25 '15 at 11:26
1

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

# 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

and the main 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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.