X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Frealwx_ctrl.cxx;h=3db5d905845a8c08e5b93a4633935ae82a82e967;hb=24c1129140dd1a04ac8a9fe5d6b0a17387b49304;hp=6be99082e6fa942bb03933a7545df663be8ed514;hpb=379e7a2fd56efc65887b55e419723903447d462d;p=flightgear.git diff --git a/src/Environment/realwx_ctrl.cxx b/src/Environment/realwx_ctrl.cxx index 6be99082e..3db5d9058 100644 --- a/src/Environment/realwx_ctrl.cxx +++ b/src/Environment/realwx_ctrl.cxx @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -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_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 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(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(globals->get_subsystem("http")); + if (http) { + http->makeRequest(new NoaaMetarGetRequest(metarDataHandler, upperId)); + } } /* -------------------------------------------------------------------------------- */ - + RealWxController * RealWxController::createInstance( SGPropertyNode_ptr rootNode ) { return new NoaaMetarRealWxController( rootNode ); } + +RealWxController::~RealWxController() +{ +} /* -------------------------------------------------------------------------------- */