- fix parsing datas in real weather

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@9217 30fe4595-0a0c-4342-8851-515496e4dcbd
This commit is contained in:
torcs-ng 2023-11-10 12:57:10 +00:00
parent a7fa57d7bc
commit 5e15d19cdf
3 changed files with 265 additions and 134 deletions

View File

@ -703,7 +703,10 @@ reTrackInitRealWeather(void)
trackLocal->winddir = (_wind_range_from + _wind_range_to) / 2;
}
}
else if (webMetar->getWindRangeFrom() == -1)
else
trackLocal->winddir = webMetar->getWindDir();
if (webMetar->getWindRangeFrom() == -1)
{
_wind_range_from = _wind_range_to = trackLocal->winddir;
}
@ -752,8 +755,8 @@ reTrackInitRealWeather(void)
else
trackLocal->dewp = (tdble)(webMetar->getDewpoint_C());
if (webMetar->getPressure_hPa() == WebMetarNaN)
trackLocal->airpressure = (tdble)(30.0 * 3386.388640341);
if (webMetar->getPressure_hPa() == WebMetarNaN )
trackLocal->airpressure = (tdble)(101300.0);
else
trackLocal->airpressure = (tdble)(webMetar->getPressure_hPa());
@ -764,6 +767,8 @@ reTrackInitRealWeather(void)
else
trackLocal->airdensity = (tdble)(webMetar->getDensity_C());
trackLocal->relativehumidity = (tdble)(webMetar->getRelativeHumidity());
if (ReInfo->s->_features & RM_FEATURE_WETTRACK && (!strcmp(ReInfo->track->category, "speedway")) == 0)
{
trackLocal->rain = webMetar->getRain();
@ -778,36 +783,33 @@ reTrackInitRealWeather(void)
if (trackLocal->hail > 0)
trackLocal->water = trackLocal->hail;
trackLocal->relativehumidity = (tdble)(webMetar->getRelHumidity());
}
else
{
trackLocal->rain = TR_RAIN_NONE;
trackLocal->snow = TR_RAIN_NONE;
trackLocal->hail = TR_RAIN_NONE;
trackLocal->relativehumidity = TR_RAIN_NONE;
trackLocal->water = TR_RAIN_NONE;
}
trackLocal->config = 0;
GfLogInfo("Visibility = %.3f\n", trackLocal->visibility);
GfLogInfo("Wind Speed = %.3f\n", trackLocal->windspeed);
GfLogInfo("Wind direction = %.3f\n", trackLocal->winddir);
GfLogInfo("Air Temperature = %.3f\n", trackLocal->airtemperature);
GfLogInfo("Dew point = %.3f\n", trackLocal->dewp);
GfLogInfo("Air pressure = %.3f\n", trackLocal->airpressure);
GfLogInfo("Visibility = %.2f\n", trackLocal->visibility);
GfLogInfo("Wind Speed = %.2f\n", trackLocal->windspeed);
GfLogInfo("Wind direction = %.2f\n", trackLocal->winddir);
GfLogInfo("Air Temperature = %.2f\n", trackLocal->airtemperature);
GfLogInfo("Dew point = %.2f\n", trackLocal->dewp);
GfLogInfo("Air pressure = %.2f\n", trackLocal->airpressure);
GfLogInfo("Air Density = %.3f\n", trackLocal->airdensity);
GfLogInfo("Rain = %i\n", trackLocal->rain);
GfLogInfo("Snow = %i\n", trackLocal->snow);
GfLogInfo("Hail = %i\n", trackLocal->hail);
GfLogInfo("Water track = %d\n", trackLocal->water);
GfLogInfo("Relative Humidity = %.3f\n", trackLocal->relativehumidity);
GfLogInfo("Relative Humidity = %.2f\n", trackLocal->relativehumidity);
ReTrackUpdate();
delete webMetar;
webMetar = NULL;
//delete webMetar;
//webMetar = NULL;
}
}
@ -1523,5 +1525,6 @@ ReTrackShutdown(void)
delete webMetar;
webMetar = 0;
}
return 0;
}

