/** @fn static void vehicle_file_close(struct vehicle_priv *priv) ***************************************************************************** * @b Description: close dialogue with the GPS ***************************************************************************** * @param priv : pointer on the private data of the plugin ***************************************************************************** **/ static void vehicle_file_close(struct vehicle_priv *priv) { dbg(1, "enter, priv->fd='%d'\n", priv->fd); vehicle_file_disable_watch(priv); #ifdef _WIN32 if(priv->file_type == file_type_serial) { if (priv->timeout_callback) { callback_destroy(priv->timeout_callback); priv->timeout_callback=NULL; // dangling pointer! prevent double freeing. } serial_io_shutdown( priv->fd ); } else #endif { if (priv->file) { #ifndef _MSC_VER pclose(priv->file); #endif /* _MSC_VER */ } else if (priv->fd >= 0) { close(priv->fd); } priv->file = NULL; priv->fd = -1; } }
/** @fn static void vehicle_file_io(struct vehicle_priv *priv) ***************************************************************************** * @b Description: function to get data from GPS ***************************************************************************** * @param priv : pointer on the private data of the plugin ***************************************************************************** * @remarks Not used on WIN32 operating system ***************************************************************************** **/ static void vehicle_file_io(struct vehicle_priv *priv) { dbg(1, "vehicle_file_io : enter\n"); #ifndef _WIN32 int size, rc = 0; char *str, *tok; size = read(priv->fd, priv->buffer + priv->buffer_pos, buffer_size - priv->buffer_pos - 1); if (size <= 0) { switch (priv->on_eof) { case 0: vehicle_file_close(priv); vehicle_file_open(priv); break; case 1: vehicle_file_disable_watch(priv); break; case 2: exit(0); break; } return; } priv->buffer_pos += size; priv->buffer[priv->buffer_pos] = '\0'; dbg(1, "size=%d pos=%d buffer='%s'\n", size, priv->buffer_pos, priv->buffer); str = priv->buffer; while ((tok = strchr(str, '\n'))) { *tok++ = '\0'; dbg(1, "line='%s'\n", str); rc +=vehicle_file_parse(priv, str); str = tok; } if (str != priv->buffer) { size = priv->buffer + priv->buffer_pos - str; memmove(priv->buffer, str, size + 1); priv->buffer_pos = size; dbg(1, "now pos=%d buffer='%s'\n", priv->buffer_pos, priv->buffer); } else if (priv->buffer_pos == buffer_size - 1) { dbg(0, "Overflow. Most likely wrong baud rate or no nmea protocol\n"); priv->buffer_pos = 0; } if (rc) callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); #endif }
/** @fn static void vehicle_file_close(struct vehicle_priv *priv) ***************************************************************************** * @b Description: close dialogue with the GPS ***************************************************************************** * @param priv : pointer on the private data of the plugin ***************************************************************************** **/ static void vehicle_file_close(struct vehicle_priv *priv) { dbg(1, "enter, priv->fd='%d'\n", priv->fd); vehicle_file_disable_watch(priv); #ifdef _WIN32 if (priv->timeout_callback) { callback_destroy(priv->timeout_callback); priv->timeout_callback=NULL; // dangling pointer! prevent double freeing. } serial_io_shutdown( priv->fd ); #else if (priv->file) pclose(priv->file); else if (priv->fd >= 0) close(priv->fd); priv->file = NULL; #endif priv->fd = -1; }
/** @fn static int vehicle_file_parse( struct vehicle_priv *priv, * char *buffer) ***************************************************************************** * @b Description: Parse the buffer ***************************************************************************** * @param priv : pointer on the private data of the plugin * @param buffer : data buffer (null terminated) ***************************************************************************** * @return 1 if The GPRMC Sentence is found * 0 if not found ***************************************************************************** **/ static int vehicle_file_parse(struct vehicle_priv *priv, char *buffer) { char *nmea_data_buf, *p, *item[32]; double lat, lng; int i, j, bcsum; int len = strlen(buffer); unsigned char csum = 0; int valid=0; int ret = 0; dbg(2, "enter: buffer='%s'\n", buffer); for (;;) { if (len < 4) { dbg(0, "'%s' too short\n", buffer); return ret; } if (buffer[len - 1] == '\r' || buffer[len - 1] == '\n') { buffer[--len] = '\0'; if (buffer[len - 1] == '\r') buffer[--len] = '\0'; } else break; } if (buffer[0] != '$') { dbg(0, "no leading $ in '%s'\n", buffer); return ret; } if (buffer[len - 3] != '*') { dbg(0, "no *XX in '%s'\n", buffer); return ret; } for (i = 1; i < len - 3; i++) { csum ^= (unsigned char) (buffer[i]); } if (!sscanf(buffer + len - 2, "%x", &bcsum) && priv->checksum_ignore != 2) { dbg(0, "no checksum in '%s'\n", buffer); return ret; } if (bcsum != csum && priv->checksum_ignore == 0) { dbg(0, "wrong checksum in '%s'\n", buffer); return ret; } if (!priv->nmea_data_buf || strlen(priv->nmea_data_buf) < 65536) { nmea_data_buf=g_strconcat(priv->nmea_data_buf ? priv->nmea_data_buf : "", buffer, "\n", NULL); g_free(priv->nmea_data_buf); priv->nmea_data_buf=nmea_data_buf; } else { dbg(0, "nmea buffer overflow, discarding '%s'\n", buffer); } i = 0; p = buffer; while (i < 31) { item[i++] = p; while (*p && *p != ',') p++; if (!*p) break; *p++ = '\0'; } if (!strncmp(buffer, "$GPGGA", 6)) { /* 1 1111 0 1 2 3 4 5 6 7 8 9 0 1234 $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C UTC of Fix[1],Latitude[2],N/S[3],Longitude[4],E/W[5],Quality(0=inv,1=gps,2=dgps)[6],Satelites used[7], HDOP[8],Altitude[9],"M"[10],height of geoid[11], "M"[12], time since dgps update[13], dgps ref station [14] */ if (*item[2] && *item[3] && *item[4] && *item[5]) { lat = g_ascii_strtod(item[2], NULL); priv->geo.lat = floor(lat / 100); lat -= priv->geo.lat * 100; priv->geo.lat += lat / 60; if (!strcasecmp(item[3],"S")) priv->geo.lat=-priv->geo.lat; lng = g_ascii_strtod(item[4], NULL); priv->geo.lng = floor(lng / 100); lng -= priv->geo.lng * 100; priv->geo.lng += lng / 60; if (!strcasecmp(item[5],"W")) priv->geo.lng=-priv->geo.lng; priv->valid=attr_position_valid_valid; dbg(2, "latitude '%2.4f' longitude %2.4f\n", priv->geo.lat, priv->geo.lng); } else priv->valid=attr_position_valid_invalid; if (*item[6]) sscanf(item[6], "%d", &priv->status); if (*item[7]) sscanf(item[7], "%d", &priv->sats_used); if (*item[8]) sscanf(item[8], "%lf", &priv->hdop); if (*item[1]) strcpy(priv->fixtime, item[1]); if (*item[9]) sscanf(item[9], "%lf", &priv->height); g_free(priv->nmea_data); priv->nmea_data=priv->nmea_data_buf; priv->nmea_data_buf=NULL; #ifndef _WIN32 if (priv->file_type == file_type_file) { if (priv->watch) { vehicle_file_disable_watch(priv); event_add_timeout(priv->time, 0, priv->cbt); } } #endif } if (!strncmp(buffer, "$GPVTG", 6)) { /* 0 1 2 34 5 6 7 8 $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A Course Over Ground Degrees True[1],"T"[2],Course Over Ground Degrees Magnetic[3],"M"[4], Speed in Knots[5],"N"[6],"Speed in KM/H"[7],"K"[8] */ if (item[1] && item[7]) valid = 1; if (i >= 10 && (*item[9] == 'A' || *item[9] == 'D')) valid = 1; if (valid) { priv->direction = g_ascii_strtod( item[1], NULL ); priv->speed = g_ascii_strtod( item[7], NULL ); dbg(2,"direction %lf, speed %2.1lf\n", priv->direction, priv->speed); } } if (!strncmp(buffer, "$GPRMC", 6)) { /* 1 1 0 1 2 3 4 5 6 7 8 9 0 1 $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A Time[1],Active/Void[2],lat[3],N/S[4],long[5],W/E[6],speed in knots[7],track angle[8],date[9], magnetic variation[10],magnetic variation direction[11] */ if (*item[2] == 'A') valid = 1; if (i >= 13 && (*item[12] == 'A' || *item[12] == 'D')) valid = 1; if (valid) { priv->direction = g_ascii_strtod( item[8], NULL ); priv->speed = g_ascii_strtod( item[7], NULL ); priv->speed *= 1.852; sscanf(item[9], "%02d%02d%02d", &priv->fixday, &priv->fixmonth, &priv->fixyear); priv->fixyear += 2000; } ret = 1; } if (!strncmp(buffer, "$GPGSV", 6) && i >= 4) { /* 0 GSV Satellites in view 1 2 Number of sentences for full data 2 1 sentence 1 of 2 3 08 Number of satellites in view 4 01 Satellite PRN number 5 40 Elevation, degrees 6 083 Azimuth, degrees 7 46 SNR - higher is better for up to 4 satellites per sentence *75 the checksum data, always begins with * */ if (item[3]) { sscanf(item[3], "%d", &priv->sats_visible); } j=4; while (j+4 <= i && priv->current_count < 24) { struct gps_sat *sat=&priv->next[priv->next_count++]; sat->prn=atoi(item[j]); sat->elevation=atoi(item[j+1]); sat->azimuth=atoi(item[j+2]); sat->snr=atoi(item[j+3]); j+=4; } if (!strcmp(item[1], item[2])) { priv->sats_signal=0; for (i = 0 ; i < priv->next_count ; i++) { priv->current[i]=priv->next[i]; if (priv->current[i].snr) priv->sats_signal++; } priv->current_count=priv->next_count; priv->next_count=0; } } if (!strncmp(buffer, "$GPZDA", 6)) { /* 0 1 2 3 4 5 6 $GPZDA,hhmmss.ss,dd,mm,yyyy,xx,yy*CC hhmmss HrMinSec(UTC) dd,mm,yyy Day,Month,Year xx local zone hours -13..13 yy local zone minutes 0..59 */ if (item[1] && item[2] && item[3] && item[4]) { // priv->fixtime = atof(item[1]); strcpy(priv->fixtime, item[1]); priv->fixday = atoi(item[2]); priv->fixmonth = atoi(item[3]); priv->fixyear = atoi(item[4]); } } if (!strncmp(buffer, "$IISMD", 6)) { /* 0 1 2 3 4 $IISMD,dir,press,height,temp*CC" dir Direction (0-359) press Pressure (hpa, i.e. 1032) height Barometric height above ground (meter) temp Temperature (Degree Celsius) */ if (item[1]) { priv->magnetic_direction = g_ascii_strtod( item[1], NULL ); dbg(1,"magnetic %d\n", priv->magnetic_direction); } } return ret; }
/** @fn static void vehicle_file_io(struct vehicle_priv *priv) ***************************************************************************** * @b Description: function to get data from GPS ***************************************************************************** * @param priv : pointer on the private data of the plugin ***************************************************************************** * @remarks ***************************************************************************** **/ static void vehicle_file_io(struct vehicle_priv *priv) { int size, rc = 0; char *str, *tok; dbg(1, "vehicle_file_io : enter\n"); if (priv->process_statefile) { unsigned char *data; priv->process_statefile=0; if (file_get_contents(priv->statefile, &data, &size)) { if (size > buffer_size) size=buffer_size; memcpy(priv->buffer, data, size); priv->buffer_pos=0; g_free(data); } else return; } else { size = read(priv->fd, priv->buffer + priv->buffer_pos, buffer_size - priv->buffer_pos - 1); } if (size <= 0) { switch (priv->on_eof) { case 0: vehicle_file_close(priv); vehicle_file_open(priv); break; case 1: vehicle_file_disable_watch(priv); break; case 2: exit(0); break; } return; } priv->buffer_pos += size; priv->buffer[priv->buffer_pos] = '\0'; dbg(1, "size=%d pos=%d buffer='%s'\n", size, priv->buffer_pos, priv->buffer); str = priv->buffer; while ((tok = strchr(str, '\n'))) { *tok++ = '\0'; dbg(1, "line='%s'\n", str); rc +=vehicle_file_parse(priv, str); str = tok; if (priv->file_type == file_type_file && rc) break; } if (str != priv->buffer) { size = priv->buffer + priv->buffer_pos - str; memmove(priv->buffer, str, size + 1); priv->buffer_pos = size; dbg(1, "now pos=%d buffer='%s'\n", priv->buffer_pos, priv->buffer); } else if (priv->buffer_pos == buffer_size - 1) { dbg(0, "Overflow. Most likely wrong baud rate or no nmea protocol\n"); priv->buffer_pos = 0; } if (rc) callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); }