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

Last change on this file since 2996 was 2996, checked in by stoecker, 13 years ago

support 51,52 as GIOVE sat numbers

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