]> ToastFreeware Gitweb - gregoa/zavai.git/blob - src/gps.vala
vapi bits and annotations
[gregoa/zavai.git] / src / gps.vala
1 /*
2  * gps - gps resource for zavai
3  *
4  * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace gps {
25
26 // For a list of dbus services, look in /etc/dbus-1/system.d/
27 public class GPS: zavai.Service
28 {
29     protected libgps.data_t data;
30     protected IOChannel gpsfd = null;
31     protected uint gpsfd_watch = 0;
32
33     protected int old_fix_status = libgps.STATUS_NO_FIX;
34
35     public signal void fix_status_changed(int status);
36
37     public GPS()
38     {
39         Object(name: "gps");
40         data = libgps.data_t();
41     }
42
43     public int fix_status() { return old_fix_status; }
44
45     protected bool on_input_data(IOChannel source, IOCondition condition)
46     {
47         while (libgps.waiting(ref data))
48         {
49             int res = libgps.poll(ref data);
50             if (res != 0)
51                 zavai.log.error(libgps.errstr(res));
52
53             if (data.status != old_fix_status)
54             {
55                 fix_status_changed(data.status);
56                 old_fix_status = data.status;
57             }
58             /*
59             stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status);
60             stderr.printf("SATUSED %d\n", data.satellites_used);
61             stderr.printf("SWT %f\n", data.skyview_time);
62             stderr.printf("SATVIS %d\n", data.satellites_visible);
63             for (int i = 0; i < data.satellites_visible; ++i)
64             {
65                 stderr.printf("PRN %d ELE %d AZI %d SS %f\n",
66                     data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]);
67             }
68             */
69         }
70         return true;
71     }
72
73     /// Request GPS resource
74     public override void start()
75     {
76         if (started) return;
77
78         try {
79             // Then run our own script
80             zavai.app.run_script(zavai.config.homedir + "/gps start");
81         } catch (Error e) {
82             zavai.log.error("Running " + zavai.config.homedir + "/gps start: " + e.message);
83             return;
84         }
85
86         int res = libgps.open_r("ciapino", "gpsd", ref data);
87         if (res != 0)
88         {
89             zavai.log.error(libgps.errstr(res));
90             return;
91         }
92
93         res = libgps.stream(ref data, libgps.WATCH_ENABLE, null);
94         if (res != 0)
95         {
96             zavai.log.error(libgps.errstr(res));
97             return;
98         }
99
100         res = libgps.send(ref data, "?SKY;");
101         //res = libgps.send(ref data, "?WATCH;");
102         //if (res != 0) zavai.log.error(libgps.errstr(res));
103
104         gpsfd = new IOChannel.unix_new(data.gps_fd);
105         try {
106             gpsfd.set_encoding(null);
107         } catch (Error e) {
108             zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message);
109         }
110         //gpsfd.set_buffered(false);
111         gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data);
112
113         zavai.log.info("GPS turned on");
114         base.start();
115     }
116
117     // Release usage of GPS
118     public override void stop()
119     {
120         if (!started) return;
121
122         Source.remove(gpsfd_watch);
123
124         int res = libgps.close(ref data);
125         if (res != 0)
126             zavai.log.error(libgps.errstr(res));
127
128         try {
129             zavai.app.run_script(zavai.config.homedir + "/gps stop");
130         } catch (Error e) {
131             zavai.log.error("Running device stop gps: " + e.message);
132         }
133
134         if (old_fix_status != libgps.STATUS_NO_FIX)
135         {
136             old_fix_status = libgps.STATUS_NO_FIX;
137             fix_status_changed(old_fix_status);
138         }
139
140         base.stop();
141     }
142 }
143
144 public class Position : zavai.Service
145 {
146         dynamic DBus.Object position;
147
148         public signal void position_changed(int fields, int tstamp, double lat, double lon, double alt);
149
150         public Position()
151         {
152                 Object(name: "gps.position");
153                 position = zavai.registry.sbus.get_object(
154                         "org.freesmartphone.ogpsd",
155                         "/org/freedesktop/Gypsy",
156                         "org.freedesktop.Gypsy.Position");
157         }
158
159         public void on_position_changed(dynamic DBus.Object pos, int fields, int tstamp, double lat, double lon, double alt)
160         {
161                 zavai.log.info("gps position: position changed");
162                 position_changed(fields, tstamp, lat, lon, alt);
163         }
164
165         public override void start()
166         {
167                 if (started) return;
168                 zavai.log.info("Starting GPS position tracking");
169                 gps.request("gps.position");
170                 position.PositionChanged += on_position_changed;
171                 base.start();
172         }
173
174         public override void stop()
175         {
176                 if (!started) return;
177                 zavai.log.info("Stopping GPS position tracking");
178                 position.PositionChanged -= on_position_changed;
179                 gps.release("gps.position");
180                 base.stop();
181         }
182 }
183
184 // #    def wait_for_fix(self, callback):
185 // #        status = self.gps.GetFixStatus()
186 // #        if status in [2, 3]:
187 // #            zavai.info("We already have a fix, good.")
188 // #            callback()
189 // #            return True
190 // #        else:
191 // #            zavai.info("Waiting for a fix...")
192 // #            self.waiting_for_fix = callback
193 // #            self.bus.add_signal_receiver(
194 // #                self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
195 // #                'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
196 // #            return False
197 // #
198 // #    def start_recording(self):
199 // #        if self.gps_monitor:
200 // #            self.gps_monitor.stop()
201 // #            self.gps_monitor = None
202 // #
203 // #        if not self.audio:
204 // #            return
205 // #
206 // #        # Sync system time
207 // #        gpstime = self.gps.gps_time.GetTime()
208 // #        subprocess.call(["date", "-s", "@%d" % gpstime])
209 // #        subprocess.call(["hwclock", "--systohc"])
210 // #
211 // #        # Compute basename for output files
212 // #        self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
213 // #        self.basename = os.path.join(AUDIODIR, self.basename)
214 // #
215 // #        # Start recording the GPX track
216 // #        self.gpx = GPX(self.basename)
217 // #        self.gps.track_position(self.on_position_changed)
218 // #
219 // #        # Start recording in background forking arecord
220 // #        self.audio.set_basename(self.basename)
221 // #        self.audio.start_recording()
222 // #
223
224 // Write GPX track and waypoint files
225 public class GPX : Service
226 {
227         public bool tracking {
228                 get { return trk != null; }
229                 set {}
230         }
231         public signal void tracking_changed(bool tracking);
232
233         FileStream trk = null;
234         FileStream wpt = null;
235         int wpt_seq = 1;
236         bool last_valid = false;
237         int last_fields;
238         time_t last_tstamp;
239         double last_lat;
240         double last_lon;
241         double last_alt;
242
243         public GPX()
244         {
245                 Object(name: "gps.gpx");
246         }
247
248         public override void start()
249         {       
250                 if (!started)
251                 {
252                         log.info("Starting GPX trace subsystem");
253                         position.request("gps.gpx");
254                         position.position_changed += on_position_changed;
255                         base.start();
256                 }
257         }
258
259         public override void stop()
260         {
261                 if (started)
262                 {
263                         log.info("Stopping GPX trace subsystem");
264                         position.release("gps.gpx");
265                         position.position_changed -= on_position_changed;
266                         stop_track();
267                         base.stop();
268                 }
269         }
270
271         public void on_position_changed(Position pos, int fields, int tstamp, double lat, double lon, double alt)
272         {
273                 last_fields = fields;
274                 last_tstamp = tstamp;
275                 last_lat = lat;
276                 last_lon = lon;
277                 last_alt = alt;
278                 last_valid = true;
279                 trackpoint();
280         }
281
282         public void start_track(time_t tstamp = 0, string? basename = null)
283         {
284                 string fname;
285                 if (basename != null)
286                         fname = basename;
287                 else
288                 {
289                         time_t now = tstamp == 0 ? time_t() : tstamp;
290
291                         // Compute basename for output files
292                         var t = Time.local(now);
293                         char[] res = new char[25];
294                         t.strftime(res, "%Y-%m-%d-%H-%M-%S");
295                         fname = zavai.config.homedir + "/" + (string)res;
296                 }
297  
298                 trk = FileStream.open(fname + "-trk.gpx", "wt");
299                 trk.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
300                 trk.puts(" <gpx");
301                 trk.puts("     version=\"1.0\"");
302                 trk.printf("     creator=\"zavai %s\"\n", zavai.config.version);
303                 trk.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
304                 trk.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
305                 trk.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
306                 trk.puts("   <trk>");
307                 trk.puts("     <trkseg>");
308  
309                 wpt = FileStream.open(fname + "-wpt.gpx", "wt");
310                 wpt.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
311                 wpt.puts(" <gpx");
312                 wpt.puts("     version=\"1.0\"");
313                 wpt.printf("     creator=\"zavai %s\"", zavai.config.version);
314                 wpt.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
315                 wpt.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
316                 wpt.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
317  
318                 wpt_seq = 1;
319                 tracking_changed(true);
320         }
321  
322         public void stop_track()
323         {
324                 if (trk != null)
325                 {
326                         trk.puts("</trkseg></trk></gpx>");
327                         trk.flush();
328                         trk = null;
329                 }
330                 if (wpt != null)
331                 {
332                         wpt.puts("</gpx>");
333                         wpt.flush();
334                         wpt = null;
335                 }
336                 last_valid = false;
337                 tracking_changed(false);
338         }
339
340         // Mark a track point
341         public void trackpoint()
342         {
343                 if (!last_valid) return;
344                 if (trk == null)
345                         start_track(last_tstamp);
346
347                 trk.printf("<trkpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
348                 var t = Time.local(last_tstamp);
349                 char[] ts = new char[25];
350                 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
351                 trk.printf("  <time>%s</time>\n", (string)ts);
352                 trk.printf("  <ele>%f</ele>\n", last_alt);
353                 // if course is not None: print >>self.trk, "    <course>%f</course>" % course
354                 // if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
355                 // if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
356                 // if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
357                 trk.puts("</trkpt>");
358         }
359
360         // Mark a waypoint
361         public void waypoint(string? name = null)
362         {
363                 if (!last_valid) return;
364                 if (wpt == null)
365                         start_track(last_tstamp);
366
367                 string wptname;
368                 if (name == null)
369                 {
370                         wptname = "wpt_%d".printf(wpt_seq);
371                         wpt_seq += 1;
372                 } else {
373                         wptname = name;
374                 }
375
376                 wpt.printf("<wpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
377                 wpt.printf("  <name>%s</name>\n", wptname);
378                 var t = Time.local(last_tstamp);
379                 char[] ts = new char[25];
380                 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
381                 wpt.printf("  <time>%s</time>\n", (string)ts);
382                 wpt.printf("  <ele>%f</ele>\n", last_alt);
383                 wpt.puts("</wpt>");
384         }
385 }
386
387 public zavai.gps.GPS gps = null;
388 public zavai.gps.Position position = null;
389 public zavai.gps.GPX gpx = null;
390
391 public void init()
392 {
393     gps = new GPS();
394     position = new Position();
395     gpx = new GPX();
396
397 }
398
399 }
400 }