source: ntrip/trunk/rtcm3torinex/rtcm3torinex.c@ 28

Last change on this file since 28 was 27, checked in by stoecker, 18 years ago

added rtcm3torinex

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