diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd578d714..e7dea2c50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build DLL on: pull_request: - branches: [main,master,dev,develop] + branches: [master,main,dev,develop] release: types: [published] diff --git a/vSMR/SMRPlugin.cpp b/vSMR/SMRPlugin.cpp index 922c35929..995fb0a4e 100644 --- a/vSMR/SMRPlugin.cpp +++ b/vSMR/SMRPlugin.cpp @@ -42,6 +42,8 @@ struct AcarsMessage { vector AircraftDemandingClearance; vector AircraftMessageSent; +vector AircraftClearedByDatalink; +map AircraftClearedTimestamps; vector AircraftMessage; vector AircraftWilco; vector AircraftStandby; @@ -54,6 +56,7 @@ string ttype; int messageId = 0; clock_t timer; +int pollInterval = 45 + rand() % 31; // Random interval between 45-75 seconds string myfrequency; @@ -188,20 +191,41 @@ void pollMessages(void * arg) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); PlaySound(MAKEINTRESOURCE(IDR_WAVE1), AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC); } - AircraftDemandingClearance.push_back(message.from); string timeS, dateS; formatNowTimeDate(timeS, dateS); - // Send ack + // Send ack synchronously before adding to clearance queue string reqAck = "DEPART MESSAGE REQUEST RECEIVED "; reqAck += timeS + " " + dateS; reqAck += " REQUEST BEING PROCESSED"; - createPlainCpdlcMessage(reqAck.c_str(), "NE"); - tdest = message.from; - _beginthread(sendDatalinkMessage, 0, NULL); + + string raw; + string url = baseUrlDatalink; + url += "?logon="; + url += logonCode; + url += "&from="; + url += logonCallsign; + url += "&to="; + url += message.from; + url += "&type=CPDLC&packet=/data2/"; + url += std::to_string(++messageId); + url += "//NE/"; + url += reqAck; + + size_t start_pos = 0; + while ((start_pos = url.find(" ", start_pos)) != std::string::npos) { + url.replace(start_pos, string(" ").length(), "%20"); + start_pos += string("%20").length(); + } + + raw.assign(httpHelper->downloadStringFromURL(url)); + + // Only add to clearance queue after ack is sent + AircraftDemandingClearance.push_back(message.from); } } else if (message.message.find("WILCO") != std::string::npos || message.message.find("ROGER") != std::string::npos || message.message.find("RGR") != std::string::npos || message.message.find("ACCEPT") != std::string::npos) { - if (std::find(AircraftMessageSent.begin(), AircraftMessageSent.end(), message.from) != AircraftMessageSent.end()) { + // Only send confirmation if this aircraft actually received a clearance (not just a voice message) + if (std::find(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), message.from) != AircraftClearedByDatalink.end()) { AircraftWilco.push_back(message.from); string timeS, dateS; formatNowTimeDate(timeS, dateS); @@ -211,6 +235,10 @@ void pollMessages(void * arg) { clearanceAck += " CLEARANCE CONFIRMED"; createPlainCpdlcMessage(clearanceAck.c_str(), "NE"); _beginthread(sendDatalinkMessage, 0, NULL); + + // Remove from cleared list - clearance workflow is complete + AircraftClearedByDatalink.erase(std::remove(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), message.from), AircraftClearedByDatalink.end()); + AircraftClearedTimestamps.erase(message.from); } } else if (message.message.length() != 0 ){ @@ -293,6 +321,8 @@ if (DatalinkToSend.sid == "CHK" && DatalinkToSend.rwy == "09R") // CPT 09R if (PendingMessages.find(DatalinkToSend.callsign) != PendingMessages.end()) PendingMessages.erase(DatalinkToSend.callsign); AircraftMessageSent.push_back(DatalinkToSend.callsign.c_str()); + AircraftClearedByDatalink.push_back(DatalinkToSend.callsign.c_str()); + AircraftClearedTimestamps[DatalinkToSend.callsign] = clock(); } }; @@ -490,6 +520,10 @@ void CSMRPlugin::OnFunctionCall(int FunctionId, const char * sItemString, POINT if (std::find(AircraftMessageSent.begin(), AircraftMessageSent.end(), FlightPlan.GetCallsign()) != AircraftMessageSent.end()) { AircraftMessageSent.erase(std::remove(AircraftMessageSent.begin(), AircraftMessageSent.end(), FlightPlan.GetCallsign()), AircraftMessageSent.end()); } + if (std::find(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), FlightPlan.GetCallsign()) != AircraftClearedByDatalink.end()) { + AircraftClearedByDatalink.erase(std::remove(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), FlightPlan.GetCallsign()), AircraftClearedByDatalink.end()); + AircraftClearedTimestamps.erase(FlightPlan.GetCallsign()); + } if (std::find(AircraftWilco.begin(), AircraftWilco.end(), FlightPlan.GetCallsign()) != AircraftWilco.end()) { AircraftWilco.erase(std::remove(AircraftWilco.begin(), AircraftWilco.end(), FlightPlan.GetCallsign()), AircraftWilco.end()); } @@ -641,6 +675,17 @@ void CSMRPlugin::OnFlightPlanDisconnect(CFlightPlan FlightPlan) if (std::find(ManuallyCorrelated.begin(), ManuallyCorrelated.end(), rt.GetSystemID()) != ManuallyCorrelated.end()) ManuallyCorrelated.erase(std::find(ManuallyCorrelated.begin(), ManuallyCorrelated.end(), rt.GetSystemID())); + + // Clean up all datalink tracking lists + string callsign = FlightPlan.GetCallsign(); + AircraftDemandingClearance.erase(std::remove(AircraftDemandingClearance.begin(), AircraftDemandingClearance.end(), callsign), AircraftDemandingClearance.end()); + AircraftMessageSent.erase(std::remove(AircraftMessageSent.begin(), AircraftMessageSent.end(), callsign), AircraftMessageSent.end()); + AircraftClearedByDatalink.erase(std::remove(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), callsign), AircraftClearedByDatalink.end()); + AircraftClearedTimestamps.erase(callsign); + AircraftMessage.erase(std::remove(AircraftMessage.begin(), AircraftMessage.end(), callsign), AircraftMessage.end()); + AircraftWilco.erase(std::remove(AircraftWilco.begin(), AircraftWilco.end(), callsign), AircraftWilco.end()); + AircraftStandby.erase(std::remove(AircraftStandby.begin(), AircraftStandby.end(), callsign), AircraftStandby.end()); + PendingMessages.erase(callsign); } void CSMRPlugin::OnTimer(int Counter) @@ -663,9 +708,22 @@ void CSMRPlugin::OnTimer(int Counter) HoppieConnected = false; } - if (((clock() - timer) / CLOCKS_PER_SEC) > 10 && HoppieConnected) { + if (((clock() - timer) / CLOCKS_PER_SEC) > pollInterval && HoppieConnected) { _beginthread(pollMessages, 0, NULL); timer = clock(); + pollInterval = 45 + rand() % 31; // Next random interval between 45-75 seconds + } + + // Remove cleared aircraft after 5 minutes (300 seconds) + clock_t currentTime = clock(); + for (auto it = AircraftClearedTimestamps.begin(); it != AircraftClearedTimestamps.end(); ) { + if (((currentTime - it->second) / CLOCKS_PER_SEC) > 300) { + string callsign = it->first; + AircraftClearedByDatalink.erase(std::remove(AircraftClearedByDatalink.begin(), AircraftClearedByDatalink.end(), callsign), AircraftClearedByDatalink.end()); + it = AircraftClearedTimestamps.erase(it); + } else { + ++it; + } } for (auto &ac : AircraftWilco)