]> ToastFreeware Gitweb - gregoa/zavai.git/blobdiff - src/gps.vala
Merge branch 'master' into gregoa
[gregoa/zavai.git] / src / gps.vala
index c7c99745467f729033cf49a9095bccc5c67714dd..64037ce3a849c56b54d56bef02c47a19ce2d002a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * gps - gps resource for zavai
  *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
  *
  * 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
@@ -24,333 +24,138 @@ namespace zavai {
 namespace gps {
 
 // For a list of dbus services, look in /etc/dbus-1/system.d/
-public class GPS: zavai.Service
+public class GPS: zavai.ScriptService
 {
-       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;
-       }
+    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)
+    {
+        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();
 
-/*
-       public void on_resourcechanged(dynamic DBus.Object pos, string name, bool state, HashTable<string, Value?> 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;
-
-    public signal void sat_info(PtrArray< HashTable<string, Value?> > data);
-
-       /*
-       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");
-         */
-
-               //ubx.DebugPacket += on_ubxdebug_packet;
-
-/*
-               // 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<<i)) != 0)
-                       {
-                               debug_busy = i;
-                               break;
-                       }
-               zavai.log.debug("UPD3 " + filters[debug_busy]);
-
-               ubx.SetDebugFilter(
-                       filters[debug_busy],
-                       true,
-                       on_debug_reply
-//                     on_debug_error
-               );
-               zavai.log.debug("UPD4");
-       }
-
-       protected void debug_request() throws GLib.Error
-       {
-               debug_have = 0;
-               debug_update();
-       }
-
-       protected void on_debug_reply() throws GLib.Error
-       {
-               debug_have |= (1<<debug_busy);
-               debug_busy = -1;
-               debug_update();
-       }
-
-       protected void on_debug_error(string e) throws GLib.Error
-       {
-               string name = debug_busy == -1 ? "none" : filters[debug_busy];
-               zavai.log.error("error while requesting debug packet " + name + ": " + e);
-               debug_error |= (1<<debug_busy);
-               debug_busy = -1;
-               debug_update();
-       }
-*/
-
-       /*
-       protected void on_satellites_changed(satellites)
-       {
-//         zavai.info("gps monitor: satellites changed")
-//         self.debug_request()
-       }
-       */
-
-    /*
-       protected void on_ubxdebug_packet(dynamic DBus.Object ubx, string clid, int length,
-                       HashTable<string, Value?>[] data)
-       {
-               zavai.log.info("gps monitor: UBX debug packet");
-               message("ZAZA %s %d", clid, length);
-               message("ZAZA %u %lu", data.length, sizeof(HashTable<string, Value?>));
-               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<string, Value?> >* prova = (PtrArray< HashTable<string, Value?> >)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)
-        //sat_info(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);
-               }
+        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]);
+        }
         */
-               //ubx.DebugPacket -= on_ubxdebug_packet;
-               //ubx.DebugPacket -= prova;
-               gps.release("gps.monitor");
-               base.stop();
-       }
+        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();
+    }
 }
 
-
-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()
@@ -380,207 +185,59 @@ public class Position : zavai.Service
 // 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-               trk.puts(" <gpx");
-               trk.puts("     version=\"1.0\"");
-               trk.printf("     creator=\"zavai %s\"\n", zavai.config.version);
-               trk.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-               trk.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
-               trk.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
-               trk.puts("   <trk>");
-               trk.puts("     <trkseg>");
-               wpt = FileStream.open(fname + "-wpt.gpx", "wt");
-               wpt.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-               wpt.puts(" <gpx");
-               wpt.puts("     version=\"1.0\"");
-               wpt.printf("     creator=\"zavai %s\"", zavai.config.version);
-               wpt.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-               wpt.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
-               wpt.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
-               wpt_seq = 1;
-               tracking_changed(true);
-       }
-       public void stop_track()
-       {
-               if (trk != null)
-               {
-                       trk.puts("</trkseg></trk></gpx>");
-                       trk.flush();
-                       trk = null;
-               }
-               if (wpt != null)
-               {
-                       wpt.puts("</gpx>");
-                       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("<trkpt lat=\"%f\" lon=\"%f\">\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("  <time>%s</time>\n", (string)ts);
-               trk.printf("  <ele>%f</ele>\n", last_alt);
-               // if course is not None: print >>self.trk, "    <course>%f</course>" % course
-               // if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
-               // if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
-               // if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
-               trk.puts("</trkpt>");
-       }
-
-       // 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("<wpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
-               wpt.printf("  <name>%s</name>\n", wptname);
-               var t = Time.local(last_tstamp);
-               char[] ts = new char[25];
-               t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
-               wpt.printf("  <time>%s</time>\n", (string)ts);
-               wpt.printf("  <ele>%f</ele>\n", last_alt);
-               wpt.puts("</wpt>");
-       }
+    protected uint wpt_seq = 0;
+    protected zavai.log.Log log = null;
+
+    public GPX()
+    {
+        Object(name: "gps.gpx");
+    }
+
+    public override void start()
+    {
+        if (!started)
+        {
+            log = zavai.log.log.start("track", "GPS track");
+            base.start();
+        }
+    }
+
+    public override void stop()
+    {
+        if (started)
+        {
+            zavai.log.log.end(log);
+            log = null;
+            base.stop();
+        }
+    }
+
+    // Mark a waypoint
+    public void waypoint(string? name = null)
+    {
+        if (log == null) return;
+
+        string wptname;
+        if (name == null)
+        {
+            wptname = "wpt_%u".printf(wpt_seq);
+            wpt_seq += 1;
+        } else {
+            wptname = name;
+        }
+
+        log.add(wptname);
+    }
 }
 
-// #    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);
+    gps = new GPS();
+    gpx = new GPX();
+
 }
 
 }