92ostream&
operator<<(ostream& s,
const SGMetarVisibility& v)
95 int m = v.getModifier();
97 if (m == SGMetarVisibility::GREATER_THAN)
99 else if (m == SGMetarVisibility::LESS_THAN)
105 double dist =
rnd(v.getVisibility_m(), 1);
107 buf <<
rnd(dist, 1) <<
" m";
109 buf <<
rnd(dist / 1000.0, -1) <<
" km";
111 const char *dir =
"";
113 if ((
i = v.getDirection()) != -1) {
117 buf <<
"\t\t\t\t\t" << mod <<
rnd(v.getVisibility_sm(), -1) <<
" US-miles " << dir;
118 return s << buf.str();
130#define NaN SGMetarNaN
136 snprintf(buf, 256,
"--airport=%s ", m->getId());
140 snprintf(buf, 256,
"--start-date-gmt=%4d:%02d:%02d:%02d:%02d:00 ",
141 m->getYear(), m->getMonth(), m->getDay(),
142 m->getHour(), m->getMinute());
146 const char *coverage_string[5] = {
147 "clear",
"few",
"scattered",
"broken",
"overcast"
149 vector<SGMetarCloud> cv = m->getClouds();
150 vector<SGMetarCloud>::iterator cloud;
151 for (
i = 0, cloud = cv.begin();
i < 5;
i++) {
154 if (cloud != cv.end()) {
155 coverage = cloud->getCoverage();
156 altitude = coverage ? cloud->getAltitude_ft() + airport_elevation : -99999;
159 snprintf(buf, 256,
"--prop:/environment/clouds/layer[%d]/coverage=%s ",
i, coverage_string[coverage]);
161 snprintf(buf, 256,
"--prop:/environment/clouds/layer[%d]/elevation-ft=%.0lf ",
i,
altitude);
163 snprintf(buf, 256,
"--prop:/environment/clouds/layer[%d]/thickness-ft=500 ",
i);
170 int wind_dir = m->getWindDir();
171 double visibility = m->getMinVisibility().getVisibility_m();
172 double dewpoint = m->getDewpoint_C();
173 double temperature = m->getTemperature_C();
174 double pressure = m->getPressure_inHg();
175 double wind_speed = m->getWindSpeed_kt();
176 double elevation = -100;
177 for (
i = 0;
i < 3;
i++, elevation += 2000.0) {
178 snprintf(buf, 256,
"--prop:/environment/config/boundary/entry[%d]/",
i);
179 int pos = strlen(buf);
180 const int rem = 256 - pos;
182 snprintf(&buf[pos], rem,
"elevation-ft=%.0lf", elevation);
184 snprintf(&buf[pos], rem,
"turbulence-norm=%.0lf", 0.0);
187 if (visibility !=
NaN) {
188 snprintf(&buf[pos], rem,
"visibility-m=%.0lf", visibility);
191 if (temperature !=
NaN) {
192 snprintf(&buf[pos], rem,
"temperature-degc=%.0lf", temperature);
195 if (dewpoint !=
NaN) {
196 snprintf(&buf[pos], rem,
"dewpoint-degc=%.0lf", dewpoint);
199 if (pressure !=
NaN) {
200 snprintf(&buf[pos], rem,
"pressure-sea-level-inhg=%.0lf", pressure);
203 if (wind_dir !=
NaN) {
204 snprintf(&buf[pos], rem,
"wind-from-heading-deg=%d", wind_dir);
207 if (wind_speed !=
NaN) {
208 snprintf(&buf[pos], rem,
"wind-speed-kt=%.0lf", wind_speed);
214 int range_from = m->getWindRangeFrom();
215 int range_to = m->getWindRangeTo();
216 double gust_speed = m->getGustSpeed_kt();
217 if (wind_speed !=
NaN && wind_dir != -1) {
218 std::ostringstream os;
221 if (range_from != -1 && range_to != -1) {
222 os << range_from <<
":" << range_to;
227 os << std::setw(3) <<
"@" << wind_speed;
228 if (gust_speed !=
NaN)
229 os <<
":" << gust_speed;
230 args.push_back(os.str());
236 vector<string>::iterator arg;
237 for (
i = 0, arg = args.begin(); arg != args.end();
i++, arg++) {
238 cout <<
"\t" << *arg << endl;
304int main(
int argc,
char *argv[])
307 bool verbose =
false;
308 double elevation = 0.0;
315 string proxy_host, proxy_port;
318 Socket::initSockets();
321 http.setProxy(proxy_host,
atoi(proxy_port.c_str()));
323 for (
int i = 1;
i < argc;
i++) {
324 if (!strcmp(argv[
i],
"-h") || !strcmp(argv[
i],
"--help"))
326 else if (!strcmp(argv[
i],
"-v") || !strcmp(argv[
i],
"--verbose"))
328 else if (!strcmp(argv[
i],
"-r") || !strcmp(argv[
i],
"--report"))
330 else if (!strcmp(argv[
i],
"-c") || !strcmp(argv[
i],
"--command-line"))
332 else if (!strcmp(argv[
i],
"-e") || !strcmp(argv[
i],
"--elevation")) {
334 cerr <<
"-e option used without elevation" << endl;
337 elevation = strtod(argv[
i], 0);
339 else if (!strcmp(argv[
i],
"-s") || !strcmp(argv[
i],
"--string")) {
341 cerr <<
"-s option used with out string\n";
344 const char*
string = argv[
i];
345 SGMetar metar(
string);
349 static bool shown =
false;
350 if (verbose && !shown) {
351 cerr <<
"Proxy host: '" << proxy_host <<
"'" << endl;
352 cerr <<
"Proxy port: '" << proxy_port <<
"'" << endl << endl;
358 static const std::string NOAA_BASE_URL =
359 "https://tgftp.nws.noaa.gov/data/observations/metar/stations/";
360 HTTP::MemoryRequest* mr =
new HTTP::MemoryRequest
362 NOAA_BASE_URL + strutils::uppercase(argv[
i]) +
".TXT"
364 HTTP::Request_ptr own(mr);
365 http.makeRequest(mr);
368 SGTimeStamp start(SGTimeStamp::now());
369 while (start.elapsedMSec() < 8000) {
371 if( mr->isComplete() )
373 SGTimeStamp::sleepForMSec(1);
376 if( !mr->isComplete() )
377 throw sg_io_exception(
"metar download timed out");
378 if( mr->responseCode() != 200 )
380 std::cerr <<
"metar download failed: "
382 <<
" (" << mr->responseCode()
383 <<
" " << mr->responseReason() <<
")"
385 throw sg_io_exception(
"metar download failed");
388 SGMetar *m =
new SGMetar(mr->responseBody());
393 cerr <<
G "INPUT: " << m->getDataString() <<
"" N << endl;
395 const auto unused = m->getUnparsedData();
397 cerr <<
R "UNUSED: " << unused <<
"" N << endl;
406 }
catch (
const sg_io_exception& e) {
407 cerr <<
R "ERROR: " << e.getFormattedMessage().c_str() <<
"" N << endl << endl;