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

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