|
@@ -58,6 +58,7 @@ PlugIn::PlugIn() :
|
|
m_screen(),
|
|
m_screen(),
|
|
m_updateQueueLock(),
|
|
m_updateQueueLock(),
|
|
m_updateQueue(),
|
|
m_updateQueue(),
|
|
|
|
+ m_initialApproachFixes(),
|
|
m_inboundsQueueLock(),
|
|
m_inboundsQueueLock(),
|
|
m_inbounds(),
|
|
m_inbounds(),
|
|
m_forcedToBackendCallsigns(),
|
|
m_forcedToBackendCallsigns(),
|
|
@@ -111,6 +112,77 @@ PlugIn::~PlugIn() {
|
|
google::protobuf::ShutdownProtobufLibrary();
|
|
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<long>(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<Json::CharReader> 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() {
|
|
void PlugIn::validateBackendData() {
|
|
if (false == this->m_configuration.valid) {
|
|
if (false == this->m_configuration.valid) {
|
|
this->m_compatible = false;
|
|
this->m_compatible = false;
|
|
@@ -191,8 +263,13 @@ void PlugIn::validateBackendData() {
|
|
|
|
|
|
std::lock_guard guard(this->m_updateQueueLock);
|
|
std::lock_guard guard(this->m_updateQueueLock);
|
|
this->m_updateQueue.clear();
|
|
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->m_updateQueue.insert({ airport, {} });
|
|
|
|
+ this->receiveConfiguration(airport);
|
|
|
|
+ }
|
|
|
|
+
|
|
this->m_compatible = true;
|
|
this->m_compatible = true;
|
|
|
|
|
|
this->DisplayUserMessage(PLUGIN_NAME, "INFO", "Reloaded AMAN-configuration", true, true, false, false, false);
|
|
this->DisplayUserMessage(PLUGIN_NAME, "INFO", "Reloaded AMAN-configuration", true, true, false, false, false);
|
|
@@ -338,7 +415,7 @@ void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarT
|
|
return;
|
|
return;
|
|
|
|
|
|
/* filter invalid destinations */
|
|
/* filter invalid destinations */
|
|
- const auto destination = std::string_view(flightPlan.GetFlightPlanData().GetDestination());
|
|
|
|
|
|
+ const auto destination = std::string(flightPlan.GetFlightPlanData().GetDestination());
|
|
if (4 != destination.length())
|
|
if (4 != destination.length())
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -387,36 +464,28 @@ void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarT
|
|
EuroScopePlugIn::CPosition iafPosition;
|
|
EuroScopePlugIn::CPosition iafPosition;
|
|
std::string iafName;
|
|
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()) {
|
|
if (0 != iafName.length()) {
|
|
- const std::string_view direct(flightPlan.GetControllerAssignedData().GetDirectToPointName());
|
|
|
|
|
|
+ std::string_view direct(flightPlan.GetControllerAssignedData().GetDirectToPointName());
|
|
bool directBehindIAF = false;
|
|
bool directBehindIAF = false;
|
|
|
|
|
|
if (0 != direct.length()) {
|
|
if (0 != direct.length()) {
|