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

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

fix GIOVE workaround

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