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

Last change on this file since 5533 was 5533, checked in by stoecker, 10 years ago

add INAV/FNAV flags

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