+
+/* -------------------------------------------------------------------------------- */
+
+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 LiveMetarProperties : public MetarProperties, MetarDataHandler {
+public:
+ LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge );
+ virtual ~LiveMetarProperties();
+ virtual void update( double dt );
+
+ virtual double getTimeToLive() const { return _timeToLive; }
+ virtual void resetTimeToLive()
+ { _timeToLive = 0.00; _pollingTimer = 0.0; }
+
+ // implementation of MetarDataHandler
+ virtual void handleMetarData( const std::string & data );
+
+ static const unsigned MAX_POLLING_INTERVAL_SECONDS = 10;
+ static const unsigned DEFAULT_TIME_TO_LIVE_SECONDS = 900;
+
+private:
+ double _timeToLive;
+ double _pollingTimer;
+ MetarRequester * _metarRequester;
+ int _maxAge;
+};
+
+typedef SGSharedPtr<LiveMetarProperties> LiveMetarProperties_ptr;
+
+LiveMetarProperties::LiveMetarProperties( SGPropertyNode_ptr rootNode, MetarRequester * metarRequester, int maxAge ) :
+ MetarProperties( rootNode ),
+ _timeToLive(0.0),
+ _pollingTimer(0.0),
+ _metarRequester(metarRequester),
+ _maxAge(maxAge)
+{
+ _tiedProperties.Tie("time-to-live", &_timeToLive );
+}
+
+LiveMetarProperties::~LiveMetarProperties()
+{
+ _tiedProperties.Untie();
+}
+
+void LiveMetarProperties::update( double dt )
+{
+ _timeToLive -= dt;
+ _pollingTimer -= dt;
+ if( _timeToLive <= 0.0 ) {
+ _timeToLive = 0.0;
+ std::string stationId = getStationId();
+ if( stationId.empty() ) return;
+ if( _pollingTimer > 0.0 ) return;
+ _metarRequester->requestMetar( this, stationId );
+ _pollingTimer = MAX_POLLING_INTERVAL_SECONDS;
+ }
+}
+
+void LiveMetarProperties::handleMetarData( const std::string & data )
+{
+ SG_LOG( SG_ENVIRONMENT, SG_DEBUG, "LiveMetarProperties::handleMetarData() received METAR for " << getStationId() << ": " << data );
+ _timeToLive = DEFAULT_TIME_TO_LIVE_SECONDS;
+
+ 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 );
+}
+
+/* -------------------------------------------------------------------------------- */
+