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

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

* empty log message *

File size: 37.4 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.10 2006/11/15 12:31:31 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.10 $";
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 != 0x80000)
306 {
307 gnss->dataflags[num] |= c;
308 gnss->measdata[num][ce] = l1range*0.02;
309 }
310 GETBITSSIGN(i, 20);
311 if(i != 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*4;
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 != 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 != 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*4;
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
449 GETBITS(sv, 6)
450 if(!sv || sv > 24)
451 {
452 --num; --gnss->numsats;
453 }
454 else
455 {
456 int freq;
457 gnss->satellites[num] = sv-1 + PRN_GLONASS_START;
458 /* L1 */
459 GETBITS(code, 1)
460 GETBITS(freq, 5)
461 if(code)
462 {
463 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
464 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
465 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
466 }
467 else
468 {
469 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
470 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
471 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
472 }
473 GETBITS(l1range, 25)
474 if(l1range != 0x80000)
475 {
476 gnss->dataflags[num] |= c;
477 gnss->measdata[num][ce] = l1range*0.02;
478 }
479 GETBITSSIGN(i, 20)
480 if(i != 0x80000)
481 {
482 gnss->dataflags[num] |= l;
483 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
484 }
485 GETBITS(i, 7)
486 lastlockl1[sv] = i;
487 if(handle->lastlockl1[sv] > i)
488 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
489 if(type == 1010 || type == 1012)
490 {
491 GETBITS(amb,7)
492 if(amb && (gnss->dataflags[num] & c))
493 {
494 gnss->measdata[num][ce] += amb*599584.916;
495 gnss->measdata[num][le] += amb*599584.916;
496 ++wasamb;
497 }
498 GETBITS(i, 8)
499 if(i)
500 {
501 gnss->dataflags[num] |= s;
502 gnss->measdata[num][se] = i*0.25;
503 i /= 4*4;
504 if(i > 9) i = 9;
505 else if(i < 1) i = 1;
506 gnss->snrL1[num] = i;
507 }
508 }
509 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
510 if(type == 1011 || type == 1012)
511 {
512 /* L2 */
513 GETBITS(code,2)
514 if(code)
515 {
516 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
517 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
518 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
519 }
520 else
521 {
522 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
523 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
524 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
525 }
526 GETBITSSIGN(i,14)
527 if(i != 0x2000)
528 {
529 gnss->dataflags[num] |= c;
530 gnss->measdata[num][ce] = l1range*0.02+i*0.02
531 +amb*599584.916;
532 }
533 GETBITSSIGN(i,20)
534 if(i != 0x80000)
535 {
536 gnss->dataflags[num] |= l;
537 gnss->measdata[num][le] = l1range*0.02+i*0.0005
538 +amb*599584.915;
539 }
540 GETBITS(i,7)
541 lastlockl2[sv] = i;
542 if(handle->lastlockl2[sv] > i)
543 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
544 if(type == 1012)
545 {
546 GETBITS(i, 8)
547 if(i)
548 {
549 gnss->dataflags[num] |= s;
550 gnss->measdata[num][se] = i*0.25;
551 i /= 4*4;
552 if(i > 9) i = 9;
553 else if(i < 1) i = 1;
554 gnss->snrL2[num] = i;
555 }
556 }
557 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
558 }
559 }
560 }
561 for(i = 0; i < 64; ++i)
562 {
563 handle->lastlockl1[i] = lastlockl1[i];
564 handle->lastlockl2[i] = lastlockl2[i];
565 }
566 if(!syncf && !old)
567 {
568 handle->Data = *gnss;
569 memset(gnss, 0, sizeof(*gnss));
570 }
571 if(!syncf || old)
572 {
573 if(wasamb) /* not RINEX compatible without */
574 ret = 1;
575 else
576 ret = 2;
577 }
578 }
579 break;
580 }
581 }
582 return ret;
583}
584
585struct Header
586{
587 const char *version;
588 const char *pgm;
589 const char *marker;
590 const char *observer;
591 const char *receiver;
592 const char *antenna;
593 const char *position;
594 const char *antennaposition;
595 const char *wavelength;
596 const char *typesofobs; /* should not be modified outside */
597 const char *timeoffirstobs; /* should not be modified outside */
598};
599
600#define MAXHEADERLINES 50
601#define MAXHEADERBUFFERSIZE 4096
602struct HeaderData
603{
604 union
605 {
606 struct Header named;
607 const char *unnamed[MAXHEADERLINES];
608 } data;
609 int numheaders;
610};
611
612struct converttimeinfo {
613 int second; /* seconds of GPS time [0..59] */
614 int minute; /* minutes of GPS time [0..59] */
615 int hour; /* hour of GPS time [0..24] */
616 int day; /* day of GPS time [1..28..30(31)*/
617 int month; /* month of GPS time [1..12]*/
618 int year; /* year of GPS time [1980..] */
619};
620
621static void converttime(struct converttimeinfo *c, int week, int tow)
622{
623 int i, k, doy, j; /* temporary variables */
624 j = week*(7*24*60*60) + tow + 5*24*60*60;
625 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
626 j -= k;
627 c->year = i;
628 doy = 1+ (j / (24*60*60));
629 j %= (24*60*60);
630 c->hour = j / (60*60);
631 j %= (60*60);
632 c->minute = j / 60;
633 c->second = j % 60;
634 j = 0;
635 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
636 j += k;
637 c->month = i;
638 c->day = doy - j;
639}
640
641#ifndef NO_RTCM3_MAIN
642void RTCM3Error(const char *fmt, ...)
643{
644 va_list v;
645 va_start(v, fmt);
646 vfprintf(stderr, fmt, v);
647 va_end(v);
648}
649#endif
650
651void RTCM3Text(const char *fmt, ...)
652{
653 va_list v;
654 va_start(v, fmt);
655 vprintf(fmt, v);
656 va_end(v);
657}
658
659#define NUMSTARTSKIP 3
660void HandleHeader(struct RTCM3ParserData *Parser)
661{
662 struct HeaderData hdata;
663 char thebuffer[MAXHEADERBUFFERSIZE];
664 char *buffer = thebuffer;
665 size_t buffersize = sizeof(thebuffer);
666 int i;
667
668 hdata.data.named.version =
669 " 2.11 OBSERVATION DATA M (Mixed)"
670 " RINEX VERSION / TYPE";
671
672 {
673 const char *str;
674 time_t t;
675 struct tm * t2;
676
677#ifdef NO_RTCM3_MAIN
678 if(revisionstr[0] == '$')
679 {
680 char *a;
681 int i=0;
682 for(a = revisionstr+11; *a && *a != ' '; ++a)
683 revisionstr[i++] = *a;
684 revisionstr[i] = 0;
685 }
686#endif
687
688 str = getenv("USER");
689 if(!str) str = "";
690 t = time(&t);
691 t2 = gmtime(&t);
692 hdata.data.named.pgm = buffer;
693 i = 1+snprintf(buffer, buffersize,
694 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
695 "PGM / RUN BY / DATE",
696 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour,
697 t2->tm_min);
698 buffer += i; buffersize -= i;
699
700 hdata.data.named.observer = buffer;
701 i = 1+snprintf(buffer, buffersize,
702 "%-20.20s "
703 "OBSERVER / AGENCY", str);
704 buffer += i; buffersize -= i;
705 }
706
707 hdata.data.named.marker =
708 "RTCM3TORINEX "
709 "MARKER NAME";
710
711 hdata.data.named.receiver =
712 " "
713 "REC # / TYPE / VERS";
714
715 hdata.data.named.antenna =
716 " "
717 "ANT # / TYPE";
718
719 hdata.data.named.position =
720 " .0000 .0000 .0000 "
721 "APPROX POSITION XYZ";
722
723 hdata.data.named.antennaposition =
724 " .0000 .0000 .0000 "
725 "ANTENNA: DELTA H/E/N";
726
727 hdata.data.named.wavelength =
728 " 1 1 "
729 "WAVELENGTH FACT L1/2";
730
731 {
732#define CHECKFLAGS(a, b) \
733 if(flags & GNSSDF_##a##DATA \
734 && !data[RINEXENTRY_##b##DATA]) \
735 { \
736 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \
737 Parser->datapos[Parser->numdatatypes++] = data[RINEXENTRY_##b##DATA] \
738 = GNSSENTRY_##a##DATA; \
739 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
740 tbufferpos += 6; \
741 }
742
743 int flags = Parser->startflags;
744 int data[RINEXENTRY_NUMBER];
745 char tbuffer[6*RINEXENTRY_NUMBER+1];
746 int tbufferpos = 0;
747 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
748 data[i] = 0;
749 for(i = 0; i < Parser->Data.numsats; ++i)
750 flags |= Parser->Data.dataflags[i];
751
752 CHECKFLAGS(C1,C1)
753 CHECKFLAGS(C2,C2)
754 CHECKFLAGS(P1,P1)
755 CHECKFLAGS(P2,P2)
756 CHECKFLAGS(L1C,L1)
757 CHECKFLAGS(L1P,L1)
758 CHECKFLAGS(L2C,L2)
759 CHECKFLAGS(L2P,L2)
760 CHECKFLAGS(D1C,D1)
761 CHECKFLAGS(D1P,D1)
762 CHECKFLAGS(D2C,D2)
763 CHECKFLAGS(D2P,D2)
764 CHECKFLAGS(S1C,S1)
765 CHECKFLAGS(S1P,S1)
766 CHECKFLAGS(S2C,S2)
767 CHECKFLAGS(S2P,S2)
768
769 hdata.data.named.typesofobs = buffer;
770 i = 1+snprintf(buffer, buffersize,
771 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);
772 if(Parser->numdatatypes>9)
773 {
774 i += snprintf(buffer+i-1, buffersize,
775 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
776 }
777 buffer += i; buffersize -= i;
778 }
779
780 {
781 struct converttimeinfo cti;
782 converttime(&cti, Parser->Data.week,
783 (int)floor(Parser->Data.timeofweek/1000.0));
784 hdata.data.named.timeoffirstobs = buffer;
785 i = 1+snprintf(buffer, buffersize,
786 " %4d %2d %2d %2d %2d %10.7f GPS "
787 "TIME OF FIRST OBS", cti.year%100, cti.month, cti.day, cti.hour,
788 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
789
790 buffer += i; buffersize -= i;
791 }
792
793 hdata.numheaders = 11;
794
795 if(Parser->headerfile)
796 {
797 FILE *fh;
798 if((fh = fopen(Parser->headerfile, "r")))
799 {
800 size_t siz;
801 char *lastblockstart;
802 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
803 {
804 buffer[siz] = '\n';
805 if(siz == buffersize)
806 {
807 RTCM3Error("Header file is too large. Only %d bytes read.",
808 siz);
809 }
810 /* scan the file line by line and enter the entries in the list */
811 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
812 /* overwrites entries, except for comments */
813 lastblockstart = buffer;
814 for(i = 0; i < (int)siz; ++i)
815 {
816 if(buffer[i] == '\n')
817 { /* we found a line */
818 char *end;
819 while(buffer[i+1] == '\r')
820 ++i; /* skip \r in case there are any */
821 end = buffer+i;
822 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
823 *(end--) = 0;
824 if(end-lastblockstart < 60+5) /* short line */
825 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
826 else
827 {
828 int pos;
829 if(!strcmp("COMMENT", lastblockstart+60))
830 pos = hdata.numheaders;
831 else
832 {
833 for(pos = 0; pos < hdata.numheaders; ++pos)
834 {
835 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
836 break;
837 }
838 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
839 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
840 {
841 RTCM3Error("Overwriting header '%s' is dangerous.\n",
842 lastblockstart+60);
843 }
844 }
845 if(pos >= MAXHEADERLINES)
846 {
847 RTCM3Error("Maximum number of header lines of %d reached.\n",
848 MAXHEADERLINES);
849 }
850 else if(!strcmp("END OF HEADER", lastblockstart+60))
851 {
852 RTCM3Error("End of header ignored.\n");
853 }
854 else
855 {
856 hdata.data.unnamed[pos] = lastblockstart;
857 if(pos == hdata.numheaders)
858 ++hdata.numheaders;
859 }
860 }
861 lastblockstart = buffer+i+1;
862 }
863 }
864 }
865 else
866 {
867 RTCM3Error("Could not read data from headerfile '%s'.\n",
868 Parser->headerfile);
869 }
870 fclose(fh);
871 }
872 else
873 {
874 RTCM3Error("Could not open header datafile '%s'.\n",
875 Parser->headerfile);
876 }
877 }
878
879#ifndef NO_RTCM3_MAIN
880 for(i = 0; i < hdata.numheaders; ++i)
881 RTCM3Text("%s\n", hdata.data.unnamed[i]);
882 RTCM3Text(" "
883 "END OF HEADER\n");
884#endif
885}
886
887void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
888{
889 Parser->Message[Parser->MessageSize++] = byte;
890 if(Parser->MessageSize >= Parser->NeedBytes)
891 {
892 int r;
893 while((r = RTCM3Parser(Parser)))
894 {
895 int i, j, o;
896 struct converttimeinfo cti;
897
898 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
899 {
900 ++Parser->init;
901
902 if(Parser->init == NUMSTARTSKIP)
903 HandleHeader(Parser);
904 else
905 {
906 for(i = 0; i < Parser->Data.numsats; ++i)
907 Parser->startflags |= Parser->Data.dataflags[i];
908 continue;
909 }
910 }
911 if(r == 2 && !Parser->validwarning)
912 {
913 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
914 " COMMENT\n");
915 Parser->validwarning = 1;
916 }
917
918 converttime(&cti, Parser->Data.week,
919 (int)floor(Parser->Data.timeofweek/1000.0));
920 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
921 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
922 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
923 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
924 {
925 if(Parser->Data.satellites[i] <= PRN_GPS_END)
926 RTCM3Text("G%02d", Parser->Data.satellites[i]);
927 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
928 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
929 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
930 else
931 RTCM3Text("%3d", Parser->Data.satellites[i]);
932 }
933 RTCM3Text("\n");
934 o = 12;
935 j = Parser->Data.numsats - 12;
936 while(j > 0)
937 {
938 RTCM3Text(" ");
939 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
940 {
941 if(Parser->Data.satellites[i] <= PRN_GPS_END)
942 RTCM3Text("G%02d", Parser->Data.satellites[i]);
943 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
944 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
945 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
946 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
947 && Parser->Data.satellites[i] <= PRN_WAAS_END)
948 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START);
949 else
950 RTCM3Text("%3d", Parser->Data.satellites[i]);
951 }
952 RTCM3Text("\n");
953 j -= 12;
954 o += 12;
955 }
956 for(i = 0; i < Parser->Data.numsats; ++i)
957 {
958 for(j = 0; j < Parser->numdatatypes; ++j)
959 {
960 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
961 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
962 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
963 { /* no or illegal data */
964 RTCM3Text(" ");
965 }
966 else
967 {
968 char lli = ' ';
969 char snr = ' ';
970 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
971 {
972 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
973 lli = '1';
974 snr = '0'+Parser->Data.snrL1[i];
975 }
976 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
977 {
978 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
979 lli = '1';
980 snr = '0'+Parser->Data.snrL2[i];
981 }
982 RTCM3Text("%14.3f%c%c",
983 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
984 }
985 if(j%5 == 4 || j == Parser->numdatatypes-1)
986 RTCM3Text("\n");
987 }
988 }
989 }
990 }
991}
992
993#ifndef NO_RTCM3_MAIN
994static char datestr[] = "$Date: 2006/11/15 12:31:31 $";
995
996/* The string, which is send as agent in HTTP request */
997#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
998
999#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1000
1001static const char encodingTable [64] = {
1002 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1003 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1004 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1005 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1006};
1007
1008/* does not buffer overrun, but breaks directly after an error */
1009/* returns the number of required bytes */
1010static int encode(char *buf, int size, const char *user, const char *pwd)
1011{
1012 unsigned char inbuf[3];
1013 char *out = buf;
1014 int i, sep = 0, fill = 0, bytes = 0;
1015
1016 while(*user || *pwd)
1017 {
1018 i = 0;
1019 while(i < 3 && *user) inbuf[i++] = *(user++);
1020 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1021 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1022 while(i < 3) {inbuf[i++] = 0; ++fill; }
1023 if(out-buf < size-1)
1024 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1025 if(out-buf < size-1)
1026 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1027 | ((inbuf [1] & 0xF0) >> 4)];
1028 if(out-buf < size-1)
1029 {
1030 if(fill == 2)
1031 *(out++) = '=';
1032 else
1033 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1034 | ((inbuf [2] & 0xC0) >> 6)];
1035 }
1036 if(out-buf < size-1)
1037 {
1038 if(fill >= 1)
1039 *(out++) = '=';
1040 else
1041 *(out++) = encodingTable[inbuf [2] & 0x3F];
1042 }
1043 bytes += 4;
1044 }
1045 if(out-buf < size)
1046 *out = 0;
1047 return bytes;
1048}
1049
1050static int stop = 0;
1051
1052struct Args
1053{
1054 const char *server;
1055 int port;
1056 const char *user;
1057 const char *password;
1058 const char *data;
1059 const char *headerfile;
1060};
1061
1062/* option parsing */
1063#ifdef NO_LONG_OPTS
1064#define LONG_OPT(a)
1065#else
1066#define LONG_OPT(a) a
1067static struct option opts[] = {
1068{ "data", required_argument, 0, 'd'},
1069{ "server", required_argument, 0, 's'},
1070{ "password", required_argument, 0, 'p'},
1071{ "port", required_argument, 0, 'r'},
1072{ "header", required_argument, 0, 'f'},
1073{ "user", required_argument, 0, 'u'},
1074{ "help", no_argument, 0, 'h'},
1075{0,0,0,0}};
1076#endif
1077#define ARGOPT "-d:hp:r:s:u:f:"
1078
1079static const char *geturl(const char *url, struct Args *args)
1080{
1081 static char buf[1000];
1082 static char *Buffer = buf;
1083 static char *Bufend = buf+sizeof(buf);
1084
1085 if(strncmp("ntrip:", url, 6))
1086 return "URL must start with 'ntrip:'.";
1087 url += 6; /* skip ntrip: */
1088
1089 if(*url != '@' && *url != '/')
1090 {
1091 /* scan for mountpoint */
1092 args->data = Buffer;
1093 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)
1094 *(Buffer++) = *(url++);
1095 if(Buffer == args->data)
1096 return "Mountpoint required.";
1097 else if(Buffer >= Bufend-1)
1098 return "Parsing buffer too short.";
1099 *(Buffer++) = 0;
1100 }
1101
1102 if(*url == '/') /* username and password */
1103 {
1104 ++url;
1105 args->user = Buffer;
1106 while(*url && *url != '@' && *url != ':' && Buffer != Bufend)
1107 *(Buffer++) = *(url++);
1108 if(Buffer == args->user)
1109 return "Username cannot be empty.";
1110 else if(Buffer >= Bufend-1)
1111 return "Parsing buffer too short.";
1112 *(Buffer++) = 0;
1113
1114 if(*url == ':') ++url;
1115
1116 args->password = Buffer;
1117 while(*url && *url != '@' && Buffer != Bufend)
1118 *(Buffer++) = *(url++);
1119 if(Buffer == args->password)
1120 return "Password cannot be empty.";
1121 else if(Buffer >= Bufend-1)
1122 return "Parsing buffer too short.";
1123 *(Buffer++) = 0;
1124 }
1125
1126 if(*url == '@') /* server */
1127 {
1128 ++url;
1129 args->server = Buffer;
1130 while(*url && *url != ':' && Buffer != Bufend)
1131 *(Buffer++) = *(url++);
1132 if(Buffer == args->server)
1133 return "Servername cannot be empty.";
1134 else if(Buffer >= Bufend-1)
1135 return "Parsing buffer too short.";
1136 *(Buffer++) = 0;
1137
1138 if(*url == ':')
1139 {
1140 char *s2 = 0;
1141 args->port = strtol(++url, &s2, 10);
1142 if(*s2 || args->port <= 0 || args->port > 0xFFFF)
1143 return "Illegal port number.";
1144 url = s2;
1145 }
1146 }
1147
1148 return *url ? "Garbage at end of server string." : 0;
1149}
1150
1151static int getargs(int argc, char **argv, struct Args *args)
1152{
1153 int res = 1;
1154 int getoptr;
1155 int help = 0;
1156 char *t;
1157
1158 args->server = "www.euref-ip.net";
1159 args->port = 80;
1160 args->user = "";
1161 args->password = "";
1162 args->data = 0;
1163 args->headerfile = 0;
1164 help = 0;
1165
1166 do
1167 {
1168#ifdef NO_LONG_OPTS
1169 switch((getoptr = getopt(argc, argv, ARGOPT)))
1170#else
1171 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1172#endif
1173 {
1174 case 's': args->server = optarg; break;
1175 case 'u': args->user = optarg; break;
1176 case 'p': args->password = optarg; break;
1177 case 'd': args->data = optarg; break;
1178 case 'f': args->headerfile = optarg; break;
1179 case 'h': help=1; break;
1180 case 'r':
1181 args->port = strtoul(optarg, &t, 10);
1182 if((t && *t) || args->port < 1 || args->port > 65535)
1183 res = 0;
1184 break;
1185 case 1:
1186 {
1187 const char *err;
1188 if((err = geturl(optarg, args)))
1189 {
1190 RTCM3Error("%s\n\n", err);
1191 res = 0;
1192 }
1193 }
1194 break;
1195 case -1: break;
1196 }
1197 } while(getoptr != -1 || !res);
1198
1199 datestr[0] = datestr[7];
1200 datestr[1] = datestr[8];
1201 datestr[2] = datestr[9];
1202 datestr[3] = datestr[10];
1203 datestr[5] = datestr[12];
1204 datestr[6] = datestr[13];
1205 datestr[8] = datestr[15];
1206 datestr[9] = datestr[16];
1207 datestr[4] = datestr[7] = '-';
1208 datestr[10] = 0;
1209
1210 if(!res || help)
1211 {
1212 RTCM3Error("Version %s (%s) GPL\nUsage: %s -s server -u user ...\n"
1213 " -d " LONG_OPT("--data ") "the requested data set\n"
1214 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1215 " -s " LONG_OPT("--server ") "the server name or address\n"
1216 " -p " LONG_OPT("--password ") "the login password\n"
1217 " -r " LONG_OPT("--port ") "the server port number (default 80)\n"
1218 " -u " LONG_OPT("--user ") "the user name\n"
1219 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n"
1220 , revisionstr, datestr, argv[0], argv[0]);
1221 exit(1);
1222 }
1223 return res;
1224}
1225
1226/* let the output complete a block if necessary */
1227static void signalhandler(int sig)
1228{
1229 if(!stop)
1230 {
1231 RTCM3Error("Stop signal number %d received. "
1232 "Trying to terminate gentle.\n", sig);
1233 stop = 1;
1234 alarm(1);
1235 }
1236}
1237
1238/* for some reason we had to abort hard (maybe waiting for data */
1239#ifdef __GNUC__
1240static __attribute__ ((noreturn)) void signalhandler_alarm(
1241int sig __attribute__((__unused__)))
1242#else /* __GNUC__ */
1243static void signalhandler_alarm(int sig)
1244#endif /* __GNUC__ */
1245{
1246 RTCM3Error("Programm forcefully terminated.\n");
1247 exit(1);
1248}
1249
1250int main(int argc, char **argv)
1251{
1252 struct Args args;
1253 struct RTCM3ParserData Parser;
1254
1255 setbuf(stdout, 0);
1256 setbuf(stdin, 0);
1257 setbuf(stderr, 0);
1258
1259 {
1260 char *a;
1261 int i=0;
1262 for(a = revisionstr+11; *a && *a != ' '; ++a)
1263 revisionstr[i++] = *a;
1264 revisionstr[i] = 0;
1265 }
1266
1267 signal(SIGINT, signalhandler);
1268 signal(SIGALRM,signalhandler_alarm);
1269 signal(SIGQUIT,signalhandler);
1270 signal(SIGTERM,signalhandler);
1271 signal(SIGPIPE,signalhandler);
1272 memset(&Parser, 0, sizeof(Parser));
1273 {
1274 time_t tim;
1275 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
1276 Parser.GPSWeek = tim/(7*24*60*60);
1277 Parser.GPSTOW = tim%(7*24*60*60);
1278 }
1279
1280 if(getargs(argc, argv, &args))
1281 {
1282 int i, sockfd, numbytes;
1283 char buf[MAXDATASIZE];
1284 struct hostent *he;
1285 struct sockaddr_in their_addr; /* connector's address information */
1286
1287 Parser.headerfile = args.headerfile;
1288
1289 if(!(he=gethostbyname(args.server)))
1290 {
1291 perror("gethostbyname");
1292 exit(1);
1293 }
1294 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1295 {
1296 perror("socket");
1297 exit(1);
1298 }
1299 their_addr.sin_family = AF_INET; /* host byte order */
1300 their_addr.sin_port = htons(args.port); /* short, network byte order */
1301 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
1302 memset(&(their_addr.sin_zero), '\0', 8);
1303 if(connect(sockfd, (struct sockaddr *)&their_addr,
1304 sizeof(struct sockaddr)) == -1)
1305 {
1306 perror("connect");
1307 exit(1);
1308 }
1309
1310 if(!args.data)
1311 {
1312 i = snprintf(buf, MAXDATASIZE,
1313 "GET / HTTP/1.0\r\n"
1314 "User-Agent: %s/%s\r\n"
1315#ifdef UNUSED
1316 "Accept: */*\r\n"
1317 "Connection: close\r\n"
1318#endif
1319 "\r\n"
1320 , AGENTSTRING, revisionstr);
1321 }
1322 else
1323 {
1324 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1325 "GET /%s HTTP/1.0\r\n"
1326 "User-Agent: %s/%s\r\n"
1327#ifdef UNUSED
1328 "Accept: */*\r\n"
1329 "Connection: close\r\n"
1330#endif
1331 "Authorization: Basic "
1332 , args.data, AGENTSTRING, revisionstr);
1333 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
1334 {
1335 RTCM3Error("Requested data too long\n");
1336 exit(1);
1337 }
1338 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
1339 if(i > MAXDATASIZE-5)
1340 {
1341 RTCM3Error("Username and/or password too long\n");
1342 exit(1);
1343 }
1344 snprintf(buf+i, 5, "\r\n\r\n");
1345 i += 5;
1346 }
1347 if(send(sockfd, buf, (size_t)i, 0) != i)
1348 {
1349 perror("send");
1350 exit(1);
1351 }
1352 if(args.data)
1353 {
1354 int k = 0;
1355 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1356 {
1357 if(!k)
1358 {
1359 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1360 {
1361 RTCM3Error("Could not get the requested data: ");
1362 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1363 {
1364 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
1365 }
1366 RTCM3Error("\n");
1367 exit(1);
1368 }
1369 ++k;
1370 }
1371 else
1372 {
1373 int z;
1374 for(z = 0; z < numbytes && !stop; ++z)
1375 HandleByte(&Parser, (unsigned int) buf[z]);
1376 }
1377 }
1378 }
1379 else
1380 {
1381 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1382 {
1383 fwrite(buf, (size_t)numbytes, 1, stdout);
1384 }
1385 }
1386
1387 close(sockfd);
1388 }
1389 return 0;
1390}
1391#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.