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

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

fix wrong factors

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