2015-06-30 01:26:58 +03:00

265 lines
6.1 KiB
C

/*
* main.c
*
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "usefull_macros.h"
#include "cmdlnopts.h"
#include "daemon.h"
#include <assert.h>
#include <signal.h>
#ifndef PIDFILE
#define PIDFILE "/tmp/GPStest.pid"
#endif
glob_pars *GP = NULL;
static void signals(int sig){
DBG("Get signal %d, quit.\n", sig);
restore_tty();
exit(sig);
}
char *get_portdata(){
static char buf[1025];
char *ptr = buf;
size_t L = 0, rest = 1024;
while(rest && (L = read_tty(ptr, rest))){
rest -= L;
ptr += L;
}
if(ptr != buf){
*ptr = 0;
ptr = buf;
}else ptr = NULL;
return ptr;
}
/**
* Checksum: return 0 if fails
*/
int checksum(char *buf){
char *eol;
char chs[2];
unsigned char checksum = 0;
if(*buf != '$' || !(eol = strchr(buf, '*'))){
DBG("Wrong data: %s\n", buf);
return 0;
}
while(++buf != eol)
checksum ^= (unsigned char) (*buf);
snprintf(chs, 2, "%X", checksum);
if(!strncmp(chs, ++buf, 2)) return 0;
return 1;
}
void gsv(_U_ char *buf){
//DBG("gsv: %s\n", buf);
}
/*
* Recommended minimum specific GPS/Transit data
* $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
* 1 = UTC of position fix
* 2 = Data status (V=navigation receiver warning)
* 3 = Latitude of fix
* 4 = N or S
* 5 = Longitude of fix
* 6 = E or W
* 7 = Speed over ground in knots
* 8 = Track made good in degrees True
* 9 = UT date
* 10 = Magnetic variation degrees (Easterly var. subtracts from true course)
* 11 = E or W
* 12 = Checksum
* 213457.00,A,4340.59415,N,04127.47560,E,2.494,,290615,,,A*7B
*/
void rmc(char *buf){
int H, M, LO, LA, d, m, y;
float S;
float longitude, lattitude, speed, track, mag;
char varn = 'V', north = '0', east = '0', mageast = '0';
sscanf(buf, "%2d%2d%f", &H, &M, &S);
buf = strchr(buf, ',')+1;
if(*buf != ',') varn = *buf;
if(varn != 'A')
printf("(data could be wrong)");
else
printf("(data valid)");
printf(" time: %02d:%02d:%05.2f", H, M, S);
buf = strchr(buf, ',')+1;
sscanf(buf, "%2d%f", &LA, &lattitude);
buf = strchr(buf, ',')+1;
if(*buf != ','){
north = *buf;
lattitude = (float)LA + lattitude / 60.;
if(north == 'S') lattitude = -lattitude;
printf(" latt: %f", lattitude);
}
buf = strchr(buf, ',')+1;
sscanf(buf, "%3d%f", &LO, &longitude);
buf = strchr(buf, ',')+1;
if(*buf != ','){
east = *buf;
longitude = (float)LO + longitude / 60.;
if(east == 'W') longitude = -longitude;
printf(" long: %f", longitude);
}
buf = strchr(buf, ',')+1;
if(*buf != ','){
sscanf(buf, "%f", &speed);
printf(" speed: %fknots", speed);
}
buf = strchr(buf, ',')+1;
if(*buf != ','){
sscanf(buf, "%f", &track);
printf(" track: %fdeg,True", track);
}
buf = strchr(buf, ',')+1;
if(sscanf(buf, "%2d%2d%2d", &d, &m, &y) == 3)
printf(" date(dd/mm/yy): %02d/%02d/%02d", d, m, y);
buf = strchr(buf, ',')+1;
sscanf(buf, "%f,%c*", &mag, &mageast);
if(mageast == 'E' || mageast == 'W'){
if(mageast == 'W') mag = -mag;
printf(" magnetic var: %f", mag);
}
printf("\n");
}
// A,2,04,31,32,14,19,,,,,,,,2.77,2.58,1.00*05
void gsa(_U_ char *buf){
//DBG("gsa: %s\n", buf);
}
// 213457.00,4340.59415,N,04127.47560,E,1,05,2.58,1275.8,M,17.0,M,,*60
void gga(_U_ char *buf){
//DBG("gga: %s\n", buf);
}
//4340.59415,N,04127.47560,E,213457.00,A,A*60
void gll(_U_ char *buf){
//DBG("gll: %s\n", buf);
}
// ,T,,M,2.494,N,4.618,K,A*23
void vtg(_U_ char *buf){
//DBG("vtg: %s\n", buf);
}
void txt(_U_ char *buf){
//DBG("txt: %s\n", buf);
}
/**
* Parce content of buffer with GPS data
* WARNING! This function changes data content
*/
void parce_data(char *buf){
char *eol;
while(buf && (eol = strchr(buf, '\r'))){
*eol = 0;
// now make checksum checking:
if(!checksum(buf)) goto cont;
if(strncmp(buf, "$GP", 3)){
DBG("Bad string: %s\n", buf);
goto cont;
}
buf += 3;
// PARSE variants: GSV, RMC, GSA, GGA, GLL, VTG, TXT
// 1st letter, cold be one of G,R,V or T
switch(*buf){
case 'G': // GSV, GSA, GGA, GLL
++buf;
if(strncmp(buf, "SV", 2) == 0){
gsv(buf+3);
}else if(strncmp(buf, "SA", 2) == 0){
gsa(buf+3);
}else if(strncmp(buf, "GA", 2) == 0){
gga(buf+3);
}else if(strncmp(buf, "LL", 2) == 0){
gll(buf+3);
}else{
DBG("Unknown: $GPG%s", buf);
goto cont;
}
break;
case 'R': // RMC
++buf;
if(strncmp(buf, "MC", 2) == 0){
rmc(buf+3);
}else{
DBG("Unknown: $GPR%s", buf);
goto cont;
}
break;
case 'V': // VTG
++buf;
if(strncmp(buf, "TG", 2) == 0){
vtg(buf+3);
}else{
DBG("Unknown: $GPV%s", buf);
goto cont;
}
break;
case 'T': // TXT
++buf;
if(strncmp(buf, "XT", 2) == 0){
txt(buf+3);
}else{
DBG("Unknown: $GPT%s", buf);
goto cont;
}
break;
default:
DBG("Unknown: $GP%s", buf);
goto cont;
}
// printf("GOT: %s\n", buf);
cont:
if(eol[1] != '\n') break;
buf = eol + 2;
}
}
int main(int argc, char **argv){
check4running(argv, PIDFILE, NULL);
initial_setup();
GP = parce_args(argc, argv);
assert(GP);
DBG("Device path: %s\n", GP->devpath);
tty_init(GP->devpath);
signal(SIGTERM, signals); // kill (-15) - quit
signal(SIGHUP, signals); // hup - quit
signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
double T0 = dtime();
char *str = NULL;
while(dtime() - T0 < 10.){
if((str = get_portdata()))
parce_data(str);
}
signals(0);
return 0;
}