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

Last change on this file since 2764 was 2764, checked in by stoecker, 13 years ago

fix GLONASS week underflow

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