#!/usr/bin/python # # Satellite monitor for Gypsy, based on the zhone satellite monitor # # Copyright (C) 2009 Enrico Zini # # 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()