diff --git a/src/core/DataManager.cpp b/src/core/DataManager.cpp index 7514e98..b5612d6 100644 --- a/src/core/DataManager.cpp +++ b/src/core/DataManager.cpp @@ -355,7 +355,20 @@ DataManager::MessageType DataManager::deltaEuroscopeToBackend(const std::array activeAirports) { std::lock_guard guard(this->m_airportLock); - this->m_activeAirports = activeAirports; + + std::list supportedAirports = Server::instance().getSupportedAirports(); + std::list cdmActiveAirports; + + for (const auto& activeAirport : activeAirports) { + for (const auto& supportedAirport : supportedAirports) { + if (supportedAirport == activeAirport) { + cdmActiveAirports.push_back(supportedAirport); + break; + } + } + } + + this->m_activeAirports = cdmActiveAirports; } void DataManager::queueFlightplanUpdate(EuroScopePlugIn::CFlightPlan flightplan) { diff --git a/src/core/Server.cpp b/src/core/Server.cpp index 475318a..ffe7766 100644 --- a/src/core/Server.cpp +++ b/src/core/Server.cpp @@ -134,89 +134,116 @@ Server::ServerConfiguration Server::getServerConfig() { return ServerConfiguration(); } +void Server::retrieveSupportedAirports() { + if (false == this->m_apiIsChecked || false == this->m_apiIsValid) { return; } + + std::lock_guard guard(m_clientMutex); + if (m_client) { + std::string url = "/api/v1/airports"; + auto result = m_client->Get(url); + + if (result && result->status == 200) { + nlohmann::json root; + + try { + root = nlohmann::json::parse(result->body); + std::list airports; + for (const auto& airport : std::as_const(root)) { + airports.push_back(airport["icao"].get()); + } + m_supportedAirports = airports; + } catch (const std::exception& e) { + SpdLogger::log(SpdLogger::LogSender::Server, "Failed to parse response JSON: " + std::string(e.what()), + SpdLogger::LogLevel::Info); + } + } + } +} + +std::list Server::getSupportedAirports() { return m_supportedAirports; }; + + + std::list Server::getPilots(const std::list airports) { std::lock_guard guard(m_clientMutex); if (!m_client) { return {}; } - std::string url = "/api/v1/pilots"; + std::list pilots; + std::string baseUrl = "/api/v1/pilots?adep="; - // Add airport filter if specified - if (!airports.empty()) { - url += "?airports="; - url += std::accumulate(std::next(airports.begin()), airports.end(), *airports.begin(), - [](const std::string& a, const std::string& b) { return a + "," + b; }); - } + for (const auto& airport : airports) { + std::string url = baseUrl + airport; - SpdLogger::log(SpdLogger::LogSender::Server, url, SpdLogger::LogLevel::Info); + SpdLogger::log(SpdLogger::LogSender::Server, url, SpdLogger::LogLevel::Info); - auto result = m_client->Get(url); - if (result && result->status == 200) { - nlohmann::json root; - - try { - root = nlohmann::json::parse(result->body); - std::list pilots; - - for (const auto& pilot : std::as_const(root)) { - pilots.push_back(types::Pilot()); - - pilots.back().callsign = pilot["callsign"].get(); - pilots.back().lastUpdate = utils::Date::isoStringToTimestamp(pilot["updatedAt"].get()); - pilots.back().inactive = pilot["inactive"].get(); - - // position data - pilots.back().latitude = pilot["position"]["lat"].get(); - pilots.back().longitude = pilot["position"]["lon"].get(); - pilots.back().taxizoneIsTaxiout = pilot["vacdm"]["taxizoneIsTaxiout"].get(); - - // flightplan & clearance data - pilots.back().origin = pilot["flightplan"]["departure"].get(); - pilots.back().destination = pilot["flightplan"]["arrival"].get(); - pilots.back().runway = pilot["clearance"]["dep_rwy"].get(); - pilots.back().sid = pilot["clearance"]["sid"].get(); - - // ACDM procedure data - pilots.back().eobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["eobt"].get()); - pilots.back().tobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tobt"].get()); - pilots.back().tobt_state = pilot["vacdm"]["tobt_state"].get(); - pilots.back().ctot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ctot"].get()); - pilots.back().ttot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ttot"].get()); - pilots.back().tsat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tsat"].get()); - pilots.back().exot = - std::chrono::utc_clock::time_point(std::chrono::minutes(pilot["vacdm"]["exot"].get())); - pilots.back().asat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asat"].get()); - pilots.back().aobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aobt"].get()); - pilots.back().atot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["atot"].get()); - pilots.back().asrt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asrt"].get()); - pilots.back().aort = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aort"].get()); - - // ECFMP measures - nlohmann::json measuresArray = pilot["measures"]; - std::vector parsedMeasures; - for (const auto& measureObject : std::as_const(measuresArray)) { - vacdm::types::EcfmpMeasure measure; - - measure.ident = measureObject["ident"].get(); - measure.value = measureObject["value"].get(); - - parsedMeasures.push_back(measure); - } - pilots.back().measures = parsedMeasures; + auto result = m_client->Get(url); + if (result && result->status == 200) { + nlohmann::json root; - // event booking data - pilots.back().hasBooking = pilot["hasBooking"].get(); + try { + root = nlohmann::json::parse(result->body); + + for (const auto& pilot : std::as_const(root)) { + pilots.push_back(types::Pilot()); + + pilots.back().callsign = pilot["callsign"].get(); + pilots.back().lastUpdate = utils::Date::isoStringToTimestamp(pilot["updatedAt"].get()); + pilots.back().inactive = pilot["inactive"].get(); + + // position data + pilots.back().latitude = pilot["position"]["lat"].get(); + pilots.back().longitude = pilot["position"]["lon"].get(); + pilots.back().taxizoneIsTaxiout = pilot["vacdm"]["taxizoneIsTaxiout"].get(); + + // flightplan & clearance data + pilots.back().origin = pilot["flightplan"]["departure"].get(); + pilots.back().destination = pilot["flightplan"]["arrival"].get(); + pilots.back().runway = pilot["clearance"]["dep_rwy"].get(); + pilots.back().sid = pilot["clearance"]["sid"].get(); + + // ACDM procedure data + pilots.back().eobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["eobt"].get()); + pilots.back().tobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tobt"].get()); + pilots.back().tobt_state = pilot["vacdm"]["tobt_state"].get(); + pilots.back().ctot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ctot"].get()); + pilots.back().ttot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ttot"].get()); + pilots.back().tsat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tsat"].get()); + pilots.back().exot = + std::chrono::utc_clock::time_point(std::chrono::minutes(pilot["vacdm"]["exot"].get())); + pilots.back().asat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asat"].get()); + pilots.back().aobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aobt"].get()); + pilots.back().atot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["atot"].get()); + pilots.back().asrt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asrt"].get()); + pilots.back().aort = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aort"].get()); + + // ECFMP measures + nlohmann::json measuresArray = pilot["measures"]; + std::vector parsedMeasures; + for (const auto& measureObject : std::as_const(measuresArray)) { + vacdm::types::EcfmpMeasure measure; + + measure.ident = measureObject["ident"].get(); + measure.value = measureObject["value"].get(); + + parsedMeasures.push_back(measure); + } + pilots.back().measures = parsedMeasures; + + // event booking data + pilots.back().hasBooking = pilot["hasBooking"].get(); + } + } catch (const std::exception& e) { + SpdLogger::log(SpdLogger::LogSender::Server, "Failed to parse response JSON: " + std::string(e.what()), + SpdLogger::LogLevel::Info); } - SpdLogger::log(SpdLogger::LogSender::Server, "Pilots size: " + std::to_string(pilots.size()), - SpdLogger::LogLevel::Info); - return pilots; - } catch (const std::exception& e) { - SpdLogger::log(SpdLogger::LogSender::Server, "Failed to parse response JSON: " + std::string(e.what()), - SpdLogger::LogLevel::Info); } } - return {}; + + SpdLogger::log(SpdLogger::LogSender::Server, "Pilots size: " + std::to_string(pilots.size()), + SpdLogger::LogLevel::Info); + return pilots; } void Server::sendPostMessage(const std::string& endpointUrl, const nlohmann::json& root) { diff --git a/src/core/Server.h b/src/core/Server.h index 7298d6b..934aa2d 100644 --- a/src/core/Server.h +++ b/src/core/Server.h @@ -35,6 +35,8 @@ class Server { std::string m_errorCode; ServerConfiguration m_serverConfiguration; + std::list m_supportedAirports; + public: ~Server(); Server(const Server&) = delete; @@ -78,6 +80,9 @@ class Server { void setMaster(bool master); bool getMaster(); + void retrieveSupportedAirports(); + std::list getSupportedAirports(); + private: // Helper method to initialize/reinitialize the HTTP client void initClient(); diff --git a/src/core/TagFunctions.h b/src/core/TagFunctions.h index bf65f2a..84c8672 100644 --- a/src/core/TagFunctions.h +++ b/src/core/TagFunctions.h @@ -139,8 +139,8 @@ void vACDM::OnFunctionCall(int functionId, const char *itemString, POINT pt, REC break; } case AOBT_NOW_AND_STATE: { - // set ASRT if ASRT has not been set yet - if (pilot.asrt == types::defaultTime) { + // set AORT if AORT has not been set yet + if (pilot.aort == types::defaultTime) { DataManager::instance().handleTagFunction(DataManager::MessageType::UpdateAORT, pilot.callsign, std::chrono::utc_clock::now()); } diff --git a/src/vACDM.cpp b/src/vACDM.cpp index 1d3cbaf..efc6381 100644 --- a/src/vACDM.cpp +++ b/src/vACDM.cpp @@ -57,6 +57,7 @@ void vACDM::checkServerConfiguration() { } else { std::string serverName = Server::instance().getServerConfig().name; DisplayMessage(("Connected to " + serverName), "Server"); + Server::instance().retrieveSupportedAirports(); // set active airports and runways this->OnAirportRunwayActivityChanged(); }