You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spOSMroute/main/gps.c

790 lines
21 KiB

/***************************************************************************
* gps.c
*
* Copyright 2010 - Steffen Pohle
* steffen@gulpe.de
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "osmroute.h"
#include "gui.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include "gps.h"
#include "memoryleak.h"
#include "draw.h"
#include "system.h"
int gps_getdatatime (char *text);
float gps_getlon (char *text);
float gps_getlat (char *text);
int gps_convert_line (char *line, struct gps_data *data);
struct gps_data gpspos;
struct gps_data gpsposvalid;
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
#if defined ANDROID
char gpsdevice[GPS_DEVICELEN] = "android:";
#else
char gpsdevice[GPS_DEVICELEN] = "serial:/dev/rfcomm0";
#endif
#else
char gpsdevice[GPS_DEVICELEN] = "serial:com1,38400";
#endif
int gpsflags = GPSF_LOG;
char gpsdata[GPS_INBUFSIZE];
int gpsdatalen = 0;
int gpsstatus = 0; /* status: 0 = not running, 1 = running, -1 = error */
time_t gpsstarttime; /* timestamp when we started to get gps informations */
int gpsdevtime = 0; /* gps device time */
int gpslasttype = GPS_T_NONE; /* type of the last opened device GPS_T_SERIAL, GPS_T_FILE */
struct gps_route *gpsroute;
char logfile[LEN_FILENAME] = "gpslog.nmea";
/*********************************************************************************************
*
* gpsroute stuff
*/
void gpsroute_free (struct gps_route *gr) {
if (gr == gpsroute) gpsroute = NULL;
if (gr->data) ml_free (gr->data);
if (gr->pdata) ml_free (gr->pdata);
ml_free (gr);
};
struct gps_route *gpsroute_new () {
struct gps_route *gr = (struct gps_route*) ml_malloc (sizeof (struct gps_route));
gr->max = 0;
gr->cnt = 0;
gr->data = NULL;
gr->pmax = 0;
gr->pcnt = 0;
gr->pdata = NULL;
return gr;
};
void gpsroute_addpos (struct gps_route *gr, float lon, float lat, float speed, time_t t) {
if (gr == NULL) return;
if (gr->cnt+1 >= gr->max) {
struct gps_routedata *tmp;
gr->max = gr->max + 1024;
tmp = (struct gps_routedata*) ml_malloc (sizeof (struct gps_routedata) * (gr->max));
ml_addinfo (tmp, "gpsroute");
if (gr->data) {
memcpy (tmp, gr->data, sizeof (struct gps_routedata) * gr->cnt);
ml_free (gr->data);
}
gr->data = tmp;
}
gr->data[gr->cnt].lon = lon;
gr->data[gr->cnt].lat = lat;
gr->data[gr->cnt].speed = speed;
gr->data[gr->cnt].time = t;
gr->cnt++;
};
void gpsroute_addpoi (struct gps_route *gr, float lon, float lat, char *text) {
if (gr == NULL) return;
if (gr->pcnt+1 >= gr->pmax) {
struct gps_routepoidata *tmp;
gr->pmax = gr->pmax + 1024;
tmp = (struct gps_routepoidata*) ml_malloc (sizeof (struct gps_routepoidata) * (gr->pmax));
ml_addinfo (tmp, "gpspoiroute");
if (gr->pdata) {
memcpy (tmp, gr->pdata, sizeof (struct gps_routepoidata) * gr->pcnt);
ml_free (gr->pdata);
}
gr->pdata = tmp;
}
gr->pdata[gr->pcnt].lon = lon;
gr->pdata[gr->pcnt].lat = lat;
strncpy (gr->pdata[gr->pcnt].name, text, GPS_ROUTEPOILEN);
gr->pcnt++;
};
void gpsroute_exportgpx (struct gps_route *gr, char *filename) {
int i;
float olon = 0.0, olat = 0.0;
char tt[128];
FILE *f;
if (gr) {
f = fopen (filename, "w");
fprintf (f, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n");
fprintf (f, " <gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"sposmroute - http://sposmroute.gulpe.de\">\n");
fprintf (f, " <trk><name>noname</name>\n");
for (i = 0; i < gr->cnt; i++) {
if (i == 0 || (olon != gr->data[i].lon && olat != gr->data[i].lat)) {
strftime (tt, 32, "%Y-%m-%dT%H:%M:%SZ", localtime(&gr->data[i].time));
fprintf (f, " <trkpt lat=\"%f\" lon=\"%f\"><time>%s</time></trkpt>\n", gr->data[i].lat, gr->data[i].lon, tt);
olon = gr->data[i].lon;
olat = gr->data[i].lat;
}
}
fprintf (f, " </trk>\n");
for (i = 0; i < gr->pcnt; i++) {
fprintf (f, " <wpt lat=\"%f\" lon=\"%f\">\n", gr->pdata[i].lat, gr->pdata[i].lon);
fprintf (f, " <name>%s</name>\n", gr->pdata[i].name);
fprintf (f, " </wpt>\n");
}
fprintf (f, " </gpx>\n");
fclose (f);
}
};
/*
void gpsroute_saveroute (struct gps_route *gr, char *filename) {
int i;
float olon = 0.0, olat = 0.0;
FILE *f;
char tt[32];
if (gr) {
f = fopen (filename, "w");
for (i = 0; i < gr->cnt; i++) {
if (i == 0 || (olon != gr->data[i].lon && olat != gr->data[i].lat)) {
strftime (tt, 32, "%Y-%m-%dT%H:%M:%SZ", localtime(&gr->data[i].time));
fprintf (f, "%s lon:%7.4f lat:%7.4f\n", tt, gr->data[i].lon, gr->data[i].lat);
olon = gr->data[i].lon;
olat = gr->data[i].lat;
}
}
fclose (f);
}
};
*/
/*********************************************************************************************
*
* variables and functions needed by all gps_file_device_ functions.
* gps_file_device* will be used to simulate gps log files, this makes it possible to playback
* driving on the street without going out.
*
*/
char *gps_file_buffer = NULL; // buffer to keep the data inside
int gps_file_buflen; // bytes inside the buffer
int gps_file_fd = 0; // file descriptor
int gps_file_size = 0; // file size
char gps_file_fn[GPS_DEVICELEN]; // currently open file
/* the times will be used to detect when we need to send another line, so we can simulate the
* whole gps stream also with simulated time */
time_t gps_file_hosttime; // daytime when we started to read the log file (in seconds)
int gps_file_filetime; // daytime of the first time found (we use $GPRMC for time) (in seconds)
int gps_file_state; // simulation?
int gps_file_get_state () { return gps_file_state; };
void gps_file_set_state (int state) {
if (state == GPSF_RUN || state == GPSF_INIT) gps_file_state = GPSF_INIT;
else gps_file_state = GPSF_PAUSE;
};
void gps_file_set_pos (int newpos) {
if (newpos >= gps_file_size) lseek (gps_file_fd, 0, SEEK_END);
else if (newpos < 0) lseek (gps_file_fd, 0, SEEK_SET);
else lseek (gps_file_fd, newpos, SEEK_SET);
gps_file_state = GPSF_INIT;
};
int gps_file_get_pos () {
int i;
i = lseek (gps_file_fd, 0, SEEK_CUR);
return i;
};
int gps_file_get_size () { return gps_file_size; };
int gps_file_device_open () {
/* copy filename */
strncpy (gps_file_fn, gpsdevice+5, GPS_DEVICELEN);
#if defined(__MINGW32CE__) || defined(_WIN32_WCE) || defined(__MINGW32__)
gps_file_fd = open (gps_file_fn, O_RDONLY | _O_BINARY);
#else
gps_file_fd = open (gps_file_fn, O_RDONLY);
#endif
if (gps_file_fd == -1) {
d_printf ("%s:%d gps_file_device_open could not open file:%s gpsdevice:%s", __FILE__, __LINE__,
gps_file_fn, gpsdevice);
return 0;
}
if (gps_file_buffer) ml_free (gps_file_buffer);
gps_file_size = lseek (gps_file_fd, 0, SEEK_END);
lseek (gps_file_fd, 0, SEEK_SET);
gps_file_buffer = (char *) ml_malloc (GPS_INBUFSIZE);
gps_file_state = GPSF_INIT;
gpswin_show ();
return 1;
};
void gps_file_device_close () {
if (gps_file_fd > 0) close (gps_file_fd);
gps_file_size = 0;
gps_file_fd = 0;
gps_file_state = GPSF_NONE;
gps_file_fn[0] = 0;
if (gps_file_buffer) ml_free (gps_file_buffer);
gps_file_buffer = NULL;
gps_file_buflen = 0;
};
int gps_file_device_read (char *ptr, int ptrsize) {
int i, nr = 0, datatime;
time_t curtime;
int eof = 0;
/*
* test if we are in state init
*/
if (gps_file_state == GPSF_INIT) {
gps_file_hosttime = time (NULL);
gps_file_filetime = -1; /* we still don't have any data to get the time */
gps_file_buflen = 0;
gps_file_state = GPSF_RUN;
}
if (gps_file_state == GPSF_RUN) {
/*
* refill the buffer
*/
if (gps_file_buflen < GPS_INBUFSIZE) {
i = read (gps_file_fd, gps_file_buffer + gps_file_buflen, GPS_INBUFSIZE-gps_file_buflen);
gps_file_buflen += i;
if (i == 0) eof = 1;
}
/*
* check if we can send a new line
*/
curtime = time (NULL);
if (strncmp (gps_file_buffer, "$GPRMC,", 7) == 0) {
datatime = gps_getdatatime (gps_file_buffer+7);
if (gps_file_filetime == -1) gps_file_filetime = datatime;
}
if (strncmp (gps_file_buffer, "$GPRMC,", 7) != 0 || (curtime-gps_file_hosttime >= datatime-gps_file_filetime)) {
for (i = 0; i < (ptrsize-1) && i < gps_file_buflen; i++) {
ptr[i] = gps_file_buffer[i];
if (gps_file_buffer[i] == '\r' || gps_file_buffer[i] == '\n') {
i++;
ptr[i] = 0;
break;
}
}
/* move the leftover inside the buffer to the beginning */
if (i >= 0) {
if (gps_file_buflen > 0) {
memmove (gps_file_buffer, gps_file_buffer+i, GPS_INBUFSIZE-i);
gps_file_buflen = gps_file_buflen - i;
}
nr = i;
}
}
if (gps_file_buflen < GPS_INBUFSIZE && eof) gps_file_state = GPSF_END;
}
return nr;
};
/********************************************************************************************
* convert text "173436.000" into time in seconds form 00:00:00
*/
int gps_getdatatime (char *text) {
char c_hms[3][3]; /* hours, mins, secs */
int i;
for (i = 0; i < 2; i++) {
c_hms[0][i] = text[i];
c_hms[1][i] = text[2+i];
c_hms[2][i] = text[4+i];
}
c_hms[0][i] = '\0';
c_hms[1][i] = '\0';
c_hms[2][i] = '\0';
return (atoi (c_hms[0]) * 3600 + atoi (c_hms[1]) * 60 + atoi (c_hms[2]));
};
float gps_getlon (char *text) {
// GGGMM.mmmm
float ret;
char g[4];
memcpy (g, text, 3);
g[3] = 0;
ret = atof (text+3)/60.0 + (float) atoi (g);
return ret;
};
float gps_getlat (char *text) {
// GGMM.mmmm
float ret;
char g[3];
memcpy (g, text, 2);
g[2] = 0;
ret = atof (text+2)/60.0 + (float) atoi (g);
return ret;
};
/********************************************************************************************
*
* other gps stuff
*
*/
/*
* return type of currently set up gps device
*/
int gps_get_devicetype () {
if (strncmp (gpsdevice, "serial:", 7) == 0) return GPS_T_SERIAL;
else if (strncmp (gpsdevice, "file:", 5) == 0) return GPS_T_FILE;
else if (strncmp (gpsdevice, "android:", 8) == 0) return GPS_T_ANDROID;
else return GPS_T_NONE;
};
/*
* setup the new device and reinit device if it was running
*/
void gps_set_device (char *device) {
int oldstatus = gpsstatus;
d_printf ("%s:%d gps_set_device (%s)", __FILE__, __LINE__, device);
gps_stop ();
strncpy (gpsdevice, device, GPS_DEVICELEN);
if (oldstatus == 1 || oldstatus == -1)
gps_start ();
};
char *gps_get_device () {
d_printf ("%s:%d gps_get_device (%s)", __FILE__, __LINE__, gpsdevice);
return gpsdevice;
};
void gps_start () {
int error = 0;
char fn[LEN_FILENAME];
d_printf ("%s:%d gps_start device(%s)", __FILE__, __LINE__, gpsdevice);
gpsstarttime = time (NULL);
strftime (fn, LEN_FILENAME, "%F-%H-%M%S.nmea", localtime(&gpsstarttime));
snprintf (logfile, LEN_FILENAME, "%s%s", cfg.logpath, fn);
d_printf ("gps-logfile set to:%s", logfile);
gpsdevtime = -1;
if (gpsroute == NULL) gpsroute = gpsroute_new();
else {
gpsroute->cnt = 0;
gpsroute->pcnt = 0;
}
gpslasttype = gps_get_devicetype ();
if (gpslasttype == GPS_T_SERIAL) error = gps_serial_device_open ();
else if (gpslasttype == GPS_T_FILE) error = gps_file_device_open ();
#ifdef ANDROID
else if (gpslasttype == GPS_T_ANDROID) error = gps_android_device_open ();
#endif
else error = 0;
if (error) {
d_printf ("%s:%d gps_start : ok", __FILE__, __LINE__);
gpsstatus = 1;
draw_set_flag (DRAW_GPS);
}
else {
d_printf ("%s:%d gps_start : error", __FILE__, __LINE__);
gpsstatus = -1;
draw_del_flag (DRAW_GPS);
}
gpsdatalen = 0;
draw ();
};
void gps_stop () {
d_printf ("%s:%d gps_stop", __FILE__, __LINE__);
if (gpslasttype == GPS_T_SERIAL) gps_serial_device_close ();
#ifdef ANDROID
else if (gpslasttype == GPS_T_ANDROID) gps_android_device_close ();
#endif
else if (gpslasttype == GPS_T_FILE) gps_file_device_close ();
gpsstatus = 0;
gpsdatalen = 0;
draw_del_flag (DRAW_GPS);
d_printf ("gps is clean now.");
};
/*
* convert the givin line into the gps_data struct, the valid flag will
* not been deleted first, only if there is no active flag
*/
int gps_convert_line (char *line, struct gps_data *data) {
char *pos;
float lon, lat;
int i;
/* reset poi data */
data->poi.name[0] = 0;
/* kick the checksum away */
if ((pos = strchr (line, '*'))) {
pos[0] = 0;
}
/*
* read the gps line
*/
pos = line;
if (strncmp (pos, "$GPRMC", 6) == 0) {
data->time = gpsstarttime;
if ((pos = strchr (pos, ',')) == NULL) return 0; // Time
pos++;
i = gps_getdatatime (pos);
if (gpsdevtime == -1) gpsdevtime = i;
if (gpsdevtime > i) i = i + (3600*24);
data->time += (i - gpsdevtime);
if ((pos = strchr (pos, ',')) == NULL) return 0; // Active
pos++;
if (pos[0] == 'A') data->valid = 1;
if ((pos = strchr (pos, ',')) == NULL) return 0; // North-South
pos++;
data->lat = gps_getlat (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // N|S
pos++;
if (pos[0] == 'S') data->lat = -data->lat;
else if (pos[0] != 'N') return 0;
if ((pos = strchr (pos, ',')) == NULL) return 0; // East-West
pos++;
data->lon = gps_getlon (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // E|W
pos++;
if (pos[0] == 'W') data->lon = -data->lon;
else if (pos[0] != 'E') return 0;
if ((pos = strchr (pos, ',')) == NULL) return 0; // Speed
pos++;
data->speed = atof (pos) * GPS_KNOTEN2KMH;
if ((pos = strchr (pos, ',')) == NULL) return 0; // direction
pos++;
if (data->speed > 1.5) data->direction = atof (pos);
}
else if (strncmp (pos, "$POI,", 5) == 0) {
if ((pos = strchr (pos, ',')) == NULL) return 0;
pos++;
lon = atof (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0;
pos++;
lat = atof (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0;
pos++;
strncpy (data->poi.name, pos, GPS_ROUTEPOILEN);
data->poi.lon = lon;
data->poi.lat = lat;
}
else if (strncmp (pos, "$GPGGA", 6) == 0) {
data->time = gpsstarttime;
if ((pos = strchr (pos, ',')) == NULL) return 0; // Time
pos++;
if ((pos = strchr (pos, ',')) == NULL) return 0; // North-South
pos++;
data->lat = gps_getlat (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // N|S
pos++;
if (pos[0] == 'S') data->lat = -data->lat;
if ((pos = strchr (pos, ',')) == NULL) return 0; // East-West
pos++;
data->lon = gps_getlon (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // E|W
pos++;
if (pos[0] == 'W') data->lon = -data->lon;
if ((pos = strchr (pos, ',')) == NULL) return 0; // Quallity
pos++;
data->quality = atoi (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // Numer of Satelites
pos++;
data->numofsatelites = atoi (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // HDOP
pos++;
data->hdop = atof (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // Height in m
pos++;
data->height = atof (pos);
}
else if (strncmp (pos, "$GPGSV", 6) == 0) {
int n, satnr;
data->time = gpsstarttime;
if ((pos = strchr (pos, ',')) == NULL) return 0; // max data blocks
pos++;
if ((pos = strchr (pos, ',')) == NULL) return 0; // current data block
pos++;
satnr = atoi (pos);
if (satnr == 1) for (n = 0; n < 32; n++) {
data->sat[n].deg_elev = 0;
data->sat[n].deg_north = 0;
data->sat[n].quality = 0;
}
if ((pos = strchr (pos, ',')) == NULL) return 0; // number of sats
pos++;
if ((pos = strchr (pos, ',')) == NULL) return 0; // first data
n = 0;
while (pos && n < 4) {
n++;
pos++;
satnr = atoi (pos); // satnr;
if (satnr > 32 || satnr < 0) {
d_printf ("%s:%d satnr invlid: %d Line:'%s'", __FILE__, __LINE__, satnr, line);
return 0;
}
if ((pos = strchr (pos, ',')) == NULL) return 0; // elev in deg
pos++;
if (satnr != 0) data->sat[satnr-1].deg_elev = atoi (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // position in deg from north
pos++;
if (satnr != 0) data->sat[satnr-1].deg_north = atoi (pos);
if ((pos = strchr (pos, ',')) == NULL) return 0; // quality
pos++;
if (pos[0] != '*' && satnr != 0)
data->sat[satnr-1].quality = atoi (pos);
pos = strchr (pos, ','); // next data
}
}
return 1;
};
/*
* returns the pointer of the last know datablock (actually only a pointer to position)
* or returns NULL if gps is not started correctly
*/
struct gps_data *gps_loop () {
int dataread = 0, i;
int to = GPS_LOOP_TIMEOUT;
char line[2*GPS_LINELEN];
time_t call;
#ifdef HAVE_LOCALE_H
setlocale(LC_ALL, "C");
#endif
d_printf ("gps_loop");
gpspos.valid = gpsposvalid.valid = 0;
call = time (NULL);
/*
* read all completed lines
*/
do {
if (time (NULL) - call > 3) d_printf ("time??????");
/*
* check if gps is open and fillup the buffer
*/
if (gpsstatus <= 0) {
d_printf ("gps loop : status:%d", gpsstatus);
return NULL;
}
if (gpslasttype == GPS_T_SERIAL) dataread = gps_serial_device_read (gpsdata + gpsdatalen, GPS_INBUFSIZE - gpsdatalen);
#ifdef ANDROID
else if (gpslasttype == GPS_T_ANDROID) dataread = gps_android_device_read (gpsdata + gpsdatalen, GPS_INBUFSIZE - gpsdatalen);
#endif
else if (gpslasttype == GPS_T_FILE) dataread = gps_file_device_read (gpsdata + gpsdatalen, GPS_INBUFSIZE - gpsdatalen);
else dataread = -1;
if (dataread < 0) {
gps_stop();
gpsstatus = -1;
return NULL;
}
else if (dataread+gpsdatalen > GPS_INBUFSIZE) {
d_printf ("%s:%d gps_loop: ERROR datapos(%d) > GPS_INBUFSIZE(%d)", __FILE__, __LINE__, gpsdatalen + dataread, GPS_INBUFSIZE);
gpsdatalen = GPS_INBUFSIZE;
gps_stop ();
}
else gpsdatalen += dataread;
for (i = 0; i < GPS_LINELEN*2 && i < gpsdatalen && gpsdata[i] != '\n' && gpsdata[i] != '\r' && gpsdata[i] != '\0'; i++) {
line[i] = gpsdata[i];
}
if (gpsdata[i] == '\n' || gpsdata[i] == '\r' || gpsdata[i] == '\0') {
if (gpsdatalen - (i+1) > 0) {
memmove (gpsdata, gpsdata+i+1, gpsdatalen - (i+1));
gpsdatalen = gpsdatalen - (i+1);
}
else gpsdatalen = 0;
}
else if (i == gpsdatalen || i >= GPS_LINELEN*2) {
break;
}
line[i] = 0;
/* write into logfile */
// d_printf ("gps line:'%s'", line);
if (i > 0) {
if (gpslasttype != GPS_T_FILE && gpsflags & GPSF_LOG) gps_save_log (logfile, line);
if (gps_convert_line (line, &gpspos) == 0) gpspos.valid = 0;
else {
if (gpspos.quality == 1) gpspos.valid = 1;
}
if (gpspos.valid == 1) {
gpsposvalid = gpspos;
gpsroute_addpos (gpsroute, gpspos.lon, gpspos.lat, gpspos.speed, gpspos.time);
}
}
} while (gpsstatus > 0 && gpsdatalen > 0 && --to > 0);
#ifdef HAVE_LOCALE_H
setlocale(LC_ALL, NULL);
#endif
if (gpsposvalid.valid == 1) return &gpsposvalid;
else return NULL;
};
/*********************************************************************
* returns TRUE (1) if gps is running
*/
int gps_isrunning () {
return (gpsstatus);
};
struct gps_data *gps_getposition () {
if (gpsposvalid.valid == 1) return &gpsposvalid;
else return &gpspos;
};
/*
* open logfile and add one line to the end.
* If fname==NULL the file name stored in logfile will be used.
*/
void gps_save_log (char *fname, char *text) {
int f;
if (fname == NULL && gpsstatus == 1 && logfile[0] != 0)
f = open (logfile, O_RDWR | O_CREAT, 0644);
else
f = open (fname, O_RDWR | O_CREAT, 0644);
if (f) {
lseek (f, 0, SEEK_END);
write (f, text, strlen (text));
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
write (f, "\n", 1);
#else
write (f, "\n\r", 2);
#endif
close (f);
}
};
void gps_load_log (char *fn) {
float minlon, minlat;
float maxlon, maxlat;
int start;
struct gps_data *pos;
char oldgps_dev[GPS_DEVICELEN];
gps_stop ();
strncpy (oldgps_dev, gpsdevice, GPS_DEVICELEN);
snprintf (gpsdevice, GPS_DEVICELEN, "file:%s", fn);
gps_start ();
start = 1;
while (gpsstatus == 1) {
pos = gps_loop ();
if (pos) if (pos->valid) {
if (start) {
minlon = maxlon = pos->lon;
minlat = maxlat = pos->lat;
start = 0;
}
else if (pos->lon < minlon) minlon = pos->lon;
else if (pos->lon > maxlon) maxlon = pos->lon;
else if (pos->lat < minlat) minlat = pos->lat;
else if (pos->lat > maxlat) maxlat = pos->lat;
}
}
gps_stop ();
strncpy (gpsdevice, oldgps_dev, GPS_DEVICELEN);
if (start == 0) {
view_lon = minlon+(maxlon-minlon)/2.0;
view_lat = minlat+(maxlat-minlat)/2.0;
draw();
}
};