Added sat-monitor python satellite monitor
authorEnrico Zini <enrico@enricozini.org>
Mon, 3 Aug 2009 18:43:53 +0000 (19:43 +0100)
committerEnrico Zini <enrico@enricozini.org>
Mon, 3 Aug 2009 18:43:53 +0000 (19:43 +0100)
src/Makefile.am
src/sat-monitor [new file with mode: 0755]

index cc687ca3450cd337a614b8987812920c1cc5189d..8ff2c75802b554f2f7cbc05bd2eef9a063868519 100644 (file)
@@ -26,6 +26,8 @@ BUILT_SOURCES = zavai.vala.stamp
 
 bin_PROGRAMS = zavai
 
+bin_SCRIPTS = sat-monitor
+
 zavai_VALASOURCES = \
        log.vala \
        config.vala \
@@ -60,4 +62,5 @@ zavai_LDADD = \
 #      gee-1.0.vapi \
 #      $(NULL)
 
-#EXTRA_DIST += $(libgee_la_VALASOURCES) gee-1.0.vapi gee.vala.stamp
+EXTRA_DIST = sat-monitor
+#$(libgee_la_VALASOURCES) gee-1.0.vapi gee.vala.stamp
diff --git a/src/sat-monitor b/src/sat-monitor
new file mode 100755 (executable)
index 0000000..70d5cdc
--- /dev/null
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+#
+# Satellite monitor for Gypsy, based on the zhone satellite monitor
+#
+# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import sys
+import os
+import os.path
+import dbus
+import dbus.mainloop.glib
+import gtk
+from gettext import gettext as _
+
+SAT_QI_NAMES = {
+    0: _("idle"),
+    1: _("searching"),
+    2: _("signal acquired"),
+    3: _("signal unusable"),
+    4: _("code lock"),
+    5: _("code&carrier lock"),
+    6: _("code&carrier lock"),
+    7: _("receiving data")
+}
+
+
+class GPSMonitor:
+    def __init__(self):
+        self.bus = dbus.SystemBus()
+
+        # see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage
+        self.usage = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage')
+        self.usage = dbus.Interface(self.usage, "org.freesmartphone.Usage")
+
+        # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy
+        gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') 
+        self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device")
+        self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX')
+
+        # This piece of machinery is taken from Zhone
+        self.debug_busy = None
+        self.debug_want = set( ["NAV-STATUS", "NAV-SVINFO"] )
+        self.debug_have = set()
+        self.debug_error = set()
+
+        self.callback = None
+
+    def debug_update(self):
+        if self.debug_busy is None:
+            pending = self.debug_want - self.debug_have - self.debug_error
+            if pending:
+                self.debug_busy = pending.pop()
+                self.gps_ubx.SetDebugFilter(
+                    self.debug_busy,
+                    True,
+                    reply_handler=self.on_debug_reply,
+                    error_handler=self.on_debug_error,
+                )
+
+    def debug_request(self):
+        self.debug_have = set()
+        self.debug_update()
+
+    def on_debug_reply(self):
+        self.debug_have.add(self.debug_busy)
+        self.debug_busy = None
+        self.debug_update()
+
+    def on_debug_error(self, e):
+        zavai.info(e, "error while requesting debug packet %s" % self.debug_busy)
+        self.debug_error.add(self.debug_busy)
+        self.debug_busy = None
+        self.debug_update()
+
+    def on_satellites_changed(self, satellites):
+        self.debug_request()
+
+    def on_ubxdebug_packet(self, clid, length, data):
+        self.callback(clid, length, data)
+
+    def start(self):
+        self.usage.RequestResource('GPS')
+
+        # TODO: find out how come sometimes these events are not sent
+        self.bus.add_signal_receiver(
+            self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
+            'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+        self.bus.add_signal_receiver(
+            self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
+            'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+        self.debug_request()
+
+    def stop(self):
+        self.bus.remove_signal_receiver(
+            self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
+            'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+        self.bus.remove_signal_receiver(
+            self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
+            'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+        self.usage.ReleaseResource('GPS')
+
+class SatelliteMonitor(gtk.Window):
+    def __init__(self, **kw):
+        super(SatelliteMonitor, self).__init__()
+
+        self.set_title(_("Satellite monitor"))
+
+        self.gps = GPSMonitor()
+        self.gps.callback = self.on_ubxdebug_packet
+
+        self.store = gtk.ListStore(str, str, str, str, str, str, str, str, str, str, str)
+        self.view = gtk.TreeView(self.store)
+        renderer = gtk.CellRendererText()
+        for idx, name in enumerate((_("CH"), _("ID"), _("SN"), _("ELE"), _("AZI"),
+                     _("Used"), _("Diff"), _("Alm"), _("Eph"),
+                     _("Bad"), _("Status"))):
+            col = gtk.TreeViewColumn(name)
+            col.pack_start(renderer, False)
+            col.add_attribute(renderer, "text", idx)
+            self.view.append_column(col)
+        self.add(self.view)
+
+        self.connect("destroy", gtk.main_quit)
+        self.set_size_request(100, 200)
+        self.show_all()
+
+    def start(self, *args):
+        self.gps.start()
+
+    def stop(self, *args):
+        self.gps.stop()
+
+    def on_ubxdebug_packet(self, clid, length, data):
+        # In zhone it is cbUBXDebugPacket
+        #if clid == "NAV-STATUS" and data:
+        #    i = ["%s: %d" % (k, data[0][k]) for k in sorted(data[0].keys())]
+        #    zavai.info("Status:", " ".join(i))
+        ##    if data[0]['TTFF']:
+        ##        zavai.info("TTFF: %f", data[0]['TTFF']/1000.0)
+        if clid == "NAV-SVINFO":
+            self.handle_ubx_sat_data(data[1:])
+        #else:
+        #    zavai.info("gps got ubxdebug packet", clid)
+        #    zavai.info("DATA:", data)
+
+    def handle_ubx_sat_data(self, ubxinfo):
+        #zavai.info("CH ID SN ELE AZI Used Diff Alm Eph Bad Status")
+        self.store.clear()
+        for sv in ubxinfo:
+            if sv["CNO"] == 0: continue
+            svid = sv["SVID"]
+            used = sv["Flags"] & 0x01
+            diff = sv["Flags"] & 0x02
+            almoreph = sv["Flags"] & 0x04
+            eph = sv["Flags"] & 0x08
+            bad = sv["Flags"] & 0x10
+            qi = ("%i: " % sv["QI"]) + SAT_QI_NAMES.get(sv["QI"], _("Unknown"))
+            self.store.append([
+                "%2d" % sv["chn"],
+                "%2d" % sv["SVID"],
+                "%2d" % sv["CNO"],
+                "%3d" % sv["Elev"],
+                "%3d" % sv["Azim"],
+                used and "used" or "",
+                diff and "diff" or "",
+                almoreph and "alm" or "",
+                eph and "eph" or "",
+                bad and "bad" or "",
+                qi])
+
+if __name__ == "__main__":
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+    app = SatelliteMonitor()
+    app.start()
+    gtk.main()
+
+