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

Last change on this file since 278 was 270, checked in by stoecker, 18 years ago

added GLONASS

File size: 36.8 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.7 2006/11/02 13:54:43 stoecker Exp $
4 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@euronik.eu>
5
6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7 a module of the BNC tool for multiformat conversion. Contact Dirk
8 Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9 conversion problems and the author of BNC for all the other problems.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <sys/types.h>
35#include <time.h>
36#include <unistd.h>
37
38#ifndef NO_RTCM3_MAIN
39#include <getopt.h>
40#include <netdb.h>
41#include <netinet/in.h>
42#include <sys/socket.h>
43#endif
44
45#ifndef sparc
46#include <stdint.h>
47#endif
48
49#include "rtcm3torinex.h"
50
51/* CVS revision and version */
52static char revisionstr[] = "$Revision: 1.7 $";
53
54static uint32_t CRC24(long size, const unsigned char *buf)
55{
56 uint32_t crc = 0;
57 int i;
58
59 while(size--)
60 {
61 crc ^= (*buf++) << (16);
62 for(i = 0; i < 8; i++)
63 {
64 crc <<= 1;
65 if(crc & 0x1000000)
66 crc ^= 0x01864cfb;
67 }
68 }
69 return crc;
70}
71
72static int GetMessage(struct RTCM3ParserData *handle)
73{
74 unsigned char *m, *e;
75 int i;
76
77 m = handle->Message+handle->SkipBytes;
78 e = handle->Message+handle->MessageSize;
79 handle->NeedBytes = handle->SkipBytes = 0;
80 while(e-m >= 3)
81 {
82 if(m[0] == 0xD3)
83 {
84 handle->size = ((m[1]&3)<<8)|m[2];
85 if(e-m >= handle->size+6)
86 {
87 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
88 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
89 {
90 handle->SkipBytes = handle->size;
91 break;
92 }
93 else
94 ++m;
95 }
96 else
97 {
98 handle->NeedBytes = handle->size+6;
99 break;
100 }
101 }
102 else
103 ++m;
104 }
105 if(e-m < 3)
106 handle->NeedBytes = 3;
107
108 /* copy buffer to front */
109 i = m - handle->Message;
110 if(i && m < e)
111 memmove(handle->Message, m, handle->MessageSize-i);
112 handle->MessageSize -= i;
113
114 return !handle->NeedBytes;
115}
116
117#define LOADBITS(a) \
118{ \
119 while((a) > numbits) \
120 { \
121 if(!size--) break; \
122 bitfield = (bitfield<<8)|*(data++); \
123 numbits += 8; \
124 } \
125}
126
127/* extract bits from data stream
128 b = variable to store result, a = number of bits */
129#define GETBITS(b, a) \
130{ \
131 LOADBITS(a) \
132 b = (bitfield<<(64-numbits))>>(64-(a)); \
133 numbits -= (a); \
134}
135
136/* extract bits from data stream
137 b = variable to store result, a = number of bits */
138#define GETBITSSIGN(b, a) \
139{ \
140 LOADBITS(a) \
141 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
142 numbits -= (a); \
143}
144
145#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
146
147struct leapseconds { /* specify the day of leap second */
148 int day; /* this is the day, where 23:59:59 exists 2 times */
149 int month; /* not the next day! */
150 int year;
151 int taicount;
152};
153static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
154static const struct leapseconds leap[] = {
155/*{31, 12, 1971, 11},*/
156/*{31, 12, 1972, 12},*/
157/*{31, 12, 1973, 13},*/
158/*{31, 12, 1974, 14},*/
159/*{31, 12, 1975, 15},*/
160/*{31, 12, 1976, 16},*/
161/*{31, 12, 1977, 17},*/
162/*{31, 12, 1978, 18},*/
163/*{31, 12, 1979, 19},*/
164{30, 06, 1981,20},
165{30, 06, 1982,21},
166{30, 06, 1983,22},
167{30, 06, 1985,23},
168{31, 12, 1987,24},
169{31, 12, 1989,25},
170{31, 12, 1990,26},
171{30, 06, 1992,27},
172{30, 06, 1993,28},
173{30, 06, 1994,29},
174{31, 12, 1995,30},
175{30, 06, 1997,31},
176{31, 12, 1998,32},
177{31, 12, 2005,33},
178{0,0,0,0} /* end marker */
179};
180#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
181
182static int longyear(int year, int month)
183{
184 if(!(year % 4) && (!(year % 400) || (year % 100)))
185 {
186 if(!month || month == 2)
187 return 1;
188 }
189 return 0;
190}
191
192static int gnumleap(int year, int month, int day)
193{
194 int ls = 0;
195 const struct leapseconds *l;
196
197 for(l = leap; l->taicount && year >= l->year; ++l)
198 {
199 if(year > l->year || month > l->month || day > l->day)
200 ls = l->taicount - GPSLEAPSTART;
201 }
202 return ls;
203}
204
205static void updatetime(int *week, int *tow, int tk)
206{
207 int y,m,d,k,l;
208 unsigned int j = *week*(7*24*60*60) + *tow + 5*24*60*60+3*60*60;
209 int glo_daynumber = 0, glo_timeofday;
210 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
211 + gnumleap(y+1,1,1); ++y)
212 {
213 j -= k; glo_daynumber += l;
214 }
215 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
216 + gnumleap(y, m+1, 1); ++m)
217 {
218 j -= k; glo_daynumber += l;
219 }
220 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
221 j -= 24*60*60;
222 glo_daynumber -= 16*365+4-d;
223 glo_timeofday = j-gnumleap(y, m, d);
224
225 if(tk < 5*60*1000 && glo_timeofday > 23*60*60)
226 *tow += 24*60*60;
227 else if(glo_timeofday < 5*60 && tk > 23*60*60*1000)
228 *tow -= 24*60*60;
229 *tow += tk/1000-glo_timeofday;
230 if(*tow < 0) {*tow += 24*60*60*7; --*week; }
231 if(*tow >= 24*60*60*7) {*tow -= 24*60*60*7; ++*week; }
232}
233
234int RTCM3Parser(struct RTCM3ParserData *handle)
235{
236 int ret=0;
237
238 while(!ret && GetMessage(handle))
239 {
240 /* using 64 bit integer types, as it is much easier than handling
241 the long datatypes in 32 bit */
242 uint64_t numbits = 0, bitfield = 0;
243 int size = handle->size, type;
244 int syncf, old = 0;
245 unsigned char *data = handle->Message+3;
246
247 GETBITS(type,12)
248 switch(type)
249 {
250 case 1001: case 1002: case 1003: case 1004:
251 if(handle->GPSWeek)
252 {
253 int lastlockl1[64];
254 int lastlockl2[64];
255 struct gnssdata *gnss;
256 int i, num, wasamb=0;
257
258 for(i = 0; i < 64; ++i)
259 lastlockl1[i] = lastlockl2[i] = 0;
260
261 gnss = &handle->DataNew;
262
263 SKIPBITS(12) /* id */
264 GETBITS(i,30)
265 if(i/1000 < (int)handle->GPSTOW - 86400)
266 ++handle->GPSWeek;
267 handle->GPSTOW = i/1000;
268 if(gnss->week && (gnss->timeofweek != i || gnss->week
269 != handle->GPSWeek))
270 {
271 handle->Data = *gnss;
272 memset(gnss, 0, sizeof(*gnss));
273 old = 1;
274 }
275 gnss->timeofweek = i;
276 gnss->week = handle->GPSWeek;
277
278 GETBITS(syncf,1) /* sync */
279 GETBITS(i,5)
280 gnss->numsats = i;
281 SKIPBITS(4) /* smind, smint */
282
283 for(num = 0; num < gnss->numsats; ++num)
284 {
285 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
286
287 GETBITS(sv, 6);
288 gnss->satellites[num] = (sv < 40 ? sv : sv+80);
289 /* L1 */
290 GETBITS(code, 1);
291 if(code)
292 {
293 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
294 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
295 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
296 }
297 else
298 {
299 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
300 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
301 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
302 }
303 GETBITS(l1range, 24);
304 if(l1range != 0x80000)
305 {
306 gnss->dataflags[num] |= c;
307 gnss->measdata[num][ce] = l1range*0.02;
308 }
309 GETBITSSIGN(i, 20);
310 if(i != 0x80000)
311 {
312 gnss->dataflags[num] |= l;
313 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
314 }
315 GETBITS(i, 7);
316 lastlockl1[sv] = i;
317 if(handle->lastlockl1[sv] > i)
318 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
319 if(type == 1002 || type == 1004)
320 {
321 GETBITS(amb,8);
322 if(amb && (gnss->dataflags[num] & c))
323 {
324 gnss->measdata[num][ce] += amb*299792.458;
325 gnss->measdata[num][le] += amb*299792.458;
326 ++wasamb;
327 }
328 GETBITS(i, 8);
329 if(i)
330 {
331 gnss->dataflags[num] |= s;
332 gnss->measdata[num][se] = i*0.25;
333 i /= 4*4;
334 if(i > 9) i = 9;
335 else if(i < 1) i = 1;
336 gnss->snrL1[num] = i;
337 }
338 }
339 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
340 if(type == 1003 || type == 1004)
341 {
342 /* L2 */
343 GETBITS(code,2);
344 if(code)
345 {
346 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
347 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
348 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
349 }
350 else
351 {
352 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
353 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
354 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
355 }
356 GETBITSSIGN(i,14);
357 if(i != 0x2000)
358 {
359 gnss->dataflags[num] |= c;
360 gnss->measdata[num][ce] = l1range*0.02+i*0.02
361 +amb*299792.458;
362 }
363 GETBITSSIGN(i,20);
364 if(i != 0x80000)
365 {
366 gnss->dataflags[num] |= l;
367 gnss->measdata[num][le] = l1range*0.02+i*0.0005
368 +amb*299792.458;
369 }
370 GETBITS(i,7);
371 lastlockl2[sv] = i;
372 if(handle->lastlockl2[sv] > i)
373 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
374 if(type == 1004)
375 {
376 GETBITS(i, 8);
377 if(i)
378 {
379 gnss->dataflags[num] |= s;
380 gnss->measdata[num][se] = i*0.25;
381 i /= 4*4;
382 if(i > 9) i = 9;
383 else if(i < 1) i = 1;
384 gnss->snrL2[num] = i;
385 }
386 }
387 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
388 }
389 }
390 for(i = 0; i < 64; ++i)
391 {
392 handle->lastlockl1[i] = lastlockl1[i];
393 handle->lastlockl2[i] = lastlockl2[i];
394 }
395 if(!syncf && !old)
396 {
397 handle->Data = *gnss;
398 memset(gnss, 0, sizeof(*gnss));
399 }
400 if(!syncf || old)
401 {
402 if(wasamb) /* not RINEX compatible without */
403 ret = 1;
404 else
405 ret = 2;
406 }
407 }
408 break;
409 case 1009: case 1010: case 1011: case 1012:
410 {
411 int lastlockl1[64];
412 int lastlockl2[64];
413 struct gnssdata *gnss;
414 int i, num;
415 int wasamb=0;
416
417 for(i = 0; i < 64; ++i)
418 lastlockl1[i] = lastlockl2[i] = 0;
419
420 gnss = &handle->DataNew;
421
422 SKIPBITS(12) /* id */;
423 GETBITS(i,27) /* tk */
424
425 updatetime(&handle->GPSWeek, &handle->GPSTOW, i);
426 i = handle->GPSTOW*1000;
427 if(gnss->week && (gnss->timeofweek != i || gnss->week
428 != handle->GPSWeek))
429 {
430 handle->Data = *gnss;
431 memset(gnss, 0, sizeof(*gnss));
432 old = 1;
433 }
434
435 gnss->timeofweek = i;
436 gnss->week = handle->GPSWeek;
437
438 GETBITS(syncf,1) /* sync */
439 GETBITS(i,5)
440 gnss->numsats += i;
441
442 SKIPBITS(4) /* smind, smint */
443
444 for(num = gnss->numsats-i; num < gnss->numsats; ++num)
445 {
446 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
447
448 GETBITS(sv, 6)
449 if(!sv || sv > 24)
450 {
451 --num; --gnss->numsats;
452 }
453 else
454 {
455 int freq;
456 gnss->satellites[num] = sv-1 + PRN_GLONASS_START;
457 /* L1 */
458 GETBITS(code, 1)
459 GETBITS(freq, 5)
460 if(code)
461 {
462 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
463 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
464 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
465 }
466 else
467 {
468 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
469 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
470 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
471 }
472 GETBITS(l1range, 25)
473 if(l1range != 0x80000)
474 {
475 gnss->dataflags[num] |= c;
476 gnss->measdata[num][ce] = l1range*0.02;
477 }
478 GETBITSSIGN(i, 20)
479 if(i != 0x80000)
480 {
481 gnss->dataflags[num] |= l;
482 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
483 }
484 GETBITS(i, 7)
485 lastlockl1[sv] = i;
486 if(handle->lastlockl1[sv] > i)
487 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
488 if(type == 1010 || type == 1012)
489 {
490 GETBITS(amb,7)
491 if(amb && (gnss->dataflags[num] & c))
492 {
493 gnss->measdata[num][ce] += amb*599584.916;
494 gnss->measdata[num][le] += amb*599584.916;
495 ++wasamb;
496 }
497 GETBITS(i, 8)
498 if(i)
499 {
500 gnss->dataflags[num] |= s;
501 gnss->measdata[num][se] = i*0.25;
502 i /= 4*4;
503 if(i > 9) i = 9;
504 else if(i < 1) i = 1;
505 gnss->snrL1[num] = i;
506 }
507 }
508 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
509 if(type == 1011 || type == 1012)
510 {
511 /* L2 */
512 GETBITS(code,2)
513 if(code)
514 {
515 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
516 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
517 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
518 }
519 else
520 {
521 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
522 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
523 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
524 }
525 GETBITSSIGN(i,14)
526 if(i != 0x2000)
527 {
528 gnss->dataflags[num] |= c;
529 gnss->measdata[num][ce] = l1range*0.02+i*0.02
530 +amb*599584.916;
531 }
532 GETBITSSIGN(i,20)
533 if(i != 0x80000)
534 {
535 gnss->dataflags[num] |= l;
536 gnss->measdata[num][le] = l1range*0.02+i*0.0005
537 +amb*599584.915;
538 }
539 GETBITS(i,7)
540 lastlockl2[sv] = i;
541 if(handle->lastlockl2[sv] > i)
542 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
543 if(type == 1012)
544 {
545 GETBITS(i, 8)
546 if(i)
547 {
548 gnss->dataflags[num] |= s;
549 gnss->measdata[num][se] = i*0.25;
550 i /= 4*4;
551 if(i > 9) i = 9;
552 else if(i < 1) i = 1;
553 gnss->snrL2[num] = i;
554 }
555 }
556 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
557 }
558 }
559 }
560 for(i = 0; i < 64; ++i)
561 {
562 handle->lastlockl1[i] = lastlockl1[i];
563 handle->lastlockl2[i] = lastlockl2[i];
564 }
565 if(!syncf && !old)
566 {
567 handle->Data = *gnss;
568 memset(gnss, 0, sizeof(*gnss));
569 }
570 if(!syncf || old)
571 {
572 if(wasamb) /* not RINEX compatible without */
573 ret = 1;
574 else
575 ret = 2;
576 }
577 }
578 break;
579 }
580 }
581 return ret;
582}
583
584struct Header
585{
586 const char *version;
587 const char *pgm;
588 const char *marker;
589 const char *observer;
590 const char *receiver;
591 const char *antenna;
592 const char *position;
593 const char *antennaposition;
594 const char *wavelength;
595 const char *typesofobs; /* should not be modified outside */
596 const char *timeoffirstobs; /* should not be modified outside */
597};
598
599#define MAXHEADERLINES 50
600#define MAXHEADERBUFFERSIZE 4096
601struct HeaderData
602{
603 union
604 {
605 struct Header named;
606 const char *unnamed[MAXHEADERLINES];
607 } data;
608 int numheaders;
609};
610
611struct converttimeinfo {
612 int second; /* seconds of GPS time [0..59] */
613 int minute; /* minutes of GPS time [0..59] */
614 int hour; /* hour of GPS time [0..24] */
615 int day; /* day of GPS time [1..28..30(31)*/
616 int month; /* month of GPS time [1..12]*/
617 int year; /* year of GPS time [1980..] */
618};
619
620static void converttime(struct converttimeinfo *c, int week, int tow)
621{
622 int i, k, doy, j; /* temporary variables */
623 j = week*(7*24*60*60) + tow + 5*24*60*60;
624 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
625 j -= k;
626 c->year = i;
627 doy = 1+ (j / (24*60*60));
628 j %= (24*60*60);
629 c->hour = j / (60*60);
630 j %= (60*60);
631 c->minute = j / 60;
632 c->second = j % 60;
633 j = 0;
634 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
635 j += k;
636 c->month = i;
637 c->day = doy - j;
638}
639
640void HandleHeader(struct RTCM3ParserData *Parser)
641{
642 struct HeaderData hdata;
643 char thebuffer[MAXHEADERBUFFERSIZE];
644 char *buffer = thebuffer;
645 int buffersize = sizeof(thebuffer);
646 int i;
647
648 hdata.data.named.version =
649 " 2.11 OBSERVATION DATA M (Mixed)"
650 " RINEX VERSION / TYPE";
651
652 {
653 const char *str;
654 time_t t;
655 struct tm * t2;
656
657#ifdef NO_RTCM3_MAIN
658 if(revisionstr[0] == '$')
659 {
660 char *a;
661 int i=0;
662 for(a = revisionstr+11; *a && *a != ' '; ++a)
663 revisionstr[i++] = *a;
664 revisionstr[i] = 0;
665 }
666#endif
667
668 str = getenv("USER");
669 if(!str) str = "";
670 t = time(&t);
671 t2 = gmtime(&t);
672 hdata.data.named.pgm = buffer;
673 i = 1+snprintf(buffer, buffersize,
674 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
675 "PGM / RUN BY / DATE",
676 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour,
677 t2->tm_min);
678 buffer += i; buffersize -= i;
679
680 hdata.data.named.observer = buffer;
681 i = 1+snprintf(buffer, buffersize,
682 "%-20.20s "
683 "OBSERVER / AGENCY", str);
684 buffer += i; buffersize -= i;
685 }
686
687 hdata.data.named.marker =
688 "RTCM3TORINEX "
689 "MARKER NAME";
690
691 hdata.data.named.receiver =
692 " "
693 "REC # / TYPE / VERS";
694
695 hdata.data.named.antenna =
696 " "
697 "ANT # / TYPE";
698
699 hdata.data.named.position =
700 " .0000 .0000 .0000 "
701 "APPROX POSITION XYZ";
702
703 hdata.data.named.antennaposition =
704 " .0000 .0000 .0000 "
705 "ANTENNA: DELTA H/E/N";
706
707 hdata.data.named.wavelength =
708 " 1 1 "
709 "WAVELENGTH FACT L1/2";
710
711 {
712#define CHECKFLAGS(a, b) \
713 if(flags & GNSSDF_##a##DATA \
714 && !data[RINEXENTRY_##b##DATA]) \
715 { \
716 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \
717 Parser->datapos[Parser->numdatatypes++] = data[RINEXENTRY_##b##DATA] \
718 = GNSSENTRY_##a##DATA; \
719 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
720 tbufferpos += 6; \
721 }
722
723 int flags = 0;
724 int data[RINEXENTRY_NUMBER];
725 char tbuffer[6*RINEXENTRY_NUMBER+1];
726 int tbufferpos = 0;
727 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
728 data[i] = 0;
729 for(i = 0; i < Parser->Data.numsats; ++i)
730 flags |= Parser->Data.dataflags[i];
731
732 CHECKFLAGS(C1,C1)
733 CHECKFLAGS(C2,C2)
734 CHECKFLAGS(P1,P1)
735 CHECKFLAGS(P2,P2)
736 CHECKFLAGS(L1C,L1)
737 CHECKFLAGS(L1P,L1)
738 CHECKFLAGS(L2C,L2)
739 CHECKFLAGS(L2P,L2)
740 CHECKFLAGS(D1C,D1)
741 CHECKFLAGS(D1P,D1)
742 CHECKFLAGS(D2C,D2)
743 CHECKFLAGS(D2P,D2)
744 CHECKFLAGS(S1C,S1)
745 CHECKFLAGS(S1P,S1)
746 CHECKFLAGS(S2C,S2)
747 CHECKFLAGS(S2P,S2)
748
749 hdata.data.named.typesofobs = buffer;
750 i = 1+snprintf(buffer, buffersize,
751 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);
752 if(Parser->numdatatypes>9)
753 {
754 i += snprintf(buffer+i-1, buffersize,
755 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
756 }
757 buffer += i; buffersize -= i;
758 }
759
760 {
761 struct converttimeinfo cti;
762 converttime(&cti, Parser->Data.week,
763 (int)floor(Parser->Data.timeofweek/1000.0));
764 hdata.data.named.timeoffirstobs = buffer;
765 i = 1+snprintf(buffer, buffersize,
766 " %4d %2d %2d %2d %2d %10.7f GPS "
767 "TIME OF FIRST OBS", cti.year%100, cti.month, cti.day, cti.hour,
768 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
769
770 buffer += i; buffersize -= i;
771 }
772
773 hdata.numheaders = 11;
774
775 if(Parser->headerfile)
776 {
777 FILE *fh;
778 if((fh = fopen(Parser->headerfile, "r")))
779 {
780 int siz;
781 char *lastblockstart;
782 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
783 {
784 buffer[siz] = '\n';
785 if(siz == buffersize)
786 {
787 fprintf(stderr, "Header file is too large. Only %d bytes read.",
788 siz);
789 }
790 /* scan the file line by line and enter the entries in the list */
791 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
792 /* overwrites entries, except for comments */
793 lastblockstart = buffer;
794 for(i = 0; i < siz; ++i)
795 {
796 if(buffer[i] == '\n')
797 { /* we found a line */
798 char *end;
799 while(buffer[i+1] == '\r')
800 ++i; /* skip \r in case there are any */
801 end = buffer+i;
802 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
803 *(end--) = 0;
804 if(end-lastblockstart < 60+5) /* short line */
805 fprintf(stderr, "Short Header line '%s' ignored.\n", lastblockstart);
806 else
807 {
808 int pos;
809 if(!strcmp("COMMENT", lastblockstart+60))
810 pos = hdata.numheaders;
811 else
812 {
813 for(pos = 0; pos < hdata.numheaders; ++pos)
814 {
815 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
816 break;
817 }
818 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
819 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
820 {
821 fprintf(stderr, "Overwriting header '%s' is dangerous.\n",
822 lastblockstart+60);
823 }
824 }
825 if(pos >= MAXHEADERLINES)
826 {
827 fprintf(stderr,
828 "Maximum number of header lines of %d reached.\n",
829 MAXHEADERLINES);
830 }
831 else if(!strcmp("END OF HEADER", lastblockstart+60))
832 {
833 fprintf(stderr, "End of header ignored.\n");
834 }
835 else
836 {
837 hdata.data.unnamed[pos] = lastblockstart;
838 if(pos == hdata.numheaders)
839 ++hdata.numheaders;
840 }
841 }
842 lastblockstart = buffer+i+1;
843 }
844 }
845 }
846 else
847 {
848 fprintf(stderr, "Could not read data from headerfile '%s'.\n",
849 Parser->headerfile);
850 }
851 fclose(fh);
852 }
853 else
854 {
855 fprintf(stderr, "Could not open header datafile '%s'.\n",
856 Parser->headerfile);
857 }
858 }
859
860 for(i = 0; i < hdata.numheaders; ++i)
861 printf("%s\n", hdata.data.unnamed[i]);
862 printf(" "
863 "END OF HEADER\n");
864}
865
866void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
867{
868 Parser->Message[Parser->MessageSize++] = byte;
869 if(Parser->MessageSize >= Parser->NeedBytes)
870 {
871 int r;
872 while((r = RTCM3Parser(Parser)))
873 {
874 int i, j, o;
875 struct converttimeinfo cti;
876
877 if(!Parser->init)
878 {
879 HandleHeader(Parser);
880 Parser->init = 1;
881 }
882 if(r == 2 && !Parser->validwarning)
883 {
884 printf("No valid RINEX! All values are modulo 299792.458!"
885 " COMMENT\n");
886 Parser->validwarning = 1;
887 }
888
889 converttime(&cti, Parser->Data.week,
890 (int)floor(Parser->Data.timeofweek/1000.0));
891 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",
892 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
893 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
894 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
895 {
896 if(Parser->Data.satellites[i] <= PRN_GPS_END)
897 printf("G%02d", Parser->Data.satellites[i]);
898 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
899 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
900 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
901 else
902 printf("%3d", Parser->Data.satellites[i]);
903 }
904 printf("\n");
905 o = 12;
906 j = Parser->Data.numsats - 12;
907 while(j > 0)
908 {
909 printf(" ");
910 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
911 {
912 if(Parser->Data.satellites[i] <= PRN_GPS_END)
913 printf("G%02d", Parser->Data.satellites[i]);
914 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
915 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
916 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
917 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
918 && Parser->Data.satellites[i] <= PRN_WAAS_END)
919 printf("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START);
920 else
921 printf("%3d", Parser->Data.satellites[i]);
922 }
923 printf("\n");
924 j -= 12;
925 o += 12;
926 }
927 for(i = 0; i < Parser->Data.numsats; ++i)
928 {
929 for(j = 0; j < Parser->numdatatypes; ++j)
930 {
931 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
932 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
933 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
934 { /* no or illegal data */
935 printf(" ");
936 }
937 else
938 {
939 char lli = ' ';
940 char snr = ' ';
941 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
942 {
943 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
944 lli = '1';
945 snr = '0'+Parser->Data.snrL1[i];
946 }
947 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
948 {
949 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
950 lli = '1';
951 snr = '0'+Parser->Data.snrL2[i];
952 }
953 printf("%14.3f%c%c",
954 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
955 }
956 if(j%5 == 4 || j == Parser->numdatatypes-1)
957 printf("\n");
958 }
959 }
960 }
961 }
962}
963
964#ifndef NO_RTCM3_MAIN
965static char datestr[] = "$Date: 2006/11/02 13:54:43 $";
966
967/* The string, which is send as agent in HTTP request */
968#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
969
970#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
971
972static const char encodingTable [64] = {
973 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
974 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
975 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
976 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
977};
978
979/* does not buffer overrun, but breaks directly after an error */
980/* returns the number of required bytes */
981static int encode(char *buf, int size, const char *user, const char *pwd)
982{
983 unsigned char inbuf[3];
984 char *out = buf;
985 int i, sep = 0, fill = 0, bytes = 0;
986
987 while(*user || *pwd)
988 {
989 i = 0;
990 while(i < 3 && *user) inbuf[i++] = *(user++);
991 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
992 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
993 while(i < 3) {inbuf[i++] = 0; ++fill; }
994 if(out-buf < size-1)
995 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
996 if(out-buf < size-1)
997 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
998 | ((inbuf [1] & 0xF0) >> 4)];
999 if(out-buf < size-1)
1000 {
1001 if(fill == 2)
1002 *(out++) = '=';
1003 else
1004 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1005 | ((inbuf [2] & 0xC0) >> 6)];
1006 }
1007 if(out-buf < size-1)
1008 {
1009 if(fill >= 1)
1010 *(out++) = '=';
1011 else
1012 *(out++) = encodingTable[inbuf [2] & 0x3F];
1013 }
1014 bytes += 4;
1015 }
1016 if(out-buf < size)
1017 *out = 0;
1018 return bytes;
1019}
1020
1021static int stop = 0;
1022
1023struct Args
1024{
1025 const char *server;
1026 int port;
1027 const char *user;
1028 const char *password;
1029 const char *data;
1030 const char *headerfile;
1031};
1032
1033/* option parsing */
1034#ifdef NO_LONG_OPTS
1035#define LONG_OPT(a)
1036#else
1037#define LONG_OPT(a) a
1038static struct option opts[] = {
1039{ "data", required_argument, 0, 'd'},
1040{ "server", required_argument, 0, 's'},
1041{ "password", required_argument, 0, 'p'},
1042{ "port", required_argument, 0, 'r'},
1043{ "header", required_argument, 0, 'f'},
1044{ "user", required_argument, 0, 'u'},
1045{ "help", no_argument, 0, 'h'},
1046{0,0,0,0}};
1047#endif
1048#define ARGOPT "-d:hp:r:s:u:f:"
1049
1050static const char *geturl(const char *url, struct Args *args)
1051{
1052 static char buf[1000];
1053 static char *Buffer = buf;
1054 static char *Bufend = buf+sizeof(buf);
1055
1056 if(strncmp("ntrip:", url, 6))
1057 return "URL must start with 'ntrip:'.";
1058 url += 6; /* skip ntrip: */
1059
1060 if(*url != '@' && *url != '/')
1061 {
1062 /* scan for mountpoint */
1063 args->data = Buffer;
1064 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)
1065 *(Buffer++) = *(url++);
1066 if(Buffer == args->data)
1067 return "Mountpoint required.";
1068 else if(Buffer >= Bufend-1)
1069 return "Parsing buffer too short.";
1070 *(Buffer++) = 0;
1071 }
1072
1073 if(*url == '/') /* username and password */
1074 {
1075 ++url;
1076 args->user = Buffer;
1077 while(*url && *url != '@' && *url != ':' && Buffer != Bufend)
1078 *(Buffer++) = *(url++);
1079 if(Buffer == args->user)
1080 return "Username cannot be empty.";
1081 else if(Buffer >= Bufend-1)
1082 return "Parsing buffer too short.";
1083 *(Buffer++) = 0;
1084
1085 if(*url == ':') ++url;
1086
1087 args->password = Buffer;
1088 while(*url && *url != '@' && Buffer != Bufend)
1089 *(Buffer++) = *(url++);
1090 if(Buffer == args->password)
1091 return "Password cannot be empty.";
1092 else if(Buffer >= Bufend-1)
1093 return "Parsing buffer too short.";
1094 *(Buffer++) = 0;
1095 }
1096
1097 if(*url == '@') /* server */
1098 {
1099 ++url;
1100 args->server = Buffer;
1101 while(*url && *url != ':' && Buffer != Bufend)
1102 *(Buffer++) = *(url++);
1103 if(Buffer == args->server)
1104 return "Servername cannot be empty.";
1105 else if(Buffer >= Bufend-1)
1106 return "Parsing buffer too short.";
1107 *(Buffer++) = 0;
1108
1109 if(*url == ':')
1110 {
1111 char *s2 = 0;
1112 args->port = strtol(++url, &s2, 10);
1113 if(*s2 || args->port <= 0 || args->port > 0xFFFF)
1114 return "Illegal port number.";
1115 url = s2;
1116 }
1117 }
1118
1119 return *url ? "Garbage at end of server string." : 0;
1120}
1121
1122static int getargs(int argc, char **argv, struct Args *args)
1123{
1124 int res = 1;
1125 int getoptr;
1126 int help = 0;
1127 char *t;
1128
1129 args->server = "www.euref-ip.net";
1130 args->port = 80;
1131 args->user = "";
1132 args->password = "";
1133 args->data = 0;
1134 args->headerfile = 0;
1135 help = 0;
1136
1137 do
1138 {
1139#ifdef NO_LONG_OPTS
1140 switch((getoptr = getopt(argc, argv, ARGOPT)))
1141#else
1142 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1143#endif
1144 {
1145 case 's': args->server = optarg; break;
1146 case 'u': args->user = optarg; break;
1147 case 'p': args->password = optarg; break;
1148 case 'd': args->data = optarg; break;
1149 case 'f': args->headerfile = optarg; break;
1150 case 'h': help=1; break;
1151 case 'r':
1152 args->port = strtoul(optarg, &t, 10);
1153 if((t && *t) || args->port < 1 || args->port > 65535)
1154 res = 0;
1155 break;
1156 case 1:
1157 {
1158 const char *err;
1159 if((err = geturl(optarg, args)))
1160 {
1161 fprintf(stderr, "%s\n\n", err);
1162 res = 0;
1163 }
1164 }
1165 break;
1166 case -1: break;
1167 }
1168 } while(getoptr != -1 || !res);
1169
1170 datestr[0] = datestr[7];
1171 datestr[1] = datestr[8];
1172 datestr[2] = datestr[9];
1173 datestr[3] = datestr[10];
1174 datestr[5] = datestr[12];
1175 datestr[6] = datestr[13];
1176 datestr[8] = datestr[15];
1177 datestr[9] = datestr[16];
1178 datestr[4] = datestr[7] = '-';
1179 datestr[10] = 0;
1180
1181 if(!res || help)
1182 {
1183 fprintf(stderr, "Version %s (%s) GPL\nUsage: %s -s server -u user ...\n"
1184 " -d " LONG_OPT("--data ") "the requested data set\n"
1185 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1186 " -s " LONG_OPT("--server ") "the server name or address\n"
1187 " -p " LONG_OPT("--password ") "the login password\n"
1188 " -r " LONG_OPT("--port ") "the server port number (default 80)\n"
1189 " -u " LONG_OPT("--user ") "the user name\n"
1190 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n"
1191 , revisionstr, datestr, argv[0], argv[0]);
1192 exit(1);
1193 }
1194 return res;
1195}
1196
1197/* let the output complete a block if necessary */
1198static void signalhandler(int sig)
1199{
1200 if(!stop)
1201 {
1202 fprintf(stderr, "Stop signal number %d received. "
1203 "Trying to terminate gentle.\n", sig);
1204 stop = 1;
1205 alarm(1);
1206 }
1207}
1208
1209/* for some reason we had to abort hard (maybe waiting for data */
1210#ifdef __GNUC__
1211static __attribute__ ((noreturn)) void signalhandler_alarm(
1212int sig __attribute__((__unused__)))
1213#else /* __GNUC__ */
1214static void signalhandler_alarm(int sig)
1215#endif /* __GNUC__ */
1216{
1217 fprintf(stderr, "Programm forcefully terminated.\n");
1218 exit(1);
1219}
1220
1221int main(int argc, char **argv)
1222{
1223 struct Args args;
1224 struct RTCM3ParserData Parser;
1225
1226 setbuf(stdout, 0);
1227 setbuf(stdin, 0);
1228 setbuf(stderr, 0);
1229
1230 {
1231 char *a;
1232 int i=0;
1233 for(a = revisionstr+11; *a && *a != ' '; ++a)
1234 revisionstr[i++] = *a;
1235 revisionstr[i] = 0;
1236 }
1237
1238 signal(SIGINT, signalhandler);
1239 signal(SIGALRM,signalhandler_alarm);
1240 signal(SIGQUIT,signalhandler);
1241 signal(SIGTERM,signalhandler);
1242 signal(SIGPIPE,signalhandler);
1243 memset(&Parser, 0, sizeof(Parser));
1244 {
1245 time_t tim;
1246 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
1247 Parser.GPSWeek = tim/(7*24*60*60);
1248 Parser.GPSTOW = tim%(7*24*60*60);
1249 }
1250
1251 if(getargs(argc, argv, &args))
1252 {
1253 int i, sockfd, numbytes;
1254 char buf[MAXDATASIZE];
1255 struct hostent *he;
1256 struct sockaddr_in their_addr; /* connector's address information */
1257
1258 Parser.headerfile = args.headerfile;
1259
1260 if(!(he=gethostbyname(args.server)))
1261 {
1262 perror("gethostbyname");
1263 exit(1);
1264 }
1265 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1266 {
1267 perror("socket");
1268 exit(1);
1269 }
1270 their_addr.sin_family = AF_INET; /* host byte order */
1271 their_addr.sin_port = htons(args.port); /* short, network byte order */
1272 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
1273 memset(&(their_addr.sin_zero), '\0', 8);
1274 if(connect(sockfd, (struct sockaddr *)&their_addr,
1275 sizeof(struct sockaddr)) == -1)
1276 {
1277 perror("connect");
1278 exit(1);
1279 }
1280
1281 if(!args.data)
1282 {
1283 i = snprintf(buf, MAXDATASIZE,
1284 "GET / HTTP/1.0\r\n"
1285 "User-Agent: %s/%s\r\n"
1286#ifdef UNUSED
1287 "Accept: */*\r\n"
1288 "Connection: close\r\n"
1289#endif
1290 "\r\n"
1291 , AGENTSTRING, revisionstr);
1292 }
1293 else
1294 {
1295 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1296 "GET /%s HTTP/1.0\r\n"
1297 "User-Agent: %s/%s\r\n"
1298#ifdef UNUSED
1299 "Accept: */*\r\n"
1300 "Connection: close\r\n"
1301#endif
1302 "Authorization: Basic "
1303 , args.data, AGENTSTRING, revisionstr);
1304 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
1305 {
1306 fprintf(stderr, "Requested data too long\n");
1307 exit(1);
1308 }
1309 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
1310 if(i > MAXDATASIZE-5)
1311 {
1312 fprintf(stderr, "Username and/or password too long\n");
1313 exit(1);
1314 }
1315 snprintf(buf+i, 5, "\r\n\r\n");
1316 i += 5;
1317 }
1318 if(send(sockfd, buf, (size_t)i, 0) != i)
1319 {
1320 perror("send");
1321 exit(1);
1322 }
1323 if(args.data)
1324 {
1325 int k = 0;
1326 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1327 {
1328 if(!k)
1329 {
1330 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1331 {
1332 fprintf(stderr, "Could not get the requested data: ");
1333 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1334 {
1335 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');
1336 }
1337 fprintf(stderr, "\n");
1338 exit(1);
1339 }
1340 ++k;
1341 }
1342 else
1343 {
1344 int z;
1345 for(z = 0; z < numbytes && !stop; ++z)
1346 HandleByte(&Parser, buf[z]);
1347 }
1348 }
1349 }
1350 else
1351 {
1352 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1353 {
1354 fwrite(buf, (size_t)numbytes, 1, stdout);
1355 }
1356 }
1357
1358 close(sockfd);
1359 }
1360 return 0;
1361}
1362#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.