]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/realwx_ctrl.cxx
Bugfix: avoid sky colour errors when vis < 1000m
[flightgear.git] / src / Environment / realwx_ctrl.cxx
index 6be99082e6fa942bb03933a7545df663be8ed514..3db5d905845a8c08e5b93a4633935ae82a82e967 100644 (file)
@@ -33,7 +33,7 @@
 #include <simgear/structure/exception.hxx>
 #include <simgear/misc/strutils.hxx>
 #include <simgear/props/tiedpropertylist.hxx>
-#include <simgear/io/HTTPRequest.hxx>
+#include <simgear/io/HTTPMemoryRequest.hxx>
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/structure/event_mgr.hxx>
 #include <simgear/structure/commands.hxx>
@@ -63,12 +63,13 @@ public:
 
 class LiveMetarProperties : public MetarProperties, MetarDataHandler {
 public:
-    LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester );
+    LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge );
     virtual ~LiveMetarProperties();
     virtual void update( double dt );
 
     virtual double getTimeToLive() const { return _timeToLive; }
-    virtual void setTimeToLive( double value ) { _timeToLive = value; }
+    virtual void resetTimeToLive()
+    { _timeToLive = 0.00; _pollingTimer = 0.0; }
 
     // implementation of MetarDataHandler
     virtual void handleMetarData( const std::string & data );
@@ -80,15 +81,17 @@ private:
     double _timeToLive;
     double _pollingTimer;
     MetarRequester * _metarRequester;
+    int _maxAge;
 };
 
 typedef SGSharedPtr<LiveMetarProperties> LiveMetarProperties_ptr;
 
-LiveMetarProperties::LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester ) :
+LiveMetarProperties::LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge ) :
     MetarProperties( rootNode ),
     _timeToLive(0.0),
     _pollingTimer(0.0),
-    _metarRequester(metarRequester)
+    _metarRequester(metarRequester),
+    _maxAge(maxAge)
 {
     _tiedProperties.Tie("time-to-live", &_timeToLive );
 }
