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

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

fix typo

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