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

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

* empty log message *

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