butcher butcher butcher
[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.ScriptService
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     protected uint old_time = 0;
35     protected double old_lat = 1000;
36     protected double old_lon = 1000;
37
38     public signal void fix_status_changed(int status);
39     public signal void time_changed(uint time);
40     public signal void pos_changed();
41
42     public GPS()
43     {
44         Object(name: "gps");
45         data = libgps.data_t();
46         started = script_status();
47     }
48
49     public int fix_status() { return old_fix_status; }
50     public double time() { return old_time; }
51     public weak libgps.data_t info() { return data; }
52
53     protected bool on_input_data(IOChannel source, IOCondition condition)
54     {
55         int res = libgps.poll(ref data);
56         if (res != 0)
57             zavai.log.error(libgps.errstr(res));
58
59         if (data.status != old_fix_status)
60         {
61             fix_status_changed(data.status);
62             old_fix_status = data.status;
63         }
64
65         uint cur_time = (uint)data.fix.time;
66         if (data.status != libgps.STATUS_NO_FIX && old_time != cur_time)
67         {
68             time_changed(cur_time);
69             old_time = cur_time;
70         }
71
72         double lat = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.latitude);
73         double lon = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.longitude);
74         if (lat != old_lat || lon != old_lon)
75             pos_changed();
76
77         /*
78         stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status);
79         stderr.printf("SATUSED %d\n", data.satellites_used);
80         stderr.printf("SWT %f\n", data.skyview_time);
81         stderr.printf("SATVIS %d\n", data.satellites_visible);
82         for (int i = 0; i < data.satellites_visible; ++i)
83         {
84             stderr.printf("PRN %d ELE %d AZI %d SS %f\n",
85                 data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]);
86         }
87         */
88         return true;
89     }
90
91     /// Request GPS resource
92     public override void start()
93     {
94         if (started) return;
95
96         if (!script_start()) return;
97
98         zavai.log.info("Connecting to gpsd at " + config.gpsd_host + ":" + config.gpsd_port);
99         int res = libgps.open_r(config.gpsd_host, config.gpsd_port, ref data);
100         if (res != 0)
101         {
102             zavai.log.error(libgps.errstr(res));
103             return;
104         }
105
106         res = libgps.stream(ref data, libgps.WATCH_ENABLE, null);
107         if (res != 0)
108         {
109             zavai.log.error(libgps.errstr(res));
110             return;
111         }
112
113         //res = libgps.send(ref data, "?SKY;");
114         //res = libgps.send(ref data, "?WATCH;");
115         //if (res != 0) zavai.log.error(libgps.errstr(res));
116
117         gpsfd = new IOChannel.unix_new(data.gps_fd);
118         try {
119             gpsfd.set_encoding(null);
120         } catch (Error e) {
121             zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message);
122         }
123         //gpsfd.set_buffered(false);
124         gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data);
125
126         zavai.log.info("GPS turned on");
127         base.start();
128     }
129
130     // Release usage of GPS
131     public override void stop()
132     {
133         if (!started) return;
134
135         Source.remove(gpsfd_watch);
136
137         int res = libgps.close(ref data);
138         if (res != 0)
139             zavai.log.error(libgps.errstr(res));
140
141         script_stop();
142
143         if (old_fix_status != libgps.STATUS_NO_FIX)
144         {
145             old_fix_status = libgps.STATUS_NO_FIX;
146             fix_status_changed(old_fix_status);
147         }
148
149         if (old_time != 0)
150         {
151             old_time = 0;
152             time_changed(old_time);
153         }
154
155         base.stop();
156     }
157 }
158
159 // #    def start_recording(self):
160 // #        if self.gps_monitor:
161 // #            self.gps_monitor.stop()
162 // #            self.gps_monitor = None
163 // #
164 // #        if not self.audio:
165 // #            return
166 // #
167 // #        # Sync system time
168 // #        gpstime = self.gps.gps_time.GetTime()
169 // #        subprocess.call(["date", "-s", "@%d" % gpstime])
170 // #        subprocess.call(["hwclock", "--systohc"])
171 // #
172 // #        # Compute basename for output files
173 // #        self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime))
174 // #        self.basename = os.path.join(AUDIODIR, self.basename)
175 // #
176 // #        # Start recording the GPX track
177 // #        self.gpx = GPX(self.basename)
178 // #        self.gps.track_position(self.on_position_changed)
179 // #
180 // #        # Start recording in background forking arecord
181 // #        self.audio.set_basename(self.basename)
182 // #        self.audio.start_recording()
183 // #
184
185 // Write GPX track and waypoint files
186 public class GPX : Service
187 {
188     protected uint wpt_seq = 0;
189     protected zavai.log.Log log = null;
190
191     public GPX()
192     {
193         Object(name: "gps.gpx");
194     }
195
196     public override void start()
197     {
198         if (!started)
199         {
200             log = zavai.log.log.start("track", "GPS track");
201             base.start();
202         }
203     }
204
205     public override void stop()
206     {
207         if (started)
208         {
209             zavai.log.log.end(log);
210             log = null;
211             base.stop();
212         }
213     }
214
215     // Mark a waypoint
216     public void waypoint(string? name = null)
217     {
218         if (log == null) return;
219
220         string wptname;
221         if (name == null)
222         {
223             wptname = "wpt_%u".printf(wpt_seq);
224             wpt_seq += 1;
225         } else {
226             wptname = name;
227         }
228
229         log.add(wptname);
230     }
231 }
232
233 public zavai.gps.GPS gps = null;
234 public zavai.gps.GPX gpx = null;
235
236 public void init()
237 {
238     gps = new GPS();
239     gpx = new GPX();
240
241 }
242
243 }
244 }