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

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

fix doppler, switch to larger fields

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