4c3b2bdf550083e23f7044e5fe3e958c57a297eb
[gregoa/zavai.git] / vala / 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
25 /*
26 public class Prova : zavai.Service
27 {
28         dynamic DBus.Object purple;
29
30         public Prova(zavai.Registry r)
31         {
32                 purple = r.sess_bus.get_object ("im.pidgin.purple.PurpleService",
33                                 "/im/pidgin/purple/PurpleObject",
34                                 "im.pidgin.purple.PurpleInterface");
35
36         }
37
38         public void msg_received (dynamic DBus.Object purple, int dummy1, string sender,
39                                string message_, int dummy2, uint dummy3)
40         {
41                 // dbus signal handler
42
43                 zavai.log.info("RECEIVED " + sender + " " + message_);
44         }
45
46         public override void start()
47         {
48                 zavai.log.info("Starting Purple test");
49                 purple.ReceivedImMsg += msg_received;
50                 base.start();
51         }
52
53         public override void stop()
54         {
55                 zavai.log.info("Stopping Purple test");
56                 purple.ReceivedImMsg -= msg_received;
57                 base.stop();
58         }
59 }
60 */
61
62 public class GPSMonitor : zavai.Service
63 {
64         static const int NAV_STATUS=0;
65         static const int NAV_SVINFO=1;
66         static const int NAV_MAX=2;
67
68         zavai.Registry* reg;
69         zavai.GPS* gps;
70         dynamic DBus.Object ubx;
71         dynamic DBus.Object time;
72         /*
73         string[] filters = { "NAV-STATUS", "NAV_SVINFO" };
74
75         int debug_busy;
76         int debug_want;
77         int debug_have;
78         int debug_error;
79         */
80
81
82         public GPSMonitor(zavai.Registry r)
83         {
84                 reg = r;
85                 gps = (zavai.GPS)r.gets("gps");
86                 ubx = r.sbus.get_object(
87                         "org.freesmartphone.ogpsd",
88                         "/org/freedesktop/Gypsy",
89                         "org.freesmartphone.GPS.UBX");
90                 time = r.sbus.get_object(
91                         "org.freesmartphone.ogpsd",
92                         "/org/freedesktop/Gypsy",
93                         "org.freedesktop.Gypsy.Time");
94
95                 zavai.log.info("SETSIG1");
96                 time.TimeChanged += timechanged;
97                 zavai.log.info("SETSIG2");
98
99                 zavai.log.info("DEBUG1");
100                 ubx.DebugPacket += on_ubxdebug_packet;
101                 zavai.log.info("DEBUG2");
102
103 /*
104                 // This piece of machinery is taken from Zhone
105                 debug_busy = -1;
106                 debug_want = (1 << NAV_STATUS) | (1 << NAV_SVINFO);
107                 debug_have = 0;
108                 debug_error = 0;
109 */
110         }
111
112         protected void timechanged(dynamic DBus.Object pos, int t)
113         {
114                 zavai.log.info("TIMECHANGED");
115         }
116
117 /*
118         protected void debug_update() throws GLib.Error
119         {
120                 zavai.log.debug("UPDATE");
121                 if (debug_busy != -1)
122                         return;
123                 zavai.log.debug("UPD1");
124                 int pending = debug_want & (~debug_have) & (~debug_error);
125                 if (pending == 0)
126                         return;
127                 zavai.log.debug("UPD2");
128                 for (int i = 0; i < NAV_MAX; ++i)
129                         if ((pending & (1<<i)) != 0)
130                         {
131                                 debug_busy = i;
132                                 break;
133                         }
134                 zavai.log.debug("UPD3 " + filters[debug_busy]);
135
136                 ubx.SetDebugFilter(
137                         filters[debug_busy],
138                         true,
139                         on_debug_reply
140 //                      on_debug_error
141                 );
142                 zavai.log.debug("UPD4");
143         }
144
145         protected void debug_request() throws GLib.Error
146         {
147                 debug_have = 0;
148                 debug_update();
149         }
150
151         protected void on_debug_reply() throws GLib.Error
152         {
153                 debug_have |= (1<<debug_busy);
154                 debug_busy = -1;
155                 debug_update();
156         }
157
158         protected void on_debug_error(string e) throws GLib.Error
159         {
160                 string name = debug_busy == -1 ? "none" : filters[debug_busy];
161                 zavai.log.error("error while requesting debug packet " + name + ": " + e);
162                 debug_error |= (1<<debug_busy);
163                 debug_busy = -1;
164                 debug_update();
165         }
166 */
167
168         /*
169         protected void on_satellites_changed(satellites)
170         {
171 //         zavai.info("gps monitor: satellites changed")
172 //         self.debug_request()
173         }
174         */
175
176         protected void on_ubxdebug_packet(dynamic DBus.Object ubx, string clid, int length, int foo, int bar)
177         {
178                 zavai.log.info("gps monitor: UBX debug packet");
179 //         self.notify("satellites", clid, length, data)
180         }
181
182         protected override void start()
183         {
184                 zavai.log.info("Starting GPS Monitor");
185                 gps->request("GPSMonitor");
186 //         # TODO: find out how come sometimes these events are not sent
187 //         self.gps.bus.add_signal_receiver(
188 //             self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
189 //             'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
190                 //ubx.DebugPacket += prova;
191                 try {
192                         //ubx.SetDebugFilter("NAV-STATUS", true);
193                         //ubx.SetDebugFilter("NAV-SVINFO", true);
194                         //debug_request();
195                         base.start();
196                 } catch (GLib.Error e) {
197                         zavai.log.error(e.message);
198                 }
199         }
200
201         protected override void stop()
202         {
203                 zavai.log.info("Stopping GPS Monitor");
204 //         self.gps.bus.remove_signal_receiver(
205 //             self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite',
206 //             'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
207                 try {
208                         ubx.SetDebugFilter("NAV-STATUS", false);
209                         ubx.SetDebugFilter("NAV-SVINFO", false);
210                 } catch (GLib.Error e) {
211                         zavai.log.error(e.message);
212                 }
213                 ubx.DebugPacket -= on_ubxdebug_packet;
214                 //ubx.DebugPacket -= prova;
215                 gps->release("GPSMonitor");
216                 base.stop();
217         }
218 }
219
220
221 public class GPSPosition : zavai.Service
222 {
223         zavai.GPS* gps;
224         dynamic DBus.Object position;
225
226         public GPSPosition(zavai.Registry r)
227         {
228                 gps = (zavai.GPS)r.gets("gps");
229                 position = r.sbus.get_object(
230                         "org.freesmartphone.ogpsd",
231                         "/org/freedesktop/Gypsy",
232                         "org.freedesktop.Gypsy.Position");
233         }
234
235         public void on_position_changed(dynamic DBus.Object pos, int fields, int tstamp, double lat, double lon, double alt)
236         {
237                 zavai.log.info("gps position: position changed");
238 //         self.notify("position", fields, tstamp, lat, lon, alt)
239         }
240
241         public override void start()
242         {
243                 zavai.log.info("Starting GPS position tracking");
244                 gps->request("GPSPosition");
245                 position.PositionChanged += on_position_changed;
246                 base.start();
247         }
248
249         public override void stop()
250         {
251                 zavai.log.info("Stopping GPS position tracking");
252                 position.PositionChanged -= on_position_changed;
253                 gps->release("GPSPosition");
254                 base.stop();
255         }
256 }
257
258 // For a list of dbus services, look in /etc/dbus-1/system.d/
259 public class GPS: zavai.Service
260 {
261         dynamic DBus.Object usage;
262
263         public GPS(zavai.Registry r)
264         {
265                 // see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage
266                 usage = r.sbus.get_object(
267                         "org.freesmartphone.ousaged",
268                         "/org/freesmartphone/Usage",
269                         "org.freesmartphone.Usage");
270
271 //         # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy
272 //         gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') 
273 //         self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device")
274 //         self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time")
275 //         self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position')
276 //         self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX')
277 // 
278 //         self.monitor = GPSMonitor(self)
279 //         self.position = GPSPosition(self)
280                 //usage.ResourceChanged += on_resourcechanged;
281         }
282
283         public void on_resourcechanged(dynamic DBus.Object pos, string name, bool state, Value attributes)
284         {
285                 zavai.log.info("RESOURCE CHANGED " + name);
286         }
287
288         /// Request GPS resource
289         public override void start()
290         {
291                 try {
292                         usage.RequestResource("GPS");
293                         zavai.log.info("Acquired GPS");
294                         base.start();
295                 } catch (GLib.Error e) {
296                         zavai.log.error(e.message);
297                 }
298         }
299
300         // Release usage of GPS
301         public override void stop()
302         {
303                 try {
304                         usage.ReleaseResource("GPS");
305                         zavai.log.info("Released GPS");
306                         base.stop();
307                 } catch (GLib.Error e) {
308                         zavai.log.error(e.message);
309                 }
310         }
311
312 // #    def wait_for_fix(self, callback):
313 // #        status = self.gps.GetFixStatus()
314 // #        if status in [2, 3]:
315 // #            zavai.info("We already have a fix, good.")
316 // #            callback()
317 // #            return True
318 // #        else:
319 // #            zavai.info("Waiting for a fix...")
320 // #            self.waiting_for_fix = callback
321 // #            self.bus.add_signal_receiver(
322 // #                self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
323 // #                'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
324 // #            return False
325 // #
326 // #    def on_fix_status_changed(self, status):
327 // #        if status not in [2, 3]: return
328 // #
329 // #        zavai.info("Got GPS fix")
330 // #        self.bus.remove_signal_receiver(
331 // #            self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device',
332 // #            'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy')
333 // #
334 // #        if self.waiting_for_fix:
335 // #            self.waiting_for_fix()
336 // #            self.waiting_for_fix = None
337 // #
338 // 
339 // #    def start_recording(self):
340 // #        if self.gps_monitor:
341 // #            self.gps_monitor.stop()
342 // #            self.gps_monitor = None
343 // #
344 // #        if not self.audio:
345 // #            return
346 // #
347 // #        # Sync system time
348 // #        gpstime = self.gps.gps_time.GetTime()
349 // #        subprocess.call(["date", "-s", "@%d" % gpstime])
350 // #        subprocess.call(["hwclock", "--systohc"])
351 // #
352 // #        # Compute basename for output files
353 // #        self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
354 // #        self.basename = os.path.join(AUDIODIR, self.basename)
355 // #
356 // #        # Start recording the GPX track
357 // #        self.gpx = GPX(self.basename)
358 // #        self.gps.track_position(self.on_position_changed)
359 // #
360 // #        # Start recording in background forking arecord
361 // #        self.audio.set_basename(self.basename)
362 // #        self.audio.start_recording()
363 // #
364 // 
365 // class GPX(zavai.Service):
366 //     "Write GPX track and waypoint files"
367 //     def __init__(self, registry, name):
368 //         super(GPX, self).__init__(["gpx"])
369 //         self.registry = registry
370 //         self.trk = None
371 //         self.wpt = None
372 //         self.last_pos = None
373 //         conf = registry.resource("conf")
374 //         self.trackdir = conf.homedir
375 //         self.activity_monitors = set()
376 // 
377 //     def add_activity_monitor(self, cb):
378 //         self.activity_monitors.add(cb)
379 //         cb(self, self.last_pos is not None)
380 // 
381 //     def del_activity_monitor(self, cb):
382 //         self.activity_monitors.discard(cb)
383 // 
384 //     def notify_activity_monitors(self):
385 //         for mon in self.activity_monitors:
386 //             mon(self, self.last_pos is not None)
387 // 
388 //     def start(self):
389 //         zavai.info("Starting GPX trace subsystem")
390 //         gps = self.registry.resource("gps")
391 //         gps.position.connect("position", self.on_position_changed)
392 // 
393 //     def stop(self):
394 //         zavai.info("Stopping GPX trace subsystem")
395 //         gps = self.registry.resource("gps")
396 //         gps.position.disconnect("position", self.on_position_changed)
397 //         self.stop_track()
398 // 
399 //     def on_position_changed(self, fields, tstamp, lat, lon, alt):
400 //         self.last_pos = (fields, tstamp, lat, lon, alt)
401 //         self.trackpoint()
402 // 
403 //     def start_track(self, tstamp = None, basename = None):
404 //         if basename is not None:
405 //             self.basename = basename
406 //         elif tstamp is not None:
407 //             # Compute basename for output files
408 //             self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(tstamp))
409 //             self.basename = os.path.join(self.trackdir, self.basename)
410 // 
411 //         self.trk = open(self.basename + "-trk.gpx", "wt")
412 //         print >>self.trk, """<?xml version="1.0" encoding="UTF-8"?>
413 // <gpx
414 //     version="1.0"
415 //     creator="audiomap %s"
416 //     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
417 //     xmlns="http://www.topografix.com/GPX/1/0"
418 //     xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
419 //   <trk>
420 //     <trkseg>""" % zavai.VERSION
421 // 
422 //         self.wpt = open(self.basename + "-wpt.gpx", "wt")
423 //         print >>self.wpt, """<?xml version="1.0" encoding="UTF-8"?>
424 // <gpx
425 //     version="1.0"
426 //     creator="audiomap %s"
427 //     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
428 //     xmlns="http://www.topografix.com/GPX/1/0"
429 //     xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">""" % zavai.VERSION
430 // 
431 //         self.wpt_seq = 1;
432 //         self.notify_activity_monitors()
433 // 
434 //     def stop_track(self):
435 //         if self.trk is not None:
436 //             print >>self.trk, "</trkseg></trk></gpx>"
437 //             self.trk.close()
438 //             self.trk = None
439 //         if self.wpt is not None:
440 //             print >>self.wpt, "</gpx>"
441 //             self.wpt.close()
442 //             self.wpt = None
443 //         self.last_pos = None
444 //         self.notify_activity_monitors()
445 // 
446 //     def trackpoint(self):
447 //         "Mark a track point"
448 //         if self.last_pos is None:
449 //             return
450 // 
451 //         fields, tstamp, lat, lon, ele = self.last_pos
452 // 
453 //         if not self.trk:
454 //             self.start_track(tstamp)
455 // 
456 //         print >>self.trk, """<trkpt lat="%f" lon="%f">
457 //   <time>%s</time>
458 //   <ele>%f</ele>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
459 //         #if course is not None: print >>self.trk, "    <course>%f</course>" % course
460 //         #if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
461 //         #if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
462 //         #if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
463 //         print >>self.trk, "</trkpt>"
464 // 
465 //     def waypoint(self, name = None):
466 //         "Mark a waypoint"
467 //         if self.last_pos is None:
468 //             return
469 // 
470 //         fields, tstamp, lat, lon, ele = self.last_pos
471 // 
472 //         if not self.wpt:
473 //             self.start_track(tstamp)
474 // 
475 //         if name is None:
476 //             name = "wpt_%d" % self.wpt_seq
477 //             self.wpt_seq += 1
478 // 
479 //         print >>self.wpt, """<wpt lat="%f" lon="%f">
480 //     <name>%s</name>
481 //     <time>%s</time>
482 //     <ele>%f</ele>
483 // </wpt>""" % (
484 //             lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
485 // 
486 // 
487 // #    def record(self):
488 // #        self.audio = Audio(self.make_waypoint)
489 // #        self.gps = GPS()
490 // #        # Get a fix and start recording
491 // #        if not self.gps.wait_for_fix(self.start_recording):
492 // #            self.gps_monitor = GPSMonitor(self.gps)
493 // #            self.gps_monitor.start()
494 // #
495 // #    def monitor(self):
496 // #        self.audio = None
497 // #        self.gps = GPS()
498 // #        self.gps_monitor = GPSMonitor(self.gps)
499 // #        self.gps_monitor.start()
500 // #
501 // #
502 // #    def make_waypoint(self):
503 // #        if self.gpx is None:
504 // #            return
505 // #        if self.last_pos is None:
506 // #            self.last_pos = self.gps.gps_position.GetPosition()
507 // #        (fields, tstamp, lat, lon, alt) = self.last_pos
508 // #        self.gpx.waypoint(tstamp, lat, lon, alt)
509 // #        zavai.info("Making waypoint at %s: %f, %f, %f" % (
510 // #            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt))
511
512 }
513
514 }