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

Last change on this file since 5333 was 5333, checked in by stoecker, 11 years ago

fix fit interval

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