#include <string>
#include <time.h>
+#include <cstring>
#include <simgear/io/sg_socket.hxx>
#include <simgear/debug/logstream.hxx>
{
struct tm now;
time_t now_sec = time(0);
-#if defined( _MSC_VER ) || defined ( __MINGW32__ )
+#ifdef _WIN32
now = *gmtime(&now_sec);
#else
gmtime_r(&now_sec, &now);
const int buflen = 512;
char buf[2 * buflen];
- string host = proxy.empty() ? "weather.noaa.gov" : proxy;
+ string metar_server = "weather.noaa.gov";
+ string host = proxy.empty() ? metar_server : proxy;
string path = "/pub/data/observations/metar/stations/";
path += string(id) + ".TXT";
- _url = "http://weather.noaa.gov" + path;
+ _url = "http://" + metar_server + path;
SGSocket *sock = new SGSocket(host, port.empty() ? "80" : port, "tcp");
sock->set_timeout(10000);
string get = "GET ";
if (!proxy.empty())
- get += "http://weather.noaa.gov";
+ get += "http://" + metar_server;
sprintf(buf, "%ld", time);
get += path + " HTTP/1.0\015\012X-Time: " + buf + "\015\012";
+ get += "Host: " + metar_server + "\015\012";
if (!auth.empty())
get += "Proxy-Authorization: " + auth + "\015\012";
int modifier = SGMetarVisibility::EQUALS;
// \d{4}(N|NE|E|SE|S|SW|W|NW)?
if (scanNumber(&m, &i, 4)) {
- if (*m == 'E')
+ if( strncmp( m, "NDV",3 ) == 0 ) {
+ m+=3; // tolerate NDV (no directional validation)
+ } else if (*m == 'E') {
m++, dir = 90;
- else if (*m == 'W')
+ } else if (*m == 'W') {
m++, dir = 270;
- else if (*m == 'N') {
+ } else if (*m == 'N') {
m++;
if (*m == 'E')
m++, dir = 45;
m++, dir = 225;
else
dir = 180;
- }
+ }
if (i == 0)
i = 50, modifier = SGMetarVisibility::LESS_THAN;
else if (i == 9999)
r._max_visibility._distance = to;
if (*m == '/') // this is not in the spec!
- *m++;
+ m++;
if (*m == 'D')
m++, r._min_visibility._tendency = SGMetarVisibility::DECREASING;
else if (*m == 'N')
static const struct Token special[] = {
{ "NSW", "no significant weather" },
- { "VCSH", "showers in the vicinity" },
- { "VCTS", "thunderstorm in the vicinity" },
+/* { "VCSH", "showers in the vicinity" },
+ { "VCTS", "thunderstorm in the vicinity" }, */
{ 0, 0 }
};
char *m = _m;
string weather;
const struct Token *a;
+
if ((a = scanToken(&m, special))) {
if (!scanBoundary(&m))
return false;
}
string pre, post;
- int intensity = 0;
+ struct Weather w;
if (*m == '-')
- m++, pre = "light ", intensity = 1;
+ m++, pre = "light ", w.intensity = LIGHT;
else if (*m == '+')
- m++, pre = "heavy ", intensity = 3;
+ m++, pre = "heavy ", w.intensity = HEAVY;
else if (!strncmp(m, "VC", 2))
- m += 2, post = "in the vicinity ";
+ m += 2, post = "in the vicinity ", w.vincinity=true;
else
- pre = "moderate ", intensity = 2;
+ pre = "moderate ", w.intensity = MODERATE;
int i;
for (i = 0; i < 3; i++) {
if (!(a = scanToken(&m, description)))
break;
+ w.descriptions.push_back(a->id);
weather += string(a->text) + " ";
}
+
for (i = 0; i < 3; i++) {
if (!(a = scanToken(&m, phenomenon)))
break;
+ w.phenomena.push_back(a->id);
weather += string(a->text) + " ";
if (!strcmp(a->id, "RA"))
- _rain = intensity;
+ _rain = w.intensity;
else if (!strcmp(a->id, "HA"))
- _hail = intensity;
+ _hail = w.intensity;
else if (!strcmp(a->id, "SN"))
- _snow = intensity;
+ _snow = w.intensity;
}
if (!weather.length())
return false;
weather = pre + weather + post;
weather.erase(weather.length() - 1);
_weather.push_back(weather);
+ if( w.phenomena.size() > 0 )
+ _weather2.push_back( w );
_grpcount++;
return true;
}
{ 0, 0 }
};
-
+#include <iostream>
// (FEW|SCT|BKN|OVC|SKC|CLR|CAVOK|VV)([0-9]{3}|///)?[:cloud_type:]?
bool SGMetar::scanSkyCondition()
{
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;
return false;
if (i == 3) {
- cl._coverage = 0;
+ cl._coverage = SGMetarCloud::COVERAGE_CLEAR;
_clouds.push_back(cl);
} else {
_cavok = true;
if (!strncmp(m, "VV", i = 2)) // vertical visibility
;
else if (!strncmp(m, "FEW", i = 3))
- cl._coverage = 1;
+ cl._coverage = SGMetarCloud::COVERAGE_FEW;
else if (!strncmp(m, "SCT", i = 3))
- cl._coverage = 2;
+ cl._coverage = SGMetarCloud::COVERAGE_SCATTERED;
else if (!strncmp(m, "BKN", i = 3))
- cl._coverage = 3;
+ cl._coverage = SGMetarCloud::COVERAGE_BROKEN;
else if (!strncmp(m, "OVC", i = 3))
- cl._coverage = 4;
+ cl._coverage = SGMetarCloud::COVERAGE_OVERCAST;
else
return false;
m += i;
} else if (!scanNumber(&m, &i, 3))
i = -1;
- if (cl._coverage == -1) {
+ if (cl._coverage == SGMetarCloud::COVERAGE_NIL) {
if (!scanBoundary(&m))
return false;
if (i == -1) // 'VV///'
}
-void SGMetarCloud::set(double alt, int cov)
+void SGMetarCloud::set(double alt, Coverage cov)
{
_altitude = alt;
if (cov != -1)
_coverage = cov;
}
+SGMetarCloud::Coverage SGMetarCloud::getCoverage( const std::string & coverage )
+{
+ if( coverage == "clear" ) return COVERAGE_CLEAR;
+ if( coverage == "few" ) return COVERAGE_FEW;
+ if( coverage == "scattered" ) return COVERAGE_SCATTERED;
+ if( coverage == "broken" ) return COVERAGE_BROKEN;
+ if( coverage == "overcast" ) return COVERAGE_OVERCAST;
+ return COVERAGE_NIL;
+}
+
+const char * SGMetarCloud::COVERAGE_NIL_STRING = "nil";
+const char * SGMetarCloud::COVERAGE_CLEAR_STRING = "clear";
+const char * SGMetarCloud::COVERAGE_FEW_STRING = "few";
+const char * SGMetarCloud::COVERAGE_SCATTERED_STRING = "scattered";
+const char * SGMetarCloud::COVERAGE_BROKEN_STRING = "broken";
+const char * SGMetarCloud::COVERAGE_OVERCAST_STRING = "overcast";
void SGMetarVisibility::set(double dist, int dir, int mod, int tend)
{