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

Last change on this file since 287 was 287, checked in by stoecker, 17 years ago

added defined

File size: 36.9 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.8 2006/11/03 11:50:11 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.8 $";
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#ifndef NO_RTCM3_MAIN
861 for(i = 0; i < hdata.numheaders; ++i)
862 printf("%s\n", hdata.data.unnamed[i]);
863 printf(" "
864 "END OF HEADER\n");
865#endif
866}
867
868void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
869{
870 Parser->Message[Parser->MessageSize++] = byte;
871 if(Parser->MessageSize >= Parser->NeedBytes)
872 {
873 int r;
874 while((r = RTCM3Parser(Parser)))
875 {
876 int i, j, o;
877 struct converttimeinfo cti;
878
879 if(!Parser->init)
880 {
881 HandleHeader(Parser);
882 Parser->init = 1;
883 }
884 if(r == 2 && !Parser->validwarning)
885 {
886 printf("No valid RINEX! All values are modulo 299792.458!"
887 " COMMENT\n");
888 Parser->validwarning = 1;
889 }
890
891 converttime(&cti, Parser->Data.week,
892 (int)floor(Parser->Data.timeofweek/1000.0));
893 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",
894 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
895 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
896 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
897 {
898 if(Parser->Data.satellites[i] <= PRN_GPS_END)
899 printf("G%02d", Parser->Data.satellites[i]);
900 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
901 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
902 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
903 else
904 printf("%3d", Parser->Data.satellites[i]);
905 }
906 printf("\n");
907 o = 12;
908 j = Parser->Data.numsats - 12;
909 while(j > 0)
910 {
911 printf(" ");
912 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
913 {
914 if(Parser->Data.satellites[i] <= PRN_GPS_END)
915 printf("G%02d", Parser->Data.satellites[i]);
916 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
917 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
918 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
919 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
920 && Parser->Data.satellites[i] <= PRN_WAAS_END)
921 printf("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START);
922 else
923 printf("%3d", Parser->Data.satellites[i]);
924 }
925 printf("\n");
926 j -= 12;
927 o += 12;
928 }
929 for(i = 0; i < Parser->Data.numsats; ++i)
930 {
931 for(j = 0; j < Parser->numdatatypes; ++j)
932 {
933 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
934 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
935 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
936 { /* no or illegal data */
937 printf(" ");
938 }
939 else
940 {
941 char lli = ' ';
942 char snr = ' ';
943 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
944 {
945 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
946 lli = '1';
947 snr = '0'+Parser->Data.snrL1[i];
948 }
949 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
950 {
951 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
952 lli = '1';
953 snr = '0'+Parser->Data.snrL2[i];
954 }
955 printf("%14.3f%c%c",
956 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
957 }
958 if(j%5 == 4 || j == Parser->numdatatypes-1)
959 printf("\n");
960 }
961 }
962 }
963 }
964}
965
966#ifndef NO_RTCM3_MAIN
967static char datestr[] = "$Date: 2006/11/03 11:50:11 $";
968
969/* The string, which is send as agent in HTTP request */
970#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
971
972#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
973
974static const char encodingTable [64] = {
975 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
976 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
977 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
978 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
979};
980
981/* does not buffer overrun, but breaks directly after an error */
982/* returns the number of required bytes */
983static int encode(char *buf, int size, const char *user, const char *pwd)
984{
985 unsigned char inbuf[3];
986 char *out = buf;
987 int i, sep = 0, fill = 0, bytes = 0;
988
989 while(*user || *pwd)
990 {
991 i = 0;
992 while(i < 3 && *user) inbuf[i++] = *(user++);
993 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
994 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
995 while(i < 3) {inbuf[i++] = 0; ++fill; }
996 if(out-buf < size-1)
997 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
998 if(out-buf < size-1)
999 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1000 | ((inbuf [1] & 0xF0) >> 4)];
1001 if(out-buf < size-1)
1002 {
1003 if(fill == 2)
1004 *(out++) = '=';
1005 else
1006 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1007 | ((inbuf [2] & 0xC0) >> 6)];
1008 }
1009 if(out-buf < size-1)
1010 {
1011 if(fill >= 1)
1012 *(out++) = '=';
1013 else
1014 *(out++) = encodingTable[inbuf [2] & 0x3F];
1015 }
1016 bytes += 4;
1017 }
1018 if(out-buf < size)
1019 *out = 0;
1020 return bytes;
1021}
1022
1023static int stop = 0;
1024
1025struct Args
1026{
1027 const char *server;
1028 int port;
1029 const char *user;
1030 const char *password;
1031 const char *data;
1032 const char *headerfile;
1033};
1034
1035/* option parsing */
1036#ifdef NO_LONG_OPTS
1037#define LONG_OPT(a)
1038#else
1039#define LONG_OPT(a) a
1040static struct option opts[] = {
1041{ "data", required_argument, 0, 'd'},
1042{ "server", required_argument, 0, 's'},
1043{ "password", required_argument, 0, 'p'},
1044{ "port", required_argument, 0, 'r'},
1045{ "header", required_argument, 0, 'f'},
1046{ "user", required_argument, 0, 'u'},
1047{ "help", no_argument, 0, 'h'},
1048{0,0,0,0}};
1049#endif
1050#define ARGOPT "-d:hp:r:s:u:f:"
1051
1052static const char *geturl(const char *url, struct Args *args)
1053{
1054 static char buf[1000];
1055 static char *Buffer = buf;
1056 static char *Bufend = buf+sizeof(buf);
1057
1058 if(strncmp("ntrip:", url, 6))
1059 return "URL must start with 'ntrip:'.";
1060 url += 6; /* skip ntrip: */
1061
1062 if(*url != '@' && *url != '/')
1063 {
1064 /* scan for mountpoint */
1065 args->data = Buffer;
1066 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)
1067 *(Buffer++) = *(url++);
1068 if(Buffer == args->data)
1069 return "Mountpoint required.";
1070 else if(Buffer >= Bufend-1)
1071 return "Parsing buffer too short.";
1072 *(Buffer++) = 0;
1073 }
1074
1075 if(*url == '/') /* username and password */
1076 {
1077 ++url;
1078 args->user = Buffer;
1079 while(*url && *url != '@' && *url != ':' && Buffer != Bufend)
1080 *(Buffer++) = *(url++);
1081 if(Buffer == args->user)
1082 return "Username cannot be empty.";
1083 else if(Buffer >= Bufend-1)
1084 return "Parsing buffer too short.";
1085 *(Buffer++) = 0;
1086
1087 if(*url == ':') ++url;
1088
1089 args->password = Buffer;
1090 while(*url && *url != '@' && Buffer != Bufend)
1091 *(Buffer++) = *(url++);
1092 if(Buffer == args->password)
1093 return "Password cannot be empty.";
1094 else if(Buffer >= Bufend-1)
1095 return "Parsing buffer too short.";
1096 *(Buffer++) = 0;
1097 }
1098
1099 if(*url == '@') /* server */
1100 {
1101 ++url;
1102 args->server = Buffer;
1103 while(*url && *url != ':' && Buffer != Bufend)
1104 *(Buffer++) = *(url++);
1105 if(Buffer == args->server)
1106 return "Servername cannot be empty.";
1107 else if(Buffer >= Bufend-1)
1108 return "Parsing buffer too short.";
1109 *(Buffer++) = 0;
1110
1111 if(*url == ':')
1112 {
1113 char *s2 = 0;
1114 args->port = strtol(++url, &s2, 10);
1115 if(*s2 || args->port <= 0 || args->port > 0xFFFF)
1116 return "Illegal port number.";
1117 url = s2;
1118 }
1119 }
1120
1121 return *url ? "Garbage at end of server string." : 0;
1122}
1123
1124static int getargs(int argc, char **argv, struct Args *args)
1125{
1126 int res = 1;
1127 int getoptr;
1128 int help = 0;
1129 char *t;
1130
1131 args->server = "www.euref-ip.net";
1132 args->port = 80;
1133 args->user = "";
1134 args->password = "";
1135 args->data = 0;
1136 args->headerfile = 0;
1137 help = 0;
1138
1139 do
1140 {
1141#ifdef NO_LONG_OPTS
1142 switch((getoptr = getopt(argc, argv, ARGOPT)))
1143#else
1144 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1145#endif
1146 {
1147 case 's': args->server = optarg; break;
1148 case 'u': args->user = optarg; break;
1149 case 'p': args->password = optarg; break;
1150 case 'd': args->data = optarg; break;
1151 case 'f': args->headerfile = optarg; break;
1152 case 'h': help=1; break;
1153 case 'r':
1154 args->port = strtoul(optarg, &t, 10);
1155 if((t && *t) || args->port < 1 || args->port > 65535)
1156 res = 0;
1157 break;
1158 case 1:
1159 {
1160 const char *err;
1161 if((err = geturl(optarg, args)))
1162 {
1163 fprintf(stderr, "%s\n\n", err);
1164 res = 0;
1165 }
1166 }
1167 break;
1168 case -1: break;
1169 }
1170 } while(getoptr != -1 || !res);
1171
1172 datestr[0] = datestr[7];
1173 datestr[1] = datestr[8];
1174 datestr[2] = datestr[9];
1175 datestr[3] = datestr[10];
1176 datestr[5] = datestr[12];
1177 datestr[6] = datestr[13];
1178 datestr[8] = datestr[15];
1179 datestr[9] = datestr[16];
1180 datestr[4] = datestr[7] = '-';
1181 datestr[10] = 0;
1182
1183 if(!res || help)
1184 {
1185 fprintf(stderr, "Version %s (%s) GPL\nUsage: %s -s server -u user ...\n"
1186 " -d " LONG_OPT("--data ") "the requested data set\n"
1187 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1188 " -s " LONG_OPT("--server ") "the server name or address\n"
1189 " -p " LONG_OPT("--password ") "the login password\n"
1190 " -r " LONG_OPT("--port ") "the server port number (default 80)\n"
1191 " -u " LONG_OPT("--user ") "the user name\n"
1192 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n"
1193 , revisionstr, datestr, argv[0], argv[0]);
1194 exit(1);
1195 }
1196 return res;
1197}
1198
1199/* let the output complete a block if necessary */
1200static void signalhandler(int sig)
1201{
1202 if(!stop)
1203 {
1204 fprintf(stderr, "Stop signal number %d received. "
1205 "Trying to terminate gentle.\n", sig);
1206 stop = 1;
1207 alarm(1);
1208 }
1209}
1210
1211/* for some reason we had to abort hard (maybe waiting for data */
1212#ifdef __GNUC__
1213static __attribute__ ((noreturn)) void signalhandler_alarm(
1214int sig __attribute__((__unused__)))
1215#else /* __GNUC__ */
1216static void signalhandler_alarm(int sig)
1217#endif /* __GNUC__ */
1218{
1219 fprintf(stderr, "Programm forcefully terminated.\n");
1220 exit(1);
1221}
1222
1223int main(int argc, char **argv)
1224{
1225 struct Args args;
1226 struct RTCM3ParserData Parser;
1227
1228 setbuf(stdout, 0);
1229 setbuf(stdin, 0);
1230 setbuf(stderr, 0);
1231
1232 {
1233 char *a;
1234 int i=0;
1235 for(a = revisionstr+11; *a && *a != ' '; ++a)
1236 revisionstr[i++] = *a;
1237 revisionstr[i] = 0;
1238 }
1239
1240 signal(SIGINT, signalhandler);
1241 signal(SIGALRM,signalhandler_alarm);
1242 signal(SIGQUIT,signalhandler);
1243 signal(SIGTERM,signalhandler);
1244 signal(SIGPIPE,signalhandler);
1245 memset(&Parser, 0, sizeof(Parser));
1246 {
1247 time_t tim;
1248 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
1249 Parser.GPSWeek = tim/(7*24*60*60);
1250 Parser.GPSTOW = tim%(7*24*60*60);
1251 }
1252
1253 if(getargs(argc, argv, &args))
1254 {
1255 int i, sockfd, numbytes;
1256 char buf[MAXDATASIZE];
1257 struct hostent *he;
1258 struct sockaddr_in their_addr; /* connector's address information */
1259
1260 Parser.headerfile = args.headerfile;
1261
1262 if(!(he=gethostbyname(args.server)))
1263 {
1264 perror("gethostbyname");
1265 exit(1);
1266 }
1267 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1268 {
1269 perror("socket");
1270 exit(1);
1271 }
1272 their_addr.sin_family = AF_INET; /* host byte order */
1273 their_addr.sin_port = htons(args.port); /* short, network byte order */
1274 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
1275 memset(&(their_addr.sin_zero), '\0', 8);
1276 if(connect(sockfd, (struct sockaddr *)&their_addr,
1277 sizeof(struct sockaddr)) == -1)
1278 {
1279 perror("connect");
1280 exit(1);
1281 }
1282
1283 if(!args.data)
1284 {
1285 i = snprintf(buf, MAXDATASIZE,
1286 "GET / HTTP/1.0\r\n"
1287 "User-Agent: %s/%s\r\n"
1288#ifdef UNUSED
1289 "Accept: */*\r\n"
1290 "Connection: close\r\n"
1291#endif
1292 "\r\n"
1293 , AGENTSTRING, revisionstr);
1294 }
1295 else
1296 {
1297 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1298 "GET /%s HTTP/1.0\r\n"
1299 "User-Agent: %s/%s\r\n"
1300#ifdef UNUSED
1301 "Accept: */*\r\n"
1302 "Connection: close\r\n"
1303#endif
1304 "Authorization: Basic "
1305 , args.data, AGENTSTRING, revisionstr);
1306 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
1307 {
1308 fprintf(stderr, "Requested data too long\n");
1309 exit(1);
1310 }
1311 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
1312 if(i > MAXDATASIZE-5)
1313 {
1314 fprintf(stderr, "Username and/or password too long\n");
1315 exit(1);
1316 }
1317 snprintf(buf+i, 5, "\r\n\r\n");
1318 i += 5;
1319 }
1320 if(send(sockfd, buf, (size_t)i, 0) != i)
1321 {
1322 perror("send");
1323 exit(1);
1324 }
1325 if(args.data)
1326 {
1327 int k = 0;
1328 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1329 {
1330 if(!k)
1331 {
1332 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1333 {
1334 fprintf(stderr, "Could not get the requested data: ");
1335 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1336 {
1337 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');
1338 }
1339 fprintf(stderr, "\n");
1340 exit(1);
1341 }
1342 ++k;
1343 }
1344 else
1345 {
1346 int z;
1347 for(z = 0; z < numbytes && !stop; ++z)
1348 HandleByte(&Parser, buf[z]);
1349 }
1350 }
1351 }
1352 else
1353 {
1354 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1355 {
1356 fwrite(buf, (size_t)numbytes, 1, stdout);
1357 }
1358 }
1359
1360 close(sockfd);
1361 }
1362 return 0;
1363}
1364#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.