View File

@ -64,7 +64,6 @@ static size_t curl_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
}
ReWebMetar::ReWebMetar() :
_grpcount(0),
_x_proxy(false),
_data(NULL),
_m(NULL),
@ -87,6 +86,7 @@ ReWebMetar::ReWebMetar() :
_rain(false),
_hail(false),
_snow(false),
_relativehumidity(-1),
_cloudnumber(0),
_cloud1(-1),
_cloud_altitude1(-1),
@ -158,7 +158,7 @@ void ReWebMetar::ReWebMetarLoad(const string& m)
{
_data = new char[m.length() + 2]; // make room for " \0"
strcpy(_data, m.c_str());
_url = _data;
_url = m;
normalizeData();
@ -202,15 +202,9 @@ void ReWebMetar::ReWebMetarLoad(const string& m)
scanRemark();
density();
if (_grpcount < 4)
{
delete[] _data;
}
_url = "";
}
/**
* Clears lists and maps to discourage access after destruction.
*/
@ -222,7 +216,6 @@ ReWebMetar::~ReWebMetar()
delete[] _data;
}
void ReWebMetar::useCurrentDate()
{
GfLogDebug("Start use current date ...\n");
@ -284,7 +277,7 @@ bool ReWebMetar::scanPreambleDate()
_month = month;
_day = day;
_m = m;
GfLogDebug("YEAR = %i - MONTH = %i - DAY = %i\n", _year, _month, _day);
GfLogInfo(" METAR YEAR = %i - MONTH = %i - DAY = %i\n", _year, _month, _day);
return true;
}
@ -297,13 +290,20 @@ bool ReWebMetar::scanPreambleTime()
int hour, minute;
if (!scanNumber(&m, &hour, 2))
{
GfLogDebug("Erreur scan Pre amble Time hour = %i\n", hour);
return false;
}
if (*m++ != ':')
return false;
if (!scanNumber(&m, &minute, 2))
{
GfLogDebug("Erreur scan Pre amble Time minute = %i\n", minute);
return false;
}
/*if (!scanBoundary(&m))
return false;*/
@ -311,7 +311,7 @@ bool ReWebMetar::scanPreambleTime()
_hour = hour;
_minute = minute;
_m = m;
GfLogDebug("HOUR = %i - MINUTES = %i\n", _hour, _minute);
GfLogInfo(" METAR hour = %i - minutes = %i\n", _hour, _minute);
return true;
}
@ -319,12 +319,12 @@ bool ReWebMetar::scanPreambleTime()
// (METAR|SPECI)
bool ReWebMetar::scanType()
{
GfLogDebug("Start scan Tyoe ...\n");
GfLogDebug("Start scan Type ...\n");
if (strncmp(_m, "METAR ", 6) && strncmp(_m, "SPECI ", 6))
return false;
_m += 6;
_grpcount++;
return true;
}
@ -344,8 +344,7 @@ bool ReWebMetar::scanId()
strncpy(_icao, _m, 4);
_icao[4] = '\0';
_m = m;
GfLogDebug("ICAO = %s\n", _icao);
_grpcount++;
GfLogInfo(" METAR ICAO = %s\n", _icao);
return true;
}
@ -376,7 +375,8 @@ bool ReWebMetar::scanDate()
_hour = hour;
_minute = minute;
_m = m;
_grpcount++;
GfLogInfo(" METAR day = %i - hour = %i - minute = %i\n", _day, _hour, _minute);
return true;
}
@ -410,8 +410,6 @@ bool ReWebMetar::scanModifier()
_report_type = type;
_m = m;
_grpcount++;
return true;
}
@ -423,27 +421,42 @@ bool ReWebMetar::scanWind()
char *m = _m;
int dir;
if(*m =='?' || *m == 'E')
m++;
if (!strncmp(m, "VRB", 3))
m += 3, dir = -1;
else if(!strncmp(m, "///", 3))
m += 3, dir = -1;
else if (!scanNumber(&m, &dir, 3))
return false;
dir = -1;
if (*m =='/' && *(m+1) != '/')
m++;
int i;
if (!scanNumber(&m, &i, 2, 3))
return false;
if (!strncmp(m, "//", 2))
m += 2, i = -1;
else if (!scanNumber(&m, &i, 1, 3))
i = -1;
double speed = i;
double gust = NaN;
if (*m == 'G')
if (*m == ' ' && *(m+1) == 'G')
m++;
if (*m == 'G')
{
m++;
if (!strncmp(m, "//", 2))
m += 2, i = -1;
if (!scanNumber(&m, &i, 2, 3))
return false;
gust = i;
if (i != -1)
gust = i;
}
double factor;
@ -463,14 +476,13 @@ bool ReWebMetar::scanWind()
return false;
_m = m;
_wind_dir = dir;
_wind_speed = speed * factor;
_wind_dir = dir == -1 ? 0 : dir;
_wind_speed = speed < 0.0 ? 00 : speed * factor;
if (gust != NaN)
_gust_speed = gust * factor;
_grpcount++;
GfLogDebug("Wind speed = %.3f - Wind Direction = %d\n", _wind_speed, _wind_dir);
GfLogInfo(" METAR Wind speed = %.3f - Wind Direction = %d\n", _wind_speed, _wind_dir);
return true;
}
@ -482,21 +494,27 @@ bool ReWebMetar::scanVariability()
char *m = _m;
int from, to;
if (!scanNumber(&m, &from, 3))
if (!strncmp(m, "///", 3))
m += 3, from = -1;
else if (!scanNumber(&m, &from, 1, 3))
return false;
if (*m++ != 'V')
return false;
if (!scanNumber(&m, &to, 3))
if (!strncmp(m, "///", 3)) // direction not measurable
m += 3, to = -1;
else if (!scanNumber(&m, &to, 1, 3))
return false;
if (!scanBoundary(&m))
return false;
_m = m;
_wind_range_from = from;
_wind_range_to = to;
_grpcount++;
GfLogInfo(" METAR wind range from = %i - wind range to = %i\n", _wind_range_from, _wind_range_to);
return true;
}
@ -505,12 +523,19 @@ bool ReWebMetar::scanVisibility()
// TODO: if only directed vis are given, do still set min/max
{
GfLogDebug("Start scan Visibility ...\n");
if (!strncmp(_m, "//// ", 5))
{ // spec compliant?
_m += 5;
_grpcount++;
if (!strncmp(_m, "///// ", 5))
return false;
return true;
if (!strncmp(_m, "////", 4))
{
_m += 4;
if (!strncmp(_m, "SM", 2))
_m += 2;
else if(!strncmp(_m, "KM", 2))
_m += 2;
return scanBoundary(&_m);
}
char *m = _m;
@ -520,7 +545,7 @@ bool ReWebMetar::scanVisibility()
// \d{4}(N|NE|E|SE|S|SW|W|NW)?
if (scanNumber(&m, &i, 4))
{
if( strncmp( m, "NDV",3 ) == 0 )
if( strncmp( m, "NDV", 3 ) == 0 )
{
m+=3; // tolerate NDV (no directional validation)
}
@ -570,7 +595,7 @@ bool ReWebMetar::scanVisibility()
if (*m == 'M')
m++, modifier = ReWebMetarVisibility::LESS_THAN;
if (!scanNumber(&m, &i, 1, 2))
if (!scanNumber(&m, &i, 1, 3))
return false;
distance = i;
@ -581,6 +606,7 @@ bool ReWebMetar::scanVisibility()
if (!scanNumber(&m, &i, 1, 2))
return false;
distance /= i;
}
else if (*m == ' ')
@ -597,7 +623,8 @@ bool ReWebMetar::scanVisibility()
if (!scanNumber(&m, &denom, 1, 2))
return false;
distance += (double)i / denom;
if (denom != 0)
distance += (double)i / denom;
}
if (!strncmp(m, "SM", 2))
@ -612,6 +639,7 @@ bool ReWebMetar::scanVisibility()
return false;
ReWebMetarVisibility *v;
if (dir != -1)
v = &_dir_visibility[dir / 45];
else if (_min_visibility._distance == NaN)
@ -624,9 +652,8 @@ bool ReWebMetar::scanVisibility()
v->_modifier = modifier;
v->_direction = dir;
_m = m;
_grpcount++;
GfLogDebug("Distance = %.3f - Modifier = %i - Direction = %i\n", v->_distance, v->_modifier, v->_direction);
GfLogInfo(" METAR visibility Distance = %.3f - Modifier = %i - Direction = %i\n", v->_distance, v->_modifier, v->_direction);
return true;
}
@ -641,8 +668,10 @@ bool ReWebMetar::scanRwyVisRange()
if (*m++ != 'R')
return false;
if (!scanNumber(&m, &i, 2))
return false;
if (*m == 'L' || *m == 'C' || *m == 'R')
m++;
@ -653,22 +682,33 @@ bool ReWebMetar::scanRwyVisRange()
if (*m++ != '/')
return false;
if (!strncmp(m, "////", 4))
{
// sensor failure... ignore
_m = m + 4;
return scanBoundary(&_m);
}
int from, to;
if (*m == 'P')
m++, r._min_visibility._modifier = ReWebMetarVisibility::GREATER_THAN;
else if (*m == 'M')
m++, r._min_visibility._modifier = ReWebMetarVisibility::LESS_THAN;
if (!scanNumber(&m, &from, 4))
return false;
if (*m == 'V')
{
m++;
if (*m == 'P')
m++, r._max_visibility._modifier = ReWebMetarVisibility::GREATER_THAN;
else if (*m == 'M')
m++, r._max_visibility._modifier = ReWebMetarVisibility::LESS_THAN;
if (!scanNumber(&m, &to, 4))
return false;
} else
@ -701,7 +741,8 @@ bool ReWebMetar::scanRwyVisRange()
_runways[id]._min_visibility = r._min_visibility;
_runways[id]._max_visibility = r._max_visibility;
_grpcount++;
GfLogInfo(" METAR Visibility = %.1f\n", r._min_visibility);
return true;
}
@ -722,6 +763,7 @@ static const struct Token description[] =
{ "FZ", "freezing" },
{ "MI", "shallow" },
{ "PR", "partial" },
{ "RE", "recent" },
{ 0, 0 }
};
@ -732,6 +774,7 @@ static const struct Token phenomenon[] =
{ "GS", "small hail and/or snow pellets" },
{ "IC", "ice crystals" },
{ "PE", "ice pellets" },
{ "PL", "ice pellets" },
{ "RA", "rain" },
{ "SG", "snow grains" },
{ "SN", "snow" },
@ -745,12 +788,11 @@ static const struct Token phenomenon[] =
{ "PY", "spray" },
{ "SA", "sand" },
{ "VA", "volcanic ash" },
{ "DS", "duststorm" },
{ "DS", "dust storm" },
{ "FC", "funnel cloud/tornado waterspout" },
{ "PO", "well-developed dust/sand whirls" },
{ "SQ", "squalls" },
{ "SS", "sandstorm" },
{ "UP", "unknown" }, // ... due to failed automatic acquisition
{ 0, 0 }
};
@ -767,10 +809,18 @@ bool ReWebMetar::scanWeather()
if (!strncmp(m, "// ", 3))
{
_m += 3;
_grpcount++;
return false;
}
// maintenance flag
if (*m == 'M' && *(m+1) == ' ')
{
_m++;
return scanBoundary(&_m);
}
if ((a = scanToken(&m, special)))
{
if (!scanBoundary(&m))
@ -815,6 +865,8 @@ bool ReWebMetar::scanWeather()
if (!strcmp(a->id, "RA"))
_rain = w.intensity;
else if (!strcmp(a->id, "DZ"))
_rain = LIGHT;
else if (!strcmp(a->id, "HA"))
{
_hail = w.intensity;
@ -843,7 +895,7 @@ bool ReWebMetar::scanWeather()
_weather2.push_back( w );
}
_grpcount++;
GfLogInfo(" METAR rain = %i\n", _rain);
return true;
}
@ -882,6 +934,7 @@ bool ReWebMetar::scanSkyCondition()
char *m = _m;
int i;
ReWebMetarCloud cl;
static ReWebMetarCloud::Coverage priorCoverage;
if (!strncmp(m, "//////", 6))
{
@ -895,8 +948,11 @@ bool ReWebMetar::scanSkyCondition()
return true;
}
if (!strncmp(m, "SKC", i = 3) // sky clear
|| !strncmp(m, "CAVOK", i = 5)) // ceiling and visibility OK (implies 9999)
if (!strncmp(m, "CLR", i = 3) // clear
|| !strncmp(m, "SKC", i = 3) // sky clear
|| !strncmp(m, "NCD", i = 3) // nil cloud detected
|| !strncmp(m, "NSC", i = 3) // no significant clouds
|| !strncmp(m, "CAVOK", i = 5)) // ceiling and visibility OK (implies 9999)
{
m += i;
@ -919,55 +975,87 @@ bool ReWebMetar::scanSkyCondition()
}
if (!strncmp(m, "VV", i = 2)) // vertical visibility
;
_vert_visibility._modifier = ReWebMetarVisibility::NOGO;
else if (!strncmp(m, "CLR", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_CIRRUS;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("CLR / CIRRUS - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR CLR / CIRRUS - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "FEW", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_FEW;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("FEW - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR FEW - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "NCD", i = 3))
else if (!strncmp(m, "NCD", i = 3) || !strncmp(m, "CB", i = 2))
{
cl._coverage = ReWebMetarCloud::COVERAGE_MANY;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("NCD / MANY CLOUDS - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR NCD / MANY CLOUDS - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "NSC", i = 3))
else if (!strncmp(m, "NSC", i = 3) || !strncmp(m, "TCU", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_CUMULUS;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("NCD / MANY CLOUDS - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR NCD / MANY CLOUDS - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "SCT", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_SCATTERED;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("SCATTERED - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR SCATTERED - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "BKN", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_BROKEN;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("BROKEN - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR BROKEN - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "OVC", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_OVERCAST;
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
GfLogDebug("OVERCAST - cloudnumber = %i\n", _cloudnumber);
GfLogInfo(" METAR OVERCAST - cloudnumber = %i\n", _cloudnumber);
}
else if (!strncmp(m, "///", i = 3))
{
cl._coverage = ReWebMetarCloud::COVERAGE_NIL; // should we add 'unknown'?
}
else
return false;
{
// check for an implied coverage element
if (*m >= '0' && *m <= '9' &&
*(m+1) >= '0' && *(m+1) <= '9' &&
*(m+2) >= '0' && *(m+2) <= '9' &&
*(m+3) == ' ')
{
priorCoverage = cl._coverage;
_cloudnumber = _cloudnumber + 1;
i = 0;
}
else
return false;
}
m += i;
if (!strncmp(m, "///", 3)) // vis not measurable (e.g. because of heavy snowing)
{
m += 3, i = -1;
i = 60;
}
else if (!strncmp(m, "CB", 2))
m +=2, i = -1;
else if(!strncmp(m, "TCU", 3))
m += 3, i = -1;
else if (scanBoundary(&m))
{
@ -977,7 +1065,7 @@ bool ReWebMetar::scanSkyCondition()
{
cl._altitude = 120 * 100 * 0.3048;
i = -1;
GfLogDebug("Cl.altitude = %.3f\n", cl._altitude);
GfLogInfo(" METAR Cl.altitude = %.3f\n", cl._altitude);
}
else
return true; // ignore single OVC/BKN/...
@ -1003,7 +1091,7 @@ bool ReWebMetar::scanSkyCondition()
else
cl._altitude = 1500;
GfLogDebug("Alitude = %.3f i = %i\n", cl._altitude, i);
GfLogInfo(" METAR Altitude = %.3f i = %i\n", cl._altitude, i);
const struct Token *a;
if ((a = scanToken(&m, cloud_types)))
@ -1017,6 +1105,12 @@ bool ReWebMetar::scanSkyCondition()
if (!strncmp(m, "///", 3))
m += 3;
if(!strncmp(m, "TCU", 3))
m += 3;
if(!strncmp(m, "CB", 2))
m += 2;
if (!scanBoundary(&m))
if (_cloudnumber < 1)
return false;
@ -1027,24 +1121,24 @@ bool ReWebMetar::scanSkyCondition()
{
_cloud1 = cl.getCoverage();
_cloud_altitude1 = cl.getAltitude_m();
GfLogDebug("WebMetar Cloud 1 = %i - Cloud Altitude = %.3f\n", _cloud1, _cloud_altitude1);
GfLogInfo(" METAR Cloud 1 = %i - Cloud Altitude = %.3f\n", _cloud1, _cloud_altitude1);
}
else if(_cloudnumber == 2)
{
_cloud2 = cl.getCoverage();
_cloud_altitude2 = cl.getAltitude_m();
GfLogDebug("WebMetar Cloud 2 = %i - Cloud Altitude = %.3f\n", _cloud2, _cloud_altitude2);
GfLogInfo(" METAR Cloud 2 = %i - Cloud Altitude = %.3f\n", _cloud2, _cloud_altitude2);
}
else if (_cloudnumber == 3)
{
_cloud3 = cl.getCoverage();
_cloud_altitude3 = cl.getAltitude_m();
GfLogDebug("WebMetar Cloud 3 = %i - Cloud Altitude = %.3f\n", _cloud3, _cloud_altitude3);
GfLogInfo(" METAR Cloud 3 = %i - Cloud Altitude = %.3f\n", _cloud3, _cloud_altitude3);
}
GfLogInfo(" METAR _m = %s\n", _m);
_m = m;
_grpcount++;
return true;
}
@ -1057,6 +1151,17 @@ bool ReWebMetar::scanTemperature()
char *m = _m;
int sign = 1, temp, dew;
/*std::string s = "M/0123456789";
for (int i=0; i<7; ++i)
{
if (*(m+i) == ' ')
break;
if (s.find(*(m+i)) == std::string::npos)
return true; // nope, bail
}*/
if (!strncmp(m, "XX/XX", 5))
{ // not spec compliant!
_m += 5;
@ -1064,10 +1169,30 @@ bool ReWebMetar::scanTemperature()
return scanBoundary(&_m);
}
if (!strncmp(m, "/////", 5))
{
// sensor failure... assume standard temperature
_temp = 15.0;
_dewp = 3.0;
_m += 5;
GfLogInfo(" METAR standard temperature = %.2f - dew point = %.2f\n", _temp, _dewp);
return scanBoundary(&_m);
}
// maintenance flag
if (*m == 'M' && *(m+1) == ' ')
{
_m++;
return scanBoundary(&_m);
}
if (*m == 'M')
m++, sign = -1;
if (!scanNumber(&m, &temp, 2))
if (!scanNumber(&m, &temp, 1, 2))
return false;
temp *= sign;
@ -1078,7 +1203,9 @@ bool ReWebMetar::scanTemperature()
if (!scanBoundary(&m))
{
if (!strncmp(m, "XX", 2)) // not spec compliant!
m += 2, sign = 0, dew = temp;
m += 2, sign = 0, dew = temp - 10;
else if (!strncmp(m, "//", 2)) // sensor failure... assume relative dew point
m += 2, sign = 0, dew = temp - 10;
else
{
sign = 1;
@ -1086,7 +1213,7 @@ bool ReWebMetar::scanTemperature()
if (*m == 'M')
m++, sign = -1;
if (!scanNumber(&m, &dew, 2))
if (!scanNumber(&m, &dew, 1, 2))
return false;
}
@ -1099,8 +1226,8 @@ bool ReWebMetar::scanTemperature()
_temp = temp;
_m = m;
_grpcount++;
GfLogDebug("Temperature = %.3f - Dew point = %.3f\n", _temp, _dewp);
GfLogInfo(" METAR Temperature = %.3f - Dew point = %.3f\n", _temp, _dewp);
return true;
}
@ -1114,6 +1241,8 @@ double ReWebMetar::getRelHumidity() const
double dewp = pow(10.0, 7.5 * _dewp / (237.7 + _dewp));
double temp = pow(10.0, 7.5 * _temp / (237.7 + _temp));
GfLogInfo(" METAR relative humidity = %.2f\n", dewp * 100 / temp);
return dewp * 100 / temp;
}
@ -1124,32 +1253,34 @@ bool ReWebMetar::scanPressure()
GfLogDebug("Start scan Pressure ...\n");
char *m = _m;
double factor;
int press, i;
bool unitProvided = true;
bool valueProvided = true;
//_pressure = 101300.0;
int press, i;
if (*m == '\0')
{
_pressure = 101300.0; // pressure not provided... assume standard pressure
return true;
}
if (*m == 'A')
factor = 3386.388640341 / 100;
{
factor = 3386.388640341 / 100.0;
m++;
}
else if (*m == 'Q')
factor = 100;
{
factor = 100.0;
m++;
}
else
return false;
m++;
if (!scanNumber(&m, &press, 2))
return false;
press *= 100;
unitProvided = false;
if (*m == ' ') // ignore space
{
m++;
}
if (!strncmp(m, "////", 4))
{
@ -1169,20 +1300,24 @@ bool ReWebMetar::scanPressure()
// sensor failure... assume standard pressure
if (*(m - 1) == 'A')
{
press = 2992;
}
else
{
press = 1013;
}
}
}
if (press < 100)
{
// 2-digit pressure may have further data following
press *= 100;
if (!strncmp(m, "//", 2)) // not spec compliant!
m += 2;
else if (scanNumber(&m, &i, 2))
press += i;
if (press < 100)
{
press *= 100;
if (!strncmp(m, "//", 2)) // not spec compliant!
m += 2;
else if (scanNumber(&m, &i, 2))
press += i;
}
}
if (*m == ',' || *m == '=') // ignore trailing comma, equals
@ -1195,28 +1330,11 @@ bool ReWebMetar::scanPressure()
if (!unitProvided)
factor = (press > 2000 ? 3386.388640341 / 100.0 : 100.0);
_pressure = (press * factor);
_pressure = press * factor;
GfLogInfo(" METAR Pressure = %g\n", _pressure);
_m = m;
return true;
/*if (!strncmp(m, "//", 2)) // not spec compliant!
m += 2;
else if (scanNumber(&m, &i, 2))
press += i;
else
return false;
if (!scanBoundary(&m))
return false;
_pressure = press * factor;
_m = m;
GfLogDebug("Pressure = %.3f\n", _pressure);
_grpcount++;
return true;*/
}
static const char *runway_deposit[] =
@ -1345,12 +1463,10 @@ bool ReWebMetar::scanRunwayReport()
_runways[id]._friction_string = r._friction_string;
_runways[id]._comment = r._comment;
_m = m;
_grpcount++;
return true;
}
// WS (ALL RWYS?|RWY ?\d\d[LCR]?)?
bool ReWebMetar::scanWindShear()
{
@ -1370,8 +1486,10 @@ bool ReWebMetar::scanWindShear()
m += 3;
if (!scanBoundary(&m))
return false;
if (strncmp(m, "RWY", 3))
return false;
m += 3;
if (*m == 'S')
@ -1523,6 +1641,8 @@ bool ReWebMetar::scanBoundary(char **s)
while (isspace(**s))
(*s)++;
GfLogDebug("Scan Boundary !!!\n");
return true;
}
@ -1541,8 +1661,10 @@ int ReWebMetar::scanNumber(char **src, int *num, int min, int max)
*num = *num * 10 + *s++ - '0';
}
for (; i < max && isdigit(*s); i++)
for (i= 1; i < max && isdigit(*s); i++)
{
*num = *num * 10 + *s++ - '0';
}
*src = s;
@ -1672,7 +1794,8 @@ void ReWebMetar::density()
tas = 12334;
_density = ((1 - ( 0.3783 * relhumidity * tas) / pressure) * pressure) / (287.058 * (temp + 273.15)) / 100;
GfLogDebug("Density = %.3f - relative humidity = %.3f\n", _density, relhumidity);
_relativehumidity = relhumidity;
GfLogDebug(" METAR Density = %.3f - relative humidity = %.3f\n", _density, _relativehumidity);
}
// find longest match of str in list
@ -1717,13 +1840,13 @@ ReWebMetarCloud::Coverage ReWebMetarCloud::getCoverage( const std::string & cove
return COVERAGE_NIL;
}
const char * ReWebMetarCloud::COVERAGE_NIL_STRING = "nil";
const char * ReWebMetarCloud::COVERAGE_CLEAR_STRING = "clear";
const char * ReWebMetarCloud::COVERAGE_NIL_STRING = "nil";
const char * ReWebMetarCloud::COVERAGE_CLEAR_STRING = "clear";
const char * ReWebMetarCloud::COVERAGE_CIRRUS_STRING = "cirrus";
const char * ReWebMetarCloud::COVERAGE_FEW_STRING = "few";
const char * ReWebMetarCloud::COVERAGE_FEW_STRING = "few";
const char * ReWebMetarCloud::COVERAGE_SCATTERED_STRING = "scattered";
const char * ReWebMetarCloud::COVERAGE_BROKEN_STRING = "broken";
const char * ReWebMetarCloud::COVERAGE_OVERCAST_STRING = "overcast";
const char * ReWebMetarCloud::COVERAGE_BROKEN_STRING = "broken";
const char * ReWebMetarCloud::COVERAGE_OVERCAST_STRING = "overcast";
void ReWebMetarVisibility::set(double dist, int dir, int mod, int tend)
{
@ -1734,5 +1857,7 @@ void ReWebMetarVisibility::set(double dist, int dir, int mod, int tend)
_modifier = mod;
if (tend != 1)
_tendency = tend;
GfLogInfo(" METAR visibility set distance = %.2f - direction = %i - modifier = %i - tendency = %.2d\n", _distance, _direction, _modifier, _tendency);
}

