]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/realwx_ctrl.cxx
Merge branch 'next' of git://gitorious.org/fg/flightgear into next
[flightgear.git] / src / Environment / realwx_ctrl.cxx
index 1c1131b047efe0fc267435ce16fde3c8d23631b3..cd315eea596002e5c9176867a80fa8238a76efe8 100644 (file)
@@ -55,13 +55,20 @@ public:
 protected:
     void bind();
     void unbind();
+    void update( double dt );
+
+    virtual void update( bool first, double dt ) = 0;
+
+    long getMetarMaxAgeMin() const { return _max_age_n == NULL ? 0 : _max_age_n->getLongValue(); }
 
     SGPropertyNode_ptr _rootNode;
     SGPropertyNode_ptr _longitude_n;
     SGPropertyNode_ptr _latitude_n;
     SGPropertyNode_ptr _ground_elevation_n;
+    SGPropertyNode_ptr _max_age_n;
 
     bool _enabled;
+    bool __enabled;
     TiedPropertyList _tiedProperties;
     MetarProperties  _metarProperties;
 };
@@ -78,7 +85,9 @@ BasicRealWxController::BasicRealWxController( SGPropertyNode_ptr rootNode ) :
   _longitude_n( fgGetNode( "/position/longitude-deg", true )),
   _latitude_n( fgGetNode( "/position/latitude-deg", true )),
   _ground_elevation_n( fgGetNode( "/position/ground-elev-m", true )),
+  _max_age_n( fgGetNode( "/environment/params/metar-max-age-min", false ) ),
   _enabled(true),
+  __enabled(false),
   _metarProperties( fgGetNode( rootNode->getStringValue("metar", "/environment/metar"), true ) )
 {
 }
@@ -89,11 +98,13 @@ BasicRealWxController::~BasicRealWxController()
 
 void BasicRealWxController::init()
 {
+    __enabled = false;
     update(0); // fetch data ASAP
 }
 
 void BasicRealWxController::reinit()
 {
+    __enabled = false;
 }
 
 void BasicRealWxController::bind()
@@ -107,13 +118,23 @@ void BasicRealWxController::unbind()
     _tiedProperties.Untie();
 }
 
