]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/realwx_ctrl.cxx
Basics on catalog list model in the GUI.
[flightgear.git] / src / Environment / realwx_ctrl.cxx
index 3db5d905845a8c08e5b93a4633935ae82a82e967..104d7db5999a37c9b14f7ca5d0643ed6505af1ae 100644 (file)
@@ -49,19 +49,11 @@ namespace Environment {
 
 /* -------------------------------------------------------------------------------- */
 
-class MetarDataHandler {
-public:
-    virtual void handleMetarData( const std::string & data ) = 0;
-};
-
-class MetarRequester {
-public:
-    virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id ) = 0;
-};
+class MetarRequester;
 
 /* -------------------------------------------------------------------------------- */
 
-class LiveMetarProperties : public MetarProperties, MetarDataHandler {
+class LiveMetarProperties : public MetarProperties {
 public:
     LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge );
     virtual ~LiveMetarProperties();
@@ -73,7 +65,8 @@ public:
 
     // implementation of MetarDataHandler
     virtual void handleMetarData( const std::string & data );
-
+    virtual void handleMetarFailure();
+  
     static const unsigned MAX_POLLING_INTERVAL_SECONDS = 10;
     static const unsigned DEFAULT_TIME_TO_LIVE_SECONDS = 900;
 
@@ -82,18 +75,27 @@ private:
     double _pollingTimer;
     MetarRequester * _metarRequester;
     int _maxAge;
+    bool _failure;
 };
 
 typedef SGSharedPtr<LiveMetarProperties> LiveMetarProperties_ptr;
 
+class MetarRequester {
+public:
+    virtual void requestMetar( LiveMetarProperties_ptr metarDataHandler, const std::string & id ) = 0;
+};
+
+
 LiveMetarProperties::LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge ) :
     MetarProperties( rootNode ),
     _timeToLive(0.0),
     _pollingTimer(0.0),
     _metarRequester(metarRequester),
-    _maxAge(maxAge)
+    _maxAge(maxAge),
+    _failure(false)
 {
     _tiedProperties.Tie("time-to-live", &_timeToLive );
+    _tiedProperties.Tie("failure", &_failure);
 }
 
 LiveMetarProperties::~LiveMetarProperties()
@@ -107,6 +109,7 @@ void LiveMetarProperties::update( double dt )
     _pollingTimer -= dt;
     if( _timeToLive <= 0.0 ) {
         _timeToLive = 0.0;
+        invalidate();
         std::string stationId = getStationId();
         if( stationId.empty() ) return;
         if( _pollingTimer > 0.0 ) return;
@@ -124,8 +127,9 @@ void LiveMetarProperties::handleMetarData( const std::string & data )
     try {
         m = new FGMetar(data.c_str());
     }
-    catch( sg_io_exception ) {
+    catch( sg_io_exception  &) {
         SG_LOG( SG_ENVIRONMENT, SG_WARN, "Can't parse metar: " << data );
+        _failure = true;
         return;
     }
 
@@ -134,10 +138,16 @@ void LiveMetarProperties::handleMetarData( const std::string & data )
         SG_LOG( SG_ENVIRONMENT, SG_DEBUG, "Ignoring outdated METAR for " << getStationId());
         return;
     }
-    
+  
+    _failure = false;
     setMetar( m );
 }
 
+void LiveMetarProperties::handleMetarFailure()
+{
+  _failure = true;
+}
+  
 /* -------------------------------------------------------------------------------- */
 
 class BasicRealWxController : public RealWxController
@@ -159,6 +169,9 @@ public:
     void addMetarAtPath(const string& propPath, const string& icao);
   
     void removeMetarAtPath(const string& propPath);
+
+    typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
+    MetarPropertiesList::iterator findMetarAtPath(const string &propPath);
 protected:
     void bind();
     void unbind();
@@ -175,7 +188,6 @@ protected:
     bool _enabled;
     bool _wasEnabled;
     simgear::TiedPropertyList _tiedProperties;
-    typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
     MetarPropertiesList _metarProperties;
     MetarRequester* _requester;
 
