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

Last change on this file since 6626 was 6626, checked in by stoecker, 9 years ago

proper size check for ephemeris

  • Property svn:keywords set to Id Revision Date
File size: 147.4 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 6626 2015-03-03 16:11:26Z stoecker $
4 Copyright (C) 2005-2012 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: 6626 $";
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 GETBITS64(b, a) \
139{ \
140 if(((a) > 56) && ((a)-56) > numbits) \
141 { \
142 uint64_t x; \
143 GETBITS(x, 56) \
144 LOADBITS((a)-56) \
145 b = ((x<<((a)-56)) | (bitfield<<(sizeof(bitfield)*8-numbits)) \
146 >>(sizeof(bitfield)*8-((a)-56))); \
147 numbits -= ((a)-56); \
148 } \
149 else \
150 { \
151 GETBITS(b, a) \
152 } \
153}
154
155/* extract bits from data stream
156 b = variable to store result, a = number of bits */
157#define GETBITS(b, a) \
158{ \
159 LOADBITS(a) \
160 b = (bitfield<<(64-numbits))>>(64-(a)); \
161 numbits -= (a); \
162}
163
164/* extract bits from data stream
165 b = variable to store result, a = number of bits */
166#define GETBITSFACTOR(b, a, c) \
167{ \
168 LOADBITS(a) \
169 b = ((bitfield<<(sizeof(bitfield)*8-numbits))>>(sizeof(bitfield)*8-(a)))*(c); \
170 numbits -= (a); \
171}
172
173/* extract floating value from data stream
174 b = variable to store result, a = number of bits */
175#define GETFLOAT(b, a, c) \
176{ \
177 LOADBITS(a) \
178 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
179 numbits -= (a); \
180}
181
182/* extract signed floating value from data stream
183 b = variable to store result, a = number of bits */
184#define GETFLOATSIGN(b, a, c) \
185{ \
186 LOADBITS(a) \
187 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
188 numbits -= (a); \
189}
190
191/* extract bits from data stream
192 b = variable to store result, a = number of bits */
193#define GETBITSSIGN(b, a) \
194{ \
195 LOADBITS(a) \
196 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
197 numbits -= (a); \
198}
199
200#define GETFLOATSIGNM(b, a, c) \
201{ int l; \
202 LOADBITS(a) \
203 l = (bitfield<<(64-numbits))>>(64-1); \
204 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
205 numbits -= (a); \
206 if(l) b *= -1.0; \
207}
208
209#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
210
211/* extract byte-aligned byte from data stream,
212 b = variable to store size, s = variable to store string pointer */
213#define GETSTRING(b, s) \
214{ \
215 b = *(data++); \
216 s = (char *) data; \
217 data += b; \
218 size -= b+1; \
219}
220
221struct leapseconds { /* specify the day of leap second */
222 int day; /* this is the day, where 23:59:59 exists 2 times */
223 int month; /* not the next day! */
224 int year;
225 int taicount;
226};
227static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
228static const struct leapseconds leap[] = {
229/*{31, 12, 1971, 10},*/
230/*{30, 06, 1972, 11},*/
231/*{31, 12, 1972, 12},*/
232/*{31, 12, 1973, 13},*/
233/*{31, 12, 1974, 14},*/
234/*{31, 12, 1975, 15},*/
235/*{31, 12, 1976, 16},*/
236/*{31, 12, 1977, 17},*/
237/*{31, 12, 1978, 18},*/
238/*{31, 12, 1979, 19},*/
239{30, 06, 1981,20},
240{30, 06, 1982,21},
241{30, 06, 1983,22},
242{30, 06, 1985,23},
243{31, 12, 1987,24},
244{31, 12, 1989,25},
245{31, 12, 1990,26},
246{30, 06, 1992,27},
247{30, 06, 1993,28},
248{30, 06, 1994,29},
249{31, 12, 1995,30},
250{30, 06, 1997,31},
251{31, 12, 1998,32},
252{31, 12, 2005,33},
253{31, 12, 2008,34},
254{30, 06, 2012,35},
255{30, 06, 2015,36},
256{0,0,0,0} /* end marker */
257};
258#define LEAPSECONDS 17 /* only needed for approx. time */
259#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
260
261static int longyear(int year, int month)
262{
263 if(!(year % 4) && (!(year % 400) || (year % 100)))
264 {
265 if(!month || month == 2)
266 return 1;
267 }
268 return 0;
269}
270
271int gnumleap(int year, int month, int day)
272{
273 int ls = 0;
274 const struct leapseconds *l;
275
276 for(l = leap; l->taicount && year >= l->year; ++l)
277 {
278 if(year > l->year || month > l->month || (month == l->month && day > l->day))
279 ls = l->taicount - GPSLEAPSTART;
280 }
281 return ls;
282}
283
284/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
285void updatetime(int *week, int *secOfWeek, int mSecOfWeek, int fixnumleap)
286{
287 int y,m,d,k,l, nul;
288 unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
289 int glo_daynumber = 0, glo_timeofday;
290 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
291 + gnumleap(y+1,1,1); ++y)
292 {
293 j -= k; glo_daynumber += l;
294 }
295 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
296 + gnumleap(y, m+1, 1); ++m)
297 {
298 j -= k; glo_daynumber += l;
299 }
300 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
301 j -= 24*60*60;
302 glo_daynumber -= 16*365+4-d;
303 nul = gnumleap(y, m, d);
304 glo_timeofday = j-nul;
305
306 // original version
307 // if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
308 // *secOfWeek += 24*60*60;
309 // else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
310 // *secOfWeek -= 24*60*60;
311
312 // new version
313 if(mSecOfWeek < 4*60*60*1000 && glo_timeofday > 20*60*60)
314 *secOfWeek += 24*60*60;
315 else if(glo_timeofday < 4*60*60 && mSecOfWeek > 20*60*60*1000)
316 *secOfWeek -= 24*60*60;
317
318 *secOfWeek += mSecOfWeek/1000-glo_timeofday;
319 if(fixnumleap)
320 *secOfWeek -= nul;
321 if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
322 if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
323}
324
325int RTCM3Parser(struct RTCM3ParserData *handle)
326{
327 int ret=0;
328
329#ifdef NO_RTCM3_MAIN
330 if(GetMessage(handle)) /* don't repeat */
331#else
332 while(!ret && GetMessage(handle))
333#endif /* NO_RTCM3_MAIN */
334 {
335 /* using 64 bit integer types, as it is much easier than handling
336 the long datatypes in 32 bit */
337 uint64_t numbits = 0, bitfield = 0;
338 int size = handle->size, type;
339 int syncf, old = 0;
340 unsigned char *data = handle->Message+3;
341
342 GETBITS(type,12)
343#ifdef NO_RTCM3_MAIN
344 handle->blocktype = type;
345#endif /* NO_RTCM3_MAIN */
346 switch(type)
347 {
348#ifdef NO_RTCM3_MAIN
349 default:
350 ret = type;
351 break;
352 case 1005: case 1006:
353 {
354 SKIPBITS(22)
355 GETBITSSIGN(handle->antX, 38)
356 SKIPBITS(2)
357 GETBITSSIGN(handle->antY, 38)
358 SKIPBITS(2)
359 GETBITSSIGN(handle->antZ, 38)
360 if(type == 1006)
361 GETBITS(handle->antH, 16)
362 ret = type;
363 }
364 break;
365 case 1007: case 1008: case 1033:
366 {
367 char *antenna;
368 int antnum;
369
370 SKIPBITS(12)
371 GETSTRING(antnum,antenna)
372 memcpy(handle->antenna, antenna, antnum);
373 handle->antenna[antnum] = 0;
374 ret = type;
375 }
376 break;
377 case 1013:
378 {
379 SKIPBITS(12);
380 GETBITS(handle->modjulday, 16);
381 GETBITS(handle->secofday, 17);
382 SKIPBITS(5);
383 GETBITS(handle->leapsec, 8);
384 ret = 1013;
385 }
386 break;
387#endif /* NO_RTCM3_MAIN */
388 case 1019:
389 if(size == 59)
390 {
391 struct gpsephemeris *ge;
392 int sv, i;
393
394 ge = &handle->ephemerisGPS;
395 memset(ge, 0, sizeof(*ge));
396
397 GETBITS(sv, 6)
398 ge->satellite = (sv < 40 ? sv : sv+80);
399 GETBITS(ge->GPSweek, 10)
400 ge->GPSweek += 1024;
401 GETBITS(ge->URAindex, 4)
402 GETBITS(sv, 2)
403 if(sv & 1)
404 ge->flags |= GPSEPHF_L2PCODE;
405 if(sv & 2)
406 ge->flags |= GPSEPHF_L2CACODE;
407 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
408 GETBITS(ge->IODE, 8)
409 GETBITS(ge->TOC, 16)
410 ge->TOC <<= 4;
411 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
412 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
413 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
414 GETBITS(ge->IODC, 10)
415 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
416 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
417 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
418 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
419 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
420 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
421 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
422 GETBITS(ge->TOE, 16)
423 ge->TOE <<= 4;
424
425 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
426 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
427 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
428 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
429 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
430 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
431 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
432 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
433 GETBITS(ge->SVhealth, 6)
434 GETBITS(sv, 1)
435 if(sv)
436 ge->flags |= GPSEPHF_L2PCODEDATA;
437 GETBITS(sv, 1)
438 if(sv)
439 ge->flags |= GPSEPHF_6HOURSFIT;
440
441 i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
442 + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
443 if(i > 5*60*60 && i < 8*60*60)
444 {
445 handle->GPSTOW = ge->TOE;
446 handle->GPSWeek = ge->GPSweek;
447 }
448 ge->TOW = 0.9999E9;
449 ret = 1019;
450 }
451 break;
452 case RTCM3ID_BDS:
453 if(size == 64)
454 {
455 struct bdsephemeris *be;
456 int sv, i, week, tow;
457 be = &handle->ephemerisBDS;
458 memset(be, 0, sizeof(*be));
459
460 GETBITS(sv, 6)
461 be->satellite = sv+PRN_BDS_START-1;
462 GETBITS(be->BDSweek, 13)
463 GETBITS(be->URAI, 4)
464 GETFLOATSIGN(be->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
465 GETBITS(be->AODE, 5)
466 GETBITS(be->TOC, 17)
467 be->TOC <<= 3;
468 GETFLOATSIGN(be->clock_driftrate, 11, 1.0/(double)(1<<30)/(double)(1<<30)/(double)(1<<6))
469 GETFLOATSIGN(be->clock_drift, 22, 1.0/(double)(1<<30)/(double)(1<<20))
470 GETFLOATSIGN(be->clock_bias, 24, 1.0/(double)(1<<30)/(double)(1<<3))
471 GETBITS(be->AODC, 5)
472 GETFLOATSIGN(be->Crs, 18, 1.0/(double)(1<<6))
473 GETFLOATSIGN(be->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
474 GETFLOATSIGN(be->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
475 GETFLOATSIGN(be->Cuc, 18, 1.0/(double)(1<<30)/(double)(1<<1))
476 GETFLOAT(be->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
477 GETFLOATSIGN(be->Cus, 18, 1.0/(double)(1<<30)/(double)(1<<1))
478 GETFLOAT(be->sqrt_A, 32, 1.0/(double)(1<<19))
479 GETBITS(be->TOE, 17)
480 be->TOE <<= 3;
481 GETFLOATSIGN(be->Cic, 18, 1.0/(double)(1<<30)/(double)(1<<1))
482 GETFLOATSIGN(be->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
483 GETFLOATSIGN(be->Cis, 18, 1.0/(double)(1<<30)/(double)(1<<1))
484 GETFLOATSIGN(be->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
485 GETFLOATSIGN(be->Crc, 18, 1.0/(double)(1<<6))
486 GETFLOATSIGN(be->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
487 GETFLOATSIGN(be->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
488 GETFLOATSIGN(be->TGD_B1_B3, 10, 0.0000000001)
489 GETFLOATSIGN(be->TGD_B2_B3, 10, 0.0000000001)
490 GETBITS(sv, 1)
491 if(sv)
492 be->flags |= BDSEPHF_SATH1;
493 week = 1356+be->BDSweek;
494 tow = 14+be->TOE;
495 if(tow > 7*24*60*60) /* overflow due to leap */
496 {
497 ++week;
498 tow -= 7*24*60*60;
499 }
500 i = (week - (int)handle->GPSWeek)*7*24*60*60
501 + (tow - (int)handle->GPSTOW) - 2*60*60;
502 if(i > 5*60*60 && i < 8*60*60)
503 {
504 handle->GPSTOW = tow;
505 handle->GPSWeek = week;
506 }
507 ret = RTCM3ID_BDS;
508 be->TOW = 0.9999E9;
509 }
510 break;
511 case 1043:
512 if(size == 27 && handle->GPSWeek)
513 {
514 struct sbasephemeris *gs;
515 int sv, i, time, tod, day;
516 gs = &handle->ephemerisSBAS;
517 memset(gs, 0, sizeof(*gs));
518
519 GETBITS(sv, 6)
520 gs->satellite = PRN_SBAS_START+sv;
521 GETBITS(gs->IODN, 8)
522 GETBITS(time, 13)
523 time <<= 4;
524 gs->GPSweek_TOE = handle->GPSWeek;
525 GETBITS(gs->URA, 4)
526 GETFLOATSIGN(gs->x_pos, 30, 0.08)
527 GETFLOATSIGN(gs->y_pos, 30, 0.08)
528 GETFLOATSIGN(gs->z_pos, 25, 0.4)
529 GETFLOATSIGN(gs->x_velocity, 17, 0.000625)
530 GETFLOATSIGN(gs->y_velocity, 17, 0.000625)
531 GETFLOATSIGN(gs->z_velocity, 18, 0.004)
532 GETFLOATSIGN(gs->x_acceleration, 10, 0.0000125)
533 GETFLOATSIGN(gs->y_acceleration, 10, 0.0000125)
534 GETFLOATSIGN(gs->z_acceleration, 10, 0.0000625)
535 GETFLOATSIGN(gs->agf0, 12, 1.0/(1<<30)/(1<<1))
536 GETFLOATSIGN(gs->agf1, 8, 1.0/(1<<30)/(1<<10))
537
538 /* calculate time */
539 tod = handle->GPSTOW%(24*60*60);
540 day = handle->GPSTOW/(24*60*60);
541 if(time > 19*60*60 && tod < 5*60*60)
542 --day;
543 else if(time < 5*60*60 && tod > 19*60*60)
544 ++day;
545 time += day*24*60*60;
546 if(time > 7*24*60*60)
547 ++gs->GPSweek_TOE;
548 else if(time < 0)
549 --gs->GPSweek_TOE;
550 gs->TOE = time;
551
552 i = (gs->GPSweek_TOE - handle->GPSWeek)*7*24*60*60
553 + (gs->TOE - handle->GPSTOW) - 2*60*60;
554 if(i > 5*60*60 && i < 8*60*60)
555 {
556 handle->GPSTOW = gs->TOE;
557 handle->GPSWeek = gs->GPSweek_TOE;
558 }
559 gs->TOW = 0.9999E9;
560 ret = 1043;
561 }
562 break;
563 case 1044:
564 if(size == 59)
565 {
566 struct gpsephemeris *ge;
567 int sv, i;
568
569 ge = &handle->ephemerisGPS;
570 memset(ge, 0, sizeof(*ge));
571
572 GETBITS(sv, 4)
573 ge->satellite = PRN_QZSS_START+sv-1;
574 GETBITS(ge->TOC, 16)
575 ge->TOC <<= 4;
576 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
577 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
578 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
579 GETBITS(ge->IODE, 8)
580 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
581 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
582 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
583 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
584 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
585 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
586 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
587 GETBITS(ge->TOE, 16)
588 ge->TOE <<= 4;
589 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
590 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
591 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
592 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
593 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
594 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
595 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
596 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
597 GETBITS(sv, 2)
598 if(sv & 1)
599 ge->flags |= GPSEPHF_L2PCODE;
600 if(sv & 2)
601 ge->flags |= GPSEPHF_L2CACODE;
602 GETBITS(ge->GPSweek, 10)
603 ge->GPSweek += 1024;
604 GETBITS(ge->URAindex, 4)
605 GETBITS(ge->SVhealth, 6)
606 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
607 GETBITS(ge->IODC, 10)
608 GETBITS(sv, 1)
609 if(sv)
610 ge->flags |= GPSEPHF_6HOURSFIT;
611
612 i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
613 + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
614 if(i > 5*60*60 && i < 8*60*60)
615 {
616 handle->GPSTOW = ge->TOE;
617 handle->GPSWeek = ge->GPSweek;
618 }
619 ge->TOW = 0.9999E9;
620 ret = 1044;
621 }
622 break;
623 case 1045: case 1046:
624 {
625 struct galileoephemeris *ge;
626 int sv;
627
628 ge = &handle->ephemerisGALILEO;
629 memset(ge, 0, sizeof(*ge));
630
631 GETBITS(sv, 6)
632 ge->satellite = sv;
633 GETBITS(ge->Week, 12)
634 GETBITS(ge->IODnav, 10)
635 GETBITS(ge->SISA, 8)
636 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
637 GETBITSFACTOR(ge->TOC, 14, 60)
638 GETFLOATSIGN(ge->clock_driftrate, 6, 1.0/(double)(1<<30)/(double)(1<<29))
639 GETFLOATSIGN(ge->clock_drift, 21, 1.0/(double)(1<<30)/(double)(1<<16))
640 GETFLOATSIGN(ge->clock_bias, 31, 1.0/(double)(1<<30)/(double)(1<<4))
641 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
642 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
643 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
644 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
645 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
646 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
647 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
648 GETBITSFACTOR(ge->TOE, 14, 60)
649 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
650 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
651 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
652 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
653 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
654 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
655 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
656 GETFLOATSIGN(ge->BGD_1_5A, 10, 1.0/(double)(1<<30)/(double)(1<<2))
657 if(type == 1046)
658 {
659 GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
660 GETBITS(ge->E5aHS, 2)
661 GETBITS(sv, 1)
662 ge->flags |= GALEPHF_INAV;
663 if(sv)
664 ge->flags |= GALEPHF_E5ADINVALID;
665 GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
666 }
667 else
668 {
669 ge->flags |= GALEPHF_FNAV;
670 GETBITS(ge->E5bHS, 2)
671 GETBITS(sv, 1)
672 if(sv)
673 ge->flags |= GALEPHF_E5BDINVALID;
674 }
675 ret = type;
676 }
677 break;
678 case 1020:
679 if(size == 43)
680 {
681 struct glonassephemeris *ge;
682 int i;
683
684 ge = &handle->ephemerisGLONASS;
685 memset(ge, 0, sizeof(*ge));
686
687 ge->flags |= GLOEPHF_PAVAILABLE;
688 GETBITS(ge->almanac_number, 6)
689 GETBITS(i, 5)
690 ge->frequency_number = i-7;
691 if(ge->almanac_number >= 1 && ge->almanac_number <= PRN_GLONASS_NUM)
692 handle->GLOFreq[ge->almanac_number-1] = 100+ge->frequency_number;
693 GETBITS(i, 1)
694 if(i)
695 ge->flags |= GLOEPHF_ALMANACHEALTHY;
696 GETBITS(i, 1)
697 if(i)
698 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
699 GETBITS(i, 2)
700 if(i & 1)
701 ge->flags |= GLOEPHF_P10TRUE;
702 if(i & 2)
703 ge->flags |= GLOEPHF_P11TRUE;
704 GETBITS(i, 5)
705 ge->tk = i*60*60;
706 GETBITS(i, 6)
707 ge->tk += i*60;
708 GETBITS(i, 1)
709 ge->tk += i*30;
710 GETBITS(i, 1)
711 if(i)
712 ge->flags |= GLOEPHF_UNHEALTHY;
713 GETBITS(i, 1)
714 if(i)
715 ge->flags |= GLOEPHF_P2TRUE;
716 GETBITS(i, 7)
717 ge->tb = i*15*60;
718 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
719 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
720 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
721 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
722 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
723 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
724 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
725 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
726 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
727 GETBITS(i, 1)
728 if(i)
729 ge->flags |= GLOEPHF_P3TRUE;
730 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
731 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
732 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
733 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
734 GETBITS(ge->E, 5)
735 /* GETBITS(b, 1) / * GLONASS-M P4 */
736 /* GETBITS(b, 4) / * GLONASS-M Ft */
737 /* GETBITS(b, 11) / * GLONASS-M Nt */
738 /* GETBITS(b, 2) / * GLONASS-M M */
739 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
740 /* GETBITS(b, 11) / * GLONASS-M Na */
741 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
742 /* GETBITS(b, 5) / * GLONASS-M N4 */
743 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
744 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
745 ge->GPSWeek = handle->GPSWeek;
746 ge->GPSTOW = handle->GPSTOW;
747 ret = 1020;
748 }
749 break;
750 case 1001: case 1002: case 1003: case 1004:
751 if(handle->GPSWeek)
752 {
753 int lastlockl1[64];
754 int lastlockl2[64];
755 struct gnssdata *gnss;
756 int i, numsats, wasamb=0;
757
758 for(i = 0; i < 64; ++i)
759 lastlockl1[i] = lastlockl2[i] = 0;
760
761 gnss = &handle->DataNew;
762
763 SKIPBITS(12) /* id */
764 GETBITS(i,30)
765 if(i/1000 < (int)handle->GPSTOW - 86400)
766 ++handle->GPSWeek;
767 handle->GPSTOW = i/1000;
768 if(gnss->week && (gnss->timeofweek != i || gnss->week
769 != handle->GPSWeek))
770 {
771 handle->Data = *gnss;
772 memset(gnss, 0, sizeof(*gnss));
773 old = 1;
774 }
775 gnss->timeofweek = i;
776 gnss->week = handle->GPSWeek;
777
778 GETBITS(syncf,1) /* sync */
779 GETBITS(numsats,5)
780 SKIPBITS(4) /* smind, smint */
781
782 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
783 {
784 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
785 int fullsat, num;
786
787 GETBITS(sv, 6)
788 fullsat = sv < 40 ? sv : sv+80;
789 for(num = 0; num < gnss->numsats
790 && fullsat != gnss->satellites[num]; ++num)
791 ;
792
793 if(num == gnss->numsats)
794 gnss->satellites[gnss->numsats++] = fullsat;
795
796 /* L1 */
797 GETBITS(code, 1);
798 if(code)
799 {
800 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
801 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
802 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
803 gnss->codetype[num][se] =
804 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1W";
805 }
806 else
807 {
808 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
809 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
810 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
811 gnss->codetype[num][se] =
812 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1C";
813 }
814 if(!handle->info[RTCM3_MSM_GPS].type[ce])
815 {
816 handle->info[RTCM3_MSM_GPS].type[ce] =
817 handle->info[RTCM3_MSM_GPS].type[le] =
818 handle->info[RTCM3_MSM_GPS].type[se] = gnss->codetype[num][ce][1];
819 }
820 GETBITS(l1range, 24);
821 GETBITSSIGN(i, 20);
822 if((i&((1<<20)-1)) != 0x80000)
823 {
824 gnss->dataflags[num] |= (c|l);
825 gnss->measdata[num][ce] = l1range*0.02;
826 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
827 }
828 GETBITS(i, 7);
829 lastlockl1[sv] = i;
830 if(handle->lastlockGPSl1[sv] > i || i == 0)
831 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
832 if(type == 1002 || type == 1004)
833 {
834 GETBITS(amb,8);
835 if(amb && (gnss->dataflags[num] & c))
836 {
837 gnss->measdata[num][ce] += amb*299792.458;
838 gnss->measdata[num][le] += amb*299792.458;
839 ++wasamb;
840 }
841 GETBITS(i, 8);
842 if(i)
843 {
844 gnss->dataflags[num] |= s;
845 gnss->measdata[num][se] = i*0.25;
846 i /= 4*4;
847 if(i > 9) i = 9;
848 else if(i < 1) i = 1;
849 gnss->snrL1[num] = i;
850 }
851 }
852 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
853 if(type == 1003 || type == 1004)
854 {
855 /* L2 */
856 GETBITS(code,2);
857 if(code)
858 {
859 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
860 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
861 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
862 if(code >= 2)
863 {
864 gnss->codetype[num][se] =
865 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2W";
866 gnss->dataflags2[num] |= GNSSDF2_XCORRL2;
867 }
868 else
869 {
870 gnss->codetype[num][se] =
871 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2P";
872 }
873 }
874 else
875 {
876 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
877 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
878 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
879 gnss->codetype[num][se] =
880 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2 ";
881 }
882 if(!handle->info[RTCM3_MSM_GPS].type[ce])
883 {
884 handle->info[RTCM3_MSM_GPS].type[ce] =
885 handle->info[RTCM3_MSM_GPS].type[le] =
886 handle->info[RTCM3_MSM_GPS].type[se] = gnss->codetype[num][ce][1];
887 }
888 GETBITSSIGN(i,14);
889 if((i&((1<<14)-1)) != 0x2000)
890 {
891 gnss->dataflags[num] |= c;
892 gnss->measdata[num][ce] = l1range*0.02+i*0.02
893 +amb*299792.458;
894 }
895 GETBITSSIGN(i,20);
896 if((i&((1<<20)-1)) != 0x80000)
897 {
898 gnss->dataflags[num] |= l;
899 gnss->measdata[num][le] = l1range*0.02+i*0.0005
900 +amb*299792.458;
901 }
902 GETBITS(i,7);
903 lastlockl2[sv] = i;
904 if(handle->lastlockGPSl2[sv] > i || i == 0)
905 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
906 if(type == 1004)
907 {
908 GETBITS(i, 8);
909 if(i)
910 {
911 gnss->dataflags[num] |= s;
912 gnss->measdata[num][se] = i*0.25;
913 i /= 4*4;
914 if(i > 9) i = 9;
915 else if(i < 1) i = 1;
916 gnss->snrL2[num] = i;
917 }
918 }
919 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
920 }
921 }
922 for(i = 0; i < 64; ++i)
923 {
924 handle->lastlockGPSl1[i] = lastlockl1[i];
925 handle->lastlockGPSl2[i] = lastlockl2[i];
926 }
927 if(!syncf && !old)
928 {
929 handle->Data = *gnss;
930 memset(gnss, 0, sizeof(*gnss));
931 }
932 if(!syncf || old)
933 {
934 if(wasamb) /* not RINEX compatible without */
935 ret = 1;
936 else
937 ret = 2;
938 }
939#ifdef NO_RTCM3_MAIN
940 else
941 ret = type;
942#endif /* NO_RTCM3_MAIN */
943 }
944 break;
945 case 1009: case 1010: case 1011: case 1012:
946 {
947 int lastlockl1[64];
948 int lastlockl2[64];
949 struct gnssdata *gnss;
950 int i, numsats;
951 int wasamb=0;
952
953 for(i = 0; i < 64; ++i)
954 lastlockl1[i] = lastlockl2[i] = 0;
955
956 gnss = &handle->DataNew;
957
958 SKIPBITS(12) /* id */;
959 GETBITS(i,27) /* tk */
960
961 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
962 i = handle->GPSTOW*1000;
963 if(gnss->week && (gnss->timeofweek != i || gnss->week
964 != handle->GPSWeek))
965 {
966 handle->Data = *gnss;
967 memset(gnss, 0, sizeof(*gnss));
968 old = 1;
969 }
970
971 gnss->timeofweek = i;
972 gnss->week = handle->GPSWeek;
973
974 GETBITS(syncf,1) /* sync */
975 GETBITS(numsats,5)
976
977 SKIPBITS(4) /* smind, smint */
978
979 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
980 {
981 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
982 int freq;
983 int fullsat, num;
984
985 GETBITS(sv, 6)
986 fullsat = sv-1 + PRN_GLONASS_START;
987 for(num = 0; num < gnss->numsats
988 && fullsat != gnss->satellites[num]; ++num)
989 ;
990
991 if(num == gnss->numsats)
992 gnss->satellites[gnss->numsats++] = fullsat;
993
994 /* L1 */
995 GETBITS(code, 1)
996 GETBITS(freq, 5)
997
998 if(sv >= 1 && sv <= PRN_GLONASS_NUM)
999 handle->GLOFreq[sv-1] = 100+freq-7;
1000
1001 if(code)
1002 {
1003 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
1004 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
1005 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
1006 gnss->codetype[num][se] =
1007 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1P";
1008 }
1009 else
1010 {
1011 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
1012 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
1013 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
1014 gnss->codetype[num][se] =
1015 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1C";
1016 }
1017 if(!handle->info[RTCM3_MSM_GLONASS].type[ce])
1018 {
1019 handle->info[RTCM3_MSM_GLONASS].type[ce] =
1020 handle->info[RTCM3_MSM_GLONASS].type[le] =
1021 handle->info[RTCM3_MSM_GLONASS].type[se] = gnss->codetype[num][ce][1];
1022 }
1023 GETBITS(l1range, 25)
1024 GETBITSSIGN(i, 20)
1025 if((i&((1<<20)-1)) != 0x80000)
1026 {
1027 /* Handle this like GPS. Actually for GLONASS L1 range is always
1028 valid. To be on the save side, we handle it as invalid like we
1029 do for GPS and also remove range in case of 0x80000. */
1030 gnss->dataflags[num] |= (c|l);
1031 gnss->measdata[num][ce] = l1range*0.02;
1032 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
1033 }
1034 GETBITS(i, 7)
1035 lastlockl1[sv] = i;
1036 if(handle->lastlockGLOl1[sv] > i || i == 0)
1037 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
1038 if(type == 1010 || type == 1012)
1039 {
1040 GETBITS(amb,7)
1041 if(amb && (gnss->dataflags[num] & c))
1042 {
1043 gnss->measdata[num][ce] += amb*599584.916;
1044 gnss->measdata[num][le] += amb*599584.916;
1045 ++wasamb;
1046 }
1047 GETBITS(i, 8)
1048 if(i)
1049 {
1050 gnss->dataflags[num] |= s;
1051 gnss->measdata[num][se] = i*0.25;
1052 i /= 4*4;
1053 if(i > 9) i = 9;
1054 else if(i < 1) i = 1;
1055 gnss->snrL1[num] = i;
1056 }
1057 }
1058 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
1059 if(type == 1011 || type == 1012)
1060 {
1061 /* L2 */
1062 GETBITS(code,2)
1063 if(code)
1064 {
1065 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
1066 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
1067 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
1068 gnss->codetype[num][se] =
1069 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2P";
1070 }
1071 else
1072 {
1073 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
1074 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
1075 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
1076 gnss->codetype[num][se] =
1077 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2C";
1078 }
1079 if(!handle->info[RTCM3_MSM_GLONASS].type[ce])
1080 {
1081 handle->info[RTCM3_MSM_GLONASS].type[ce] =
1082 handle->info[RTCM3_MSM_GLONASS].type[le] =
1083 handle->info[RTCM3_MSM_GLONASS].type[se] = gnss->codetype[num][ce][1];
1084 }
1085 GETBITSSIGN(i,14)
1086 if((i&((1<<14)-1)) != 0x2000)
1087 {
1088 gnss->dataflags[num] |= c;
1089 gnss->measdata[num][ce] = l1range*0.02+i*0.02
1090 +amb*599584.916;
1091 }
1092 GETBITSSIGN(i,20)
1093 if((i&((1<<20)-1)) != 0x80000)
1094 {
1095 gnss->dataflags[num] |= l;
1096 gnss->measdata[num][le] = l1range*0.02+i*0.0005
1097 +amb*599584.916;
1098 }
1099 GETBITS(i,7)
1100 lastlockl2[sv] = i;
1101 if(handle->lastlockGLOl2[sv] > i || i == 0)
1102 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
1103 if(type == 1012)
1104 {
1105 GETBITS(i, 8)
1106 if(i)
1107 {
1108 gnss->dataflags[num] |= s;
1109 gnss->measdata[num][se] = i*0.25;
1110 i /= 4*4;
1111 if(i > 9) i = 9;
1112 else if(i < 1) i = 1;
1113 gnss->snrL2[num] = i;
1114 }
1115 }
1116 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
1117 }
1118 if(!sv || sv > 24) /* illegal, remove it again */
1119 --gnss->numsats;
1120 }
1121 for(i = 0; i < 64; ++i)
1122 {
1123 handle->lastlockGLOl1[i] = lastlockl1[i];
1124 handle->lastlockGLOl2[i] = lastlockl2[i];
1125 }
1126 if(!syncf && !old)
1127 {
1128 handle->Data = *gnss;
1129 memset(gnss, 0, sizeof(*gnss));
1130 }
1131 if(!syncf || old)
1132 {
1133 if(wasamb) /* not RINEX compatible without */
1134 ret = 1;
1135 else
1136 ret = 2;
1137 }
1138#ifdef NO_RTCM3_MAIN
1139 else
1140 ret = type;
1141#endif /* NO_RTCM3_MAIN */
1142 }
1143 break;
1144 case 1071: case 1081: case 1091: case 1101: case 1111: case 1121:
1145 case 1072: case 1082: case 1092: case 1102: case 1112: case 1122:
1146 case 1073: case 1083: case 1093: case 1103: case 1113: case 1123:
1147 case 1074: case 1084: case 1094: case 1104: case 1114: case 1124:
1148 case 1075: case 1085: case 1095: case 1105: case 1115: case 1125:
1149 case 1076: case 1086: case 1096: case 1106: case 1116: case 1126:
1150 case 1077: case 1087: case 1097: case 1107: case 1117: case 1127:
1151 if(handle->GPSWeek)
1152 {
1153 struct CodeData {
1154 int typeR;
1155 int typeP;
1156 int typeD;
1157 int typeS;
1158 int lock;
1159 double wl;
1160 const char *code; /* currently unused */
1161 };
1162 struct CodeData gps[RTCM3_MSM_NUMSIG] =
1163 {
1164 {0,0,0,0,0,0,0},
1165 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1166 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
1167 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1168 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
1169 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1170 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1W"},
1171 {0,0,0,0,0,0,0}/*{GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1172 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1Y"}*/,
1173 {0,0,0,0,0,0,0},
1174 {0,0,0,0,0,0,0},
1175 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1176 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2C"},
1177 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1178 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2P"},
1179 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1180 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2W"},
1181 {0,0,0,0,0,0,0}/*{GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1182 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2Y"}*/,
1183 {0,0,0,0,0,0,0},
1184 {0,0,0,0,0,0,0},
1185 {0,0,0,0,0,0,0},
1186 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1187 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
1188 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1189 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
1190 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1191 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
1192 {0,0,0,0,0,0,0},
1193 {0,0,0,0,0,0,0},
1194 {0,0,0,0,0,0,0},
1195 {0,0,0,0,0,0,0},
1196 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1197 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
1198 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1199 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
1200 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1201 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
1202 {0,0,0,0,0,0,0},
1203 {0,0,0,0,0,0,0},
1204 {0,0,0,0,0,0,0},
1205 {0,0,0,0,0,0,0},
1206 {0,0,0,0,0,0,0},
1207 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1208 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1S"},
1209 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1210 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1L"},
1211 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1212 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1X"}
1213 };
1214 /* NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later! */
1215 struct CodeData glo[RTCM3_MSM_NUMSIG] =
1216 {
1217 {0,0,0,0,0,0,0},
1218 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1219 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1C"},
1220 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1221 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,0.0,"1P"},
1222 {0,0,0,0,0,0,0},
1223 {0,0,0,0,0,0,0},
1224 {0,0,0,0,0,0,0},
1225 {0,0,0,0,0,0,0},
1226 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1227 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,1.0,"2C"},
1228 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1229 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,1.0,"2P"},
1230 {0,0,0,0,0,0,0},
1231 {0,0,0,0,0,0,0},
1232 {0,0,0,0,0,0,0},
1233 {0,0,0,0,0,0,0},
1234 {0,0,0,0,0,0,0},
1235 {0,0,0,0,0,0,0},
1236 {0,0,0,0,0,0,0},
1237 {0,0,0,0,0,0,0},
1238 {0,0,0,0,0,0,0},
1239 {0,0,0,0,0,0,0},
1240 {0,0,0,0,0,0,0},
1241 {0,0,0,0,0,0,0},
1242 {0,0,0,0,0,0,0},
1243 {0,0,0,0,0,0,0},
1244 {0,0,0,0,0,0,0},
1245 {0,0,0,0,0,0,0},
1246 {0,0,0,0,0,0,0},
1247 {0,0,0,0,0,0,0},
1248 {0,0,0,0,0,0,0},
1249 {0,0,0,0,0,0,0},
1250 {0,0,0,0,0,0,0},
1251 {0,0,0,0,0,0,0},
1252 {0,0,0,0,0,0,0}
1253 };
1254 struct CodeData gal[RTCM3_MSM_NUMSIG] =
1255 {
1256 {0,0,0,0,0,0,0},
1257 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1258 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1C"},
1259 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1260 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1A"},
1261 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1262 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1B"},
1263 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1264 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1X"},
1265 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1266 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1Z"},
1267 {0,0,0,0,0,0,0},
1268 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1269 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6C"},
1270 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1271 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6A"},
1272 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1273 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6B"},
1274 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1275 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6X"},
1276 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1277 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Z"},
1278 {0,0,0,0,0,0,0},
1279 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1280 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7I"},
1281 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1282 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7Q"},
1283 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1284 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7X"},
1285 {0,0,0,0,0,0,0},
1286 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1287 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8I"},
1288 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1289 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8Q"},
1290 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1291 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8X"},
1292 {0,0,0,0,0,0,0},
1293 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1294 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5I"},
1295 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1296 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5Q"},
1297 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1298 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5X"},
1299 {0,0,0,0,0,0,0},
1300 {0,0,0,0,0,0,0},
1301 {0,0,0,0,0,0,0},
1302 {0,0,0,0,0,0,0},
1303 {0,0,0,0,0,0,0},
1304 {0,0,0,0,0,0,0},
1305 {0,0,0,0,0,0,0},
1306 {0,0,0,0,0,0,0},
1307 };
1308 struct CodeData qzss[RTCM3_MSM_NUMSIG] =
1309 {
1310 {0,0,0,0,0,0,0},
1311 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1312 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
1313 {0,0,0,0,0,0,0},
1314 {0,0,0,0,0,0,0},
1315 {0,0,0,0,0,0,0},
1316 {GNSSENTRY_CSAIFDATA,GNSSENTRY_LSAIFDATA,GNSSENTRY_DSAIFDATA,
1317 GNSSENTRY_SSAIFDATA,GNSSDF2_LOCKLOSSSAIF,GPS_WAVELENGTH_L1,"1Z"},
1318 {0,0,0,0,0,0,0},
1319 {0,0,0,0,0,0,0},
1320 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1321 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6S"},
1322 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1323 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6L"},
1324 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1325 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6X"},
1326 {0,0,0,0,0,0,0},
1327 {0,0,0,0,0,0,0},
1328 {0,0,0,0,0,0,0},
1329 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1330 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
1331 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1332 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
1333 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1334 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
1335 {0,0,0,0,0,0,0},
1336 {0,0,0,0,0,0,0},
1337 {0,0,0,0,0,0,0},
1338 {0,0,0,0,0,0,0},
1339 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1340 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
1341 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1342 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
1343 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1344 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
1345 {0,0,0,0,0,0,0},
1346 {0,0,0,0,0,0,0},
1347 {0,0,0,0,0,0,0},
1348 {0,0,0,0,0,0,0},
1349 {0,0,0,0,0,0,0},
1350 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1351 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1D"},
1352 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1353 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
1354 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1355 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1X"}
1356 };
1357 struct CodeData bds[RTCM3_MSM_NUMSIG] =
1358 {
1359 {0,0,0,0,0,0,0},
1360 {GNSSENTRY_CB1DATA,GNSSENTRY_LB1DATA,GNSSENTRY_DB1DATA,
1361 GNSSENTRY_SB1DATA,GNSSDF2_LOCKLOSSB1,BDS_WAVELENGTH_B1,"1I"},
1362 {0,0,0,0,0,0,0},
1363 {0,0,0,0,0,0,0},
1364 {0,0,0,0,0,0,0},
1365 {0,0,0,0,0,0,0},
1366 {0,0,0,0,0,0,0},
1367 {GNSSENTRY_CB3DATA,GNSSENTRY_LB3DATA,GNSSENTRY_DB3DATA,
1368 GNSSENTRY_SB3DATA,GNSSDF2_LOCKLOSSB3,BDS_WAVELENGTH_B3,"6I"},
1369 {0,0,0,0,0,0,0},
1370 {0,0,0,0,0,0,0},
1371 {0,0,0,0,0,0,0},
1372 {0,0,0,0,0,0,0},
1373 {0,0,0,0,0,0,0},
1374 {GNSSENTRY_CB2DATA,GNSSENTRY_LB2DATA,GNSSENTRY_DB2DATA,
1375 GNSSENTRY_SB2DATA,GNSSDF2_LOCKLOSSB2,BDS_WAVELENGTH_B2,"7I"},
1376 {0,0,0,0,0,0,0},
1377 {0,0,0,0,0,0,0},
1378 {0,0,0,0,0,0,0},
1379 {0,0,0,0,0,0,0},
1380 {0,0,0,0,0,0,0},
1381 {0,0,0,0,0,0,0},
1382 {0,0,0,0,0,0,0},
1383 {0,0,0,0,0,0,0},
1384 {0,0,0,0,0,0,0},
1385 {0,0,0,0,0,0,0},
1386 {0,0,0,0,0,0,0},
1387 {0,0,0,0,0,0,0},
1388 {0,0,0,0,0,0,0},
1389 {0,0,0,0,0,0,0},
1390 {0,0,0,0,0,0,0},
1391 {0,0,0,0,0,0,0},
1392 {0,0,0,0,0,0,0},
1393 {0,0,0,0,0,0,0},
1394 };
1395
1396 int sys = RTCM3_MSM_GPS, i=0, count, j, old = 0, wasnoamb = 0,
1397 start=PRN_GPS_START;
1398 int syncf, sigmask, numsat = 0, numsig = 0, numcells;
1399 uint64_t satmask, cellmask, ui;
1400 double rrmod[RTCM3_MSM_NUMSAT];
1401 int rrint[RTCM3_MSM_NUMSAT], rdop[RTCM3_MSM_NUMSAT],
1402 extsat[RTCM3_MSM_NUMSAT];
1403 int ll[RTCM3_MSM_NUMCELLS]/*, hc[RTCM3_MSM_NUMCELLS]*/;
1404 double cnr[RTCM3_MSM_NUMCELLS];
1405 double cp[RTCM3_MSM_NUMCELLS], psr[RTCM3_MSM_NUMCELLS],
1406 dop[RTCM3_MSM_NUMCELLS];
1407 struct gnssdata *gnss = &handle->DataNew;
1408
1409 SKIPBITS(12)
1410 if(type >= 1121)
1411 {
1412 sys = RTCM3_MSM_BDS;
1413 start = PRN_BDS_START;
1414 }
1415 else if(type >= 1111)
1416 {
1417 sys = RTCM3_MSM_QZSS;
1418 start = PRN_QZSS_START;
1419 }
1420 else if(type >= 1101)
1421 {
1422 sys = RTCM3_MSM_SBAS;
1423 start = PRN_SBAS_START;
1424 }
1425 else if(type >= 1091)
1426 {
1427 sys = RTCM3_MSM_GALILEO;
1428 start = PRN_GALILEO_START;
1429 }
1430 else if(type >= 1081)
1431 {
1432 sys = RTCM3_MSM_GLONASS;
1433 start = PRN_GLONASS_START;
1434 }
1435
1436 for(i = 0; i < RTCM3_MSM_NUMSAT; ++i)
1437 extsat[i] = 15;
1438
1439 switch(sys)
1440 {
1441 case RTCM3_MSM_BDS:
1442 GETBITS(i,30)
1443 i += 14000;
1444 if(i >= 7*24*60*60*1000)
1445 i -= 7*24*60*60*1000;
1446 if(i/1000 < (int)handle->GPSTOW - 86400)
1447 ++handle->GPSWeek;
1448 handle->GPSTOW = i/1000;
1449 break;
1450 case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
1451 case RTCM3_MSM_QZSS:
1452 case RTCM3_MSM_SBAS:
1453 case RTCM3_MSM_GPS:
1454 GETBITS(i,30)
1455 if(i/1000 < (int)handle->GPSTOW - 86400)
1456 ++handle->GPSWeek;
1457 handle->GPSTOW = i/1000;
1458 break;
1459 case RTCM3_MSM_GLONASS:
1460 SKIPBITS(3)
1461 GETBITS(i,27) /* tk */
1462
1463 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
1464 i = handle->GPSTOW*1000;
1465 break;
1466 }
1467
1468 if(gnss->week && (gnss->timeofweek != i || gnss->week
1469 != handle->GPSWeek))
1470 {
1471 handle->Data = *gnss;
1472 memset(gnss, 0, sizeof(*gnss));
1473 old = 1;
1474 }
1475 gnss->timeofweek = i;
1476 gnss->week = handle->GPSWeek;
1477
1478 GETBITS(syncf, 1)
1479 SKIPBITS(3+7+2+2+1+3)
1480 GETBITS64(satmask, RTCM3_MSM_NUMSAT)
1481
1482 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1483 for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1484 ++numsat;
1485 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1486 for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1487 ++numsig;
1488 i = numsat*numsig;
1489 GETBITS64(cellmask, (unsigned)i)
1490
1491 switch(type % 10)
1492 {
1493 case 1: case 2: case 3:
1494 ++wasnoamb;
1495 for(j = numsat; j--;)
1496 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1497 break;
1498 case 4: case 6:
1499 for(j = numsat; j--;)
1500 GETBITS(rrint[j], 8)
1501 for(j = numsat; j--;)
1502 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1503 break;
1504 case 5: case 7:
1505 for(j = numsat; j--;)
1506 GETBITS(rrint[j], 8)
1507 for(j = numsat; j--;)
1508 GETBITS(extsat[j], 4)
1509 for(j = numsat; j--;)
1510 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1511 for(j = numsat; j--;)
1512 GETBITSSIGN(rdop[j], 14)
1513 break;
1514 }
1515
1516 numcells = numsat*numsig;
1517 if(numcells <= RTCM3_MSM_NUMCELLS)
1518 {
1519 switch(type % 10)
1520 {
1521 case 1:
1522 for(count = numcells; count--;)
1523 if(cellmask & (UINT64(1)<<count))
1524 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1525 break;
1526 case 2:
1527 for(count = numcells; count--;)
1528 if(cellmask & (UINT64(1)<<count))
1529 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1530 for(count = numcells; count--;)
1531 if(cellmask & (UINT64(1)<<count))
1532 GETBITS(ll[count], 4)
1533 for(count = numcells; count--;)
1534 if(cellmask & (UINT64(1)<<count))
1535 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1536 break;
1537 case 3:
1538 for(count = numcells; count--;)
1539 if(cellmask & (UINT64(1)<<count))
1540 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1541 for(count = numcells; count--;)
1542 if(cellmask & (UINT64(1)<<count))
1543 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1544 for(count = numcells; count--;)
1545 if(cellmask & (UINT64(1)<<count))
1546 GETBITS(ll[count], 4)
1547 for(count = numcells; count--;)
1548 if(cellmask & (UINT64(1)<<count))
1549 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1550 break;
1551 case 4:
1552 for(count = numcells; count--;)
1553 if(cellmask & (UINT64(1)<<count))
1554 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1555 for(count = numcells; count--;)
1556 if(cellmask & (UINT64(1)<<count))
1557 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1558 for(count = numcells; count--;)
1559 if(cellmask & (UINT64(1)<<count))
1560 GETBITS(ll[count], 4)
1561 for(count = numcells; count--;)
1562 if(cellmask & (UINT64(1)<<count))
1563 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1564 for(count = numcells; count--;)
1565 if(cellmask & (UINT64(1)<<count))
1566 GETBITS(cnr[count], 6)
1567 break;
1568 case 5:
1569 for(count = numcells; count--;)
1570 if(cellmask & (UINT64(1)<<count))
1571 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1572 for(count = numcells; count--;)
1573 if(cellmask & (UINT64(1)<<count))
1574 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1575 for(count = numcells; count--;)
1576 if(cellmask & (UINT64(1)<<count))
1577 GETBITS(ll[count], 4)
1578 for(count = numcells; count--;)
1579 if(cellmask & (UINT64(1)<<count))
1580 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1581 for(count = numcells; count--;)
1582 if(cellmask & (UINT64(1)<<count))
1583 GETFLOAT(cnr[count], 6, 1.0)
1584 for(count = numcells; count--;)
1585 if(cellmask & (UINT64(1)<<count))
1586 GETFLOATSIGN(dop[count], 15, 0.0001)
1587 break;
1588 case 6:
1589 for(count = numcells; count--;)
1590 if(cellmask & (UINT64(1)<<count))
1591 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1592 for(count = numcells; count--;)
1593 if(cellmask & (UINT64(1)<<count))
1594 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1595 for(count = numcells; count--;)
1596 if(cellmask & (UINT64(1)<<count))
1597 GETBITS(ll[count], 10)
1598 for(count = numcells; count--;)
1599 if(cellmask & (UINT64(1)<<count))
1600 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1601 for(count = numcells; count--;)
1602 if(cellmask & (UINT64(1)<<count))
1603 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1604 break;
1605 case 7:
1606 for(count = numcells; count--;)
1607 if(cellmask & (UINT64(1)<<count))
1608 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1609 for(count = numcells; count--;)
1610 if(cellmask & (UINT64(1)<<count))
1611 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1612 for(count = numcells; count--;)
1613 if(cellmask & (UINT64(1)<<count))
1614 GETBITS(ll[count], 10)
1615 for(count = numcells; count--;)
1616 if(cellmask & (UINT64(1)<<count))
1617 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1618 for(count = numcells; count--;)
1619 if(cellmask & (UINT64(1)<<count))
1620 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1621 for(count = numcells; count--;)
1622 if(cellmask & (UINT64(1)<<count))
1623 GETFLOATSIGN(dop[count], 15, 0.0001)
1624 break;
1625 }
1626 i = RTCM3_MSM_NUMSAT;
1627 j = -1;
1628 for(count = numcells; count--;)
1629 {
1630 while(j >= 0 && !(sigmask&(1<<--j)))
1631 ;
1632 if(j < 0)
1633 {
1634 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1635 ;
1636 j = RTCM3_MSM_NUMSIG;
1637 while(!(sigmask&(1<<--j)))
1638 ;
1639 --numsat;
1640 }
1641 if(cellmask & (UINT64(1)<<count))
1642 {
1643 struct CodeData cd = {0,0,0,0,0,0,0};
1644 double wl = 0.0;
1645 switch(sys)
1646 {
1647 case RTCM3_MSM_QZSS:
1648 cd = qzss[RTCM3_MSM_NUMSIG-j-1];
1649 wl = cd.wl;
1650 break;
1651 case RTCM3_MSM_BDS:
1652 cd = bds[RTCM3_MSM_NUMSIG-j-1];
1653 wl = cd.wl;
1654 break;
1655 case RTCM3_MSM_GPS: case RTCM3_MSM_SBAS:
1656 cd = gps[RTCM3_MSM_NUMSIG-j-1];
1657 wl = cd.wl;
1658 break;
1659 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1660 {
1661 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1662 if(!k && extsat[numsat] < 14)
1663 {
1664 k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1]
1665 = 100+extsat[numsat]-7;
1666 }
1667 if(k)
1668 {
1669 if(cd.wl == 0.0)
1670 wl = GLO_WAVELENGTH_L1(k-100);
1671 else if(cd.wl == 1.0)
1672 wl = GLO_WAVELENGTH_L2(k-100);
1673 }
1674 }
1675 break;
1676 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1677 wl = cd.wl;
1678 break;
1679 }
1680 if(cd.lock && wl) /* lock cannot have a valid zero value */
1681 {
1682 int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1683
1684 if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1685 fullsat += PRN_GIOVE_START-50;
1686 else
1687 fullsat += start;
1688
1689 for(num = 0; num < gnss->numsats
1690 && fullsat != gnss->satellites[num]; ++num)
1691 ;
1692
1693 if(num == gnss->numsats)
1694 gnss->satellites[gnss->numsats++] = fullsat;
1695
1696 gnss->codetype[num][cd.typeR] =
1697 gnss->codetype[num][cd.typeP] =
1698 gnss->codetype[num][cd.typeD] =
1699 gnss->codetype[num][cd.typeS] = cd.code;
1700 if(!handle->info[sys].type[cd.typeR])
1701 {
1702 handle->info[sys].type[cd.typeR] =
1703 handle->info[sys].type[cd.typeP] =
1704 handle->info[sys].type[cd.typeD] =
1705 handle->info[sys].type[cd.typeS] = cd.code[1];
1706 }
1707
1708 switch(type % 10)
1709 {
1710 case 1:
1711 if(psr[count] > -1.0/(1<<10))
1712 {
1713 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1714 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1715 gnss->dataflags[num] |= (1LL<<cd.typeR);
1716 }
1717 break;
1718 case 2:
1719 if(wl && cp[count] > -1.0/(1<<8))
1720 {
1721 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1722 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1723 if(handle->lastlockmsm[j][i] > ll[count])
1724 gnss->dataflags2[num] |= cd.lock;
1725 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1726 gnss->dataflags[num] |= (1LL<<cd.typeP);
1727 }
1728 break;
1729 case 3:
1730 if(psr[count] > -1.0/(1<<10))
1731 {
1732 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1733 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1734 gnss->dataflags[num] |= (1LL<<cd.typeR);
1735 }
1736
1737 if(wl && cp[count] > -1.0/(1<<8))
1738 {
1739 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1740 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1741 if(handle->lastlockmsm[j][i] > ll[count])
1742 gnss->dataflags2[num] |= cd.lock;
1743 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1744 gnss->dataflags[num] |= (1LL<<cd.typeP);
1745 }
1746 break;
1747 case 4:
1748 if(psr[count] > -1.0/(1<<10))
1749 {
1750 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1751 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1752 gnss->dataflags[num] |= (1LL<<cd.typeR);
1753 }
1754
1755 if(wl && cp[count] > -1.0/(1<<8))
1756 {
1757 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1758 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1759 if(handle->lastlockmsm[j][i] > ll[count])
1760 gnss->dataflags2[num] |= cd.lock;
1761 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1762 gnss->dataflags[num] |= (1LL<<cd.typeP);
1763 }
1764
1765 gnss->measdata[num][cd.typeS] = cnr[count];
1766 gnss->dataflags[num] |= (1LL<<cd.typeS);
1767 break;
1768 case 5:
1769 if(psr[count] > -1.0/(1<<10))
1770 {
1771 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1772 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1773 gnss->dataflags[num] |= (1LL<<cd.typeR);
1774 }
1775
1776 if(wl && cp[count] > -1.0/(1<<8))
1777 {
1778 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1779 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1780 if(handle->lastlockmsm[j][i] > ll[count])
1781 gnss->dataflags2[num] |= cd.lock;
1782 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1783 gnss->dataflags[num] |= (1LL<<cd.typeP);
1784 }
1785
1786 gnss->measdata[num][cd.typeS] = cnr[count];
1787 gnss->dataflags[num] |= (1<<cd.typeS);
1788
1789 if(dop[count] > -1.6384)
1790 {
1791 gnss->measdata[num][cd.typeD] = -(dop[count]
1792 +rdop[numsat])/wl;
1793 gnss->dataflags[num] |= (1LL<<cd.typeD);
1794 }
1795 break;
1796 case 6:
1797 if(psr[count] > -1.0/(1<<10))
1798 {
1799 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1800 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1801 gnss->dataflags[num] |= (1LL<<cd.typeR);
1802 }
1803
1804 if(wl && cp[count] > -1.0/(1<<8))
1805 {
1806 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1807 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1808 if(handle->lastlockmsm[j][i] > ll[count])
1809 gnss->dataflags2[num] |= cd.lock;
1810 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1811 gnss->dataflags[num] |= (1LL<<cd.typeP);
1812 }
1813
1814 gnss->measdata[num][cd.typeS] = cnr[count];
1815 gnss->dataflags[num] |= (1LL<<cd.typeS);
1816 break;
1817 case 7:
1818 if(psr[count] > -1.0/(1<<10))
1819 {
1820 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1821 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1822 gnss->dataflags[num] |= (1LL<<cd.typeR);
1823 }
1824
1825 if(wl && cp[count] > -1.0/(1<<8))
1826 {
1827 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1828 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1829 if(handle->lastlockmsm[j][i] > ll[count])
1830 gnss->dataflags2[num] |= cd.lock;
1831 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1832 gnss->dataflags[num] |= (1LL<<cd.typeP);
1833 }
1834
1835 gnss->measdata[num][cd.typeS] = cnr[count];
1836 gnss->dataflags[num] |= (1LL<<cd.typeS);
1837
1838 if(dop[count] > -1.6384)
1839 {
1840 gnss->measdata[num][cd.typeD] = -(dop[count]
1841 +rdop[numsat])/wl;
1842 gnss->dataflags[num] |= (1LL<<cd.typeD);
1843 }
1844 break;
1845 }
1846 }
1847 }
1848 }
1849 }
1850 if(!syncf && !old)
1851 {
1852 handle->Data = *gnss;
1853 memset(gnss, 0, sizeof(*gnss));
1854 }
1855 if(!syncf || old)
1856 {
1857 if(!wasnoamb) /* not RINEX compatible without */
1858 ret = 1;
1859 else
1860 ret = 2;
1861 }
1862#ifdef NO_RTCM3_MAIN
1863 else
1864 ret = type;
1865#endif /* NO_RTCM3_MAIN */
1866 }
1867 break;
1868 }
1869 }
1870 return ret;
1871}
1872
1873struct Header
1874{
1875 const char *version;
1876 const char *pgm;
1877 const char *marker;
1878 const char *markertype;
1879 const char *observer;
1880 const char *receiver;
1881 const char *antenna;
1882 const char *position;
1883 const char *antennaposition;
1884 const char *wavelength;
1885 const char *typesofobs; /* should not be modified outside */
1886 const char *typesofobsG; /* should not be modified outside */
1887 const char *typesofobsR; /* should not be modified outside */
1888 const char *typesofobsS; /* should not be modified outside */
1889 const char *typesofobsE; /* should not be modified outside */
1890 const char *typesofobsC; /* should not be modified outside */
1891 const char *typesofobsJ; /* should not be modified outside */
1892 const char *timeoffirstobs; /* should not be modified outside */
1893};
1894
1895#define MAXHEADERLINES 50
1896#define MAXHEADERBUFFERSIZE 4096
1897struct HeaderData
1898{
1899 union
1900 {
1901 struct Header named;
1902 const char *unnamed[MAXHEADERLINES];
1903 } data;
1904 int numheaders;
1905};
1906
1907void converttime(struct converttimeinfo *c, int week, int tow)
1908{
1909 int i, k, doy, j; /* temporary variables */
1910 j = week*(7*24*60*60) + tow + 5*24*60*60;
1911 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1912 j -= k;
1913 c->year = i;
1914 doy = 1+ (j / (24*60*60));
1915 j %= (24*60*60);
1916 c->hour = j / (60*60);
1917 j %= (60*60);
1918 c->minute = j / 60;
1919 c->second = j % 60;
1920 j = 0;
1921 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1922 j += k;
1923 c->month = i;
1924 c->day = doy - j;
1925}
1926
1927void converttimebds(struct converttimeinfo *c, int week, int tow)
1928{
1929 int i, k, doy, j; /* temporary variables */
1930 j = week*(7*24*60*60) + tow;
1931 for(i = 2006; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1932 j -= k;
1933 c->year = i;
1934 doy = 1+ (j / (24*60*60));
1935 j %= (24*60*60);
1936 c->hour = j / (60*60);
1937 j %= (60*60);
1938 c->minute = j / 60;
1939 c->second = j % 60;
1940 j = 0;
1941 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1942 j += k;
1943 c->month = i;
1944 c->day = doy - j;
1945}
1946
1947#ifndef NO_RTCM3_MAIN
1948void RTCM3Error(const char *fmt, ...)
1949{
1950 va_list v;
1951 va_start(v, fmt);
1952 vfprintf(stderr, fmt, v);
1953 va_end(v);
1954}
1955#endif
1956
1957void RTCM3Text(const char *fmt, ...)
1958{
1959 va_list v;
1960 va_start(v, fmt);
1961 vprintf(fmt, v);
1962 va_end(v);
1963}
1964
1965static void fixrevision(void)
1966{
1967 if(revisionstr[0] == '$')
1968 {
1969 char *a;
1970 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1971 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1972 for(a = revisionstr+11; *a && *a != ' '; ++a)
1973 revisionstr[i++] = *a;
1974 revisionstr[i] = 0;
1975 }
1976}
1977
1978static int HandleRunBy(char *buffer, int buffersize, const char **u,
1979int rinex3)
1980{
1981 const char *user;
1982 time_t t;
1983 struct tm * t2;
1984
1985#ifdef NO_RTCM3_MAIN
1986 fixrevision();
1987#endif
1988
1989 user= getenv("USER");
1990 if(!user) user = "";
1991 t = time(&t);
1992 t2 = gmtime(&t);
1993 if(u) *u = user;
1994 if(rinex3)
1995 {
1996 return 1+snprintf(buffer, buffersize,
1997 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1998 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1999 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
2000 }
2001 else
2002 {
2003 return 1+snprintf(buffer, buffersize,
2004 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
2005 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
2006 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min);
2007 }
2008}
2009
2010#ifdef NO_RTCM3_MAIN
2011#define NUMSTARTSKIP 1
2012#else
2013#define NUMSTARTSKIP 3
2014#endif
2015
2016int HandleObsHeader(struct RTCM3ParserData *Parser, char *buffer,
2017size_t buffersize, struct HeaderData *hdata)
2018{
2019 int buffersizeold = buffersize;
2020 int i, modified = 0;
2021
2022 if(Parser->rinex3)
2023 {
2024 int flags;
2025#define CHECKFLAGSNEW(a, b, c) \
2026 if(flags & GNSSDF_##b##DATA) \
2027 { \
2028 int new = hdata ? 1 : 0; \
2029 if(!hdata) /* check if already known */ \
2030 { \
2031 int ic; \
2032 for(ic = 0; ic < Parser->info[RTCM3_MSM_##a].numtypes \
2033 && Parser->info[RTCM3_MSM_##a].flags[ic] != GNSSDF_##b##DATA; ++ic) \
2034 ; \
2035 if(ic == Parser->info[RTCM3_MSM_##a].numtypes) \
2036 new = 1; \
2037 } \
2038 if(new) \
2039 { \
2040 Parser->info[RTCM3_MSM_##a].flags[Parser->info[RTCM3_MSM_##a].numtypes] \
2041 = GNSSDF_##b##DATA; \
2042 Parser->info[RTCM3_MSM_##a].pos[Parser->info[RTCM3_MSM_##a].numtypes] \
2043 = GNSSENTRY_##b##DATA; \
2044 if(Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]) \
2045 { \
2046 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
2047 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
2048 " %-2.2s%c", #c, Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]); \
2049 } \
2050 else \
2051 { \
2052 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
2053 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
2054 " %-3s", #c); \
2055 } \
2056 ++Parser->info[RTCM3_MSM_##a].numtypes; \
2057 ++modified; \
2058 } \
2059 }
2060
2061#define INITFLAGS(a) \
2062 flags = Parser->startflags; \
2063 modified = 0; \
2064 for(i = 0; i < Parser->Data.numsats; ++i) \
2065 { \
2066 if(Parser->Data.satellites[i] >= PRN_##a##_START \
2067 && Parser->Data.satellites[i] <= PRN_##a##_END) \
2068 flags |= Parser->Data.dataflags[i]; \
2069 }
2070
2071 INITFLAGS(SBAS)
2072 CHECKFLAGSNEW(SBAS, C1, C1C)
2073 CHECKFLAGSNEW(SBAS, L1C, L1C)
2074 CHECKFLAGSNEW(SBAS, D1C, D1C)
2075 CHECKFLAGSNEW(SBAS, S1C, S1C)
2076 CHECKFLAGSNEW(SBAS, C5, C5)
2077 CHECKFLAGSNEW(SBAS, L5, L5)
2078 CHECKFLAGSNEW(SBAS, D5, D5)
2079 CHECKFLAGSNEW(SBAS, S5, S5)
2080
2081 if(modified)
2082 {
2083 if(hdata)
2084 hdata->data.named.typesofobsS = buffer;
2085 i = 1+snprintf(buffer, buffersize,
2086 "S %3d%-52.52s SYS / # / OBS TYPES",
2087 Parser->info[RTCM3_MSM_SBAS].numtypes, Parser->fieldbufferSBAS);
2088 buffer += i; buffersize -= i;
2089 }
2090
2091 INITFLAGS(GPS)
2092 CHECKFLAGSNEW(GPS, C1, C1C)
2093 CHECKFLAGSNEW(GPS, L1C, L1C)
2094 CHECKFLAGSNEW(GPS, D1C, D1C)
2095 CHECKFLAGSNEW(GPS, S1C, S1C)
2096 CHECKFLAGSNEW(GPS, P1, C1W)
2097 CHECKFLAGSNEW(GPS, L1P, L1W)
2098 CHECKFLAGSNEW(GPS, D1P, D1W)
2099 CHECKFLAGSNEW(GPS, S1P, S1W)
2100 CHECKFLAGSNEW(GPS, C5, C5)
2101 CHECKFLAGSNEW(GPS, L5, L5)
2102 CHECKFLAGSNEW(GPS, D5, D5)
2103 CHECKFLAGSNEW(GPS, S5, S5)
2104 CHECKFLAGSNEW(GPS, P2, C2W)
2105 CHECKFLAGSNEW(GPS, L2P, L2W)
2106 CHECKFLAGSNEW(GPS, D2P, D2W)
2107 CHECKFLAGSNEW(GPS, S2P, S2W)
2108 CHECKFLAGSNEW(GPS, C2, C2)
2109 CHECKFLAGSNEW(GPS, L2C, L2)
2110 CHECKFLAGSNEW(GPS, D2C, D2)
2111 CHECKFLAGSNEW(GPS, S2C, S2)
2112 CHECKFLAGSNEW(GPS, C1N, C1)
2113 CHECKFLAGSNEW(GPS, L1N, L1)
2114 CHECKFLAGSNEW(GPS, D1N, D1)
2115 CHECKFLAGSNEW(GPS, S1N, S1)
2116
2117 if(modified)
2118 {
2119 if(hdata)
2120 hdata->data.named.typesofobsG = buffer;
2121 i = 1+snprintf(buffer, buffersize,
2122 "G %3d%-52.52s SYS / # / OBS TYPES",
2123 Parser->info[RTCM3_MSM_GPS].numtypes, Parser->fieldbufferGPS);
2124 if(Parser->info[RTCM3_MSM_GPS].numtypes>13)
2125 {
2126 i += snprintf(buffer+i-1, buffersize,
2127 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGPS+13*4);
2128 }
2129 buffer += i; buffersize -= i;
2130 }
2131
2132 INITFLAGS(GLONASS)
2133 CHECKFLAGSNEW(GLONASS, C1, C1C)
2134 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2135 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2136 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2137 CHECKFLAGSNEW(GLONASS, P1, C1P)
2138 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2139 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2140 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2141 CHECKFLAGSNEW(GLONASS, P2, C2P)
2142 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2143 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2144 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2145 CHECKFLAGSNEW(GLONASS, C2, C2C)
2146 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2147 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2148 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2149
2150 if(modified)
2151 {
2152 if(hdata)
2153 hdata->data.named.typesofobsR = buffer;
2154 i = 1+snprintf(buffer, buffersize,
2155 "R %3d%-52.52s SYS / # / OBS TYPES",
2156 Parser->info[RTCM3_MSM_GLONASS].numtypes, Parser->fieldbufferGLONASS);
2157 if(Parser->info[RTCM3_MSM_GLONASS].numtypes>13)
2158 {
2159 i += snprintf(buffer+i-1, buffersize,
2160 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGLONASS+13*4);
2161 }
2162 buffer += i; buffersize -= i;
2163 }
2164
2165 INITFLAGS(GALGIO)
2166 CHECKFLAGSNEW(GALILEO, C1, C1)
2167 CHECKFLAGSNEW(GALILEO, L1C, L1)
2168 CHECKFLAGSNEW(GALILEO, D1C, D1)
2169 CHECKFLAGSNEW(GALILEO, S1C, S1)
2170 CHECKFLAGSNEW(GALILEO, C6, C6)
2171 CHECKFLAGSNEW(GALILEO, L6, L6)
2172 CHECKFLAGSNEW(GALILEO, D6, D6)
2173 CHECKFLAGSNEW(GALILEO, S6, S6)
2174 CHECKFLAGSNEW(GALILEO, C5, C5)
2175 CHECKFLAGSNEW(GALILEO, L5, L5)
2176 CHECKFLAGSNEW(GALILEO, D5, D5)
2177 CHECKFLAGSNEW(GALILEO, S5, S5)
2178 CHECKFLAGSNEW(GALILEO, C5B, C7)
2179 CHECKFLAGSNEW(GALILEO, L5B, L7)
2180 CHECKFLAGSNEW(GALILEO, D5B, D7)
2181 CHECKFLAGSNEW(GALILEO, S5B, S7)
2182 CHECKFLAGSNEW(GALILEO, C5AB, C8)
2183 CHECKFLAGSNEW(GALILEO, L5AB, L8)
2184 CHECKFLAGSNEW(GALILEO, D5AB, D8)
2185 CHECKFLAGSNEW(GALILEO, S5AB, S8)
2186
2187 if(modified)
2188 {
2189 if(hdata)
2190 hdata->data.named.typesofobsE = buffer;
2191 i = 1+snprintf(buffer, buffersize,
2192 "E %3d%-52.52s SYS / # / OBS TYPES",
2193 Parser->info[RTCM3_MSM_GALILEO].numtypes, Parser->fieldbufferGALILEO);
2194 if(Parser->info[RTCM3_MSM_GALILEO].numtypes>13)
2195 {
2196 i += snprintf(buffer+i-1, buffersize,
2197 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGALILEO+13*4);
2198 }
2199 buffer += i; buffersize -= i;
2200 }
2201
2202 INITFLAGS(BDS)
2203 CHECKFLAGSNEW(BDS, CB1, C2I)
2204 CHECKFLAGSNEW(BDS, LB1, L2I)
2205 CHECKFLAGSNEW(BDS, DB1, D2I)
2206 CHECKFLAGSNEW(BDS, SB1, S2I)
2207 CHECKFLAGSNEW(BDS, CB2, C7I)
2208 CHECKFLAGSNEW(BDS, LB2, L7I)
2209 CHECKFLAGSNEW(BDS, DB2, D7I)
2210 CHECKFLAGSNEW(BDS, SB2, S7I)
2211 CHECKFLAGSNEW(BDS, CB3, C6I)
2212 CHECKFLAGSNEW(BDS, LB3, L6I)
2213 CHECKFLAGSNEW(BDS, DB3, D6I)
2214 CHECKFLAGSNEW(BDS, SB3, S6I)
2215
2216 if(modified)
2217 {
2218 if(hdata)
2219 hdata->data.named.typesofobsC = buffer;
2220 i = 1+snprintf(buffer, buffersize,
2221 "C %3d%-52.52s SYS / # / OBS TYPES",
2222 Parser->info[RTCM3_MSM_BDS].numtypes, Parser->fieldbufferBDS);
2223 if(Parser->info[RTCM3_MSM_BDS].numtypes>13)
2224 {
2225 i += snprintf(buffer+i-1, buffersize,
2226 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferBDS+13*4);
2227 }
2228 buffer += i; buffersize -= i;
2229 }
2230
2231 INITFLAGS(QZSS)
2232
2233 CHECKFLAGSNEW(QZSS, C1, C1C)
2234 CHECKFLAGSNEW(QZSS, L1C, L1C)
2235 CHECKFLAGSNEW(QZSS, D1C, D1C)
2236 CHECKFLAGSNEW(QZSS, S1C, S1C)
2237
2238 CHECKFLAGSNEW(QZSS, CSAIF, C1Z)
2239 CHECKFLAGSNEW(QZSS, LSAIF, L1Z)
2240 CHECKFLAGSNEW(QZSS, DSAIF, D1Z)
2241 CHECKFLAGSNEW(QZSS, SSAIF, S1Z)
2242
2243 CHECKFLAGSNEW(QZSS, C1N, C1)
2244 CHECKFLAGSNEW(QZSS, L1N, L1)
2245 CHECKFLAGSNEW(QZSS, D1N, D1)
2246 CHECKFLAGSNEW(QZSS, S1N, S1)
2247
2248 CHECKFLAGSNEW(QZSS, C6, C6)
2249 CHECKFLAGSNEW(QZSS, L6, L6)
2250 CHECKFLAGSNEW(QZSS, D6, D6)
2251 CHECKFLAGSNEW(QZSS, S6, S6)
2252
2253 CHECKFLAGSNEW(QZSS, C2, C2)
2254 CHECKFLAGSNEW(QZSS, L2C, L2)
2255 CHECKFLAGSNEW(QZSS, D2C, D2)
2256 CHECKFLAGSNEW(QZSS, S2C, S2)
2257
2258 CHECKFLAGSNEW(QZSS, C5, C5)
2259 CHECKFLAGSNEW(QZSS, L5, L5)
2260 CHECKFLAGSNEW(QZSS, D5, D5)
2261 CHECKFLAGSNEW(QZSS, S5, S5)
2262
2263 if(modified)
2264 {
2265 if(hdata)
2266 hdata->data.named.typesofobsJ = buffer;
2267 i = 1+snprintf(buffer, buffersize,
2268 "J %3d%-52.52s SYS / # / OBS TYPES",
2269 Parser->info[RTCM3_MSM_QZSS].numtypes, Parser->fieldbufferQZSS);
2270 if(Parser->info[RTCM3_MSM_QZSS].numtypes>13)
2271 {
2272 i += snprintf(buffer+i-1, buffersize,
2273 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferQZSS+13*4);
2274 }
2275 buffer += i; buffersize -= i;
2276 }
2277 }
2278 else
2279 {
2280#define CHECKFLAGS(a, b) \
2281 if(flags & GNSSDF_##a##DATA) \
2282 { \
2283 if(Parser->datafields[RINEXENTRY_##b##DATA]) \
2284 { \
2285 Parser->info[RTCM3_MSM_GPS].flags[Parser->datafields[\
2286 RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
2287 Parser->info[RTCM3_MSM_GPS].pos[Parser->datafields[\
2288 RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
2289 } \
2290 else \
2291 { \
2292 Parser->flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##a##DATA; \
2293 Parser->pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##a##DATA; \
2294 Parser->datafields[RINEXENTRY_##b##DATA] = \
2295 ++Parser->info[RTCM3_MSM_GPS].numtypes; \
2296 snprintf(Parser->fieldbuffer+6*Parser->numdatafields, \
2297 sizeof(Parser->fieldbuffer)-6*Parser->numdatafields, " "#b); \
2298 ++Parser->numdatafields; \
2299 ++modified; \
2300 } \
2301 }
2302
2303 int flags = Parser->startflags;
2304 for(i = 0; i < Parser->Data.numsats; ++i)
2305 flags |= Parser->Data.dataflags[i];
2306
2307 CHECKFLAGS(C1,C1)
2308 CHECKFLAGS(C2,C2)
2309 CHECKFLAGS(P1,P1)
2310 CHECKFLAGS(P2,P2)
2311 CHECKFLAGS(L1C,L1)
2312 CHECKFLAGS(L1P,L1)
2313 CHECKFLAGS(L2C,L2)
2314 CHECKFLAGS(L2P,L2)
2315 CHECKFLAGS(D1C,D1)
2316 CHECKFLAGS(D1P,D1)
2317 CHECKFLAGS(D2C,D2)
2318 CHECKFLAGS(D2P,D2)
2319 CHECKFLAGS(S1C,S1)
2320 CHECKFLAGS(S1P,S1)
2321 CHECKFLAGS(S2C,S2)
2322 CHECKFLAGS(S2P,S2)
2323 CHECKFLAGS(C5,C5)
2324 CHECKFLAGS(L5,L5)
2325 CHECKFLAGS(D5,D5)
2326 CHECKFLAGS(S5,S5)
2327 CHECKFLAGS(C5AB,C8)
2328 CHECKFLAGS(L5AB,L8)
2329 CHECKFLAGS(D5AB,D8)
2330 CHECKFLAGS(S5AB,S8)
2331 CHECKFLAGS(C5B,C7)
2332 CHECKFLAGS(L5B,L7)
2333 CHECKFLAGS(D5B,D7)
2334 CHECKFLAGS(S5B,S7)
2335 CHECKFLAGS(C6,C6)
2336 CHECKFLAGS(L6,L6)
2337 CHECKFLAGS(D6,D6)
2338 CHECKFLAGS(S6,S6)
2339 /* Skip C1N and SAIF for RINEX2! */
2340
2341 if(hdata)
2342 hdata->data.named.typesofobs = buffer;
2343 if(modified)
2344 {
2345 i = 1+snprintf(buffer, buffersize,
2346 "%6d%-54.54s# / TYPES OF OBSERV", Parser->info[RTCM3_MSM_GPS].numtypes,
2347 Parser->fieldbuffer);
2348 if(Parser->info[RTCM3_MSM_GPS].numtypes>9)
2349 {
2350 i += snprintf(buffer+i-1, buffersize,
2351 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+9*6);
2352 }
2353 if(Parser->info[RTCM3_MSM_GPS].numtypes>18)
2354 {
2355 i += snprintf(buffer+i-1, buffersize,
2356 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+18*6);
2357 }
2358 buffer += i; buffersize -= i;
2359 }
2360 }
2361 return buffersizeold - buffersize;
2362}
2363
2364void HandleHeader(struct RTCM3ParserData *Parser)
2365{
2366#ifdef NO_RTCM3_MAIN
2367 int flags, modified = 0;
2368 if(Parser->allflags == 0)
2369 Parser->allflags = ~0;
2370 flags = Parser->allflags;
2371 if(Parser->rinex3)
2372 {
2373 struct HeaderData *hdata = 0;
2374 CHECKFLAGSNEW(GPS, C1, C1C)
2375 CHECKFLAGSNEW(GPS, L1C, L1C)
2376 CHECKFLAGSNEW(GPS, D1C, D1C)
2377 CHECKFLAGSNEW(GPS, S1C, S1C)
2378 CHECKFLAGSNEW(GPS, P1, C1P)
2379 CHECKFLAGSNEW(GPS, L1P, L1P)
2380 CHECKFLAGSNEW(GPS, D1P, D1P)
2381 CHECKFLAGSNEW(GPS, S1P, S1P)
2382 CHECKFLAGSNEW(GPS, P2, C2P)
2383 CHECKFLAGSNEW(GPS, L2P, L2P)
2384 CHECKFLAGSNEW(GPS, D2P, D2P)
2385 CHECKFLAGSNEW(GPS, S2P, S2P)
2386 CHECKFLAGSNEW(GPS, C2, C2X)
2387 CHECKFLAGSNEW(GPS, L2C, L2X)
2388 CHECKFLAGSNEW(GPS, D2C, D2X)
2389 CHECKFLAGSNEW(GPS, S2C, S2X)
2390 CHECKFLAGSNEW(GLONASS, C1, C1C)
2391 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2392 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2393 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2394 CHECKFLAGSNEW(GLONASS, P1, C1P)
2395 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2396 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2397 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2398 CHECKFLAGSNEW(GLONASS, P2, C2P)
2399 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2400 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2401 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2402 CHECKFLAGSNEW(GLONASS, C2, C2C)
2403 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2404 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2405 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2406 }
2407 else
2408 {
2409 CHECKFLAGS(C1,C1)
2410 CHECKFLAGS(C2,C2)
2411 CHECKFLAGS(P1,P1)
2412 CHECKFLAGS(P2,P2)
2413 CHECKFLAGS(L1C,L1)
2414 CHECKFLAGS(L1P,L1)
2415 CHECKFLAGS(L2C,L2)
2416 CHECKFLAGS(L2P,L2)
2417 CHECKFLAGS(D1C,D1)
2418 CHECKFLAGS(D1P,D1)
2419 CHECKFLAGS(D2C,D2)
2420 CHECKFLAGS(D2P,D2)
2421 CHECKFLAGS(S1C,S1)
2422 CHECKFLAGS(S1P,S1)
2423 CHECKFLAGS(S2C,S2)
2424 CHECKFLAGS(S2P,S2)
2425 CHECKFLAGS(C5,C5)
2426 CHECKFLAGS(L5,L5)
2427 CHECKFLAGS(D5,D5)
2428 CHECKFLAGS(S5,S5)
2429 CHECKFLAGS(C5AB,C8)
2430 CHECKFLAGS(L5AB,L8)
2431 CHECKFLAGS(D5AB,D8)
2432 CHECKFLAGS(S5AB,S8)
2433 CHECKFLAGS(C5B,C7)
2434 CHECKFLAGS(L5B,L7)
2435 CHECKFLAGS(D5B,D7)
2436 CHECKFLAGS(S5B,S7)
2437 CHECKFLAGS(C6,C6)
2438 CHECKFLAGS(L6,L6)
2439 CHECKFLAGS(D6,D6)
2440 CHECKFLAGS(S6,S6)
2441 }
2442#else /* NO_RTCM3_MAIN */
2443 struct HeaderData hdata;
2444 char thebuffer[MAXHEADERBUFFERSIZE];
2445 char *buffer = thebuffer;
2446 size_t buffersize = sizeof(thebuffer);
2447 int i;
2448
2449 memset(&hdata, 0, sizeof(hdata));
2450
2451 hdata.data.named.version = buffer;
2452 i = 1+snprintf(buffer, buffersize,
2453 "%9.2f OBSERVATION DATA M (Mixed)"
2454 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
2455 buffer += i; buffersize -= i;
2456
2457 {
2458 const char *str;
2459 hdata.data.named.pgm = buffer;
2460 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
2461 buffer += i; buffersize -= i;
2462 hdata.data.named.observer = buffer;
2463 i = 1+snprintf(buffer, buffersize,
2464 "%-20.20s "
2465 "OBSERVER / AGENCY", str);
2466 buffer += i; buffersize -= i;
2467 }
2468
2469 hdata.data.named.marker =
2470 "RTCM3TORINEX "
2471 "MARKER NAME";
2472
2473 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
2474 "GEODETIC "
2475 "MARKER TYPE";
2476
2477 hdata.data.named.receiver =
2478 " "
2479 "REC # / TYPE / VERS";
2480
2481 hdata.data.named.antenna =
2482 " "
2483 "ANT # / TYPE";
2484
2485 hdata.data.named.position =
2486 " .0000 .0000 .0000 "
2487 "APPROX POSITION XYZ";
2488
2489 hdata.data.named.antennaposition =
2490 " .0000 .0000 .0000 "
2491 "ANTENNA: DELTA H/E/N";
2492
2493 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
2494 " 1 1 "
2495 "WAVELENGTH FACT L1/2";
2496
2497 hdata.numheaders = 18;
2498
2499 i = HandleObsHeader(Parser, buffer, buffersize, &hdata);
2500 buffer += i; buffersize -= i;
2501
2502 {
2503 struct converttimeinfo cti;
2504 converttime(&cti, Parser->Data.week,
2505 (int)floor(Parser->Data.timeofweek/1000.0));
2506 hdata.data.named.timeoffirstobs = buffer;
2507 i = 1+snprintf(buffer, buffersize,
2508 " %4d %2d %2d %2d %2d %10.7f GPS "
2509 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
2510 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
2511
2512 buffer += i; buffersize -= i;
2513 }
2514
2515 if(Parser->headerfile)
2516 {
2517 FILE *fh;
2518 if((fh = fopen(Parser->headerfile, "r")))
2519 {
2520 size_t siz;
2521 char *lastblockstart;
2522 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
2523 {
2524 buffer[siz] = '\n';
2525 if(siz == buffersize)
2526 {
2527 RTCM3Error("Header file is too large. Only %d bytes read.",
2528 (int)siz);
2529 }
2530 /* scan the file line by line and enter the entries in the list */
2531 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
2532 /* overwrites entries, except for comments */
2533 lastblockstart = buffer;
2534 for(i = 0; i < (int)siz; ++i)
2535 {
2536 if(buffer[i] == '\n')
2537 { /* we found a line */
2538 char *end;
2539 while(buffer[i+1] == '\r')
2540 ++i; /* skip \r in case there are any */
2541 end = buffer+i;
2542 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2543 *(end--) = 0;
2544 if(end-lastblockstart < 60+5) /* short line */
2545 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2546 else
2547 {
2548 int pos;
2549 if(!strcmp("COMMENT", lastblockstart+60))
2550 pos = hdata.numheaders;
2551 else
2552 {
2553 for(pos = 0; pos < hdata.numheaders; ++pos)
2554 {
2555 if(hdata.data.unnamed[pos] &&
2556 !strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2557 break;
2558 }
2559 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2560 || !strcmp("SYS / # / OBS TYPES", lastblockstart+60)
2561 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2562 {
2563 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2564 lastblockstart+60);
2565 }
2566 }
2567 if(pos >= MAXHEADERLINES)
2568 {
2569 RTCM3Error("Maximum number of header lines of %d reached.\n",
2570 MAXHEADERLINES);
2571 }
2572 else if(!strcmp("END OF HEADER", lastblockstart+60))
2573 {
2574 RTCM3Error("End of header ignored.\n");
2575 }
2576 else
2577 {
2578 hdata.data.unnamed[pos] = lastblockstart;
2579 if(pos == hdata.numheaders)
2580 ++hdata.numheaders;
2581 }
2582 }
2583 lastblockstart = buffer+i+1;
2584 }
2585 }
2586 }
2587 else
2588 {
2589 RTCM3Error("Could not read data from headerfile '%s'.\n",
2590 Parser->headerfile);
2591 }
2592 fclose(fh);
2593 }
2594 else
2595 {
2596 RTCM3Error("Could not open header datafile '%s'.\n",
2597 Parser->headerfile);
2598 }
2599 }
2600
2601 for(i = 0; i < hdata.numheaders; ++i)
2602 {
2603 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2604 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2605 }
2606 RTCM3Text(" "
2607 "END OF HEADER\n");
2608#endif
2609}
2610
2611static void ConvLine(FILE *file, const char *fmt, ...)
2612{
2613 char buffer[100], *b;
2614 va_list v;
2615 va_start(v, fmt);
2616 vsnprintf(buffer, sizeof(buffer), fmt, v);
2617 for(b = buffer; *b; ++b)
2618 {
2619 if(*b == 'e') *b = 'D';
2620 }
2621 fprintf(file, "%s", buffer);
2622 va_end(v);
2623}
2624
2625void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2626{
2627 Parser->Message[Parser->MessageSize++] = byte;
2628 if(Parser->MessageSize >= Parser->NeedBytes)
2629 {
2630 int r;
2631 while((r = RTCM3Parser(Parser)))
2632 {
2633 double ver = Parser->rinex3 ? 3.02 : 2.11;
2634 if(r == 1020 || r == RTCM3ID_BDS || r == 1019 || r == 1044 || r == 1043)
2635 {
2636 FILE *file = 0;
2637
2638 if(Parser->mixedephemeris)
2639 {
2640 if(Parser->mixedephemeris != (const char *)1)
2641 {
2642 if(!(Parser->mixedfile = fopen(Parser->mixedephemeris, "w")))
2643 {
2644 RTCM3Error("Could not open ephemeris output file.\n");
2645 }
2646 else
2647 {
2648 char buffer[100];
2649 fprintf(Parser->mixedfile,
2650 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", ver, "", "");
2651 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2652 fprintf(Parser->mixedfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2653 }
2654 Parser->mixedephemeris = (const char *)1;
2655 }
2656 file = Parser->mixedfile;
2657 }
2658 else
2659 {
2660 if(r == 1020)
2661 {
2662 if(Parser->glonassephemeris)
2663 {
2664 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2665 {
2666 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2667 }
2668 else
2669 {
2670 char buffer[100];
2671 fprintf(Parser->glonassfile,
2672 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", ver, "", "");
2673 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2674 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2675 }
2676 Parser->glonassephemeris = 0;
2677 }
2678 file = Parser->glonassfile;
2679 }
2680 else if(r == 1019)
2681 {
2682 if(Parser->gpsephemeris)
2683 {
2684 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2685 {
2686 RTCM3Error("Could not open GPS ephemeris output file.\n");
2687 }
2688 else
2689 {
2690 char buffer[100];
2691 fprintf(Parser->gpsfile,
2692 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", ver, "", "");
2693 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2694 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2695 }
2696 Parser->gpsephemeris = 0;
2697 }
2698 file = Parser->gpsfile;
2699 }
2700 else if(r == 1043)
2701 {
2702 if(Parser->sbasephemeris)
2703 {
2704 if(!(Parser->sbasfile = fopen(Parser->sbasephemeris, "w")))
2705 {
2706 RTCM3Error("Could not open SBAS ephemeris output file.\n");
2707 }
2708 else
2709 {
2710 char buffer[100];
2711 fprintf(Parser->sbasfile,
2712 "%9.2f%11sN: SBAS NAV DATA%24sRINEX VERSION / TYPE\n", ver, "", "");
2713 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2714 fprintf(Parser->sbasfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2715 }
2716 Parser->sbasephemeris = 0;
2717 }
2718 file = Parser->sbasfile;
2719 }
2720 else if(r == 1044)
2721 {
2722 if(Parser->qzssephemeris)
2723 {
2724 if(!(Parser->qzssfile = fopen(Parser->qzssephemeris, "w")))
2725 {
2726 RTCM3Error("Could not open QZSS ephemeris output file.\n");
2727 }
2728 else
2729 {
2730 char buffer[100];
2731 fprintf(Parser->qzssfile,
2732 "%9.2f%11sN: QZSS NAV DATA%24sRINEX VERSION / TYPE\n", ver, "", "");
2733 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2734 fprintf(Parser->qzssfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2735 }
2736 Parser->qzssephemeris = 0;
2737 }
2738 file = Parser->qzssfile;
2739 }
2740 else if(r == RTCM3ID_BDS)
2741 {
2742 if(Parser->bdsephemeris)
2743 {
2744 if(!(Parser->bdsfile = fopen(Parser->bdsephemeris, "w")))
2745 {
2746 RTCM3Error("Could not open BDS ephemeris output file.\n");
2747 }
2748 else
2749 {
2750 char buffer[100];
2751 fprintf(Parser->bdsfile,
2752 "%9.2f%11sN: BDS NAV DATA%25sRINEX VERSION / TYPE\n", ver, "", "");
2753 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2754 fprintf(Parser->bdsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2755 }
2756 Parser->bdsephemeris = 0;
2757 }
2758 file = Parser->bdsfile;
2759 }
2760 }
2761 if(file)
2762 {
2763 const char *sep = " ";
2764 if(r == 1020)
2765 {
2766 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2767 int w = e->GPSWeek, tow = e->GPSTOW, i;
2768 struct converttimeinfo cti;
2769
2770 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2771 converttime(&cti, w, tow);
2772
2773 i = e->tk-3*60*60; if(i < 0) i += 86400;
2774
2775 if(Parser->rinex3)
2776 {
2777 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2778 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2779 cti.second, -e->tau, e->gamma, (double) i);
2780 sep = " ";
2781 }
2782 else
2783 {
2784 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2785 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2786 (double) cti.second, -e->tau, e->gamma, (double) i);
2787 }
2788 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2789 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2790 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2791 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2792 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2793 e->z_velocity, e->z_acceleration, (double) e->E);
2794 }
2795 else if(r == 1043)
2796 {
2797 struct sbasephemeris *e = &Parser->ephemerisSBAS;
2798 struct converttimeinfo cti;
2799 converttime(&cti, e->GPSweek_TOE, e->TOE);
2800 if(Parser->rinex3)
2801 {
2802 ConvLine(file, "S%02d %04d %2d %2d %2d %2d %2d%19.12e%19.12e%19.12e\n",
2803 e->satellite-100, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2804 cti.second, e->agf0, e->agf1, (double)e->TOW);
2805 sep = " ";
2806 }
2807 else
2808 {
2809 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2810 e->satellite-100, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2811 (double)cti.second, e->agf0, e->agf1, (double)e->TOW);
2812 }
2813 /* X, health */
2814 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2815 e->x_velocity, e->x_acceleration, e->URA == 15 ? 1.0 : 0.0);
2816 /* Y, accuracy */
2817 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2818 e->y_velocity, e->y_acceleration, (double)e->URA);
2819 /* Z */
2820 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2821 e->z_velocity, e->z_acceleration, (double)e->IODN);
2822 }
2823 else if(r == RTCM3ID_BDS)
2824 {
2825 struct bdsephemeris *e = &Parser->ephemerisBDS;
2826 double d; /* temporary variable */
2827 struct converttimeinfo cti;
2828 converttimebds(&cti, e->BDSweek, e->TOC);
2829 int num = e->satellite-PRN_BDS_START+1;
2830
2831 if(Parser->rinex3)
2832 {
2833 ConvLine(file,
2834 "C%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2835 num, cti.year, cti.month, cti.day, cti.hour,
2836 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2837 e->clock_driftrate);
2838 sep = " ";
2839 }
2840 else /* actually this is never used, as BDS is undefined for 2.x */
2841 {
2842 ConvLine(file,
2843 "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2844 num, cti.year%100, cti.month, cti.day, cti.hour,
2845 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2846 e->clock_driftrate);
2847 }
2848 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2849 (double)e->AODE, e->Crs, e->Delta_n, e->M0);
2850 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->Cuc,
2851 e->e, e->Cus, e->sqrt_A);
2852 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2853 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2854 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->i0,
2855 e->Crc, e->omega, e->OMEGADOT);
2856 ConvLine(file, "%s%19.12e %19.12e\n", sep, e->IDOT,
2857 (double) e->BDSweek);
2858 if(e->URAI <= 6) /* URA index */
2859 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAI)/2.0))/10.0;
2860 else
2861 d = ceil(10.0*pow(2.0, ((double)e->URAI)/2.0))/10.0;
2862 /* 15 indicates not to use satellite. We can't handle this special
2863 case, so we create a high "non"-accuracy value. */
2864 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, d,
2865 ((double) (e->flags & BDSEPHF_SATH1)), e->TGD_B1_B3,
2866 e->TGD_B2_B3);
2867
2868 ConvLine(file, "%s%19.12e%19.12e\n", sep, ((double)e->TOW),
2869 (double) e->AODC);
2870 /* TOW, AODC */
2871 }
2872 else /* if(r == 1019 || r == 1044) */
2873 {
2874 struct gpsephemeris *e = &Parser->ephemerisGPS;
2875 double d; /* temporary variable */
2876 unsigned long int i; /* temporary variable */
2877 struct converttimeinfo cti;
2878 converttime(&cti, e->GPSweek, e->TOC);
2879 int qzss = 0;
2880 int num = e->satellite;
2881
2882 if(num >= PRN_QZSS_START)
2883 {
2884 qzss = 1;
2885 num -= PRN_QZSS_START-1;
2886 }
2887 if(Parser->rinex3)
2888 {
2889 ConvLine(file,
2890 "%s%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2891 qzss ? "J" : "G", num, cti.year, cti.month, cti.day, cti.hour,
2892 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2893 e->clock_driftrate);
2894 sep = " ";
2895 }
2896 else
2897 {
2898 ConvLine(file,
2899 "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2900 num, cti.year%100, cti.month, cti.day, cti.hour,
2901 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2902 e->clock_driftrate);
2903 }
2904 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2905 (double)e->IODE, e->Crs, e->Delta_n, e->M0);
2906 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->Cuc,
2907 e->e, e->Cus, e->sqrt_A);
2908 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2909 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2910 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->i0,
2911 e->Crc, e->omega, e->OMEGADOT);
2912 d = 0;
2913 i = e->flags;
2914 if(i & GPSEPHF_L2CACODE)
2915 d += 2.0;
2916 if(i & GPSEPHF_L2PCODE)
2917 d += 1.0;
2918 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->IDOT, d,
2919 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2920 if(e->URAindex <= 6) /* URA index */
2921 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2922 else
2923 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2924 /* 15 indicates not to use satellite. We can't handle this special
2925 case, so we create a high "non"-accuracy value. */
2926 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, d,
2927 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2928
2929 ConvLine(file, "%s%19.12e%19.12e\n", sep, ((double)e->TOW),
2930 (i & GPSEPHF_6HOURSFIT) ? (Parser->rinex3 ? 1 : qzss ? 4.0 : 6.0)
2931 : (Parser->rinex3 ? 0 : qzss ? 2.0 : 4.0));
2932 /* TOW,Fit */
2933 }
2934 }
2935 }
2936 else if (r == 1 || r == 2)
2937 {
2938 int i, j, o, nh=0, hl=2;
2939 char newheader[512];
2940 struct converttimeinfo cti;
2941
2942 /* skip first epochs to detect correct data types */
2943 if(Parser->init < (Parser->changeobs ? 1 : NUMSTARTSKIP))
2944 {
2945 ++Parser->init;
2946
2947 if(Parser->init == (Parser->changeobs ? 1 : NUMSTARTSKIP))
2948 HandleHeader(Parser);
2949 else
2950 {
2951 for(i = 0; i < Parser->Data.numsats; ++i)
2952 Parser->startflags |= Parser->Data.dataflags[i];
2953 continue;
2954 }
2955 }
2956 if(r == 2 && !Parser->validwarning)
2957 {
2958 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2959 " COMMENT\n");
2960 Parser->validwarning = 1;
2961 }
2962
2963 converttime(&cti, Parser->Data.week,
2964 (int)floor(Parser->Data.timeofweek/1000.0));
2965 newheader[0] = 0;
2966 if(Parser->changeobs)
2967 {
2968 nh = HandleObsHeader(Parser, newheader, sizeof(newheader), 0);
2969 for(i = 0; i < nh; ++i)
2970 {
2971 if(newheader[i] == '\n')
2972 ++hl;
2973 }
2974 }
2975 if(Parser->rinex3)
2976 {
2977 if(nh)
2978 {
2979 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 4%3d\n",
2980 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2981 + fmod(Parser->Data.timeofweek/1000.0,1.0), hl);
2982 RTCM3Text("%s\n "
2983 " END OF HEADER\n", newheader);
2984 }
2985 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f %d%3d\n",
2986 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2987 + fmod(Parser->Data.timeofweek/1000.0,1.0), 0,
2988 Parser->Data.numsats);
2989 for(i = 0; i < Parser->Data.numsats; ++i)
2990 {
2991 int sys[RTCM3_MSM_NUMSYS] = {0,0,0,0,0,0};
2992 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2993 {
2994 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2995 sys[RTCM3_MSM_GPS] = 1;
2996 }
2997 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2998 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2999 {
3000 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
3001 sys[RTCM3_MSM_GLONASS] = 1;
3002 }
3003 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3004 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3005 {
3006 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
3007 sys[RTCM3_MSM_GALILEO] = 1;
3008 }
3009 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3010 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3011 {
3012 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3013 sys[RTCM3_MSM_GALILEO] = 1;
3014 }
3015 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3016 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3017 {
3018 RTCM3Text("J%02d", Parser->Data.satellites[i] - (PRN_QZSS_START-1));
3019 sys[RTCM3_MSM_QZSS] = 1;
3020 }
3021 else if(Parser->Data.satellites[i] >= PRN_BDS_START
3022 && Parser->Data.satellites[i] <= PRN_BDS_END)
3023 {
3024 RTCM3Text("C%02d", Parser->Data.satellites[i] - (PRN_BDS_START-1));
3025 sys[RTCM3_MSM_BDS] = 1;
3026 }
3027 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3028 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3029 {
3030 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_SBAS_START+20);
3031 sys[RTCM3_MSM_SBAS] = 1;
3032 }
3033 else
3034 {
3035 RTCM3Text("%3d", Parser->Data.satellites[i]);
3036 }
3037
3038 if(sys[RTCM3_MSM_GLONASS])
3039 {
3040 for(j = 0; j < Parser->info[RTCM3_MSM_GLONASS].numtypes; ++j)
3041 {
3042 long long df = Parser->info[RTCM3_MSM_GLONASS].flags[j];
3043 int pos = Parser->info[RTCM3_MSM_GLONASS].pos[j];
3044 if((Parser->Data.dataflags[i] & df)
3045 && !isnan(Parser->Data.measdata[i][pos])
3046 && !isinf(Parser->Data.measdata[i][pos])
3047 && (Parser->Data.codetype[i][pos]
3048 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
3049 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
3050 == Parser->Data.codetype[i][pos][1]))
3051 {
3052 char lli = ' ';
3053 char snr = ' ';
3054 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3055 {
3056 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3057 lli = '1';
3058 snr = '0'+Parser->Data.snrL1[i];
3059 }
3060 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3061 {
3062 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3063 lli = '1';
3064 snr = '0'+Parser->Data.snrL2[i];
3065 }
3066 RTCM3Text("%14.3f%c%c",
3067 Parser->Data.measdata[i][pos],lli,snr);
3068 }
3069 else
3070 { /* no or illegal data */
3071 RTCM3Text(" ");
3072 }
3073 }
3074 }
3075 else if(sys[RTCM3_MSM_GALILEO])
3076 {
3077 for(j = 0; j < Parser->info[RTCM3_MSM_GALILEO].numtypes; ++j)
3078 {
3079 long long df = Parser->info[RTCM3_MSM_GALILEO].flags[j];
3080 int pos = Parser->info[RTCM3_MSM_GALILEO].pos[j];
3081 if((Parser->Data.dataflags[i] & df)
3082 && !isnan(Parser->Data.measdata[i][pos])
3083 && !isinf(Parser->Data.measdata[i][pos])
3084 && (Parser->Data.codetype[i][pos]
3085 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
3086 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
3087 == Parser->Data.codetype[i][pos][1]))
3088 {
3089 char lli = ' ';
3090 char snr = ' ';
3091 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3092 {
3093 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3094 lli = '1';
3095 snr = '0'+Parser->Data.snrL1[i];
3096 }
3097 if(df & GNSSDF_L6DATA)
3098 {
3099 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
3100 lli = '1';
3101 snr = ' ';
3102 }
3103 if(df & GNSSDF_L5DATA)
3104 {
3105 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3106 lli = '1';
3107 snr = ' ';
3108 }
3109 if(df & GNSSDF_L5BDATA)
3110 {
3111 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
3112 lli = '1';
3113 snr = ' ';
3114 }
3115 if(df & GNSSDF_L5ABDATA)
3116 {
3117 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
3118 lli = '1';
3119 snr = ' ';
3120 }
3121 RTCM3Text("%14.3f%c%c",
3122 Parser->Data.measdata[i][pos],lli,snr);
3123 }
3124 else
3125 { /* no or illegal data */
3126 RTCM3Text(" ");
3127 }
3128 }
3129 }
3130 else if(sys[RTCM3_MSM_BDS])
3131 {
3132 for(j = 0; j < Parser->info[RTCM3_MSM_BDS].numtypes; ++j)
3133 {
3134 long long df = Parser->info[RTCM3_MSM_BDS].flags[j];
3135 int pos = Parser->info[RTCM3_MSM_BDS].pos[j];
3136 if((Parser->Data.dataflags[i] & df)
3137 && !isnan(Parser->Data.measdata[i][pos])
3138 && !isinf(Parser->Data.measdata[i][pos])
3139 && (Parser->Data.codetype[i][pos]
3140 && Parser->info[RTCM3_MSM_BDS].type[pos]
3141 && Parser->info[RTCM3_MSM_BDS].type[pos]
3142 == Parser->Data.codetype[i][pos][1]))
3143 {
3144 char lli = ' ';
3145 char snr = ' ';
3146 if(df & GNSSDF_LB1DATA)
3147 {
3148 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB1)
3149 lli = '1';
3150 }
3151 if(df & GNSSDF_LB2DATA)
3152 {
3153 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB2)
3154 lli = '1';
3155 }
3156 if(df & GNSSDF_LB3DATA)
3157 {
3158 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB3)
3159 lli = '1';
3160 }
3161 RTCM3Text("%14.3f%c%c",
3162 Parser->Data.measdata[i][pos],lli,snr);
3163 }
3164 else
3165 { /* no or illegal data */
3166 RTCM3Text(" ");
3167 }
3168 }
3169 }
3170 else if(sys[RTCM3_MSM_QZSS])
3171 {
3172 for(j = 0; j < Parser->info[RTCM3_MSM_QZSS].numtypes; ++j)
3173 {
3174 long long df = Parser->info[RTCM3_MSM_QZSS].flags[j];
3175 int pos = Parser->info[RTCM3_MSM_QZSS].pos[j];
3176 if((Parser->Data.dataflags[i] & df)
3177 && !isnan(Parser->Data.measdata[i][pos])
3178 && !isinf(Parser->Data.measdata[i][pos])
3179 && (Parser->Data.codetype[i][pos]
3180 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3181 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3182 == Parser->Data.codetype[i][pos][1]))
3183 {
3184 char lli = ' ';
3185 char snr = ' ';
3186 if(df & GNSSDF_L1CDATA)
3187 {
3188 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3189 lli = '1';
3190 snr = '0'+Parser->Data.snrL1[i];
3191 }
3192 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3193 {
3194 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3195 lli = '1';
3196 snr = '0'+Parser->Data.snrL2[i];
3197 }
3198 if(df & GNSSDF_L5DATA)
3199 {
3200 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3201 lli = '1';
3202 snr = ' ';
3203 }
3204 RTCM3Text("%14.3f%c%c",
3205 Parser->Data.measdata[i][pos],lli,snr);
3206 }
3207 else
3208 { /* no or illegal data */
3209 RTCM3Text(" ");
3210 }
3211 }
3212 }
3213 else if(sys[RTCM3_MSM_SBAS])
3214 {
3215 for(j = 0; j < Parser->info[RTCM3_MSM_SBAS].numtypes; ++j)
3216 {
3217 long long df = Parser->info[RTCM3_MSM_SBAS].flags[j];
3218 int pos = Parser->info[RTCM3_MSM_SBAS].pos[j];
3219 if((Parser->Data.dataflags[i] & df)
3220 && !isnan(Parser->Data.measdata[i][pos])
3221 && !isinf(Parser->Data.measdata[i][pos])
3222 && (Parser->Data.codetype[i][pos]
3223 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3224 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3225 == Parser->Data.codetype[i][pos][1]))
3226 {
3227 char lli = ' ';
3228 char snr = ' ';
3229 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3230 {
3231 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3232 lli = '1';
3233 snr = '0'+Parser->Data.snrL1[i];
3234 }
3235 if(df & GNSSDF_L5DATA)
3236 {
3237 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3238 lli = '1';
3239 snr = ' ';
3240 }
3241 RTCM3Text("%14.3f%c%c",
3242 Parser->Data.measdata[i][pos],lli,snr);
3243 }
3244 else
3245 { /* no or illegal data */
3246 RTCM3Text(" ");
3247 }
3248 }
3249 }
3250 else
3251 {
3252 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3253 {
3254 long long df = Parser->info[RTCM3_MSM_GPS].flags[j];
3255 int pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3256 if((Parser->Data.dataflags[i] & df)
3257 && !isnan(Parser->Data.measdata[i][pos])
3258 && !isinf(Parser->Data.measdata[i][pos])
3259 && (Parser->Data.codetype[i][pos]
3260 && Parser->info[RTCM3_MSM_GPS].type[pos]
3261 && Parser->info[RTCM3_MSM_GPS].type[pos]
3262 == Parser->Data.codetype[i][pos][1]))
3263 {
3264 char lli = ' ';
3265 char snr = ' ';
3266 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3267 {
3268 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3269 lli = '1';
3270 snr = '0'+Parser->Data.snrL1[i];
3271 }
3272 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3273 {
3274 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3275 lli = '1';
3276 snr = '0'+Parser->Data.snrL2[i];
3277 }
3278 if(df & GNSSDF_L5DATA)
3279 {
3280 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3281 lli = '1';
3282 snr = ' ';
3283 }
3284 RTCM3Text("%14.3f%c%c",
3285 Parser->Data.measdata[i][pos],lli,snr);
3286 }
3287 else
3288 { /* no or illegal data */
3289 RTCM3Text(" ");
3290 }
3291 }
3292 }
3293 RTCM3Text("\n");
3294 }
3295 }
3296 else
3297 {
3298 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f %d%3d",
3299 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
3300 + fmod(Parser->Data.timeofweek/1000.0,1.0), nh ? 4 : 0,
3301 Parser->Data.numsats);
3302 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
3303 {
3304 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3305 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3306 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3307 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3308 RTCM3Text("R%02d", Parser->Data.satellites[i]
3309 - (PRN_GLONASS_START-1));
3310 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3311 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3312 RTCM3Text("S%02d", Parser->Data.satellites[i]
3313 - PRN_SBAS_START+20);
3314 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3315 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3316 RTCM3Text("E%02d", Parser->Data.satellites[i]
3317 - (PRN_GALILEO_START-1));
3318 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3319 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3320 RTCM3Text("E%02d", Parser->Data.satellites[i]
3321 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3322 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3323 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3324 RTCM3Text("J%02d", Parser->Data.satellites[i]
3325 - (PRN_QZSS_START-1));
3326 else if(Parser->Data.satellites[i] >= PRN_BDS_START
3327 && Parser->Data.satellites[i] <= PRN_BDS_END)
3328 RTCM3Text("C%02d", Parser->Data.satellites[i]
3329 - (PRN_BDS_START-1));
3330 else
3331 RTCM3Text("%3d", Parser->Data.satellites[i]);
3332 }
3333 RTCM3Text("\n");
3334 o = 12;
3335 j = Parser->Data.numsats - 12;
3336 while(j > 0)
3337 {
3338 RTCM3Text(" ");
3339 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
3340 {
3341 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3342 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3343 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3344 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3345 RTCM3Text("R%02d", Parser->Data.satellites[i]
3346 - (PRN_GLONASS_START-1));
3347 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3348 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3349 RTCM3Text("S%02d", Parser->Data.satellites[i]
3350 - PRN_SBAS_START+20);
3351 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3352 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3353 RTCM3Text("E%02d", Parser->Data.satellites[i]
3354 - (PRN_GALILEO_START-1));
3355 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3356 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3357 RTCM3Text("E%02d", Parser->Data.satellites[i]
3358 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3359 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3360 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3361 RTCM3Text("J%02d", Parser->Data.satellites[i]
3362 - (PRN_QZSS_START-1));
3363 else if(Parser->Data.satellites[i] >= PRN_BDS_START
3364 && Parser->Data.satellites[i] <= PRN_BDS_END)
3365 RTCM3Text("C%02d", Parser->Data.satellites[i]
3366 - (PRN_BDS_START-1));
3367 else
3368 RTCM3Text("%3d", Parser->Data.satellites[i]);
3369 }
3370 RTCM3Text("\n");
3371 j -= 12;
3372 o += 12;
3373 }
3374 if(nh)
3375 {
3376 RTCM3Text("%s\n "
3377 " END OF HEADER\n", newheader);
3378 }
3379 for(i = 0; i < Parser->Data.numsats; ++i)
3380 {
3381 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3382 {
3383 int v = 0;
3384 long long df = Parser->flags[j];
3385 int pos = Parser->pos[j];
3386 if((Parser->Data.dataflags[i] & df)
3387 && !isnan(Parser->Data.measdata[i][pos])
3388 && !isinf(Parser->Data.measdata[i][pos]))
3389 {
3390 v = 1;
3391 }
3392 else
3393 {
3394 df = Parser->info[RTCM3_MSM_GPS].flags[j];
3395 pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3396
3397 if((Parser->Data.dataflags[i] & df)
3398 && !isnan(Parser->Data.measdata[i][pos])
3399 && !isinf(Parser->Data.measdata[i][pos]))
3400 {
3401 v = 1;
3402 }
3403 }
3404
3405 if(!v)
3406 { /* no or illegal data */
3407 RTCM3Text(" ");
3408 }
3409 else
3410 {
3411 char lli = ' ';
3412 char snr = ' ';
3413 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3414 {
3415 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3416 lli = '1';
3417 snr = '0'+Parser->Data.snrL1[i];
3418 }
3419 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3420 {
3421 if(Parser->Data.dataflags2[i]
3422 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
3423 {
3424 lli = '0';
3425 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3426 lli += 1;
3427 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
3428 lli += 4;
3429 }
3430 snr = '0'+Parser->Data.snrL2[i];
3431 }
3432 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
3433 & GNSSDF2_XCORRL2))
3434 lli = '4';
3435 RTCM3Text("%14.3f%c%c",
3436 Parser->Data.measdata[i][pos],lli,snr);
3437 }
3438 if(j%5 == 4 || j == Parser->info[RTCM3_MSM_GPS].numtypes-1)
3439 RTCM3Text("\n");
3440 }
3441 }
3442 }
3443 }
3444 }
3445 }
3446}
3447
3448#ifndef NO_RTCM3_MAIN
3449static char datestr[] = "$Date: 2015-03-03 16:11:26 +0000 (Tue, 03 Mar 2015) $";
3450
3451/* The string, which is send as agent in HTTP request */
3452#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
3453
3454#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
3455
3456static const char encodingTable [64] = {
3457 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
3458 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
3459 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
3460 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
3461};
3462
3463/* does not buffer overrun, but breaks directly after an error */
3464/* returns the number of required bytes */
3465static int encode(char *buf, int size, const char *user, const char *pwd)
3466{
3467 unsigned char inbuf[3];
3468 char *out = buf;
3469 int i, sep = 0, fill = 0, bytes = 0;
3470
3471 while(*user || *pwd)
3472 {
3473 i = 0;
3474 while(i < 3 && *user) inbuf[i++] = *(user++);
3475 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
3476 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
3477 while(i < 3) {inbuf[i++] = 0; ++fill; }
3478 if(out-buf < size-1)
3479 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
3480 if(out-buf < size-1)
3481 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
3482 | ((inbuf [1] & 0xF0) >> 4)];
3483 if(out-buf < size-1)
3484 {
3485 if(fill == 2)
3486 *(out++) = '=';
3487 else
3488 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
3489 | ((inbuf [2] & 0xC0) >> 6)];
3490 }
3491 if(out-buf < size-1)
3492 {
3493 if(fill >= 1)
3494 *(out++) = '=';
3495 else
3496 *(out++) = encodingTable[inbuf [2] & 0x3F];
3497 }
3498 bytes += 4;
3499 }
3500 if(out-buf < size)
3501 *out = 0;
3502 return bytes;
3503}
3504
3505static int stop = 0;
3506
3507struct Args
3508{
3509 const char *server;
3510 const char *port;
3511 int mode;
3512 int timeout;
3513 int rinex3;
3514 int changeobs;
3515 const char *user;
3516 const char *password;
3517 const char *proxyhost;
3518 const char *proxyport;
3519 const char *nmea;
3520 const char *data;
3521 const char *headerfile;
3522 const char *sbasephemeris;
3523 const char *gpsephemeris;
3524 const char *qzssephemeris;
3525 const char *glonassephemeris;
3526 const char *bdsephemeris;
3527 const char *mixedephemeris;
3528};
3529
3530/* option parsing */
3531#ifdef NO_LONG_OPTS
3532#define LONG_OPT(a)
3533#else
3534#define LONG_OPT(a) a
3535static struct option opts[] = {
3536{ "data", required_argument, 0, 'd'},
3537{ "server", required_argument, 0, 's'},
3538{ "password", required_argument, 0, 'p'},
3539{ "port", required_argument, 0, 'r'},
3540{ "timeout", required_argument, 0, 't'},
3541{ "header", required_argument, 0, 'f'},
3542{ "user", required_argument, 0, 'u'},
3543{ "bdsephemeris", required_argument, 0, 'C'},
3544{ "gpsephemeris", required_argument, 0, 'E'},
3545{ "qzssephemeris", required_argument, 0, 'Q'},
3546{ "glonassephemeris", required_argument, 0, 'G'},
3547{ "sbasephemeris", required_argument, 0, 'B'},
3548{ "mixedephemeris", required_argument, 0, 'P'},
3549{ "rinex3", no_argument, 0, '3'},
3550{ "changeobs", no_argument, 0, 'O'},
3551{ "proxyport", required_argument, 0, 'R'},
3552{ "proxyhost", required_argument, 0, 'S'},
3553{ "nmea", required_argument, 0, 'n'},
3554{ "mode", required_argument, 0, 'M'},
3555{ "help", no_argument, 0, 'h'},
3556{0,0,0,0}};
3557#endif
3558#define ARGOPT "-d:s:p:r:t:f:u:E:C:G:B:P:Q:M:S:R:n:h3O"
3559
3560enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
3561
3562static const char *geturl(const char *url, struct Args *args)
3563{
3564 static char buf[1000];
3565 static char *Buffer = buf;
3566 static char *Bufend = buf+sizeof(buf);
3567
3568 if(strncmp("ntrip:", url, 6))
3569 return "URL must start with 'ntrip:'.";
3570 url += 6; /* skip ntrip: */
3571
3572 if(*url != '@' && *url != '/')
3573 {
3574 /* scan for mountpoint */
3575 args->data = Buffer;
3576 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
3577 *(Buffer++) = *(url++);
3578 if(Buffer == args->data)
3579 return "Mountpoint required.";
3580 else if(Buffer >= Bufend-1)
3581 return "Parsing buffer too short.";
3582 *(Buffer++) = 0;
3583 }
3584
3585 if(*url == '/') /* username and password */
3586 {
3587 ++url;
3588 args->user = Buffer;
3589 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
3590 *(Buffer++) = *(url++);
3591 if(Buffer == args->user)
3592 return "Username cannot be empty.";
3593 else if(Buffer >= Bufend-1)
3594 return "Parsing buffer too short.";
3595 *(Buffer++) = 0;
3596
3597 if(*url == ':') ++url;
3598
3599 args->password = Buffer;
3600 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3601 *(Buffer++) = *(url++);
3602 if(Buffer == args->password)
3603 return "Password cannot be empty.";
3604 else if(Buffer >= Bufend-1)
3605 return "Parsing buffer too short.";
3606 *(Buffer++) = 0;
3607 }
3608
3609 if(*url == '@') /* server */
3610 {
3611 ++url;
3612 if(*url != '@' && *url != ':')
3613 {
3614 args->server = Buffer;
3615 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
3616 *(Buffer++) = *(url++);
3617 if(Buffer == args->server)
3618 return "Servername cannot be empty.";
3619 else if(Buffer >= Bufend-1)
3620 return "Parsing buffer too short.";
3621 *(Buffer++) = 0;
3622 }
3623
3624 if(*url == ':')
3625 {
3626 ++url;
3627 args->port = Buffer;
3628 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3629 *(Buffer++) = *(url++);
3630 if(Buffer == args->port)
3631 return "Port cannot be empty.";
3632 else if(Buffer >= Bufend-1)
3633 return "Parsing buffer too short.";
3634 *(Buffer++) = 0;
3635 }
3636
3637 if(*url == '@') /* proxy */
3638 {
3639 ++url;
3640 args->proxyhost = Buffer;
3641 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
3642 *(Buffer++) = *(url++);
3643 if(Buffer == args->proxyhost)
3644 return "Proxy servername cannot be empty.";
3645 else if(Buffer >= Bufend-1)
3646 return "Parsing buffer too short.";
3647 *(Buffer++) = 0;
3648
3649 if(*url == ':')
3650 {
3651 ++url;
3652 args->proxyport = Buffer;
3653 while(*url && *url != ';' && Buffer != Bufend)
3654 *(Buffer++) = *(url++);
3655 if(Buffer == args->proxyport)
3656 return "Proxy port cannot be empty.";
3657 else if(Buffer >= Bufend-1)
3658 return "Parsing buffer too short.";
3659 *(Buffer++) = 0;
3660 }
3661 }
3662 }
3663 if(*url == ';') /* NMEA */
3664 {
3665 args->nmea = ++url;
3666 while(*url)
3667 ++url;
3668 }
3669
3670 return *url ? "Garbage at end of server string." : 0;
3671}
3672
3673static int getargs(int argc, char **argv, struct Args *args)
3674{
3675 int res = 1;
3676 int getoptr;
3677 int help = 0;
3678 char *t;
3679
3680 args->server = "www.euref-ip.net";
3681 args->port = "2101";
3682 args->timeout = 60;
3683 args->user = "";
3684 args->password = "";
3685 args->data = 0;
3686 args->headerfile = 0;
3687 args->gpsephemeris = 0;
3688 args->qzssephemeris = 0;
3689 args->sbasephemeris = 0;
3690 args->glonassephemeris = 0;
3691 args->bdsephemeris = 0;
3692 args->mixedephemeris = 0;
3693 args->rinex3 = 0;
3694 args->nmea = 0;
3695 args->changeobs = 0;
3696 args->proxyhost = 0;
3697 args->proxyport = "2101";
3698 args->mode = AUTO;
3699 help = 0;
3700
3701 do
3702 {
3703
3704#ifdef NO_LONG_OPTS
3705 switch((getoptr = getopt(argc, argv, ARGOPT)))
3706#else
3707 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
3708#endif
3709 {
3710 case 's': args->server = optarg; break;
3711 case 'u': args->user = optarg; break;
3712 case 'p': args->password = optarg; break;
3713 case 'd': args->data = optarg; break;
3714 case 'f': args->headerfile = optarg; break;
3715 case 'C': args->bdsephemeris = optarg; break;
3716 case 'E': args->gpsephemeris = optarg; break;
3717 case 'B': args->sbasephemeris = optarg; break;
3718 case 'G': args->glonassephemeris = optarg; break;
3719 case 'Q': args->qzssephemeris = optarg; break;
3720 case 'P': args->mixedephemeris = optarg; break;
3721 case 'r': args->port = optarg; break;
3722 case '3': args->rinex3 = 1; break;
3723 case 'S': args->proxyhost = optarg; break;
3724 case 'n': args->nmea = optarg; break;
3725 case 'R': args->proxyport = optarg; break;
3726 case 'O': args->changeobs = 1; break;
3727 case 'h': help=1; break;
3728 case 'M':
3729 args->mode = 0;
3730 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
3731 args->mode = NTRIP1;
3732 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
3733 args->mode = HTTP;
3734 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
3735 args->mode = RTSP;
3736 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
3737 args->mode = AUTO;
3738 else args->mode = atoi(optarg);
3739 if((args->mode == 0) || (args->mode >= END))
3740 {
3741 fprintf(stderr, "Mode %s unknown\n", optarg);
3742 res = 0;
3743 }
3744 break;
3745 case 't':
3746 args->timeout = strtoul(optarg, &t, 10);
3747 if((t && *t) || args->timeout < 0)
3748 res = 0;
3749 break;
3750
3751 case 1:
3752 {
3753 const char *err;
3754 if((err = geturl(optarg, args)))
3755 {
3756 RTCM3Error("%s\n\n", err);
3757 res = 0;
3758 }
3759 }
3760 break;
3761 case -1: break;
3762 }
3763 } while(getoptr != -1 || !res);
3764
3765 datestr[0] = datestr[7];
3766 datestr[1] = datestr[8];
3767 datestr[2] = datestr[9];
3768 datestr[3] = datestr[10];
3769 datestr[5] = datestr[12];
3770 datestr[6] = datestr[13];
3771 datestr[8] = datestr[15];
3772 datestr[9] = datestr[16];
3773 datestr[4] = datestr[7] = '-';
3774 datestr[10] = 0;
3775
3776 if(args->mixedephemeris && !args->rinex3)
3777 {
3778 RTCM3Error("RINEX2 cannot created combined ephemeris file.\n");
3779 res = 0;
3780 }
3781 else if(args->mixedephemeris && (args->gpsephemeris || args->glonassephemeris
3782 || args->bdsephemeris || args->qzssephemeris || args->sbasephemeris))
3783 {
3784 RTCM3Error("Combined ephemeris file specified with another one.\n"
3785 "Please specify only one navigation file.\n");
3786 res = 0;
3787 }
3788 else if(args->bdsephemeris && !args->rinex3)
3789 {
3790 RTCM3Error("RINEX2 cannot produce BDS ephemeris.\n");
3791 res = 0;
3792 }
3793 else if(!res || help)
3794 {
3795 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
3796 "\nUsage: %s -s server -u user ...\n"
3797 " -d " LONG_OPT("--data ") "the requested data set\n"
3798 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
3799 " -s " LONG_OPT("--server ") "the server name or address\n"
3800 " -p " LONG_OPT("--password ") "the login password\n"
3801 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
3802 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
3803 " -u " LONG_OPT("--user ") "the user name\n"
3804 " -C " LONG_OPT("--bdsephemeris ") "output file for BDS ephemeris data\n"
3805 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
3806 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
3807 " -Q " LONG_OPT("--qzssephemeris ") "output file for QZSS ephemeris data\n"
3808 " -B " LONG_OPT("--sbasephemeris ") "output file for SBAS ephemeris data\n"
3809 " -P " LONG_OPT("--mixedephemeris ") "output file for all ephemeris data\n"
3810 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
3811 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
3812 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
3813 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
3814 " -O " LONG_OPT("--changeobs ") "Add observation type change header lines\n"
3815 " -M " LONG_OPT("--mode ") "mode for data request\n"
3816 " Valid modes are:\n"
3817 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
3818 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
3819 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
3820 " 4, a, auto automatic detection (default)\n"
3821 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
3822 , revisionstr, datestr, argv[0], argv[0]);
3823 exit(1);
3824 }
3825 return res;
3826}
3827
3828/* let the output complete a block if necessary */
3829static void signalhandler(int sig)
3830{
3831 if(!stop)
3832 {
3833 RTCM3Error("Stop signal number %d received. "
3834 "Trying to terminate gentle.\n", sig);
3835 stop = 1;
3836 alarm(1);
3837 }
3838}
3839
3840#ifndef WINDOWSVERSION
3841static void WaitMicro(int mic)
3842{
3843 struct timeval tv;
3844 tv.tv_sec = mic/1000000;
3845 tv.tv_usec = mic%1000000;
3846#ifdef DEBUG
3847 fprintf(stderr, "Waiting %d micro seconds\n", mic);
3848#endif
3849 select(0, 0, 0, 0, &tv);
3850}
3851#else /* WINDOWSVERSION */
3852void WaitMicro(int mic)
3853{
3854 Sleep(mic/1000);
3855}
3856#endif /* WINDOWSVERSION */
3857
3858#define ALARMTIME (2*60)
3859
3860/* for some reason we had to abort hard (maybe waiting for data */
3861#ifdef __GNUC__
3862static __attribute__ ((noreturn)) void signalhandler_alarm(
3863int sig __attribute__((__unused__)))
3864#else /* __GNUC__ */
3865static void signalhandler_alarm(int sig)
3866#endif /* __GNUC__ */
3867{
3868 RTCM3Error("Programm forcefully terminated.\n");
3869 exit(1);
3870}
3871
3872int main(int argc, char **argv)
3873{
3874 struct Args args;
3875 struct RTCM3ParserData Parser;
3876
3877 setbuf(stdout, 0);
3878 setbuf(stdin, 0);
3879 setbuf(stderr, 0);
3880
3881 fixrevision();
3882
3883 signal(SIGINT, signalhandler);
3884 signal(SIGALRM,signalhandler_alarm);
3885 signal(SIGQUIT,signalhandler);
3886 signal(SIGTERM,signalhandler);
3887 signal(SIGPIPE,signalhandler);
3888 memset(&Parser, 0, sizeof(Parser));
3889 {
3890 time_t tim;
3891 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
3892 Parser.GPSWeek = tim/(7*24*60*60);
3893 Parser.GPSTOW = tim%(7*24*60*60);
3894 }
3895
3896 if(getargs(argc, argv, &args))
3897 {
3898 int sockfd, numbytes;
3899 char buf[MAXDATASIZE];
3900 struct sockaddr_in their_addr; /* connector's address information */
3901 struct hostent *he;
3902 struct servent *se;
3903 const char *server, *port, *proxyserver = 0;
3904 char proxyport[6];
3905 char *b;
3906 long i;
3907 struct timeval tv;
3908
3909 alarm(ALARMTIME);
3910
3911 Parser.headerfile = args.headerfile;
3912 Parser.glonassephemeris = args.glonassephemeris;
3913 Parser.gpsephemeris = args.gpsephemeris;
3914 Parser.bdsephemeris = args.bdsephemeris;
3915 Parser.qzssephemeris = args.qzssephemeris;
3916 Parser.sbasephemeris = args.sbasephemeris;
3917 Parser.mixedephemeris = args.mixedephemeris;
3918 Parser.rinex3 = args.rinex3;
3919 Parser.changeobs = args.changeobs;
3920
3921 if(args.proxyhost)
3922 {
3923 int p;
3924 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
3925 p = i;
3926 else if(!(se = getservbyname(args.port, 0)))
3927 {
3928 RTCM3Error("Can't resolve port %s.", args.port);
3929 exit(1);
3930 }
3931 else
3932 {
3933 p = ntohs(se->s_port);
3934 }
3935 snprintf(proxyport, sizeof(proxyport), "%d", p);
3936 port = args.proxyport;
3937 proxyserver = args.server;
3938 server = args.proxyhost;
3939 }
3940 else
3941 {
3942 server = args.server;
3943 port = args.port;
3944 }
3945
3946 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3947 if((i = strtol(port, &b, 10)) && (!b || !*b))
3948 their_addr.sin_port = htons(i);
3949 else if(!(se = getservbyname(port, 0)))
3950 {
3951 RTCM3Error("Can't resolve port %s.", port);
3952 exit(1);
3953 }
3954 else
3955 {
3956 their_addr.sin_port = se->s_port;
3957 }
3958 if(!(he=gethostbyname(server)))
3959 {
3960 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3961 exit(1);
3962 }
3963 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3964 {
3965 perror("socket");
3966 exit(1);
3967 }
3968
3969 tv.tv_sec = args.timeout;
3970 tv.tv_usec = 0;
3971 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3972 {
3973 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3974 exit(1);
3975 }
3976
3977 their_addr.sin_family = AF_INET;
3978 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3979
3980 if(args.data && args.mode == RTSP)
3981 {
3982 struct sockaddr_in local;
3983 int sockudp, localport;
3984 int cseq = 1;
3985 socklen_t len;
3986
3987 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3988 {
3989 perror("socket");
3990 exit(1);
3991 }
3992 /* fill structure with local address information for UDP */
3993 memset(&local, 0, sizeof(local));
3994 local.sin_family = AF_INET;
3995 local.sin_port = htons(0);
3996 local.sin_addr.s_addr = htonl(INADDR_ANY);
3997 len = sizeof(local);
3998 /* bind() in order to get a random RTP client_port */
3999 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
4000 {
4001 perror("bind");
4002 exit(1);
4003 }
4004 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
4005 {
4006 localport = ntohs(local.sin_port);
4007 }
4008 else
4009 {
4010 perror("local access failed");
4011 exit(1);
4012 }
4013 if(connect(sockfd, (struct sockaddr *)&their_addr,
4014 sizeof(struct sockaddr)) == -1)
4015 {
4016 perror("connect");
4017 exit(1);
4018 }
4019 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
4020 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
4021 "CSeq: %d\r\n"
4022 "Ntrip-Version: Ntrip/2.0\r\n"
4023 "Ntrip-Component: Ntripclient\r\n"
4024 "User-Agent: %s/%s\r\n"
4025 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
4026 "Authorization: Basic ",
4027 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
4028 args.data, cseq++, AGENTSTRING, revisionstr, localport);
4029 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
4030 {
4031 RTCM3Error("Requested data too long\n");
4032 exit(1);
4033 }
4034 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
4035 if(i > MAXDATASIZE-4)
4036 {
4037 RTCM3Error("Username and/or password too long\n");
4038 exit(1);
4039 }
4040 buf[i++] = '\r';
4041 buf[i++] = '\n';
4042 buf[i++] = '\r';
4043 buf[i++] = '\n';
4044 if(args.nmea)
4045 {
4046 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
4047 if(j >= 0 && j < MAXDATASIZE-i)
4048 i += j;
4049 else
4050 {
4051 RTCM3Error("NMEA string too long\n");
4052 exit(1);
4053 }
4054 }
4055 if(send(sockfd, buf, (size_t)i, 0) != i)
4056 {
4057 perror("send");
4058 exit(1);
4059 }
4060 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
4061 {
4062 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
4063 {
4064 int serverport = 0, session = 0;
4065 const char *portcheck = "server_port=";
4066 const char *sessioncheck = "session: ";
4067 int l = strlen(portcheck)-1;
4068 int j=0;
4069 for(i = 0; j != l && i < numbytes-l; ++i)
4070 {
4071 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
4072 ;
4073 }
4074 if(i == numbytes-l)
4075 {
4076 RTCM3Error("No server port number found\n");
4077 exit(1);
4078 }
4079 else
4080 {
4081 i+=l;
4082 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
4083 serverport = serverport * 10 + buf[i++]-'0';
4084 if(buf[i] != '\r' && buf[i] != ';')
4085 {
4086 RTCM3Error("Could not extract server port\n");
4087 exit(1);
4088 }
4089 }
4090 l = strlen(sessioncheck)-1;
4091 j=0;
4092 for(i = 0; j != l && i < numbytes-l; ++i)
4093 {
4094 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
4095 ;
4096 }
4097 if(i == numbytes-l)
4098 {
4099 RTCM3Error("No session number found\n");
4100 exit(1);
4101 }
4102 else
4103 {
4104 i+=l;
4105 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
4106 session = session * 10 + buf[i++]-'0';
4107 if(buf[i] != '\r')
4108 {
4109 RTCM3Error("Could not extract session number\n");
4110 exit(1);
4111 }
4112 }
4113
4114 i = snprintf(buf, MAXDATASIZE,
4115 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
4116 "CSeq: %d\r\n"
4117 "Session: %d\r\n"
4118 "\r\n",
4119 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
4120 args.data, cseq++, session);
4121
4122 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
4123 {
4124 RTCM3Error("Requested data too long\n");
4125 exit(1);
4126 }
4127 if(send(sockfd, buf, (size_t)i, 0) != i)
4128 {
4129 perror("send");
4130 exit(1);
4131 }
4132 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
4133 {
4134 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
4135 {
4136 struct sockaddr_in addrRTP;
4137 /* fill structure with caster address information for UDP */
4138 memset(&addrRTP, 0, sizeof(addrRTP));
4139 addrRTP.sin_family = AF_INET;
4140 addrRTP.sin_port = htons(serverport);
4141 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
4142 len = sizeof(addrRTP);
4143 int ts = 0;
4144 int sn = 0;
4145 int ssrc = 0;
4146 int init = 0;
4147 int u, v, w;
4148 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
4149 (struct sockaddr*) &addrRTP, &len)) > 0)
4150 {
4151 alarm(ALARMTIME);
4152 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
4153 {
4154 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
4155 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
4156 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
4157 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
4158 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
4159
4160 if(init)
4161 {
4162 int z;
4163 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
4164 if(ssrc != w || ts > v)
4165 {
4166 RTCM3Error("Illegal UDP data received.\n");
4167 exit(1);
4168 }
4169 if(u > sn) /* don't show out-of-order packets */
4170 for(z = 12; z < i && !stop; ++z)
4171 HandleByte(&Parser, (unsigned int) buf[z]);
4172 }
4173 sn = u; ts = v; ssrc = w; init = 1;
4174 }
4175 else
4176 {
4177 RTCM3Error("Illegal UDP header.\n");
4178 exit(1);
4179 }
4180 }
4181 }
4182 i = snprintf(buf, MAXDATASIZE,
4183 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
4184 "CSeq: %d\r\n"
4185 "Session: %d\r\n"
4186 "\r\n",
4187 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
4188 args.data, cseq++, session);
4189
4190 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
4191 {
4192 RTCM3Error("Requested data too long\n");
4193 exit(1);
4194 }
4195 if(send(sockfd, buf, (size_t)i, 0) != i)
4196 {
4197 perror("send");
4198 exit(1);
4199 }
4200 }
4201 else
4202 {
4203 RTCM3Error("Could not start data stream.\n");
4204 exit(1);
4205 }
4206 }
4207 else
4208 {
4209 RTCM3Error("Could not setup initial control connection.\n");
4210 exit(1);
4211 }
4212 }
4213 else
4214 {
4215 perror("recv");
4216 exit(1);
4217 }
4218 }
4219 else
4220 {
4221 if(connect(sockfd, (struct sockaddr *)&their_addr,
4222 sizeof(struct sockaddr)) == -1)
4223 {
4224 perror("connect");
4225 exit(1);
4226 }
4227 if(!args.data)
4228 {
4229 i = snprintf(buf, MAXDATASIZE,
4230 "GET %s%s%s%s/ HTTP/1.0\r\n"
4231 "Host: %s\r\n%s"
4232 "User-Agent: %s/%s\r\n"
4233 "Connection: close\r\n"
4234 "\r\n"
4235 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4236 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4237 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4238 AGENTSTRING, revisionstr);
4239 }
4240 else
4241 {
4242 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
4243 "GET %s%s%s%s/%s HTTP/1.0\r\n"
4244 "Host: %s\r\n%s"
4245 "User-Agent: %s/%s\r\n"
4246 "Connection: close\r\n"
4247 "Authorization: Basic "
4248 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4249 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4250 args.data, args.server,
4251 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4252 AGENTSTRING, revisionstr);
4253 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
4254 {
4255 RTCM3Error("Requested data too long\n");
4256 exit(1);
4257 }
4258 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
4259 if(i > MAXDATASIZE-4)
4260 {
4261 RTCM3Error("Username and/or password too long\n");
4262 exit(1);
4263 }
4264 buf[i++] = '\r';
4265 buf[i++] = '\n';
4266 buf[i++] = '\r';
4267 buf[i++] = '\n';
4268 if(args.nmea)
4269 {
4270 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
4271 if(j >= 0 && j < MAXDATASIZE-i)
4272 i += j;
4273 else
4274 {
4275 RTCM3Error("NMEA string too long\n");
4276 exit(1);
4277 }
4278 }
4279 }
4280 if(send(sockfd, buf, (size_t)i, 0) != i)
4281 {
4282 perror("send");
4283 exit(1);
4284 }
4285 if(args.data)
4286 {
4287 int k = 0;
4288 int chunkymode = 0;
4289 int totalbytes = 0;
4290 int chunksize = 0;
4291
4292 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
4293 {
4294 if(numbytes > 0)
4295 alarm(ALARMTIME);
4296 else
4297 {
4298 WaitMicro(100);
4299 continue;
4300 }
4301 if(!k)
4302 {
4303 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
4304 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
4305 {
4306 const char *datacheck = "Content-Type: gnss/data\r\n";
4307 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
4308 int l = strlen(datacheck)-1;
4309 int j=0;
4310 for(i = 0; j != l && i < numbytes-l; ++i)
4311 {
4312 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
4313 ;
4314 }
4315 if(i == numbytes-l)
4316 {
4317 RTCM3Error("No 'Content-Type: gnss/data' found\n");
4318 exit(1);
4319 }
4320 l = strlen(chunkycheck)-1;
4321 j=0;
4322 for(i = 0; j != l && i < numbytes-l; ++i)
4323 {
4324 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
4325 ;
4326 }
4327 if(i < numbytes-l)
4328 chunkymode = 1;
4329 }
4330 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
4331 {
4332 RTCM3Error("Could not get the requested data: ");
4333 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
4334 {
4335 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
4336 }
4337 RTCM3Error("\n");
4338 exit(1);
4339 }
4340 else if(args.mode != NTRIP1)
4341 {
4342 if(args.mode != AUTO)
4343 {
4344 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
4345 args.mode == AUTO ? ", falling back to NTRIP1" : "");
4346 }
4347 if(args.mode == HTTP)
4348 exit(1);
4349 }
4350 ++k;
4351 }
4352 else
4353 {
4354 if(chunkymode)
4355 {
4356 int stop = 0;
4357 int pos = 0;
4358 while(!stop && pos < numbytes)
4359 {
4360 switch(chunkymode)
4361 {
4362 case 1: /* reading number starts */
4363 chunksize = 0;
4364 ++chunkymode; /* no break */
4365 case 2: /* during reading number */
4366 i = buf[pos++];
4367 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
4368 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
4369 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
4370 else if(i == '\r') ++chunkymode;
4371 else if(i == ';') chunkymode = 5;
4372 else stop = 1;
4373 break;
4374 case 3: /* scanning for return */
4375 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
4376 else stop = 1;
4377 break;
4378 case 4: /* output data */
4379 i = numbytes-pos;
4380 if(i > chunksize) i = chunksize;
4381 {
4382 int z;
4383 for(z = 0; z < i && !stop; ++z)
4384 HandleByte(&Parser, (unsigned int) buf[pos+z]);
4385 }
4386 totalbytes += i;
4387 chunksize -= i;
4388 pos += i;
4389 if(!chunksize)
4390 chunkymode = 1;
4391 break;
4392 case 5:
4393 if(i == '\r') chunkymode = 3;
4394 break;
4395 }
4396 }
4397 if(stop)
4398 {
4399 RTCM3Error("Error in chunky transfer encoding\n");
4400 break;
4401 }
4402 }
4403 else
4404 {
4405 totalbytes += numbytes;
4406 {
4407 int z;
4408 for(z = 0; z < numbytes && !stop; ++z)
4409 HandleByte(&Parser, (unsigned int) buf[z]);
4410 }
4411 }
4412 if(totalbytes < 0) /* overflow */
4413 {
4414 totalbytes = 0;
4415 }
4416 }
4417 }
4418 }
4419 else
4420 {
4421 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
4422 {
4423 alarm(ALARMTIME);
4424 fwrite(buf, (size_t)numbytes, 1, stdout);
4425 }
4426 }
4427 close(sockfd);
4428 }
4429 }
4430 return 0;
4431}
4432#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.