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

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

fix header changes in new MSM

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