/[zanavi_public1]/navit/navit/vehicle/gypsy/vehicle_gypsy.c
ZANavi

Contents of /navit/navit/vehicle/gypsy/vehicle_gypsy.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 12172 byte(s)
import files
1 /** @file vehicle_gypsy.c
2 * @brief gypsy uses dbus signals
3 *
4 * Navit, a modular navigation system.
5 * Copyright (C) 2005-2008 Navit Team
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
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
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * @Author Tim Niemeyer <reddog@mastersword.de>
22 * @date 2008-2009
23 */
24
25 #include <config.h>
26 #include <gypsy/gypsy-device.h>
27 #include <gypsy/gypsy-control.h>
28 #include <gypsy/gypsy-course.h>
29 #include <gypsy/gypsy-position.h>
30 #include <gypsy/gypsy-satellite.h>
31 #ifdef USE_BINDING_DBUS
32 #include <dbus/dbus.h>
33 #include <dbus/dbus-glib.h>
34 #include <dbus/dbus-glib-lowlevel.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <sys/types.h>
38 #include <unistd.h>
39 #endif
40 #include <string.h>
41 #include <glib.h>
42 #include <math.h>
43 #include "debug.h"
44 #include "callback.h"
45 #include "plugin.h"
46 #include "coord.h"
47 #include "item.h"
48 #include "vehicle.h"
49
50 static struct vehicle_priv {
51 char *source;
52 GypsyControl *control;
53 GypsyPosition *position;
54 GypsyDevice *device;
55 GypsyCourse *course;
56 GypsySatellite *satellite;
57 char *path;
58 struct callback_list *cbl;
59 guint retry_interval;
60 struct coord_geo geo;
61 double speed;
62 double direction;
63 double height;
64 int fix_type;
65 time_t fix_time;
66 char fixiso8601[128];
67 int sats;
68 int sats_used;
69 guint retry_timer;
70 struct attr ** attrs;
71 int have_cords;
72 } *vehicle_last;
73
74 #define DEFAULT_RETRY_INTERVAL 10 // seconds
75 #define MIN_RETRY_INTERVAL 1 // seconds
76
77 /**
78 * @brief When the fixstatus has changed, this function get called
79 *
80 * fixstatus can be one of this:
81 * GYPSY_DEVICE_FIX_STATUS_INVALID = 0
82 * GYPSY_DEVICE_FIX_STATUS_NONE = 1
83 * GYPSY_DEVICE_FIX_STATUS_2D = 2
84 * GYPSY_DEVICE_FIX_STATUS_3D = 3
85 *
86 * Anytime this functions get called, we have to call the global
87 * callback.
88 *
89 * @param device The GypsyDevice
90 * @param fixstatus The fisstatus 0, 1, 2 or 3
91 * @param userdata
92 * @returns nothing
93 */
94 static void
95 vehicle_gypsy_fixstatus_changed(GypsyDevice *device,
96 gint fixstatus,
97 gpointer userdata)
98 {
99 struct vehicle_priv *priv = vehicle_last;
100
101 if (fixstatus==GYPSY_DEVICE_FIX_STATUS_3D)
102 priv->fix_type = 3;
103 else if (fixstatus==GYPSY_DEVICE_FIX_STATUS_2D)
104 priv->fix_type = 1;
105 else
106 priv->fix_type = 0;
107
108 callback_list_call_attr_0(priv->cbl, attr_position_coord_geo);
109 }
110
111 /**
112 * @brief When the position has changed, this function get called
113 *
114 * The fields_set can hold:
115 * GYPSY_POSITION_FIELDS_NONE = 1 << 0,
116 * GYPSY_POSITION_FIELDS_LATITUDE = 1 << 1,
117 * GYPSY_POSITION_FIELDS_LONGITUDE = 1 << 2,
118 * GYPSY_POSITION_FIELDS_ALTITUDE = 1 << 3
119 *
120 * If we get any new information, we have to call the global
121 * callback.
122 *
123 * @param position The GypsyPosition
124 * @param fields_set Bitmask indicating what field was set
125 * @param timestamp the time since Unix Epoch
126 * @param latitude
127 * @param longitude
128 * @param altitude
129 * @param userdata
130 * @returns nothing
131 */
132 static void
133 vehicle_gypsy_position_changed(GypsyPosition *position,
134 GypsyPositionFields fields_set, int timestamp,
135 double latitude, double longitude, double altitude,
136 gpointer userdata)
137 {
138 struct vehicle_priv *priv = vehicle_last;
139 int cb = FALSE;
140
141 if (timestamp > 0)
142 priv->fix_time = timestamp;
143
144 if (fields_set & GYPSY_POSITION_FIELDS_LATITUDE)
145 {
146 cb = TRUE;
147 priv->geo.lat = latitude;
148 }
149 if (fields_set & GYPSY_POSITION_FIELDS_LONGITUDE)
150 {
151 cb = TRUE;
152 priv->geo.lng = longitude;
153 }
154 if (fields_set & GYPSY_POSITION_FIELDS_ALTITUDE)
155 {
156 cb = TRUE;
157 priv->height = altitude;
158 }
159
160 if (cb)
161 {
162 priv->have_cords = 1;
163 callback_list_call_attr_0(priv->cbl, attr_position_coord_geo);
164 }
165 }
166
167 /**
168 * @brief Everytime any Sat-Details are changed, this function get called
169 *
170 * Going through all Sats, counting those wich are in use.
171 *
172 * Anytime this functions get called, we have to call the global
173 * callback.
174 *
175 * @param satellite The GypsySatellite
176 * @param satellites An GPtrArray wich hold information of all sats
177 * @param userdata
178 * @returns nothing
179 */
180 static void
181 vehicle_gypsy_satellite_changed(GypsySatellite *satellite,
182 GPtrArray *satellites,
183 gpointer userdata)
184 {
185 struct vehicle_priv *priv = vehicle_last;
186
187 int i, sats, used=0;
188
189 sats = satellites->len;
190 for (i = 0; i < sats; i++) {
191 GypsySatelliteDetails *details = satellites->pdata[i];
192 if (details->in_use)
193 used++;
194 }
195
196 priv->sats_used = used;
197 priv->sats = sats;
198
199 callback_list_call_attr_0(priv->cbl, attr_position_coord_geo);
200 }
201
202 /**
203 * @brief When the course or speed has changed, this function get called
204 *
205 * Only speed and direction are used!
206 *
207 * If we get any new information, we have to call the global
208 * callback.
209 *
210 * @param course The GypsyCourse
211 * @param fields Bitmask indicating what field was set
212 * @param timestamp the time since Unix Epoch
213 * @param speed
214 * @param direction
215 * @param climb
216 * @param userdata
217 * @returns nothing
218 */
219 static void
220 vehicle_gypsy_course_changed (GypsyCourse *course,
221 GypsyCourseFields fields,
222 int timestamp,
223 double speed,
224 double direction,
225 double climb,
226 gpointer userdata)
227 {
228 struct vehicle_priv *priv = vehicle_last;
229 int cb = FALSE;
230
231 if (fields & GYPSY_COURSE_FIELDS_SPEED)
232 {
233 priv->speed = speed;
234 cb = TRUE;
235 }
236 if (fields & GYPSY_COURSE_FIELDS_DIRECTION)
237 {
238 priv->direction = direction;
239 cb = TRUE;
240 }
241
242 if (cb)
243 callback_list_call_attr_0(priv->cbl, attr_position_coord_geo);
244 }
245
246 /**
247 * @brief Attempt to open the gypsy device.
248 *
249 * Tells gypsy wich functions to call when anything occours.
250 *
251 * @param data
252 * @returns TRUE to try again; FALSE if retry not required
253 */
254 static gboolean
255 vehicle_gypsy_try_open(gpointer *data)
256 {
257 struct vehicle_priv *priv = (struct vehicle_priv *)data;
258 char *source = g_strdup(priv->source);
259
260 GError *error = NULL;
261
262 g_type_init();
263 priv->control = gypsy_control_get_default();
264 priv->path = gypsy_control_create(priv->control, source+8, &error);
265 if (priv->path == NULL) {
266 g_warning ("Error creating gypsy conrtol path for %s: %s", source+8, error->message);
267 return TRUE;
268 }
269
270 priv->position = gypsy_position_new(priv->path);
271 g_signal_connect(priv->position, "position-changed", G_CALLBACK (vehicle_gypsy_position_changed), NULL);
272
273 priv->satellite = gypsy_satellite_new(priv->path);
274 g_signal_connect(priv->satellite, "satellites-changed", G_CALLBACK (vehicle_gypsy_satellite_changed), NULL);
275
276 priv->course = gypsy_course_new(priv->path);
277 g_signal_connect(priv->course, "course-changed", G_CALLBACK (vehicle_gypsy_course_changed), NULL);
278
279 priv->device = gypsy_device_new(priv->path);
280 g_signal_connect(priv->device, "fix-status-changed", G_CALLBACK (vehicle_gypsy_fixstatus_changed), NULL);
281
282 gypsy_device_start(priv->device, &error);
283 if (error != NULL) {
284 g_warning ("Error starting gypsy for %s: %s", source+8, error->message);
285 return TRUE;
286 }
287
288 vehicle_last = priv;
289 dbg(0,"gypsy connected to %d\n", source+8);
290 g_free(source);
291 return FALSE;
292 }
293
294 /**
295 * @brief Open a connection to gypsy. Will re-try the connection if it fails
296 *
297 * @param priv
298 * @returns nothing
299 */
300 static void
301 vehicle_gypsy_open(struct vehicle_priv *priv)
302 {
303 priv->retry_timer=0;
304 if (vehicle_gypsy_try_open((gpointer *)priv)) {
305 priv->retry_timer = g_timeout_add(priv->retry_interval*1000, (GSourceFunc)vehicle_gypsy_try_open, (gpointer *)priv);
306 }
307 }
308
309 /**
310 * @brief Stop retry timer; Free alloced memory
311 *
312 * @param priv
313 * @returns nothing
314 */
315 static void
316 vehicle_gypsy_close(struct vehicle_priv *priv)
317 {
318 if (priv->retry_timer) {
319 g_source_remove(priv->retry_timer);
320 priv->retry_timer=0;
321 }
322 if (priv->path)
323 g_free(priv->path);
324
325 if (priv->position)
326 g_free(priv->position);
327
328 if (priv->satellite)
329 g_free(priv->satellite);
330
331 if (priv->course)
332 g_free(priv->course);
333
334 if (priv->device)
335 g_free(priv->device);
336
337 if (priv->control)
338 g_object_unref(G_OBJECT (priv->control));
339 }
340
341 /**
342 * @brief Free the gypsy_vehicle
343 *
344 * @param priv
345 * @returns nothing
346 */
347 static void
348 vehicle_gypsy_destroy(struct vehicle_priv *priv)
349 {
350 vehicle_gypsy_close(priv);
351 if (priv->source)
352 g_free(priv->source);
353 g_free(priv);
354 }
355
356 /**
357 * @brief Provide the outside with information
358 *
359 * @param priv
360 * @param type TODO: What can this be?
361 * @param attr
362 * @returns true/false
363 */
364 static int
365 vehicle_gypsy_position_attr_get(struct vehicle_priv *priv,
366 enum attr_type type, struct attr *attr)
367 {
368 struct attr * active=NULL;
369 switch (type) {
370 case attr_position_fix_type:
371 attr->u.num = priv->fix_type;
372 break;
373 case attr_position_height:
374 attr->u.numd = &priv->height;
375 break;
376 case attr_position_speed:
377 attr->u.numd = &priv->speed;
378 break;
379 case attr_position_direction:
380 attr->u.numd = &priv->direction;
381 break;
382 case attr_position_qual:
383 attr->u.num = priv->sats;
384 break;
385 case attr_position_sats_used:
386 attr->u.num = priv->sats_used;
387 break;
388 case attr_position_coord_geo:
389 attr->u.coord_geo = &priv->geo;
390 if (!priv->have_cords)
391 return 0;
392 break;
393 case attr_position_time_iso8601:
394 {
395 struct tm tm;
396 if (!priv->fix_time)
397 return 0;
398 if (gmtime_r(&priv->fix_time, &tm)) {
399 strftime(priv->fixiso8601, sizeof(priv->fixiso8601),
400 "%Y-%m-%dT%TZ", &tm);
401 attr->u.str=priv->fixiso8601;
402 } else
403 return 0;
404 }
405 case attr_active:
406 active = attr_search(priv->attrs,NULL,attr_active);
407 if(active != NULL && active->u.num == 1)
408 return 1;
409 else
410 return 0;
411 break;
412
413 default:
414 return 0;
415 }
416 attr->type = type;
417 return 1;
418 }
419
420 struct vehicle_methods vehicle_gypsy_methods = {
421 vehicle_gypsy_destroy,
422 vehicle_gypsy_position_attr_get,
423 };
424
425 /**
426 * @brief Create gypsy_vehicle
427 *
428 * @param meth
429 * @param cbl
430 * @param attrs
431 * @returns vehicle_priv
432 */
433 static struct vehicle_priv *
434 vehicle_gypsy_new_gypsy(struct vehicle_methods *meth,
435 struct callback_list *cbl,
436 struct attr **attrs)
437 {
438 struct vehicle_priv *ret;
439 struct attr *source, *retry_int;
440
441 #if defined(USE_BINDING_DBUS) && defined(HAVE_UNISTD_H)
442 DBusConnection *conn;
443 DBusMessage *message;
444 dbus_uint32_t serial,pid=getpid();
445 struct attr *destination,*path,*interface,*method;
446
447 destination=attr_search(attrs, NULL, attr_dbus_destination);
448 path=attr_search(attrs, NULL, attr_dbus_path);
449 interface=attr_search(attrs, NULL, attr_dbus_interface);
450 method=attr_search(attrs, NULL, attr_dbus_method);
451 if (destination && path && interface && method) {
452 conn=dbus_bus_get(DBUS_BUS_SESSION, NULL);
453 if (conn) {
454 message=dbus_message_new_method_call(destination->u.str,path->u.str,interface->u.str,method->u.str);
455 dbus_message_append_args(message, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID);
456 dbus_connection_send(conn, message, &serial);
457 dbus_message_unref(message);
458 dbus_connection_unref(conn);
459 } else {
460 dbg(0,"failed to connect to session bus\n");
461 }
462 }
463 #endif
464 dbg(1, "enter\n");
465 source = attr_search(attrs, NULL, attr_source);
466 ret = g_new0(struct vehicle_priv, 1);
467 ret->have_cords = 0;
468 ret->source = g_strdup(source->u.str);
469 ret->attrs = attrs;
470 retry_int = attr_search(attrs, NULL, attr_retry_interval);
471 if (retry_int) {
472 ret->retry_interval = retry_int->u.num;
473 if (ret->retry_interval < MIN_RETRY_INTERVAL) {
474 dbg(0, "Retry interval %d too small, setting to %d\n", ret->retry_interval, MIN_RETRY_INTERVAL);
475 ret->retry_interval = MIN_RETRY_INTERVAL;
476 }
477 } else {
478 dbg(0, "Retry interval not defined, setting to %d\n", DEFAULT_RETRY_INTERVAL);
479 ret->retry_interval = DEFAULT_RETRY_INTERVAL;
480 }
481 ret->cbl = cbl;
482 *meth = vehicle_gypsy_methods;
483 vehicle_gypsy_open(ret);
484 return ret;
485 }
486
487 /**
488 * @brief register vehicle_gypsy
489 *
490 * @returns nothing
491 */
492 void
493 plugin_init(void)
494 {
495 dbg(1, "enter\n");
496 plugin_register_vehicle_type("gypsy", vehicle_gypsy_new_gypsy);
497 }

   
Visit the ZANavi Wiki