MERGE : incorporate changes on cleaning branch to completelly decouple wifiview and... cleaned
authorjaviplx <javiplx@gmail.com>
Sun, 1 May 2011 19:43:28 +0000 (19:43 +0000)
committerjaviplx <javiplx@gmail.com>
Sun, 1 May 2011 19:43:28 +0000 (19:43 +0000)
git-svn-id: file:///svnroot/wifihood/trunk@104 c51dfc6a-5949-4919-9c8e-f207a149c383

wifiscanner/wifimap/__init__.py
wifiscanner/wifimap/db.py
wifiscanner/wifimap/gps.py
wifiscanner/wifimap/replay.py [new file with mode: 0644]
wifiscanner/wifimap/scanner.py [new file with mode: 0644]
wifiscanner/wifimap/view.py
wifiscanner/wifimap/wifiscan.py
wifiscanner/wifiscanner.py
wifiscanner/wifiview.py

index a1c5f09..edc2cb7 100644 (file)
@@ -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 *
+
index 92fd45b..e5a4c45 100644 (file)
@@ -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 :
index e83e7b1..aaaf4fe 100644 (file)
 
-
 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 (file)
index 0000000..520a4dd
--- /dev/null
@@ -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 (file)
index 0000000..03389ba
--- /dev/null
@@ -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()                                 
+
index f98f582..bcb4c51 100755 (executable)
@@ -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
+
index ca7da15..33221b0 100644 (file)
@@ -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()                                 
 
index 2370750..a73d763 100755 (executable)
@@ -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 ) :
 
index b2d942c..0437d70 100755 (executable)
@@ -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