@@ -102,7 +105,7 @@ void LiveMetarProperties::update( double dt )
 {
     _timeToLive -= dt;
     _pollingTimer -= dt;
-    if( _timeToLive < 0.0 ) {
+    if( _timeToLive <= 0.0 ) {
         _timeToLive = 0.0;
         std::string stationId = getStationId();
         if( stationId.empty() ) return;
@@ -114,9 +117,25 @@ void LiveMetarProperties::update( double dt )
 
 void LiveMetarProperties::handleMetarData( const std::string & data )
 {
-    SG_LOG( SG_ENVIRONMENT, SG_INFO, "LiveMetarProperties::handleMetarData() received METAR for " << getStationId() << ": " << data );
+    SG_LOG( SG_ENVIRONMENT, SG_DEBUG, "LiveMetarProperties::handleMetarData() received METAR for " << getStationId() << ": " << data );
     _timeToLive = DEFAULT_TIME_TO_LIVE_SECONDS;
-    setMetar( data );
+    
+    SGSharedPtr<FGMetar> m;
+    try {
+        m = new FGMetar(data.c_str());
+    }
+    catch( sg_io_exception ) {
+        SG_LOG( SG_ENVIRONMENT, SG_WARN, "Can't parse metar: " << data );
+        return;
+    }
+
+    if (_maxAge && (m->getAge_min() > _maxAge)) {
+        // METAR is older than max-age, ignore
+        SG_LOG( SG_ENVIRONMENT, SG_DEBUG, "Ignoring outdated METAR for " << getStationId());
+        return;
+    }
+    
+    setMetar( m );
 }
 
 /* -------------------------------------------------------------------------------- */
@@ -213,27 +232,33 @@ BasicRealWxController::BasicRealWxController( SGPropertyNode_ptr rootNode, Metar
   _wasEnabled(false),
   _requester(metarRequester)
 {
-    // at least instantiate MetarProperties for /environment/metar
-    _metarProperties.push_back( new LiveMetarProperties( 
-            fgGetNode( rootNode->getStringValue("metar", "/environment/metar"), true ), metarRequester ));
-
-    BOOST_FOREACH( SGPropertyNode_ptr n, rootNode->getChildren("metar") ) {
-        SGPropertyNode_ptr metarNode = fgGetNode( n->getStringValue(), true );
-        addMetarAtPath(metarNode->getPath(), "");
-    }
-  
-    SGCommandMgr::instance()->addCommand("request-metar", commandRequestMetar);
-    SGCommandMgr::instance()->addCommand("clear-metar", commandClearMetar);
+    
+    globals->get_commands()->addCommand("request-metar", commandRequestMetar);
+    globals->get_commands()->addCommand("clear-metar", commandClearMetar);
 }
 
 BasicRealWxController::~BasicRealWxController()
 {
-  //SGCommandMgr::instance()->removeCommand("request-metar");
+    globals->get_commands()->removeCommand("request-metar");
+    globals->get_commands()->removeCommand("clear-metar");
 }
 
 void BasicRealWxController::init()
 {
     _wasEnabled = false;
+    
+    // at least instantiate MetarProperties for /environment/metar
+    SGPropertyNode_ptr metarNode = fgGetNode( _rootNode->getStringValue("metar", "/environment/metar"), true );
+    _metarProperties.push_back( new LiveMetarProperties(metarNode,
+                                                        _requester,
+                                                        getMetarMaxAgeMin()));
+    
+    BOOST_FOREACH( SGPropertyNode_ptr n, _rootNode->getChildren("metar") ) {
+        SGPropertyNode_ptr metarNode = fgGetNode( n->getStringValue(), true );
+        addMetarAtPath(metarNode->getPath(), "");
+    }
+
+    checkNearbyMetar();
     update(0); // fetch data ASAP
     
     globals->get_event_mgr()->addTask("checkNearbyMetar", this,
@@ -243,6 +268,8 @@ void BasicRealWxController::init()
 void BasicRealWxController::reinit()
 {
     _wasEnabled = false;
+    checkNearbyMetar();
+    update(0); // fetch data ASAP
 }
     
 void BasicRealWxController::shutdown()
@@ -262,14 +289,13 @@ void BasicRealWxController::unbind()
 }
 
 void BasicRealWxController::update( double dt )
-{
+{  
   if( _enabled ) {
     bool firstIteration = !_wasEnabled;
-
     // clock tick for every METAR in stock
     BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) {
       // first round? All received METARs are outdated
-      if( firstIteration ) p->setTimeToLive( 0.0 );
+      if( firstIteration ) p->resetTimeToLive();
       p->update(dt);
     }
 
@@ -287,7 +313,7 @@ void BasicRealWxController::addMetarAtPath(const string& propPath, const string&
       // already exists
       if (p->getStationId() != icao) {
         p->setStationId(icao);
-        p->setTimeToLive(0.0);
+        p->resetTimeToLive();
       }
       
       return;
@@ -296,7 +322,7 @@ void BasicRealWxController::addMetarAtPath(const string& propPath, const string&
 
   SGPropertyNode_ptr metarNode = fgGetNode(propPath, true);
   SG_LOG( SG_ENVIRONMENT, SG_INFO, "Adding metar properties at " << propPath );
-  LiveMetarProperties_ptr p(new LiveMetarProperties( metarNode, _requester ));
+  LiveMetarProperties_ptr p(new LiveMetarProperties( metarNode, _requester, getMetarMaxAgeMin() ));
   _metarProperties.push_back(p);
   p->setStationId(icao);
 }
@@ -340,7 +366,7 @@ void BasicRealWxController::checkNearbyMetar()
               _metarProperties[0]->getStationId() <<
               "', new: '" << nearestAirport->ident() << "'" );
           _metarProperties[0]->setStationId( nearestAirport->ident() );
-          _metarProperties[0]->setTimeToLive( 0.0 );
+          _metarProperties[0]->resetTimeToLive();
       }
     }
     catch( sg_exception & ) {
@@ -358,6 +384,9 @@ public:
     // implementation of MetarRequester
     virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id );
 
+    virtual ~NoaaMetarRealWxController()
+    {
+    }
 private:
     
 };
@@ -367,83 +396,81 @@ NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNod
 {
 }
 
-void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandler, const std::string & id )
+void NoaaMetarRealWxController::requestMetar
+(
+  MetarDataHandler* metarDataHandler,
+  const std::string& id
+)
 {
-    class NoaaMetarGetRequest : public simgear::HTTP::Request
-    {
+  static const std::string NOAA_BASE_URL =
+    "http://weather.noaa.gov/pub/data/observations/metar/stations/";
+  class NoaaMetarGetRequest:
+    public simgear::HTTP::MemoryRequest
+  {
     public:
-        NoaaMetarGetRequest(MetarDataHandler* metarDataHandler, const string& stationId ) :
-              Request("http://weather.noaa.gov/pub/data/observations/metar/stations/" + stationId + ".TXT"),
-              _fromProxy(false),
-              _metarDataHandler(metarDataHandler)
-          {
-          }
-
-          virtual string_list requestHeaders() const
-          {
-              string_list reply;
-              reply.push_back("X-TIME");
-              return reply;
-          }
-
-          virtual std::string header(const std::string& name) const
-          {
-              string reply;
-
-              if( name == "X-TIME" ) {
-                  std::ostringstream buf;
-                  buf <<  globals->get_time_params()->get_cur_time();
-                  reply = buf.str();
-              }
-
-              return reply;
-          }
-
-          virtual void responseHeader(const string& key, const string& value)
-          {
-              if (key == "x-metarproxy") {
-                  _fromProxy = true;
-              }
-          }
-
-          virtual void gotBodyData(const char* s, int n)
-          {
-              _metar += string(s, n);
-          }
-
-          virtual void responseComplete()
-          {
-              if (responseCode() == 200) {
-                  _metarDataHandler->handleMetarData( simgear::strutils::simplify(_metar) );
-              } else {
-                  SG_LOG(SG_ENVIRONMENT, SG_WARN, "metar download failed:" << url() << ": reason:" << responseReason());
-              }
-          }
-
-//          bool fromMetarProxy() const
-//          { return _fromProxy; }
-    private:  
-        string _metar;
-        bool _fromProxy;
-        MetarDataHandler * _metarDataHandler;
-    };
-
-    string upperId = boost::to_upper_copy(id);
-
-    SG_LOG(SG_ENVIRONMENT, SG_INFO,
-        "NoaaMetarRealWxController::update(): spawning load request for station-id '" << upperId << "'" );
-    FGHTTPClient* http = static_cast<FGHTTPClient*>(globals->get_subsystem("http"));
-    if (http) {
-        http->makeRequest(new NoaaMetarGetRequest(metarDataHandler, upperId));
-    }
+      NoaaMetarGetRequest( MetarDataHandler* metarDataHandler,
+                           const std::string& stationId ):
+        MemoryRequest(NOAA_BASE_URL + stationId + ".TXT"),
+        _metarDataHandler(metarDataHandler)
+      {
+        std::ostringstream buf;
+        buf <<  globals->get_time_params()->get_cur_time();
+        requestHeader("X-TIME") = buf.str();
+      }
+
+      virtual void onDone()
+      {
+        if( responseCode() != 200 )
+        {
+          SG_LOG
+          (
+            SG_ENVIRONMENT,
+            SG_WARN,
+            "metar download failed:" << url() << ": reason:" << responseReason()
+          );
+          return;
+        }
+
+        _metarDataHandler->handleMetarData
+        (
+          simgear::strutils::simplify(responseBody())
+        );
+      }
+
+      virtual void onFail()
+      {
+        SG_LOG(SG_ENVIRONMENT, SG_INFO, "metar download failure");
+      }
+
+    private:
+      MetarDataHandler * _metarDataHandler;
+  };
+
+  string upperId = boost::to_upper_copy(id);
+
+  SG_LOG
+  (
+    SG_ENVIRONMENT,
+    SG_INFO,
+    "NoaaMetarRealWxController::update(): "
+    "spawning load request for station-id '" << upperId << "'"
+  );
+  FGHTTPClient* http = static_cast<FGHTTPClient*>(globals->get_subsystem("http"));
+  if (http) {
+      http->makeRequest(new NoaaMetarGetRequest(metarDataHandler, upperId));
+  }
 }
 
 /* -------------------------------------------------------------------------------- */
-
+    
 RealWxController * RealWxController::createInstance( SGPropertyNode_ptr rootNode )
 {
   return new NoaaMetarRealWxController( rootNode );
 }
+    
+RealWxController::~RealWxController()
+{
+}
 
 /* -------------------------------------------------------------------------------- */