From 92a51059b4a1dc19c78331ae34abcab676bcf766 Mon Sep 17 00:00:00 2001 From: Richard Senior Date: Tue, 5 Apr 2016 11:49:59 +0100 Subject: [PATCH] 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. --- simgear/environment/metar.cxx | 31 +++++++++++++++++++++++--- simgear/environment/test_metar.cxx | 35 +++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/simgear/environment/metar.cxx b/simgear/environment/metar.cxx index ec4375ab..4e96839c 100644 --- a/simgear/environment/metar.cxx +++ b/simgear/environment/metar.cxx @@ -23,6 +23,16 @@ /** * @file metar.cxx * 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 # include @@ -465,6 +475,7 @@ bool SGMetar::scanRwyVisRange() char *m = _m; int i; SGMetarRunway r; + if (*m++ != 'R') return false; if (!scanNumber(&m, &i, 2)) @@ -582,6 +593,14 @@ bool SGMetar::scanWeather() string weather; 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 (!scanBoundary(&m)) return false; @@ -591,7 +610,7 @@ bool SGMetar::scanWeather() } string pre, post; - struct Weather w; + struct Weather w; if (*m == '-') m++, pre = "light ", w.intensity = LIGHT; else if (*m == '+') @@ -685,7 +704,7 @@ bool SGMetar::scanSkyCondition() return false; if (i == 3) { - cl._coverage = SGMetarCloud::COVERAGE_CLEAR; + cl._coverage = SGMetarCloud::COVERAGE_CLEAR; _clouds.push_back(cl); } else { _cavok = true; @@ -716,7 +735,7 @@ bool SGMetar::scanSkyCondition() } else if (!scanNumber(&m, &i, 3)) i = -1; - if (cl._coverage == SGMetarCloud::COVERAGE_NIL) { + if (cl._coverage == SGMetarCloud::COVERAGE_NIL) { if (!scanBoundary(&m)) return false; if (i == -1) // 'VV///' @@ -735,9 +754,15 @@ bool SGMetar::scanSkyCondition() cl._type = a->id; 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)) return false; _clouds.push_back(cl); + _m = m; _grpcount++; return true; diff --git a/simgear/environment/test_metar.cxx b/simgear/environment/test_metar.cxx index 814094b2..41934188 100644 --- a/simgear/environment/test_metar.cxx +++ b/simgear/environment/test_metar.cxx @@ -58,6 +58,37 @@ void test_basic() COMPARE(m1.getWindDir(), 270); 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.getDewpoint_C(), 5, TEST_EPSILON); FUZZY_COMPARE(m1.getPressure_hPa(), 1025, TEST_EPSILON); @@ -66,7 +97,9 @@ void test_basic() int main(int argc, char* argv[]) { try { - test_basic(); + test_basic(); + test_sensor_failure_weather(); + test_sensor_failure_cloud(); } catch (sg_exception& e) { cerr << "got exception:" << e.getMessage() << endl; return -1; -- 2.39.5