+void BasicRealWxController::update( double dt )
+{
+  if( _enabled ) {
+    update( !__enabled, dt );
+    __enabled = true;
+  } else {
+    __enabled = false;
+  }
+}
+
 /* -------------------------------------------------------------------------------- */
 
 class NoaaMetarRealWxController : public BasicRealWxController {
 public:
     NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
     virtual ~NoaaMetarRealWxController();
-    virtual void update (double delta_time_sec);
+    virtual void update (bool first, double delta_time_sec);
 
     class MetarLoadRequest {
     public:
@@ -142,13 +163,14 @@ private:
 #if defined(ENABLE_THREADS)
      class MetarLoadThread : public OpenThreads::Thread {
      public:
-         MetarLoadThread( NoaaMetarRealWxController & controller );
-         void requestMetar( const MetarLoadRequest & metarRequest );
-         bool hasMetar() { return _responseQueue.size() > 0; }
-         string getMetar() { return _responseQueue.pop(); }
-         virtual void run();
+        MetarLoadThread( long maxAge );
+        void requestMetar( const MetarLoadRequest & metarRequest, bool background = true );
+        bool hasMetar() { return _responseQueue.size() > 0; }
+        string getMetar() { return _responseQueue.pop(); }
+        virtual void run();
      private:
-        NoaaMetarRealWxController & _controller;
+        void fetch( const MetarLoadRequest & );
+        long _maxAge;
         SGBlockingQueue <MetarLoadRequest> _requestQueue;
         SGBlockingQueue <string> _responseQueue;
      };
@@ -167,7 +189,7 @@ NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNod
   _metarStationIdNode(_metarProperties.get_root_node()->getNode("station-id",true))
 {
 #if defined(ENABLE_THREADS)
-    _metarLoadThread = new MetarLoadThread(*this);
+    _metarLoadThread = new MetarLoadThread(getMetarMaxAgeMin());
     _metarLoadThread->start();
 #endif
 }
@@ -184,14 +206,8 @@ NoaaMetarRealWxController::~NoaaMetarRealWxController()
 #endif // ENABLE_THREADS
 }
 
-void NoaaMetarRealWxController::update( double dt )
+void NoaaMetarRealWxController::update( bool first, double dt )
 {
-    if( !_enabled )
-        return;
-
-    if( _metarLoadThread->hasMetar() )
-        _metarDataNode->setStringValue( _metarLoadThread->getMetar() );
-
     _metarTimeToLive -= dt;
     _positionTimeToLive -= dt;
     _minimumRequestInterval -= dt;
@@ -199,6 +215,7 @@ void NoaaMetarRealWxController::update( double dt )
     bool valid = _metarValidNode->getBoolValue();
     string stationId = valid ? _metarStationIdNode->getStringValue() : "";
 
+    if( first ) _metarTimeToLive = 0.0;
 
     if( _metarTimeToLive <= 0.0 ) {
         valid = false;
@@ -227,31 +244,45 @@ void NoaaMetarRealWxController::update( double dt )
     if( !valid ) {
         if( _minimumRequestInterval <= 0 && stationId.length() > 0 ) {
             MetarLoadRequest request( stationId );
-            _metarLoadThread->requestMetar( request );
+            // load the first metar in the foreground to make sure a metar is received
+            // before the automatic runway selection code runs. All subsequent calls
+            // run in the background
+            _metarLoadThread->requestMetar( request, !first );
             _minimumRequestInterval = 10;
         }
     }
 
+    if( _metarLoadThread->hasMetar() ) {
+        string metar = _metarLoadThread->getMetar();
+        SG_LOG( SG_ALL, SG_ALERT, "NoaaMetarRwalWxController::update() received METAR " << metar );
+        _metarDataNode->setStringValue( metar );
+    }
+
+
 }
 
 /* -------------------------------------------------------------------------------- */
 
 #if defined(ENABLE_THREADS)
-NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( NoaaMetarRealWxController & controller ) :
-  _controller(controller)
+NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) :
+  _maxAge(maxAge)
 {
 }
 
-void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest )
+void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest, bool background )
 {
-    if( _requestQueue.size() > 10 ) {
-        SG_LOG(SG_ALL,SG_ALERT,
-            "NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping " 
-            << metarRequest._stationId );
-        return;
-    }
+    if( background ) {
+        if( _requestQueue.size() > 10 ) {
+            SG_LOG(SG_ALL,SG_ALERT,
+                "NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping " 
+                << metarRequest._stationId );
+            return;
+        }
 
-    _requestQueue.push( metarRequest );
+        _requestQueue.push( metarRequest );
+    } else {
+        fetch( metarRequest );
+    }
 }
 
 void NoaaMetarRealWxController::MetarLoadThread::run()
@@ -262,25 +293,39 @@ void NoaaMetarRealWxController::MetarLoadThread::run()
         if( request._stationId.size() == 0 )
             break;
 
-       SGSharedPtr<FGMetar> result = NULL;
+        fetch( request );
+    }
+}
 
-        try {
-            result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
-        } catch (const sg_io_exception& e) {
-            SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for " 
-                                        << request._stationId << ":" << e.getFormattedMessage().c_str() );
-            continue;
-        }
+void NoaaMetarRealWxController::MetarLoadThread::fetch( const MetarLoadRequest & request )
+{
+   SGSharedPtr<FGMetar> result = NULL;
+
+    try {
+        result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
+    } catch (const sg_io_exception& e) {
+        SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for " 
+                                    << request._stationId << ":" << e.getFormattedMessage().c_str() );
+        return;
+    }
 
-        if( result == NULL )
-            continue;
+    string reply = result->getData();
+    std::replace(reply.begin(), reply.end(), '\n', ' ');
+    string metar = simgear::strutils::strip( reply );
 
-        string reply = result->getData();
-        std::replace(reply.begin(), reply.end(), '\n', ' ');
-        string metar = simgear::strutils::strip( reply );
-        if( metar.length() > 0 )
-            _responseQueue.push( metar );
+    if( metar.empty() ) {
+        SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for " 
+                                    << request._stationId );
+        return;
     }
+
+    if( _maxAge && result->getAge_min() > _maxAge ) {
+        SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR " 
+                                     << metar );
+        return;
+    }
+
+    _responseQueue.push( metar );
 }
 #endif