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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<string>& getWeather() { return _weather; }
|
||||
|
||||
protected:
|
||||
string _url;
|
||||
int _grpcount;
|
||||
char *_data;
|
||||
char *_m;
|
||||
|
||||
Reference in New Issue
Block a user