From a5748f18f167a8b80278c1f063eed0e0aa6d3c21 Mon Sep 17 00:00:00 2001 From: javiplx Date: Sun, 1 May 2011 19:43:28 +0000 Subject: [PATCH] MERGE : incorporate changes on cleaning branch to completelly decouple wifiview and wifiscanner git-svn-id: file:///svnroot/wifihood/trunk@104 c51dfc6a-5949-4919-9c8e-f207a149c383 --- wifiscanner/wifimap/__init__.py | 6 +- wifiscanner/wifimap/db.py | 25 ++++-- wifiscanner/wifimap/gps.py | 153 +++++++++++++++++-------------------- wifiscanner/wifimap/replay.py | 93 ++++++++++++++++++++++ wifiscanner/wifimap/scanner.py | 94 +++++++++++++++++++++++ wifiscanner/wifimap/view.py | 149 +++++++++++++++++++++++++++++++++--- wifiscanner/wifimap/wifiscan.py | 145 +++++++++++++---------------------- wifiscanner/wifiscanner.py | 113 ++++++++++++++------------- wifiscanner/wifiview.py | 161 +-------------------------------------- 9 files changed, 528 insertions(+), 411 deletions(-) create mode 100644 wifiscanner/wifimap/replay.py create mode 100644 wifiscanner/wifimap/scanner.py diff --git a/wifiscanner/wifimap/__init__.py b/wifiscanner/wifimap/__init__.py index a1c5f09..edc2cb7 100644 --- a/wifiscanner/wifimap/__init__.py +++ b/wifiscanner/wifimap/__init__.py @@ -1,5 +1,5 @@ -__all__ = [ 'config' , 'db' , 'gps' , 'wifiscan' , 'view' ] +__all__ = [ 'config' , 'db' , 'gps' , 'wifiscan' , 'scanner' , 'view' ] from config import * @@ -9,5 +9,9 @@ from gps import * from wifiscan import * +from scanner import * + from view import * +from replay import * + diff --git a/wifiscanner/wifimap/db.py b/wifiscanner/wifimap/db.py index 92fd45b..e5a4c45 100644 --- a/wifiscanner/wifimap/db.py +++ b/wifiscanner/wifimap/db.py @@ -49,23 +49,32 @@ class database : rc = self.db.execute( query ) return rc.fetchone() - def add ( self , mac , rss , timestamp , gps=None ) : + def __extend_query ( self , gps ) : + query = [] + lat , lon , alt = gps + if lat and lon : + query.append( "lat=lat+%f , lat2=lat2+%f , lon=lon+%f , lon2=lon2+%f" % ( lat , lat*lat , lon , lon*lon ) ) + if alt : + query.append( "alt=alt+%f , alt2=alt2+%f" % ( alt , alt*alt ) ) + return " , ".join( query ) + + def add ( self , mac , rss , timestamp , gps ) : query = "INSERT INTO ap ( mac , rss , last_seen ) VALUES ( '%s' , %d , %f )" % ( mac , rss , timestamp ) rc = self.db.execute( query ) if rc.rowcount : - if gps : - lat , lon , alt = gps - query = "UPDATE ap SET n=1 , lat=%f , lat2=%f , lon=%f , lon2=%f , alt=%f , alt2=%f WHERE mac='%s'" % ( lat , lat*lat , lon , lon*lon , alt , alt*alt , mac ) + extra = self.__extend_query(gps) + if extra : + query = "UPDATE ap SET n=1 , %s WHERE mac='%s'" % ( extra , mac ) rc = self.db.execute( query ) self.db.commit() - def update ( self , mac , rss , timestamp , gps=None ) : + def update ( self , mac , rss , timestamp , gps ) : query = "UPDATE ap set rss=%d , last_seen=%f" % ( rss , timestamp ) - if gps : - lat , lon , alt = gps - query += " , n=n+1 , lat=lat+%f , lat2=lat2+%f , lon=lon+%f , lon2=lon2+%f , alt=alt+%f , alt2=alt2+%f" % ( lat , lat*lat , lon , lon*lon , alt , alt*alt ) + extra = self.__extend_query(gps) + if extra : + query += " , n=n+1 , %s" % extra query += " WHERE mac='%s'" % mac rc = self.db.execute( query ) if rc.rowcount : diff --git a/wifiscanner/wifimap/gps.py b/wifiscanner/wifimap/gps.py index e83e7b1..aaaf4fe 100644 --- a/wifiscanner/wifimap/gps.py +++ b/wifiscanner/wifimap/gps.py @@ -1,111 +1,96 @@ - import location + import gobject class GPSObject ( gobject.GObject ) : - def __init__ ( self , widget=None ) : + def __init__ ( self ) : gobject.GObject.__init__( self ) - self._parent = widget - self._debug = False + self.control = location.GPSDControl.get_default() + self.control.set_properties(preferred_method=location.METHOD_GNSS, + preferred_interval=location.INTERVAL_DEFAULT) self.device = location.GPSDevice() - # properties : maincontext_pointer preferred_interval preferred_method - self.method = location.METHOD_GNSS - self.gps_state = False - self.gps_info = "NO_FIX 0 0 NaN NaN NaN NaN NaN NaN NaN" - self.update_handler = None + self.device.connect_object("changed", GPSObject.update , self) + + # Values to be set by GPSDevice changed events + self.info = None, 0, 0, None, None, None, None self.satellites = None - self.cell_info = None + self.cells = None self.ngps = 0 - self.status = None def set_method ( self , method="gps" ) : if method == "agps" : - self.method = location.METHOD_GNSS | location.METHOD_AGNSS + self.control.set_properties(preferred_method=location.METHOD_GNSS|location.METHOD_AGNSS) else : - self.method = location.METHOD_GNSS - - def set_interval ( self , interval="1" ) : - if interval == "1" : - self.interval = location.INTERVAL_1S - elif interval == "2" : - self.interval = location.INTERVAL_2S - elif interval == "5" : - self.interval = location.INTERVAL_5S - elif interval == "10" : - self.interval = location.INTERVAL_10S - elif interval == "20" : - self.interval = location.INTERVAL_20S - elif interval == "30" : - self.interval = location.INTERVAL_30S - elif interval == "60" : - self.interval = location.INTERVAL_60S - elif interval == "120" : - self.interval = location.INTERVAL_120S + control.set_properties(preferred_method=location.METHOD_GNSS) + + def set_interval ( self , interval=0 ) : + if interval <= 0 : + self.control.set_properties(preferred_interval=location.INTERVAL_DEFAULT) + elif interval <= 1 : + self.control.set_properties(preferred_interval=location.INTERVAL_1S) + elif interval <= 2 : + self.control.set_properties(preferred_interval=location.INTERVAL_2S) + elif interval <= 5 : + self.control.set_properties(preferred_interval=location.INTERVAL_5S) + elif interval <= 10 : + self.control.set_properties(preferred_interval=location.INTERVAL_10S) + elif interval <= 20 : + self.control.set_properties(preferred_interval=location.INTERVAL_20S) + elif interval <= 30 : + self.control.set_properties(preferred_interval=location.INTERVAL_30S) + elif interval <= 60 : + self.control.set_properties(preferred_interval=location.INTERVAL_60S) else : - self.interval = location.INTERVAL_DEFAULT + self.control.set_properties(preferred_interval=location.INTERVAL_120S) - def do_start ( self ) : - self.control.set_properties(preferred_method=self.method, - preferred_interval=self.interval) - if not self.update_handler : - self.update_handler = self.device.connect_object("changed", GPSObject.do_update , self) + def start ( self ) : + if not self.device.online : self.control.start() # FIXME : Stopping does not work, at least while getting fix - def do_stop ( self ) : - if self.update_handler : - # FIXME : Is this removal OK? - del self.update_handler - self.update_handler = None - self.control.stop() - - def do_update ( self ) : - - if self.device : - if self.device.status == location.GPS_DEVICE_STATUS_NO_FIX : - self.gps_state = "NO_FIX" - elif self.device.status == location.GPS_DEVICE_STATUS_FIX : - self.gps_state = "FIX" + def stop ( self ) : + if self.device.online : + self.control.stop() + + def update ( self ) : + + if self.device.online : + if self.device.status == location.GPS_DEVICE_STATUS_FIX : + state = "FIX" self.ngps += 1 - self.refresh_infowin() elif self.device.status == location.GPS_DEVICE_STATUS_DGPS_FIX : - self.gps_state = "DGPS" - - self.gps_info = "%s %d %d %s %s %s %s %s %s %s" % ( self.gps_state , self.device.satellites_in_use , self.device.satellites_in_view , self.device.fix[2] , self.device.fix[4] , self.device.fix[5] , self.device.fix[7] , self.device.fix[9] , self.device.fix[11] , self.device.fix[13] ) + state = "DGPS" + # FIXME : Increase also ngps here ??? + else : + state = None + + lat , lon , alt = None , None , None + if self.device.fix[1] & location.GPS_DEVICE_LATLONG_SET: + lat , lon = device.fix[4:6] + if self.device.fix[1] & location.GPS_DEVICE_ALTITUDE_SET: + alt = device.fix[7] + # FIXME : get time from GPS fix + self.info = state , self.device.satellites_in_view , self.device.satellites_in_use , self.device.fix[2] , lat , lon , alt self.satellites = self.device.satellites - self.cell_info = self.device.cell_info - - def set_infowin ( self , statuswin ) : - self.status = statuswin - - def refresh_infowin ( self ) : - if self.status : - self.status.set_label( "%d gps" % self.ngps ) - - -# mode = device.fix[0] -# if mode == location.GPS_DEVICE_MODE_NOT_SEEN : # This means ?? -# print "mode is NOSEEN" -# if mode == location.GPS_DEVICE_MODE_NO_FIX : # This implies device.status == location.GPS_DEVICE_STATUS_NO_FIX -# # and probably device.fix[1] == location.GPS_DEVICE_NONE_SET -# print "mode is NOFIX" -# if mode == location.GPS_DEVICE_MODE_2D : -# print "mode is 2D" -# if mode == location.GPS_DEVICE_MODE_3D : -# print "mode is 3D" - -# if flags & location.GPS_DEVICE_SPEED_SET : -# print "GPS_DEVICE_SPEED_SET" -# if flags & location.GPS_DEVICE_TRACK_SET : -# print "GPS_DEVICE_TRACK_SET" -# if flags & location.GPS_DEVICE_ALTITUDE_SET : -# print "GPS_DEVICE_ALTITUDE_SET" -# if flags & location.GPS_DEVICE_CLIMB_SET : -# print "GPS_DEVICE_CLIMB_SET" + self.cells = self.device.cell_info + else : + self.info = None, 0, 0, None, None, None, None + + def report ( self ) : + return "%d gps" % self.ngps gobject.type_register(GPSObject) +if __name__ == "__main__" : + loop = gobject.MainLoop() + sample = GPSObject() + def on_stop(control, mainloop): + mainloop.quit() + sample.control.connect("gpsd-stopped", on_stop, loop) + sample.start() + loop.run() + sample.stop() diff --git a/wifiscanner/wifimap/replay.py b/wifiscanner/wifimap/replay.py new file mode 100644 index 0000000..520a4dd --- /dev/null +++ b/wifiscanner/wifimap/replay.py @@ -0,0 +1,93 @@ + +import config + +import gobject + +import os + +conf = config.Configuration() + +class ReplayScanner ( gobject.GObject ) : + + def __init__ ( self ) : + gobject.GObject.__init__( self ) + self.scan_timeout = 0 + + # Values specific to replaying + self._file = os.path.join( conf.homedir , "wiscan_gui.info" ) + self._fd = None + self._current = None + + # Values to be set by GPSDevice changed events + self.info = None, 0, 0, None, None, None, None + self.satellites = None + self.cells = None + self.ngps = 0 + + # Values to be set by wireless scans + self.scanlist = {} + self.tstamp = 0 + self.nscan = 0 + self.nfp = 0 + + # Values from the Scanner object + self.newap = 0 + + def start ( self , timeout=5000 ) : + self.scan_timeout = timeout + self._fd = open( self._file ) + self._current = self._fd.readline().split() + + def stop ( self ) : + self.scan_timeout = 0 + self._fd.close() + + def scan ( self ) : + + if not self.scan_timeout : + return + + next = self._fd.readline().split() + delta = float(next[0]) - float(self._current[0]) + gobject.timeout_add( int(1000 * delta) , self.scan ) + + self.info = self._current[1:8] + if self.info[0] == "FIX" : + self.ngps += 1 + + self.nscan +=1 + self.scanlist.clear() + self.tstamp = float(self._current[0]) + for n in range(11, len(self._current), 2) : + self.nfp += 1 + self.scanlist[ self._current[n] ] = int(self._current[n+1]) + + self._current = next + + def report ( self ) : + return "%d gps\t%d scan\t%d fp\t%d ap\t%d total ap" % ( self.ngps , self.nscan , self.nfp , self.newap , -1 ) + + +gobject.type_register(ReplayScanner) + +if __name__ == "__main__" : + loop = gobject.MainLoop() + sample = ReplayScanner() + def show_scan(wifiscanner): + gobject.timeout_add( 5000 , show_scan , sample ) + print "scan results %s" % wifiscanner.report() + print " tstamp %s" % wifiscanner.tstamp + c = 0 + for k,v in wifiscanner.scanlist.iteritems() : + c += 1 + print " %s %s" % ( k , v ) + if c > 5 : + print " ..." + break + print + sample.start() + sample.scan() + gobject.timeout_add( 5100 , show_scan , sample ) + loop.run() + sample.stop() + diff --git a/wifiscanner/wifimap/scanner.py b/wifiscanner/wifimap/scanner.py new file mode 100644 index 0000000..03389ba --- /dev/null +++ b/wifiscanner/wifimap/scanner.py @@ -0,0 +1,94 @@ + +try : + import osso +except : + import osso_wrapper as osso + +import time + +import config , db +import gps , wifiscan + +import gobject + +import os + +conf = config.Configuration() + +class Scanner ( gps.GPSObject , wifiscan.WifiScanner ) : + + def __init__ ( self , ifname="wlan0" ) : + gps.GPSObject.__init__( self ) + wifiscan.WifiScanner.__init__( self ) + self.db = db.database( os.path.join( conf.homedir , conf.dbname ) ) + + # Values to be set by wireless scans + self.newap = 0 + + def start ( self , timeout=5000 ) : + gps.GPSObject.start( self ) + wifiscan.WifiScanner.start( self , timeout ) + self.db.open() + + def stop ( self ) : + gps.GPSObject.stop( self ) + wifiscan.WifiScanner.stop( self ) + self.db.close() + + def scan ( self ) : + wifiscan.WifiScanner.scan( self ) + for mac,max_rss in self.scanlist.iteritems() : + stored = self.db.get( mac ) + if stored : + if stored[0] > max_rss : + max_rss = stored[0] + self.db.update( mac , max_rss , self.tstamp , self.info[4:] ) + else : + self.newap += 1 + self.db.add( mac , max_rss , self.tstamp , self.info[4:] ) + self.write_logs() + + def write_logs ( self ) : + fd = open( os.path.join( conf.homedir , "wiscan_gui.info" ) , 'a' ) + fd.write( "%s %s %s\n" % ( self.tstamp , self.info , self.scanlist ) ) + fd.close() + if self.satellites : + loclist = open( os.path.join( conf.homedir , "location.info" ) , 'a' ) + loclist.write ( "%s\n" % ( self.satellites ,) ) + loclist.close() + if self.cells : + celllist = open( os.path.join( conf.homedir , "cell.info" ) , 'a' ) + celllist.write ( "%s\n" % ( self.cells ,) ) + celllist.close() + + def report ( self ) : + # BUG : if report is called after close, db.nrows() will produce an exception + return "%s\t%s\t%d ap\t%d total ap" % ( gps.GPSObject.report(self) , wifiscan.WifiScanner.report(self) , self.newap , self.db.nrows() ) + + +gobject.type_register(Scanner) + +if __name__ == "__main__" : + loop = gobject.MainLoop() + sample = Scanner() + def on_stop(control, mainloop): + mainloop.quit() + sample.control.connect("gpsd-stopped", on_stop, loop) + def show_scan(wifiscanner): + gobject.timeout_add( 5000 , show_scan , sample ) + print "scan results %s" % wifiscanner.report() + print " tstamp %s" % wifiscanner.tstamp + c = 0 + for k,v in wifiscanner.scanlist.iteritems() : + c += 1 + print " %s %s" % ( k , v ) + if c > 5 : + print " ..." + break + print + sample.start() + sample.scan() + gobject.timeout_add( 5100 , show_scan , sample ) + loop.run() + sample.stop() + diff --git a/wifiscanner/wifimap/view.py b/wifiscanner/wifimap/view.py index f98f582..bcb4c51 100755 --- a/wifiscanner/wifimap/view.py +++ b/wifiscanner/wifimap/view.py @@ -1,4 +1,5 @@ +import gtk import gobject import urllib2 @@ -30,17 +31,6 @@ class AbstractmapWidget : number = math.modf( ( 1 - math.log( math.tan( lat ) + 1 / math.cos( lat ) ) / math.pi ) / 2 * 2 ** zoom ) return int( number[1] ) , int( self.tile_size * number[0] ) - def tilex2lon ( self , ( tilex , pixx ) , zoom ) : - tilex = float(tilex) - pixx = float(pixx) - return ( tilex + pixx/self.tile_size ) / 2.0 ** zoom * 360.0 - 180.0 - - def tiley2lat ( self , ( tiley , pixy ) , zoom ) : - tiley = float(tiley) - pixy = float(pixy) - tiley = math.pi * ( 1 - 2 * ( tiley + pixy/self.tile_size ) / 2.0 ** zoom ) - return math.degrees( math.atan( math.sinh( tiley ) ) ) - def gps2pix ( self , ( lat , lon ) , ( center_x , center_y ) ) : x_pos = self.lon2tilex( lon , self.conf.zoom ) @@ -81,6 +71,19 @@ class AbstractmapWidget : os.mkdir(rootsubdir) return "%s/%s.png" % ( rootsubdir , tiley ) +class interactiveMapWidget : + + def tilex2lon ( self , ( tilex , pixx ) , zoom ) : + tilex = float(tilex) + pixx = float(pixx) + return ( tilex + pixx/self.tile_size ) / 2.0 ** zoom * 360.0 - 180.0 + + def tiley2lat ( self , ( tiley , pixy ) , zoom ) : + tiley = float(tiley) + pixy = float(pixy) + tiley = math.pi * ( 1 - 2 * ( tiley + pixy/self.tile_size ) / 2.0 ** zoom ) + return math.degrees( math.atan( math.sinh( tiley ) ) ) + def Shift( self , dx , dy ) : self.hide() @@ -134,3 +137,127 @@ class AbstractmapWidget : self.composeMap() self.show() +class simpleMapWidget ( AbstractmapWidget , gtk.Image ) : + + def __init__ ( self , config , map_size=(800,480) ) : + AbstractmapWidget.__init__( self , config , map_size ) + + gtk.Image.__init__(self) + + p = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, self.win_x, self.win_y) + self.set_from_pixbuf(p) + + self.composeMap() + + def composeMap( self ) : + center_x , center_y = self.win_x / 2 , self.win_y / 2 + + # To get the central pixel in the window center, we must shift to the tile origin + center_x -= self.refpix_x + center_y -= self.refpix_y + + # Ranges should be long enough as to fill the screen + # Maybe they should be decided based on self.win_x, self.win_y + for i in range(-3,4) : + for j in range(-3,4) : + file = self.tilename( i , j , self.conf.zoom ) + if file is None : + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, self.tile_size, self.tile_size ) + pixbuf.fill( 0x00000000 ) + else : + try : + pixbuf = gtk.gdk.pixbuf_new_from_file( file ) + except gobject.GError , ex : + print "Corrupted file %s" % ( file ) + os.unlink( file ) + #file = self.tilename( self.reftile_x + i , self.reftile_y + j , self.conf.zoom ) + file = self.tilename( i , j , self.conf.zoom ) + try : + pixbuf = gtk.gdk.pixbuf_new_from_file( file ) + except : + print "Total failure for tile for %s,%s" % ( self.reftile_x + i , self.reftile_y + j ) + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, self.tile_size, self.tile_size ) + + dest_x = self.tile_size * i + center_x + dest_y = self.tile_size * j + center_y + + init_x = 0 + size_x = self.tile_size + if dest_x < 0 : + init_x = abs(dest_x) + size_x = self.tile_size + dest_x + dest_x = 0 + if dest_x + self.tile_size > self.win_x : + size_x = self.win_x - dest_x + + init_y = 0 + size_y = self.tile_size + if dest_y < 0 : + init_y = abs(dest_y) + size_y = self.tile_size + dest_y + dest_y = 0 + if dest_y + self.tile_size > self.win_y : + size_y = self.win_y - dest_y + + if ( size_x > 0 and size_y > 0 ) and ( init_x < self.tile_size and init_y < self.tile_size ) : + pixbuf.copy_area( init_x, init_y, size_x, size_y, self.get_pixbuf(), dest_x , dest_y ) + del(pixbuf) + + self.draw_paths() + self.plot_APs() + + def draw_paths( self ) : + + center_x , center_y = self.win_x / 2 , self.win_y / 2 + + # To get the central pixel in the window center, we must shift to the tile origin + center_x -= self.refpix_x + center_y -= self.refpix_y + + pixmap,mask = self.get_pixbuf().render_pixmap_and_mask() + red = pixmap.new_gc() + red.foreground = pixmap.get_colormap().alloc_color("red") + green = pixmap.new_gc() + green.foreground = pixmap.get_colormap().alloc_color("green") + blue = pixmap.new_gc() + blue.foreground = pixmap.get_colormap().alloc_color("blue") + + filename = "data/wiscan_gui.info.old" + fd = open( filename ) + for line in fd.readlines() : + values = line.split() + if values[1] == "FIX" : + dest_x , dest_y = self.gps2pix( ( float(values[5]) , float(values[6]) ) , ( center_x , center_y ) ) + pixmap.draw_rectangle(blue, True , dest_x , dest_y , 3 , 3 ) + fd.close() + + self.get_pixbuf().get_from_drawable( pixmap , pixmap.get_colormap() , 0, 0 , 0 , 0 , self.win_x, self.win_y ) + + def plot_APs( self ) : + + center_x , center_y = self.win_x / 2 , self.win_y / 2 + + # To get the central pixel in the window center, we must shift to the tile origin + center_x -= self.refpix_x + center_y -= self.refpix_y + + pixmap,mask = self.get_pixbuf().render_pixmap_and_mask() + blue = pixmap.new_gc() + blue.foreground = pixmap.get_colormap().alloc_color("blue") + + db = wifimap.db.database( os.path.join( self.conf.homedir , self.conf.dbname ) ) + db.open() + # NOTE : Intervals for query are just educated guesses to fit in window + lat , lon = self.conf.lat , self.conf.lon + for ap in db.db.execute( "SELECT * FROM ap where lat/n>%f and lat/n<%f and lon/n>%f and lon/n<%f" % ( lat - 0.003 , lat + 0.003 , lon - 0.007 , lon + 0.007 ) ) : + if ap[3] > 1 : + dest_x , dest_y = self.gps2pix( ( ap[4]/ap[3] , ap[5]/ap[3] ) , ( center_x , center_y ) ) + pixmap.draw_rectangle(blue, True , dest_x , dest_y , 3 , 3 ) + db.close() + + self.get_pixbuf().get_from_drawable( pixmap , pixmap.get_colormap() , 0, 0 , 0 , 0 , self.win_x, self.win_y ) + +class mapWidget ( simpleMapWidget , interactiveMapWidget ) : + + pass + diff --git a/wifiscanner/wifimap/wifiscan.py b/wifiscanner/wifimap/wifiscan.py index ca7da15..33221b0 100644 --- a/wifiscanner/wifimap/wifiscan.py +++ b/wifiscanner/wifimap/wifiscan.py @@ -6,119 +6,76 @@ except : import time -import config , db , gps - import gobject import os -conf = config.Configuration() +class WifiScanner ( gobject.GObject ) : -class Scanner ( gps.GPSObject ) : + def __init__ ( self , ifname="wlan0" ) : + gobject.GObject.__init__( self ) + self.osso_context = osso.Context("wifi_scanner", "2.0", False) + osso_rpc = osso.Rpc(self.osso_context) + osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "wakeup", wait_reply = True) + self.scan_timeout = 0 - def __init__ ( self , widget=None , ifname="wlan0" ) : - gps.GPSObject.__init__( self , widget ) - self.osso_context = None - if widget : - self.osso_context = osso.Context("wifi_scanner", "2.0", False) - osso_rpc = osso.Rpc(self.osso_context) - osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "wakeup", wait_reply = True) - self._timer = None + # Values to be set by wireless scans + self.scanlist = {} + self.tstamp = 0 self.nscan = 0 self.nfp = 0 - self.scanlist = None - self.newap = 0 - self.db = db.database( os.path.join( conf.homedir , conf.dbname ) ) - def start ( self ) : - if self.osso_context : - osso_rpc = osso.Rpc(self.osso_context) - scan_out = osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "start") - self.db.open() + def start ( self , timeout=5000 ) : + osso_rpc = osso.Rpc(self.osso_context) + osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "start") + self.scan_timeout = timeout def stop ( self ) : osso_rpc = osso.Rpc(self.osso_context) - scan_out = osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "stop") - self.db.close() + osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "stop") + self.scan_timeout = 0 def scan ( self ) : osso_rpc = osso.Rpc(self.osso_context) try : scan_out = osso_rpc.rpc_run("org.javiplx.wifiscan", "/org/javiplx/wifiscan", "org.javiplx.wifiscan", "scan", wait_reply = True) + if self.scan_timeout : + gobject.timeout_add( self.scan_timeout , self.scan ) + # BUG : if scan is called after stop (maybe in other cases), 'ERROR' is returned and split raises exception self.nscan +=1 + self.scanlist.clear() + self.tstamp = time.time() + for net in scan_out.split() : + self.nfp += 1 + items = net.rsplit(":", 1) + self.scanlist[ items[0] ] = int(items[1]) except Exception , ex : osso.SystemNote(self.osso_context).system_note_infoprint("Exception scanning %s" % ex ) - return True - if self.scanlist : - start, end = self.scanlist.get_bounds() - self.scanlist.delete( start , end ) - tstamp = time.time() - latlon = None - if self.gps_state == "FIX" : - latlon = ( self.device.fix[4] , self.device.fix[5] , self.device.fix[7] ) - self.store_scan( tstamp , scan_out , latlon ) - self.refresh_infowin() - if self._debug : - osso.SystemNote(self.osso_context).system_note_infoprint("Found %d APs" % len(scan_out) ) - else : - self.write_logs( tstamp , scan_out ) - - return True - - def store_scan ( self , timestamp , scan_out , gps_info ) : - for net in scan_out.split() : - self.nfp += 1 - items = net.rsplit(":", 1) - if self.scanlist : - self.scanlist.insert_at_cursor( "%s %5d\n" % ( items[0] , int(items[1]) ) ) - stored = self.db.get( items[0] ) - if stored : - max_rss = int(items[1]) - if stored[0] > max_rss : - max_rss = stored[0] - self.db.update( items[0] , max_rss , timestamp , gps_info ) - else : - self.newap += 1 - self.db.add( items[0] , int(items[1]) , timestamp , gps_info ) - - def store_legacy ( self , timestamp , scan_out , gps_info ) : - nets = scan_out.split() - while nets : - self.nfp += 1 - items = ( nets.pop(0) , nets.pop(0) ) - if self.scanlist : - self.scanlist.insert_at_cursor( "%s %5d\n" % ( items[0] , int(items[1]) ) ) - stored = self.db.get( items[0] ) - if stored : - max_rss = int(items[1]) - if stored[0] > max_rss : - max_rss = stored[0] - self.db.update( items[0] , max_rss , timestamp , gps_info ) - else : - self.newap += 1 - self.db.add( items[0] , int(items[1]) , timestamp , gps_info ) - - def write_logs ( self , timestamp , out_str ) : - fd = open( os.path.join( conf.homedir , "wiscan_gui.info" ) , 'a' ) - fd.write( "%s %s %s\n" % ( timestamp , self.gps_info , out_str ) ) - fd.close() - if self.satellites : - loclist = open( os.path.join( conf.homedir , "location.info" ) , 'a' ) - loclist.write ( "%s\n" % ( self.satellites ,) ) - loclist.close() - if self.cell_info : - celllist = open( os.path.join( conf.homedir , "cell.info" ) , 'a' ) - celllist.write ( "%s\n" % ( self.cell_info ,) ) - celllist.close() - - def set_infowin ( self , statuswin , listwin ) : - gps.GPSObject.set_infowin( self , statuswin ) - self.scanlist = listwin - - def refresh_infowin ( self ) : - if self.status : - self.status.set_text( "%d gps\t%d scan\t%d fp\t%d ap\t%d total ap" % ( self.ngps , self.nscan , self.nfp , self.newap , self.db.nrows() ) ) - -gobject.type_register(Scanner) + def report ( self ) : + return "%d scan\t%d fp" % ( self.nscan , self.nfp ) + + +gobject.type_register(WifiScanner) + +if __name__ == "__main__" : + loop = gobject.MainLoop() + sample = WifiScanner() + sample.start() + def show_scan(sample): + gobject.timeout_add( 5000 , show_scan , sample ) + print "scan results : %s" % sample.report() + print " tstamp %s" % sample.tstamp + c = 0 + for k,v in sample.scanlist.iteritems() : + c += 1 + print " %s %s" % ( k , v ) + if c > 5 : + print " ..." + break + print + sample.scan() + gobject.timeout_add( 5100 , show_scan , sample ) + loop.run() + sample.stop() diff --git a/wifiscanner/wifiscanner.py b/wifiscanner/wifiscanner.py index 2370750..a73d763 100755 --- a/wifiscanner/wifiscanner.py +++ b/wifiscanner/wifiscanner.py @@ -1,5 +1,5 @@ -import wifimap , wifiview +import wifimap import gtk , pango try : @@ -7,57 +7,60 @@ try : except : hildon = False -import gobject - -def hello(widget, data): - data.do_start() - if widget.handler_id : - widget.disconnect( widget.handler_id ) - widget.handler_id = widget.connect("clicked", bye, data) - widget.set_label("Switch Off!") - -def bye(widget, data): - data.do_stop() - if widget.handler_id : - widget.disconnect( widget.handler_id ) - widget.handler_id = widget.connect("clicked", hello, data) - widget.set_label("Switch On!") - -def enable_agps(widget): - if widget.get_active() : - print "%s state is active" % widget - -def scana(widget, data): - if not data._timer : - data._timer = gobject.timeout_add( 5000 , data.scan ) - else : - if hildon : - hildon.hildon_banner_show_information( widget , "icon_path" , "Scanning was already active" ) - if widget.handler_id : - widget.disconnect( widget.handler_id ) - widget.handler_id = widget.connect("clicked", scano, data) - widget.set_label("Stop scanning now !!") - -def scano(widget, data): - if data._timer : - if hildon : - hildon.hildon_banner_show_information( widget , "icon_path" , "Timer was running, stopping it" ) - gobject.source_remove( data._timer ) - data._timer = None - data.stop() - else : - if hildon : - hildon.hildon_banner_show_information( widget , "icon_path" , "Scanning is not active" ) - if widget.handler_id : - widget.disconnect( widget.handler_id ) - widget.handler_id = widget.connect("clicked", scana, data) - widget.set_label("Start scanning now !!") +def global_start(button, scanner): + scanner.start() + if button._id : + button.disconnect( button._id ) + button._id = button.connect("clicked", global_stop, scanner) + button.set_label("Switch GPS Off") + +def global_stop(button, scanner): + scanner.stop() + if button._id : + button.disconnect( button._id ) + button._id = button.connect("clicked", global_start, scanner) + button.set_label("Switch GPS On") + +def enable_agps(button): + if button.get_active() : + print "%s state is active" % button + +def start_scan(button, scanner): + # BUG : If gps is not started in advance, database is not opened and an exception happens + scanner.scan() + if button._id : + button.disconnect( button._id ) + button._id = button.connect("clicked", stop_scan, scanner) + button.set_label("Stop scanning") + +def stop_scan(button, scanner): + # FIXME : This method do not clear the scheduled scan + scanner.scan_timeout = 0 + if button._id : + button.disconnect( button._id ) + button._id = button.connect("clicked", start_scan, scanner) + button.set_label("Start scanning") + + +class scanner ( wifimap.Scanner ) : + + def scan ( self ) : + wifimap.Scanner.scan( self ) + self.report() + + def report ( self ) : + self.status.set_label( wifimap.Scanner.report(self) ) + start, end = self.buffer.get_bounds() + self.buffer.delete( start , end ) + for mac,rss in self.scanlist.iteritems() : + self.buffer.insert_at_cursor( "%s %5d\n" % ( mac , rss ) ) + class AbstractWifiscanner : def __init__ ( self ) : - self.gpsdev = wifimap.Scanner( self ) + _scanner = scanner() self.connect("delete_event", gtk.main_quit, None) @@ -93,12 +96,12 @@ class AbstractWifiscanner : scrollview.set_policy( gtk.POLICY_NEVER , gtk.POLICY_AUTOMATIC ) # Buttons creation - button = self.Button( "Switch On!") - button.handler_id = button.connect("clicked", hello, self.gpsdev) + button = self.Button( "Switch GPS On") + button._id = button.connect("clicked", global_start, _scanner) buttons.pack_start(button, expand=False) - button_scan = self.Button( "Start scanning now !!") - button_scan.handler_id = button_scan.connect("clicked", scana, self.gpsdev) + button_scan = self.Button( "Start scanning") + button_scan._id = button_scan.connect("clicked", start_scan, _scanner) buttons.pack_start(button_scan, expand=False) toggle_button = self.CheckButton( "Use Assisted GPS" ) @@ -107,12 +110,12 @@ class AbstractWifiscanner : # Bottom frame population status = gtk.Label( "status bar ..." ) - self.gpsdev.set_infowin( status , textview.get_buffer() ) + _scanner.status = status + _scanner.buffer = textview.get_buffer() bottom_box.pack_start( status , expand=False , padding=20 ) def run ( self ) : self.show_all() - self.gpsdev.start() gtk.main() if hildon : @@ -124,7 +127,7 @@ if hildon : self.config = wifimap.config.Configuration() self.config.zoom = 16 - self.map = wifiview.mapWidget( self.config ) + self.map = wifimap.simpleMapWidget( self.config ) self.map.plot_APs() self.add( self.map ) @@ -166,7 +169,7 @@ else : self.config = wifimap.config.Configuration() self.config.zoom = 16 - self.add( wifiview.mapWidget( self.config , (640,400) ) ) + self.add( wifimap.simpleMapWidget( self.config , (640,400) ) ) class Wifiscanner ( AbstractWifiscanner , gtk.Window ) : diff --git a/wifiscanner/wifiview.py b/wifiscanner/wifiview.py index b2d942c..0437d70 100755 --- a/wifiscanner/wifiview.py +++ b/wifiscanner/wifiview.py @@ -1,6 +1,5 @@ import gtk -import gobject try : import hildon except : @@ -8,139 +7,10 @@ except : import math -import os - import wifimap.config import wifimap.view -class mapWidget ( wifimap.view.AbstractmapWidget , gtk.Image ) : - - def __init__ ( self , config , map_size=(800,480) ) : - wifimap.view.AbstractmapWidget.__init__( self , config , map_size ) - - gtk.Image.__init__(self) - - p = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, self.win_x, self.win_y) - self.set_from_pixbuf(p) - - self.composeMap() - - def composeMap( self ) : - center_x , center_y = self.win_x / 2 , self.win_y / 2 - - # To get the central pixel in the window center, we must shift to the tile origin - center_x -= self.refpix_x - center_y -= self.refpix_y - - # Ranges should be long enough as to fill the screen - # Maybe they should be decided based on self.win_x, self.win_y - for i in range(-3,4) : - for j in range(-3,4) : - file = self.tilename( i , j , self.conf.zoom ) - if file is None : - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, self.tile_size, self.tile_size ) - pixbuf.fill( 0x00000000 ) - else : - try : - pixbuf = gtk.gdk.pixbuf_new_from_file( file ) - except gobject.GError , ex : - print "Corrupted file %s" % ( file ) - os.unlink( file ) - #file = self.tilename( self.reftile_x + i , self.reftile_y + j , self.conf.zoom ) - file = self.tilename( i , j , self.conf.zoom ) - try : - pixbuf = gtk.gdk.pixbuf_new_from_file( file ) - except : - print "Total failure for tile for %s,%s" % ( self.reftile_x + i , self.reftile_y + j ) - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, self.tile_size, self.tile_size ) - - dest_x = self.tile_size * i + center_x - dest_y = self.tile_size * j + center_y - - init_x = 0 - size_x = self.tile_size - if dest_x < 0 : - init_x = abs(dest_x) - size_x = self.tile_size + dest_x - dest_x = 0 - if dest_x + self.tile_size > self.win_x : - size_x = self.win_x - dest_x - - init_y = 0 - size_y = self.tile_size - if dest_y < 0 : - init_y = abs(dest_y) - size_y = self.tile_size + dest_y - dest_y = 0 - if dest_y + self.tile_size > self.win_y : - size_y = self.win_y - dest_y - - if ( size_x > 0 and size_y > 0 ) and ( init_x < self.tile_size and init_y < self.tile_size ) : - pixbuf.copy_area( init_x, init_y, size_x, size_y, self.get_pixbuf(), dest_x , dest_y ) - del(pixbuf) - - self.draw_paths - - def draw_paths( self ) : - - center_x , center_y = self.win_x / 2 , self.win_y / 2 - - # To get the central pixel in the window center, we must shift to the tile origin - center_x -= self.refpix_x - center_y -= self.refpix_y - - pixmap,mask = self.get_pixbuf().render_pixmap_and_mask() - red = pixmap.new_gc() - red.foreground = pixmap.get_colormap().alloc_color("red") - green = pixmap.new_gc() - green.foreground = pixmap.get_colormap().alloc_color("green") - blue = pixmap.new_gc() - blue.foreground = pixmap.get_colormap().alloc_color("blue") - - filename = "data/wiscan_gui.info.old" - fd = open( filename ) - for line in fd.readlines() : - values = line.split() - if values[1] == "FIX" : - dest_x , dest_y = self.gps2pix( ( float(values[5]) , float(values[6]) ) , ( center_x , center_y ) ) - pixmap.draw_rectangle(blue, True , dest_x , dest_y , 3 , 3 ) - fd.close() - - db = wifimap.db.database( os.path.join( self.conf.homedir , self.conf.dbname ) ) - db.open() - for ap in db.db.execute( "SELECT * FROM ap" ) : - if ap[3] > 1 : - dest_x , dest_y = self.gps2pix( ( ap[4]/ap[3] , ap[5]/ap[3] ) , ( center_x , center_y ) ) - pixmap.draw_rectangle(red, True , dest_x , dest_y , 3 , 3 ) - db.close() - - self.get_pixbuf().get_from_drawable( pixmap , pixmap.get_colormap() , 0, 0 , 0 , 0 , self.win_x, self.win_y ) - - def plot_APs( self ) : - - center_x , center_y = self.win_x / 2 , self.win_y / 2 - - # To get the central pixel in the window center, we must shift to the tile origin - center_x -= self.refpix_x - center_y -= self.refpix_y - - pixmap,mask = self.get_pixbuf().render_pixmap_and_mask() - blue = pixmap.new_gc() - blue.foreground = pixmap.get_colormap().alloc_color("blue") - - db = wifimap.db.database( os.path.join( self.conf.homedir , self.conf.dbname ) ) - db.open() - # NOTE : Intervals for query are just educated guesses to fit in window - lat , lon = self.conf.lat , self.conf.lon - for ap in db.db.execute( "SELECT * FROM ap where lat/n>%f and lat/n<%f and lon/n>%f and lon/n<%f" % ( lat - 0.003 , lat + 0.003 , lon - 0.007 , lon + 0.007 ) ) : - if ap[3] > 1 : - dest_x , dest_y = self.gps2pix( ( ap[4]/ap[3] , ap[5]/ap[3] ) , ( center_x , center_y ) ) - pixmap.draw_rectangle(blue, True , dest_x , dest_y , 3 , 3 ) - db.close() - - self.get_pixbuf().get_from_drawable( pixmap , pixmap.get_colormap() , 0, 0 , 0 , 0 , self.win_x, self.win_y ) - if hildon : @@ -211,42 +81,21 @@ class AbstractMapWindow: gtk.main_quit() def press_event ( self, widget, event, *args ) : - # FIXME : Set only if far enough from borders - border_x = 40 - border_y = 30 - print "press ",event.get_coords(),event.get_root_coords() + border_x , border_y = 40 , 30 if event.x > border_x and event.y > border_y and event.x < ( self.size_x - border_x ) and event.y < ( self.size_y - border_y ) : self.click_x = event.x self.click_y = event.y def release_event ( self, widget, event, *args ) : min_shift = 50 - print "unpress",event.get_coords(),event.get_root_coords() if self.click_x is not None and self.click_y is not None : delta_x = int( event.x - self.click_x ) delta_y = int( event.y - self.click_y ) shift = math.sqrt( delta_x * delta_x + delta_y * delta_y ) if shift > min_shift : self.map.Shift(delta_x, delta_y) - # if delta_x > 100 : - # self.map.Left() - # elif delta_x < -100 : - # self.map.Right() - # elif delta_y > 100 : - # self.map.Up() - # elif delta_y < -100 : - # self.map.Down() self.click_x , self.click_y = None , None - def screen_event ( self, widget, event, *args ) : - print "REDIOS",event - print " ",widget - print " ",args - - - def on_button_press ( self, widget, event, *args ) : - print "HOLA",event - def on_key_press ( self, widget, event, *args ) : if event.keyval == gtk.keysyms.Up : self.map.Up() @@ -269,16 +118,12 @@ class AbstractMapWindow: self.vbox = gtk.VBox(False, 0) - # To get explicit GDK_BUTTON_PRESS instead of paired GDK_LEAVE_NOTIFY & GDK_ENTER_NOTIFY -# self.add_events(gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK) self.set_events( gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK ) - # -# self.connect('motion_notify_event', self.screen_event) self.connect('button_press_event', self.press_event) self.connect('button_release_event', self.release_event) - # + self.config = wifimap.config.Configuration() - self.map = mapWidget( self.config , map_size ) + self.map = wifimap.view.mapWidget( self.config , map_size ) self.vbox.pack_end( self.map , True , True , 5) self.size_x , self.size_y = map_size -- 1.7.9.5