View File

@ -245,7 +245,7 @@ public:
inline double getTemperature_F() const { return _temp == WebMetarNaN ? WebMetarNaN : 1.8 * _temp + 32; }
inline double getDewpoint_C() const { return _dewp; }
inline double getDewpoint_F() const { return _dewp == WebMetarNaN ? WebMetarNaN : 1.8 * _dewp + 32; }
inline double getPressure_hPa() const { return _pressure == WebMetarNaN ? WebMetarNaN : _pressure / 100; }
inline double getPressure_hPa() const { return _pressure == WebMetarNaN ? WebMetarNaN : _pressure; }
inline double getPressure_inHg() const { return _pressure == WebMetarNaN ? WebMetarNaN : _pressure * 0.0002952998330101010; }
inline double getDensity_C() const { return _density; }
@ -254,6 +254,9 @@ public:
inline int getSnow() const { return _snow; }
inline bool getCAVOK() const { return _cavok; }
inline double getRelativeHumidity() const { return _relativehumidity; }
double getRelHumidity() const;
inline const std::vector<ReWebMetarCloud>& getClouds() const { return _clouds; }
@ -263,7 +266,6 @@ public:
protected:
std::string _url;
int _grpcount;
bool _x_proxy;
char* _data;
char* _m;
@ -287,6 +289,7 @@ protected:
int _rain;
int _hail;
int _snow;
double _relativehumidity;
int _cloudnumber;
int _cloud1;
double _cloud_altitude1;