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

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

set proper do not know TOW

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