- Timestamp:
- Oct 8, 2007, 2:51:24 PM (17 years ago)
- Location:
- trunk/rtcm3torinex
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/rtcm3torinex/rtcm3torinex.c
r498 r502 1 1 /* 2 2 Converter for RTCM3 data to RINEX. 3 $Id: rtcm3torinex.c,v 1.2 1 2007/08/14 10:14:37stoecker Exp $4 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@ euronik.eu>3 $Id: rtcm3torinex.c,v 1.22 2007/10/01 11:07:08 stoecker Exp $ 4 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@alberding.eu> 5 5 6 6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as … … 51 51 52 52 /* CVS revision and version */ 53 static char revisionstr[] = "$Revision: 1.2 1$";53 static char revisionstr[] = "$Revision: 1.22 $"; 54 54 55 55 #ifndef COMPILEDATE … … 139 139 } 140 140 141 /* extract floating value from data stream 142 b = variable to store result, a = number of bits */ 143 #define GETFLOAT(b, a, c) \ 144 { \ 145 LOADBITS(a) \ 146 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \ 147 numbits -= (a); \ 148 } 149 150 /* extract signed floating value from data stream 151 b = variable to store result, a = number of bits */ 152 #define GETFLOATSIGN(b, a, c) \ 153 { \ 154 LOADBITS(a) \ 155 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \ 156 numbits -= (a); \ 157 } 158 141 159 /* extract bits from data stream 142 160 b = variable to store result, a = number of bits */ … … 146 164 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \ 147 165 numbits -= (a); \ 166 } 167 168 #define GETFLOATSIGNM(b, a, c) \ 169 { int l; \ 170 LOADBITS(a) \ 171 l = (bitfield<<(64-numbits))>>(64-1); \ 172 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \ 173 numbits -= (a); \ 174 if(l) b *= -1.0; \ 148 175 } 149 176 … … 209 236 } 210 237 211 static void updatetime(int *week, int *tow, int tk )238 static void updatetime(int *week, int *tow, int tk, int fixnumleap) 212 239 { 213 int y,m,d,k,l ;240 int y,m,d,k,l, nul; 214 241 unsigned int j = *week*(7*24*60*60) + *tow + 5*24*60*60+3*60*60; 215 242 int glo_daynumber = 0, glo_timeofday; … … 227 254 j -= 24*60*60; 228 255 glo_daynumber -= 16*365+4-d; 229 glo_timeofday = j-gnumleap(y, m, d); 256 nul = gnumleap(y, m, d); 257 glo_timeofday = j-nul; 230 258 231 259 if(tk < 5*60*1000 && glo_timeofday > 23*60*60) … … 234 262 *tow -= 24*60*60; 235 263 *tow += tk/1000-glo_timeofday; 264 if(fixnumleap) 265 *tow -= nul; 236 266 if(*tow < 0) {*tow += 24*60*60*7; --*week; } 237 267 if(*tow >= 24*60*60*7) {*tow -= 24*60*60*7; ++*week; } … … 254 284 switch(type) 255 285 { 286 case 1019: 287 { 288 struct gpsephemeris *ge; 289 int sv; 290 291 ge = &handle->ephemerisGPS; 292 memset(ge, 0, sizeof(*ge)); 293 294 GETBITS(sv, 6) 295 ge->satellite = (sv < 40 ? sv : sv+80); 296 GETBITS(ge->GPSweek, 10) 297 ge->GPSweek += 1024; 298 GETBITS(ge->URAindex, 4) 299 GETBITS(sv, 2) 300 if(sv & 1) 301 ge->flags |= GPSEPHF_L2PCODE; 302 if(sv & 2) 303 ge->flags |= GPSEPHF_L2CACODE; 304 GETFLOATSIGN(ge->IDOT, 14, PI/(double)(1<<30)/(double)(1<<13)) 305 GETBITS(ge->IODE, 8) 306 GETBITS(ge->TOC, 16) 307 ge->TOC <<= 4; 308 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25)) 309 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13)) 310 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1)) 311 GETBITS(ge->IODC, 10) 312 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5)) 313 GETFLOATSIGN(ge->Delta_n, 16, PI/(double)(1<<30)/(double)(1<<13)) 314 GETFLOATSIGN(ge->M0, 32, PI/(double)(1<<30)/(double)(1<<1)) 315 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29)) 316 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3)) 317 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29)) 318 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19)) 319 GETBITS(ge->TOE, 16) 320 ge->TOE <<= 4; 321 322 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29)) 323 GETFLOATSIGN(ge->OMEGA0, 32, PI/(double)(1<<30)/(double)(1<<1)) 324 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29)) 325 GETFLOATSIGN(ge->i0, 32, PI/(double)(1<<30)/(double)(1<<1)) 326 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5)) 327 GETFLOATSIGN(ge->omega, 32, PI/(double)(1<<30)/(double)(1<<1)) 328 GETFLOATSIGN(ge->OMEGADOT, 24, PI/(double)(1<<30)/(double)(1<<13)) 329 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1)) 330 GETBITS(ge->SVhealth, 6) 331 GETBITS(sv, 1) 332 if(sv) 333 ge->flags |= GPSEPHF_L2PCODEDATA; 334 335 ret = 1019; 336 } 337 break; 338 case 1020: 339 { 340 struct glonassephemeris *ge; 341 int i; 342 343 ge = &handle->ephemerisGLONASS; 344 memset(ge, 0, sizeof(*ge)); 345 346 ge->flags |= GLOEPHF_PAVAILABLE; 347 GETBITS(ge->almanac_number, 6) 348 GETBITS(i, 5) 349 ge->frequency_number = i-7; 350 GETBITS(i, 1) 351 if(i) 352 ge->flags |= GLOEPHF_ALMANACHEALTHY; 353 GETBITS(i, 1) 354 if(i) 355 ge->flags |= GLOEPHF_ALMANACHEALTHOK; 356 GETBITS(i, 2) 357 if(i & 1) 358 ge->flags |= GLOEPHF_P10TRUE; 359 if(i & 2) 360 ge->flags |= GLOEPHF_P11TRUE; 361 GETBITS(i, 5) 362 ge->tk = i*60*60; 363 GETBITS(i, 6) 364 ge->tk += i*60; 365 GETBITS(i, 1) 366 ge->tk += i*30; 367 GETBITS(i, 1) 368 if(i) 369 ge->flags |= GLOEPHF_UNHEALTHY; 370 GETBITS(i, 1) 371 if(i) 372 ge->flags |= GLOEPHF_P2TRUE; 373 GETBITS(i, 7) 374 ge->tb = i*15*60; 375 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20)) 376 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11)) 377 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30)) 378 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20)) 379 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11)) 380 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30)) 381 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20)) 382 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11)) 383 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30)) 384 GETBITS(i, 1) 385 if(i) 386 ge->flags |= GLOEPHF_P3TRUE; 387 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10)) 388 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */ 389 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */ 390 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */ 391 GETBITS(ge->E, 5) 392 /* GETBITS(b, 1) / * GLONASS-M P4 */ 393 /* GETBITS(b, 4) / * GLONASS-M Ft */ 394 /* GETBITS(b, 11) / * GLONASS-M Nt */ 395 /* GETBITS(b, 2) / * GLONASS-M M */ 396 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */ 397 /* GETBITS(b, 11) / * GLONASS-M Na */ 398 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */ 399 /* GETBITS(b, 5) / * GLONASS-M N4 */ 400 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */ 401 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */ 402 ge->GPSWeek = handle->GPSWeek; 403 ge->GPSTOW = handle->GPSTOW; 404 ret = 1020; 405 } 406 break; 256 407 case 1001: case 1002: case 1003: case 1004: 257 408 if(handle->GPSWeek) … … 429 580 GETBITS(i,27) /* tk */ 430 581 431 updatetime(&handle->GPSWeek, &handle->GPSTOW, i );582 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); 432 583 i = handle->GPSTOW*1000; 433 584 if(gnss->week && (gnss->timeofweek != i || gnss->week … … 597 748 const char *wavelength; 598 749 const char *typesofobs; /* should not be modified outside */ 750 const char *typesofobsG; /* should not be modified outside */ 751 const char *typesofobsR; /* should not be modified outside */ 752 const char *typesofobsS; /* should not be modified outside */ 599 753 const char *timeoffirstobs; /* should not be modified outside */ 600 754 }; … … 659 813 } 660 814 815 static int HandleRunBy(char *buffer, int buffersize, const char **u) 816 { 817 const char *user; 818 time_t t; 819 struct tm * t2; 820 821 #ifdef NO_RTCM3_MAIN 822 if(revisionstr[0] == '$') 823 { 824 char *a; 825 int i=0; 826 for(a = revisionstr+11; *a && *a != ' '; ++a) 827 revisionstr[i++] = *a; 828 revisionstr[i] = 0; 829 } 830 #endif 831 832 user= getenv("USER"); 833 if(!user) user = ""; 834 t = time(&t); 835 t2 = gmtime(&t); 836 if(u) *u = user; 837 return 1+snprintf(buffer, buffersize, 838 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d " 839 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year, 840 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min); 841 } 842 661 843 #define NUMSTARTSKIP 3 662 844 void HandleHeader(struct RTCM3ParserData *Parser) … … 668 850 int i; 669 851 670 hdata.data.named.version = 671 " 2.11 OBSERVATION DATA M (Mixed)" 672 " RINEX VERSION / TYPE"; 852 hdata.data.named.version = buffer; 853 i = 1+snprintf(buffer, buffersize, 854 "%9.2f OBSERVATION DATA M (Mixed)" 855 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11); 856 buffer += i; buffersize -= i; 673 857 674 858 { 675 859 const char *str; 676 time_t t;677 struct tm * t2;678 679 #ifdef NO_RTCM3_MAIN680 if(revisionstr[0] == '$')681 {682 char *a;683 int i=0;684 for(a = revisionstr+11; *a && *a != ' '; ++a)685 revisionstr[i++] = *a;686 revisionstr[i] = 0;687 }688 #endif689 690 str = getenv("USER");691 if(!str) str = "";692 t = time(&t);693 t2 = gmtime(&t);694 860 hdata.data.named.pgm = buffer; 695 i = 1+snprintf(buffer, buffersize, 696 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d " 697 "PGM / RUN BY / DATE", 698 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour, 699 t2->tm_min); 861 i = HandleRunBy(buffer, buffersize, &str); 700 862 buffer += i; buffersize -= i; 701 702 863 hdata.data.named.observer = buffer; 703 864 i = 1+snprintf(buffer, buffersize, … … 727 888 "ANTENNA: DELTA H/E/N"; 728 889 729 hdata.data.named.wavelength = 890 hdata.data.named.wavelength = Parser->rinex3 ? 0 : 730 891 " 1 1 " 731 892 "WAVELENGTH FACT L1/2"; 732 893 894 if(Parser->rinex3) 895 { 896 #define CHECKFLAGSNEW(a, b, c) \ 897 if(flags & GNSSDF_##b##DATA) \ 898 { \ 899 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \ 900 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \ 901 ++Parser->numdatatypes##a; \ 902 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#c); \ 903 tbufferpos += 4; \ 904 } 905 906 int flags = Parser->startflags; 907 char tbuffer[6*RINEXENTRY_NUMBER+1]; 908 int tbufferpos = 0; 909 for(i = 0; i < Parser->Data.numsats; ++i) 910 flags |= Parser->Data.dataflags[i]; 911 912 CHECKFLAGSNEW(GPS, C1, C1C) 913 CHECKFLAGSNEW(GPS, L1C, L1C) 914 CHECKFLAGSNEW(GPS, D1C, D1C) 915 CHECKFLAGSNEW(GPS, S1C, S1C) 916 CHECKFLAGSNEW(GPS, P1, C1P) 917 CHECKFLAGSNEW(GPS, L1P, L1P) 918 CHECKFLAGSNEW(GPS, D1P, D1P) 919 CHECKFLAGSNEW(GPS, S1P, S1P) 920 921 hdata.data.named.typesofobsS = buffer; 922 i = 1+snprintf(buffer, buffersize, 923 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer); 924 buffer += i; buffersize -= i; 925 926 CHECKFLAGSNEW(GPS, P2, C2P) 927 CHECKFLAGSNEW(GPS, L2P, L2P) 928 CHECKFLAGSNEW(GPS, D2P, D2P) 929 CHECKFLAGSNEW(GPS, S2P, S2P) 930 CHECKFLAGSNEW(GPS, C2, C2X) 931 CHECKFLAGSNEW(GPS, L2C, L2X) 932 CHECKFLAGSNEW(GPS, D2C, D2X) 933 CHECKFLAGSNEW(GPS, S2C, S2X) 934 935 hdata.data.named.typesofobsG = buffer; 936 i = 1+snprintf(buffer, buffersize, 937 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer); 938 if(Parser->numdatatypesGPS>13) 939 { 940 i += snprintf(buffer+i-1, buffersize, 941 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4); 942 } 943 buffer += i; buffersize -= i; 944 945 tbufferpos = 0; 946 947 CHECKFLAGSNEW(GLO, C1, C1C) 948 CHECKFLAGSNEW(GLO, L1C, L1C) 949 CHECKFLAGSNEW(GLO, D1C, D1C) 950 CHECKFLAGSNEW(GLO, S1C, S1C) 951 CHECKFLAGSNEW(GLO, P1, C1P) 952 CHECKFLAGSNEW(GLO, L1P, L1P) 953 CHECKFLAGSNEW(GLO, D1P, D1P) 954 CHECKFLAGSNEW(GLO, S1P, S1P) 955 CHECKFLAGSNEW(GLO, P2, C2P) 956 CHECKFLAGSNEW(GLO, L2P, L2P) 957 CHECKFLAGSNEW(GLO, D2P, D2P) 958 CHECKFLAGSNEW(GLO, S2P, S2P) 959 CHECKFLAGSNEW(GLO, C2, C2C) 960 CHECKFLAGSNEW(GLO, L2C, L2C) 961 CHECKFLAGSNEW(GLO, D2C, D2C) 962 CHECKFLAGSNEW(GLO, S2C, S2C) 963 964 hdata.data.named.typesofobsR = buffer; 965 i = 1+snprintf(buffer, buffersize, 966 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer); 967 if(Parser->numdatatypesGLO>13) 968 { 969 i += snprintf(buffer+i-1, buffersize, 970 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4); 971 } 972 buffer += i; buffersize -= i; 973 } 974 else 733 975 { 734 976 #define CHECKFLAGS(a, b) \ … … 737 979 if(data[RINEXENTRY_##b##DATA]) \ 738 980 { \ 739 Parser->dataflag 2[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \740 Parser->datapos 2[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \981 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \ 982 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \ 741 983 } \ 742 984 else \ 743 985 { \ 744 Parser->dataflag[Parser->numdatatypes ] = GNSSDF_##a##DATA; \745 Parser->datapos[Parser->numdatatypes ] = GNSSENTRY_##a##DATA; \746 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypes ; \986 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \ 987 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \ 988 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \ 747 989 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \ 748 990 tbufferpos += 6; \ … … 778 1020 hdata.data.named.typesofobs = buffer; 779 1021 i = 1+snprintf(buffer, buffersize, 780 "%6 i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);781 if(Parser->numdatatypes >9)1022 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer); 1023 if(Parser->numdatatypesGPS>9) 782 1024 { 783 1025 i += snprintf(buffer+i-1, buffersize, … … 792 1034 (int)floor(Parser->Data.timeofweek/1000.0)); 793 1035 hdata.data.named.timeoffirstobs = buffer; 794 1036 i = 1+snprintf(buffer, buffersize, 795 1037 " %4d %2d %2d %2d %2d %10.7f GPS " 796 1038 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour, … … 800 1042 } 801 1043 802 hdata.numheaders = 1 1;1044 hdata.numheaders = 14; 803 1045 804 1046 if(Parser->headerfile) … … 888 1130 #ifndef NO_RTCM3_MAIN 889 1131 for(i = 0; i < hdata.numheaders; ++i) 890 RTCM3Text("%s\n", hdata.data.unnamed[i]); 1132 { 1133 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0]) 1134 RTCM3Text("%s\n", hdata.data.unnamed[i]); 1135 } 891 1136 RTCM3Text(" " 892 1137 "END OF HEADER\n"); … … 894 1139 } 895 1140 1141 static void ConvLine(FILE *file, const char *fmt, ...) 1142 { 1143 char buffer[100], *b; 1144 va_list v; 1145 va_start(v, fmt); 1146 vsnprintf(buffer, sizeof(buffer), fmt, v); 1147 for(b = buffer; *b; ++b) 1148 { 1149 if(*b == 'e') *b = 'D'; 1150 } 1151 fprintf(file, "%s", buffer); 1152 va_end(v); 1153 } 1154 896 1155 void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte) 897 1156 { … … 902 1161 while((r = RTCM3Parser(Parser))) 903 1162 { 904 int i, j, o; 905 struct converttimeinfo cti; 906 907 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */ 908 { 909 ++Parser->init; 910 911 if(Parser->init == NUMSTARTSKIP) 912 HandleHeader(Parser); 1163 if(r == 1020 || r == 1019) 1164 { 1165 FILE *file = 0; 1166 1167 if(Parser->rinex3 && !(file = Parser->gpsfile)) 1168 { 1169 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris; 1170 if(n) 1171 { 1172 if(!(Parser->gpsfile = fopen(n, "w"))) 1173 { 1174 RTCM3Error("Could not open ephemeris output file.\n"); 1175 } 1176 else 1177 { 1178 char buffer[100]; 1179 fprintf(Parser->gpsfile, 1180 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", ""); 1181 HandleRunBy(buffer, sizeof(buffer), 0); 1182 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, ""); 1183 } 1184 Parser->gpsephemeris = 0; 1185 Parser->glonassephemeris = 0; 1186 file = Parser->gpsfile; 1187 } 1188 } 913 1189 else 914 1190 { 1191 if(r == 1020) 1192 { 1193 if(Parser->glonassephemeris) 1194 { 1195 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w"))) 1196 { 1197 RTCM3Error("Could not open GLONASS ephemeris output file.\n"); 1198 } 1199 else 1200 { 1201 char buffer[100]; 1202 fprintf(Parser->glonassfile, 1203 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", ""); 1204 HandleRunBy(buffer, sizeof(buffer), 0); 1205 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, ""); 1206 } 1207 Parser->glonassephemeris = 0; 1208 } 1209 file = Parser->glonassfile; 1210 } 1211 else if(r == 1019) 1212 { 1213 if(Parser->gpsephemeris) 1214 { 1215 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w"))) 1216 { 1217 RTCM3Error("Could not open GPS ephemeris output file.\n"); 1218 } 1219 else 1220 { 1221 char buffer[100]; 1222 fprintf(Parser->gpsfile, 1223 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", ""); 1224 HandleRunBy(buffer, sizeof(buffer), 0); 1225 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, ""); 1226 } 1227 Parser->gpsephemeris = 0; 1228 } 1229 file = Parser->gpsfile; 1230 } 1231 } 1232 if(file) 1233 { 1234 if(r == 1020) 1235 { 1236 struct glonassephemeris *e = &Parser->ephemerisGLONASS; 1237 int w = e->GPSWeek, tow = e->GPSTOW, i; 1238 struct converttimeinfo cti; 1239 1240 updatetime(&w, &tow, e->tb*1000, 1); 1241 converttime(&cti, w, tow); 1242 1243 i = e->tk-3*60*60; if(i < 0) i += 86400; 1244 1245 if(Parser->rinex3) 1246 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n", 1247 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute, 1248 cti.second, -e->tau, e->gamma, (double) i); 1249 else 1250 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n", 1251 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute, 1252 (double) cti.second, -e->tau, e->gamma, (double) i); 1253 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos, 1254 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0); 1255 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos, 1256 e->y_velocity, e->y_acceleration, (double) e->frequency_number); 1257 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos, 1258 e->z_velocity, e->z_acceleration, (double) e->E); 1259 } 1260 else /* if(r == 1019) */ 1261 { 1262 struct gpsephemeris *e = &Parser->ephemerisGPS; 1263 double d; /* temporary variable */ 1264 unsigned long int i; /* temporary variable */ 1265 struct converttimeinfo cti; 1266 converttime(&cti, e->GPSweek, e->TOC); 1267 1268 if(Parser->rinex3) 1269 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n", 1270 e->satellite, cti.year, cti.month, cti.day, cti.hour, 1271 cti.minute, cti.second, e->clock_bias, e->clock_drift, 1272 e->clock_driftrate); 1273 else 1274 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n", 1275 e->satellite, cti.year%100, cti.month, cti.day, cti.hour, 1276 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift, 1277 e->clock_driftrate); 1278 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE, 1279 e->Crs, e->Delta_n, e->M0); 1280 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc, 1281 e->e, e->Cus, e->sqrt_A); 1282 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", 1283 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis); 1284 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0, 1285 e->Crc, e->omega, e->OMEGADOT); 1286 d = 0; 1287 i = e->flags; 1288 if(i & GPSEPHF_L2CACODE) 1289 d += 2.0; 1290 if(i & GPSEPHF_L2PCODE) 1291 d += 1.0; 1292 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d, 1293 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0); 1294 if(e->URAindex <= 6) /* URA index */ 1295 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0; 1296 else 1297 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0; 1298 /* 15 indicates not to use satellite. We can't handle this special 1299 case, so we create a high "non"-accuracy value. */ 1300 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d, 1301 ((double) e->SVhealth), e->TGD, ((double) e->IODC)); 1302 1303 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0); 1304 /* TOW */ 1305 } 1306 } 1307 } 1308 else 1309 { 1310 int i, j, o; 1311 struct converttimeinfo cti; 1312 1313 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */ 1314 { 1315 ++Parser->init; 1316 1317 if(Parser->init == NUMSTARTSKIP) 1318 HandleHeader(Parser); 1319 else 1320 { 1321 for(i = 0; i < Parser->Data.numsats; ++i) 1322 Parser->startflags |= Parser->Data.dataflags[i]; 1323 continue; 1324 } 1325 } 1326 if(r == 2 && !Parser->validwarning) 1327 { 1328 RTCM3Text("No valid RINEX! All values are modulo 299792.458!" 1329 " COMMENT\n"); 1330 Parser->validwarning = 1; 1331 } 1332 1333 converttime(&cti, Parser->Data.week, 1334 (int)floor(Parser->Data.timeofweek/1000.0)); 1335 if(Parser->rinex3) 1336 { 1337 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n", 1338 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second 1339 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats); 915 1340 for(i = 0; i < Parser->Data.numsats; ++i) 916 Parser->startflags |= Parser->Data.dataflags[i]; 917 continue; 918 } 919 } 920 if(r == 2 && !Parser->validwarning) 921 { 922 RTCM3Text("No valid RINEX! All values are modulo 299792.458!" 923 " COMMENT\n"); 924 Parser->validwarning = 1; 925 } 926 927 converttime(&cti, Parser->Data.week, 928 (int)floor(Parser->Data.timeofweek/1000.0)); 929 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d", 930 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second 931 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats); 932 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i) 933 { 934 if(Parser->Data.satellites[i] <= PRN_GPS_END) 935 RTCM3Text("G%02d", Parser->Data.satellites[i]); 936 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START 937 && Parser->Data.satellites[i] <= PRN_GLONASS_END) 938 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1)); 939 else if(Parser->Data.satellites[i] >= PRN_WAAS_START 940 && Parser->Data.satellites[i] <= PRN_WAAS_END) 941 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20); 1341 { 1342 int glo = 0; 1343 if(Parser->Data.satellites[i] <= PRN_GPS_END) 1344 RTCM3Text("G%02d", Parser->Data.satellites[i]); 1345 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START 1346 && Parser->Data.satellites[i] <= PRN_GLONASS_END) 1347 { 1348 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1)); 1349 glo = 1; 1350 } 1351 else if(Parser->Data.satellites[i] >= PRN_WAAS_START 1352 && Parser->Data.satellites[i] <= PRN_WAAS_END) 1353 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20); 1354 else 1355 RTCM3Text("%3d", Parser->Data.satellites[i]); 1356 1357 if(glo) 1358 { 1359 for(j = 0; j < Parser->numdatatypesGLO; ++j) 1360 { 1361 int df = Parser->dataflagGLO[j]; 1362 int pos = Parser->dataposGLO[j]; 1363 if((Parser->Data.dataflags[i] & df) 1364 && !isnan(Parser->Data.measdata[i][pos]) 1365 && !isinf(Parser->Data.measdata[i][pos])) 1366 { 1367 char lli = ' '; 1368 char snr = ' '; 1369 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA)) 1370 { 1371 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1) 1372 lli = '1'; 1373 snr = '0'+Parser->Data.snrL1[i]; 1374 } 1375 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA)) 1376 { 1377 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2) 1378 lli = '1'; 1379 snr = '0'+Parser->Data.snrL2[i]; 1380 } 1381 RTCM3Text("%14.3f%c%c", 1382 Parser->Data.measdata[i][pos],lli,snr); 1383 } 1384 else 1385 { /* no or illegal data */ 1386 RTCM3Text(" "); 1387 } 1388 } 1389 } 1390 else 1391 { 1392 for(j = 0; j < Parser->numdatatypesGPS; ++j) 1393 { 1394 int df = Parser->dataflagGPS[j]; 1395 int pos = Parser->dataposGPS[j]; 1396 if((Parser->Data.dataflags[i] & df) 1397 && !isnan(Parser->Data.measdata[i][pos]) 1398 && !isinf(Parser->Data.measdata[i][pos])) 1399 { 1400 char lli = ' '; 1401 char snr = ' '; 1402 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA)) 1403 { 1404 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1) 1405 lli = '1'; 1406 snr = '0'+Parser->Data.snrL1[i]; 1407 } 1408 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA)) 1409 { 1410 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2) 1411 lli = '1'; 1412 snr = '0'+Parser->Data.snrL2[i]; 1413 } 1414 RTCM3Text("%14.3f%c%c", 1415 Parser->Data.measdata[i][pos],lli,snr); 1416 } 1417 else 1418 { /* no or illegal data */ 1419 RTCM3Text(" "); 1420 } 1421 } 1422 } 1423 RTCM3Text("\n"); 1424 } 1425 } 942 1426 else 943 RTCM3Text("%3d", Parser->Data.satellites[i]); 944 } 945 RTCM3Text("\n"); 946 o = 12; 947 j = Parser->Data.numsats - 12; 948 while(j > 0) 949 { 950 RTCM3Text(" "); 951 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i) 952 { 953 if(Parser->Data.satellites[i] <= PRN_GPS_END) 954 RTCM3Text("G%02d", Parser->Data.satellites[i]); 955 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START 956 && Parser->Data.satellites[i] <= PRN_GLONASS_END) 957 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1)); 958 else if(Parser->Data.satellites[i] >= PRN_WAAS_START 959 && Parser->Data.satellites[i] <= PRN_WAAS_END) 960 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20); 961 else 962 RTCM3Text("%3d", Parser->Data.satellites[i]); 963 } 964 RTCM3Text("\n"); 965 j -= 12; 966 o += 12; 967 } 968 for(i = 0; i < Parser->Data.numsats; ++i) 969 { 970 for(j = 0; j < Parser->numdatatypes; ++j) 971 { 972 int v = 0; 973 int df = Parser->dataflag[j]; 974 int pos = Parser->datapos[j]; 975 if((Parser->Data.dataflags[i] & df) 976 && !isnan(Parser->Data.measdata[i][pos]) 977 && !isinf(Parser->Data.measdata[i][pos])) 978 { 979 v = 1; 980 } 981 else 982 { 983 df = Parser->dataflag2[j]; 984 pos = Parser->datapos2[j]; 985 986 if((Parser->Data.dataflags[i] & df) 987 && !isnan(Parser->Data.measdata[i][pos]) 988 && !isinf(Parser->Data.measdata[i][pos])) 989 { 990 v = 1; 991 } 992 } 993 994 if(!v) 995 { /* no or illegal data */ 996 RTCM3Text(" "); 997 } 998 else 999 { 1000 char lli = ' '; 1001 char snr = ' '; 1002 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA)) 1003 { 1004 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1) 1005 lli = '1'; 1006 snr = '0'+Parser->Data.snrL1[i]; 1007 } 1008 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA)) 1009 { 1010 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2) 1011 lli = '1'; 1012 snr = '0'+Parser->Data.snrL2[i]; 1013 } 1014 RTCM3Text("%14.3f%c%c", 1015 Parser->Data.measdata[i][pos],lli,snr); 1016 } 1017 if(j%5 == 4 || j == Parser->numdatatypes-1) 1427 { 1428 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d", 1429 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second 1430 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats); 1431 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i) 1432 { 1433 if(Parser->Data.satellites[i] <= PRN_GPS_END) 1434 RTCM3Text("G%02d", Parser->Data.satellites[i]); 1435 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START 1436 && Parser->Data.satellites[i] <= PRN_GLONASS_END) 1437 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1)); 1438 else if(Parser->Data.satellites[i] >= PRN_WAAS_START 1439 && Parser->Data.satellites[i] <= PRN_WAAS_END) 1440 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20); 1441 else 1442 RTCM3Text("%3d", Parser->Data.satellites[i]); 1443 } 1444 RTCM3Text("\n"); 1445 o = 12; 1446 j = Parser->Data.numsats - 12; 1447 while(j > 0) 1448 { 1449 RTCM3Text(" "); 1450 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i) 1451 { 1452 if(Parser->Data.satellites[i] <= PRN_GPS_END) 1453 RTCM3Text("G%02d", Parser->Data.satellites[i]); 1454 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START 1455 && Parser->Data.satellites[i] <= PRN_GLONASS_END) 1456 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1)); 1457 else if(Parser->Data.satellites[i] >= PRN_WAAS_START 1458 && Parser->Data.satellites[i] <= PRN_WAAS_END) 1459 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20); 1460 else 1461 RTCM3Text("%3d", Parser->Data.satellites[i]); 1462 } 1018 1463 RTCM3Text("\n"); 1464 j -= 12; 1465 o += 12; 1466 } 1467 for(i = 0; i < Parser->Data.numsats; ++i) 1468 { 1469 for(j = 0; j < Parser->numdatatypesGPS; ++j) 1470 { 1471 int v = 0; 1472 int df = Parser->dataflag[j]; 1473 int pos = Parser->datapos[j]; 1474 if((Parser->Data.dataflags[i] & df) 1475 && !isnan(Parser->Data.measdata[i][pos]) 1476 && !isinf(Parser->Data.measdata[i][pos])) 1477 { 1478 v = 1; 1479 } 1480 else 1481 { 1482 df = Parser->dataflagGPS[j]; 1483 pos = Parser->dataposGPS[j]; 1484 1485 if((Parser->Data.dataflags[i] & df) 1486 && !isnan(Parser->Data.measdata[i][pos]) 1487 && !isinf(Parser->Data.measdata[i][pos])) 1488 { 1489 v = 1; 1490 } 1491 } 1492 1493 if(!v) 1494 { /* no or illegal data */ 1495 RTCM3Text(" "); 1496 } 1497 else 1498 { 1499 char lli = ' '; 1500 char snr = ' '; 1501 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA)) 1502 { 1503 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1) 1504 lli = '1'; 1505 snr = '0'+Parser->Data.snrL1[i]; 1506 } 1507 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA)) 1508 { 1509 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2) 1510 lli = '1'; 1511 snr = '0'+Parser->Data.snrL2[i]; 1512 } 1513 RTCM3Text("%14.3f%c%c", 1514 Parser->Data.measdata[i][pos],lli,snr); 1515 } 1516 if(j%5 == 4 || j == Parser->numdatatypesGPS-1) 1517 RTCM3Text("\n"); 1518 } 1519 } 1019 1520 } 1020 1521 } … … 1024 1525 1025 1526 #ifndef NO_RTCM3_MAIN 1026 static char datestr[] = "$Date: 2007/ 08/14 10:14:37$";1527 static char datestr[] = "$Date: 2007/10/01 11:07:08 $"; 1027 1528 1028 1529 /* The string, which is send as agent in HTTP request */ … … 1085 1586 { 1086 1587 const char *server; 1087 int port; 1588 const char *port; 1589 int mode; 1088 1590 int timeout; 1591 int rinex3; 1089 1592 const char *user; 1090 1593 const char *password; 1594 const char *proxyhost; 1595 const char *proxyport; 1596 const char *nmea; 1091 1597 const char *data; 1092 1598 const char *headerfile; 1599 const char *gpsephemeris; 1600 const char *glonassephemeris; 1093 1601 }; 1094 1602 … … 1099 1607 #define LONG_OPT(a) a 1100 1608 static struct option opts[] = { 1101 { "data", required_argument, 0, 'd'}, 1102 { "server", required_argument, 0, 's'}, 1103 { "password", required_argument, 0, 'p'}, 1104 { "port", required_argument, 0, 'r'}, 1105 { "timeout", required_argument, 0, 't'}, 1106 { "header", required_argument, 0, 'f'}, 1107 { "user", required_argument, 0, 'u'}, 1108 { "help", no_argument, 0, 'h'}, 1609 { "data", required_argument, 0, 'd'}, 1610 { "server", required_argument, 0, 's'}, 1611 { "password", required_argument, 0, 'p'}, 1612 { "port", required_argument, 0, 'r'}, 1613 { "timeout", required_argument, 0, 't'}, 1614 { "header", required_argument, 0, 'f'}, 1615 { "user", required_argument, 0, 'u'}, 1616 { "gpsephemeris", required_argument, 0, 'E'}, 1617 { "glonassephemeris", required_argument, 0, 'G'}, 1618 { "rinex3", no_argument, 0, '3'}, 1619 { "proxyport", required_argument, 0, 'R'}, 1620 { "proxyhost", required_argument, 0, 'S'}, 1621 { "nmea", required_argument, 0, 'n'}, 1622 { "mode", required_argument, 0, 'M'}, 1623 { "help", no_argument, 0, 'h'}, 1109 1624 {0,0,0,0}}; 1110 1625 #endif 1111 #define ARGOPT "-d:s:p:r:t:f:u:h" 1626 #define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3" 1627 1628 enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END }; 1112 1629 1113 1630 static const char *geturl(const char *url, struct Args *args) … … 1125 1642 /* scan for mountpoint */ 1126 1643 args->data = Buffer; 1127 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)1644 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend) 1128 1645 *(Buffer++) = *(url++); 1129 1646 if(Buffer == args->data) … … 1138 1655 ++url; 1139 1656 args->user = Buffer; 1140 while(*url && *url != '@' && *url != ' :' && Buffer != Bufend)1657 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend) 1141 1658 *(Buffer++) = *(url++); 1142 1659 if(Buffer == args->user) … … 1149 1666 1150 1667 args->password = Buffer; 1151 while(*url && *url != '@' && Buffer != Bufend)1668 while(*url && *url != '@' && *url != ';' && Buffer != Bufend) 1152 1669 *(Buffer++) = *(url++); 1153 1670 if(Buffer == args->password) … … 1161 1678 { 1162 1679 ++url; 1163 args->server = Buffer; 1164 while(*url && *url != ':' && Buffer != Bufend) 1165 *(Buffer++) = *(url++); 1166 if(Buffer == args->server) 1167 return "Servername cannot be empty."; 1168 else if(Buffer >= Bufend-1) 1169 return "Parsing buffer too short."; 1170 *(Buffer++) = 0; 1680 if(*url != '@' && *url != ':') 1681 { 1682 args->server = Buffer; 1683 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend) 1684 *(Buffer++) = *(url++); 1685 if(Buffer == args->server) 1686 return "Servername cannot be empty."; 1687 else if(Buffer >= Bufend-1) 1688 return "Parsing buffer too short."; 1689 *(Buffer++) = 0; 1690 } 1171 1691 1172 1692 if(*url == ':') 1173 1693 { 1174 char *s2 = 0; 1175 args->port = strtol(++url, &s2, 10); 1176 if(*s2 || args->port <= 0 || args->port > 0xFFFF) 1177 return "Illegal port number."; 1178 url = s2; 1179 } 1694 ++url; 1695 args->port = Buffer; 1696 while(*url && *url != '@' && *url != ';' && Buffer != Bufend) 1697 *(Buffer++) = *(url++); 1698 if(Buffer == args->port) 1699 return "Port cannot be empty."; 1700 else if(Buffer >= Bufend-1) 1701 return "Parsing buffer too short."; 1702 *(Buffer++) = 0; 1703 } 1704 1705 if(*url == '@') /* proxy */ 1706 { 1707 ++url; 1708 args->proxyhost = Buffer; 1709 while(*url && *url != ':' && *url != ';' && Buffer != Bufend) 1710 *(Buffer++) = *(url++); 1711 if(Buffer == args->proxyhost) 1712 return "Proxy servername cannot be empty."; 1713 else if(Buffer >= Bufend-1) 1714 return "Parsing buffer too short."; 1715 *(Buffer++) = 0; 1716 1717 if(*url == ':') 1718 { 1719 ++url; 1720 args->proxyport = Buffer; 1721 while(*url && *url != ';' && Buffer != Bufend) 1722 *(Buffer++) = *(url++); 1723 if(Buffer == args->proxyport) 1724 return "Proxy port cannot be empty."; 1725 else if(Buffer >= Bufend-1) 1726 return "Parsing buffer too short."; 1727 *(Buffer++) = 0; 1728 } 1729 } 1730 } 1731 if(*url == ';') /* NMEA */ 1732 { 1733 args->nmea = ++url; 1734 while(*url) 1735 ++url; 1180 1736 } 1181 1737 … … 1191 1747 1192 1748 args->server = "www.euref-ip.net"; 1193 args->port = 2101;1749 args->port = "2101"; 1194 1750 args->timeout = 60; 1195 1751 args->user = ""; … … 1197 1753 args->data = 0; 1198 1754 args->headerfile = 0; 1755 args->gpsephemeris = 0; 1756 args->glonassephemeris = 0; 1757 args->rinex3 = 0; 1758 args->nmea = 0; 1759 args->proxyhost = 0; 1760 args->proxyport = "2101"; 1761 args->mode = AUTO; 1199 1762 help = 0; 1200 1763 … … 1213 1776 case 'd': args->data = optarg; break; 1214 1777 case 'f': args->headerfile = optarg; break; 1778 case 'E': args->gpsephemeris = optarg; break; 1779 case 'G': args->glonassephemeris = optarg; break; 1780 case 'r': args->port = optarg; break; 1781 case '3': args->rinex3 = 1; break; 1782 case 'S': args->proxyhost = optarg; break; 1783 case 'n': args->nmea = optarg; break; 1784 case 'R': args->proxyport = optarg; break; 1215 1785 case 'h': help=1; break; 1216 case 'r': 1217 args->port = strtoul(optarg, &t, 10); 1218 if((t && *t) || args->port < 1 || args->port > 65535) 1786 case 'M': 1787 args->mode = 0; 1788 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1")) 1789 args->mode = NTRIP1; 1790 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http")) 1791 args->mode = HTTP; 1792 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp")) 1793 args->mode = RTSP; 1794 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto")) 1795 args->mode = AUTO; 1796 else args->mode = atoi(optarg); 1797 if((args->mode == 0) || (args->mode >= END)) 1798 { 1799 fprintf(stderr, "Mode %s unknown\n", optarg); 1219 1800 res = 0; 1801 } 1220 1802 break; 1221 case 't': 1803 case 't': 1222 1804 args->timeout = strtoul(optarg, &t, 10); 1223 1805 if((t && *t) || args->timeout < 0) … … 1250 1832 datestr[10] = 0; 1251 1833 1252 if(!res || help) 1834 if(args->gpsephemeris && args->glonassephemeris && args->rinex3) 1835 { 1836 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"); 1837 res = 0; 1838 } 1839 else if(!res || help) 1253 1840 { 1254 1841 RTCM3Error("Version %s (%s) GPL" COMPILEDATE 1255 1842 "\nUsage: %s -s server -u user ...\n" 1256 " -d " LONG_OPT("--data ") "the requested data set\n" 1257 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n" 1258 " -s " LONG_OPT("--server ") "the server name or address\n" 1259 " -p " LONG_OPT("--password ") "the login password\n" 1260 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n" 1261 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n" 1262 " -u " LONG_OPT("--user ") "the user name\n" 1263 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n" 1843 " -d " LONG_OPT("--data ") "the requested data set\n" 1844 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n" 1845 " -s " LONG_OPT("--server ") "the server name or address\n" 1846 " -p " LONG_OPT("--password ") "the login password\n" 1847 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n" 1848 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n" 1849 " -u " LONG_OPT("--user ") "the user name\n" 1850 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n" 1851 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n" 1852 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n" 1853 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n" 1854 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n" 1855 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n" 1856 " -M " LONG_OPT("--mode ") "mode for data request\n" 1857 " Valid modes are:\n" 1858 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n" 1859 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n" 1860 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n" 1861 " 4, a, auto automatic detection (default)\n" 1862 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n" 1264 1863 , revisionstr, datestr, argv[0], argv[0]); 1265 1864 exit(1); … … 1279 1878 } 1280 1879 } 1880 1881 #define ALARMTIME (2*60) 1281 1882 1282 1883 /* for some reason we had to abort hard (maybe waiting for data */ … … 1297 1898 struct RTCM3ParserData Parser; 1298 1899 1299 struct timeval tv;1300 1301 1900 setbuf(stdout, 0); 1302 1901 setbuf(stdin, 0); … … 1326 1925 if(getargs(argc, argv, &args)) 1327 1926 { 1328 int i,sockfd, numbytes;1927 int sockfd, numbytes; 1329 1928 char buf[MAXDATASIZE]; 1929 struct sockaddr_in their_addr; /* connector's address information */ 1330 1930 struct hostent *he; 1331 struct sockaddr_in their_addr; /* connector's address information */ 1931 struct servent *se; 1932 const char *server, *port, *proxyserver = 0; 1933 char proxyport[6]; 1934 char *b; 1935 long i; 1936 struct timeval tv; 1937 1938 alarm(ALARMTIME); 1332 1939 1333 1940 Parser.headerfile = args.headerfile; 1334 1335 if(!(he=gethostbyname(args.server))) 1941 Parser.glonassephemeris = args.glonassephemeris; 1942 Parser.gpsephemeris = args.gpsephemeris; 1943 Parser.rinex3 = args.rinex3; 1944 1945 if(args.proxyhost) 1336 1946 { 1337 RTCM3Error("Function gethostbyname: %s\n", strerror(errno)); 1947 int p; 1948 if((i = strtol(args.port, &b, 10)) && (!b || !*b)) 1949 p = i; 1950 else if(!(se = getservbyname(args.port, 0))) 1951 { 1952 RTCM3Error("Can't resolve port %s.", args.port); 1953 exit(1); 1954 } 1955 else 1956 { 1957 p = ntohs(se->s_port); 1958 } 1959 snprintf(proxyport, sizeof(proxyport), "%d", p); 1960 port = args.proxyport; 1961 proxyserver = args.server; 1962 server = args.proxyhost; 1963 } 1964 else 1965 { 1966 server = args.server; 1967 port = args.port; 1968 } 1969 1970 memset(&their_addr, 0, sizeof(struct sockaddr_in)); 1971 if((i = strtol(port, &b, 10)) && (!b || !*b)) 1972 their_addr.sin_port = htons(i); 1973 else if(!(se = getservbyname(port, 0))) 1974 { 1975 RTCM3Error("Can't resolve port %s.", port); 1976 exit(1); 1977 } 1978 else 1979 { 1980 their_addr.sin_port = se->s_port; 1981 } 1982 if(!(he=gethostbyname(server))) 1983 { 1984 RTCM3Error("Server name lookup failed for '%s'.\n", server); 1338 1985 exit(1); 1339 1986 } 1340 1987 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 1341 1988 { 1342 RTCM3Error("Function socket: %s\n", strerror(errno));1989 perror("socket"); 1343 1990 exit(1); 1344 1991 } … … 1352 1999 } 1353 2000 1354 their_addr.sin_family = AF_INET; /* host byte order */ 1355 their_addr.sin_port = htons(args.port); /* short, network byte order */ 2001 their_addr.sin_family = AF_INET; 1356 2002 their_addr.sin_addr = *((struct in_addr *)he->h_addr); 1357 memset(&(their_addr.sin_zero), '\0', 8); 1358 if(connect(sockfd, (struct sockaddr *)&their_addr, 1359 sizeof(struct sockaddr)) == -1) 2003 2004 if(args.data && args.mode == RTSP) 1360 2005 { 1361 RTCM3Error("Function connect: %s\n", strerror(errno)); 1362 exit(1); 1363 } 1364 1365 if(!args.data) 1366 { 1367 i = snprintf(buf, MAXDATASIZE, 1368 "GET / HTTP/1.0\r\n" 2006 struct sockaddr_in local; 2007 int sockudp, localport; 2008 int cseq = 1; 2009 socklen_t len; 2010 2011 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 2012 { 2013 perror("socket"); 2014 exit(1); 2015 } 2016 /* fill structure with local address information for UDP */ 2017 memset(&local, 0, sizeof(local)); 2018 local.sin_family = AF_INET; 2019 local.sin_port = htons(0); 2020 local.sin_addr.s_addr = htonl(INADDR_ANY); 2021 len = sizeof(local); 2022 /* bind() in order to get a random RTP client_port */ 2023 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0) 2024 { 2025 perror("bind"); 2026 exit(1); 2027 } 2028 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1) 2029 { 2030 localport = ntohs(local.sin_port); 2031 } 2032 else 2033 { 2034 perror("local access failed"); 2035 exit(1); 2036 } 2037 if(connect(sockfd, (struct sockaddr *)&their_addr, 2038 sizeof(struct sockaddr)) == -1) 2039 { 2040 perror("connect"); 2041 exit(1); 2042 } 2043 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */ 2044 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n" 2045 "CSeq: %d\r\n" 2046 "Ntrip-Version: Ntrip/2.0\r\n" 2047 "Ntrip-Component: Ntripclient\r\n" 1369 2048 "User-Agent: %s/%s\r\n" 1370 #ifdef UNUSED 1371 "Accept: */*\r\n" 1372 "Connection: close\r\n" 1373 #endif 1374 "\r\n" 1375 , AGENTSTRING, revisionstr); 1376 } 1377 else 1378 { 1379 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */ 1380 "GET /%s HTTP/1.0\r\n" 1381 "User-Agent: %s/%s\r\n" 1382 #ifdef UNUSED 1383 "Accept: */*\r\n" 1384 "Connection: close\r\n" 1385 #endif 1386 "Authorization: Basic " 1387 , args.data, AGENTSTRING, revisionstr); 2049 "Transport: RTP/GNSS;unicast;client_port=%u\r\n" 2050 "Authorization: Basic ", 2051 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "", 2052 args.data, cseq++, AGENTSTRING, revisionstr, localport); 1388 2053 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */ 1389 2054 { … … 1401 2066 buf[i++] = '\r'; 1402 2067 buf[i++] = '\n'; 1403 } 1404 if(send(sockfd, buf, (size_t)i, 0) != i) 1405 { 1406 RTCM3Error("Function send: %s\n", strerror(errno)); 1407 exit(1); 1408 } 1409 if(args.data) 1410 { 1411 int k = 0; 1412 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1) 1413 { 1414 if(!k) 1415 { 1416 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12)) 1417 { 1418 RTCM3Error("Could not get the requested data: "); 1419 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k) 1420 { 1421 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.'); 1422 } 1423 RTCM3Error("\n"); 2068 if(args.nmea) 2069 { 2070 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea); 2071 if(j >= 0 && j < MAXDATASIZE-i) 2072 i += j; 2073 else 2074 { 2075 RTCM3Error("NMEA string too long\n"); 2076 exit(1); 2077 } 2078 } 2079 if(send(sockfd, buf, (size_t)i, 0) != i) 2080 { 2081 perror("send"); 2082 exit(1); 2083 } 2084 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1) 2085 { 2086 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17)) 2087 { 2088 int serverport = 0, session = 0; 2089 const char *portcheck = "server_port="; 2090 const char *sessioncheck = "session: "; 2091 int l = strlen(portcheck)-1; 2092 int j=0; 2093 for(i = 0; j != l && i < numbytes-l; ++i) 2094 { 2095 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j) 2096 ; 2097 } 2098 if(i == numbytes-l) 2099 { 2100 RTCM3Error("No server port number found\n"); 1424 2101 exit(1); 1425 2102 } 1426 ++k; 2103 else 2104 { 2105 i+=l; 2106 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9') 2107 serverport = serverport * 10 + buf[i++]-'0'; 2108 if(buf[i] != '\r' && buf[i] != ';') 2109 { 2110 RTCM3Error("Could not extract server port\n"); 2111 exit(1); 2112 } 2113 } 2114 l = strlen(sessioncheck)-1; 2115 j=0; 2116 for(i = 0; j != l && i < numbytes-l; ++i) 2117 { 2118 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j) 2119 ; 2120 } 2121 if(i == numbytes-l) 2122 { 2123 RTCM3Error("No session number found\n"); 2124 exit(1); 2125 } 2126 else 2127 { 2128 i+=l; 2129 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9') 2130 session = session * 10 + buf[i++]-'0'; 2131 if(buf[i] != '\r') 2132 { 2133 RTCM3Error("Could not extract session number\n"); 2134 exit(1); 2135 } 2136 } 2137 2138 i = snprintf(buf, MAXDATASIZE, 2139 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n" 2140 "CSeq: %d\r\n" 2141 "Session: %d\r\n" 2142 "\r\n", 2143 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "", 2144 args.data, cseq++, session); 2145 2146 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */ 2147 { 2148 RTCM3Error("Requested data too long\n"); 2149 exit(1); 2150 } 2151 if(send(sockfd, buf, (size_t)i, 0) != i) 2152 { 2153 perror("send"); 2154 exit(1); 2155 } 2156 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1) 2157 { 2158 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17)) 2159 { 2160 struct sockaddr_in addrRTP; 2161 /* fill structure with caster address information for UDP */ 2162 memset(&addrRTP, 0, sizeof(addrRTP)); 2163 addrRTP.sin_family = AF_INET; 2164 addrRTP.sin_port = htons(serverport); 2165 their_addr.sin_addr = *((struct in_addr *)he->h_addr); 2166 len = sizeof(addrRTP); 2167 int ts = 0; 2168 int sn = 0; 2169 int ssrc = 0; 2170 int init = 0; 2171 int u, v, w; 2172 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0, 2173 (struct sockaddr*) &addrRTP, &len)) > 0) 2174 { 2175 alarm(ALARMTIME); 2176 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60) 2177 { 2178 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3]; 2179 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16) 2180 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7]; 2181 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16) 2182 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11]; 2183 2184 if(init) 2185 { 2186 if(u < -30000 && sn > 30000) sn -= 0xFFFF; 2187 if(ssrc != w || ts > v) 2188 { 2189 RTCM3Error("Illegal UDP data received.\n"); 2190 exit(1); 2191 } 2192 if(u > sn) /* don't show out-of-order packets */ 2193 fwrite(buf+12, (size_t)i-12, 1, stdout); 2194 } 2195 sn = u; ts = v; ssrc = w; init = 1; 2196 } 2197 else 2198 { 2199 RTCM3Error("Illegal UDP header.\n"); 2200 exit(1); 2201 } 2202 } 2203 } 2204 i = snprintf(buf, MAXDATASIZE, 2205 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n" 2206 "CSeq: %d\r\n" 2207 "Session: %d\r\n" 2208 "\r\n", 2209 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "", 2210 args.data, cseq++, session); 2211 2212 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */ 2213 { 2214 RTCM3Error("Requested data too long\n"); 2215 exit(1); 2216 } 2217 if(send(sockfd, buf, (size_t)i, 0) != i) 2218 { 2219 perror("send"); 2220 exit(1); 2221 } 2222 } 2223 else 2224 { 2225 RTCM3Error("Could not start data stream.\n"); 2226 exit(1); 2227 } 1427 2228 } 1428 2229 else 1429 2230 { 1430 int z; 1431 for(z = 0; z < numbytes && !stop; ++z) 1432 HandleByte(&Parser, (unsigned int) buf[z]); 1433 } 2231 RTCM3Error("Could not setup initial control connection.\n"); 2232 exit(1); 2233 } 2234 } 2235 else 2236 { 2237 perror("recv"); 2238 exit(1); 1434 2239 } 1435 2240 } 1436 2241 else 1437 2242 { 1438 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0) 1439 { 1440 fwrite(buf, (size_t)numbytes, 1, stdout); 1441 } 1442 } 1443 1444 close(sockfd); 2243 if(connect(sockfd, (struct sockaddr *)&their_addr, 2244 sizeof(struct sockaddr)) == -1) 2245 { 2246 perror("connect"); 2247 exit(1); 2248 } 2249 if(!args.data) 2250 { 2251 i = snprintf(buf, MAXDATASIZE, 2252 "GET %s%s%s%s/ HTTP/1.0\r\n" 2253 "Host: %s\r\n%s" 2254 "User-Agent: %s/%s\r\n" 2255 "\r\n" 2256 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "", 2257 proxyserver ? ":" : "", proxyserver ? proxyport : "", 2258 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n", 2259 AGENTSTRING, revisionstr); 2260 } 2261 else 2262 { 2263 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */ 2264 "GET %s%s%s%s/%s HTTP/1.0\r\n" 2265 "Host: %s\r\n%s" 2266 "User-Agent: %s/%s\r\n" 2267 "Authorization: Basic " 2268 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "", 2269 proxyserver ? ":" : "", proxyserver ? proxyport : "", 2270 args.data, args.server, 2271 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n", 2272 AGENTSTRING, revisionstr); 2273 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */ 2274 { 2275 RTCM3Error("Requested data too long\n"); 2276 exit(1); 2277 } 2278 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password); 2279 if(i > MAXDATASIZE-4) 2280 { 2281 RTCM3Error("Username and/or password too long\n"); 2282 exit(1); 2283 } 2284 buf[i++] = '\r'; 2285 buf[i++] = '\n'; 2286 buf[i++] = '\r'; 2287 buf[i++] = '\n'; 2288 if(args.nmea) 2289 { 2290 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea); 2291 if(j >= 0 && j < MAXDATASIZE-i) 2292 i += j; 2293 else 2294 { 2295 RTCM3Error("NMEA string too long\n"); 2296 exit(1); 2297 } 2298 } 2299 } 2300 if(send(sockfd, buf, (size_t)i, 0) != i) 2301 { 2302 perror("send"); 2303 exit(1); 2304 } 2305 if(args.data) 2306 { 2307 int k = 0; 2308 int chunkymode = 0; 2309 int starttime = time(0); 2310 int lastout = starttime; 2311 int totalbytes = 0; 2312 int chunksize = 0; 2313 2314 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1) 2315 { 2316 alarm(ALARMTIME); 2317 if(!k) 2318 { 2319 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) 2320 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17))) 2321 { 2322 const char *datacheck = "Content-Type: gnss/data\r\n"; 2323 const char *chunkycheck = "Transfer-Encoding: chunked\r\n"; 2324 int l = strlen(datacheck)-1; 2325 int j=0; 2326 for(i = 0; j != l && i < numbytes-l; ++i) 2327 { 2328 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j) 2329 ; 2330 } 2331 if(i == numbytes-l) 2332 { 2333 RTCM3Error("No 'Content-Type: gnss/data' found\n"); 2334 exit(1); 2335 } 2336 l = strlen(chunkycheck)-1; 2337 j=0; 2338 for(i = 0; j != l && i < numbytes-l; ++i) 2339 { 2340 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j) 2341 ; 2342 } 2343 if(i < numbytes-l) 2344 chunkymode = 1; 2345 } 2346 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12)) 2347 { 2348 RTCM3Error("Could not get the requested data: "); 2349 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k) 2350 { 2351 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.'); 2352 } 2353 RTCM3Error("\n"); 2354 exit(1); 2355 } 2356 else if(args.mode != NTRIP1) 2357 { 2358 if(args.mode != AUTO) 2359 { 2360 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n", 2361 args.mode == AUTO ? ", falling back to NTRIP1" : ""); 2362 } 2363 if(args.mode == HTTP) 2364 exit(1); 2365 } 2366 ++k; 2367 } 2368 else 2369 { 2370 if(chunkymode) 2371 { 2372 int stop = 0; 2373 int pos = 0; 2374 while(!stop && pos < numbytes) 2375 { 2376 switch(chunkymode) 2377 { 2378 case 1: /* reading number starts */ 2379 chunksize = 0; 2380 ++chunkymode; /* no break */ 2381 case 2: /* during reading number */ 2382 i = buf[pos++]; 2383 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0'; 2384 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10; 2385 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10; 2386 else if(i == '\r') ++chunkymode; 2387 else stop = 1; 2388 break; 2389 case 3: /* scanning for return */ 2390 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1; 2391 else stop = 1; 2392 break; 2393 case 4: /* output data */ 2394 i = numbytes-pos; 2395 if(i > chunksize) i = chunksize; 2396 { 2397 int z; 2398 for(z = 0; z < i && !stop; ++z) 2399 HandleByte(&Parser, (unsigned int) buf[pos+z]); 2400 } 2401 totalbytes += i; 2402 chunksize -= i; 2403 pos += i; 2404 if(!chunksize) 2405 chunkymode = 1; 2406 break; 2407 } 2408 } 2409 if(stop) 2410 { 2411 RTCM3Error("Error in chunky transfer encoding\n"); 2412 break; 2413 } 2414 } 2415 else 2416 { 2417 totalbytes += numbytes; 2418 { 2419 int z; 2420 for(z = 0; z < numbytes && !stop; ++z) 2421 HandleByte(&Parser, (unsigned int) buf[z]); 2422 } 2423 } 2424 if(totalbytes < 0) /* overflow */ 2425 { 2426 totalbytes = 0; 2427 starttime = time(0); 2428 lastout = starttime; 2429 } 2430 } 2431 } 2432 } 2433 else 2434 { 2435 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0) 2436 { 2437 alarm(ALARMTIME); 2438 fwrite(buf, (size_t)numbytes, 1, stdout); 2439 } 2440 } 2441 close(sockfd); 2442 } 1445 2443 } 1446 2444 return 0; -
trunk/rtcm3torinex/rtcm3torinex.h
r365 r502 4 4 /* 5 5 Converter for RTCM3 data to RINEX. 6 $Id: rtcm3torinex.h,v 1. 5 2007/01/11 14:10:13stoecker Exp $7 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@ euronik.eu>6 $Id: rtcm3torinex.h,v 1.6 2007/01/15 13:01:40 stoecker Exp $ 7 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@alberding.eu> 8 8 9 9 This program is free software; you can redistribute it and/or modify … … 110 110 }; 111 111 112 #define GPSEPHF_L2PCODEDATA (1<<0) /* set, if NAV data OFF on L2 P-code, s1w4b01 */ 113 #define GPSEPHF_L2PCODE (1<<1) /* set, if P-code available, s1w3b12 */ 114 #define GPSEPHF_L2CACODE (1<<2) /* set, if CA-code available, s1w3b11 */ 115 #define GPSEPHF_VALIDATED (1<<3) /* data is completely valid */ 116 117 #define PI 3.1415926535898 118 119 struct gpsephemeris { 120 int flags; /* GPSEPHF_xxx */ 121 int satellite; /* SV ID ICD-GPS data position */ 122 int IODE; /* [s2w3b01-08] */ 123 int URAindex; /* [1..15] [s1w3b13-16] */ 124 int SVhealth; /* [s1w3b17-22] */ 125 int GPSweek; /* [s1w3b01-10] */ 126 int IODC; /* [s1w3b23-32,w8b01-08] */ 127 int TOW; /* [s] [s1w2b01-17] */ 128 int TOC; /* [s] [s1w8b09-24] */ 129 int TOE; /* [s] [s2w10b1-16] */ 130 double clock_bias; /* [s] [s1w10b1-22, af0] */ 131 double clock_drift; /* [s/s] [s1w9b09-24, af1] */ 132 double clock_driftrate; /* [s/s^2] [s1w9b01-08, af2] */ 133 double Crs; /* [m] [s2w3b09-24] */ 134 double Delta_n; /* [rad/s] [s2w4b01-16 * Pi] */ 135 double M0; /* [rad] [s2w4b17-24,w5b01-24 * Pi]*/ 136 double Cuc; /* [rad] [s2w6b01-16] */ 137 double e; /* [s2w6b17-24,w6b01-24] */ 138 double Cus; /* [rad] [s2w8b01-16] */ 139 double sqrt_A; /* [m^0.5] [s2w8b16-24,w9b01-24] */ 140 double Cic; /* [rad] [s3w3b01-16] */ 141 double OMEGA0; /* [rad] [s3w3b17-24,w4b01-24 * Pi]*/ 142 double Cis; /* [rad] [s3w5b01-16] */ 143 double i0; /* [rad] [s3w5b17-24,w6b01-24 * Pi]*/ 144 double Crc; /* [m] [s3w701-16] */ 145 double omega; /* [rad] [s3w7b17-24,w8b01-24 * Pi]*/ 146 double OMEGADOT; /* [rad/s] [s3w9b01-24 * Pi] */ 147 double IDOT; /* [rad/s] [s3w10b9-22 * Pi] */ 148 double TGD; /* [s] [s1w7b17-24] */ 149 }; 150 151 #define GLOEPHF_UNHEALTHY (1<<0) /* set if unhealty satellite, f2b78 */ 152 #define GLOEPHF_ALMANACHEALTHOK (1<<1) /* set if ALM health is available */ 153 #define GLOEPHF_ALMANACHEALTHY (1<<2) /* set if Cn word is true */ 154 #define GLOEPHF_PAVAILABLE (1<<3) /* set if the 3 P flags are available */ 155 #define GLOEPHF_P10TRUE (1<<4) 156 #define GLOEPHF_P11TRUE (1<<5) 157 #define GLOEPHF_P2TRUE (1<<6) 158 #define GLOEPHF_P3TRUE (1<<7) 159 160 struct glonassephemeris { 161 int GPSWeek; 162 int GPSTOW; 163 int flags; /* GLOEPHF_xxx */ 164 int almanac_number; 165 int frequency_number; /* ICD-GLONASS data position */ 166 int tb; /* [s] [f2b70-76] */ 167 int tk; /* [s] [f1b65-76] */ 168 int E; /* [days] [f4b49-53] */ 169 double tau; /* [s] [f4b59-80] */ 170 double gamma; /* [f3b69-79] */ 171 double x_pos; /* [km] [f1b09-35] */ 172 double x_velocity; /* [km/s] [f1b41-64] */ 173 double x_acceleration; /* [km/s^2][f1b36-40] */ 174 double y_pos; /* [km] [f2b09-35] */ 175 double y_velocity; /* [km/s] [f2b41-64] */ 176 double y_acceleration; /* [km/s^2][f2b36-40] */ 177 double z_pos; /* [km] [f3b09-35] */ 178 double z_velocity; /* [km/s] [f3b41-64] */ 179 double z_acceleration; /* [km/s^2][f3b36-40] */ 180 }; 181 112 182 struct RTCM3ParserData { 113 183 unsigned char Message[2048]; /* input-buffer */ … … 118 188 int GPSTOW; /* in seconds */ 119 189 struct gnssdata Data; 190 struct gpsephemeris ephemerisGPS; 191 struct glonassephemeris ephemerisGLONASS; 120 192 struct gnssdata DataNew; 121 193 int size; … … 124 196 int datapos[RINEXENTRY_NUMBER]; 125 197 int dataflag[RINEXENTRY_NUMBER]; 126 int datapos2[RINEXENTRY_NUMBER]; 127 int dataflag2[RINEXENTRY_NUMBER]; 128 int numdatatypes; 198 /* for RINEX2 GPS and GLO are both handled in GPS */ 199 int dataposGPS[RINEXENTRY_NUMBER]; /* SBAS has same entries */ 200 int dataflagGPS[RINEXENTRY_NUMBER]; 201 int dataposGLO[RINEXENTRY_NUMBER]; /* only used for RINEX3 */ 202 int dataflagGLO[RINEXENTRY_NUMBER]; 203 int numdatatypesGPS; 204 int numdatatypesGLO; /* only used for RINEX3 */ 129 205 int validwarning; 130 206 int init; 131 207 int startflags; 208 int rinex3; 132 209 const char * headerfile; 210 const char * glonassephemeris; 211 const char * gpsephemeris; 212 FILE *glonassfile; 213 FILE *gpsfile; 133 214 }; 134 215 -
trunk/rtcm3torinex/rtcm3torinex.txt
r318 r502 22 22 1012 GLONASS L1 and L2 code and phase and ambiguities and carrier to noise ratio 23 23 1013 Modified julian date, leep second, configured message types and intervall 24 1014-1017 Network RTK (MAK) messages (under development)25 1019 GPS Ephemeris (under development)26 1020 GLONASS Ephemeris (under development)24 1014-1017 Network RTK (MAK) messages 25 1019 GPS Ephemeris 26 1020 GLONASS Ephemeris 27 27 4088-4095 Proprietary messages (under development) 28 28 29 29 Note that this version of rtcm3torinex only handles RTCM3 message types 1001, 30 1002, 1003, 1004, 1009, 1010, 1011 and 1012.30 1002, 1003, 1004, 1009, 1010, 1011, 1012, 1019 and 1020. 31 31 32 32 The generated RINEX is somewhat limited due to the streaming character of the … … 37 37 additional fields cannot be provided. 38 38 - The number of observables cannot change during the program runtime. Only 39 the observables, which exist in the first epoch are output ted. If there39 the observables, which exist in the first epoch are output. If there 40 40 are new observables later on, these are ignored. 41 41 - Only known message types are interpreted. This means only GPS data at the … … 48 48 easy positioning algorithm). 49 49 50 Usage: rtcm3torinex -s server -u user ... 51 -d --data the requested data set 52 -f --headerfile file for RINEX header information 53 -s --server the server name or address 54 -p --password the login password 55 -r --port the server port number (default 80) 56 -u --user the user name 50 Usage: ./rtcm3torinex -s server -u user ... 51 -d --data the requested data set 52 -f --headerfile file for RINEX header information 53 -s --server the server name or address 54 -p --password the login password 55 -r --port the server port number (default 2101) 56 -t --timeout timeout in seconds (default 60) 57 -u --user the user name 58 -E --gpsephemeris output file for GPS ephemeris data 59 -G --glonassephemeris output file for GLONASS ephemeris data 60 -3 --rinex3 output RINEX type 3 data 61 -S --proxyhost proxy name or address 62 -R --proxyport proxy port, optional (default 2101) 63 -n --nmea NMEA string for sending to server 64 -M --mode mode for data request 65 Valid modes are: 66 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode 67 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode 68 3, n, ntrip1 NTRIP Version 1.0 Caster 69 4, a, auto automatic detection (default) 57 70 58 71 The fields --user and --password are used to specify the access data for the 59 72 NTRIP server. The arguments --server and --port are used to specify the NTRIP 60 server itself (defaults to "www.euref-ip.net" port 80). The Argument --data73 server itself (defaults to "www.euref-ip.net" port 2101). The Argument --data 61 74 must be used to specify the RTCM3 input data stream. If it is not given, you 62 75 will be shown the source table of the selected NTRIP caster. 63 76 64 77 Alternatively a single text of the form 65 "ntrip: mountpoint[/username[:password]][@server[:port]]"78 "ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]" 66 79 can be used. Everything in brackets is optional. 67 80 … … 101 114 102 115 Dirk Stoecker 103 EuronikGmbH104 http://www. euronik.eu/116 Alberding GmbH 117 http://www.alberding.eu/ 105 118 106 119 for … … 111 124 http://igs.bkg.bund.de/index_ntrip.htm 112 125 113 Contact Dirk Stoecker [stoecker@ euronik.eu] or [euref-ip@bkg.bund.de]126 Contact Dirk Stoecker [stoecker@alberding.eu] or [euref-ip@bkg.bund.de] 114 127 with your comments, suggestions, improvements, patches, ...
Note:
See TracChangeset
for help on using the changeset viewer.