# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#import sys
-#import os
+import os
import os.path
import time
-#import signal
-#import optparse
import dbus
-#import gobject
import zavai
class GPSMonitor():
if not self.callbacks:
self._stop_listening()
+class GPSPosition():
+ def __init__(self, gps):
+ self.gps = gps
+ self.callbacks = set()
+
+ def on_position_changed(self, fields, tstamp, lat, lon, alt):
+ zavai.info("gps position: position changed")
+ for c in self.callbacks:
+ c(fields, tstamp, lat, lon, alt)
+
+ def _start_listening(self):
+ self.gps.request(self)
+
+ self.bus.add_signal_receiver(
+ self.on_position_changed, 'PositionChanged', 'org.freedesktop.Gypsy.Position',
+ 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+
+ # TODO: find out how come sometimes these events are not sent
+ self.gps.bus.add_signal_receiver(
+ self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
+ 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+ self.gps.bus.add_signal_receiver(
+ self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
+ 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+ self.debug_request()
+
+ def _stop_listening(self):
+ self.gps.bus.remove_signal_receiver(
+ self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
+ 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+ self.gps.bus.remove_signal_receiver(
+ self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
+ 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+ self.gps.release(self)
+
+ def connect(self, callback):
+ "Send position changed messages to the given callback"
+ do_start = not self.callbacks
+ self.callbacks.add(callback)
+ if do_start:
+ self._start_listening()
+
+ def disconnect(self, callback):
+ "Stop sending position changed messages to the given callback"
+ if not self.callbacks: return
+ self.callbacks.discard(callback)
+ if not self.callbacks:
+ self._stop_listening()
+
# For a list of dbus services, look in /etc/dbus-1/system.d/
class GPS(zavai.Resource):
self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX')
self.monitor = GPSMonitor(self)
+ self.position = GPSPosition(self)
self.requestors = set()
# self.waiting_for_fix()
# self.waiting_for_fix = None
#
-# def track_position(self, callback):
-# self.bus.add_signal_receiver(
-# callback, 'PositionChanged', 'org.freedesktop.Gypsy.Position',
-# 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
+# def start_recording(self):
+# if self.gps_monitor:
+# self.gps_monitor.stop()
+# self.gps_monitor = None
+#
+# if not self.audio:
+# return
+#
+# # Sync system time
+# gpstime = self.gps.gps_time.GetTime()
+# subprocess.call(["date", "-s", "@%d" % gpstime])
+# subprocess.call(["hwclock", "--systohc"])
+#
+# # Compute basename for output files
+# self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
+# self.basename = os.path.join(AUDIODIR, self.basename)
+#
+# # Start recording the GPX track
+# self.gpx = GPX(self.basename)
+# self.gps.track_position(self.on_position_changed)
+#
+# # Start recording in background forking arecord
+# self.audio.set_basename(self.basename)
+# self.audio.start_recording()
+#
class GPX(zavai.Resource):
"Write GPX track and waypoint files"
- def __init__(self, resource, name):
- self.resource = resource
+ def __init__(self, registry, name):
+ self.registry = registry
self.trk = None
self.wpt = None
+ self.last_pos = None
+ self.requestors = set()
+ conf = registry.resource("conf")
+ self.trackdir = os.path.expanduser("~/.zavai")
+ if conf.has_section("gps"):
+ if conf.has_option("gps", "trackdir"):
+ self.trackdir = conf.get("gps", "trackdir")
+ if not os.path.isdir(self.trackdir):
+ os.makedirs(self.trackdir)
+
+ def request(self, tag):
+ "Request the GPX trace to be taken"
+ do_start = not self.requestors
+ self.requestors.add(tag)
+ if do_start:
+ zavai.info("Starting GPX trace subsystem")
+ gps = self.registry.resource("gps")
+ gps.position.connect(self.on_position_changed)
+
+ def release(self, tag):
+ "Release a GPX trace request"
+ if not self.requestors: return
+ self.requestors.discard(tag)
+ if not self.requestors:
+ zavai.info("Stopping GPX trace subsystem")
+ gps = self.registry.resource("gps")
+ gps.position.disconnect(self.on_position_changed)
+ self.stop()
+
+ def on_position_changed(self, fields, tstamp, lat, lon, alt):
+ self.last_pos = (fields, tstamp, lat, lon, alt)
+ self.trackpoint()
def start(basename = None, tstamp = None):
if basename is None:
- # compute it from GPS
- pass
+ # Compute basename for output files
+ basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(tstamp))
+ basename = os.path.join(self.trackdir, self.basename)
self.trk = open(basename + "-trk.gpx", "wt")
print >>self.trk, """<?xml version="1.0" encoding="UTF-8"?>
print >>self.wpt, "</gpx>"
self.wpt.close()
self.wpt = None
+ self.last_pos = None
def shutdown(self):
self.stop()
- def waypoint(self, tstamp, lat, lon, ele = None, name = None):
+ def trackpoint(self):
+ "Mark a track point"
+ if self.last_pos is None:
+ return
+
+ fields, tstamp, lat, lon, ele = self.last_pos
+
+ if not self.trk:
+ self.start(tstamp)
+
+ print >>self.trk, """<trkpt lat="%f" lon="%f">
+ <time>%s</time>
+ <ele>%f</ele>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
+ #if course is not None: print >>self.trk, " <course>%f</course>" % course
+ #if speed is not None: print >>self.trk, " <speed>%f</speed>" % speed
+ #if fix is not None: print >>self.trk, " <fix>%f</fix>" % fix
+ #if hdop is not None: print >>self.trk, " <hdop>%f</hdop>" % hdop
+ print >>self.trk, "</trkpt>"
+
+ def waypoint(self, name = None):
"Mark a waypoint"
+ if self.last_pos is None:
+ return
+
+ fields, tstamp, lat, lon, ele = self.last_pos
+
+ if not self.wpt:
+ self.start(tstamp)
+
if name is None:
name = "wpt_%d" % self.wpt_seq
self.wpt_seq += 1
print >>self.wpt, """<wpt lat="%f" lon="%f">
<name>%s</name>
- <time>%s</time>""" % (
- lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
- if ele is not None:
- print >>self.wpt, " <ele>%f</ele>""" % ele
- print >>self.wpt, "</wpt>"
-
- def trackpoint(self, tstamp, lat, lon, ele = None, course = None, speed = None, fix = None, hdop = None):
- print >>self.trk, """<trkpt lat="%f" lon="%f">
- <time>%s</time>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
- if ele is not None: print >>self.trk, " <ele>%f</ele>" % ele
- if course is not None: print >>self.trk, " <course>%f</course>" % course
- if speed is not None: print >>self.trk, " <speed>%f</speed>" % speed
- if fix is not None: print >>self.trk, " <fix>%f</fix>" % fix
- if hdop is not None: print >>self.trk, " <hdop>%f</hdop>" % hdop
- print >>self.trk, "</trkpt>"
-
-
+ <time>%s</time>
+ <ele>%f</ele>
+</wpt>""" % (
+ lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
# def record(self):
# self.gps_monitor = GPSMonitor(self.gps)
# self.gps_monitor.start()
#
-# def start_recording(self):
-# if self.gps_monitor:
-# self.gps_monitor.stop()
-# self.gps_monitor = None
-#
-# if not self.audio:
-# return
-#
-# # Sync system time
-# gpstime = self.gps.gps_time.GetTime()
-# subprocess.call(["date", "-s", "@%d" % gpstime])
-# subprocess.call(["hwclock", "--systohc"])
-#
-# # Compute basename for output files
-# self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
-# self.basename = os.path.join(AUDIODIR, self.basename)
-#
-# # Start recording the GPX track
-# self.gpx = GPX(self.basename)
-# self.gps.track_position(self.on_position_changed)
-#
-# # Start recording in background forking arecord
-# self.audio.set_basename(self.basename)
-# self.audio.start_recording()
-#
-# def on_position_changed(self, fields, tstamp, lat, lon, alt):
-# self.last_pos = (fields, tstamp, lat, lon, alt)
-# if self.gpx:
-# self.gpx.trackpoint(tstamp, lat, lon, alt)
#
# def make_waypoint(self):
# if self.gpx is None: