]> git.mxchange.org Git - simgear.git/commitdiff
Remove using std:: from the metar header, remove HTTP support, add very basic unit...
authorJames Turner <zakalawe@mac.com>
Fri, 21 Oct 2011 08:35:37 +0000 (09:35 +0100)
committerJames Turner <zakalawe@mac.com>
Fri, 21 Oct 2011 08:35:37 +0000 (09:35 +0100)
simgear/environment/CMakeLists.txt
simgear/environment/metar.cxx
simgear/environment/metar.hxx
simgear/environment/test_metar.cxx [new file with mode: 0644]

index 5a4dce1e101760c84c5a01e7ad6ed014b623062b..c59f98a7575f6673d3936fb865d163ac769db712 100644 (file)
@@ -5,3 +5,12 @@ set(HEADERS metar.hxx precipitation.hxx)
 set(SOURCES metar.cxx precipitation.cxx)
 
 simgear_component(environment environment "${SOURCES}" "${HEADERS}")
+
+add_executable(test_metar test_metar.cxx)
+target_link_libraries(test_metar
+    sgenvironment sgstructure sgmisc sgdebug
+    ${CMAKE_THREAD_LIBS_INIT}
+    ${ZLIB_LIBRARY}
+    ${RT_LIBRARY}) 
+    
+add_test(metar ${EXECUTABLE_OUTPUT_PATH}/test_metar)
\ No newline at end of file
index c15c4a7286074115f2598aee51703be58b2de24e..75109b75651d03eb413a08b9975696ec02315384 100644 (file)
@@ -32,7 +32,6 @@
 #include <time.h>
 #include <cstring>
 
-#include <simgear/io/sg_socket.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/structure/exception.hxx>
 
 
 #define NaN SGMetarNaN
 
+using std::string;
+using std::map;
+using std::vector;
+
 /**
- * The constructor takes a Metar string, or a four-letter ICAO code. In the
- * latter case the metar string is downloaded from
- * http://weather.noaa.gov/pub/data/observations/metar/stations/.
+ * The constructor takes a Metar string
  * The constructor throws sg_io_exceptions on failure. The "METAR"
  * keyword has no effect (apart from incrementing the group counter
  * @a grpcount) and can be left away. A keyword "SPECI" is
  * likewise accepted.
  *
  * @param m     ICAO station id or metar string
- * @param proxy proxy host (optional; default: "")
- * @param port  proxy port (optional; default: "80")
- * @param auth  proxy authorization information (optional; default: "")
  *
  * @par Examples:
  * @code
  * SGMetar *m = new SGMetar("METAR KSFO 061656Z 19004KT 9SM SCT100 OVC200 08/03 A3013");
  * double t = m->getTemperature_F();
  * delete m;
- *
- * SGMetar n("KSFO", "proxy.provider.foo", "3128", "proxy-password");
- * double d = n.getDewpoint_C();
+
  * @endcode
  */
-SGMetar::SGMetar(const string& m, const string& proxy, const string& port,
-               const string& auth, const time_t time) :
+SGMetar::SGMetar(const string& m) :
        _grpcount(0),
        _x_proxy(false),
        _year(-1),
