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

Last change on this file since 453 was 416, checked in by mervart, 18 years ago

* empty log message *

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