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

Last change on this file since 4498 was 4498, checked in by stoecker, 12 years ago

switch place for L1 signal to match JAXA drafts

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