@@ -87,16 +82,10 @@ SGMetar::SGMetar(const string& m, const string& proxy, const string& port,
        _snow(false),
        _cavok(false)
 {
-       if (m.length() == 4 && isalnum(m[0]) && isalnum(m[1]) && isalnum(m[2]) && isalnum(m[3])) {
-               for (int i = 0; i < 4; i++)
-                       _icao[i] = toupper(m[i]);
-               _icao[4] = '\0';
-               _data = loadData(_icao, proxy, port, auth, time);
-       } else {
-               _data = new char[m.length() + 2];       // make room for " \0"
-               strcpy(_data, m.c_str());
-               _url = _data;
-       }
+       _data = new char[m.length() + 2];       // make room for " \0"
+       strcpy(_data, m.c_str());
+       _url = _data;
+               
        normalizeData();
 
        _m = _data;
@@ -169,85 +158,6 @@ void SGMetar::useCurrentDate()
        _month = now.tm_mon + 1;
 }
 
-
-/**
-  * If called with "KSFO" loads data from
-  * @code
-  * http://weather.noaa.gov/pub/data/observations/metar/stations/KSFO.TXT.
-  * @endcode
-  * Throws sg_io_exception on failure. Gives up after waiting longer than 10 seconds.
-  *
-  * @param id four-letter ICAO Metar station code, e.g. "KSFO".
-  * @param proxy proxy host (optional; default: "")
-  * @param port  proxy port (optional; default: "80")
-  * @param auth  proxy authorization information (optional; default: "")
-  * @return pointer to Metar data string, allocated by new char[].
-  * @see rfc2068.txt for proxy spec ("Proxy-Authorization")
-  */
-char *SGMetar::loadData(const char *id, const string& proxy, const string& port,
-               const string& auth, time_t time)
-{
-       const int buflen = 512;
-       char buf[2 * buflen];
-
-       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://" + metar_server + path;
-
-       SGSocket *sock = new SGSocket(host, port.empty() ? "80" : port, "tcp");
-       sock->set_timeout(10000);
-       if (!sock->open(SG_IO_OUT)) {
-               delete sock;
-               throw sg_io_exception("cannot connect to ", sg_location(host));
-       }
-
-       string get = "GET ";
-       if (!proxy.empty())
-               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";
-
-       get += "\015\012";
-       sock->writestring(get.c_str());
-
-       int i;
-
-       // skip HTTP header
-       while ((i = sock->readline(buf, buflen))) {
-               if (i <= 2 && isspace(buf[0]) && (!buf[1] || isspace(buf[1])))
-                       break;
-               if (!strncmp(buf, "X-MetarProxy: ", 13))
-                       _x_proxy = true;
-       }
-       if (i) {
-               i = sock->readline(buf, buflen);
-               if (i)
-                       sock->readline(&buf[i], buflen);
-       }
-
-       sock->close();
-       delete sock;
-
-       char *b = buf;
-       scanBoundary(&b);
-       if (*b == '<')
-               throw sg_io_exception("no metar data available from ", 
-                               sg_location(_url));
-
-       char *metar = new char[strlen(b) + 2];  // make room for " \0"
-       strcpy(metar, b);
-       return metar;
-}
-
-
 /**
   * Replace any number of subsequent spaces by just one space, and add
   * a trailing space. This makes scanning for things like "ALL RWY" easier.
index e501a0c4611ff8b8c6a235cd0cfb92063d6ef7c6..26e8523ef21f9ba4cffee641ea83127a43d176bc 100644 (file)
 
 #include <simgear/constants.h>
 
-using std::vector;
-using std::map;
-using std::string;
-
-const double SGMetarNaN = -1E20;
-#define NaN SGMetarNaN
-
 struct Token {
        const char *id;
        const char *text;
 };
 
+const double SGMetarNaN = -1E20;
 
 class SGMetar;
 
@@ -48,7 +42,7 @@ class SGMetarVisibility {
        friend class SGMetar;
 public:
        SGMetarVisibility() :
-               _distance(NaN),
+               _distance(SGMetarNaN),
                _direction(-1),
                _modifier(EQUALS),
                _tendency(NONE) {}
@@ -70,8 +64,8 @@ public:
        void set(double dist, int dir = -1, int mod = -1, int tend = -1);
 
        inline double   getVisibility_m()       const { return _distance; }
-       inline double   getVisibility_ft()      const { return _distance == NaN ? NaN : _distance * SG_METER_TO_FEET; }
-       inline double   getVisibility_sm()      const { return _distance == NaN ? NaN : _distance * SG_METER_TO_SM; }
+       inline double   getVisibility_ft()      const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_FEET; }
+       inline double   getVisibility_sm()      const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_SM; }
        inline int      getDirection()          const { return _direction; }
        inline int      getModifier()           const { return _modifier; }
        inline int      getTendency()           const { return _tendency; }
@@ -93,8 +87,8 @@ public:
                _deposit_string(0),
                _extent(-1),
                _extent_string(0),
-               _depth(NaN),
-               _friction(NaN),
+               _depth(SGMetarNaN),
+               _friction(SGMetarNaN),
                _friction_string(0),
                _comment(0),
                _wind_shear(false) {}
@@ -146,14 +140,14 @@ public:
        static const char * COVERAGE_BROKEN_STRING;
        static const char * COVERAGE_OVERCAST_STRING;
 
-       SGMetarCloud() : _coverage(COVERAGE_NIL), _altitude(NaN), _type(0), _type_long(0) {}
+       SGMetarCloud() : _coverage(COVERAGE_NIL), _altitude(SGMetarNaN), _type(0), _type_long(0) {}
 
        void set(double alt, Coverage cov = COVERAGE_NIL );
 
        inline Coverage getCoverage() const { return _coverage; }
        static Coverage getCoverage( const std::string & coverage );
        inline double getAltitude_m() const { return _altitude; }
-       inline double getAltitude_ft() const { return _altitude == NaN ? NaN : _altitude * SG_METER_TO_FEET; }
+       inline double getAltitude_ft() const { return _altitude == SGMetarNaN ? SGMetarNaN : _altitude * SG_METER_TO_FEET; }
        inline const char *getTypeString() const { return _type; }
        inline const char *getTypeLongString() const { return _type_long; }
 
@@ -167,8 +161,7 @@ protected:
 
 class SGMetar {
 public:
-       SGMetar(const string& m, const string& proxy = "", const string& port = "",
-                       const string &auth = "", const time_t time = 0);
+       SGMetar(const std::string& m);
        ~SGMetar();
 
        enum ReportType {
@@ -189,8 +182,8 @@ public:
                Weather() { intensity = NIL; vincinity = false; }
                Intensity intensity;
                bool      vincinity;
-               vector<string> descriptions;
-               vector<string> phenomena;
+               std::vector<std::string> descriptions;
+               std::vector<std::string> phenomena;
        };
 
        inline const char *getData()            const { return _data; }
@@ -206,14 +199,14 @@ 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 * 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   getWindSpeed_kmh()      const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KMH; }
+       inline double   getWindSpeed_kt()       const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KT; }
+       inline double   getWindSpeed_mph()      const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _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 * 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; }
+       inline double   getGustSpeed_kmh()      const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KMH; }
+       inline double   getGustSpeed_kt()       const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KT; }
+       inline double   getGustSpeed_mph()      const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_MPH; }
 
        inline int      getWindRangeFrom()      const { return _wind_range_from; }
        inline int      getWindRangeTo()        const { return _wind_range_to; }
@@ -224,11 +217,11 @@ public:
        inline const SGMetarVisibility *getDirVisibility()      const { return _dir_visibility; }
 
        inline double   getTemperature_C()      const { return _temp; }
-       inline double   getTemperature_F()      const { return _temp == NaN ? NaN : 1.8 * _temp + 32; }
+       inline double   getTemperature_F()      const { return _temp == SGMetarNaN ? SGMetarNaN : 1.8 * _temp + 32; }
        inline double   getDewpoint_C()         const { return _dewp; }
-       inline double   getDewpoint_F()         const { return _dewp == NaN ? NaN : 1.8 * _dewp + 32; }
-       inline double   getPressure_hPa()       const { return _pressure == NaN ? NaN : _pressure / 100; }
-       inline double   getPressure_inHg()      const { return _pressure == NaN ? NaN : _pressure * SG_PA_TO_INHG; }
+       inline double   getDewpoint_F()         const { return _dewp == SGMetarNaN ? SGMetarNaN : 1.8 * _dewp + 32; }
+       inline double   getPressure_hPa()       const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure / 100; }
+       inline double   getPressure_inHg()      const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure * SG_PA_TO_INHG; }
 
        inline int      getRain()               const { return _rain; }
        inline int      getHail()               const { return _hail; }
@@ -237,13 +230,13 @@ public:
 
        double          getRelHumidity()        const;
 
-       inline const vector<SGMetarCloud>& getClouds()  const   { return _clouds; }
-       inline const map<string, SGMetarRunway>& getRunways()   const   { return _runways; }
-       inline const vector<string>& getWeather()               const   { return _weather; }
-       inline const vector<struct Weather> getWeather2()       const   { return _weather2; }
+       inline const std::vector<SGMetarCloud>& getClouds()     const   { return _clouds; }
+       inline const std::map<std::string, SGMetarRunway>& getRunways() const   { return _runways; }
+       inline const std::vector<std::string>& getWeather()             const   { return _weather; }
+       inline const std::vector<struct Weather> getWeather2()  const   { return _weather2; }
 
 protected:
-       string  _url;
+       std::string     _url;
        int     _grpcount;
        bool    _x_proxy;
        char    *_data;
@@ -267,15 +260,15 @@ protected:
        int     _hail;
        int     _snow;
        bool    _cavok;
-       vector<struct Weather> _weather2;
+       std::vector<struct Weather> _weather2;
 
        SGMetarVisibility               _min_visibility;
        SGMetarVisibility               _max_visibility;
        SGMetarVisibility               _vert_visibility;
        SGMetarVisibility               _dir_visibility[8];
-       vector<SGMetarCloud>            _clouds;
-       map<string, SGMetarRunway>      _runways;
-       vector<string>                  _weather;
+       std::vector<SGMetarCloud>               _clouds;
+       std::map<std::string, SGMetarRunway>    _runways;
+       std::vector<std::string>                        _weather;
 
        bool    scanPreambleDate();
        bool    scanPreambleTime();
@@ -303,10 +296,7 @@ protected:
        int     scanNumber(char **str, int *num, int min, int max = 0);
        bool    scanBoundary(char **str);
        const struct Token *scanToken(char **str, const struct Token *list);
-       char    *loadData(const char *id, const string& proxy, const string& port,
-                       const string &auth, time_t time);
        void    normalizeData();
 };
 
-#undef NaN
 #endif // _METAR_HXX
diff --git a/simgear/environment/test_metar.cxx b/simgear/environment/test_metar.cxx
new file mode 100644 (file)
index 0000000..bcdc772
--- /dev/null
@@ -0,0 +1,68 @@
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+
+#ifdef _MSC_VER
+#   define  random  rand
+#endif
+
+#include <simgear/misc/sg_dir.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include "metar.hxx"
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+
+#define COMPARE(a, b) \
+    if ((a) != (b))  { \
+        cerr << "failed:" << #a << " != " << #b << endl; \
+        cerr << "\tgot:" << a << endl; \
+        exit(1); \
+    }
+
+#define VERIFY(a) \
+    if (!(a))  { \
+        cerr << "failed:" << #a << endl; \
+        exit(1); \
+    }
+    
+
+void test_basic()
+{
+    SGMetar m1("2011/10/20 11:25 EHAM 201125Z 27012KT 240V300 9999 VCSH FEW025CB SCT048 10/05 Q1025 TEMPO VRB03KT");
+    COMPARE(m1.getYear(), 2011);
+    COMPARE(m1.getMonth(), 10);
+    COMPARE(m1.getDay(), 20);
+    COMPARE(m1.getHour(), 11);
+    COMPARE(m1.getMinute(), 25);
+    COMPARE(m1.getReportType(), -1); // should default to NIL?
+    
+    COMPARE(m1.getWindDir(), 270);
+    COMPARE(m1.getWindSpeed_kt(), 12);
+    
+    COMPARE(m1.getTemperature_C(), 10);
+    COMPARE(m1.getDewpoint_C(), 5);
+    COMPARE(m1.getPressure_hPa(), 1025);
+}
+
+int main(int argc, char* argv[])
+{
+    try {
+    test_basic();
+    } catch (sg_exception& e) {
+        cerr << "got exception:" << e.getMessage() << endl;
+        return -1;
+    }
+    
+    return 0;
+}