Contents of /trunk/src/gps.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 112 - (hide annotations)
Fri Mar 6 13:41:08 2009 UTC (15 years, 2 months ago) by harbaum
File MIME type: text/plain
File size: 6732 byte(s)
Maemo 5.0alpha compile fixes
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of OSM2Go.
5     *
6     * OSM2Go 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 3 of the License, or
9     * (at your option) any later version.
10     *
11     * OSM2Go 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 OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <stdio.h>
21     #include <string.h>
22     #include <math.h>
23    
24     #include "appdata.h"
25    
26 harbaum 112 #ifdef ENABLE_GPSBT
27 harbaum 1 #include <gpsbt.h>
28     #include <gpsmgr.h>
29     #include <errno.h>
30     #endif
31    
32     /* maybe user configurable later on ... */
33     #define GPSD_HOST "127.0.0.1"
34     #define GPSD_PORT 2947
35    
36     pos_t *gps_get_pos(appdata_t *appdata) {
37     static pos_t retval;
38    
39     retval.lat = NAN;
40    
41     g_mutex_lock(appdata->gps_state->mutex);
42     if(appdata->gps_state->gpsdata.set & STATUS_SET)
43     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
44     if(appdata->gps_state->gpsdata.set & LATLON_SET)
45     retval = appdata->gps_state->gpsdata.fix.pos;
46    
47     g_mutex_unlock(appdata->gps_state->mutex);
48    
49     if(isnan(retval.lat))
50     return NULL;
51    
52     return &retval;
53     }
54    
55     static int gps_connect(gps_state_t *gps_state) {
56     GnomeVFSResult vfs_result;
57 harbaum 112 #ifdef ENABLE_GPSBT
58 harbaum 1 char errstr[256] = "";
59    
60     /* We need to start gpsd (via gpsbt) first. */
61     memset(&gps_state->context, 0, sizeof(gpsbt_t));
62     errno = 0;
63    
64     if(gpsbt_start(NULL, 0, 0, 0, errstr, sizeof(errstr),
65     0, &gps_state->context) < 0) {
66     printf("Error connecting to GPS receiver: (%d) %s (%s)\n",
67     errno, strerror(errno), errstr);
68     }
69     #endif
70    
71     /************** from here down pure gnome/gtk/gpsd ********************/
72    
73     /* try to connect to gpsd */
74     /* Create a socket to interact with GPSD. */
75    
76     int retries = 5;
77     while(retries &&
78     (GNOME_VFS_OK != (vfs_result = gnome_vfs_inet_connection_create(
79     &gps_state->iconn, GPSD_HOST, GPSD_PORT, NULL)))) {
80     printf("Error creating connection to GPSD, retrying ...\n");
81    
82     retries--;
83     sleep(1);
84     }
85    
86     if(!retries) {
87     printf("Finally failed ...\n");
88     return -1;
89     }
90    
91     retries = 5;
92     while(retries && ((gps_state->socket =
93     gnome_vfs_inet_connection_to_socket(gps_state->iconn)) == NULL)) {
94     printf("Error creating connecting GPSD socket, retrying ...\n");
95    
96     retries--;
97     sleep(1);
98     }
99    
100     if(!retries) {
101     printf("Finally failed ...\n");
102     gnome_vfs_inet_connection_destroy(gps_state->iconn, NULL);
103     return -1;
104     }
105    
106     GTimeVal timeout = { 10, 0 };
107     if(GNOME_VFS_OK != (vfs_result = gnome_vfs_socket_set_timeout(
108     gps_state->socket, &timeout, NULL))) {
109     printf("Error setting GPSD timeout\n");
110     gnome_vfs_inet_connection_destroy(gps_state->iconn, NULL);
111     return -1;
112     }
113    
114     printf("GPSD connected ...\n");
115    
116     return 0;
117     }
118    
119     void gps_clear_fix(struct gps_fix_t *fixp) {
120     fixp->mode = MODE_NOT_SEEN;
121     fixp->pos.lat = fixp->pos.lon = NAN;
122     fixp->eph = NAN;
123     }
124    
125     /* unpack a daemon response into a status structure */
126     static void gps_unpack(char *buf, struct gps_data_t *gpsdata) {
127     char *ns, *sp, *tp;
128    
129     for(ns = buf; ns; ns = strstr(ns+1, "GPSD")) {
130     if(strncmp(ns, "GPSD", 4) == 0) {
131     /* the following should execute each time we have a good next sp */
132     for (sp = ns + 5; *sp != '\0'; sp = tp+1) {
133     tp = sp + strcspn(sp, ",\r\n");
134     if (*tp == '\0') tp--;
135     else *tp = '\0';
136    
137     switch (*sp) {
138     case 'O':
139     if (sp[2] == '?') {
140     gpsdata->set =
141     (gpsdata->set & SATELLITE_SET) | // fix for below
142     MODE_SET | STATUS_SET; // this clears sat info??
143     gpsdata->status = STATUS_NO_FIX;
144     gps_clear_fix(&gpsdata->fix);
145     } else {
146     struct gps_fix_t nf;
147     char tag[MAXTAGLEN+1], alt[20], eph[20], lat[20], lon[20], mode[2];
148     int st = sscanf(sp+2,
149     "%8s %*s %*s %19s %19s "
150     "%19s %19s %*s %*s %*s %*s "
151     "%*s %*s %*s %1s",
152     tag, lat, lon,
153     alt, eph,
154     mode);
155     if (st >= 5) {
156     #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
157     nf.pos.lat = DEFAULT(lat);
158     nf.pos.lon = DEFAULT(lon);
159     nf.eph = DEFAULT(eph);
160     #undef DEFAULT
161     if (st >= 6)
162     nf.mode = (mode[0] == '?') ? MODE_NOT_SEEN : atoi(mode);
163     else
164     nf.mode = (alt[0] == '?') ? MODE_2D : MODE_3D;
165     gpsdata->fix = nf;
166     gpsdata->set |= LATLON_SET|MODE_SET;
167     gpsdata->status = STATUS_FIX;
168     gpsdata->set |= STATUS_SET;
169     }
170     }
171     break;
172     }
173     }
174     }
175     }
176     }
177    
178     gpointer gps_thread(gpointer data) {
179     GnomeVFSFileSize bytes_read;
180     GnomeVFSResult vfs_result;
181     char str[512];
182     appdata_t *appdata = (appdata_t*)data;
183    
184     const char *msg = "o\r\n"; /* pos request */
185    
186     appdata->gps_state->gpsdata.set = 0;
187    
188     gboolean connected = FALSE;
189    
190     while(1) {
191     if(appdata->gps_enabled) {
192     if(!connected) {
193     printf("trying to connect\n");
194    
195     if(gps_connect(appdata->gps_state) < 0)
196     sleep(10);
197     else
198     connected = TRUE;
199     } else {
200     if(GNOME_VFS_OK ==
201     (vfs_result = gnome_vfs_socket_write(appdata->gps_state->socket,
202     msg, strlen(msg)+1, &bytes_read, NULL))) {
203    
204     /* update every second, wait here to make sure a complete */
205     /* reply is received */
206     sleep(1);
207    
208     if(bytes_read == (strlen(msg)+1)) {
209     vfs_result = gnome_vfs_socket_read(appdata->gps_state->socket,
210     str, sizeof(str)-1, &bytes_read, NULL);
211     if(vfs_result == GNOME_VFS_OK) {
212     str[bytes_read] = 0;
213    
214     printf("msg: %s (%d)\n", str, strlen(str));
215    
216     g_mutex_lock(appdata->gps_state->mutex);
217    
218     appdata->gps_state->gpsdata.set &=
219     ~(LATLON_SET|MODE_SET|STATUS_SET);
220    
221     gps_unpack(str, &appdata->gps_state->gpsdata);
222     g_mutex_unlock(appdata->gps_state->mutex);
223     }
224     }
225     }
226     }
227     } else {
228     if(connected) {
229     printf("stopping GPS connection due to user request\n");
230     gnome_vfs_inet_connection_destroy(appdata->gps_state->iconn, NULL);
231    
232 harbaum 112 #ifdef ENABLE_GPSBT
233 harbaum 1 gpsbt_stop(&appdata->gps_state->context);
234     #endif
235     connected = FALSE;
236     } else
237     sleep(1);
238     }
239     }
240    
241     printf("GPS thread ended???\n");
242     return NULL;
243     }
244    
245     void gps_init(appdata_t *appdata) {
246     appdata->gps_state = g_new0(gps_state_t, 1);
247    
248     /* start a new thread to listen to gpsd */
249     appdata->gps_state->mutex = g_mutex_new();
250     appdata->gps_state->thread_p =
251     g_thread_create(gps_thread, appdata, FALSE, NULL);
252     }
253    
254     void gps_release(appdata_t *appdata) {
255 harbaum 112 #ifdef ENABLE_GPSBT
256 harbaum 1 gpsbt_stop(&appdata->gps_state->context);
257     #endif
258     g_free(appdata->gps_state);
259     }