source: ntrip/trunk/rtcm3torinex/rtcm3torinex.c@ 101

Last change on this file since 101 was 81, checked in by stoecker, 18 years ago

fixed unit of measurement

File size: 30.2 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.4 2006/05/08 09:25:11 stoecker Exp $
4 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@euronav.de>
5
6 This program 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 2 of the License, or
9 (at your option) any later version.
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 Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 or read http://www.gnu.org/licenses/gpl.txt
20*/
21
22#include <ctype.h>
23#include <errno.h>
24#include <getopt.h>
25#include <math.h>
26#include <netdb.h>
27#include <netinet/in.h>
28#include <signal.h>
29#include <stdint.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35#include <time.h>
36#include <unistd.h>
37
38/* The string, which is send as agent in HTTP request */
39#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
40
41#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
42
43/* CVS revision and version */
44static char revisionstr[] = "$Revision: 1.4 $";
45static char datestr[] = "$Date: 2006/05/08 09:25:11 $";
46static int stop = 0;
47
48/* unimportant, only for approx. time needed */
49#define LEAPSECONDS 14
50
51struct converttimeinfo {
52 int second; /* seconds of GPS time [0..59] */
53 int minute; /* minutes of GPS time [0..59] */
54 int hour; /* hour of GPS time [0..24] */
55 int day; /* day of GPS time [1..28..30(31)*/
56 int month; /* month of GPS time [1..12]*/
57 int year; /* year of GPS time [1980..] */
58};
59
60#define PRN_GPS_START 1
61#define PRN_GPS_END 32
62#define PRN_GLONASS_START 38
63#define PRN_GLONASS_END 61
64
65#define GNSSENTRY_C1DATA 0
66#define GNSSENTRY_C2DATA 1
67#define GNSSENTRY_P1DATA 2
68#define GNSSENTRY_P2DATA 3
69#define GNSSENTRY_L1CDATA 4
70#define GNSSENTRY_L1PDATA 5
71#define GNSSENTRY_L2CDATA 6
72#define GNSSENTRY_L2PDATA 7
73#define GNSSENTRY_D1CDATA 8
74#define GNSSENTRY_D1PDATA 9
75#define GNSSENTRY_D2CDATA 10
76#define GNSSENTRY_D2PDATA 11
77#define GNSSENTRY_S1CDATA 12
78#define GNSSENTRY_S1PDATA 13
79#define GNSSENTRY_S2CDATA 14
80#define GNSSENTRY_S2PDATA 15
81#define GNSSENTRY_NUMBER 16 /* number of types!!! */
82
83/* Data flags. These flags are used in the dataflags field of gpsdata structure
84 and are used the determine, which data fields are filled with valid data. */
85#define GNSSDF_C1DATA (1<<GNSSENTRY_C1DATA)
86#define GNSSDF_C2DATA (1<<GNSSENTRY_C2DATA)
87#define GNSSDF_P1DATA (1<<GNSSENTRY_P1DATA)
88#define GNSSDF_P2DATA (1<<GNSSENTRY_P2DATA)
89#define GNSSDF_L1CDATA (1<<GNSSENTRY_L1CDATA)
90#define GNSSDF_L1PDATA (1<<GNSSENTRY_L1PDATA)
91#define GNSSDF_L2CDATA (1<<GNSSENTRY_L2CDATA)
92#define GNSSDF_L2PDATA (1<<GNSSENTRY_L2PDATA)
93#define GNSSDF_D1CDATA (1<<GNSSENTRY_D1CDATA)
94#define GNSSDF_D1PDATA (1<<GNSSENTRY_D1PDATA)
95#define GNSSDF_D2CDATA (1<<GNSSENTRY_D2CDATA)
96#define GNSSDF_D2PDATA (1<<GNSSENTRY_D2PDATA)
97#define GNSSDF_S1CDATA (1<<GNSSENTRY_S1CDATA)
98#define GNSSDF_S1PDATA (1<<GNSSENTRY_S1PDATA)
99#define GNSSDF_S2CDATA (1<<GNSSENTRY_S2CDATA)
100#define GNSSDF_S2PDATA (1<<GNSSENTRY_S2PDATA)
101
102#define RINEXENTRY_C1DATA 0
103#define RINEXENTRY_C2DATA 1
104#define RINEXENTRY_P1DATA 2
105#define RINEXENTRY_P2DATA 3
106#define RINEXENTRY_L1DATA 4
107#define RINEXENTRY_L2DATA 5
108#define RINEXENTRY_D1DATA 6
109#define RINEXENTRY_D2DATA 7
110#define RINEXENTRY_S1DATA 8
111#define RINEXENTRY_S2DATA 9
112#define RINEXENTRY_NUMBER 10
113
114/* Additional flags for the data field, which tell us more. */
115#define GNSSDF_LOCKLOSSL1 (1<<29) /* lost lock on L1 */
116#define GNSSDF_LOCKLOSSL2 (1<<30) /* lost lock on L2 */
117#define LIGHTSPEED 2.99792458e8 /* m/sec */
118#define GPS_FREQU_L1 1575420000.0 /* Hz */
119#define GPS_FREQU_L2 1227600000.0 /* Hz */
120#define GPS_WAVELENGTH_L1 (LIGHTSPEED / GPS_FREQU_L1) /* m */
121#define GPS_WAVELENGTH_L2 (LIGHTSPEED / GPS_FREQU_L2) /* m */
122
123struct gnssdata {
124 int flags; /* GPSF_xxx */
125 int week; /* week number of GPS date */
126 int numsats;
127 double timeofweek; /* milliseconds in GPS week */
128 double measdata[24][GNSSENTRY_NUMBER]; /* data fields */
129 int dataflags[24]; /* GPSDF_xxx */
130 int satellites[24]; /* SV - IDs */
131 int snrL1[24]; /* Important: all the 5 SV-specific fields must */
132 int snrL2[24]; /* have the same SV-order */
133};
134
135struct RTCM3ParserData {
136 unsigned char Message[2048]; /* input-buffer */
137 int MessageSize; /* current buffer size */
138 int NeedBytes; /* bytes wanted for next run */
139 int SkipBytes; /* bytes to skip in next round */
140 int GPSWeek;
141 int GPSTOW; /* in seconds */
142 struct gnssdata Data;
143 int size;
144 int lastlockl1[64];
145 int lastlockl2[64];
146 int datapos[RINEXENTRY_NUMBER];
147 int dataflag[RINEXENTRY_NUMBER];
148 int numdatatypes;
149 int validwarning;
150 int init;
151 const char * headerfile;
152};
153
154struct Args
155{
156 const char *server;
157 int port;
158 const char *user;
159 const char *password;
160 const char *data;
161 const char *headerfile;
162};
163
164/* option parsing */
165#ifdef NO_LONG_OPTS
166#define LONG_OPT(a)
167#else
168#define LONG_OPT(a) a
169static struct option opts[] = {
170{ "data", required_argument, 0, 'd'},
171{ "server", required_argument, 0, 's'},
172{ "password", required_argument, 0, 'p'},
173{ "port", required_argument, 0, 'r'},
174{ "header", required_argument, 0, 'f'},
175{ "user", required_argument, 0, 'u'},
176{ "help", no_argument, 0, 'h'},
177{0,0,0,0}};
178#endif
179#define ARGOPT "d:hp:r:s:u:f:"
180
181static int getargs(int argc, char **argv, struct Args *args)
182{
183 int res = 1;
184 int getoptr;
185 int help = 0;
186 char *t;
187
188 args->server = "www.euref-ip.net";
189 args->port = 80;
190 args->user = "";
191 args->password = "";
192 args->data = 0;
193 args->headerfile = 0;
194 help = 0;
195
196 do
197 {
198#ifdef NO_LONG_OPTS
199 switch((getoptr = getopt(argc, argv, ARGOPT)))
200#else
201 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
202#endif
203 {
204 case 's': args->server = optarg; break;
205 case 'u': args->user = optarg; break;
206 case 'p': args->password = optarg; break;
207 case 'd': args->data = optarg; break;
208 case 'f': args->headerfile = optarg; break;
209 case 'h': help=1; break;
210 case 'r':
211 args->port = strtoul(optarg, &t, 10);
212 if((t && *t) || args->port < 1 || args->port > 65535)
213 res = 0;
214 break;
215 case -1: break;
216 }
217 } while(getoptr != -1 || !res);
218
219 datestr[0] = datestr[7];
220 datestr[1] = datestr[8];
221 datestr[2] = datestr[9];
222 datestr[3] = datestr[10];
223 datestr[5] = datestr[12];
224 datestr[6] = datestr[13];
225 datestr[8] = datestr[15];
226 datestr[9] = datestr[16];
227 datestr[4] = datestr[7] = '-';
228 datestr[10] = 0;
229
230 if(!res || help)
231 {
232 fprintf(stderr, "Version %s (%s) GPL\nUsage: %s -s server -u user ...\n"
233 " -d " LONG_OPT("--data ") "the requested data set\n"
234 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
235 " -s " LONG_OPT("--server ") "the server name or address\n"
236 " -p " LONG_OPT("--password ") "the login password\n"
237 " -r " LONG_OPT("--port ") "the server port number (default 80)\n"
238 " -u " LONG_OPT("--user ") "the user name\n"
239 , revisionstr, datestr, argv[0]);
240 exit(1);
241 }
242 return res;
243}
244
245static const char encodingTable [64] = {
246 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
247 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
248 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
249 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
250};
251
252/* does not buffer overrun, but breaks directly after an error */
253/* returns the number of required bytes */
254static int encode(char *buf, int size, const char *user, const char *pwd)
255{
256 unsigned char inbuf[3];
257 char *out = buf;
258 int i, sep = 0, fill = 0, bytes = 0;
259
260 while(*user || *pwd)
261 {
262 i = 0;
263 while(i < 3 && *user) inbuf[i++] = *(user++);
264 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
265 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
266 while(i < 3) {inbuf[i++] = 0; ++fill; }
267 if(out-buf < size-1)
268 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
269 if(out-buf < size-1)
270 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
271 | ((inbuf [1] & 0xF0) >> 4)];
272 if(out-buf < size-1)
273 {
274 if(fill == 2)
275 *(out++) = '=';
276 else
277 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
278 | ((inbuf [2] & 0xC0) >> 6)];
279 }
280 if(out-buf < size-1)
281 {
282 if(fill >= 1)
283 *(out++) = '=';
284 else
285 *(out++) = encodingTable[inbuf [2] & 0x3F];
286 }
287 bytes += 4;
288 }
289 if(out-buf < size)
290 *out = 0;
291 return bytes;
292}
293
294static uint32_t CRC24(long size, const unsigned char *buf)
295{
296 uint32_t crc = 0;
297 int i;
298
299 while(size--)
300 {
301 crc ^= (*buf++) << (16);
302 for(i = 0; i < 8; i++)
303 {
304 crc <<= 1;
305 if(crc & 0x1000000)
306 crc ^= 0x01864cfb;
307 }
308 }
309 return crc;
310}
311
312static int GetMessage(struct RTCM3ParserData *handle)
313{
314 unsigned char *m, *e;
315 int i;
316
317 m = handle->Message+handle->SkipBytes;
318 e = handle->Message+handle->MessageSize;
319 handle->NeedBytes = handle->SkipBytes = 0;
320 while(e-m >= 3)
321 {
322 if(m[0] == 0xD3)
323 {
324 handle->size = ((m[1]&3)<<8)|m[2];
325 if(e-m >= handle->size+6)
326 {
327 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
328 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
329 {
330 handle->SkipBytes = handle->size;
331 break;
332 }
333 else
334 ++m;
335 }
336 else
337 {
338 handle->NeedBytes = handle->size+6;
339 break;
340 }
341 }
342 else
343 ++m;
344 }
345 if(e-m < 3)
346 handle->NeedBytes = 3;
347
348 /* copy buffer to front */
349 i = m - handle->Message;
350 if(i && m < e)
351 memmove(handle->Message, m, handle->MessageSize-i);
352 handle->MessageSize -= i;
353
354 return !handle->NeedBytes;
355}
356
357#define LOADBITS(a) \
358{ \
359 while((a) > numbits) \
360 { \
361 if(!size--) break; \
362 bitfield = (bitfield<<8)|*(data++); \
363 numbits += 8; \
364 } \
365}
366
367/* extract bits from data stream
368 b = variable to store result, a = number of bits */
369#define GETBITS(b, a) \
370{ \
371 LOADBITS(a) \
372 b = (bitfield<<(64-numbits))>>(64-(a)); \
373 numbits -= (a); \
374}
375
376/* extract bits from data stream
377 b = variable to store result, a = number of bits */
378#define GETBITSSIGN(b, a) \
379{ \
380 LOADBITS(a) \
381 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
382 numbits -= (a); \
383}
384
385#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
386
387static int RTCM3Parser(struct RTCM3ParserData *handle)
388{
389 int ret=0;
390
391 while(!ret && GetMessage(handle))
392 {
393 /* using 64 bit integer types, as it is much easier than handling
394 the long datatypes in 32 bit */
395 uint64_t numbits = 0, bitfield = 0;
396 int size = handle->size, type;
397 unsigned char *data = handle->Message+3;
398
399 GETBITS(type,12)
400 switch(type)
401 {
402 case 1001: case 1002: case 1003: case 1004:
403 if(handle->GPSWeek)
404 {
405 int lastlockl1[64];
406 int lastlockl2[64];
407 struct gnssdata *gnss;
408 int i, num, wasamb=0;
409
410 for(i = 0; i < 64; ++i)
411 lastlockl1[i] = lastlockl2[i] = 0;
412
413 gnss = &handle->Data;
414 memset(gnss, 0, sizeof(*gnss));
415
416 SKIPBITS(12) /* id */
417 GETBITS(i,30)
418 if(i/1000 < (int)handle->GPSTOW - 86400)
419 ++handle->GPSWeek;
420 handle->GPSTOW = i/1000;
421 gnss->timeofweek = i;
422 gnss->week = handle->GPSWeek;
423
424 SKIPBITS(1) /* sync */
425 GETBITS(i,5)
426 gnss->numsats = i;
427 SKIPBITS(4) /* smind, smint */
428
429 for(num = 0; num < gnss->numsats; ++num)
430 {
431 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
432
433 GETBITS(sv, 6);
434 gnss->satellites[num] = (sv < 40 ? sv : sv+80);
435 /* L1 */
436 GETBITS(code, 1);
437 if(code)
438 {
439 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
440 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
441 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
442 }
443 else
444 {
445 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
446 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
447 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
448 }
449 GETBITS(l1range, 24);
450 if(l1range != 0x80000)
451 {
452 gnss->dataflags[num] |= c;
453 gnss->measdata[num][ce] = l1range*0.02;
454 }
455 GETBITSSIGN(i, 20);
456 if(i != 0x80000)
457 {
458 gnss->dataflags[num] |= l;
459 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
460 }
461 GETBITS(i, 7);
462 lastlockl1[sv] = i;
463 if(handle->lastlockl1[sv] > i)
464 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
465 if(type == 1002 || type == 1004)
466 {
467 GETBITS(amb,8);
468 if(amb && (gnss->dataflags[num] & c))
469 {
470 gnss->measdata[num][ce] += amb*299792.458;
471 gnss->measdata[num][le] += amb*299792.458;
472 ++wasamb;
473 }
474 GETBITS(i, 8);
475 if(i)
476 {
477 gnss->dataflags[num] |= s;
478 gnss->measdata[num][se] = i*0.25;
479 i /= 4*4;
480 if(i > 9) i = 9;
481 else if(i < 1) i = 1;
482 gnss->snrL1[num] = i;
483 }
484 }
485 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
486 if(type == 1003 || type == 1004)
487 {
488 /* L2 */
489 GETBITS(code,2);
490 if(code)
491 {
492 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
493 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
494 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
495 }
496 else
497 {
498 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
499 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
500 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
501 }
502 GETBITSSIGN(i,14);
503 if(i != 0x2000)
504 {
505 gnss->dataflags[num] |= c;
506 gnss->measdata[num][ce] = l1range*0.02+i*0.02
507 +amb*299792.458;
508 }
509 GETBITSSIGN(i,20);
510 if(i != 0x80000)
511 {
512 gnss->dataflags[num] |= l;
513 gnss->measdata[num][le] = l1range*0.02+i*0.0005
514 +amb*299792.458;
515 }
516 GETBITS(i,7);
517 lastlockl2[sv] = i;
518 if(handle->lastlockl2[sv] > i)
519 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
520 if(type == 1004)
521 {
522 GETBITS(i, 8);
523 if(i)
524 {
525 gnss->dataflags[num] |= s;
526 gnss->measdata[num][se] = i*0.25;
527 i /= 4*4;
528 if(i > 9) i = 9;
529 else if(i < 1) i = 1;
530 gnss->snrL2[num] = i;
531 }
532 }
533 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
534 }
535 }
536 for(i = 0; i < 64; ++i)
537 {
538 handle->lastlockl1[i] = lastlockl1[i];
539 handle->lastlockl2[i] = lastlockl2[i];
540 }
541 if(wasamb) /* not RINEX compatible without */
542 ret = 1;
543 else
544 ret = 2;
545 }
546 break;
547 }
548 }
549 return ret;
550}
551
552static int longyear(int year, int month)
553{
554 if(!(year % 4) && (!(year % 400) || (year % 100)))
555 {
556 if(!month || month == 2)
557 return 1;
558 }
559 return 0;
560}
561
562static void converttime(struct converttimeinfo *c, int week, int tow)
563{
564 /* static variables */
565 static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
566
567 int i, k, doy, j; /* temporary variables */
568 j = week*(7*24*60*60) + tow + 5*24*60*60;
569 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
570 j -= k;
571 c->year = i;
572 doy = 1+ (j / (24*60*60));
573 j %= (24*60*60);
574 c->hour = j / (60*60);
575 j %= (60*60);
576 c->minute = j / 60;
577 c->second = j % 60;
578 j = 0;
579 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
580 j += k;
581 c->month = i;
582 c->day = doy - j;
583}
584
585struct Header
586{
587 const char *version;
588 const char *pgm;
589 const char *marker;
590 const char *observer;
591 const char *receiver;
592 const char *antenna;
593 const char *position;
594 const char *antennaposition;
595 const char *wavelength;
596 const char *typesofobs; /* should not be modified outside */
597 const char *timeoffirstobs; /* should not be modified outside */
598};
599
600#define MAXHEADERLINES 50
601#define MAXHEADERBUFFERSIZE 4096
602struct HeaderData
603{
604 union
605 {
606 struct Header named;
607 const char *unnamed[MAXHEADERLINES];
608 } data;
609 int numheaders;
610};
611
612static void HandleHeader(struct RTCM3ParserData *Parser)
613{
614 struct HeaderData hdata;
615 char thebuffer[MAXHEADERBUFFERSIZE];
616 char *buffer = thebuffer;
617 int buffersize = sizeof(thebuffer);
618 int i;
619
620 hdata.data.named.version =
621 " 2.11 OBSERVATION DATA M (Mixed)"
622 " RINEX VERSION / TYPE";
623
624 {
625 const char *str;
626 time_t t;
627 struct tm * t2;
628
629 str = getenv("USER");
630 if(!str) str = "";
631 t = time(&t);
632 t2 = gmtime(&t);
633 hdata.data.named.pgm = buffer;
634 i = 1+snprintf(buffer, buffersize,
635 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
636 "PGM / RUN BY / DATE",
637 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour,
638 t2->tm_min);
639 buffer += i; buffersize -= i;
640
641 hdata.data.named.observer = buffer;
642 i = 1+snprintf(buffer, buffersize,
643 "%-20.20s "
644 "OBSERVER / AGENCY", str);
645 buffer += i; buffersize -= i;
646 }
647
648 hdata.data.named.marker =
649 "RTCM3TORINEX "
650 "MARKER NAME";
651
652 hdata.data.named.receiver =
653 " "
654 "REC # / TYPE / VERS";
655
656 hdata.data.named.antenna =
657 " "
658 "ANT # / TYPE";
659
660 hdata.data.named.position =
661 " .0000 .0000 .0000 "
662 "APPROX POSITION XYZ";
663
664 hdata.data.named.antennaposition =
665 " .0000 .0000 .0000 "
666 "ANTENNA: DELTA H/E/N";
667
668 hdata.data.named.wavelength =
669 " 1 1 "
670 "WAVELENGTH FACT L1/2";
671
672 {
673#define CHECKFLAGS(a, b) \
674 if(flags & GNSSDF_##a##DATA \
675 && !data[RINEXENTRY_##b##DATA]) \
676 { \
677 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \
678 Parser->datapos[Parser->numdatatypes++] = data[RINEXENTRY_##b##DATA] \
679 = GNSSENTRY_##a##DATA; \
680 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
681 tbufferpos += 6; \
682 }
683
684 int flags = 0;
685 int data[RINEXENTRY_NUMBER];
686 char tbuffer[6*RINEXENTRY_NUMBER+1];
687 int tbufferpos = 0;
688 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
689 data[i] = 0;
690 for(i = 0; i < Parser->Data.numsats; ++i)
691 flags |= Parser->Data.dataflags[i];
692
693 CHECKFLAGS(C1,C1)
694 CHECKFLAGS(C2,C2)
695 CHECKFLAGS(P1,P1)
696 CHECKFLAGS(P2,P2)
697 CHECKFLAGS(L1C,L1)
698 CHECKFLAGS(L1P,L1)
699 CHECKFLAGS(L2C,L2)
700 CHECKFLAGS(L2P,L2)
701 CHECKFLAGS(D1C,D1)
702 CHECKFLAGS(D1P,D1)
703 CHECKFLAGS(D2C,D2)
704 CHECKFLAGS(D2P,D2)
705 CHECKFLAGS(S1C,S1)
706 CHECKFLAGS(S1P,S1)
707 CHECKFLAGS(S2C,S2)
708 CHECKFLAGS(S2P,S2)
709
710 hdata.data.named.typesofobs = buffer;
711 i = 1+snprintf(buffer, buffersize,
712 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);
713 if(Parser->numdatatypes>9)
714 {
715 i += snprintf(buffer+i-1, buffersize,
716 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
717 }
718 buffer += i; buffersize -= i;
719 }
720
721 {
722 struct converttimeinfo cti;
723 converttime(&cti, Parser->Data.week,
724 floor(Parser->Data.timeofweek/1000.0));
725 hdata.data.named.timeoffirstobs = buffer;
726 i = 1+snprintf(buffer, buffersize,
727 " %4d %2d %2d %2d %2d %10.7f GPS "
728 "TIME OF FIRST OBS", cti.year%100, cti.month, cti.day, cti.hour,
729 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
730
731 buffer += i; buffersize -= i;
732 }
733
734 hdata.numheaders = 11;
735
736 if(Parser->headerfile)
737 {
738 FILE *fh;
739 if((fh = fopen(Parser->headerfile, "r")))
740 {
741 int siz;
742 char *lastblockstart;
743 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
744 {
745 buffer[siz] = '\n';
746 if(siz == buffersize)
747 {
748 fprintf(stderr, "Header file is too large. Only %d bytes read.",
749 siz);
750 }
751 /* scan the file line by line and enter the entries in the list */
752 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
753 /* overwrites entries, except for comments */
754 lastblockstart = buffer;
755 for(i = 0; i < siz; ++i)
756 {
757 if(buffer[i] == '\n')
758 { /* we found a line */
759 char *end;
760 while(buffer[i+1] == '\r')
761 ++i; /* skip \r in case there are any */
762 end = buffer+i;
763 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
764 *(end--) = 0;
765 if(end-lastblockstart < 60+5) /* short line */
766 fprintf(stderr, "Short Header line '%s' ignored.\n", lastblockstart);
767 else
768 {
769 int pos;
770 if(!strcmp("COMMENT", lastblockstart+60))
771 pos = hdata.numheaders;
772 else
773 {
774 for(pos = 0; pos < hdata.numheaders; ++pos)
775 {
776 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
777 break;
778 }
779 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
780 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
781 {
782 fprintf(stderr, "Overwriting header '%s' is dangerous.\n",
783 lastblockstart+60);
784 }
785 }
786 if(pos >= MAXHEADERLINES)
787 {
788 fprintf(stderr,
789 "Maximum number of header lines of %d reached.\n",
790 MAXHEADERLINES);
791 }
792 else if(!strcmp("END OF HEADER", lastblockstart+60))
793 {
794 fprintf(stderr, "End of header ignored.\n");
795 }
796 else
797 {
798 hdata.data.unnamed[pos] = lastblockstart;
799 if(pos == hdata.numheaders)
800 ++hdata.numheaders;
801 }
802 }
803 lastblockstart = buffer+i+1;
804 }
805 }
806 }
807 else
808 {
809 fprintf(stderr, "Could not read data from headerfile '%s'.\n",
810 Parser->headerfile);
811 }
812 fclose(fh);
813 }
814 else
815 {
816 fprintf(stderr, "Could not open header datafile '%s'.\n",
817 Parser->headerfile);
818 }
819 }
820
821 for(i = 0; i < hdata.numheaders; ++i)
822 printf("%s\n", hdata.data.unnamed[i]);
823 printf(" "
824 "END OF HEADER\n");
825}
826
827/* let the output complete a block if necessary */
828static void signalhandler(int sig)
829{
830 if(!stop)
831 {
832 fprintf(stderr, "Stop signal number %d received. "
833 "Trying to terminate gentle.\n", sig);
834 stop = 1;
835 alarm(1);
836 }
837}
838
839/* for some reason we had to abort hard (maybe waiting for data */
840#ifdef __GNUC__
841static __attribute__ ((noreturn)) void signalhandler_alarm(
842int sig __attribute__((__unused__)))
843#else /* __GNUC__ */
844static void signalhandler_alarm(int sig)
845#endif /* __GNUC__ */
846{
847 fprintf(stderr, "Programm forcefully terminated.\n");
848 exit(1);
849}
850
851static void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
852{
853 Parser->Message[Parser->MessageSize++] = byte;
854 if(Parser->MessageSize >= Parser->NeedBytes)
855 {
856 int r;
857 while((r = RTCM3Parser(Parser)))
858 {
859 int i, j, o;
860 struct converttimeinfo cti;
861
862 if(!Parser->init)
863 {
864 HandleHeader(Parser);
865 Parser->init = 1;
866 }
867 if(r == 2 && !Parser->validwarning)
868 {
869 printf("No valid RINEX! All values are modulo 299792.458!"
870 " COMMENT\n");
871 Parser->validwarning = 1;
872 }
873
874 converttime(&cti, Parser->Data.week,
875 floor(Parser->Data.timeofweek/1000.0));
876 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",
877 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
878 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
879 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
880 {
881 if(Parser->Data.satellites[i] <= PRN_GPS_END)
882 printf("G%02d", Parser->Data.satellites[i]);
883 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
884 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
885 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
886 else
887 printf("%3d", Parser->Data.satellites[i]);
888 }
889 printf("\n");
890 o = 12;
891 j = Parser->Data.numsats - 12;
892 while(j > 0)
893 {
894 printf(" ");
895 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
896 {
897 if(Parser->Data.satellites[i] <= PRN_GPS_END)
898 printf("G%02d", Parser->Data.satellites[i]);
899 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
900 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
901 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
902 else
903 printf("%3d", Parser->Data.satellites[i]);
904 }
905 printf("\n");
906 j -= 12;
907 o += 12;
908 }
909 for(i = 0; i < Parser->Data.numsats; ++i)
910 {
911 for(j = 0; j < Parser->numdatatypes; ++j)
912 {
913 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
914 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
915 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
916 { /* no or illegal data */
917 printf(" ");
918 }
919 else
920 {
921 char lli = ' ';
922 char snr = ' ';
923 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
924 {
925 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
926 lli = '1';
927 snr = '0'+Parser->Data.snrL1[i];
928 }
929 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
930 {
931 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
932 lli = '1';
933 snr = '0'+Parser->Data.snrL2[i];
934 }
935 printf("%14.3f%c%c",
936 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
937 }
938 if(j%5 == 4 || j == Parser->numdatatypes-1)
939 printf("\n");
940 }
941 }
942 }
943 }
944}
945
946int main(int argc, char **argv)
947{
948 struct Args args;
949 struct RTCM3ParserData Parser;
950
951 setbuf(stdout, 0);
952 setbuf(stdin, 0);
953 setbuf(stderr, 0);
954
955 {
956 char *a;
957 int i=0;
958 for(a = revisionstr+11; *a && *a != ' '; ++a)
959 revisionstr[i++] = *a;
960 revisionstr[i] = 0;
961 }
962
963 signal(SIGINT, signalhandler);
964 signal(SIGALRM,signalhandler_alarm);
965 signal(SIGQUIT,signalhandler);
966 signal(SIGTERM,signalhandler);
967 signal(SIGPIPE,signalhandler);
968 memset(&Parser, 0, sizeof(Parser));
969 {
970 time_t tim;
971 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
972 Parser.GPSWeek = tim/(7*24*60*60);
973 Parser.GPSTOW = tim%(7*24*60*60);
974 }
975
976 if(getargs(argc, argv, &args))
977 {
978 int i, sockfd, numbytes;
979 char buf[MAXDATASIZE];
980 struct hostent *he;
981 struct sockaddr_in their_addr; /* connector's address information */
982
983 Parser.headerfile = args.headerfile;
984
985 if(!(he=gethostbyname(args.server)))
986 {
987 perror("gethostbyname");
988 exit(1);
989 }
990 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
991 {
992 perror("socket");
993 exit(1);
994 }
995 their_addr.sin_family = AF_INET; /* host byte order */
996 their_addr.sin_port = htons(args.port); /* short, network byte order */
997 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
998 memset(&(their_addr.sin_zero), '\0', 8);
999 if(connect(sockfd, (struct sockaddr *)&their_addr,
1000 sizeof(struct sockaddr)) == -1)
1001 {
1002 perror("connect");
1003 exit(1);
1004 }
1005
1006 if(!args.data)
1007 {
1008 i = snprintf(buf, MAXDATASIZE,
1009 "GET / HTTP/1.0\r\n"
1010 "User-Agent: %s/%s\r\n"
1011#ifdef UNUSED
1012 "Accept: */*\r\n"
1013 "Connection: close\r\n"
1014#endif
1015 "\r\n"
1016 , AGENTSTRING, revisionstr);
1017 }
1018 else
1019 {
1020 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1021 "GET /%s HTTP/1.0\r\n"
1022 "User-Agent: %s/%s\r\n"
1023#ifdef UNUSED
1024 "Accept: */*\r\n"
1025 "Connection: close\r\n"
1026#endif
1027 "Authorization: Basic "
1028 , args.data, AGENTSTRING, revisionstr);
1029 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
1030 {
1031 fprintf(stderr, "Requested data too long\n");
1032 exit(1);
1033 }
1034 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
1035 if(i > MAXDATASIZE-5)
1036 {
1037 fprintf(stderr, "Username and/or password too long\n");
1038 exit(1);
1039 }
1040 snprintf(buf+i, 5, "\r\n\r\n");
1041 i += 5;
1042 }
1043 if(send(sockfd, buf, (size_t)i, 0) != i)
1044 {
1045 perror("send");
1046 exit(1);
1047 }
1048 if(args.data)
1049 {
1050 int k = 0;
1051 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1052 {
1053 if(!k)
1054 {
1055 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1056 {
1057 fprintf(stderr, "Could not get the requested data: ");
1058 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1059 {
1060 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');
1061 }
1062 fprintf(stderr, "\n");
1063 exit(1);
1064 }
1065 ++k;
1066 }
1067 else
1068 {
1069 int z;
1070 for(z = 0; z < numbytes && !stop; ++z)
1071 HandleByte(&Parser, buf[z]);
1072 }
1073 }
1074 }
1075 else
1076 {
1077 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1078 {
1079 fwrite(buf, (size_t)numbytes, 1, stdout);
1080 }
1081 }
1082
1083 close(sockfd);
1084 }
1085 return 0;
1086}
Note: See TracBrowser for help on using the repository browser.