1

I currently have a Python 2.6 piece of code that runs two loops simultaneously. The code uses the gps (gpsd) module and the scapy module. Basically the first function (gpsInfo) contains a continual while loop grabbing GPS data from a GPS device and writing the location to console. The second function (ClientDetect) runs in a continual loop also sniffs the air for wifi data and prints this data when specific packets are found. I've threaded these two loops with the GPS one running as a background thread. What I am looking to do (and have been struggling for 5 days to work out how) is for, when the ClientDetect function finds a match and prints the respective info, I want the respective GPS coordinates of when that hit was made also printed to console. At present my code doesn't seem to work.

observedclients = [] p = ""  # Relate to wifi packet session =
gps.gps(mode=gps.WATCH_NEWSTYLE)

def gpsInfo():

    while True:
        session.poll()
        time.sleep(5)
        if gps.PACKET_SET:
            session.stream
            print session.fix.latitude + session.fix.longitude
            time.sleep(0.1)

def WifiDetect(p):
    if p.haslayer(Dot11):
        if p.type == 0 and p.subtype in stamgmtstypes:
            if p.addr2 not in observedclients:
                print p.addr2
                observedclients.append(p.addr2)  

def ActivateWifiDetect():
    sniff(iface="mon0", prn=WifiDetect)

if __name__ == '__main__':
    t = threading.Thread(target=gpsInfo)
    t.start()
    WifiDetect()

Can anybody look at my code to see how best to grab the data simultaneously for when there is a wifi hit, for the GPS coordinates to be printed too? Somebody mentioned implementing queuing but I have researched this but to no avail with regards to how to implement it.

As said, the aim of this code is to scan for both GPS and specific wifi packets and when detected, print details relating to the packet and the location where is was detected.

Ry-
  • 218,210
  • 55
  • 464
  • 476
thefragileomen
  • 1,537
  • 8
  • 24
  • 40

3 Answers3

2

A simple way of getting this is store the gps location in a global variable, and have the wifi sniffing thread read that global when it needs to print some data; The gotcha is that since two threads can be accessing the global variable at the same time, you'll want to wrap it with a mutex;

last_location = (None, None)
location_mutex = threading.Lock()

def gpsInfo():
    global last_location
    while True:
        session.poll()
        time.sleep(5)
        if gps.PACKET_SET:
            session.stream
            with location_mutex:
                # DON'T Print from inside thread!
                last_location = session.fix.latitude, session.fix.longitude
            time.sleep(0.1)

def WifiDetect(p):
    if p.haslayer(Dot11):
        if p.type == 0 and p.subtype in stamgmtstypes:
            if p.addr2 not in observedclients:
                with location_mutex:
                    print p.addr2, last_location
                    observedclients.append((p.addr2, last_location))  
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • With the mutex / lock though, won't I be stopping the GPS loop pending a wifi packet being detected? By this I mean, it may be 5 minutes before the specific wifi packet is sniffed and if so, won't the GPS location be dated as the first GPS location detected was locked pending the wifi result? – thefragileomen Sep 28 '11 at 21:12
  • No, the lock is only retained just long enough to read or write that variable, Neither thread will wait for IO at the same time that they are holding the lock. The likelihood of actually blocking on that lock is fantastically low. The only time you're likely to see this actually wait on the lock is during the time it takes for `print` to actually flush a newline to the console, which is not a long time. – SingleNegationElimination Sep 28 '11 at 21:13
  • Works a treat thanks TokenMacGuy. I've actually amended my code to grab the Unix time from the GPS device just to compare to the time the packets are detected and they are synced exactly to the second which reflects that the reported location is indeed the location at the time the packet is sniffed. – thefragileomen Sep 28 '11 at 21:47
1

you need to tell python you are using an external variable when you use gps in a function. The code should look like this:

def gpsInfo():
    global gps # new line

    while True:
        session.poll()
        time.sleep(5)
        if gps.PACKET_SET:
            session.stream
            print session.fix.latitude + session.fix.longitude
            time.sleep(0.1)


def WifiDetect(p):
    global p, observedclients # new line

    if p.haslayer(Dot11):
        if p.type == 0 and p.subtype in stamgmtstypes:
            if p.addr2 not in observedclients:
                print p.addr2
                observedclients.append(p.addr2)  
Serdalis
  • 10,296
  • 2
  • 38
  • 58
1

I think you should be more specific in your goal.

If all you want to do is get GPS coords when a Wifi network is sniffed, just do (psuedo-code):

while True:
    if networkSniffed():
        async_GetGPSCoords()

If you want a log of all GPS coords and want to match that up with Wifi network data, just print all the data out along with timestamps, and do post-processing do match up Wifi networks with GPS coords via timestamp.

Kurt Spindler
  • 1,311
  • 1
  • 14
  • 22