2 * gps - gps resource for zavai
4 * Copyright (C) 2009--2010 Enrico Zini <enrico@enricozini.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 // For a list of dbus services, look in /etc/dbus-1/system.d/
27 public class GPS: zavai.Service
29 protected libgps.data_t data;
30 protected IOChannel gpsfd = null;
31 protected uint gpsfd_watch = 0;
33 protected int old_fix_status = libgps.STATUS_NO_FIX;
34 protected uint old_time = 0;
36 public signal void fix_status_changed(int status);
37 public signal void time_changed(uint time);
42 data = libgps.data_t();
45 public int fix_status() { return old_fix_status; }
46 public double time() { return old_time; }
47 public weak libgps.data_t info() { return data; }
49 protected bool on_input_data(IOChannel source, IOCondition condition)
51 while (libgps.waiting(ref data))
53 int res = libgps.poll(ref data);
55 zavai.log.error(libgps.errstr(res));
57 if (data.status != old_fix_status)
59 fix_status_changed(data.status);
60 old_fix_status = data.status;
63 uint cur_time = (uint)data.fix.time;
64 if (data.status != libgps.STATUS_NO_FIX && old_time != cur_time)
66 time_changed(cur_time);
71 stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status);
72 stderr.printf("SATUSED %d\n", data.satellites_used);
73 stderr.printf("SWT %f\n", data.skyview_time);
74 stderr.printf("SATVIS %d\n", data.satellites_visible);
75 for (int i = 0; i < data.satellites_visible; ++i)
77 stderr.printf("PRN %d ELE %d AZI %d SS %f\n",
78 data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]);
85 /// Request GPS resource
86 public override void start()
91 // Then run our own script
92 zavai.app.run_script(zavai.config.homedir + "/gps start");
94 zavai.log.error("Running " + zavai.config.homedir + "/gps start: " + e.message);
98 int res = libgps.open_r("ciapino", "gpsd", ref data);
101 zavai.log.error(libgps.errstr(res));
105 res = libgps.stream(ref data, libgps.WATCH_ENABLE, null);
108 zavai.log.error(libgps.errstr(res));
112 res = libgps.send(ref data, "?SKY;");
113 //res = libgps.send(ref data, "?WATCH;");
114 //if (res != 0) zavai.log.error(libgps.errstr(res));
116 gpsfd = new IOChannel.unix_new(data.gps_fd);
118 gpsfd.set_encoding(null);
120 zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message);
122 //gpsfd.set_buffered(false);
123 gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data);
125 zavai.log.info("GPS turned on");
129 // Release usage of GPS
130 public override void stop()
132 if (!started) return;
134 Source.remove(gpsfd_watch);
136 int res = libgps.close(ref data);
138 zavai.log.error(libgps.errstr(res));
141 zavai.app.run_script(zavai.config.homedir + "/gps stop");
143 zavai.log.error("Running device stop gps: " + e.message);
146 if (old_fix_status != libgps.STATUS_NO_FIX)
148 old_fix_status = libgps.STATUS_NO_FIX;
149 fix_status_changed(old_fix_status);
155 time_changed(old_time);
162 public class Position : zavai.Service
164 dynamic DBus.Object position;
166 public signal void position_changed(int fields, int tstamp, double lat, double lon, double alt);
170 Object(name: "gps.position");
171 position = zavai.registry.sbus.get_object(
172 "org.freesmartphone.ogpsd",
173 "/org/freedesktop/Gypsy",
174 "org.freedesktop.Gypsy.Position");
177 public void on_position_changed(dynamic DBus.Object pos, int fields, int tstamp, double lat, double lon, double alt)
179 zavai.log.info("gps position: position changed");
180 position_changed(fields, tstamp, lat, lon, alt);
183 public override void start()
186 zavai.log.info("Starting GPS position tracking");
187 gps.request("gps.position");
188 position.PositionChanged += on_position_changed;
192 public override void stop()
194 if (!started) return;
195 zavai.log.info("Stopping GPS position tracking");
196 position.PositionChanged -= on_position_changed;
197 gps.release("gps.position");
202 // # def wait_for_fix(self, callback):
203 // # status = self.gps.GetFixStatus()
204 // # if status in [2, 3]:
205 // # zavai.info("We already have a fix, good.")
209 // # zavai.info("Waiting for a fix...")
210 // # self.waiting_for_fix = callback
211 // # self.bus.add_signal_receiver(
212 // # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
213 // # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
216 // # def start_recording(self):
217 // # if self.gps_monitor:
218 // # self.gps_monitor.stop()
219 // # self.gps_monitor = None
221 // # if not self.audio:
224 // # # Sync system time
225 // # gpstime = self.gps.gps_time.GetTime()
226 // # subprocess.call(["date", "-s", "@%d" % gpstime])
227 // # subprocess.call(["hwclock", "--systohc"])
229 // # # Compute basename for output files
230 // # self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
231 // # self.basename = os.path.join(AUDIODIR, self.basename)
233 // # # Start recording the GPX track
234 // # self.gpx = GPX(self.basename)
235 // # self.gps.track_position(self.on_position_changed)
237 // # # Start recording in background forking arecord
238 // # self.audio.set_basename(self.basename)
239 // # self.audio.start_recording()
242 // Write GPX track and waypoint files
243 public class GPX : Service
245 public bool tracking {
246 get { return trk != null; }
249 public signal void tracking_changed(bool tracking);
251 FileStream trk = null;
252 FileStream wpt = null;
254 bool last_valid = false;
263 Object(name: "gps.gpx");
266 public override void start()
270 log.info("Starting GPX trace subsystem");
271 position.request("gps.gpx");
272 position.position_changed += on_position_changed;
277 public override void stop()
281 log.info("Stopping GPX trace subsystem");
282 position.release("gps.gpx");
283 position.position_changed -= on_position_changed;
289 public void on_position_changed(Position pos, int fields, int tstamp, double lat, double lon, double alt)
291 last_fields = fields;
292 last_tstamp = tstamp;
300 public void start_track(time_t tstamp = 0, string? basename = null)
303 if (basename != null)
307 time_t now = tstamp == 0 ? time_t() : tstamp;
309 // Compute basename for output files
310 var t = Time.local(now);
311 char[] res = new char[25];
312 t.strftime(res, "%Y-%m-%d-%H-%M-%S");
313 fname = zavai.config.homedir + "/" + (string)res;
316 trk = FileStream.open(fname + "-trk.gpx", "wt");
317 trk.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
319 trk.puts(" version=\"1.0\"");
320 trk.printf(" creator=\"zavai %s\"\n", zavai.config.version);
321 trk.puts(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
322 trk.puts(" xmlns=\"http://www.topografix.com/GPX/1/0\"");
323 trk.puts(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
325 trk.puts(" <trkseg>");
327 wpt = FileStream.open(fname + "-wpt.gpx", "wt");
328 wpt.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
330 wpt.puts(" version=\"1.0\"");
331 wpt.printf(" creator=\"zavai %s\"", zavai.config.version);
332 wpt.puts(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
333 wpt.puts(" xmlns=\"http://www.topografix.com/GPX/1/0\"");
334 wpt.puts(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
337 tracking_changed(true);
340 public void stop_track()
344 trk.puts("</trkseg></trk></gpx>");
355 tracking_changed(false);
358 // Mark a track point
359 public void trackpoint()
361 if (!last_valid) return;
363 start_track(last_tstamp);
365 trk.printf("<trkpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
366 var t = Time.local(last_tstamp);
367 char[] ts = new char[25];
368 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
369 trk.printf(" <time>%s</time>\n", (string)ts);
370 trk.printf(" <ele>%f</ele>\n", last_alt);
371 // if course is not None: print >>self.trk, " <course>%f</course>" % course
372 // if speed is not None: print >>self.trk, " <speed>%f</speed>" % speed
373 // if fix is not None: print >>self.trk, " <fix>%f</fix>" % fix
374 // if hdop is not None: print >>self.trk, " <hdop>%f</hdop>" % hdop
375 trk.puts("</trkpt>");
379 public void waypoint(string? name = null)
381 if (!last_valid) return;
383 start_track(last_tstamp);
388 wptname = "wpt_%d".printf(wpt_seq);
394 wpt.printf("<wpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
395 wpt.printf(" <name>%s</name>\n", wptname);
396 var t = Time.local(last_tstamp);
397 char[] ts = new char[25];
398 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
399 wpt.printf(" <time>%s</time>\n", (string)ts);
400 wpt.printf(" <ele>%f</ele>\n", last_alt);
405 public zavai.gps.GPS gps = null;
406 public zavai.gps.Position position = null;
407 public zavai.gps.GPX gpx = null;
412 position = new Position();