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

Last change on this file since 112 was 99, 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.6 2006/09/02 12:23:05 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.6 $";
69static char datestr[] = "$Date: 2006/09/02 12:23:05 $";
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 for(i = 0; i < hdata.numheaders; ++i)
743 printf("%s\n", hdata.data.unnamed[i]);
744 printf(" "
745 "END OF HEADER\n");
746}
747
748#ifndef NO_RTCM3_MAIN
749
750/* let the output complete a block if necessary */
751static void signalhandler(int sig)
752{
753 if(!stop)
754 {
755 fprintf(stderr, "Stop signal number %d received. "
756 "Trying to terminate gentle.\n", sig);
757 stop = 1;
758 alarm(1);
759 }
760}
761
762static void signalhandler_alarm(int sig)
763{
764 fprintf(stderr, "Programm forcefully terminated.\n");
765 exit(1);
766}
767
768void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
769{
770 Parser->Message[Parser->MessageSize++] = byte;
771 if(Parser->MessageSize >= Parser->NeedBytes)
772 {
773 int r;
774 while((r = RTCM3Parser(Parser)))
775 {
776 int i, j, o;
777 struct converttimeinfo cti;
778
779 if(!Parser->init)
780 {
781 HandleHeader(Parser);
782 Parser->init = 1;
783 }
784 if(r == 2 && !Parser->validwarning)
785 {
786 printf("No valid RINEX! All values are modulo 299792.458!"
787 " COMMENT\n");
788 Parser->validwarning = 1;
789 }
790
791 converttime(&cti, Parser->Data.week,
792 floor(Parser->Data.timeofweek/1000.0));
793 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",
794 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
795 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
796 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
797 {
798 if(Parser->Data.satellites[i] <= PRN_GPS_END)
799 printf("G%02d", Parser->Data.satellites[i]);
800 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
801 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
802 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
803 else
804 printf("%3d", Parser->Data.satellites[i]);
805 }
806 printf("\n");
807 o = 12;
808 j = Parser->Data.numsats - 12;
809 while(j > 0)
810 {
811 printf(" ");
812 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
813 {
814 if(Parser->Data.satellites[i] <= PRN_GPS_END)
815 printf("G%02d", Parser->Data.satellites[i]);
816 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
817 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
818 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
819 else
820 printf("%3d", Parser->Data.satellites[i]);
821 }
822 printf("\n");
823 j -= 12;
824 o += 12;
825 }
826 for(i = 0; i < Parser->Data.numsats; ++i)
827 {
828 for(j = 0; j < Parser->numdatatypes; ++j)
829 {
830 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
831 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
832 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
833 { /* no or illegal data */
834 printf(" ");
835 }
836 else
837 {
838 char lli = ' ';
839 char snr = ' ';
840 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
841 {
842 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
843 lli = '1';
844 snr = '0'+Parser->Data.snrL1[i];
845 }
846 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
847 {
848 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
849 lli = '1';
850 snr = '0'+Parser->Data.snrL2[i];
851 }
852 printf("%14.3f%c%c",
853 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
854 }
855 if(j%5 == 4 || j == Parser->numdatatypes-1)
856 printf("\n");
857 }
858 }
859 }
860 }
861}
862
863int main(int argc, char **argv)
864{
865 struct Args args;
866 struct RTCM3ParserData Parser;
867
868 setbuf(stdout, 0);
869 setbuf(stdin, 0);
870 setbuf(stderr, 0);
871
872 {
873 char *a;
874 int i=0;
875 for(a = revisionstr+11; *a && *a != ' '; ++a)
876 revisionstr[i++] = *a;
877 revisionstr[i] = 0;
878 }
879
880 signal(SIGINT, signalhandler);
881 signal(SIGALRM,signalhandler_alarm);
882 signal(SIGQUIT,signalhandler);
883 signal(SIGTERM,signalhandler);
884 signal(SIGPIPE,signalhandler);
885 memset(&Parser, 0, sizeof(Parser));
886 {
887 time_t tim;
888 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
889 Parser.GPSWeek = tim/(7*24*60*60);
890 Parser.GPSTOW = tim%(7*24*60*60);
891 }
892
893 if(getargs(argc, argv, &args))
894 {
895 int i, sockfd, numbytes;
896 char buf[MAXDATASIZE];
897 struct hostent *he;
898 struct sockaddr_in their_addr; /* connector's address information */
899
900 Parser.headerfile = args.headerfile;
901
902 if(!(he=gethostbyname(args.server)))
903 {
904 perror("gethostbyname");
905 exit(1);
906 }
907 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
908 {
909 perror("socket");
910 exit(1);
911 }
912 their_addr.sin_family = AF_INET; /* host byte order */
913 their_addr.sin_port = htons(args.port); /* short, network byte order */
914 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
915 memset(&(their_addr.sin_zero), '\0', 8);
916 if(connect(sockfd, (struct sockaddr *)&their_addr,
917 sizeof(struct sockaddr)) == -1)
918 {
919 perror("connect");
920 exit(1);
921 }
922
923 if(!args.data)
924 {
925 i = snprintf(buf, MAXDATASIZE,
926 "GET / HTTP/1.0\r\n"
927 "User-Agent: %s/%s\r\n"
928#ifdef UNUSED
929 "Accept: */*\r\n"
930 "Connection: close\r\n"
931#endif
932 "\r\n"
933 , AGENTSTRING, revisionstr);
934 }
935 else
936 {
937 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
938 "GET /%s HTTP/1.0\r\n"
939 "User-Agent: %s/%s\r\n"
940#ifdef UNUSED
941 "Accept: */*\r\n"
942 "Connection: close\r\n"
943#endif
944 "Authorization: Basic "
945 , args.data, AGENTSTRING, revisionstr);
946 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
947 {
948 fprintf(stderr, "Requested data too long\n");
949 exit(1);
950 }
951 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
952 if(i > MAXDATASIZE-5)
953 {
954 fprintf(stderr, "Username and/or password too long\n");
955 exit(1);
956 }
957 snprintf(buf+i, 5, "\r\n\r\n");
958 i += 5;
959 }
960 if(send(sockfd, buf, (size_t)i, 0) != i)
961 {
962 perror("send");
963 exit(1);
964 }
965 if(args.data)
966 {
967 int k = 0;
968 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
969 {
970 if(!k)
971 {
972 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
973 {
974 fprintf(stderr, "Could not get the requested data: ");
975 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
976 {
977 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');
978 }
979 fprintf(stderr, "\n");
980 exit(1);
981 }
982 ++k;
983 }
984 else
985 {
986 int z;
987 for(z = 0; z < numbytes && !stop; ++z)
988 HandleByte(&Parser, buf[z]);
989 }
990 }
991 }
992 else
993 {
994 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
995 {
996 fwrite(buf, (size_t)numbytes, 1, stdout);
997 }
998 }
999
1000 close(sockfd);
1001 }
1002 return 0;
1003}
1004
1005#endif // NO_RTCM3_MAIN
Note: See TracBrowser for help on using the repository browser.