From 1873c68ab0366d1b2f424c49ae4061304fd8edfc Mon Sep 17 00:00:00 2001 From: Sven Czarnian Date: Sun, 26 Dec 2021 10:43:15 +0100 Subject: [PATCH] use the server's IAFs to check if we have a new inbound and over which IAF --- src/PlugIn.cpp | 121 ++++++++++++++++++++++++++++++++++++++----------- src/PlugIn.h | 30 +++++++----- 2 files changed, 113 insertions(+), 38 deletions(-) diff --git a/src/PlugIn.cpp b/src/PlugIn.cpp index 27d41db..c82d492 100644 --- a/src/PlugIn.cpp +++ b/src/PlugIn.cpp @@ -58,6 +58,7 @@ PlugIn::PlugIn() : m_screen(), m_updateQueueLock(), m_updateQueue(), + m_initialApproachFixes(), m_inboundsQueueLock(), m_inbounds(), m_forcedToBackendCallsigns(), @@ -111,6 +112,77 @@ PlugIn::~PlugIn() { google::protobuf::ShutdownProtobufLibrary(); } +void PlugIn::receiveConfiguration(const std::string& airport) { + /* set up the URL */ + std::string url; + if (true == this->m_configuration.httpsProtocol) + url += "https://"; + else + url += "http://"; + url += this->m_configuration.address + ":" + std::to_string(this->m_configuration.portRestAPI) + "/aman/configuration/" + airport; + + CURL* curl = curl_easy_init(); + CURLcode result; + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receiveCurl); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L); + + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Accept: */*"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + __receivedAmanData.clear(); + + result = curl_easy_perform(curl); + + if (CURLE_OK != result) { + MessageBoxA(nullptr, "Unable to receive backend information", "AMAN-Error", MB_OK); + return; + } + + /* validate the json data */ + Json::Value root; + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + if (false == reader->parse(__receivedAmanData.c_str(), __receivedAmanData.c_str() + __receivedAmanData.length(), &root, nullptr)) { + MessageBoxA(nullptr, "Received invalid backend data", "AMAN-Error", MB_OK); + return; + } + + for (auto it = root.begin(); root.end() != it; ++it) { + if ("iafs" == it.key().asString() && true == it->isArray()) { + auto iafArray = *it; + this->m_initialApproachFixes.insert({ airport, {} }); + + this->m_initialApproachFixes[airport].reserve(iafArray.size()); + for (Json::Value::ArrayIndex i = 0; i < iafArray.size(); ++i) { + if (true == iafArray[i].isObject()) { + Angle latitude, longitude; + std::string name; + + for (auto cit = iafArray[i].begin(); iafArray[i].end() != cit; ++cit) { + if ("name" == cit.key().asString()) + name = cit->asString(); + else if ("lat" == cit.key().asString()) + latitude = cit->asFloat() * degree; + else if ("lon" == cit.key().asString()) + longitude = cit->asFloat() * degree; + } + + this->m_initialApproachFixes[airport].push_back({ name, GeoCoordinate(longitude, latitude) }); + } + } + } + } +} + void PlugIn::validateBackendData() { if (false == this->m_configuration.valid) { this->m_compatible = false; @@ -191,8 +263,13 @@ void PlugIn::validateBackendData() { std::lock_guard guard(this->m_updateQueueLock); this->m_updateQueue.clear(); - for (const auto& airport : std::as_const(airports)) + this->m_initialApproachFixes.clear(); + + for (const auto& airport : std::as_const(airports)) { this->m_updateQueue.insert({ airport, {} }); + this->receiveConfiguration(airport); + } + this->m_compatible = true; this->DisplayUserMessage(PLUGIN_NAME, "INFO", "Reloaded AMAN-configuration", true, true, false, false, false); @@ -338,7 +415,7 @@ void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarT return; /* filter invalid destinations */ - const auto destination = std::string_view(flightPlan.GetFlightPlanData().GetDestination()); + const auto destination = std::string(flightPlan.GetFlightPlanData().GetDestination()); if (4 != destination.length()) return; @@ -387,36 +464,28 @@ void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarT EuroScopePlugIn::CPosition iafPosition; std::string iafName; - for (auto element = this->SectorFileElementSelectFirst(EuroScopePlugIn::SECTOR_ELEMENT_STAR); - true == element.IsValid(); - element = this->SectorFileElementSelectNext(element, EuroScopePlugIn::SECTOR_ELEMENT_STAR)) - { - auto split = String::splitString(element.GetName(), " "); - - /* find the correct star */ - if (0 != split.size() && destination == gsl::at(split, 0)) { - /* get the IAF */ - EuroScopePlugIn::CPosition position; - if (true == element.GetPosition(&position, 0)) { - /* match the waypoints to get the name*/ - for (int i = 0; i < flightPlan.GetExtractedRoute().GetPointsNumber(); ++i) { - if (1.0f >= flightPlan.GetExtractedRoute().GetPointPosition(i).DistanceTo(position)) { - iafPosition = flightPlan.GetExtractedRoute().GetPointPosition(i); - iafName = flightPlan.GetExtractedRoute().GetPointName(i); - report->set_initialapproachfix(iafName); - iafRouteIndex = i; - break; - } + auto iafIt = this->m_initialApproachFixes.find(destination); + if (this->m_initialApproachFixes.cend() != iafIt) { + for (const auto& iaf : std::as_const(iafIt->second)) { + for (int i = 0; i < flightPlan.GetExtractedRoute().GetPointsNumber(); ++i) { + if (flightPlan.GetExtractedRoute().GetPointName(i) == iaf.name) { + iafName = iaf.name; + break; } } - } - if (0 != iafName.length()) - break; + if (0 == iafName.length()) { + if (flightPlan.GetControllerAssignedData().GetDirectToPointName() == iaf.name) + iafName = iaf.name; + } + + if (0 != iafName.length()) + break; + } } if (0 != iafName.length()) { - const std::string_view direct(flightPlan.GetControllerAssignedData().GetDirectToPointName()); + std::string_view direct(flightPlan.GetControllerAssignedData().GetDirectToPointName()); bool directBehindIAF = false; if (0 != direct.length()) { diff --git a/src/PlugIn.h b/src/PlugIn.h index 452ae9a..d418ff8 100644 --- a/src/PlugIn.h +++ b/src/PlugIn.h @@ -47,6 +47,10 @@ namespace aman { std::vector arrivalRunways; std::list inboundUpdates; }; + struct InitialApproachFix { + std::string name; + GeoCoordinate coordinate; + }; enum class TagItemElement { EstimatedTimeOfArrival = 0, @@ -56,6 +60,7 @@ namespace aman { }; void validateBackendData(); + void receiveConfiguration(const std::string& airport); aman::Aircraft* generateAircraftMessage(const EuroScopePlugIn::CRadarTarget& target) const; void generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarTarget, aman::AircraftReport* report); void addUpdateQueue(EuroScopePlugIn::CRadarTarget& radarTarget); @@ -64,18 +69,19 @@ namespace aman { static void distanceToPredictedIaf(const EuroScopePlugIn::CRadarTarget& radarTarget, const EuroScopePlugIn::CFlightPlan& flightPlan, const EuroScopePlugIn::CPosition& iafPosition, aman::AircraftReport* report); - Communication m_configuration; - std::shared_ptr m_screen; - std::mutex m_updateQueueLock; - std::map m_updateQueue; - std::mutex m_inboundsQueueLock; - std::map m_inbounds; - std::map m_selectedRunway; - std::list m_forcedToBackendCallsigns; - bool m_compatible; - bool m_connectedToNetwork; - bool m_sweatboxValid; - bool m_playbackValid; + Communication m_configuration; + std::shared_ptr m_screen; + std::mutex m_updateQueueLock; + std::map m_updateQueue; + std::map> m_initialApproachFixes; + std::mutex m_inboundsQueueLock; + std::map m_inbounds; + std::map m_selectedRunway; + std::list m_forcedToBackendCallsigns; + bool m_compatible; + bool m_connectedToNetwork; + bool m_sweatboxValid; + bool m_playbackValid; public: /**