//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
-// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#include <iomanip>
#include <sstream>
+#include <iostream>
+#include <string.h>
+#include <time.h>
+#include <cstdlib>
+#include <cstdio>
+
+#include <boost/algorithm/string.hpp>
-#include <simgear/debug/logstream.hxx>
-#include <simgear/structure/exception.hxx>
#include <simgear/environment/metar.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include <simgear/io/HTTPClient.hxx>
+#include <simgear/io/HTTPMemoryRequest.hxx>
+#include <simgear/io/raw_socket.hxx>
+#include <simgear/timing/timestamp.hxx>
using namespace std;
+using namespace simgear;
// text color
-#if defined(__linux__) || defined( __sun__ ) ||defined(__CYGWIN__) || defined( __FreeBSD__ )
+#if defined(__linux__) || defined(__sun) || defined(__CYGWIN__) \
+ || defined( __FreeBSD__ ) || defined ( sgi )
# define R "\033[31;1m" // red
# define G "\033[32;1m" // green
# define Y "\033[33;1m" // yellow
double rnd(double r, int g = 0)
{
double f = pow(10.0, g);
- return f * rint(r / f);
+ return f * floor(r / f + 0.5);
}
-ostream& operator<<(ostream& s, SGMetarVisibility& v)
+ostream& operator<<(ostream& s, const SGMetarVisibility& v)
{
ostringstream buf;
int m = v.getModifier();
// date/time
int year = m->getYear();
int month = m->getMonth();
- cout << "Report time:\t\t";
- if (year != -1 && month != -1)
- cout << year << '/' << month << '/' << m->getDay();
+ cout << "Report time:\t\t" << year << '/' << month << '/' << m->getDay();
cout << ' ' << m->getHour() << ':';
cout << setw(2) << setfill('0') << m->getMinute() << " UTC" << endl;
// directed visibility
- SGMetarVisibility *dirvis = m->getDirVisibility();
+ const SGMetarVisibility *dirvis = m->getDirVisibility();
for (i = 0; i < 8; i++, dirvis++)
if (dirvis->getVisibility_m() != NaN)
cout << "\t\t\t" << *dirvis << endl;
// assemble surface string
vector<string> surface;
- if ((s = rwy.getDeposit()) && strlen(s))
+ if ((s = rwy.getDepositString()) && strlen(s))
surface.push_back(s);
if ((s = rwy.getExtentString()) && strlen(s))
surface.push_back(s);
if ((d = rwy.getDepth()) != NaN) {
- sprintf(buf, "%.0lf mm", d * 1000.0);
+ sprintf(buf, "%.1lf mm", d * 1000.0);
surface.push_back(buf);
}
if ((s = rwy.getFrictionString()) && strlen(s))
surface.push_back(buf);
}
- if (surface.size()) {
+ if (! surface.empty()) {
vector<string>::iterator rwysurf = surface.begin();
for (i = 0; rwysurf != surface.end(); rwysurf++, i++) {
if (i)
}
-void help()
+void getproxy(string& host, string& port)
+{
+ host = "";
+ port = "80";
+
+ const char *p = getenv("http_proxy");
+ if (!p)
+ return;
+ while (isspace(*p))
+ p++;
+ if (!strncmp(p, "http://", 7))
+ p += 7;
+ if (!*p)
+ return;
+
+ char s[256], *t;
+ strncpy(s, p, 255);
+ s[255] = '\0';
+
+ for (t = s + strlen(s); t > s; t--)
+ if (!isspace(t[-1]) && t[-1] != '/')
+ break;
+ *t = '\0';
+
+ t = strchr(s, ':');
+ if (t) {
+ *t++ = '\0';
+ port = t;
+ }
+ host = s;
+}
+
+
+void usage()
{
printf(
- "Usage: metar [-v] [-e elevation] [-r|-c] <list of ICAO airport ids or METAR strings>\n"
- " -h|--help show this help\n"
- " -v|--verbose verbose output\n"
- " -r|--report print report (default)\n"
- " -c|--command-line print command line\n"
- " -e E|--elevation E set airport elevation to E meters\n"
- " (added to cloud bases in command line mode)\n"
+ "Usage: metar [-v] [-e elevation] [-r|-c] <list of ICAO airport ids or METAR strings>\n"
+ " metar -h\n"
"\n"
- "Examples: metar ksfo koak\n"
- " metar -c ksfo -r ksfo\n"
- " metar \"LOWL 161500Z 19004KT 160V240 9999 FEW035 SCT300 29/23 Q1006 NOSIG\"\n"
- " fgfs `metar -e 183 -c loww`\n"
+ " -h|--help show this help\n"
+ " -v|--verbose verbose output\n"
+ " -r|--report print report (default)\n"
+ " -c|--command-line print command line\n"
+ " -e E|--elevation E set airport elevation to E meters\n"
+ " (added to cloud bases in command line mode)\n"
+ "Environment:\n"
+ " http_proxy set proxy in the form \"http://host:port/\"\n"
+ "\n"
+ "Examples:\n"
+ " $ metar ksfo koak\n"
+ " $ metar -c ksfo -r ksfo\n"
+ " $ metar \"LOWL 161500Z 19004KT 160V240 9999 FEW035 SCT300 29/23 Q1006 NOSIG\"\n"
+ " $ fgfs `metar -e 183 -c loww`\n"
+ " $ http_proxy=http://localhost:3128/ metar ksfo\n"
"\n"
);
}
-
int main(int argc, char *argv[])
{
bool report = true;
double elevation = 0.0;
if (argc <= 1) {
- help();
+ usage();
return 0;
}
+ string proxy_host, proxy_port;
+ getproxy(proxy_host, proxy_port);
+
+ Socket::initSockets();
+
+ HTTP::Client http;
+ http.setProxy(proxy_host, atoi(proxy_port.c_str()));
+
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
- help();
+ usage();
else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))
verbose = true;
else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--report"))
report = false;
else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--elevation")) {
if (++i >= argc) {
- cerr << "-e options used without elevation" << endl;
+ cerr << "-e option used without elevation" << endl;
return 1;
}
elevation = strtod(argv[i], 0);
} else {
- try {
- SGMetar *m = new SGMetar(argv[i]);
+ static bool shown = false;
+ if (verbose && !shown) {
+ cerr << "Proxy host: '" << proxy_host << "'" << endl;
+ cerr << "Proxy port: '" << proxy_port << "'" << endl << endl;
+ shown = true;
+ }
+
+ try
+ {
+ static const std::string NOAA_BASE_URL =
+ "http://weather.noaa.gov/pub/data/observations/metar/stations/";
+ HTTP::MemoryRequest* mr = new HTTP::MemoryRequest
+ (
+ NOAA_BASE_URL
+ + boost::to_upper_copy<std::string>(argv[i]) + ".TXT"
+ );
+ HTTP::Request_ptr own(mr);
+ http.makeRequest(mr);
+
+ // spin until the request completes, fails or times out
+ SGTimeStamp start(SGTimeStamp::now());
+ while (start.elapsedMSec() < 8000) {
+ http.update();
+ if( mr->isComplete() )
+ break;
+ SGTimeStamp::sleepForMSec(1);
+ }
+
+ if( !mr->isComplete() )
+ throw sg_io_exception("metar download timed out");
+ if( mr->responseCode() != 200 )
+ {
+ std::cerr << "metar download failed: "
+ << mr->url()
+ << " (" << mr->responseCode()
+ << " " << mr->responseReason() << ")"
+ << std::endl;
+ throw sg_io_exception("metar download failed");
+ }
+
+ SGMetar *m = new SGMetar(mr->responseBody());
+
//SGMetar *m = new SGMetar("2004/01/11 01:20\nLOWG 110120Z AUTO VRB01KT 0050 1600N R35/0600 FG M06/M06 Q1019 88//////\n");
if (verbose) {