From 70dbbf52f020a23f2590fa56d27b713f0d266a82 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 23 Feb 2004 20:07:20 +0000 Subject: [PATCH] Melchior FRANZ: Here are some updates for the metar class: - support for empty visibility group - support for 4-alnum IACO ids (rather than only 4-alpha) - better diagnosis in exception messages - check for 404 http response - replace last constant by constants.h definition --- simgear/environment/metar.cxx | 48 ++++++++++++++++++++++++----------- simgear/environment/metar.hxx | 11 +++----- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/simgear/environment/metar.cxx b/simgear/environment/metar.cxx index a3e01623..8e67bc66 100644 --- a/simgear/environment/metar.cxx +++ b/simgear/environment/metar.cxx @@ -47,7 +47,7 @@ * @par Examples: * @code * SGMetar *m = new SGMetar("METAR KSFO 061656Z 19004KT 9SM SCT100 OVC200 08/03 A3013"); - * double t = m->getTemperature(); + * double t = m->getTemperature_F(); * delete m; * * SGMetar n("KSFO"); @@ -71,15 +71,15 @@ SGMetar::SGMetar(const char *m) : _dewp(NaN), _pressure(NaN) { - int i; - if (isalpha(m[0]) && isalpha(m[1]) && isalpha(m[2]) && isalpha(m[3]) && !m[4]) { - for (i = 0; i < 4; i++) + if (isalnum(m[0]) && isalnum(m[1]) && isalnum(m[2]) && isalnum(m[3]) && !m[4]) { + for (int i = 0; i < 4; i++) _icao[i] = toupper(m[i]); _icao[4] = '\0'; _data = loadData(_icao); } else { - _data = new char[strlen(m) + 1]; + _data = new char[strlen(m) + 2]; // make room for " \0" strcpy(_data, m); + _url = _data; } normalizeData(); @@ -92,8 +92,10 @@ SGMetar::SGMetar(const char *m) : // METAR header scanType(); - if (!scanId() || !scanDate()) - throw sg_io_exception("metar data incomplete"); + if (!scanId() || !scanDate()) { + delete[] _data; + throw sg_io_exception("metar data incomplete (" + _url + ')'); + } scanModifier(); // base set @@ -116,8 +118,11 @@ SGMetar::SGMetar(const char *m) : scanRemainder(); scanRemark(); - if (_grpcount < 4) - throw sg_io_exception("metar data invalid"); + if (_grpcount < 4) { + delete[] _data; + throw sg_io_exception("metar data invalid (" + _url + ')'); + } + _url = ""; } @@ -148,14 +153,15 @@ char *SGMetar::loadData(const char *id) string host = "weather.noaa.gov"; string path = "/pub/data/observations/metar/stations/"; path += string(id) + ".TXT"; + _url = "http://" + host + path; + string get = string("GET ") + path + " HTTP/1.0\r\n\r\n"; SGSocket *sock = new SGSocket(host, "80", "tcp"); sock->set_timeout(10000); if (!sock->open(SG_IO_OUT)) { delete sock; - string err = "failed to load metar data from http://" + host + path; - throw sg_io_exception(err); + throw sg_io_exception("failed to load metar data from " + _url); } sock->writestring(get.c_str()); @@ -177,8 +183,13 @@ char *SGMetar::loadData(const char *id) sock->close(); delete sock; - char *metar = new char[strlen(buf) + 1]; - strcpy(metar, buf); + char *b = buf; + scanBoundary(&b); + if (*b == '<') + throw sg_io_exception("no metar data available from " + _url); + + char *metar = new char[strlen(b) + 2]; // make room for " \0" + strcpy(metar, b); return metar; } @@ -256,8 +267,9 @@ bool SGMetar::scanType() bool SGMetar::scanId() { char *m = _m; - if (!(isupper(*m++) && isupper(*m++) && isupper(*m++) && isupper(*m++))) - return false; + for (int i = 0; i < 4; m++, i++) + if (!(isalpha(*m) || isdigit(*m))) + return false; if (!scanBoundary(&m)) return false; strncpy(_icao, _m, 4); @@ -387,6 +399,12 @@ bool SGMetar::scanVariability() bool SGMetar::scanVisibility() // TODO: if only directed vis are given, do still set min/max { + if (!strncmp(_m, "//// ", 5)) { // spec compliant? + _m += 5; + _grpcount++; + return true; + } + char *m = _m; double distance; int i, dir = -1; diff --git a/simgear/environment/metar.hxx b/simgear/environment/metar.hxx index c1e29f21..29efbf73 100644 --- a/simgear/environment/metar.hxx +++ b/simgear/environment/metar.hxx @@ -148,12 +148,6 @@ protected: class SGMetar { public: SGMetar(const char *m); - - // The following contructor is tempting, but it is not - // correct, it creates an anonymous instance of SGMetar and - // then immediately throws it away. - // SGMetar(const string m) { SGMetar(m.c_str()); } - ~SGMetar(); enum ReportType { @@ -175,12 +169,12 @@ public: inline int getWindDir() const { return _wind_dir; } inline double getWindSpeed_mps() const { return _wind_speed; } - inline double getWindSpeed_kmh() const { return _wind_speed == NaN ? NaN : _wind_speed * 3.6; } + inline double getWindSpeed_kmh() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KMH; } inline double getWindSpeed_kt() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KT; } inline double getWindSpeed_mph() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_MPH; } inline double getGustSpeed_mps() const { return _gust_speed; } - inline double getGustSpeed_kmh() const { return _gust_speed == NaN ? NaN : _gust_speed * 3.6; } + inline double getGustSpeed_kmh() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KMH; } inline double getGustSpeed_kt() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KT; } inline double getGustSpeed_mph() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_MPH; } @@ -206,6 +200,7 @@ public: inline vector& getWeather() { return _weather; } protected: + string _url; int _grpcount; char *_data; char *_m; -- 2.39.5