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

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

fix illegal code

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