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

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