@@ -308,20 +320,19 @@ void BasicRealWxController::update( double dt )
 void BasicRealWxController::addMetarAtPath(const string& propPath, const string& icao)
 {
   // check for duplicate entries
-  BOOST_FOREACH( LiveMetarProperties_ptr p, _metarProperties ) {
-    if( p->get_root_node()->getPath() == propPath ) {
-      // already exists
-      if (p->getStationId() != icao) {
-        p->setStationId(icao);
-        p->resetTimeToLive();
-      }
-      
-      return;
+  MetarPropertiesList::iterator it = findMetarAtPath(propPath);
+  if( it != _metarProperties.end() ) {
+    SG_LOG( SG_ENVIRONMENT, SG_INFO, "Reusing metar properties at " << propPath << " for " << icao);
+    // already exists
+    if ((*it)->getStationId() != icao) {
+      (*it)->setStationId(icao);
+      (*it)->resetTimeToLive();
     }
-  } // of exitsing metar properties iteration
+    return;
+  }
 
   SGPropertyNode_ptr metarNode = fgGetNode(propPath, true);
-  SG_LOG( SG_ENVIRONMENT, SG_INFO, "Adding metar properties at " << propPath );
+  SG_LOG( SG_ENVIRONMENT, SG_INFO, "Adding metar properties at " << propPath << " for " << icao);
   LiveMetarProperties_ptr p(new LiveMetarProperties( metarNode, _requester, getMetarMaxAgeMin() ));
   _metarProperties.push_back(p);
   p->setStationId(icao);
@@ -329,17 +340,29 @@ void BasicRealWxController::addMetarAtPath(const string& propPath, const string&
 
 void BasicRealWxController::removeMetarAtPath(const string &propPath)
 {
-  MetarPropertiesList::iterator it = _metarProperties.begin();
-  for (; it != _metarProperties.end(); ++it) {
-    LiveMetarProperties_ptr p(*it);
-    if( p->get_root_node()->getPath() == propPath ) {
-      _metarProperties.erase(it);
-      // final ref will drop, and delete the MetarProperties, when we return
-      return;
-    }
+  MetarPropertiesList::iterator it = findMetarAtPath( propPath );
+  if( it != _metarProperties.end() ) {
+    SG_LOG(SG_ENVIRONMENT, SG_INFO, "removing metar properties at " << propPath);
+    _metarProperties.erase(it);
+  } else {
+    SG_LOG(SG_ENVIRONMENT, SG_WARN, "no metar properties at " << propPath);
   }
-  
-  SG_LOG(SG_ENVIRONMENT, SG_WARN, "no metar properties at " << propPath);
+}
+
+BasicRealWxController::MetarPropertiesList::iterator BasicRealWxController::findMetarAtPath(const string &propPath)
+{
+  // don not compare unprocessed property path
+  // /foo/bar[0]/baz equals /foo/bar/baz
+  SGPropertyNode_ptr n = fgGetNode(propPath,false);
+  if( false == n.valid() ) // trivial: node does not exist
+    return _metarProperties.end();
+
+  MetarPropertiesList::iterator it = _metarProperties.begin();
+  while( it != _metarProperties.end() &&
+         (*it)->get_root_node()->getPath() != n->getPath() )
+    ++it;
+
+  return it;
 }
   
 void BasicRealWxController::checkNearbyMetar()
@@ -382,7 +405,7 @@ public:
     NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
 
     // implementation of MetarRequester
-    virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id );
+    virtual void requestMetar( LiveMetarProperties_ptr metarDataHandler, const std::string & id );
 
     virtual ~NoaaMetarRealWxController()
     {
@@ -398,7 +421,7 @@ NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNod
 
 void NoaaMetarRealWxController::requestMetar
 (
-  MetarDataHandler* metarDataHandler,
+  LiveMetarProperties_ptr metarDataHandler,
   const std::string& id
 )
 {
@@ -408,7 +431,7 @@ void NoaaMetarRealWxController::requestMetar
     public simgear::HTTP::MemoryRequest
   {
     public:
-      NoaaMetarGetRequest( MetarDataHandler* metarDataHandler,
+      NoaaMetarGetRequest( LiveMetarProperties_ptr metarDataHandler,
                            const std::string& stationId ):
         MemoryRequest(NOAA_BASE_URL + stationId + ".TXT"),
         _metarDataHandler(metarDataHandler)
@@ -440,10 +463,11 @@ void NoaaMetarRealWxController::requestMetar
       virtual void onFail()
       {
         SG_LOG(SG_ENVIRONMENT, SG_INFO, "metar download failure");
+        _metarDataHandler->handleMetarFailure();
       }
 
     private:
-      MetarDataHandler * _metarDataHandler;
+      LiveMetarProperties_ptr _metarDataHandler;
   };
 
   string upperId = boost::to_upper_copy(id);