Changeset 65 in ntrip for trunk/BNC/RTCM3/rtcm3.cpp
- Timestamp:
- Aug 24, 2006, 3:58:20 PM (18 years ago)
- Location:
- trunk/BNC
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC
- Property svn:ignore
-
old new 2 2 Makefile 3 3 bnc 4 anlagen 4 5 moc_bnccaster.cpp 5 6 moc_bncgetthread.cpp
-
- Property svn:ignore
-
trunk/BNC/RTCM3/rtcm3.cpp
r53 r65 1 /*2 Converter for RTCM3 data to RINEX.3 $Id: rtcm3.cpp,v 1.1 2006/08/20 13:35:39 mervart Exp $4 1 5 Program written bei 6 Dirk Stoecker 7 Euronik GmbH 8 http://www.euronik.eu/ 2 /* ------------------------------------------------------------------------- 3 * Bernese NTRIP Client 4 * ------------------------------------------------------------------------- 5 * 6 * Class: rtcm3 7 * 8 * Purpose: RTCM3 Decoder 9 * 10 * Author: L. Mervart 11 * 12 * Created: 24-Aug-2006 13 * 14 * Changes: 15 * 16 * -----------------------------------------------------------------------*/ 9 17 10 for 18 #include "rtcm3.h" 11 19 12 Federal Agency for Cartography and Geodesy (BKG) 13 Richard-Strauss-Allee 11 14 D-60598 Frankfurt 15 http://igs.bkg.bund.de/index_ntrip.htm 20 using namespace std; 16 21 17 Contact Dirk Stoecker [stoecker@euronik.eu] or [euref-ip@bkg.bund.de] 18 with your comments, suggestions, improvements, patches. 19 20 Copyright (C) 2005-2006 by German Federal Agency for Cartography and Geodesy 21 22 This program is free software; you can redistribute it and/or modify 23 it under the terms of the GNU General Public License as published by 24 the Free Software Foundation; either version 2 of the License, or 25 (at your option) any later version. 26 27 This program is distributed in the hope that it will be useful, 28 but WITHOUT ANY WARRANTY; without even the implied warranty of 29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 GNU General Public License for more details. 31 32 You should have received a copy of the GNU General Public License 33 along with this program; if not, write to the Free Software 34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35 or read http://www.gnu.org/licenses/gpl.txt 36 */ 37 38 #include <ctype.h> 39 #include <errno.h> 40 #include <getopt.h> 41 #include <math.h> 42 #include <netdb.h> 43 #include <netinet/in.h> 44 #include <signal.h> 45 #include <stdint.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <sys/socket.h> 50 #include <sys/types.h> 51 #include <time.h> 52 #include <unistd.h> 53 54 /* The string, which is send as agent in HTTP request */ 55 #define AGENTSTRING "NTRIP NtripRTCM3ToRINEX" 56 57 #define MAXDATASIZE 1000 /* max number of bytes we can get at once */ 58 59 /* CVS revision and version */ 60 static char revisionstr[] = "$Revision: 1.1 $"; 61 static char datestr[] = "$Date: 2006/08/20 13:35:39 $"; 62 static int stop = 0; 63 64 /* unimportant, only for approx. time needed */ 65 #define LEAPSECONDS 14 66 67 struct converttimeinfo { 68 int second; /* seconds of GPS time [0..59] */ 69 int minute; /* minutes of GPS time [0..59] */ 70 int hour; /* hour of GPS time [0..24] */ 71 int day; /* day of GPS time [1..28..30(31)*/ 72 int month; /* month of GPS time [1..12]*/ 73 int year; /* year of GPS time [1980..] */ 74 }; 75 76 #define PRN_GPS_START 1 77 #define PRN_GPS_END 32 78 #define PRN_GLONASS_START 38 79 #define PRN_GLONASS_END 61 80 81 #define GNSSENTRY_C1DATA 0 82 #define GNSSENTRY_C2DATA 1 83 #define GNSSENTRY_P1DATA 2 84 #define GNSSENTRY_P2DATA 3 85 #define GNSSENTRY_L1CDATA 4 86 #define GNSSENTRY_L1PDATA 5 87 #define GNSSENTRY_L2CDATA 6 88 #define GNSSENTRY_L2PDATA 7 89 #define GNSSENTRY_D1CDATA 8 90 #define GNSSENTRY_D1PDATA 9 91 #define GNSSENTRY_D2CDATA 10 92 #define GNSSENTRY_D2PDATA 11 93 #define GNSSENTRY_S1CDATA 12 94 #define GNSSENTRY_S1PDATA 13 95 #define GNSSENTRY_S2CDATA 14 96 #define GNSSENTRY_S2PDATA 15 97 #define GNSSENTRY_NUMBER 16 /* number of types!!! */ 98 99 /* Data flags. These flags are used in the dataflags field of gpsdata structure 100 and are used the determine, which data fields are filled with valid data. */ 101 #define GNSSDF_C1DATA (1<<GNSSENTRY_C1DATA) 102 #define GNSSDF_C2DATA (1<<GNSSENTRY_C2DATA) 103 #define GNSSDF_P1DATA (1<<GNSSENTRY_P1DATA) 104 #define GNSSDF_P2DATA (1<<GNSSENTRY_P2DATA) 105 #define GNSSDF_L1CDATA (1<<GNSSENTRY_L1CDATA) 106 #define GNSSDF_L1PDATA (1<<GNSSENTRY_L1PDATA) 107 #define GNSSDF_L2CDATA (1<<GNSSENTRY_L2CDATA) 108 #define GNSSDF_L2PDATA (1<<GNSSENTRY_L2PDATA) 109 #define GNSSDF_D1CDATA (1<<GNSSENTRY_D1CDATA) 110 #define GNSSDF_D1PDATA (1<<GNSSENTRY_D1PDATA) 111 #define GNSSDF_D2CDATA (1<<GNSSENTRY_D2CDATA) 112 #define GNSSDF_D2PDATA (1<<GNSSENTRY_D2PDATA) 113 #define GNSSDF_S1CDATA (1<<GNSSENTRY_S1CDATA) 114 #define GNSSDF_S1PDATA (1<<GNSSENTRY_S1PDATA) 115 #define GNSSDF_S2CDATA (1<<GNSSENTRY_S2CDATA) 116 #define GNSSDF_S2PDATA (1<<GNSSENTRY_S2PDATA) 117 118 #define RINEXENTRY_C1DATA 0 119 #define RINEXENTRY_C2DATA 1 120 #define RINEXENTRY_P1DATA 2 121 #define RINEXENTRY_P2DATA 3 122 #define RINEXENTRY_L1DATA 4 123 #define RINEXENTRY_L2DATA 5 124 #define RINEXENTRY_D1DATA 6 125 #define RINEXENTRY_D2DATA 7 126 #define RINEXENTRY_S1DATA 8 127 #define RINEXENTRY_S2DATA 9 128 #define RINEXENTRY_NUMBER 10 129 130 /* Additional flags for the data field, which tell us more. */ 131 #define GNSSDF_LOCKLOSSL1 (1<<29) /* lost lock on L1 */ 132 #define GNSSDF_LOCKLOSSL2 (1<<30) /* lost lock on L2 */ 133 134 struct gnssdata { 135 int flags; /* GPSF_xxx */ 136 int week; /* week number of GPS date */ 137 int numsats; 138 double timeofweek; /* milliseconds in GPS week */ 139 double measdata[24][GNSSENTRY_NUMBER]; /* data fields */ 140 int dataflags[24]; /* GPSDF_xxx */ 141 int satellites[24]; /* SV - IDs */ 142 int snrL1[24]; /* Important: all the 5 SV-specific fields must */ 143 int snrL2[24]; /* have the same SV-order */ 144 }; 145 146 struct RTCM3ParserData { 147 unsigned char Message[2048]; /* input-buffer */ 148 int MessageSize; /* current buffer size */ 149 int NeedBytes; /* bytes wanted for next run */ 150 int SkipBytes; /* bytes to skip in next round */ 151 int GPSWeek; 152 int GPSTOW; /* in seconds */ 153 struct gnssdata Data; 154 int size; 155 int lastlockl1[64]; 156 int lastlockl2[64]; 157 int datapos[RINEXENTRY_NUMBER]; 158 int dataflag[RINEXENTRY_NUMBER]; 159 int numdatatypes; 160 int validwarning; 161 int init; 162 const char * headerfile; 163 }; 164 165 struct Args 166 { 167 const char *server; 168 int port; 169 const char *user; 170 const char *password; 171 const char *data; 172 const char *headerfile; 173 }; 174 175 /* option parsing */ 176 #ifdef NO_LONG_OPTS 177 #define LONG_OPT(a) 178 #else 179 #define LONG_OPT(a) a 180 static struct option opts[] = { 181 { "data", required_argument, 0, 'd'}, 182 { "server", required_argument, 0, 's'}, 183 { "password", required_argument, 0, 'p'}, 184 { "port", required_argument, 0, 'r'}, 185 { "header", required_argument, 0, 'f'}, 186 { "user", required_argument, 0, 'u'}, 187 { "help", no_argument, 0, 'h'}, 188 {0,0,0,0}}; 189 #endif 190 #define ARGOPT "d:hp:r:s:u:f:" 191 192 static int getargs(int argc, char **argv, struct Args *args) 193 { 194 int res = 1; 195 int getoptr; 196 int help = 0; 197 char *t; 198 199 args->server = "www.euref-ip.net"; 200 args->port = 80; 201 args->user = ""; 202 args->password = ""; 203 args->data = 0; 204 args->headerfile = 0; 205 help = 0; 206 207 do 208 { 209 #ifdef NO_LONG_OPTS 210 switch((getoptr = getopt(argc, argv, ARGOPT))) 211 #else 212 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0))) 213 #endif 214 { 215 case 's': args->server = optarg; break; 216 case 'u': args->user = optarg; break; 217 case 'p': args->password = optarg; break; 218 case 'd': args->data = optarg; break; 219 case 'f': args->headerfile = optarg; break; 220 case 'h': help=1; break; 221 case 'r': 222 args->port = strtoul(optarg, &t, 10); 223 if((t && *t) || args->port < 1 || args->port > 65535) 224 res = 0; 225 break; 226 case -1: break; 227 } 228 } while(getoptr != -1 || !res); 229 230 datestr[0] = datestr[7]; 231 datestr[1] = datestr[8]; 232 datestr[2] = datestr[9]; 233 datestr[3] = datestr[10]; 234 datestr[5] = datestr[12]; 235 datestr[6] = datestr[13]; 236 datestr[8] = datestr[15]; 237 datestr[9] = datestr[16]; 238 datestr[4] = datestr[7] = '-'; 239 datestr[10] = 0; 240 241 if(!res || help) 242 { 243 fprintf(stderr, "Version %s (%s) GPL\nUsage: %s -s server -u user ...\n" 244 " -d " LONG_OPT("--data ") "the requested data set\n" 245 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n" 246 " -s " LONG_OPT("--server ") "the server name or address\n" 247 " -p " LONG_OPT("--password ") "the login password\n" 248 " -r " LONG_OPT("--port ") "the server port number (default 80)\n" 249 " -u " LONG_OPT("--user ") "the user name\n" 250 , revisionstr, datestr, argv[0]); 251 exit(1); 252 } 253 return res; 22 // Constructor 23 //////////////////////////////////////////////////////////////////////////// 24 rtcm3::rtcm3() : GPSDecoder() { 25 memset(&_Parser, 0, sizeof(_Parser)); 26 time_t tim; 27 tim = time(0) - ((10*365+2+5)*24*60*60 + LEAPSECONDS); 28 _Parser.GPSWeek = tim/(7*24*60*60); 29 _Parser.GPSTOW = tim%(7*24*60*60); 254 30 } 255 31 256 static const char encodingTable [64] = { 257 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 258 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 259 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 260 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' 261 }; 262 263 /* does not buffer overrun, but breaks directly after an error */ 264 /* returns the number of required bytes */ 265 static int encode(char *buf, int size, const char *user, const char *pwd) 266 { 267 unsigned char inbuf[3]; 268 char *out = buf; 269 int i, sep = 0, fill = 0, bytes = 0; 270 271 while(*user || *pwd) 272 { 273 i = 0; 274 while(i < 3 && *user) inbuf[i++] = *(user++); 275 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; } 276 while(i < 3 && *pwd) inbuf[i++] = *(pwd++); 277 while(i < 3) {inbuf[i++] = 0; ++fill; } 278 if(out-buf < size-1) 279 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2]; 280 if(out-buf < size-1) 281 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4) 282 | ((inbuf [1] & 0xF0) >> 4)]; 283 if(out-buf < size-1) 284 { 285 if(fill == 2) 286 *(out++) = '='; 287 else 288 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2) 289 | ((inbuf [2] & 0xC0) >> 6)]; 290 } 291 if(out-buf < size-1) 292 { 293 if(fill >= 1) 294 *(out++) = '='; 295 else 296 *(out++) = encodingTable[inbuf [2] & 0x3F]; 297 } 298 bytes += 4; 299 } 300 if(out-buf < size) 301 *out = 0; 302 return bytes; 32 // Destructor 33 //////////////////////////////////////////////////////////////////////////// 34 rtcm3::~rtcm3() { 303 35 } 304 36 305 static uint32_t CRC24(long size, const unsigned char *buf) 306 { 307 uint32_t crc = 0; 308 int i; 309 310 while(size--) 311 { 312 crc ^= (*buf++) << (16); 313 for(i = 0; i < 8; i++) 314 { 315 crc <<= 1; 316 if(crc & 0x1000000) 317 crc ^= 0x01864cfb; 318 } 319 } 320 return crc; 321 } 322 323 static int GetMessage(struct RTCM3ParserData *handle) 324 { 325 unsigned char *m, *e; 326 int i; 327 328 m = handle->Message+handle->SkipBytes; 329 e = handle->Message+handle->MessageSize; 330 handle->NeedBytes = handle->SkipBytes = 0; 331 while(e-m >= 3) 332 { 333 if(m[0] == 0xD3) 334 { 335 handle->size = ((m[1]&3)<<8)|m[2]; 336 if(e-m >= handle->size+6) 337 { 338 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8) 339 |(m[3+handle->size+2])) == CRC24(handle->size+3, m)) 340 { 341 handle->SkipBytes = handle->size; 342 break; 343 } 344 else 345 ++m; 346 } 347 else 348 { 349 handle->NeedBytes = handle->size+6; 350 break; 351 } 352 } 353 else 354 ++m; 355 } 356 if(e-m < 3) 357 handle->NeedBytes = 3; 358 359 /* copy buffer to front */ 360 i = m - handle->Message; 361 if(i && m < e) 362 memmove(handle->Message, m, handle->MessageSize-i); 363 handle->MessageSize -= i; 364 365 return !handle->NeedBytes; 366 } 367 368 #define LOADBITS(a) \ 369 { \ 370 while((a) > numbits) \ 371 { \ 372 if(!size--) break; \ 373 bitfield = (bitfield<<8)|*(data++); \ 374 numbits += 8; \ 375 } \ 376 } 377 378 /* extract bits from data stream 379 b = variable to store result, a = number of bits */ 380 #define GETBITS(b, a) \ 381 { \ 382 LOADBITS(a) \ 383 b = (bitfield<<(64-numbits))>>(64-(a)); \ 384 numbits -= (a); \ 385 } 386 387 /* extract bits from data stream 388 b = variable to store result, a = number of bits */ 389 #define GETBITSSIGN(b, a) \ 390 { \ 391 LOADBITS(a) \ 392 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \ 393 numbits -= (a); \ 394 } 395 396 #define SKIPBITS(b) { LOADBITS(b) numbits -= (b); } 397 398 static int RTCM3Parser(struct RTCM3ParserData *handle) 399 { 400 int ret=0; 401 402 while(!ret && GetMessage(handle)) 403 { 404 /* using 64 bit integer types, as it is much easier than handling 405 the long datatypes in 32 bit */ 406 uint64_t numbits = 0, bitfield = 0; 407 int size = handle->size, type; 408 unsigned char *data = handle->Message+3; 409 410 GETBITS(type,12) 411 switch(type) 412 { 413 case 1001: case 1002: case 1003: case 1004: 414 if(handle->GPSWeek) 415 { 416 int lastlockl1[64]; 417 int lastlockl2[64]; 418 struct gnssdata *gnss; 419 int i, num, wasamb=0; 420 421 for(i = 0; i < 64; ++i) 422 lastlockl1[i] = lastlockl2[i] = 0; 423 424 gnss = &handle->Data; 425 memset(gnss, 0, sizeof(*gnss)); 426 427 SKIPBITS(12) /* id */ 428 GETBITS(i,30) 429 if(i/1000 < (int)handle->GPSTOW - 86400) 430 ++handle->GPSWeek; 431 handle->GPSTOW = i/1000; 432 gnss->timeofweek = i; 433 gnss->week = handle->GPSWeek; 434 435 SKIPBITS(1) /* sync */ 436 GETBITS(i,5) 437 gnss->numsats = i; 438 SKIPBITS(4) /* smind, smint */ 439 440 for(num = 0; num < gnss->numsats; ++num) 441 { 442 int sv, code, l1range, c,l,s,ce,le,se,amb=0; 443 444 GETBITS(sv, 6); 445 gnss->satellites[num] = (sv < 40 ? sv : sv+80); 446 /* L1 */ 447 GETBITS(code, 1); 448 if(code) 449 { 450 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA; 451 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA; 452 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA; 453 } 454 else 455 { 456 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA; 457 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA; 458 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA; 459 } 460 GETBITS(l1range, 24); 461 if(l1range != 0x80000) 462 { 463 gnss->dataflags[num] |= c; 464 gnss->measdata[num][ce] = l1range*0.02; 465 } 466 GETBITSSIGN(i, 20); 467 if(i != 0x80000) 468 { 469 gnss->dataflags[num] |= l; 470 gnss->measdata[num][le] = l1range*0.02+i*0.0005; 471 } 472 GETBITS(i, 7); 473 lastlockl1[sv] = i; 474 if(handle->lastlockl1[sv] > i) 475 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1; 476 if(type == 1002 || type == 1004) 477 { 478 GETBITS(amb,8); 479 if(amb && (gnss->dataflags[num] & c)) 480 { 481 gnss->measdata[num][ce] += amb*299792.458; 482 gnss->measdata[num][le] += amb*299792.458; 483 ++wasamb; 484 } 485 GETBITS(i, 8); 486 if(i) 487 { 488 gnss->dataflags[num] |= s; 489 gnss->measdata[num][se] = i*0.25; 490 i /= 4*4; 491 if(i > 9) i = 9; 492 else if(i < 1) i = 1; 493 gnss->snrL1[num] = i; 494 } 495 } 496 if(type == 1003 || type == 1004) 497 { 498 /* L2 */ 499 GETBITS(code,2); 500 if(code) 501 { 502 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA; 503 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA; 504 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA; 505 } 506 else 507 { 508 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA; 509 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA; 510 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA; 511 } 512 GETBITSSIGN(i,14); 513 if(i != 0x2000) 514 { 515 gnss->dataflags[num] |= c; 516 gnss->measdata[num][ce] = l1range*0.02+i*0.02 517 +amb*299792.458; 518 } 519 GETBITSSIGN(i,20); 520 if(i != 0x80000) 521 { 522 gnss->dataflags[num] |= l; 523 gnss->measdata[num][le] = l1range*0.02+i*0.0005 524 +amb*299792.458; 525 } 526 GETBITS(i,7); 527 lastlockl2[sv] = i; 528 if(handle->lastlockl2[sv] > i) 529 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2; 530 if(type == 1004) 531 { 532 GETBITS(i, 8); 533 if(i) 534 { 535 gnss->dataflags[num] |= s; 536 gnss->measdata[num][se] = i*0.25; 537 i /= 4*4; 538 if(i > 9) i = 9; 539 else if(i < 1) i = 1; 540 gnss->snrL2[num] = i; 541 } 542 } 543 } 544 } 545 for(i = 0; i < 64; ++i) 546 { 547 handle->lastlockl1[i] = lastlockl1[i]; 548 handle->lastlockl2[i] = lastlockl2[i]; 549 } 550 if(wasamb) /* not RINEX compatible without */ 551 ret = 1; 552 else 553 ret = 2; 554 } 555 break; 556 } 557 } 558 return ret; 559 } 560 561 static int longyear(int year, int month) 562 { 563 if(!(year % 4) && (!(year % 400) || (year % 100))) 564 { 565 if(!month || month == 2) 566 return 1; 567 } 568 return 0; 569 } 570 571 static void converttime(struct converttimeinfo *c, int week, int tow) 572 { 573 /* static variables */ 574 static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; 575 576 int i, k, doy, j; /* temporary variables */ 577 j = week*(7*24*60*60) + tow + 5*24*60*60; 578 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i) 579 j -= k; 580 c->year = i; 581 doy = 1+ (j / (24*60*60)); 582 j %= (24*60*60); 583 c->hour = j / (60*60); 584 j %= (60*60); 585 c->minute = j / 60; 586 c->second = j % 60; 587 j = 0; 588 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i) 589 j += k; 590 c->month = i; 591 c->day = doy - j; 592 } 593 594 struct Header 595 { 596 const char *version; 597 const char *pgm; 598 const char *marker; 599 const char *observer; 600 const char *receiver; 601 const char *antenna; 602 const char *position; 603 const char *antennaposition; 604 const char *wavelength; 605 const char *typesofobs; /* should not be modified outside */ 606 const char *timeoffirstobs; /* should not be modified outside */ 607 }; 608 609 #define MAXHEADERLINES 50 610 #define MAXHEADERBUFFERSIZE 4096 611 struct HeaderData 612 { 613 union 614 { 615 struct Header named; 616 const char *unnamed[MAXHEADERLINES]; 617 } data; 618 int numheaders; 619 }; 620 621 static void HandleHeader(struct RTCM3ParserData *Parser) 622 { 623 struct HeaderData hdata; 624 char thebuffer[MAXHEADERBUFFERSIZE]; 625 char *buffer = thebuffer; 626 int buffersize = sizeof(thebuffer); 627 int i; 628 629 hdata.data.named.version = 630 " 2.11 OBSERVATION DATA M (Mixed)" 631 " RINEX VERSION / TYPE"; 632 633 { 634 const char *str; 635 time_t t; 636 struct tm * t2; 637 638 str = getenv("USER"); 639 if(!str) str = ""; 640 t = time(&t); 641 t2 = gmtime(&t); 642 hdata.data.named.pgm = buffer; 643 i = 1+snprintf(buffer, buffersize, 644 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d " 645 "PGM / RUN BY / DATE", 646 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour, 647 t2->tm_min); 648 buffer += i; buffersize -= i; 649 650 hdata.data.named.observer = buffer; 651 i = 1+snprintf(buffer, buffersize, 652 "%-20.20s " 653 "OBSERVER / AGENCY", str); 654 buffer += i; buffersize -= i; 655 } 656 657 hdata.data.named.marker = 658 "RTCM3TORINEX " 659 "MARKER NAME"; 660 661 hdata.data.named.receiver = 662 " " 663 "REC # / TYPE / VERS"; 664 665 hdata.data.named.antenna = 666 " " 667 "ANT # / TYPE"; 668 669 hdata.data.named.position = 670 " .0000 .0000 .0000 " 671 "APPROX POSITION XYZ"; 672 673 hdata.data.named.antennaposition = 674 " .0000 .0000 .0000 " 675 "ANTENNA: DELTA H/E/N"; 676 677 hdata.data.named.wavelength = 678 " 1 1 " 679 "WAVELENGTH FACT L1/2"; 680 681 { 682 #define CHECKFLAGS(a, b) \ 683 if(flags & GNSSDF_##a##DATA \ 684 && !data[RINEXENTRY_##b##DATA]) \ 685 { \ 686 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \ 687 Parser->datapos[Parser->numdatatypes++] = data[RINEXENTRY_##b##DATA] \ 688 = GNSSENTRY_##a##DATA; \ 689 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \ 690 tbufferpos += 6; \ 691 } 692 693 int flags = 0; 694 int data[RINEXENTRY_NUMBER]; 695 char tbuffer[6*RINEXENTRY_NUMBER+1]; 696 int tbufferpos = 0; 697 for(i = 0; i < RINEXENTRY_NUMBER; ++i) 698 data[i] = 0; 699 for(i = 0; i < Parser->Data.numsats; ++i) 700 flags |= Parser->Data.dataflags[i]; 701 702 CHECKFLAGS(C1,C1) 703 CHECKFLAGS(C2,C2) 704 CHECKFLAGS(P1,P1) 705 CHECKFLAGS(P2,P2) 706 CHECKFLAGS(L1C,L1) 707 CHECKFLAGS(L1P,L1) 708 CHECKFLAGS(L2C,L2) 709 CHECKFLAGS(L2P,L2) 710 CHECKFLAGS(D1C,D1) 711 CHECKFLAGS(D1P,D1) 712 CHECKFLAGS(D2C,D2) 713 CHECKFLAGS(D2P,D2) 714 CHECKFLAGS(S1C,S1) 715 CHECKFLAGS(S1P,S1) 716 CHECKFLAGS(S2C,S2) 717 CHECKFLAGS(S2P,S2) 718 719 hdata.data.named.typesofobs = buffer; 720 i = 1+snprintf(buffer, buffersize, 721 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer); 722 if(Parser->numdatatypes>9) 723 { 724 i += snprintf(buffer+i-1, buffersize, 725 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6); 726 } 727 buffer += i; buffersize -= i; 728 } 729 730 { 731 struct converttimeinfo cti; 732 converttime(&cti, Parser->Data.week, 733 int(floor(Parser->Data.timeofweek/1000.0))); 734 hdata.data.named.timeoffirstobs = buffer; 735 i = 1+snprintf(buffer, buffersize, 736 " %4d %2d %2d %2d %2d %10.7f GPS " 737 "TIME OF FIRST OBS", cti.year%100, cti.month, cti.day, cti.hour, 738 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0)); 739 740 buffer += i; buffersize -= i; 741 } 742 743 hdata.numheaders = 11; 744 745 if(Parser->headerfile) 746 { 747 FILE *fh; 748 if((fh = fopen(Parser->headerfile, "r"))) 749 { 750 int siz; 751 char *lastblockstart; 752 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0) 753 { 754 buffer[siz] = '\n'; 755 if(siz == buffersize) 756 { 757 fprintf(stderr, "Header file is too large. Only %d bytes read.", 758 siz); 759 } 760 /* scan the file line by line and enter the entries in the list */ 761 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */ 762 /* overwrites entries, except for comments */ 763 lastblockstart = buffer; 764 for(i = 0; i < siz; ++i) 765 { 766 if(buffer[i] == '\n') 767 { /* we found a line */ 768 char *end; 769 while(buffer[i+1] == '\r') 770 ++i; /* skip \r in case there are any */ 771 end = buffer+i; 772 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n') 773 *(end--) = 0; 774 if(end-lastblockstart < 60+5) /* short line */ 775 fprintf(stderr, "Short Header line '%s' ignored.\n", lastblockstart); 776 else 777 { 778 int pos; 779 if(!strcmp("COMMENT", lastblockstart+60)) 780 pos = hdata.numheaders; 781 else 782 { 783 for(pos = 0; pos < hdata.numheaders; ++pos) 784 { 785 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60)) 786 break; 787 } 788 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60) 789 || !strcmp("TIME OF FIRST OBS", lastblockstart+60)) 790 { 791 fprintf(stderr, "Overwriting header '%s' is dangerous.\n", 792 lastblockstart+60); 793 } 794 } 795 if(pos >= MAXHEADERLINES) 796 { 797 fprintf(stderr, 798 "Maximum number of header lines of %d reached.\n", 799 MAXHEADERLINES); 800 } 801 else if(!strcmp("END OF HEADER", lastblockstart+60)) 802 { 803 fprintf(stderr, "End of header ignored.\n"); 804 } 805 else 806 { 807 hdata.data.unnamed[pos] = lastblockstart; 808 if(pos == hdata.numheaders) 809 ++hdata.numheaders; 810 } 811 } 812 lastblockstart = buffer+i+1; 813 } 814 } 815 } 816 else 817 { 818 fprintf(stderr, "Could not read data from headerfile '%s'.\n", 819 Parser->headerfile); 820 } 821 fclose(fh); 822 } 823 else 824 { 825 fprintf(stderr, "Could not open header datafile '%s'.\n", 826 Parser->headerfile); 827 } 828 } 829 830 for(i = 0; i < hdata.numheaders; ++i) 831 printf("%s\n", hdata.data.unnamed[i]); 832 printf(" " 833 "END OF HEADER\n"); 834 } 835 836 /* let the output complete a block if necessary */ 837 static void signalhandler(int sig) 838 { 839 if(!stop) 840 { 841 fprintf(stderr, "Stop signal number %d received. " 842 "Trying to terminate gentle.\n", sig); 843 stop = 1; 844 alarm(1); 37 // 38 //////////////////////////////////////////////////////////////////////////// 39 void rtcm3::Decode(char* buffer, int bufLen) { 40 for (int ii = 0; ii < bufLen; ii++) { 41 HandleByte(&_Parser, buffer[ii]); 845 42 } 846 43 } 847 848 static void signalhandler_alarm(int sig)849 {850 fprintf(stderr, "Programm forcefully terminated.\n");851 exit(1);852 }853 854 static void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)855 {856 Parser->Message[Parser->MessageSize++] = byte;857 if(Parser->MessageSize >= Parser->NeedBytes)858 {859 int r;860 while((r = RTCM3Parser(Parser)))861 {862 int i, j, o;863 struct converttimeinfo cti;864 865 if(!Parser->init)866 {867 HandleHeader(Parser);868 Parser->init = 1;869 }870 if(r == 2 && !Parser->validwarning)871 {872 printf("No valid RINEX! All values are modulo 299792.458!"873 " COMMENT\n");874 Parser->validwarning = 1;875 }876 877 converttime(&cti, Parser->Data.week,878 floor(Parser->Data.timeofweek/1000.0));879 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",880 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second881 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);882 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)883 {884 if(Parser->Data.satellites[i] <= PRN_GPS_END)885 printf("G%02d", Parser->Data.satellites[i]);886 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START887 && Parser->Data.satellites[i] <= PRN_GLONASS_END)888 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));889 else890 printf("%3d", Parser->Data.satellites[i]);891 }892 printf("\n");893 o = 12;894 j = Parser->Data.numsats - 12;895 while(j > 0)896 {897 printf(" ");898 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)899 {900 if(Parser->Data.satellites[i] <= PRN_GPS_END)901 printf("G%02d", Parser->Data.satellites[i]);902 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START903 && Parser->Data.satellites[i] <= PRN_GLONASS_END)904 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));905 else906 printf("%3d", Parser->Data.satellites[i]);907 }908 printf("\n");909 j -= 12;910 o += 12;911 }912 for(i = 0; i < Parser->Data.numsats; ++i)913 {914 for(j = 0; j < Parser->numdatatypes; ++j)915 {916 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])917 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])918 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))919 { /* no or illegal data */920 printf(" ");921 }922 else923 {924 char lli = ' ';925 char snr = ' ';926 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))927 {928 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)929 lli = '1';930 snr = '0'+Parser->Data.snrL1[i];931 }932 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))933 {934 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)935 lli = '1';936 snr = '0'+Parser->Data.snrL2[i];937 }938 printf("%14.3f%c%c",939 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);940 }941 if(j%5 == 4 || j == Parser->numdatatypes-1)942 printf("\n");943 }944 }945 }946 }947 }948 949 int main(int argc, char **argv)950 {951 struct Args args;952 struct RTCM3ParserData Parser;953 954 setbuf(stdout, 0);955 setbuf(stdin, 0);956 setbuf(stderr, 0);957 958 {959 char *a;960 int i=0;961 for(a = revisionstr+11; *a && *a != ' '; ++a)962 revisionstr[i++] = *a;963 revisionstr[i] = 0;964 }965 966 signal(SIGINT, signalhandler);967 signal(SIGALRM,signalhandler_alarm);968 signal(SIGQUIT,signalhandler);969 signal(SIGTERM,signalhandler);970 signal(SIGPIPE,signalhandler);971 memset(&Parser, 0, sizeof(Parser));972 {973 time_t tim;974 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);975 Parser.GPSWeek = tim/(7*24*60*60);976 Parser.GPSTOW = tim%(7*24*60*60);977 }978 979 if(getargs(argc, argv, &args))980 {981 int i, sockfd, numbytes;982 char buf[MAXDATASIZE];983 struct hostent *he;984 struct sockaddr_in their_addr; /* connector's address information */985 986 Parser.headerfile = args.headerfile;987 988 if(!(he=gethostbyname(args.server)))989 {990 perror("gethostbyname");991 exit(1);992 }993 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)994 {995 perror("socket");996 exit(1);997 }998 their_addr.sin_family = AF_INET; /* host byte order */999 their_addr.sin_port = htons(args.port); /* short, network byte order */1000 their_addr.sin_addr = *((struct in_addr *)he->h_addr);1001 memset(&(their_addr.sin_zero), '\0', 8);1002 if(connect(sockfd, (struct sockaddr *)&their_addr,1003 sizeof(struct sockaddr)) == -1)1004 {1005 perror("connect");1006 exit(1);1007 }1008 1009 if(!args.data)1010 {1011 i = snprintf(buf, MAXDATASIZE,1012 "GET / HTTP/1.0\r\n"1013 "User-Agent: %s/%s\r\n"1014 #ifdef UNUSED1015 "Accept: */*\r\n"1016 "Connection: close\r\n"1017 #endif1018 "\r\n"1019 , AGENTSTRING, revisionstr);1020 }1021 else1022 {1023 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */1024 "GET /%s HTTP/1.0\r\n"1025 "User-Agent: %s/%s\r\n"1026 #ifdef UNUSED1027 "Accept: */*\r\n"1028 "Connection: close\r\n"1029 #endif1030 "Authorization: Basic "1031 , args.data, AGENTSTRING, revisionstr);1032 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */1033 {1034 fprintf(stderr, "Requested data too long\n");1035 exit(1);1036 }1037 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);1038 if(i > MAXDATASIZE-5)1039 {1040 fprintf(stderr, "Username and/or password too long\n");1041 exit(1);1042 }1043 snprintf(buf+i, 5, "\r\n\r\n");1044 i += 5;1045 }1046 if(send(sockfd, buf, (size_t)i, 0) != i)1047 {1048 perror("send");1049 exit(1);1050 }1051 if(args.data)1052 {1053 int k = 0;1054 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)1055 {1056 if(!k)1057 {1058 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))1059 {1060 fprintf(stderr, "Could not get the requested data: ");1061 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)1062 {1063 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');1064 }1065 fprintf(stderr, "\n");1066 exit(1);1067 }1068 ++k;1069 }1070 else1071 {1072 int z;1073 for(z = 0; z < numbytes && !stop; ++z)1074 HandleByte(&Parser, buf[z]);1075 }1076 }1077 }1078 else1079 {1080 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)1081 {1082 fwrite(buf, (size_t)numbytes, 1, stdout);1083 }1084 }1085 1086 close(sockfd);1087 }1088 return 0;1089 }
Note:
See TracChangeset
for help on using the changeset viewer.