00001 #pragma ident "$Id: SMODFData.cpp 1122 2008-03-14 13:36:58Z snelsen $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00044 #include "StringUtils.hpp"
00045 #include "SMODFData.hpp"
00046 #include "SMODFStream.hpp"
00047
00048 using namespace gpstk::StringUtils;
00049 using namespace std;
00050
00051 namespace gpstk
00052 {
00053 const int SMODFData::SMO_LEN_ICD211 = 85;
00054 const int SMODFData::SMO_LEN_LEGACY = 80;
00055 const int SMODFData::BEGINGPS2DYEAR = 80;
00056
00057 void SMODFData::reallyPutRecord(gpstk::FFStream& ffs) const
00058 throw(std::exception, gpstk::FFStreamError,
00059 gpstk::StringUtils::StringException)
00060 {
00061 SMODFStream& strm = dynamic_cast<SMODFStream&>(ffs);
00062
00063
00064 if (strm.format == SMODFStream::undefined)
00065 strm.format = SMODFStream::icd211;
00066
00067 string line;
00068
00069 if (strm.format == SMODFStream::icd211)
00070 {
00071 line += rightJustify(asString<short>(time.DOYyear()),4);
00072 line += rightJustify(asString<short>(time.DOYday()),3,'0');
00073 line += rightJustify(asString(time.DOYsecond(),7),13);
00074 line += rightJustify(asString<short>(PRNID),3);
00075 line += rightJustify(asString<long>(station),5);
00076 line += rightJustify(asString<short>(channel),2);
00077 line += rightJustify(asString<short>(type),1);
00078
00079 if (type == 9)
00080 line += rightJustify(asString<short>(lol),1);
00081 else
00082 line += string(1, ' ');
00083
00084 line += doub2funny(obs, 21, 2);
00085 line += doub2funny(stdDev, 12, 2);
00086 line += string(1, ' ');
00087 line += rightJustify(asString<short>(tempSource),1);
00088 line += rightJustify(asString<short>(pressSource),1);
00089 line += rightJustify(asString<short>(humidSource),1);
00090 line += rightJustify(asString(temp,1), 5);
00091 line += rightJustify(asString(pressure,1), 6);
00092 line += rightJustify(asString(humidity,1), 5);
00093
00094 }
00095 else if (strm.format == SMODFStream::legacy)
00096 {
00097 line += time.printf("%02y%3j%12.6s");
00098 line += rightJustify(asString<short>(PRNID),3);
00099 line += rightJustify(asString<long>(station),5);
00100 line += rightJustify(asString<short>(channel),2);
00101 line += rightJustify(asString<short>(type),1);
00102
00103 if (type == 9)
00104 line += rightJustify(asString<short>(lol),1);
00105 else
00106 line += string(1, ' ');
00107
00108
00109
00110 line += string(1, ' ');
00111 line += doub2for(obs, 20, 2);
00112
00113 line += string(1, ' ');
00114 line += doub2for(stdDev, 11, 2);
00115 line += string(1, ' ');
00116
00117
00118 short wxsource = 0;
00119 if (tempSource == pressSource == humidSource)
00120 wxsource = tempSource;
00121 else if (tempSource && pressSource && humidSource)
00122 {
00123
00124
00125
00126
00127
00128
00129
00130 wxsource = 2;
00131 }
00132 else
00133 {
00134
00135
00136 gpstk::FFStreamError err("Assertion failed: all weather data must be"
00137 " either present or missing");
00138 if (tempSource == 0)
00139 err.addText("temperature data is missing");
00140 if (pressSource == 0)
00141 err.addText("pressure data is missing");
00142 if (humidSource == 0)
00143 err.addText("humidity data is missing");
00144 err.addText("unlisted weather measurements are present");
00145 }
00146
00147 if (wxsource == 1)
00148 wxsource = 7;
00149
00150 line += rightJustify(asString<short>(wxsource),1);
00151 line += rightJustify(asString(temp,1), 5);
00152 line += rightJustify(asString(pressure,1), 6);
00153 line += rightJustify(asString(humidity,1), 5);
00154 }
00155 else
00156 {
00157 gpstk::FFStreamError err("Unknown SMODF format: " +
00158 asString<unsigned long>(strm.format));
00159 err.addText("Make sure you specify the format of the data.");
00160 GPSTK_THROW(err);
00161 }
00162
00163 ffs << line << endl;
00164 strm.lineNumber++;
00165 }
00166
00167 void SMODFData::dump(ostream& s) const
00168 {
00169 s << time << " Station: " << station << " Type: " << type
00170 << " PRN " << PRNID << endl;
00171 }
00172
00173 void SMODFData::reallyGetRecord(gpstk::FFStream& ffs)
00174 throw(std::exception, gpstk::FFStreamError,
00175 gpstk::StringUtils::StringException)
00176 {
00177 SMODFStream& strm = dynamic_cast<SMODFStream&>(ffs);
00178
00179 string str, currentLine;
00180
00181 strm.formattedGetLine(currentLine, true);
00182 int len=currentLine.length();
00183
00184
00185
00186 if (strm.format == SMODFStream::undefined)
00187 {
00188 if (len == SMO_LEN_ICD211)
00189 strm.format = SMODFStream::icd211;
00190 else if (len == SMO_LEN_LEGACY)
00191 strm.format = SMODFStream::legacy;
00192 else
00193 {
00194 gpstk::FFStreamError e("Unreconized format");
00195 GPSTK_THROW(e);
00196 }
00197 }
00198
00199 if (strm.format == SMODFStream::icd211)
00200 {
00201 if (len != SMO_LEN_ICD211)
00202 {
00203 gpstk::FFStreamError e("Bad 211 format line length: " +
00204 asString(len));
00205 GPSTK_THROW(e);
00206 }
00207
00208
00209
00210 currentLine[65] = ' ';
00211
00212 if (currentLine[31]!='1')
00213 currentLine[31]='0';
00214
00215
00216 short year = asInt(currentLine.substr( 0, 4));
00217 short DOY = asInt(currentLine.substr( 4, 3));
00218 double SOD = asDouble(currentLine.substr( 7, 13));
00219 PRNID = asInt(currentLine.substr(21, 2));
00220 station = asInt(currentLine.substr(23, 5));
00221 channel = asInt(currentLine.substr(28, 2));
00222 type = asInt(currentLine.substr(30, 1));
00223 lol = asInt(currentLine.substr(31, 1));
00224 obs = for2doub(currentLine.substr(32, 21));
00225 stdDev = for2doub(currentLine.substr(53, 12));
00226 tempSource = asInt(currentLine.substr(66, 1));
00227 pressSource = asInt(currentLine.substr(67, 1));
00228 humidSource = asInt(currentLine.substr(68, 1));
00229 temp = asDouble(currentLine.substr(69, 5));
00230 pressure = asDouble(currentLine.substr(74, 6));
00231 humidity = asDouble(currentLine.substr(80, 5));
00232
00233
00234
00235 if (DOY < 0 || DOY > 366 || SOD > 86400 || PRNID > 32 ||
00236 (type != 0 && type != 9) ||
00237 stdDev > 100 || stdDev <= 0)
00238 {
00239 gpstk::FFStreamError e(string("Bad 211 format data"));
00240 GPSTK_THROW(e);
00241 }
00242
00243
00244
00245 time.setYDoySod(year, DOY, SOD);
00246 }
00247 else if (strm.format == SMODFStream::legacy)
00248 {
00249 if (len != SMO_LEN_LEGACY)
00250 {
00251 gpstk::FFStreamError e("Bad legacy format line length: " +
00252 asString(len));
00253 GPSTK_THROW(e);
00254 }
00255
00256
00257
00258 currentLine[62] = ' ';
00259
00260 if (currentLine[28]!='1')
00261 currentLine[28]='0';
00262
00263
00264 short year = asInt(currentLine.substr( 0, 2));
00265 short DOY = asInt(currentLine.substr( 2, 3));
00266 double SOD = asDouble(currentLine.substr( 5, 12));
00267 PRNID = asInt(currentLine.substr(17, 3));
00268 station = asInt(currentLine.substr(20, 5));
00269 channel = asInt(currentLine.substr(25, 2));
00270 type = asInt(currentLine.substr(27, 1));
00271 lol = asInt(currentLine.substr(28, 1));
00272 obs = for2doub(currentLine.substr(29, 21));
00273 stdDev = for2doub(currentLine.substr(50, 12));
00274 short src = asInt(currentLine.substr(63, 1));
00275 temp = asDouble(currentLine.substr(64, 5));
00276 pressure = asDouble(currentLine.substr(69, 6));
00277 humidity = asDouble(currentLine.substr(75, 5));
00278
00279
00280
00281 if (DOY < 0 || DOY > 366 || SOD > 86400 || PRNID > 32 ||
00282 (type != 0 && type != 9) ||
00283 stdDev > 100 || stdDev <= 0)
00284 {
00285 gpstk::FFStreamError e(string("Bad legacy format data"));
00286 GPSTK_THROW(e);
00287 }
00288
00289
00290 if ( year < BEGINGPS2DYEAR )
00291 year += 2000;
00292 else
00293 year += 1900;
00294 time.setYDoySod(year, DOY, SOD);
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 if ( src==1 || src==7 )
00309 tempSource = pressSource = humidSource = 1;
00310 else if ( src==2 || src==6 )
00311 tempSource = pressSource = humidSource = 2;
00312 else
00313 tempSource = pressSource = humidSource = 0;
00314 }
00315 }
00316
00317 string SMODFData::doub2funny(const double& num,
00318 const std::string::size_type length,
00319 const std::string::size_type expLen)
00320 {
00321
00322
00323 string str((num >= 0 ? 1 : 0), ' ');
00324 str += doub2sci(num, length, expLen);
00325
00326 std::string::size_type idx = str.find_first_of("eE");
00327 if (idx != std::string::npos)
00328 str[idx] = 'D';
00329 return str;
00330 }
00331
00332 }