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

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

untested BDS support

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