/* * gps - gps resource for zavai * * Copyright (C) 2009 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.Service { public dynamic DBus.Object usage; public dynamic DBus.Object device; public GPS() { name = "gps"; // see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage usage = zavai.registry.sbus.get_object( "org.freesmartphone.ousaged", "/org/freesmartphone/Usage", "org.freesmartphone.Usage"); device = zavai.registry.sbus.get_object( "org.freesmartphone.ogpsd", "/org/freedesktop/Gypsy", "org.freedesktop.Gypsy.Device"); // # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy // gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') // self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device") // self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time") // self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position') // self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX') usage.ResourceChanged += on_resourcechanged; } public void on_resourcechanged(dynamic DBus.Object pos, string name, bool state, HashTable attributes) { zavai.log.info("RESOURCE CHANGED " + name); } /// Request GPS resource public override void start() { if (started) return; try { usage.RequestResource("GPS"); zavai.log.info("Acquired GPS"); base.start(); } catch (GLib.Error e) { zavai.log.error(e.message); } base.start(); } // Release usage of GPS public override void stop() { if (!started) return; try { usage.ReleaseResource("GPS"); zavai.log.info("Released GPS"); base.stop(); } catch (GLib.Error e) { zavai.log.error(e.message); } base.stop(); } } public class Monitor : zavai.Service { static const int NAV_STATUS=0; static const int NAV_SVINFO=1; static const int NAV_MAX=2; dynamic DBus.Object ubx; dynamic DBus.Object time; /* string[] filters = { "NAV-STATUS", "NAV_SVINFO" }; int debug_busy; int debug_want; int debug_have; int debug_error; */ public Monitor() { name = "gps.monitor"; ubx = zavai.registry.sbus.get_object( "org.freesmartphone.ogpsd", "/org/freedesktop/Gypsy", "org.freesmartphone.GPS.UBX"); time = zavai.registry.sbus.get_object( "org.freesmartphone.ogpsd", "/org/freedesktop/Gypsy", "org.freedesktop.Gypsy.Time"); zavai.log.info("SETSIG1"); time.TimeChanged += timechanged; zavai.log.info("SETSIG2"); zavai.log.info("DEBUG1"); ubx.DebugPacket += on_ubxdebug_packet; zavai.log.info("DEBUG2"); /* // This piece of machinery is taken from Zhone debug_busy = -1; debug_want = (1 << NAV_STATUS) | (1 << NAV_SVINFO); debug_have = 0; debug_error = 0; */ } protected void timechanged(dynamic DBus.Object pos, int t) { zavai.log.info("TIMECHANGED"); } /* protected void debug_update() throws GLib.Error { zavai.log.debug("UPDATE"); if (debug_busy != -1) return; zavai.log.debug("UPD1"); int pending = debug_want & (~debug_have) & (~debug_error); if (pending == 0) return; zavai.log.debug("UPD2"); for (int i = 0; i < NAV_MAX; ++i) if ((pending & (1<[] data) { zavai.log.info("gps monitor: UBX debug packet"); message("ZAZA %s %d", clid, length); message("ZAZA %u %lu", data.length, sizeof(HashTable)); message("ZAZA %p %p", (void*)data.length, this); message("ZAZA %p", data[0]); message("ZAZA %p", data[1]); message("ZAZA %p", data[2]); /* message("ZAZA %u", data[0].size()); foreach (string k in data[0].get_keys()) message("ZAZA %s", k); */ PtrArray< HashTable >* prova = (PtrArray< HashTable >)data; message("ZAZA %u", prova->len); /* foreach (string k in prova[0].get_keys()) message("ZAZA %s", k); */ /* for (int i = 0; data[i] != null; ++i) { zavai.log.info("ZAZA"); } */ //message("Size: %d", data.size()); // self.notify("satellites", clid, length, data) } protected override void start() { if (started) return; zavai.log.info("Starting GPS Monitor"); gps.request("gps.monitor"); // # 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') //ubx.DebugPacket += prova; //try { //ubx.SetDebugFilter("NAV-STATUS", true); //ubx.SetDebugFilter("NAV-SVINFO", true); //debug_request(); base.start(); //} catch (GLib.Error e) { //zavai.log.error(e.message); //} } protected override void stop() { if (!started) return; zavai.log.info("Stopping GPS Monitor"); // self.gps.bus.remove_signal_receiver( // self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite', // 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') try { ubx.SetDebugFilter("NAV-STATUS", false); ubx.SetDebugFilter("NAV-SVINFO", false); } catch (GLib.Error e) { zavai.log.error(e.message); } ubx.DebugPacket -= on_ubxdebug_packet; //ubx.DebugPacket -= prova; gps.release("gps.monitor"); base.stop(); } } public class Position : zavai.Service { dynamic DBus.Object position; public signal void position_changed(int fields, int tstamp, double lat, double lon, double alt); public Position() { name = "gps.position"; position = zavai.registry.sbus.get_object( "org.freesmartphone.ogpsd", "/org/freedesktop/Gypsy", "org.freedesktop.Gypsy.Position"); } public void on_position_changed(dynamic DBus.Object pos, int fields, int tstamp, double lat, double lon, double alt) { zavai.log.info("gps position: position changed"); position_changed(fields, tstamp, lat, lon, alt); } public override void start() { if (started) return; zavai.log.info("Starting GPS position tracking"); gps.request("gps.position"); position.PositionChanged += on_position_changed; base.start(); } public override void stop() { if (!started) return; zavai.log.info("Stopping GPS position tracking"); position.PositionChanged -= on_position_changed; gps.release("gps.position"); base.stop(); } } // # def wait_for_fix(self, callback): // # status = self.gps.GetFixStatus() // # if status in [2, 3]: // # zavai.info("We already have a fix, good.") // # callback() // # return True // # else: // # zavai.info("Waiting for a fix...") // # self.waiting_for_fix = callback // # self.bus.add_signal_receiver( // # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', // # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') // # return False // # // # def on_fix_status_changed(self, status): // # if status not in [2, 3]: return // # // # zavai.info("Got GPS fix") // # self.bus.remove_signal_receiver( // # self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', // # 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') // # // # if self.waiting_for_fix: // # self.waiting_for_fix() // # self.waiting_for_fix = None // # // // # 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 { public bool tracking { get { return trk != null; } set {} } public signal void tracking_changed(bool tracking); FileStream trk = null; FileStream wpt = null; int wpt_seq = 1; bool last_valid = false; int last_fields; time_t last_tstamp; double last_lat; double last_lon; double last_alt; public GPX() { name = "gps.gpx"; } public override void start() { if (!started) { log.info("Starting GPX trace subsystem"); position.request("gps.gpx"); position.position_changed += on_position_changed; base.start(); } } public override void stop() { if (started) { log.info("Stopping GPX trace subsystem"); position.release("gps.gpx"); position.position_changed -= on_position_changed; stop_track(); base.stop(); } } public void on_position_changed(Position pos, int fields, int tstamp, double lat, double lon, double alt) { last_fields = fields; last_tstamp = tstamp; last_lat = lat; last_lon = lon; last_alt = alt; last_valid = true; trackpoint(); } public void start_track(time_t tstamp = 0, string? basename = null) { string fname; if (basename != null) fname = basename; else { time_t now = tstamp == 0 ? time_t() : tstamp; // Compute basename for output files var t = Time.local(now); char[] res = new char[25]; t.strftime(res, "%Y-%m-%d-%H-%M-%S"); fname = zavai.config.homedir + "/" + (string)res; } trk = FileStream.open(fname + "-trk.gpx", "wt"); trk.puts(""); trk.puts(" "); trk.puts(" "); trk.puts(" "); wpt = FileStream.open(fname + "-wpt.gpx", "wt"); wpt.puts(""); wpt.puts(" "); wpt_seq = 1; tracking_changed(true); } public void stop_track() { if (trk != null) { trk.puts(""); trk.flush(); trk = null; } if (wpt != null) { wpt.puts(""); wpt.flush(); wpt = null; } last_valid = false; tracking_changed(false); } // Mark a track point public void trackpoint() { if (!last_valid) return; if (trk == null) start_track(last_tstamp); trk.printf("\n", last_lat, last_lon); var t = Time.local(last_tstamp); char[] ts = new char[25]; t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ"); trk.printf(" \n", (string)ts); trk.printf(" %f\n", last_alt); // if course is not None: print >>self.trk, " %f" % course // if speed is not None: print >>self.trk, " %f" % speed // if fix is not None: print >>self.trk, " %f" % fix // if hdop is not None: print >>self.trk, " %f" % hdop trk.puts(""); } // Mark a waypoint public void waypoint(string? name = null) { if (!last_valid) return; if (wpt == null) start_track(last_tstamp); string wptname; if (name == null) { wptname = "wpt_%d".printf(wpt_seq); wpt_seq += 1; } else { wptname = name; } wpt.printf("\n", last_lat, last_lon); wpt.printf(" %s\n", wptname); var t = Time.local(last_tstamp); char[] ts = new char[25]; t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ"); wpt.printf(" \n", (string)ts); wpt.printf(" %f\n", last_alt); wpt.puts(""); } } // # def record(self): // # self.audio = Audio(self.make_waypoint) // # self.gps = GPS() // # # Get a fix and start recording // # if not self.gps.wait_for_fix(self.start_recording): // # self.gps_monitor = GPSMonitor(self.gps) // # self.gps_monitor.start() // # // # def monitor(self): // # self.audio = None // # self.gps = GPS() // # self.gps_monitor = GPSMonitor(self.gps) // # self.gps_monitor.start() // # // # // # def make_waypoint(self): // # if self.gpx is None: // # return // # if self.last_pos is None: // # self.last_pos = self.gps.gps_position.GetPosition() // # (fields, tstamp, lat, lon, alt) = self.last_pos // # self.gpx.waypoint(tstamp, lat, lon, alt) // # zavai.info("Making waypoint at %s: %f, %f, %f" % ( // # time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt)) public zavai.gps.GPS gps = null; public zavai.gps.Monitor monitor = null; public zavai.gps.Position position = null; public zavai.gps.GPX gpx = null; public void init() { gps = new GPS(); monitor = new Monitor(); position = new Position(); gpx = new GPX(); zavai.registry.register_service(gps); zavai.registry.register_service(position); zavai.registry.register_service(monitor); zavai.registry.register_service(gpx); } } }