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

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

adapt GLO channels

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