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

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

first test of MSM messages

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