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

Last change on this file since 366 was 366, checked in by mervart, 17 years ago

* empty log message *

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