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

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

add type 1046

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