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

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

update type 1045 to newest proposal

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