source: ntrip/trunk/BNC/RTCM3/rtcm3torinex.cpp@ 222

Last change on this file since 222 was 131, checked in by mervart, 18 years ago

* empty log message *

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