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

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

fix L1/P code for GPS

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