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
27 #import dbus.mainloop.glib
32 def __init__(self, gps):
34 self.gps_ubx = gps.gps_ubx
36 # This piece of machinery is taken from Zhone
37 self.debug_busy = None
38 self.debug_want = set( ["NAV-STATUS", "NAV-SVINFO"] )
39 self.debug_have = set()
40 self.debug_error = set()
42 self.callbacks = set()
44 def debug_update(self):
45 if self.debug_busy is None:
46 pending = self.debug_want - self.debug_have - self.debug_error
48 self.debug_busy = pending.pop()
49 self.gps_ubx.SetDebugFilter(
52 reply_handler=self.on_debug_reply,
53 error_handler=self.on_debug_error,
56 def debug_request(self):
57 self.debug_have = set()
60 def on_debug_reply(self):
61 self.debug_have.add(self.debug_busy)
62 self.debug_busy = None
65 def on_debug_error(self, e):
66 zavai.info(e, "error while requesting debug packet %s" % self.debug_busy)
67 self.debug_error.add(self.debug_busy)
68 self.debug_busy = None
71 def on_satellites_changed(self, satellites):
72 self.gps_debug.request()
74 def on_ubxdebug_packet(self, clid, length, data):
75 for c in self.callbacks:
78 def _start_listening(self):
79 self.gps.request(self)
80 # TODO: find out how come sometimes these events are not sent
81 self.gps.bus.add_signal_receiver(
82 self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
83 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
84 self.gps.bus.add_signal_receiver(
85 self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
86 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
89 def _stop_listening(self):
90 self.gps.bus.remove_signal_receiver(
91 self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
92 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
93 self.gps.bus.remove_signal_receiver(
94 self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX',
95 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
96 self.gps.release(self)
98 def connect(self, callback):
99 "Send UBX debug packets to the given callback"
100 do_start = not self.callbacks
101 self.callbacks.add(callback)
103 self._start_listening()
105 def disconnect(self, callback):
106 "Stop sending UBX debug packets to the given callback"
107 if not self.callbacks: return
108 self.callbacks.discard(callback)
109 if not self.callbacks:
110 self._stop_listening()
112 # # In zhone it is cbUBXDebugPacket
113 # #if clid == "NAV-STATUS" and data:
114 # # i = ["%s: %d" % (k, data[0][k]) for k in sorted(data[0].keys())]
115 # # zavai.info("Status:", " ".join(i))
116 # ## if data[0]['TTFF']:
117 # ## zavai.info("TTFF: %f", data[0]['TTFF']/1000.0)
118 # if clid == "NAV-SVINFO":
119 # self.print_ubx_sat_data(data[1:])
121 # # zavai.info("gps got ubxdebug packet", clid)
122 # # zavai.info("DATA:", data)
124 # def print_ubx_sat_data(self, ubxinfo):
125 # zavai.info("CH ID SN ELE AZI Used Diff Alm Eph Bad Status")
127 # if sv["CNO"] == 0: continue
129 # used = sv["Flags"] & 0x01
130 # diff = sv["Flags"] & 0x02
131 # almoreph = sv["Flags"] & 0x04
132 # eph = sv["Flags"] & 0x08
133 # bad = sv["Flags"] & 0x10
134 # qi = ("%i: " % sv["QI"]) + {
137 # 2: "signal acquired",
138 # 3: "signal unusable",
140 # 5: "code&carrier lock",
141 # 6: "code&carrier lock",
142 # 7: "receiving data"
144 # zavai.info("%2d %2d %2d %3d %3d %s %s %s %s %s %s" % (
145 # sv["chn"], sv["SVID"],
146 # sv["CNO"], sv["Elev"], sv["Azim"],
147 # used and "used" or "----",
148 # diff and "diff" or "----",
149 # almoreph and "alm" or "---",
150 # eph and "eph" or "---",
151 # bad and "bad" or "---",
154 # def print_sat_data(self, satellites):
155 # for sat in satellites:
156 # if sat[4] == 0: continue
157 # zavai.info("PRN %u" % sat[0],
158 # sat[1] and "used" or "unused",
163 # For a list of dbus services, look in /etc/dbus-1/system.d/
164 class GPS(zavai.Resource):
165 def __init__(self, registry, name):
166 self.bus = registry.resource("dbus.system_bus")
168 # see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage
169 self.usage = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage')
170 self.usage = dbus.Interface(self.usage, "org.freesmartphone.Usage")
172 # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy
173 gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
174 self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device")
175 self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time")
176 self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position')
177 self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX')
179 self.monitor = GPSMonitor(self)
181 self.requestors = set()
183 def request(self, tag):
184 "Request usage of GPS by the subsystem with the given tag"
185 do_start = not self.requestors
186 self.requestors.add(tag)
188 # Request GPS resource
189 self.usage.RequestResource('GPS')
190 zavai.info("Acquired GPS")
192 def release(self, tag):
193 "Release usage of GPS by the subsystem with the given tag"
194 if not self.requestors: return
195 self.requestors.discard(tag)
196 if not self.requestors:
197 self.usage.ReleaseResource('GPS')
198 zavai.info("Released GPS")
202 self.requestors.clear()
203 self.usage.ReleaseResource('GPS')
204 zavai.info("Released GPS")
206 # def wait_for_fix(self, callback):
207 # status = self.gps.GetFixStatus()
208 # if status in [2, 3]:
209 # zavai.info("We already have a fix, good.")
213 # zavai.info("Waiting for a fix...")
214 # self.waiting_for_fix = callback
215 # self.bus.add_signal_receiver(
216 # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
217 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
220 # def on_fix_status_changed(self, status):
221 # if status not in [2, 3]: return
223 # zavai.info("Got GPS fix")
224 # self.bus.remove_signal_receiver(
225 # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
226 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
228 # if self.waiting_for_fix:
229 # self.waiting_for_fix()
230 # self.waiting_for_fix = None
232 # def track_position(self, callback):
233 # self.bus.add_signal_receiver(
234 # callback, 'PositionChanged', 'org.freedesktop.Gypsy.Position',
235 # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
238 class GPX(zavai.Resource):
239 "Write GPX track and waypoint files"
240 def __init__(self, resource, name):
241 self.resource = resource
245 def start(basename = None, tstamp = None):
247 # compute it from GPS
250 self.trk = open(basename + "-trk.gpx", "wt")
251 print >>self.trk, """<?xml version="1.0" encoding="UTF-8"?>
254 creator="audiomap %s"
255 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
256 xmlns="http://www.topografix.com/GPX/1/0"
257 xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
259 <trkseg>""" % VERSION
261 self.wpt = open(basename + "-wpt.gpx", "wt")
262 print >>self.wpt, """<?xml version="1.0" encoding="UTF-8"?>
265 creator="audiomap %s"
266 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
267 xmlns="http://www.topografix.com/GPX/1/0"
268 xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">""" % VERSION
273 if self.trk is not None:
274 print >>self.trk, "</trkseg></trk></gpx>"
277 if self.wpt is not None:
278 print >>self.wpt, "</gpx>"
285 def waypoint(self, tstamp, lat, lon, ele = None, name = None):
288 name = "wpt_%d" % self.wpt_seq
291 print >>self.wpt, """<wpt lat="%f" lon="%f">
293 <time>%s</time>""" % (
294 lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
296 print >>self.wpt, " <ele>%f</ele>""" % ele
297 print >>self.wpt, "</wpt>"
299 def trackpoint(self, tstamp, lat, lon, ele = None, course = None, speed = None, fix = None, hdop = None):
300 print >>self.trk, """<trkpt lat="%f" lon="%f">
301 <time>%s</time>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)))
302 if ele is not None: print >>self.trk, " <ele>%f</ele>" % ele
303 if course is not None: print >>self.trk, " <course>%f</course>" % course
304 if speed is not None: print >>self.trk, " <speed>%f</speed>" % speed
305 if fix is not None: print >>self.trk, " <fix>%f</fix>" % fix
306 if hdop is not None: print >>self.trk, " <hdop>%f</hdop>" % hdop
307 print >>self.trk, "</trkpt>"
313 # self.audio = Audio(self.make_waypoint)
315 # # Get a fix and start recording
316 # if not self.gps.wait_for_fix(self.start_recording):
317 # self.gps_monitor = GPSMonitor(self.gps)
318 # self.gps_monitor.start()
323 # self.gps_monitor = GPSMonitor(self.gps)
324 # self.gps_monitor.start()
326 # def start_recording(self):
327 # if self.gps_monitor:
328 # self.gps_monitor.stop()
329 # self.gps_monitor = None
335 # gpstime = self.gps.gps_time.GetTime()
336 # subprocess.call(["date", "-s", "@%d" % gpstime])
337 # subprocess.call(["hwclock", "--systohc"])
339 # # Compute basename for output files
340 # self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
341 # self.basename = os.path.join(AUDIODIR, self.basename)
343 # # Start recording the GPX track
344 # self.gpx = GPX(self.basename)
345 # self.gps.track_position(self.on_position_changed)
347 # # Start recording in background forking arecord
348 # self.audio.set_basename(self.basename)
349 # self.audio.start_recording()
351 # def on_position_changed(self, fields, tstamp, lat, lon, alt):
352 # self.last_pos = (fields, tstamp, lat, lon, alt)
354 # self.gpx.trackpoint(tstamp, lat, lon, alt)
356 # def make_waypoint(self):
357 # if self.gpx is None:
359 # if self.last_pos is None:
360 # self.last_pos = self.gps.gps_position.GetPosition()
361 # (fields, tstamp, lat, lon, alt) = self.last_pos
362 # self.gpx.waypoint(tstamp, lat, lon, alt)
363 # zavai.info("Making waypoint at %s: %f, %f, %f" % (
364 # time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt))