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

Last change on this file since 3270 was 3270, checked in by mervart, 13 years ago

LM: modification due to 24-hour problem

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