Fix problems parsing METAR strings that denote temporary sensor failures

1. Weather (normally blank, RA, SN, etc.) can be "//"
2. Cloud can be suffixed by "///", e.g. FEW045///

Also updated unit test.
This commit is contained in:
Richard Senior 2016-04-05 11:49:59 +01:00
parent 177c5ec709
commit 92a51059b4
2 changed files with 62 additions and 4 deletions

View File

@ -23,6 +23,16 @@
/** /**
* @file metar.cxx * @file metar.cxx
* Interface for encoded Meteorological Aerodrome Reports (METAR). * Interface for encoded Meteorological Aerodrome Reports (METAR).
*
* @see WMO-49
* Technical Regulations, Basic Documents No. 2 (WMO No. 49)
* Volume II - Meteorological Service for International Air Navigation
* http://library.wmo.int/pmb_ged/wmo_49-v2_2013_en.pdf
*
* Refer to Table A3-2 (Template for METAR and SPECI) following page 78.
*
* For general information:
* World Meteorological Organization http://library.wmo.int
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include <simgear_config.h> # include <simgear_config.h>
@ -465,6 +475,7 @@ bool SGMetar::scanRwyVisRange()
char *m = _m; char *m = _m;
int i; int i;
SGMetarRunway r; SGMetarRunway r;
if (*m++ != 'R') if (*m++ != 'R')
return false; return false;
if (!scanNumber(&m, &i, 2)) if (!scanNumber(&m, &i, 2))
@ -582,6 +593,14 @@ bool SGMetar::scanWeather()
string weather; string weather;
const struct Token *a; const struct Token *a;
// @see WMO-49 Section 4.4.2.9
// Denotes a temporary failure of the sensor
if (!strncmp(m, "// ", 3)) {
_m += 3;
_grpcount++;
return false;
}
if ((a = scanToken(&m, special))) { if ((a = scanToken(&m, special))) {
if (!scanBoundary(&m)) if (!scanBoundary(&m))
return false; return false;
@ -591,7 +610,7 @@ bool SGMetar::scanWeather()
} }
string pre, post; string pre, post;
struct Weather w; struct Weather w;
if (*m == '-') if (*m == '-')
m++, pre = "light ", w.intensity = LIGHT; m++, pre = "light ", w.intensity = LIGHT;
else if (*m == '+') else if (*m == '+')
@ -685,7 +704,7 @@ bool SGMetar::scanSkyCondition()
return false; return false;
if (i == 3) { if (i == 3) {
cl._coverage = SGMetarCloud::COVERAGE_CLEAR; cl._coverage = SGMetarCloud::COVERAGE_CLEAR;
_clouds.push_back(cl); _clouds.push_back(cl);
} else { } else {
_cavok = true; _cavok = true;
@ -716,7 +735,7 @@ bool SGMetar::scanSkyCondition()
} else if (!scanNumber(&m, &i, 3)) } else if (!scanNumber(&m, &i, 3))
i = -1; i = -1;
if (cl._coverage == SGMetarCloud::COVERAGE_NIL) { if (cl._coverage == SGMetarCloud::COVERAGE_NIL) {
if (!scanBoundary(&m)) if (!scanBoundary(&m))
return false; return false;
if (i == -1) // 'VV///' if (i == -1) // 'VV///'
@ -735,9 +754,15 @@ bool SGMetar::scanSkyCondition()
cl._type = a->id; cl._type = a->id;
cl._type_long = a->text; cl._type_long = a->text;
} }
// @see WMO-49 Section 4.5.4.5
// Denotes temporary failure of sensor and covers cases like FEW045///
if (!strncmp(m, "///", 3))
m += 3;
if (!scanBoundary(&m)) if (!scanBoundary(&m))
return false; return false;
_clouds.push_back(cl); _clouds.push_back(cl);
_m = m; _m = m;
_grpcount++; _grpcount++;
return true; return true;

View File

@ -58,6 +58,37 @@ void test_basic()
COMPARE(m1.getWindDir(), 270); COMPARE(m1.getWindDir(), 270);
FUZZY_COMPARE(m1.getWindSpeed_kt(), 12, TEST_EPSILON); FUZZY_COMPARE(m1.getWindSpeed_kt(), 12, TEST_EPSILON);
COMPARE(m1.getWeather().size(), 1);
COMPARE(m1.getClouds().size(), 2);
FUZZY_COMPARE(m1.getTemperature_C(), 10, TEST_EPSILON);
FUZZY_COMPARE(m1.getDewpoint_C(), 5, TEST_EPSILON);
FUZZY_COMPARE(m1.getPressure_hPa(), 1025, TEST_EPSILON);
}
void test_sensor_failure_weather()
{
SGMetar m1("2011/10/20 11:25 EHAM 201125Z 27012KT 240V300 9999 // FEW025CB SCT048 10/05 Q1025");
COMPARE(m1.getWindDir(), 270);
FUZZY_COMPARE(m1.getWindSpeed_kt(), 12, TEST_EPSILON);
COMPARE(m1.getWeather().size(), 0);
COMPARE(m1.getClouds().size(), 2);
FUZZY_COMPARE(m1.getTemperature_C(), 10, TEST_EPSILON);
FUZZY_COMPARE(m1.getDewpoint_C(), 5, TEST_EPSILON);
FUZZY_COMPARE(m1.getPressure_hPa(), 1025, TEST_EPSILON);
}
void test_sensor_failure_cloud()
{
SGMetar m1("2011/10/20 11:25 EHAM 201125Z 27012KT 240V300 9999 FEW025CB/// SCT048/// 10/05 Q1025");
COMPARE(m1.getWindDir(), 270);
FUZZY_COMPARE(m1.getWindSpeed_kt(), 12, TEST_EPSILON);
COMPARE(m1.getWeather().size(), 0);
COMPARE(m1.getClouds().size(), 2);
FUZZY_COMPARE(m1.getTemperature_C(), 10, TEST_EPSILON); FUZZY_COMPARE(m1.getTemperature_C(), 10, TEST_EPSILON);
FUZZY_COMPARE(m1.getDewpoint_C(), 5, TEST_EPSILON); FUZZY_COMPARE(m1.getDewpoint_C(), 5, TEST_EPSILON);
FUZZY_COMPARE(m1.getPressure_hPa(), 1025, TEST_EPSILON); FUZZY_COMPARE(m1.getPressure_hPa(), 1025, TEST_EPSILON);
@ -66,7 +97,9 @@ void test_basic()
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
try { try {
test_basic(); test_basic();
test_sensor_failure_weather();
test_sensor_failure_cloud();
} catch (sg_exception& e) { } catch (sg_exception& e) {
cerr << "got exception:" << e.getMessage() << endl; cerr << "got exception:" << e.getMessage() << endl;
return -1; return -1;