Do not create the satellite monitor app anymore
[gregoa/zavai.git] / src / gps.vala
1 /*
2  * gps - gps resource for zavai
3  *
4  * Copyright (C) 2009  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         public dynamic DBus.Object usage;
30         public dynamic DBus.Object device;
31
32         public GPS()
33         {
34                 name = "gps";
35
36                 // see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage
37                 usage = zavai.registry.sbus.get_object(
38                         "org.freesmartphone.ousaged",
39                         "/org/freesmartphone/Usage",
40                         "org.freesmartphone.Usage");
41
42                 device = zavai.registry.sbus.get_object(
43                         "org.freesmartphone.ogpsd", 
44                         "/org/freedesktop/Gypsy",
45                         "org.freedesktop.Gypsy.Device");
46         }
47
48         /// Request GPS resource
49         public override void start()
50         {
51                 if (started) return;
52                 try {
53                         usage.RequestResource("GPS");
54                         zavai.log.info("Acquired GPS");
55                         base.start();
56                 } catch (GLib.Error e) {
57                         zavai.log.error(e.message);
58                 }
59                 base.start();
60         }
61
62         // Release usage of GPS
63         public override void stop()
64         {
65                 if (!started) return;
66                 try {
67                         usage.ReleaseResource("GPS");
68                         zavai.log.info("Released GPS");
69                         base.stop();
70                 } catch (GLib.Error e) {
71                         zavai.log.error(e.message);
72                 }
73                 base.stop();
74         }
75 }
76
77 public class Position : zavai.Service
78 {
79         dynamic DBus.Object position;
80
81         public signal void position_changed(int fields, int tstamp, double lat, double lon, double alt);
82
83         public Position()
84         {
85                 name = "gps.position";
86                 position = zavai.registry.sbus.get_object(
87                         "org.freesmartphone.ogpsd",
88                         "/org/freedesktop/Gypsy",
89                         "org.freedesktop.Gypsy.Position");
90         }
91
92         public void on_position_changed(dynamic DBus.Object pos, int fields, int tstamp, double lat, double lon, double alt)
93         {
94                 zavai.log.info("gps position: position changed");
95                 position_changed(fields, tstamp, lat, lon, alt);
96         }
97
98         public override void start()
99         {
100                 if (started) return;
101                 zavai.log.info("Starting GPS position tracking");
102                 gps.request("gps.position");
103                 position.PositionChanged += on_position_changed;
104                 base.start();
105         }
106
107         public override void stop()
108         {
109                 if (!started) return;
110                 zavai.log.info("Stopping GPS position tracking");
111                 position.PositionChanged -= on_position_changed;
112                 gps.release("gps.position");
113                 base.stop();
114         }
115 }
116
117 // #    def wait_for_fix(self, callback):
118 // #        status = self.gps.GetFixStatus()
119 // #        if status in [2, 3]:
120 // #            zavai.info("We already have a fix, good.")
121 // #            callback()
122 // #            return True
123 // #        else:
124 // #            zavai.info("Waiting for a fix...")
125 // #            self.waiting_for_fix = callback
126 // #            self.bus.add_signal_receiver(
127 // #                self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
128 // #                'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
129 // #            return False
130 // #
131 // #    def start_recording(self):
132 // #        if self.gps_monitor:
133 // #            self.gps_monitor.stop()
134 // #            self.gps_monitor = None
135 // #
136 // #        if not self.audio:
137 // #            return
138 // #
139 // #        # Sync system time
140 // #        gpstime = self.gps.gps_time.GetTime()
141 // #        subprocess.call(["date", "-s", "@%d" % gpstime])
142 // #        subprocess.call(["hwclock", "--systohc"])
143 // #
144 // #        # Compute basename for output files
145 // #        self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
146 // #        self.basename = os.path.join(AUDIODIR, self.basename)
147 // #
148 // #        # Start recording the GPX track
149 // #        self.gpx = GPX(self.basename)
150 // #        self.gps.track_position(self.on_position_changed)
151 // #
152 // #        # Start recording in background forking arecord
153 // #        self.audio.set_basename(self.basename)
154 // #        self.audio.start_recording()
155 // #
156
157 // Write GPX track and waypoint files
158 public class GPX : Service
159 {
160         public bool tracking {
161                 get { return trk != null; }
162                 set {}
163         }
164         public signal void tracking_changed(bool tracking);
165
166         FileStream trk = null;
167         FileStream wpt = null;
168         int wpt_seq = 1;
169         bool last_valid = false;
170         int last_fields;
171         time_t last_tstamp;
172         double last_lat;
173         double last_lon;
174         double last_alt;
175
176         public GPX()
177         {
178                 name = "gps.gpx";
179         }
180
181         public override void start()
182         {       
183                 if (!started)
184                 {
185                         log.info("Starting GPX trace subsystem");
186                         position.request("gps.gpx");
187                         position.position_changed += on_position_changed;
188                         base.start();
189                 }
190         }
191
192         public override void stop()
193         {
194                 if (started)
195                 {
196                         log.info("Stopping GPX trace subsystem");
197                         position.release("gps.gpx");
198                         position.position_changed -= on_position_changed;
199                         stop_track();
200                         base.stop();
201                 }
202         }
203
204         public void on_position_changed(Position pos, int fields, int tstamp, double lat, double lon, double alt)
205         {
206                 last_fields = fields;
207                 last_tstamp = tstamp;
208                 last_lat = lat;
209                 last_lon = lon;
210                 last_alt = alt;
211                 last_valid = true;
212                 trackpoint();
213         }
214
215         public void start_track(time_t tstamp = 0, string? basename = null)
216         {
217                 string fname;
218                 if (basename != null)
219                         fname = basename;
220                 else
221                 {
222                         time_t now = tstamp == 0 ? time_t() : tstamp;
223
224                         // Compute basename for output files
225                         var t = Time.local(now);
226                         char[] res = new char[25];
227                         t.strftime(res, "%Y-%m-%d-%H-%M-%S");
228                         fname = zavai.config.homedir + "/" + (string)res;
229                 }
230  
231                 trk = FileStream.open(fname + "-trk.gpx", "wt");
232                 trk.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
233                 trk.puts(" <gpx");
234                 trk.puts("     version=\"1.0\"");
235                 trk.printf("     creator=\"zavai %s\"\n", zavai.config.version);
236                 trk.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
237                 trk.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
238                 trk.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
239                 trk.puts("   <trk>");
240                 trk.puts("     <trkseg>");
241  
242                 wpt = FileStream.open(fname + "-wpt.gpx", "wt");
243                 wpt.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
244                 wpt.puts(" <gpx");
245                 wpt.puts("     version=\"1.0\"");
246                 wpt.printf("     creator=\"zavai %s\"", zavai.config.version);
247                 wpt.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
248                 wpt.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"");
249                 wpt.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
250  
251                 wpt_seq = 1;
252                 tracking_changed(true);
253         }
254  
255         public void stop_track()
256         {
257                 if (trk != null)
258                 {
259                         trk.puts("</trkseg></trk></gpx>");
260                         trk.flush();
261                         trk = null;
262                 }
263                 if (wpt != null)
264                 {
265                         wpt.puts("</gpx>");
266                         wpt.flush();
267                         wpt = null;
268                 }
269                 last_valid = false;
270                 tracking_changed(false);
271         }
272
273         // Mark a track point
274         public void trackpoint()
275         {
276                 if (!last_valid) return;
277                 if (trk == null)
278                         start_track(last_tstamp);
279
280                 trk.printf("<trkpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
281                 var t = Time.local(last_tstamp);
282                 char[] ts = new char[25];
283                 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
284                 trk.printf("  <time>%s</time>\n", (string)ts);
285                 trk.printf("  <ele>%f</ele>\n", last_alt);
286                 // if course is not None: print >>self.trk, "    <course>%f</course>" % course
287                 // if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
288                 // if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
289                 // if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
290                 trk.puts("</trkpt>");
291         }
292
293         // Mark a waypoint
294         public void waypoint(string? name = null)
295         {
296                 if (!last_valid) return;
297                 if (wpt == null)
298                         start_track(last_tstamp);
299
300                 string wptname;
301                 if (name == null)
302                 {
303                         wptname = "wpt_%d".printf(wpt_seq);
304                         wpt_seq += 1;
305                 } else {
306                         wptname = name;
307                 }
308
309                 wpt.printf("<wpt lat=\"%f\" lon=\"%f\">\n", last_lat, last_lon);
310                 wpt.printf("  <name>%s</name>\n", wptname);
311                 var t = Time.local(last_tstamp);
312                 char[] ts = new char[25];
313                 t.strftime(ts, "%Y-%m-%dT%H:%M:%SZ");
314                 wpt.printf("  <time>%s</time>\n", (string)ts);
315                 wpt.printf("  <ele>%f</ele>\n", last_alt);
316                 wpt.puts("</wpt>");
317         }
318 }
319
320 public zavai.gps.GPS gps = null;
321 public zavai.gps.Position position = null;
322 public zavai.gps.GPX gpx = null;
323
324 public void init()
325 {
326         gps = new GPS();
327         position = new Position();
328         gpx = new GPX();
329
330         zavai.registry.register_service(gps);
331         zavai.registry.register_service(position);
332         zavai.registry.register_service(gpx);
333 }
334
335 }
336 }