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

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

fix RINEX3 for old style RTCM3

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