/*
* 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
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;
- }
-
- 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");
- */
-
- 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 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();
-/*
- 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,
- PtrArray< HashTable<string, Value?> > data)
- //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]);
+ 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]);
+ }
*/
- /*
- 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);
- }
- 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();
- }
+ 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 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()
// 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();
+
}
}