//
// 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/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__ ) || defined ( sgi )
+#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();
// 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;
if ((i = m->getWindDir()) == -1)
cout << "from variable directions";
else
- cout << "from the " << azimuthName(i) << " (" << i << "°)";
+ cout << "from the " << azimuthName(i) << " (" << i << "°)";
cout << " at " << rnd(d, -1) << " km/h";
cout << "\t\t" << rnd(m->getWindSpeed_kt(), -1) << " kt";
if (from != to) {
cout << "\t\t\tvariable from " << azimuthName(from);
cout << " to " << azimuthName(to);
- cout << " (" << from << "°--" << to << "°)" << endl;
+ cout << " (" << from << "°--" << to << "°)" << endl;
}
}
// temperature/humidity/air pressure
if ((d = m->getTemperature_C()) != NaN) {
- cout << "Temperature:\t\t" << d << "°C\t\t\t\t\t";
- cout << rnd(m->getTemperature_F(), -1) << "°F" << endl;
+ cout << "Temperature:\t\t" << d << "°C\t\t\t\t\t";
+ cout << rnd(m->getTemperature_F(), -1) << "°F" << endl;
if ((d = m->getDewpoint_C()) != NaN) {
- cout << "Dewpoint:\t\t" << d << "°C\t\t\t\t\t";
- cout << rnd(m->getDewpoint_F(), -1) << "°F" << endl;
+ cout << "Dewpoint:\t\t" << d << "°C\t\t\t\t\t";
+ cout << rnd(m->getDewpoint_F(), -1) << "°F" << endl;
cout << "Rel. Humidity:\t\t" << rnd(m->getRelHumidity()) << "%" << endl;
}
}
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)
sprintf(&buf[strlen(buf)], ":%.0lf", gust_speed);
args.push_back(buf);
}
-
+
// output everything
//cout << "fgfs" << endl;
);
}
-
int main(int argc, char *argv[])
{
bool report = true;
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"))
usage();
shown = true;
}
- try {
- SGMetar *m = new SGMetar(argv[i], proxy_host, proxy_port, "", time(0));
+ 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) {
- cerr << G"INPUT: " << m->getData() << ""N << endl;
+ cerr << G "INPUT: " << m->getData() << "" N << endl;
const char *unused = m->getUnusedData();
if (*unused)
- cerr << R"UNUSED: " << unused << ""N << endl;
+ cerr << R "UNUSED: " << unused << "" N << endl;
}
if (report)
delete m;
} catch (const sg_io_exception& e) {
- cerr << R"ERROR: " << e.getFormattedMessage().c_str() << ""N << endl << endl;
+ cerr << R "ERROR: " << e.getFormattedMessage().c_str() << "" N << endl << endl;
}
}
}