/* * gps - gps resource for zavai * * Copyright (C) 2009--2010 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 */ using GLib; namespace zavai { namespace gps { // For a list of dbus services, look in /etc/dbus-1/system.d/ public class GPS: zavai.ScriptService { protected libgps.data_t data; protected IOChannel gpsfd = null; protected uint gpsfd_watch = 0; protected int old_fix_status = libgps.STATUS_NO_FIX; protected uint old_time = 0; protected double old_lat = 1000; protected double old_lon = 1000; public signal void fix_status_changed(int status); public signal void time_changed(uint time); public signal void pos_changed(); public GPS() { Object(name: "gps"); data = libgps.data_t(); started = script_status(); } public int fix_status() { return old_fix_status; } public double time() { return old_time; } public weak libgps.data_t info() { return data; } protected bool on_input_data(IOChannel source, IOCondition condition) { while (libgps.waiting(ref data)) { int res = libgps.poll(ref data); if (res != 0) zavai.log.error(libgps.errstr(res)); if (data.status != old_fix_status) { fix_status_changed(data.status); old_fix_status = data.status; } uint cur_time = (uint)data.fix.time; if (data.status != libgps.STATUS_NO_FIX && old_time != cur_time) { time_changed(cur_time); old_time = cur_time; } double lat = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.latitude); double lon = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.longitude); if (lat != old_lat || lon != old_lon) pos_changed(); stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status); stderr.printf("SATUSED %d\n", data.satellites_used); stderr.printf("SWT %f\n", data.skyview_time); stderr.printf("SATVIS %d\n", data.satellites_visible); for (int i = 0; i < data.satellites_visible; ++i) { stderr.printf("PRN %d ELE %d AZI %d SS %f\n", data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]); } /* */ } return true; } /// Request GPS resource public override void start() { if (started) return; if (!script_start()) return; zavai.log.info("Connecting to gpsd at " + config.gpsd_host + ":" + config.gpsd_port); int res = libgps.open_r(config.gpsd_host, config.gpsd_port, ref data); if (res != 0) { zavai.log.error(libgps.errstr(res)); return; } res = libgps.stream(ref data, libgps.WATCH_ENABLE, null); if (res != 0) { zavai.log.error(libgps.errstr(res)); return; } res = libgps.send(ref data, "?SKY;"); //res = libgps.send(ref data, "?WATCH;"); //if (res != 0) zavai.log.error(libgps.errstr(res)); gpsfd = new IOChannel.unix_new(data.gps_fd); try { gpsfd.set_encoding(null); } catch (Error e) { zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message); } //gpsfd.set_buffered(false); gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data); zavai.log.info("GPS turned on"); base.start(); } // Release usage of GPS public override void stop() { if (!started) return; Source.remove(gpsfd_watch); int res = libgps.close(ref data); if (res != 0) zavai.log.error(libgps.errstr(res)); script_stop(); if (old_fix_status != libgps.STATUS_NO_FIX) { old_fix_status = libgps.STATUS_NO_FIX; fix_status_changed(old_fix_status); } if (old_time != 0) { old_time = 0; time_changed(old_time); } base.stop(); } } // # 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() // # // Write GPX track and waypoint files public class GPX : Service { protected uint wpt_seq = 0; protected uint log_id = 0; public GPX() { Object(name: "gps.gpx"); } public override void start() { if (!started) { log_id = log.log.start("track", "GPS track"); base.start(); } } public override void stop() { if (started) { log.log.end(log_id); log_id = 0; base.stop(); } } // Mark a waypoint public void waypoint(string? name = null) { if (log_id == 0) return; string wptname; if (name == null) { wptname = "wpt_%u".printf(wpt_seq); wpt_seq += 1; } else { wptname = name; } log.log.add(log_id, wptname); } } public zavai.gps.GPS gps = null; public zavai.gps.GPX gpx = null; public void init() { gps = new GPS(); gpx = new GPX(); } } }