1 # gps - gps resource for zavai
3 # Copyright (C) 2009 Enrico Zini <enrico@enricozini.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 def __init__(self, gps):
32 self.gps_ubx = gps.gps_ubx
34 # This piece of machinery is taken from Zhone
35 self.debug_busy = None
36 self.debug_want = set( ["NAV-STATUS", "NAV-SVINFO"] )
37 self.debug_have = set()
38 self.debug_error = set()
40 self.callbacks = set()
42 def debug_update(self):
43 if self.debug_busy is None:
44 pending = self.debug_want - self.debug_have - self.debug_error
46 self.debug_busy = pending.pop()
47 self.gps_ubx.SetDebugFilter(
50 reply_handler=self.on_debug_reply,
51 error_handler=self.on_debug_error,
54 def debug_request(self):
55 self.debug_have = set()
58 def on_debug_reply(self):
59 self.debug_have.add(self.debug_busy)
60 self.debug_busy = None
63 def on_debug_error(self, e):
64 zavai.info(e, "error while requesting debug packet %s" % self.debug_busy)
65 self.debug_error.add(self.debug_busy)
66 self.debug_busy = None
69 def on_satellites_changed(self, satellites):
72 def on_ubxdebug_packet(self, clid, length, data):
73 for c in self.callbacks:
76 def _start_listening(self):
77 self.gps.request(self)
78 # TODO: find out how come sometimes these events are not sent
79 self.gps.bus.add_signal_receiver(
80 self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
81 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
82 self.gps.bus.add_signal_receiver(
83 self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
84 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
87 def _stop_listening(self):
88 self.gps.bus.remove_signal_receiver(
89 self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
90 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
91 self.gps.bus.remove_signal_receiver(
92 self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
93 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
94 self.gps.release(self)
96 def connect(self, callback):
97 "Send UBX debug packets to the given callback"
98 do_start = not self.callbacks
99 self.callbacks.add(callback)
101 self._start_listening()
103 def disconnect(self, callback):
104 "Stop sending UBX debug packets to the given callback"
105 if not self.callbacks: return
106 self.callbacks.discard(callback)
107 if not self.callbacks:
108 self._stop_listening()
111 # For a list of dbus services, look in /etc/dbus-1/system.d/
112 class GPS(zavai.Resource):
113 def __init__(self, registry, name):
114 self.bus = registry.resource("dbus.system_bus")
116 # see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage
117 self.usage = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage')
118 self.usage = dbus.Interface(self.usage, "org.freesmartphone.Usage")
120 # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy
121 gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
122 self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device")
123 self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time")
124 self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position')
125 self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX')
127 self.monitor = GPSMonitor(self)
129 self.requestors = set()
131 def request(self, tag):
132 "Request usage of GPS by the subsystem with the given tag"
133 do_start = not self.requestors
134 self.requestors.add(tag)
136 # Request GPS resource
137 self.usage.RequestResource('GPS')
138 zavai.info("Acquired GPS")
140 def release(self, tag):
141 "Release usage of GPS by the subsystem with the given tag"
142 if not self.requestors: return
143 self.requestors.discard(tag)
144 if not self.requestors:
145 self.usage.ReleaseResource('GPS')
146 zavai.info("Released GPS")
150 self.requestors.clear()
151 self.usage.ReleaseResource('GPS')
152 zavai.info("Released GPS")
154 # def wait_for_fix(self, callback):
155 # status = self.gps.GetFixStatus()
156 # if status in [2, 3]:
157 # zavai.info("We already have a fix, good.")
161 # zavai.info("Waiting for a fix...")
162 # self.waiting_for_fix = callback
163 # self.bus.add_signal_receiver(
164 # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
165 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
168 # def on_fix_status_changed(self, status):
169 # if status not in [2, 3]: return
171 # zavai.info("Got GPS fix")
172 # self.bus.remove_signal_receiver(
173 # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
174 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
176 # if self.waiting_for_fix:
177 # self.waiting_for_fix()
178 # self.waiting_for_fix = None
180 # def track_position(self, callback):
181 # self.bus.add_signal_receiver(
182 # callback, 'PositionChanged', 'org.freedesktop.Gypsy.Position',
183 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
186 class GPX(zavai.Resource):
187 "Write GPX track and waypoint files"
188 def __init__(self, resource, name):
189 self.resource = resource
193 def start(basename = None, tstamp = None):
195 # compute it from GPS
198 self.trk = open(basename + "-trk.gpx", "wt")
199 print >>self.trk, """<?xml version="1.0" encoding="UTF-8"?>
202 creator="audiomap %s"
203 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
204 xmlns="http://www.topografix.com/GPX/1/0"
205 xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
207 <trkseg>""" % VERSION
209 self.wpt = open(basename + "-wpt.gpx", "wt")
210 print >>self.wpt, """<?xml version="1.0" encoding="UTF-8"?>
213 creator="audiomap %s"
214 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
215 xmlns="http://www.topografix.com/GPX/1/0"
216 xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">""" % VERSION
221 if self.trk is not None:
222 print >>self.trk, "</trkseg></trk></gpx>"
225 if self.wpt is not None:
226 print >>self.wpt, "</gpx>"
233 def waypoint(self, tstamp, lat, lon, ele = None, name = None):
236 name = "wpt_%d" % self.wpt_seq
239 print >>self.wpt, """<wpt lat="%f" lon="%f">
241 <time>%s</time>""" % (
242 lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
244 print >>self.wpt, " <ele>%f</ele>""" % ele
245 print >>self.wpt, "</wpt>"
247 def trackpoint(self, tstamp, lat, lon, ele = None, course = None, speed = None, fix = None, hdop = None):
248 print >>self.trk, """<trkpt lat="%f" lon="%f">
249 <time>%s</time>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
250 if ele is not None: print >>self.trk, " <ele>%f</ele>" % ele
251 if course is not None: print >>self.trk, " <course>%f</course>" % course
252 if speed is not None: print >>self.trk, " <speed>%f</speed>" % speed
253 if fix is not None: print >>self.trk, " <fix>%f</fix>" % fix
254 if hdop is not None: print >>self.trk, " <hdop>%f</hdop>" % hdop
255 print >>self.trk, "</trkpt>"
261 # self.audio = Audio(self.make_waypoint)
263 # # Get a fix and start recording
264 # if not self.gps.wait_for_fix(self.start_recording):
265 # self.gps_monitor = GPSMonitor(self.gps)
266 # self.gps_monitor.start()
271 # self.gps_monitor = GPSMonitor(self.gps)
272 # self.gps_monitor.start()
274 # def start_recording(self):
275 # if self.gps_monitor:
276 # self.gps_monitor.stop()
277 # self.gps_monitor = None
283 # gpstime = self.gps.gps_time.GetTime()
284 # subprocess.call(["date", "-s", "@%d" % gpstime])
285 # subprocess.call(["hwclock", "--systohc"])
287 # # Compute basename for output files
288 # self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
289 # self.basename = os.path.join(AUDIODIR, self.basename)
291 # # Start recording the GPX track
292 # self.gpx = GPX(self.basename)
293 # self.gps.track_position(self.on_position_changed)
295 # # Start recording in background forking arecord
296 # self.audio.set_basename(self.basename)
297 # self.audio.start_recording()
299 # def on_position_changed(self, fields, tstamp, lat, lon, alt):
300 # self.last_pos = (fields, tstamp, lat, lon, alt)
302 # self.gpx.trackpoint(tstamp, lat, lon, alt)
304 # def make_waypoint(self):
305 # if self.gpx is None:
307 # if self.last_pos is None:
308 # self.last_pos = self.gps.gps_position.GetPosition()
309 # (fields, tstamp, lat, lon, alt) = self.last_pos
310 # self.gpx.waypoint(tstamp, lat, lon, alt)
311 # zavai.info("Making waypoint at %s: %f, %f, %f" % (
312 # time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt))