source: ntrip/trunk/rtcm3torinex/lib/rtcm3torinex.c@ 2725

Last change on this file since 2725 was 2699, checked in by stoecker, 14 years ago

fix bugs in Galileo code

  • Property svn:keywords set to Id Revision Date
File size: 106.2 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 2699 2010-11-15 13:08:27Z stoecker $
4 Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.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#ifndef isinf
51#define isinf(x) 0
52#endif
53
54#include "rtcm3torinex.h"
55
56/* CVS revision and version */
57static char revisionstr[] = "$Revision: 2699 $";
58
59#ifndef COMPILEDATE
60#define COMPILEDATE " built " __DATE__
61#endif
62
63static uint32_t CRC24(long size, const unsigned char *buf)
64{
65 uint32_t crc = 0;
66 int i;
67
68 while(size--)
69 {
70 crc ^= (*buf++) << (16);
71 for(i = 0; i < 8; i++)
72 {
73 crc <<= 1;
74 if(crc & 0x1000000)
75 crc ^= 0x01864cfb;
76 }
77 }
78 return crc;
79}
80
81static int GetMessage(struct RTCM3ParserData *handle)
82{
83 unsigned char *m, *e;
84 int i;
85
86 m = handle->Message+handle->SkipBytes;
87 e = handle->Message+handle->MessageSize;
88 handle->NeedBytes = handle->SkipBytes = 0;
89 while(e-m >= 3)
90 {
91 if(m[0] == 0xD3)
92 {
93 handle->size = ((m[1]&3)<<8)|m[2];
94 if(e-m >= handle->size+6)
95 {
96 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
97 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
98 {
99 handle->SkipBytes = handle->size;
100 break;
101 }
102 else
103 ++m;
104 }
105 else
106 {
107 handle->NeedBytes = handle->size+6;
108 break;
109 }
110 }
111 else
112 ++m;
113 }
114 if(e-m < 3)
115 handle->NeedBytes = 3;
116
117 /* copy buffer to front */
118 i = m - handle->Message;
119 if(i && m < e)
120 memmove(handle->Message, m, (size_t)(handle->MessageSize-i));
121 handle->MessageSize -= i;
122
123 return !handle->NeedBytes;
124}
125
126#define LOADBITS(a) \
127{ \
128 while((a) > numbits) \
129 { \
130 if(!size--) break; \
131 bitfield = (bitfield<<8)|*(data++); \
132 numbits += 8; \
133 } \
134}
135
136/* extract bits from data stream
137 b = variable to store result, a = number of bits */
138#define GETBITS(b, a) \
139{ \
140 LOADBITS(a) \
141 b = (bitfield<<(64-numbits))>>(64-(a)); \
142 numbits -= (a); \
143}
144
145/* extract floating value from data stream
146 b = variable to store result, a = number of bits */
147#define GETFLOAT(b, a, c) \
148{ \
149 LOADBITS(a) \
150 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
151 numbits -= (a); \
152}
153
154/* extract signed floating value from data stream
155 b = variable to store result, a = number of bits */
156#define GETFLOATSIGN(b, a, c) \
157{ \
158 LOADBITS(a) \
159 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
160 numbits -= (a); \
161}
162
163/* extract bits from data stream
164 b = variable to store result, a = number of bits */
165#define GETBITSSIGN(b, a) \
166{ \
167 LOADBITS(a) \
168 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
169 numbits -= (a); \
170}
171
172#define GETFLOATSIGNM(b, a, c) \
173{ int l; \
174 LOADBITS(a) \
175 l = (bitfield<<(64-numbits))>>(64-1); \
176 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
177 numbits -= (a); \
178 if(l) b *= -1.0; \
179}
180
181#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
182
183/* extract byte-aligned byte from data stream,
184 b = variable to store size, s = variable to store string pointer */
185#define GETSTRING(b, s) \
186{ \
187 b = *(data++); \
188 s = (char *) data; \
189 data += b; \
190 size -= b+1; \
191}
192
193struct leapseconds { /* specify the day of leap second */
194 int day; /* this is the day, where 23:59:59 exists 2 times */
195 int month; /* not the next day! */
196 int year;
197 int taicount;
198};
199static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
200static const struct leapseconds leap[] = {
201/*{31, 12, 1971, 11},*/
202/*{31, 12, 1972, 12},*/
203/*{31, 12, 1973, 13},*/
204/*{31, 12, 1974, 14},*/
205/*{31, 12, 1975, 15},*/
206/*{31, 12, 1976, 16},*/
207/*{31, 12, 1977, 17},*/
208/*{31, 12, 1978, 18},*/
209/*{31, 12, 1979, 19},*/
210{30, 06, 1981,20},
211{30, 06, 1982,21},
212{30, 06, 1983,22},
213{30, 06, 1985,23},
214{31, 12, 1987,24},
215{31, 12, 1989,25},
216{31, 12, 1990,26},
217{30, 06, 1992,27},
218{30, 06, 1993,28},
219{30, 06, 1994,29},
220{31, 12, 1995,30},
221{30, 06, 1997,31},
222{31, 12, 1998,32},
223{31, 12, 2005,33},
224{31, 12, 2008,34},
225{0,0,0,0} /* end marker */
226};
227#define LEAPSECONDS 15 /* only needed for approx. time */
228#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
229
230static int longyear(int year, int month)
231{
232 if(!(year % 4) && (!(year % 400) || (year % 100)))
233 {
234 if(!month || month == 2)
235 return 1;
236 }
237 return 0;
238}
239
240int gnumleap(int year, int month, int day)
241{
242 int ls = 0;
243 const struct leapseconds *l;
244
245 for(l = leap; l->taicount && year >= l->year; ++l)
246 {
247 if(year > l->year || month > l->month || (month == l->month && day > l->day))
248 ls = l->taicount - GPSLEAPSTART;
249 }
250 return ls;
251}
252
253/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
254void updatetime(int *week, int *secOfWeek, int mSecOfWeek, int fixnumleap)
255{
256 int y,m,d,k,l, nul;
257 unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
258 int glo_daynumber = 0, glo_timeofday;
259 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
260 + gnumleap(y+1,1,1); ++y)
261 {
262 j -= k; glo_daynumber += l;
263 }
264 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
265 + gnumleap(y, m+1, 1); ++m)
266 {
267 j -= k; glo_daynumber += l;
268 }
269 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
270 j -= 24*60*60;
271 glo_daynumber -= 16*365+4-d;
272 nul = gnumleap(y, m, d);
273 glo_timeofday = j-nul;
274
275 if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
276 *secOfWeek += 24*60*60;
277 else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
278 *secOfWeek -= 24*60*60;
279 *secOfWeek += mSecOfWeek/1000-glo_timeofday;
280 if(fixnumleap)
281 *secOfWeek -= nul;
282 if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
283 if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
284}
285
286int RTCM3Parser(struct RTCM3ParserData *handle)
287{
288 int ret=0;
289
290#ifdef NO_RTCM3_MAIN
291 if(GetMessage(handle)) /* don't repeat */
292#else
293 while(!ret && GetMessage(handle))
294#endif /* NO_RTCM3_MAIN */
295 {
296 /* using 64 bit integer types, as it is much easier than handling
297 the long datatypes in 32 bit */
298 uint64_t numbits = 0, bitfield = 0;
299 int size = handle->size, type;
300 int syncf, old = 0;
301 unsigned char *data = handle->Message+3;
302
303 GETBITS(type,12)
304#ifdef NO_RTCM3_MAIN
305 handle->blocktype = type;
306#endif /* NO_RTCM3_MAIN */
307 switch(type)
308 {
309#ifdef NO_RTCM3_MAIN
310 default:
311 ret = type;
312 break;
313 case 1005: case 1006:
314 {
315 SKIPBITS(22)
316 GETBITSSIGN(handle->antX, 38)
317 SKIPBITS(2)
318 GETBITSSIGN(handle->antY, 38)
319 SKIPBITS(2)
320 GETBITSSIGN(handle->antZ, 38)
321 if(type == 1006)
322 GETBITS(handle->antH, 16)
323 ret = type;
324 }
325 break;
326 case 1007: case 1008: case 1033:
327 {
328 char *antenna;
329 int antnum;
330
331 SKIPBITS(12)
332 GETSTRING(antnum,antenna)
333 memcpy(handle->antenna, antenna, antnum);
334 handle->antenna[antnum] = 0;
335 ret = type;
336 }
337 break;
338 case 1013:
339 {
340 SKIPBITS(12);
341 GETBITS(handle->modjulday, 16);
342 GETBITS(handle->secofday, 17);
343 SKIPBITS(5);
344 GETBITS(handle->leapsec, 8);
345 ret = 1013;
346 }
347 break;
348#endif /* NO_RTCM3_MAIN */
349 case 1019:
350 {
351 struct gpsephemeris *ge;
352 int sv;
353
354 ge = &handle->ephemerisGPS;
355 memset(ge, 0, sizeof(*ge));
356
357 GETBITS(sv, 6)
358 ge->satellite = (sv < 40 ? sv : sv+80);
359 GETBITS(ge->GPSweek, 10)
360 ge->GPSweek += 1024;
361 GETBITS(ge->URAindex, 4)
362 GETBITS(sv, 2)
363 if(sv & 1)
364 ge->flags |= GPSEPHF_L2PCODE;
365 if(sv & 2)
366 ge->flags |= GPSEPHF_L2CACODE;
367 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
368 GETBITS(ge->IODE, 8)
369 GETBITS(ge->TOC, 16)
370 ge->TOC <<= 4;
371 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
372 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
373 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
374 GETBITS(ge->IODC, 10)
375 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
376 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
377 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
378 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
379 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
380 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
381 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
382 GETBITS(ge->TOE, 16)
383 ge->TOE <<= 4;
384
385 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
386 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
387 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
388 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
389 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
390 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
391 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
392 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
393 GETBITS(ge->SVhealth, 6)
394 GETBITS(sv, 1)
395 if(sv)
396 ge->flags |= GPSEPHF_L2PCODEDATA;
397
398 ret = 1019;
399 }
400 break;
401 case 1020:
402 {
403 struct glonassephemeris *ge;
404 int i;
405
406 ge = &handle->ephemerisGLONASS;
407 memset(ge, 0, sizeof(*ge));
408
409 ge->flags |= GLOEPHF_PAVAILABLE;
410 GETBITS(ge->almanac_number, 6)
411 GETBITS(i, 5)
412 ge->frequency_number = i-7;
413 if(ge->almanac_number >= 1 && ge->almanac_number <= PRN_GLONASS_NUM)
414 handle->GLOFreq[ge->almanac_number-1] = 100+ge->frequency_number;
415 GETBITS(i, 1)
416 if(i)
417 ge->flags |= GLOEPHF_ALMANACHEALTHY;
418 GETBITS(i, 1)
419 if(i)
420 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
421 GETBITS(i, 2)
422 if(i & 1)
423 ge->flags |= GLOEPHF_P10TRUE;
424 if(i & 2)
425 ge->flags |= GLOEPHF_P11TRUE;
426 GETBITS(i, 5)
427 ge->tk = i*60*60;
428 GETBITS(i, 6)
429 ge->tk += i*60;
430 GETBITS(i, 1)
431 ge->tk += i*30;
432 GETBITS(i, 1)
433 if(i)
434 ge->flags |= GLOEPHF_UNHEALTHY;
435 GETBITS(i, 1)
436 if(i)
437 ge->flags |= GLOEPHF_P2TRUE;
438 GETBITS(i, 7)
439 ge->tb = i*15*60;
440 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
441 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
442 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
443 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
444 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
445 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
446 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
447 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
448 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
449 GETBITS(i, 1)
450 if(i)
451 ge->flags |= GLOEPHF_P3TRUE;
452 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
453 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
454 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
455 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
456 GETBITS(ge->E, 5)
457 /* GETBITS(b, 1) / * GLONASS-M P4 */
458 /* GETBITS(b, 4) / * GLONASS-M Ft */
459 /* GETBITS(b, 11) / * GLONASS-M Nt */
460 /* GETBITS(b, 2) / * GLONASS-M M */
461 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
462 /* GETBITS(b, 11) / * GLONASS-M Na */
463 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
464 /* GETBITS(b, 5) / * GLONASS-M N4 */
465 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
466 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
467 ge->GPSWeek = handle->GPSWeek;
468 ge->GPSTOW = handle->GPSTOW;
469 ret = 1020;
470 }
471 break;
472 case 1001: case 1002: case 1003: case 1004:
473 if(handle->GPSWeek)
474 {
475 int lastlockl1[64];
476 int lastlockl2[64];
477 struct gnssdata *gnss;
478 int i, numsats, wasamb=0;
479
480 for(i = 0; i < 64; ++i)
481 lastlockl1[i] = lastlockl2[i] = 0;
482
483 gnss = &handle->DataNew;
484
485 SKIPBITS(12) /* id */
486 GETBITS(i,30)
487 if(i/1000 < (int)handle->GPSTOW - 86400)
488 ++handle->GPSWeek;
489 handle->GPSTOW = i/1000;
490 if(gnss->week && (gnss->timeofweek != i || gnss->week
491 != handle->GPSWeek))
492 {
493 handle->Data = *gnss;
494 memset(gnss, 0, sizeof(*gnss));
495 old = 1;
496 }
497 gnss->timeofweek = i;
498 gnss->week = handle->GPSWeek;
499
500 GETBITS(syncf,1) /* sync */
501 GETBITS(numsats,5)
502 SKIPBITS(4) /* smind, smint */
503
504 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
505 {
506 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
507 int fullsat, num;
508
509 GETBITS(sv, 6)
510 fullsat = sv < 40 ? sv : sv+80;
511 for(num = 0; num < gnss->numsats
512 && fullsat != gnss->satellites[num]; ++num)
513 ;
514
515 if(num == gnss->numsats)
516 gnss->satellites[gnss->numsats++] = fullsat;
517
518 /* L1 */
519 GETBITS(code, 1);
520 if(code)
521 {
522 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
523 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
524 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
525 }
526 else
527 {
528 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
529 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
530 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
531 }
532 GETBITS(l1range, 24);
533 GETBITSSIGN(i, 20);
534 if((i&((1<<20)-1)) != 0x80000)
535 {
536 gnss->dataflags[num] |= (c|l);
537 gnss->measdata[num][ce] = l1range*0.02;
538 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
539 }
540 GETBITS(i, 7);
541 lastlockl1[sv] = i;
542 if(handle->lastlockGPSl1[sv] > i || i == 0)
543 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
544 if(type == 1002 || type == 1004)
545 {
546 GETBITS(amb,8);
547 if(amb && (gnss->dataflags[num] & c))
548 {
549 gnss->measdata[num][ce] += amb*299792.458;
550 gnss->measdata[num][le] += amb*299792.458;
551 ++wasamb;
552 }
553 GETBITS(i, 8);
554 if(i)
555 {
556 gnss->dataflags[num] |= s;
557 gnss->measdata[num][se] = i*0.25;
558 i /= 4*4;
559 if(i > 9) i = 9;
560 else if(i < 1) i = 1;
561 gnss->snrL1[num] = i;
562 }
563 }
564 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
565 if(type == 1003 || type == 1004)
566 {
567 /* L2 */
568 GETBITS(code,2);
569 if(code)
570 {
571 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
572 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
573 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
574 if(code >= 2)
575 gnss->dataflags2[num] |= GNSSDF2_XCORRL2;
576 }
577 else
578 {
579 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
580 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
581 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
582 }
583 GETBITSSIGN(i,14);
584 if((i&((1<<14)-1)) != 0x2000)
585 {
586 gnss->dataflags[num] |= c;
587 gnss->measdata[num][ce] = l1range*0.02+i*0.02
588 +amb*299792.458;
589 }
590 GETBITSSIGN(i,20);
591 if((i&((1<<20)-1)) != 0x80000)
592 {
593 gnss->dataflags[num] |= l;
594 gnss->measdata[num][le] = l1range*0.02+i*0.0005
595 +amb*299792.458;
596 }
597 GETBITS(i,7);
598 lastlockl2[sv] = i;
599 if(handle->lastlockGPSl2[sv] > i || i == 0)
600 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
601 if(type == 1004)
602 {
603 GETBITS(i, 8);
604 if(i)
605 {
606 gnss->dataflags[num] |= s;
607 gnss->measdata[num][se] = i*0.25;
608 i /= 4*4;
609 if(i > 9) i = 9;
610 else if(i < 1) i = 1;
611 gnss->snrL2[num] = i;
612 }
613 }
614 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
615 }
616 }
617 for(i = 0; i < 64; ++i)
618 {
619 handle->lastlockGPSl1[i] = lastlockl1[i];
620 handle->lastlockGPSl2[i] = lastlockl2[i];
621 }
622 if(!syncf && !old)
623 {
624 handle->Data = *gnss;
625 memset(gnss, 0, sizeof(*gnss));
626 }
627 if(!syncf || old)
628 {
629 if(wasamb) /* not RINEX compatible without */
630 ret = 1;
631 else
632 ret = 2;
633 }
634#ifdef NO_RTCM3_MAIN
635 else
636 ret = type;
637#endif /* NO_RTCM3_MAIN */
638 }
639 break;
640 case 1009: case 1010: case 1011: case 1012:
641 {
642 int lastlockl1[64];
643 int lastlockl2[64];
644 struct gnssdata *gnss;
645 int i, numsats;
646 int wasamb=0;
647
648 for(i = 0; i < 64; ++i)
649 lastlockl1[i] = lastlockl2[i] = 0;
650
651 gnss = &handle->DataNew;
652
653 SKIPBITS(12) /* id */;
654 GETBITS(i,27) /* tk */
655
656 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
657 i = handle->GPSTOW*1000;
658 if(gnss->week && (gnss->timeofweek != i || gnss->week
659 != handle->GPSWeek))
660 {
661 handle->Data = *gnss;
662 memset(gnss, 0, sizeof(*gnss));
663 old = 1;
664 }
665
666 gnss->timeofweek = i;
667 gnss->week = handle->GPSWeek;
668
669 GETBITS(syncf,1) /* sync */
670 GETBITS(numsats,5)
671
672 SKIPBITS(4) /* smind, smint */
673
674 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
675 {
676 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
677 int freq;
678 int fullsat, num;
679
680 GETBITS(sv, 6)
681 fullsat = sv-1 + PRN_GLONASS_START;
682 for(num = 0; num < gnss->numsats
683 && fullsat != gnss->satellites[num]; ++num)
684 ;
685
686 if(num == gnss->numsats)
687 gnss->satellites[gnss->numsats++] = fullsat;
688
689 /* L1 */
690 GETBITS(code, 1)
691 GETBITS(freq, 5)
692
693 if(sv >= 1 && sv <= PRN_GLONASS_NUM)
694 handle->GLOFreq[sv-1] = 100+freq-7;
695
696 if(code)
697 {
698 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
699 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
700 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
701 }
702 else
703 {
704 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
705 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
706 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
707 }
708 GETBITS(l1range, 25)
709 GETBITSSIGN(i, 20)
710 if((i&((1<<20)-1)) != 0x80000)
711 {
712 /* Handle this like GPS. Actually for GLONASS L1 range is always
713 valid. To be on the save side, we handle it as invalid like we
714 do for GPS and also remove range in case of 0x80000. */
715 gnss->dataflags[num] |= (c|l);
716 gnss->measdata[num][ce] = l1range*0.02;
717 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
718 }
719 GETBITS(i, 7)
720 lastlockl1[sv] = i;
721 if(handle->lastlockGLOl1[sv] > i || i == 0)
722 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
723 if(type == 1010 || type == 1012)
724 {
725 GETBITS(amb,7)
726 if(amb && (gnss->dataflags[num] & c))
727 {
728 gnss->measdata[num][ce] += amb*599584.916;
729 gnss->measdata[num][le] += amb*599584.916;
730 ++wasamb;
731 }
732 GETBITS(i, 8)
733 if(i)
734 {
735 gnss->dataflags[num] |= s;
736 gnss->measdata[num][se] = i*0.25;
737 i /= 4*4;
738 if(i > 9) i = 9;
739 else if(i < 1) i = 1;
740 gnss->snrL1[num] = i;
741 }
742 }
743 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
744 if(type == 1011 || type == 1012)
745 {
746 /* L2 */
747 GETBITS(code,2)
748 if(code)
749 {
750 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
751 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
752 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
753 }
754 else
755 {
756 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
757 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
758 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
759 }
760 GETBITSSIGN(i,14)
761 if((i&((1<<14)-1)) != 0x2000)
762 {
763 gnss->dataflags[num] |= c;
764 gnss->measdata[num][ce] = l1range*0.02+i*0.02
765 +amb*599584.916;
766 }
767 GETBITSSIGN(i,20)
768 if((i&((1<<20)-1)) != 0x80000)
769 {
770 gnss->dataflags[num] |= l;
771 gnss->measdata[num][le] = l1range*0.02+i*0.0005
772 +amb*599584.916;
773 }
774 GETBITS(i,7)
775 lastlockl2[sv] = i;
776 if(handle->lastlockGLOl2[sv] > i || i == 0)
777 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
778 if(type == 1012)
779 {
780 GETBITS(i, 8)
781 if(i)
782 {
783 gnss->dataflags[num] |= s;
784 gnss->measdata[num][se] = i*0.25;
785 i /= 4*4;
786 if(i > 9) i = 9;
787 else if(i < 1) i = 1;
788 gnss->snrL2[num] = i;
789 }
790 }
791 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
792 }
793 if(!sv || sv > 24) /* illegal, remove it again */
794 --gnss->numsats;
795 }
796 for(i = 0; i < 64; ++i)
797 {
798 handle->lastlockGLOl1[i] = lastlockl1[i];
799 handle->lastlockGLOl2[i] = lastlockl2[i];
800 }
801 if(!syncf && !old)
802 {
803 handle->Data = *gnss;
804 memset(gnss, 0, sizeof(*gnss));
805 }
806 if(!syncf || old)
807 {
808 if(wasamb) /* not RINEX compatible without */
809 ret = 1;
810 else
811 ret = 2;
812 }
813#ifdef NO_RTCM3_MAIN
814 else
815 ret = type;
816#endif /* NO_RTCM3_MAIN */
817 }
818 break;
819 case 1071: case 1081: case 1091:
820 case 1072: case 1082: case 1092:
821 case 1073: case 1083: case 1093:
822 case 1074: case 1084: case 1094:
823 case 1075: case 1085: case 1095:
824 case 1076: case 1086: case 1096:
825 case 1077: case 1087: case 1097:
826 if(handle->GPSWeek)
827 {
828 struct CodeData {
829 int typeR;
830 int typeP;
831 int typeD;
832 int typeS;
833 int lock;
834 double wl;
835 const char *code; /* currently unused */
836 };
837 struct CodeData gps[RTCM3_MSM_NUMSIG] =
838 {
839 {0,0,0,0,0,0,0},
840 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
841 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
842 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
843 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
844 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
845 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1W"},
846 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
847 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1Y"},
848 {0,0,0,0,0,0,0},
849 {0,0,0,0,0,0,0},
850 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
851 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2C"},
852 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
853 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2P"},
854 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
855 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2W"},
856 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
857 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2Y"},
858 {0,0,0,0,0,0,0},
859 {0,0,0,0,0,0,0},
860 {0,0,0,0,0,0,0},
861 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
862 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
863 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
864 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
865 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
866 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
867 {0,0,0,0,0,0,0},
868 {0,0,0,0,0,0,0},
869 {0,0,0,0,0,0,0},
870 {0,0,0,0,0,0,0},
871 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
872 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
873 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
874 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
875 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
876 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"}
877 };
878 /* NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later! */
879 struct CodeData glo[RTCM3_MSM_NUMSIG] =
880 {
881 {0,0,0,0,0,0,0},
882 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
883 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1C"},
884 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
885 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,0.0,"1P"},
886 {0,0,0,0,0,0,0},
887 {0,0,0,0,0,0,0},
888 {0,0,0,0,0,0,0},
889 {0,0,0,0,0,0,0},
890 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
891 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,1.0,"2C"},
892 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
893 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,1.0,"2P"},
894 {0,0,0,0,0,0,0},
895 {0,0,0,0,0,0,0},
896 {0,0,0,0,0,0,0},
897 {0,0,0,0,0,0,0},
898 {0,0,0,0,0,0,0},
899 {0,0,0,0,0,0,0},
900 {0,0,0,0,0,0,0},
901 {0,0,0,0,0,0,0},
902 {0,0,0,0,0,0,0},
903 {0,0,0,0,0,0,0},
904 {0,0,0,0,0,0,0},
905 {0,0,0,0,0,0,0},
906 {0,0,0,0,0,0,0},
907 {0,0,0,0,0,0,0},
908 {0,0,0,0,0,0,0}
909 };
910 struct CodeData gal[RTCM3_MSM_NUMSIG] =
911 {
912 {0,0,0,0,0,0,0},
913 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
914 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1C"},
915 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
916 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1A"},
917 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
918 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1B"},
919 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
920 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1X"},
921 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
922 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1Z"},
923 {0,0,0,0,0,0,0},
924 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
925 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6I"},
926 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
927 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Q"},
928 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
929 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6I"},
930 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
931 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Q"},
932 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
933 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6X"},
934 {0,0,0,0,0,0,0},
935 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
936 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7I"},
937 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
938 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7Q"},
939 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
940 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7X"},
941 {0,0,0,0,0,0,0},
942 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
943 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8I"},
944 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
945 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8Q"},
946 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
947 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8X"},
948 {0,0,0,0,0,0,0},
949 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
950 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5I"},
951 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
952 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5Q"},
953 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
954 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5X"},
955 };
956
957 int sys = RTCM3_MSM_GPS, i=0, count, j, old = 0, wasnoamb = 0;
958 int syncf, sigmask, numsat = 0, numsig = 0, numcells;
959 uint64_t satmask, cellmask, ui;
960 double rrmod[RTCM3_MSM_NUMSAT];
961 int rrint[RTCM3_MSM_NUMSAT], rdop[RTCM3_MSM_NUMSAT];
962 int ll[RTCM3_MSM_NUMCELLS];
963 double cnr[RTCM3_MSM_NUMCELLS];
964 double cp[RTCM3_MSM_NUMCELLS], psr[RTCM3_MSM_NUMCELLS],
965 dop[RTCM3_MSM_NUMCELLS];
966 struct gnssdata *gnss = &handle->DataNew;
967
968 SKIPBITS(12)
969 if(type >= 1091)
970 sys = RTCM3_MSM_GALILEO;
971 else if(type >= 1081)
972 sys = RTCM3_MSM_GLONASS;
973
974 switch(sys)
975 {
976 case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
977 case RTCM3_MSM_GPS:
978 GETBITS(i,30)
979 if(i/1000 < (int)handle->GPSTOW - 86400)
980 ++handle->GPSWeek;
981 handle->GPSTOW = i/1000;
982 break;
983 case RTCM3_MSM_GLONASS:
984 SKIPBITS(3)
985 GETBITS(i,27) /* tk */
986
987 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
988 i = handle->GPSTOW*1000;
989 break;
990 }
991
992 if(gnss->week && (gnss->timeofweek != i || gnss->week
993 != handle->GPSWeek))
994 {
995 handle->Data = *gnss;
996 memset(gnss, 0, sizeof(*gnss));
997 old = 1;
998 }
999 gnss->timeofweek = i;
1000 gnss->week = handle->GPSWeek;
1001
1002 GETBITS(syncf, 1)
1003 if(((type % 10) == 6) || ((type % 10) == 7))
1004 SKIPBITS(3)
1005 GETBITS(satmask, RTCM3_MSM_NUMSAT)
1006
1007 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1008 for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1009 ++numsat;
1010 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1011 for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1012 ++numsig;
1013 i = numsat*numsig;
1014 GETBITS(cellmask, (unsigned)i)
1015
1016 switch(type % 10)
1017 {
1018 case 1: case 2: case 3:
1019 ++wasnoamb;
1020 for(j = numsat; j--;)
1021 GETFLOAT(rrmod[j], 10, 1/1024.0)
1022 break;
1023 case 4: case 6:
1024 for(j = numsat; j--;)
1025 GETBITS(rrint[j], 8)
1026 for(j = numsat; j--;)
1027 GETFLOAT(rrmod[j], 10, 1/1024.0)
1028 break;
1029 case 5: case 7:
1030 for(j = numsat; j--;)
1031 GETBITS(rrint[j], 8)
1032 for(j = numsat; j--;)
1033 GETFLOAT(rrmod[j], 10, 1/1024.0)
1034 for(j = numsat; j--;)
1035 GETBITSSIGN(rdop[j], 14)
1036 break;
1037 }
1038
1039 numcells = numsat*numsig;
1040 if(numcells <= RTCM3_MSM_NUMCELLS)
1041 {
1042 switch(type % 10)
1043 {
1044 case 1:
1045 for(count = numcells; count--;)
1046 if(cellmask & (UINT64(1)<<count))
1047 GETFLOATSIGN(psr[count], 15, 0.02)
1048 break;
1049 case 2:
1050 for(count = numcells; count--;)
1051 if(cellmask & (UINT64(1)<<count))
1052 GETFLOATSIGN(cp[count], 20, 1/256.0)
1053 for(count = numcells; count--;)
1054 if(cellmask & (UINT64(1)<<count))
1055 GETBITS(ll[count], 4)
1056 break;
1057 case 3:
1058 for(count = numcells; count--;)
1059 if(cellmask & (UINT64(1)<<count))
1060 GETFLOATSIGN(psr[count], 15, 0.02)
1061 for(count = numcells; count--;)
1062 if(cellmask & (UINT64(1)<<count))
1063 GETFLOATSIGN(cp[count], 20, 1/256.0)
1064 for(count = numcells; count--;)
1065 if(cellmask & (UINT64(1)<<count))
1066 GETBITS(ll[count], 4)
1067 break;
1068 case 4:
1069 for(count = numcells; count--;)
1070 if(cellmask & (UINT64(1)<<count))
1071 GETFLOATSIGN(psr[count], 15, 0.02)
1072 for(count = numcells; count--;)
1073 if(cellmask & (UINT64(1)<<count))
1074 GETFLOATSIGN(cp[count], 20, 1/256.0)
1075 for(count = numcells; count--;)
1076 if(cellmask & (UINT64(1)<<count))
1077 GETBITS(ll[count], 4)
1078 for(count = numcells; count--;)
1079 if(cellmask & (UINT64(1)<<count))
1080 GETBITS(cnr[count], 6)
1081 break;
1082 case 5:
1083 for(count = numcells; count--;)
1084 if(cellmask & (UINT64(1)<<count))
1085 GETFLOATSIGN(psr[count], 15, 0.02)
1086 for(count = numcells; count--;)
1087 if(cellmask & (UINT64(1)<<count))
1088 GETFLOATSIGN(cp[count], 20, 1/256.0)
1089 for(count = numcells; count--;)
1090 if(cellmask & (UINT64(1)<<count))
1091 GETBITS(ll[count], 4)
1092 for(count = numcells; count--;)
1093 if(cellmask & (UINT64(1)<<count))
1094 GETFLOAT(cnr[count], 6, 1.0)
1095 for(count = numcells; count--;)
1096 if(cellmask & (UINT64(1)<<count))
1097 GETFLOATSIGN(dop[count], 15, 0.0001)
1098 break;
1099 case 6:
1100 for(count = numcells; count--;)
1101 if(cellmask & (UINT64(1)<<count))
1102 GETFLOATSIGN(psr[count], 20, 0.001)
1103 for(count = numcells; count--;)
1104 if(cellmask & (UINT64(1)<<count))
1105 GETFLOATSIGN(cp[count], 22, 1/1024.0)
1106 for(count = numcells; count--;)
1107 if(cellmask & (UINT64(1)<<count))
1108 GETBITS(ll[count], 10)
1109 for(count = numcells; count--;)
1110 if(cellmask & (UINT64(1)<<count))
1111 GETFLOAT(cnr[count], 10, 0.1)
1112 case 7:
1113 for(count = numcells; count--;)
1114 if(cellmask & (UINT64(1)<<count))
1115 GETFLOATSIGN(psr[count], 20, 0.001)
1116 for(count = numcells; count--;)
1117 if(cellmask & (UINT64(1)<<count))
1118 GETFLOATSIGN(cp[count], 22, 1/1024.0)
1119 for(count = numcells; count--;)
1120 if(cellmask & (UINT64(1)<<count))
1121 GETBITS(ll[count], 10)
1122 for(count = numcells; count--;)
1123 if(cellmask & (UINT64(1)<<count))
1124 GETFLOAT(cnr[count], 10, 0.1)
1125 for(count = numcells; count--;)
1126 if(cellmask & (UINT64(1)<<count))
1127 GETFLOATSIGN(dop[count], 15, 0.0001)
1128 break;
1129 }
1130 i = RTCM3_MSM_NUMSAT;
1131 j = -1;
1132 for(count = numcells; count--;)
1133 {
1134 while(j >= 0 && !(sigmask&(1<<--j)))
1135 ;
1136 if(j < 0)
1137 {
1138 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1139 ;
1140 j = RTCM3_MSM_NUMSIG;
1141 while(!(sigmask&(1<<--j)))
1142 ;
1143 --numsat;
1144 }
1145 if(cellmask & (UINT64(1)<<count))
1146 {
1147 struct CodeData cd = {0,0,0,0,0,0,0};
1148 double wl = 0.0;
1149 switch(sys)
1150 {
1151 case RTCM3_MSM_GPS: cd = gps[RTCM3_MSM_NUMSIG-j-1];
1152 wl = cd.wl;
1153 break;
1154 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1155 {
1156 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1157 if(k)
1158 {
1159 if(cd.wl == 0.0)
1160 wl = GLO_WAVELENGTH_L1(k-100);
1161 else if(cd.wl == 1.0)
1162 wl = GLO_WAVELENGTH_L2(k-100);
1163 }
1164 }
1165 break;
1166 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1167 wl = cd.wl;
1168 break;
1169 }
1170 if(cd.lock && wl) /* lock cannot have a valid zero value */
1171 {
1172 int fullsat = sys+RTCM3_MSM_NUMSAT-i-1, num;
1173 /* FIXME: workaround for GIOVE */
1174 if(fullsat >= PRN_GALILEO_START && fullsat <= PRN_GALILEO_START+2)
1175 fullsat += PRN_GIOVE_START-PRN_GALILEO_START;
1176 for(num = 0; num < gnss->numsats
1177 && fullsat != gnss->satellites[num]; ++num)
1178 ;
1179
1180 if(num == gnss->numsats)
1181 gnss->satellites[gnss->numsats++] = fullsat;
1182
1183 switch(type % 10)
1184 {
1185 case 1:
1186 if(psr[count] > -327.68)
1187 {
1188 gnss->measdata[num][cd.typeR] = psr[count]
1189 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1190 gnss->dataflags[num] |= (1<<cd.typeR);
1191 }
1192 break;
1193 case 2:
1194 if(wl && cp[count] > -2048.0)
1195 {
1196 gnss->measdata[num][cd.typeP] = cp[count]
1197 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1198 if(handle->lastlockmsm[j][i] != ll[count])
1199 {
1200 gnss->dataflags2[num] |= cd.lock;
1201 handle->lastlockmsm[j][i] = ll[count];
1202 }
1203 gnss->dataflags[num] |= (1<<cd.typeP);
1204 }
1205 break;
1206 case 3:
1207 if(psr[count] > -327.68)
1208 {
1209 gnss->measdata[num][cd.typeR] = psr[count]
1210 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1211 gnss->dataflags[num] |= (1<<cd.typeR);
1212 }
1213
1214 if(wl && cp[count] > -2048.0)
1215 {
1216 gnss->measdata[num][cd.typeP] = cp[count]
1217 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1218 if(handle->lastlockmsm[j][i] != ll[count])
1219 {
1220 gnss->dataflags2[num] |= cd.lock;
1221 handle->lastlockmsm[j][i] = ll[count];
1222 }
1223 gnss->dataflags[num] |= (1<<cd.typeP);
1224 }
1225 break;
1226 case 4:
1227 if(psr[count] > -327.68)
1228 {
1229 gnss->measdata[num][cd.typeR] = psr[count]
1230 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1231 gnss->dataflags[num] |= (1<<cd.typeR);
1232 }
1233
1234 if(wl && cp[count] > -2048.0)
1235 {
1236 gnss->measdata[num][cd.typeP] = cp[count]
1237 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1238 if(handle->lastlockmsm[j][i] != ll[count])
1239 {
1240 gnss->dataflags2[num] |= cd.lock;
1241 handle->lastlockmsm[j][i] = ll[count];
1242 }
1243 gnss->dataflags[num] |= (1<<cd.typeP);
1244 }
1245
1246 gnss->measdata[num][cd.typeS] = cnr[count];
1247 gnss->dataflags[num] |= (1<<cd.typeS);
1248 break;
1249 case 5:
1250 if(psr[count] > -327.68)
1251 {
1252 gnss->measdata[num][cd.typeR] = psr[count]
1253 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1254 gnss->dataflags[num] |= (1<<cd.typeR);
1255 }
1256
1257 if(wl && cp[count] > -2048.0)
1258 {
1259 gnss->measdata[num][cd.typeP] = cp[count]
1260 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1261 if(handle->lastlockmsm[j][i] != ll[count])
1262 {
1263 gnss->dataflags2[num] |= cd.lock;
1264 handle->lastlockmsm[j][i] = ll[count];
1265 }
1266 gnss->dataflags[num] |= (1<<cd.typeP);
1267 }
1268
1269 gnss->measdata[num][cd.typeS] = cnr[count];
1270 gnss->dataflags[num] |= (1<<cd.typeS);
1271
1272 if(dop[count] > -1.6384)
1273 {
1274 gnss->measdata[num][cd.typeD] = dop[count]+rdop[numsat];
1275 gnss->dataflags[num] |= (1<<cd.typeD);
1276 }
1277 break;
1278 case 6:
1279 if(psr[count] > -524.288)
1280 {
1281 gnss->measdata[num][cd.typeR] = psr[count]
1282 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1283 gnss->dataflags[num] |= (1<<cd.typeR);
1284 }
1285
1286 if(wl && cp[count] > -2055.0)
1287 {
1288 gnss->measdata[num][cd.typeP] = cp[count]
1289 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1290 if(handle->lastlockmsm[j][i] != ll[count])
1291 {
1292 gnss->dataflags2[num] |= cd.lock;
1293 handle->lastlockmsm[j][i] = ll[count];
1294 }
1295 gnss->dataflags[num] |= (1<<cd.typeP);
1296 }
1297
1298 gnss->measdata[num][cd.typeS] = cnr[count];
1299 gnss->dataflags[num] |= (1<<cd.typeS);
1300 break;
1301 case 7:
1302 if(psr[count] > -524.288)
1303 {
1304 gnss->measdata[num][cd.typeR] = psr[count]
1305 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1306 gnss->dataflags[num] |= (1<<cd.typeR);
1307 }
1308
1309 if(wl && cp[count] > -2055.0)
1310 {
1311 gnss->measdata[num][cd.typeP] = cp[count]
1312 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1313 if(handle->lastlockmsm[j][i] != ll[count])
1314 {
1315 gnss->dataflags2[num] |= cd.lock;
1316 handle->lastlockmsm[j][i] = ll[count];
1317 }
1318 gnss->dataflags[num] |= (1<<cd.typeP);
1319 }
1320
1321 gnss->measdata[num][cd.typeS] = cnr[count];
1322 gnss->dataflags[num] |= (1<<cd.typeS);
1323
1324 if(dop[count] > -1.6384)
1325 {
1326 gnss->measdata[num][cd.typeD] = dop[count]+rdop[numsat];
1327 gnss->dataflags[num] |= (1<<cd.typeD);
1328 }
1329 break;
1330 }
1331 }
1332 }
1333 }
1334 }
1335 if(!syncf && !old)
1336 {
1337 handle->Data = *gnss;
1338 memset(gnss, 0, sizeof(*gnss));
1339 }
1340 if(!syncf || old)
1341 {
1342 if(!wasnoamb) /* not RINEX compatible without */
1343 ret = 1;
1344 else
1345 ret = 2;
1346 }
1347#ifdef NO_RTCM3_MAIN
1348 else
1349 ret = type;
1350#endif /* NO_RTCM3_MAIN */
1351 }
1352 break;
1353 }
1354 }
1355 return ret;
1356}
1357
1358struct Header
1359{
1360 const char *version;
1361 const char *pgm;
1362 const char *marker;
1363 const char *markertype;
1364 const char *observer;
1365 const char *receiver;
1366 const char *antenna;
1367 const char *position;
1368 const char *antennaposition;
1369 const char *wavelength;
1370 const char *typesofobs; /* should not be modified outside */
1371 const char *typesofobsG; /* should not be modified outside */
1372 const char *typesofobsR; /* should not be modified outside */
1373 const char *typesofobsS; /* should not be modified outside */
1374 const char *typesofobsE; /* should not be modified outside */
1375 const char *timeoffirstobs; /* should not be modified outside */
1376};
1377
1378#define MAXHEADERLINES 50
1379#define MAXHEADERBUFFERSIZE 4096
1380struct HeaderData
1381{
1382 union
1383 {
1384 struct Header named;
1385 const char *unnamed[MAXHEADERLINES];
1386 } data;
1387 int numheaders;
1388};
1389
1390void converttime(struct converttimeinfo *c, int week, int tow)
1391{
1392 int i, k, doy, j; /* temporary variables */
1393 j = week*(7*24*60*60) + tow + 5*24*60*60;
1394 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1395 j -= k;
1396 c->year = i;
1397 doy = 1+ (j / (24*60*60));
1398 j %= (24*60*60);
1399 c->hour = j / (60*60);
1400 j %= (60*60);
1401 c->minute = j / 60;
1402 c->second = j % 60;
1403 j = 0;
1404 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1405 j += k;
1406 c->month = i;
1407 c->day = doy - j;
1408}
1409
1410#ifndef NO_RTCM3_MAIN
1411void RTCM3Error(const char *fmt, ...)
1412{
1413 va_list v;
1414 va_start(v, fmt);
1415 vfprintf(stderr, fmt, v);
1416 va_end(v);
1417}
1418#endif
1419
1420void RTCM3Text(const char *fmt, ...)
1421{
1422 va_list v;
1423 va_start(v, fmt);
1424 vprintf(fmt, v);
1425 va_end(v);
1426}
1427
1428static void fixrevision(void)
1429{
1430 if(revisionstr[0] == '$')
1431 {
1432 char *a;
1433 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1434 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1435 for(a = revisionstr+11; *a && *a != ' '; ++a)
1436 revisionstr[i++] = *a;
1437 revisionstr[i] = 0;
1438 }
1439}
1440
1441static int HandleRunBy(char *buffer, int buffersize, const char **u,
1442int rinex3)
1443{
1444 const char *user;
1445 time_t t;
1446 struct tm * t2;
1447
1448#ifdef NO_RTCM3_MAIN
1449 fixrevision();
1450#endif
1451
1452 user= getenv("USER");
1453 if(!user) user = "";
1454 t = time(&t);
1455 t2 = gmtime(&t);
1456 if(u) *u = user;
1457 return 1+snprintf(buffer, buffersize,
1458 rinex3 ?
1459 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1460 "PGM / RUN BY / DATE" :
1461 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1462 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1463 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1464}
1465
1466#ifdef NO_RTCM3_MAIN
1467#define NUMSTARTSKIP 1
1468#else
1469#define NUMSTARTSKIP 3
1470#endif
1471
1472void HandleHeader(struct RTCM3ParserData *Parser)
1473{
1474#ifdef NO_RTCM3_MAIN
1475 int i;
1476 if(Parser->allflags == 0)
1477 Parser->allflags = ~0;
1478 if(Parser->rinex3)
1479 {
1480#define CHECKFLAGSNEW(a, b, c) \
1481 if(Parser->allflags & GNSSDF_##b##DATA) \
1482 { \
1483 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1484 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1485 ++Parser->numdatatypes##a; \
1486 }
1487
1488 CHECKFLAGSNEW(GPS, C1, C1C)
1489 CHECKFLAGSNEW(GPS, L1C, L1C)
1490 CHECKFLAGSNEW(GPS, D1C, D1C)
1491 CHECKFLAGSNEW(GPS, S1C, S1C)
1492 CHECKFLAGSNEW(GPS, P1, C1P)
1493 CHECKFLAGSNEW(GPS, L1P, L1P)
1494 CHECKFLAGSNEW(GPS, D1P, D1P)
1495 CHECKFLAGSNEW(GPS, S1P, S1P)
1496 CHECKFLAGSNEW(GPS, P2, C2P)
1497 CHECKFLAGSNEW(GPS, L2P, L2P)
1498 CHECKFLAGSNEW(GPS, D2P, D2P)
1499 CHECKFLAGSNEW(GPS, S2P, S2P)
1500 CHECKFLAGSNEW(GPS, C2, C2X)
1501 CHECKFLAGSNEW(GPS, L2C, L2X)
1502 CHECKFLAGSNEW(GPS, D2C, D2X)
1503 CHECKFLAGSNEW(GPS, S2C, S2X)
1504 CHECKFLAGSNEW(GLO, C1, C1C)
1505 CHECKFLAGSNEW(GLO, L1C, L1C)
1506 CHECKFLAGSNEW(GLO, D1C, D1C)
1507 CHECKFLAGSNEW(GLO, S1C, S1C)
1508 CHECKFLAGSNEW(GLO, P1, C1P)
1509 CHECKFLAGSNEW(GLO, L1P, L1P)
1510 CHECKFLAGSNEW(GLO, D1P, D1P)
1511 CHECKFLAGSNEW(GLO, S1P, S1P)
1512 CHECKFLAGSNEW(GLO, P2, C2P)
1513 CHECKFLAGSNEW(GLO, L2P, L2P)
1514 CHECKFLAGSNEW(GLO, D2P, D2P)
1515 CHECKFLAGSNEW(GLO, S2P, S2P)
1516 CHECKFLAGSNEW(GLO, C2, C2C)
1517 CHECKFLAGSNEW(GLO, L2C, L2C)
1518 CHECKFLAGSNEW(GLO, D2C, D2C)
1519 CHECKFLAGSNEW(GLO, S2C, S2C)
1520 }
1521 else
1522 {
1523#define CHECKFLAGS(a, b) \
1524 if(Parser->allflags & GNSSDF_##a##DATA) \
1525 { \
1526 if(data[RINEXENTRY_##b##DATA]) \
1527 { \
1528 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1529 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1530 } \
1531 else \
1532 { \
1533 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1534 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1535 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1536 } \
1537 }
1538
1539 int data[RINEXENTRY_NUMBER];
1540 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
1541
1542 CHECKFLAGS(C1,C1)
1543 CHECKFLAGS(C2,C2)
1544 CHECKFLAGS(P1,P1)
1545 CHECKFLAGS(P2,P2)
1546 CHECKFLAGS(L1C,L1)
1547 CHECKFLAGS(L1P,L1)
1548 CHECKFLAGS(L2C,L2)
1549 CHECKFLAGS(L2P,L2)
1550 CHECKFLAGS(D1C,D1)
1551 CHECKFLAGS(D1P,D1)
1552 CHECKFLAGS(D2C,D2)
1553 CHECKFLAGS(D2P,D2)
1554 CHECKFLAGS(S1C,S1)
1555 CHECKFLAGS(S1P,S1)
1556 CHECKFLAGS(S2C,S2)
1557 CHECKFLAGS(S2P,S2)
1558 CHECKFLAGS(C5,C5)
1559 CHECKFLAGS(L5,L5)
1560 CHECKFLAGS(D5,D5)
1561 CHECKFLAGS(S5,S5)
1562 CHECKFLAGS(C5AB,C5AB)
1563 CHECKFLAGS(L5AB,L5AB)
1564 CHECKFLAGS(D5AB,D5AB)
1565 CHECKFLAGS(S5AB,S5AB)
1566 CHECKFLAGS(C5B,C5B)
1567 CHECKFLAGS(L5B,L5B)
1568 CHECKFLAGS(D5B,D5B)
1569 CHECKFLAGS(S5B,S5B)
1570 CHECKFLAGS(C6,C6)
1571 CHECKFLAGS(L6,L6)
1572 CHECKFLAGS(D6,D6)
1573 CHECKFLAGS(S6,S6)
1574 }
1575#else /* NO_RTCM3_MAIN */
1576 struct HeaderData hdata;
1577 char thebuffer[MAXHEADERBUFFERSIZE];
1578 char *buffer = thebuffer;
1579 size_t buffersize = sizeof(thebuffer);
1580 int i;
1581
1582 memset(&hdata, 0, sizeof(hdata));
1583
1584 hdata.data.named.version = buffer;
1585 i = 1+snprintf(buffer, buffersize,
1586 "%9.2f OBSERVATION DATA M (Mixed)"
1587 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1588 buffer += i; buffersize -= i;
1589
1590 {
1591 const char *str;
1592 hdata.data.named.pgm = buffer;
1593 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1594 buffer += i; buffersize -= i;
1595 hdata.data.named.observer = buffer;
1596 i = 1+snprintf(buffer, buffersize,
1597 "%-20.20s "
1598 "OBSERVER / AGENCY", str);
1599 buffer += i; buffersize -= i;
1600 }
1601
1602 hdata.data.named.marker =
1603 "RTCM3TORINEX "
1604 "MARKER NAME";
1605
1606 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1607 "GEODETIC "
1608 "MARKER TYPE";
1609
1610 hdata.data.named.receiver =
1611 " "
1612 "REC # / TYPE / VERS";
1613
1614 hdata.data.named.antenna =
1615 " "
1616 "ANT # / TYPE";
1617
1618 hdata.data.named.position =
1619 " .0000 .0000 .0000 "
1620 "APPROX POSITION XYZ";
1621
1622 hdata.data.named.antennaposition =
1623 " .0000 .0000 .0000 "
1624 "ANTENNA: DELTA H/E/N";
1625
1626 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1627 " 1 1 "
1628 "WAVELENGTH FACT L1/2";
1629
1630 if(Parser->rinex3)
1631 {
1632#define CHECKFLAGSNEW(a, b, c) \
1633 if(flags & GNSSDF_##b##DATA) \
1634 { \
1635 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1636 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1637 ++Parser->numdatatypes##a; \
1638 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-3s", #c); \
1639 tbufferpos += 4; \
1640 }
1641
1642 int flags = Parser->startflags;
1643 char tbuffer[6*RINEXENTRY_NUMBER+1];
1644 int tbufferpos = 0;
1645 for(i = 0; i < Parser->Data.numsats; ++i)
1646 flags |= Parser->Data.dataflags[i];
1647
1648 CHECKFLAGSNEW(GPS, C1, C1C)
1649 CHECKFLAGSNEW(GPS, L1C, L1C)
1650 CHECKFLAGSNEW(GPS, D1C, D1C)
1651 CHECKFLAGSNEW(GPS, S1C, S1C)
1652 CHECKFLAGSNEW(GPS, P1, C1W)
1653 CHECKFLAGSNEW(GPS, L1P, L1W)
1654 CHECKFLAGSNEW(GPS, D1P, D1W)
1655 CHECKFLAGSNEW(GPS, S1P, S1W)
1656
1657 hdata.data.named.typesofobsS = buffer;
1658 i = 1+snprintf(buffer, buffersize,
1659 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1660 buffer += i; buffersize -= i;
1661
1662 CHECKFLAGSNEW(GPS, P2, C2P)
1663 CHECKFLAGSNEW(GPS, L2P, L2P)
1664 CHECKFLAGSNEW(GPS, D2P, D2P)
1665 CHECKFLAGSNEW(GPS, S2P, S2P)
1666 CHECKFLAGSNEW(GPS, C2, C2X)
1667 CHECKFLAGSNEW(GPS, L2C, L2X)
1668 CHECKFLAGSNEW(GPS, D2C, D2X)
1669 CHECKFLAGSNEW(GPS, S2C, S2X)
1670 CHECKFLAGSNEW(GPS, C5, C5)
1671 CHECKFLAGSNEW(GPS, L5, L5)
1672 CHECKFLAGSNEW(GPS, D5, D5)
1673 CHECKFLAGSNEW(GPS, S5, S5)
1674
1675 hdata.data.named.typesofobsG = buffer;
1676 i = 1+snprintf(buffer, buffersize,
1677 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1678 if(Parser->numdatatypesGPS>13)
1679 {
1680 i += snprintf(buffer+i-1, buffersize,
1681 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1682 }
1683 buffer += i; buffersize -= i;
1684
1685 tbufferpos = 0;
1686
1687 CHECKFLAGSNEW(GLO, C1, C1C)
1688 CHECKFLAGSNEW(GLO, L1C, L1C)
1689 CHECKFLAGSNEW(GLO, D1C, D1C)
1690 CHECKFLAGSNEW(GLO, S1C, S1C)
1691 CHECKFLAGSNEW(GLO, P1, C1P)
1692 CHECKFLAGSNEW(GLO, L1P, L1P)
1693 CHECKFLAGSNEW(GLO, D1P, D1P)
1694 CHECKFLAGSNEW(GLO, S1P, S1P)
1695 CHECKFLAGSNEW(GLO, P2, C2P)
1696 CHECKFLAGSNEW(GLO, L2P, L2P)
1697 CHECKFLAGSNEW(GLO, D2P, D2P)
1698 CHECKFLAGSNEW(GLO, S2P, S2P)
1699 CHECKFLAGSNEW(GLO, C2, C2C)
1700 CHECKFLAGSNEW(GLO, L2C, L2C)
1701 CHECKFLAGSNEW(GLO, D2C, D2C)
1702 CHECKFLAGSNEW(GLO, S2C, S2C)
1703
1704 hdata.data.named.typesofobsR = buffer;
1705 i = 1+snprintf(buffer, buffersize,
1706 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1707 if(Parser->numdatatypesGLO>13)
1708 {
1709 i += snprintf(buffer+i-1, buffersize,
1710 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1711 }
1712 buffer += i; buffersize -= i;
1713
1714 tbufferpos = 0;
1715
1716 CHECKFLAGSNEW(GAL, C1, C1)
1717 CHECKFLAGSNEW(GAL, L1C, L1)
1718 CHECKFLAGSNEW(GAL, D1C, D1)
1719 CHECKFLAGSNEW(GAL, S1C, S1)
1720 CHECKFLAGSNEW(GAL, C6, C6)
1721 CHECKFLAGSNEW(GAL, L6, L6)
1722 CHECKFLAGSNEW(GAL, D6, D6)
1723 CHECKFLAGSNEW(GAL, S6, S6)
1724 CHECKFLAGSNEW(GAL, C5, C5)
1725 CHECKFLAGSNEW(GAL, L5, L5)
1726 CHECKFLAGSNEW(GAL, D5, D5)
1727 CHECKFLAGSNEW(GAL, S5, S5)
1728 CHECKFLAGSNEW(GAL, C5B, C7)
1729 CHECKFLAGSNEW(GAL, L5B, L7)
1730 CHECKFLAGSNEW(GAL, D5B, D7)
1731 CHECKFLAGSNEW(GAL, S5B, S7)
1732 CHECKFLAGSNEW(GAL, C5AB, C8)
1733 CHECKFLAGSNEW(GAL, L5AB, L8)
1734 CHECKFLAGSNEW(GAL, D5AB, D8)
1735 CHECKFLAGSNEW(GAL, S5AB, S8)
1736
1737 hdata.data.named.typesofobsE = buffer;
1738 i = 1+snprintf(buffer, buffersize,
1739 "E %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGAL, tbuffer);
1740 if(Parser->numdatatypesGAL>13)
1741 {
1742 i += snprintf(buffer+i-1, buffersize,
1743 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1744 }
1745 buffer += i; buffersize -= i;
1746 }
1747 else
1748 {
1749#define CHECKFLAGS(a, b) \
1750 if(flags & GNSSDF_##a##DATA) \
1751 { \
1752 if(data[RINEXENTRY_##b##DATA]) \
1753 { \
1754 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1755 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1756 } \
1757 else \
1758 { \
1759 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1760 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1761 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1762 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1763 tbufferpos += 6; \
1764 } \
1765 }
1766
1767 int flags = Parser->startflags;
1768 int data[RINEXENTRY_NUMBER];
1769 char tbuffer[6*RINEXENTRY_NUMBER+1];
1770 int tbufferpos = 0;
1771 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1772 data[i] = 0;
1773 for(i = 0; i < Parser->Data.numsats; ++i)
1774 flags |= Parser->Data.dataflags[i];
1775
1776 CHECKFLAGS(C1,C1)
1777 CHECKFLAGS(C2,C2)
1778 CHECKFLAGS(P1,P1)
1779 CHECKFLAGS(P2,P2)
1780 CHECKFLAGS(L1C,L1)
1781 CHECKFLAGS(L1P,L1)
1782 CHECKFLAGS(L2C,L2)
1783 CHECKFLAGS(L2P,L2)
1784 CHECKFLAGS(D1C,D1)
1785 CHECKFLAGS(D1P,D1)
1786 CHECKFLAGS(D2C,D2)
1787 CHECKFLAGS(D2P,D2)
1788 CHECKFLAGS(S1C,S1)
1789 CHECKFLAGS(S1P,S1)
1790 CHECKFLAGS(S2C,S2)
1791 CHECKFLAGS(S2P,S2)
1792 CHECKFLAGS(C5,C5)
1793 CHECKFLAGS(L5,L5)
1794 CHECKFLAGS(D5,D5)
1795 CHECKFLAGS(S5,S5)
1796 CHECKFLAGS(C5AB,C5AB)
1797 CHECKFLAGS(L5AB,L5AB)
1798 CHECKFLAGS(D5AB,D5AB)
1799 CHECKFLAGS(S5AB,S5AB)
1800 CHECKFLAGS(C5B,C5B)
1801 CHECKFLAGS(L5B,L5B)
1802 CHECKFLAGS(D5B,D5B)
1803 CHECKFLAGS(S5B,S5B)
1804 CHECKFLAGS(C6,C6)
1805 CHECKFLAGS(L6,L6)
1806 CHECKFLAGS(D6,D6)
1807 CHECKFLAGS(S6,S6)
1808
1809 hdata.data.named.typesofobs = buffer;
1810 i = 1+snprintf(buffer, buffersize,
1811 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1812 if(Parser->numdatatypesGPS>9)
1813 {
1814 i += snprintf(buffer+i-1, buffersize,
1815 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1816 }
1817 buffer += i; buffersize -= i;
1818 }
1819
1820 {
1821 struct converttimeinfo cti;
1822 converttime(&cti, Parser->Data.week,
1823 (int)floor(Parser->Data.timeofweek/1000.0));
1824 hdata.data.named.timeoffirstobs = buffer;
1825 i = 1+snprintf(buffer, buffersize,
1826 " %4d %2d %2d %2d %2d %10.7f GPS "
1827 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1828 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1829
1830 buffer += i; buffersize -= i;
1831 }
1832
1833 hdata.numheaders = 15;
1834
1835 if(Parser->headerfile)
1836 {
1837 FILE *fh;
1838 if((fh = fopen(Parser->headerfile, "r")))
1839 {
1840 size_t siz;
1841 char *lastblockstart;
1842 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1843 {
1844 buffer[siz] = '\n';
1845 if(siz == buffersize)
1846 {
1847 RTCM3Error("Header file is too large. Only %d bytes read.",
1848 (int)siz);
1849 }
1850 /* scan the file line by line and enter the entries in the list */
1851 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1852 /* overwrites entries, except for comments */
1853 lastblockstart = buffer;
1854 for(i = 0; i < (int)siz; ++i)
1855 {
1856 if(buffer[i] == '\n')
1857 { /* we found a line */
1858 char *end;
1859 while(buffer[i+1] == '\r')
1860 ++i; /* skip \r in case there are any */
1861 end = buffer+i;
1862 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1863 *(end--) = 0;
1864 if(end-lastblockstart < 60+5) /* short line */
1865 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1866 else
1867 {
1868 int pos;
1869 if(!strcmp("COMMENT", lastblockstart+60))
1870 pos = hdata.numheaders;
1871 else
1872 {
1873 for(pos = 0; pos < hdata.numheaders; ++pos)
1874 {
1875 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
1876 break;
1877 }
1878 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
1879 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
1880 {
1881 RTCM3Error("Overwriting header '%s' is dangerous.\n",
1882 lastblockstart+60);
1883 }
1884 }
1885 if(pos >= MAXHEADERLINES)
1886 {
1887 RTCM3Error("Maximum number of header lines of %d reached.\n",
1888 MAXHEADERLINES);
1889 }
1890 else if(!strcmp("END OF HEADER", lastblockstart+60))
1891 {
1892 RTCM3Error("End of header ignored.\n");
1893 }
1894 else
1895 {
1896 hdata.data.unnamed[pos] = lastblockstart;
1897 if(pos == hdata.numheaders)
1898 ++hdata.numheaders;
1899 }
1900 }
1901 lastblockstart = buffer+i+1;
1902 }
1903 }
1904 }
1905 else
1906 {
1907 RTCM3Error("Could not read data from headerfile '%s'.\n",
1908 Parser->headerfile);
1909 }
1910 fclose(fh);
1911 }
1912 else
1913 {
1914 RTCM3Error("Could not open header datafile '%s'.\n",
1915 Parser->headerfile);
1916 }
1917 }
1918
1919 for(i = 0; i < hdata.numheaders; ++i)
1920 {
1921 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
1922 RTCM3Text("%s\n", hdata.data.unnamed[i]);
1923 }
1924 RTCM3Text(" "
1925 "END OF HEADER\n");
1926#endif
1927}
1928
1929static void ConvLine(FILE *file, const char *fmt, ...)
1930{
1931 char buffer[100], *b;
1932 va_list v;
1933 va_start(v, fmt);
1934 vsnprintf(buffer, sizeof(buffer), fmt, v);
1935 for(b = buffer; *b; ++b)
1936 {
1937 if(*b == 'e') *b = 'D';
1938 }
1939 fprintf(file, "%s", buffer);
1940 va_end(v);
1941}
1942
1943void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
1944{
1945 Parser->Message[Parser->MessageSize++] = byte;
1946 if(Parser->MessageSize >= Parser->NeedBytes)
1947 {
1948 int r;
1949 while((r = RTCM3Parser(Parser)))
1950 {
1951 if(r == 1020 || r == 1019)
1952 {
1953 FILE *file = 0;
1954
1955 if(Parser->rinex3 && !(file = Parser->gpsfile))
1956 {
1957 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
1958 if(n)
1959 {
1960 if(!(Parser->gpsfile = fopen(n, "w")))
1961 {
1962 RTCM3Error("Could not open ephemeris output file.\n");
1963 }
1964 else
1965 {
1966 char buffer[100];
1967 fprintf(Parser->gpsfile,
1968 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
1969 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1970 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1971 }
1972 Parser->gpsephemeris = 0;
1973 Parser->glonassephemeris = 0;
1974 file = Parser->gpsfile;
1975 }
1976 }
1977 else
1978 {
1979 if(r == 1020)
1980 {
1981 if(Parser->glonassephemeris)
1982 {
1983 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
1984 {
1985 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
1986 }
1987 else
1988 {
1989 char buffer[100];
1990 fprintf(Parser->glonassfile,
1991 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
1992 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1993 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1994 }
1995 Parser->glonassephemeris = 0;
1996 }
1997 file = Parser->glonassfile;
1998 }
1999 else if(r == 1019)
2000 {
2001 if(Parser->gpsephemeris)
2002 {
2003 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2004 {
2005 RTCM3Error("Could not open GPS ephemeris output file.\n");
2006 }
2007 else
2008 {
2009 char buffer[100];
2010 fprintf(Parser->gpsfile,
2011 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2012 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2013 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2014 }
2015 Parser->gpsephemeris = 0;
2016 }
2017 file = Parser->gpsfile;
2018 }
2019 }
2020 if(file)
2021 {
2022 if(r == 1020)
2023 {
2024 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2025 int w = e->GPSWeek, tow = e->GPSTOW, i;
2026 struct converttimeinfo cti;
2027
2028 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2029 converttime(&cti, w, tow);
2030
2031 i = e->tk-3*60*60; if(i < 0) i += 86400;
2032
2033 if(Parser->rinex3)
2034 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2035 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2036 cti.second, -e->tau, e->gamma, (double) i);
2037 else
2038 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2039 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2040 (double) cti.second, -e->tau, e->gamma, (double) i);
2041 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2042 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2043 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2044 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2045 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2046 e->z_velocity, e->z_acceleration, (double) e->E);
2047 }
2048 else /* if(r == 1019) */
2049 {
2050 struct gpsephemeris *e = &Parser->ephemerisGPS;
2051 double d; /* temporary variable */
2052 unsigned long int i; /* temporary variable */
2053 struct converttimeinfo cti;
2054 converttime(&cti, e->GPSweek, e->TOC);
2055
2056 if(Parser->rinex3)
2057 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2058 e->satellite, cti.year, cti.month, cti.day, cti.hour,
2059 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2060 e->clock_driftrate);
2061 else
2062 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2063 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2064 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2065 e->clock_driftrate);
2066 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2067 e->Crs, e->Delta_n, e->M0);
2068 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2069 e->e, e->Cus, e->sqrt_A);
2070 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
2071 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2072 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2073 e->Crc, e->omega, e->OMEGADOT);
2074 d = 0;
2075 i = e->flags;
2076 if(i & GPSEPHF_L2CACODE)
2077 d += 2.0;
2078 if(i & GPSEPHF_L2PCODE)
2079 d += 1.0;
2080 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2081 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2082 if(e->URAindex <= 6) /* URA index */
2083 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2084 else
2085 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2086 /* 15 indicates not to use satellite. We can't handle this special
2087 case, so we create a high "non"-accuracy value. */
2088 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
2089 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2090
2091 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2092 /* TOW */
2093 }
2094 }
2095 }
2096 else if (r == 1 || r == 2)
2097 {
2098 int i, j, o;
2099 struct converttimeinfo cti;
2100
2101 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2102 {
2103 ++Parser->init;
2104
2105 if(Parser->init == NUMSTARTSKIP)
2106 HandleHeader(Parser);
2107 else
2108 {
2109 for(i = 0; i < Parser->Data.numsats; ++i)
2110 Parser->startflags |= Parser->Data.dataflags[i];
2111 continue;
2112 }
2113 }
2114 if(r == 2 && !Parser->validwarning)
2115 {
2116 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2117 " COMMENT\n");
2118 Parser->validwarning = 1;
2119 }
2120
2121 converttime(&cti, Parser->Data.week,
2122 (int)floor(Parser->Data.timeofweek/1000.0));
2123 if(Parser->rinex3)
2124 {
2125 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
2126 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2127 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2128 for(i = 0; i < Parser->Data.numsats; ++i)
2129 {
2130 int glo = 0, gal = 0;
2131 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2132 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2133 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2134 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2135 {
2136 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2137 glo = 1;
2138 }
2139 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2140 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2141 {
2142 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2143 gal = 1;
2144 }
2145 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2146 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2147 {
2148 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2149 gal = 1;
2150 }
2151 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2152 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2153 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
2154 else
2155 RTCM3Text("%3d", Parser->Data.satellites[i]);
2156
2157 if(glo)
2158 {
2159 for(j = 0; j < Parser->numdatatypesGLO; ++j)
2160 {
2161 int df = Parser->dataflagGLO[j];
2162 int pos = Parser->dataposGLO[j];
2163 if((Parser->Data.dataflags[i] & df)
2164 && !isnan(Parser->Data.measdata[i][pos])
2165 && !isinf(Parser->Data.measdata[i][pos]))
2166 {
2167 char lli = ' ';
2168 char snr = ' ';
2169 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2170 {
2171 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2172 lli = '1';
2173 snr = '0'+Parser->Data.snrL1[i];
2174 }
2175 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2176 {
2177 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2178 lli = '1';
2179 snr = '0'+Parser->Data.snrL2[i];
2180 }
2181 RTCM3Text("%14.3f%c%c",
2182 Parser->Data.measdata[i][pos],lli,snr);
2183 }
2184 else
2185 { /* no or illegal data */
2186 RTCM3Text(" ");
2187 }
2188 }
2189 }
2190 else if(gal)
2191 {
2192 for(j = 0; j < Parser->numdatatypesGAL; ++j)
2193 {
2194 int df = Parser->dataflagGAL[j];
2195 int pos = Parser->dataposGAL[j];
2196 if((Parser->Data.dataflags[i] & df)
2197 && !isnan(Parser->Data.measdata[i][pos])
2198 && !isinf(Parser->Data.measdata[i][pos]))
2199 {
2200 char lli = ' ';
2201 char snr = ' ';
2202 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2203 {
2204 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2205 lli = '1';
2206 snr = '0'+Parser->Data.snrL1[i];
2207 }
2208 if(df & GNSSDF_L6DATA)
2209 {
2210 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2211 lli = '1';
2212 snr = ' ';
2213 }
2214 if(df & GNSSDF_L5DATA)
2215 {
2216 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2217 lli = '1';
2218 snr = ' ';
2219 }
2220 if(df & GNSSDF_L5BDATA)
2221 {
2222 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2223 lli = '1';
2224 snr = ' ';
2225 }
2226 if(df & GNSSDF_L5ABDATA)
2227 {
2228 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2229 lli = '1';
2230 snr = ' ';
2231 }
2232 RTCM3Text("%14.3f%c%c",
2233 Parser->Data.measdata[i][pos],lli,snr);
2234 }
2235 else
2236 { /* no or illegal data */
2237 RTCM3Text(" ");
2238 }
2239 }
2240 }
2241 else
2242 {
2243 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2244 {
2245 int df = Parser->dataflagGPS[j];
2246 int pos = Parser->dataposGPS[j];
2247 if((Parser->Data.dataflags[i] & df)
2248 && !isnan(Parser->Data.measdata[i][pos])
2249 && !isinf(Parser->Data.measdata[i][pos]))
2250 {
2251 char lli = ' ';
2252 char snr = ' ';
2253 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2254 {
2255 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2256 lli = '1';
2257 snr = '0'+Parser->Data.snrL1[i];
2258 }
2259 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2260 {
2261 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2262 lli = '1';
2263 snr = '0'+Parser->Data.snrL2[i];
2264 }
2265 if(df & GNSSDF_L5DATA)
2266 {
2267 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2268 lli = '1';
2269 snr = ' ';
2270 }
2271 RTCM3Text("%14.3f%c%c",
2272 Parser->Data.measdata[i][pos],lli,snr);
2273 }
2274 else
2275 { /* no or illegal data */
2276 RTCM3Text(" ");
2277 }
2278 }
2279 }
2280 RTCM3Text("\n");
2281 }
2282 }
2283 else
2284 {
2285 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
2286 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2287 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2288 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2289 {
2290 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2291 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2292 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2293 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2294 RTCM3Text("R%02d", Parser->Data.satellites[i]
2295 - (PRN_GLONASS_START-1));
2296 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2297 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2298 RTCM3Text("S%02d", Parser->Data.satellites[i]
2299 - PRN_WAAS_START+20);
2300 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2301 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2302 RTCM3Text("E%02d", Parser->Data.satellites[i]
2303 - (PRN_GALILEO_START-1));
2304 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2305 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2306 RTCM3Text("E%02d", Parser->Data.satellites[i]
2307 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2308 else
2309 RTCM3Text("%3d", Parser->Data.satellites[i]);
2310 }
2311 RTCM3Text("\n");
2312 o = 12;
2313 j = Parser->Data.numsats - 12;
2314 while(j > 0)
2315 {
2316 RTCM3Text(" ");
2317 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2318 {
2319 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2320 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2321 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2322 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2323 RTCM3Text("R%02d", Parser->Data.satellites[i]
2324 - (PRN_GLONASS_START-1));
2325 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2326 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2327 RTCM3Text("S%02d", Parser->Data.satellites[i]
2328 - PRN_WAAS_START+20);
2329 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2330 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2331 RTCM3Text("E%02d", Parser->Data.satellites[i]
2332 - (PRN_GALILEO_START-1));
2333 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2334 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2335 RTCM3Text("E%02d", Parser->Data.satellites[i]
2336 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2337 else
2338 RTCM3Text("%3d", Parser->Data.satellites[i]);
2339 }
2340 RTCM3Text("\n");
2341 j -= 12;
2342 o += 12;
2343 }
2344 for(i = 0; i < Parser->Data.numsats; ++i)
2345 {
2346 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2347 {
2348 int v = 0;
2349 int df = Parser->dataflag[j];
2350 int pos = Parser->datapos[j];
2351 if((Parser->Data.dataflags[i] & df)
2352 && !isnan(Parser->Data.measdata[i][pos])
2353 && !isinf(Parser->Data.measdata[i][pos]))
2354 {
2355 v = 1;
2356 }
2357 else
2358 {
2359 df = Parser->dataflagGPS[j];
2360 pos = Parser->dataposGPS[j];
2361
2362 if((Parser->Data.dataflags[i] & df)
2363 && !isnan(Parser->Data.measdata[i][pos])
2364 && !isinf(Parser->Data.measdata[i][pos]))
2365 {
2366 v = 1;
2367 }
2368 }
2369
2370 if(!v)
2371 { /* no or illegal data */
2372 RTCM3Text(" ");
2373 }
2374 else
2375 {
2376 char lli = ' ';
2377 char snr = ' ';
2378 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2379 {
2380 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2381 lli = '1';
2382 snr = '0'+Parser->Data.snrL1[i];
2383 }
2384 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2385 {
2386 if(Parser->Data.dataflags2[i]
2387 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2388 {
2389 lli = '0';
2390 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2391 lli += 1;
2392 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2393 lli += 4;
2394 }
2395 snr = '0'+Parser->Data.snrL2[i];
2396 }
2397 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2398 & GNSSDF2_XCORRL2))
2399 lli = '4';
2400 RTCM3Text("%14.3f%c%c",
2401 Parser->Data.measdata[i][pos],lli,snr);
2402 }
2403 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
2404 RTCM3Text("\n");
2405 }
2406 }
2407 }
2408 }
2409 }
2410 }
2411}
2412
2413#ifndef NO_RTCM3_MAIN
2414static char datestr[] = "$Date: 2010-11-15 13:08:27 +0000 (Mon, 15 Nov 2010) $";
2415
2416/* The string, which is send as agent in HTTP request */
2417#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2418
2419#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2420
2421static const char encodingTable [64] = {
2422 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2423 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2424 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2425 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2426};
2427
2428/* does not buffer overrun, but breaks directly after an error */
2429/* returns the number of required bytes */
2430static int encode(char *buf, int size, const char *user, const char *pwd)
2431{
2432 unsigned char inbuf[3];
2433 char *out = buf;
2434 int i, sep = 0, fill = 0, bytes = 0;
2435
2436 while(*user || *pwd)
2437 {
2438 i = 0;
2439 while(i < 3 && *user) inbuf[i++] = *(user++);
2440 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
2441 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
2442 while(i < 3) {inbuf[i++] = 0; ++fill; }
2443 if(out-buf < size-1)
2444 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2445 if(out-buf < size-1)
2446 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2447 | ((inbuf [1] & 0xF0) >> 4)];
2448 if(out-buf < size-1)
2449 {
2450 if(fill == 2)
2451 *(out++) = '=';
2452 else
2453 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2454 | ((inbuf [2] & 0xC0) >> 6)];
2455 }
2456 if(out-buf < size-1)
2457 {
2458 if(fill >= 1)
2459 *(out++) = '=';
2460 else
2461 *(out++) = encodingTable[inbuf [2] & 0x3F];
2462 }
2463 bytes += 4;
2464 }
2465 if(out-buf < size)
2466 *out = 0;
2467 return bytes;
2468}
2469
2470static int stop = 0;
2471
2472struct Args
2473{
2474 const char *server;
2475 const char *port;
2476 int mode;
2477 int timeout;
2478 int rinex3;
2479 const char *user;
2480 const char *password;
2481 const char *proxyhost;
2482 const char *proxyport;
2483 const char *nmea;
2484 const char *data;
2485 const char *headerfile;
2486 const char *gpsephemeris;
2487 const char *glonassephemeris;
2488};
2489
2490/* option parsing */
2491#ifdef NO_LONG_OPTS
2492#define LONG_OPT(a)
2493#else
2494#define LONG_OPT(a) a
2495static struct option opts[] = {
2496{ "data", required_argument, 0, 'd'},
2497{ "server", required_argument, 0, 's'},
2498{ "password", required_argument, 0, 'p'},
2499{ "port", required_argument, 0, 'r'},
2500{ "timeout", required_argument, 0, 't'},
2501{ "header", required_argument, 0, 'f'},
2502{ "user", required_argument, 0, 'u'},
2503{ "gpsephemeris", required_argument, 0, 'E'},
2504{ "glonassephemeris", required_argument, 0, 'G'},
2505{ "rinex3", no_argument, 0, '3'},
2506{ "proxyport", required_argument, 0, 'R'},
2507{ "proxyhost", required_argument, 0, 'S'},
2508{ "nmea", required_argument, 0, 'n'},
2509{ "mode", required_argument, 0, 'M'},
2510{ "help", no_argument, 0, 'h'},
2511{0,0,0,0}};
2512#endif
2513#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
2514
2515enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
2516
2517static const char *geturl(const char *url, struct Args *args)
2518{
2519 static char buf[1000];
2520 static char *Buffer = buf;
2521 static char *Bufend = buf+sizeof(buf);
2522
2523 if(strncmp("ntrip:", url, 6))
2524 return "URL must start with 'ntrip:'.";
2525 url += 6; /* skip ntrip: */
2526
2527 if(*url != '@' && *url != '/')
2528 {
2529 /* scan for mountpoint */
2530 args->data = Buffer;
2531 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
2532 *(Buffer++) = *(url++);
2533 if(Buffer == args->data)
2534 return "Mountpoint required.";
2535 else if(Buffer >= Bufend-1)
2536 return "Parsing buffer too short.";
2537 *(Buffer++) = 0;
2538 }
2539
2540 if(*url == '/') /* username and password */
2541 {
2542 ++url;
2543 args->user = Buffer;
2544 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
2545 *(Buffer++) = *(url++);
2546 if(Buffer == args->user)
2547 return "Username cannot be empty.";
2548 else if(Buffer >= Bufend-1)
2549 return "Parsing buffer too short.";
2550 *(Buffer++) = 0;
2551
2552 if(*url == ':') ++url;
2553
2554 args->password = Buffer;
2555 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2556 *(Buffer++) = *(url++);
2557 if(Buffer == args->password)
2558 return "Password cannot be empty.";
2559 else if(Buffer >= Bufend-1)
2560 return "Parsing buffer too short.";
2561 *(Buffer++) = 0;
2562 }
2563
2564 if(*url == '@') /* server */
2565 {
2566 ++url;
2567 if(*url != '@' && *url != ':')
2568 {
2569 args->server = Buffer;
2570 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
2571 *(Buffer++) = *(url++);
2572 if(Buffer == args->server)
2573 return "Servername cannot be empty.";
2574 else if(Buffer >= Bufend-1)
2575 return "Parsing buffer too short.";
2576 *(Buffer++) = 0;
2577 }
2578
2579 if(*url == ':')
2580 {
2581 ++url;
2582 args->port = Buffer;
2583 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2584 *(Buffer++) = *(url++);
2585 if(Buffer == args->port)
2586 return "Port cannot be empty.";
2587 else if(Buffer >= Bufend-1)
2588 return "Parsing buffer too short.";
2589 *(Buffer++) = 0;
2590 }
2591
2592 if(*url == '@') /* proxy */
2593 {
2594 ++url;
2595 args->proxyhost = Buffer;
2596 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
2597 *(Buffer++) = *(url++);
2598 if(Buffer == args->proxyhost)
2599 return "Proxy servername cannot be empty.";
2600 else if(Buffer >= Bufend-1)
2601 return "Parsing buffer too short.";
2602 *(Buffer++) = 0;
2603
2604 if(*url == ':')
2605 {
2606 ++url;
2607 args->proxyport = Buffer;
2608 while(*url && *url != ';' && Buffer != Bufend)
2609 *(Buffer++) = *(url++);
2610 if(Buffer == args->proxyport)
2611 return "Proxy port cannot be empty.";
2612 else if(Buffer >= Bufend-1)
2613 return "Parsing buffer too short.";
2614 *(Buffer++) = 0;
2615 }
2616 }
2617 }
2618 if(*url == ';') /* NMEA */
2619 {
2620 args->nmea = ++url;
2621 while(*url)
2622 ++url;
2623 }
2624
2625 return *url ? "Garbage at end of server string." : 0;
2626}
2627
2628static int getargs(int argc, char **argv, struct Args *args)
2629{
2630 int res = 1;
2631 int getoptr;
2632 int help = 0;
2633 char *t;
2634
2635 args->server = "www.euref-ip.net";
2636 args->port = "2101";
2637 args->timeout = 60;
2638 args->user = "";
2639 args->password = "";
2640 args->data = 0;
2641 args->headerfile = 0;
2642 args->gpsephemeris = 0;
2643 args->glonassephemeris = 0;
2644 args->rinex3 = 0;
2645 args->nmea = 0;
2646 args->proxyhost = 0;
2647 args->proxyport = "2101";
2648 args->mode = AUTO;
2649 help = 0;
2650
2651 do
2652 {
2653
2654#ifdef NO_LONG_OPTS
2655 switch((getoptr = getopt(argc, argv, ARGOPT)))
2656#else
2657 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
2658#endif
2659 {
2660 case 's': args->server = optarg; break;
2661 case 'u': args->user = optarg; break;
2662 case 'p': args->password = optarg; break;
2663 case 'd': args->data = optarg; break;
2664 case 'f': args->headerfile = optarg; break;
2665 case 'E': args->gpsephemeris = optarg; break;
2666 case 'G': args->glonassephemeris = optarg; break;
2667 case 'r': args->port = optarg; break;
2668 case '3': args->rinex3 = 1; break;
2669 case 'S': args->proxyhost = optarg; break;
2670 case 'n': args->nmea = optarg; break;
2671 case 'R': args->proxyport = optarg; break;
2672 case 'h': help=1; break;
2673 case 'M':
2674 args->mode = 0;
2675 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
2676 args->mode = NTRIP1;
2677 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
2678 args->mode = HTTP;
2679 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
2680 args->mode = RTSP;
2681 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
2682 args->mode = AUTO;
2683 else args->mode = atoi(optarg);
2684 if((args->mode == 0) || (args->mode >= END))
2685 {
2686 fprintf(stderr, "Mode %s unknown\n", optarg);
2687 res = 0;
2688 }
2689 break;
2690 case 't':
2691 args->timeout = strtoul(optarg, &t, 10);
2692 if((t && *t) || args->timeout < 0)
2693 res = 0;
2694 break;
2695
2696 case 1:
2697 {
2698 const char *err;
2699 if((err = geturl(optarg, args)))
2700 {
2701 RTCM3Error("%s\n\n", err);
2702 res = 0;
2703 }
2704 }
2705 break;
2706 case -1: break;
2707 }
2708 } while(getoptr != -1 || !res);
2709
2710 datestr[0] = datestr[7];
2711 datestr[1] = datestr[8];
2712 datestr[2] = datestr[9];
2713 datestr[3] = datestr[10];
2714 datestr[5] = datestr[12];
2715 datestr[6] = datestr[13];
2716 datestr[8] = datestr[15];
2717 datestr[9] = datestr[16];
2718 datestr[4] = datestr[7] = '-';
2719 datestr[10] = 0;
2720
2721 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
2722 {
2723 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
2724 "Please specify only one navigation file.\n");
2725 res = 0;
2726 }
2727 else if(!res || help)
2728 {
2729 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2730 "\nUsage: %s -s server -u user ...\n"
2731 " -d " LONG_OPT("--data ") "the requested data set\n"
2732 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
2733 " -s " LONG_OPT("--server ") "the server name or address\n"
2734 " -p " LONG_OPT("--password ") "the login password\n"
2735 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
2736 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
2737 " -u " LONG_OPT("--user ") "the user name\n"
2738 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
2739 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2740 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
2741 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
2742 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
2743 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
2744 " -M " LONG_OPT("--mode ") "mode for data request\n"
2745 " Valid modes are:\n"
2746 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
2747 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2748 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
2749 " 4, a, auto automatic detection (default)\n"
2750 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2751 , revisionstr, datestr, argv[0], argv[0]);
2752 exit(1);
2753 }
2754 return res;
2755}
2756
2757/* let the output complete a block if necessary */
2758static void signalhandler(int sig)
2759{
2760 if(!stop)
2761 {
2762 RTCM3Error("Stop signal number %d received. "
2763 "Trying to terminate gentle.\n", sig);
2764 stop = 1;
2765 alarm(1);
2766 }
2767}
2768
2769#ifndef WINDOWSVERSION
2770static void WaitMicro(int mic)
2771{
2772 struct timeval tv;
2773 tv.tv_sec = mic/1000000;
2774 tv.tv_usec = mic%1000000;
2775#ifdef DEBUG
2776 fprintf(stderr, "Waiting %d micro seconds\n", mic);
2777#endif
2778 select(0, 0, 0, 0, &tv);
2779}
2780#else /* WINDOWSVERSION */
2781void WaitMicro(int mic)
2782{
2783 Sleep(mic/1000);
2784}
2785#endif /* WINDOWSVERSION */
2786
2787#define ALARMTIME (2*60)
2788
2789/* for some reason we had to abort hard (maybe waiting for data */
2790#ifdef __GNUC__
2791static __attribute__ ((noreturn)) void signalhandler_alarm(
2792int sig __attribute__((__unused__)))
2793#else /* __GNUC__ */
2794static void signalhandler_alarm(int sig)
2795#endif /* __GNUC__ */
2796{
2797 RTCM3Error("Programm forcefully terminated.\n");
2798 exit(1);
2799}
2800
2801int main(int argc, char **argv)
2802{
2803 struct Args args;
2804 struct RTCM3ParserData Parser;
2805
2806 setbuf(stdout, 0);
2807 setbuf(stdin, 0);
2808 setbuf(stderr, 0);
2809
2810 fixrevision();
2811
2812 signal(SIGINT, signalhandler);
2813 signal(SIGALRM,signalhandler_alarm);
2814 signal(SIGQUIT,signalhandler);
2815 signal(SIGTERM,signalhandler);
2816 signal(SIGPIPE,signalhandler);
2817 memset(&Parser, 0, sizeof(Parser));
2818 {
2819 time_t tim;
2820 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2821 Parser.GPSWeek = tim/(7*24*60*60);
2822 Parser.GPSTOW = tim%(7*24*60*60);
2823 }
2824
2825 if(getargs(argc, argv, &args))
2826 {
2827 int sockfd, numbytes;
2828 char buf[MAXDATASIZE];
2829 struct sockaddr_in their_addr; /* connector's address information */
2830 struct hostent *he;
2831 struct servent *se;
2832 const char *server, *port, *proxyserver = 0;
2833 char proxyport[6];
2834 char *b;
2835 long i;
2836 struct timeval tv;
2837
2838 alarm(ALARMTIME);
2839
2840 Parser.headerfile = args.headerfile;
2841 Parser.glonassephemeris = args.glonassephemeris;
2842 Parser.gpsephemeris = args.gpsephemeris;
2843 Parser.rinex3 = args.rinex3;
2844
2845 if(args.proxyhost)
2846 {
2847 int p;
2848 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2849 p = i;
2850 else if(!(se = getservbyname(args.port, 0)))
2851 {
2852 RTCM3Error("Can't resolve port %s.", args.port);
2853 exit(1);
2854 }
2855 else
2856 {
2857 p = ntohs(se->s_port);
2858 }
2859 snprintf(proxyport, sizeof(proxyport), "%d", p);
2860 port = args.proxyport;
2861 proxyserver = args.server;
2862 server = args.proxyhost;
2863 }
2864 else
2865 {
2866 server = args.server;
2867 port = args.port;
2868 }
2869
2870 memset(&their_addr, 0, sizeof(struct sockaddr_in));
2871 if((i = strtol(port, &b, 10)) && (!b || !*b))
2872 their_addr.sin_port = htons(i);
2873 else if(!(se = getservbyname(port, 0)))
2874 {
2875 RTCM3Error("Can't resolve port %s.", port);
2876 exit(1);
2877 }
2878 else
2879 {
2880 their_addr.sin_port = se->s_port;
2881 }
2882 if(!(he=gethostbyname(server)))
2883 {
2884 RTCM3Error("Server name lookup failed for '%s'.\n", server);
2885 exit(1);
2886 }
2887 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2888 {
2889 perror("socket");
2890 exit(1);
2891 }
2892
2893 tv.tv_sec = args.timeout;
2894 tv.tv_usec = 0;
2895 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
2896 {
2897 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
2898 exit(1);
2899 }
2900
2901 their_addr.sin_family = AF_INET;
2902 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2903
2904 if(args.data && args.mode == RTSP)
2905 {
2906 struct sockaddr_in local;
2907 int sockudp, localport;
2908 int cseq = 1;
2909 socklen_t len;
2910
2911 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2912 {
2913 perror("socket");
2914 exit(1);
2915 }
2916 /* fill structure with local address information for UDP */
2917 memset(&local, 0, sizeof(local));
2918 local.sin_family = AF_INET;
2919 local.sin_port = htons(0);
2920 local.sin_addr.s_addr = htonl(INADDR_ANY);
2921 len = sizeof(local);
2922 /* bind() in order to get a random RTP client_port */
2923 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
2924 {
2925 perror("bind");
2926 exit(1);
2927 }
2928 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
2929 {
2930 localport = ntohs(local.sin_port);
2931 }
2932 else
2933 {
2934 perror("local access failed");
2935 exit(1);
2936 }
2937 if(connect(sockfd, (struct sockaddr *)&their_addr,
2938 sizeof(struct sockaddr)) == -1)
2939 {
2940 perror("connect");
2941 exit(1);
2942 }
2943 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2944 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
2945 "CSeq: %d\r\n"
2946 "Ntrip-Version: Ntrip/2.0\r\n"
2947 "Ntrip-Component: Ntripclient\r\n"
2948 "User-Agent: %s/%s\r\n"
2949 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
2950 "Authorization: Basic ",
2951 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2952 args.data, cseq++, AGENTSTRING, revisionstr, localport);
2953 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2954 {
2955 RTCM3Error("Requested data too long\n");
2956 exit(1);
2957 }
2958 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2959 if(i > MAXDATASIZE-4)
2960 {
2961 RTCM3Error("Username and/or password too long\n");
2962 exit(1);
2963 }
2964 buf[i++] = '\r';
2965 buf[i++] = '\n';
2966 buf[i++] = '\r';
2967 buf[i++] = '\n';
2968 if(args.nmea)
2969 {
2970 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2971 if(j >= 0 && j < MAXDATASIZE-i)
2972 i += j;
2973 else
2974 {
2975 RTCM3Error("NMEA string too long\n");
2976 exit(1);
2977 }
2978 }
2979 if(send(sockfd, buf, (size_t)i, 0) != i)
2980 {
2981 perror("send");
2982 exit(1);
2983 }
2984 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2985 {
2986 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2987 {
2988 int serverport = 0, session = 0;
2989 const char *portcheck = "server_port=";
2990 const char *sessioncheck = "session: ";
2991 int l = strlen(portcheck)-1;
2992 int j=0;
2993 for(i = 0; j != l && i < numbytes-l; ++i)
2994 {
2995 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
2996 ;
2997 }
2998 if(i == numbytes-l)
2999 {
3000 RTCM3Error("No server port number found\n");
3001 exit(1);
3002 }
3003 else
3004 {
3005 i+=l;
3006 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3007 serverport = serverport * 10 + buf[i++]-'0';
3008 if(buf[i] != '\r' && buf[i] != ';')
3009 {
3010 RTCM3Error("Could not extract server port\n");
3011 exit(1);
3012 }
3013 }
3014 l = strlen(sessioncheck)-1;
3015 j=0;
3016 for(i = 0; j != l && i < numbytes-l; ++i)
3017 {
3018 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3019 ;
3020 }
3021 if(i == numbytes-l)
3022 {
3023 RTCM3Error("No session number found\n");
3024 exit(1);
3025 }
3026 else
3027 {
3028 i+=l;
3029 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3030 session = session * 10 + buf[i++]-'0';
3031 if(buf[i] != '\r')
3032 {
3033 RTCM3Error("Could not extract session number\n");
3034 exit(1);
3035 }
3036 }
3037
3038 i = snprintf(buf, MAXDATASIZE,
3039 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3040 "CSeq: %d\r\n"
3041 "Session: %d\r\n"
3042 "\r\n",
3043 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3044 args.data, cseq++, session);
3045
3046 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3047 {
3048 RTCM3Error("Requested data too long\n");
3049 exit(1);
3050 }
3051 if(send(sockfd, buf, (size_t)i, 0) != i)
3052 {
3053 perror("send");
3054 exit(1);
3055 }
3056 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3057 {
3058 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3059 {
3060 struct sockaddr_in addrRTP;
3061 /* fill structure with caster address information for UDP */
3062 memset(&addrRTP, 0, sizeof(addrRTP));
3063 addrRTP.sin_family = AF_INET;
3064 addrRTP.sin_port = htons(serverport);
3065 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3066 len = sizeof(addrRTP);
3067 int ts = 0;
3068 int sn = 0;
3069 int ssrc = 0;
3070 int init = 0;
3071 int u, v, w;
3072 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3073 (struct sockaddr*) &addrRTP, &len)) > 0)
3074 {
3075 alarm(ALARMTIME);
3076 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3077 {
3078 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3079 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3080 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3081 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3082 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3083
3084 if(init)
3085 {
3086 int z;
3087 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3088 if(ssrc != w || ts > v)
3089 {
3090 RTCM3Error("Illegal UDP data received.\n");
3091 exit(1);
3092 }
3093 if(u > sn) /* don't show out-of-order packets */
3094 for(z = 12; z < i && !stop; ++z)
3095 HandleByte(&Parser, (unsigned int) buf[z]);
3096 }
3097 sn = u; ts = v; ssrc = w; init = 1;
3098 }
3099 else
3100 {
3101 RTCM3Error("Illegal UDP header.\n");
3102 exit(1);
3103 }
3104 }
3105 }
3106 i = snprintf(buf, MAXDATASIZE,
3107 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3108 "CSeq: %d\r\n"
3109 "Session: %d\r\n"
3110 "\r\n",
3111 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3112 args.data, cseq++, session);
3113
3114 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3115 {
3116 RTCM3Error("Requested data too long\n");
3117 exit(1);
3118 }
3119 if(send(sockfd, buf, (size_t)i, 0) != i)
3120 {
3121 perror("send");
3122 exit(1);
3123 }
3124 }
3125 else
3126 {
3127 RTCM3Error("Could not start data stream.\n");
3128 exit(1);
3129 }
3130 }
3131 else
3132 {
3133 RTCM3Error("Could not setup initial control connection.\n");
3134 exit(1);
3135 }
3136 }
3137 else
3138 {
3139 perror("recv");
3140 exit(1);
3141 }
3142 }
3143 else
3144 {
3145 if(connect(sockfd, (struct sockaddr *)&their_addr,
3146 sizeof(struct sockaddr)) == -1)
3147 {
3148 perror("connect");
3149 exit(1);
3150 }
3151 if(!args.data)
3152 {
3153 i = snprintf(buf, MAXDATASIZE,
3154 "GET %s%s%s%s/ HTTP/1.0\r\n"
3155 "Host: %s\r\n%s"
3156 "User-Agent: %s/%s\r\n"
3157 "Connection: close\r\n"
3158 "\r\n"
3159 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3160 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3161 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3162 AGENTSTRING, revisionstr);
3163 }
3164 else
3165 {
3166 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3167 "GET %s%s%s%s/%s HTTP/1.0\r\n"
3168 "Host: %s\r\n%s"
3169 "User-Agent: %s/%s\r\n"
3170 "Connection: close\r\n"
3171 "Authorization: Basic "
3172 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3173 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3174 args.data, args.server,
3175 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3176 AGENTSTRING, revisionstr);
3177 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3178 {
3179 RTCM3Error("Requested data too long\n");
3180 exit(1);
3181 }
3182 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3183 if(i > MAXDATASIZE-4)
3184 {
3185 RTCM3Error("Username and/or password too long\n");
3186 exit(1);
3187 }
3188 buf[i++] = '\r';
3189 buf[i++] = '\n';
3190 buf[i++] = '\r';
3191 buf[i++] = '\n';
3192 if(args.nmea)
3193 {
3194 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3195 if(j >= 0 && j < MAXDATASIZE-i)
3196 i += j;
3197 else
3198 {
3199 RTCM3Error("NMEA string too long\n");
3200 exit(1);
3201 }
3202 }
3203 }
3204 if(send(sockfd, buf, (size_t)i, 0) != i)
3205 {
3206 perror("send");
3207 exit(1);
3208 }
3209 if(args.data)
3210 {
3211 int k = 0;
3212 int chunkymode = 0;
3213 int starttime = time(0);
3214 int lastout = starttime;
3215 int totalbytes = 0;
3216 int chunksize = 0;
3217
3218 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3219 {
3220 if(numbytes > 0)
3221 alarm(ALARMTIME);
3222 else
3223 {
3224 WaitMicro(100);
3225 continue;
3226 }
3227 if(!k)
3228 {
3229 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3230 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3231 {
3232 const char *datacheck = "Content-Type: gnss/data\r\n";
3233 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3234 int l = strlen(datacheck)-1;
3235 int j=0;
3236 for(i = 0; j != l && i < numbytes-l; ++i)
3237 {
3238 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3239 ;
3240 }
3241 if(i == numbytes-l)
3242 {
3243 RTCM3Error("No 'Content-Type: gnss/data' found\n");
3244 exit(1);
3245 }
3246 l = strlen(chunkycheck)-1;
3247 j=0;
3248 for(i = 0; j != l && i < numbytes-l; ++i)
3249 {
3250 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3251 ;
3252 }
3253 if(i < numbytes-l)
3254 chunkymode = 1;
3255 }
3256 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3257 {
3258 RTCM3Error("Could not get the requested data: ");
3259 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3260 {
3261 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3262 }
3263 RTCM3Error("\n");
3264 exit(1);
3265 }
3266 else if(args.mode != NTRIP1)
3267 {
3268 if(args.mode != AUTO)
3269 {
3270 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3271 args.mode == AUTO ? ", falling back to NTRIP1" : "");
3272 }
3273 if(args.mode == HTTP)
3274 exit(1);
3275 }
3276 ++k;
3277 }
3278 else
3279 {
3280 if(chunkymode)
3281 {
3282 int stop = 0;
3283 int pos = 0;
3284 while(!stop && pos < numbytes)
3285 {
3286 switch(chunkymode)
3287 {
3288 case 1: /* reading number starts */
3289 chunksize = 0;
3290 ++chunkymode; /* no break */
3291 case 2: /* during reading number */
3292 i = buf[pos++];
3293 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3294 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3295 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3296 else if(i == '\r') ++chunkymode;
3297 else if(i == ';') chunkymode = 5;
3298 else stop = 1;
3299 break;
3300 case 3: /* scanning for return */
3301 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3302 else stop = 1;
3303 break;
3304 case 4: /* output data */
3305 i = numbytes-pos;
3306 if(i > chunksize) i = chunksize;
3307 {
3308 int z;
3309 for(z = 0; z < i && !stop; ++z)
3310 HandleByte(&Parser, (unsigned int) buf[pos+z]);
3311 }
3312 totalbytes += i;
3313 chunksize -= i;
3314 pos += i;
3315 if(!chunksize)
3316 chunkymode = 1;
3317 break;
3318 case 5:
3319 if(i == '\r') chunkymode = 3;
3320 break;
3321 }
3322 }
3323 if(stop)
3324 {
3325 RTCM3Error("Error in chunky transfer encoding\n");
3326 break;
3327 }
3328 }
3329 else
3330 {
3331 totalbytes += numbytes;
3332 {
3333 int z;
3334 for(z = 0; z < numbytes && !stop; ++z)
3335 HandleByte(&Parser, (unsigned int) buf[z]);
3336 }
3337 }
3338 if(totalbytes < 0) /* overflow */
3339 {
3340 totalbytes = 0;
3341 starttime = time(0);
3342 lastout = starttime;
3343 }
3344 }
3345 }
3346 }
3347 else
3348 {
3349 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3350 {
3351 alarm(ALARMTIME);
3352 fwrite(buf, (size_t)numbytes, 1, stdout);
3353 }
3354 }
3355 close(sockfd);
3356 }
3357 }
3358 return 0;
3359}
3360#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.