From bbbb99bc687b3085c92264885694d1c0a53284cb Mon Sep 17 00:00:00 2001 From: Ben Walker <146777065+BenWalker01@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:32:08 +0000 Subject: [PATCH 1/5] only send clearance after ACK has been sent --- vSMR/SMRPlugin.cpp | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/vSMR/SMRPlugin.cpp b/vSMR/SMRPlugin.cpp index 922c35929..00c78d1a4 100644 --- a/vSMR/SMRPlugin.cpp +++ b/vSMR/SMRPlugin.cpp @@ -188,16 +188,36 @@ 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) { From 98520ad3603895a8c487df6f905b2859e72c0de5 Mon Sep 17 00:00:00 2001 From: Ben Walker <146777065+BenWalker01@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:33:25 +0000 Subject: [PATCH 2/5] poll every 60s for hoppies --- vSMR/SMRPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vSMR/SMRPlugin.cpp b/vSMR/SMRPlugin.cpp index 00c78d1a4..5ceb57f06 100644 --- a/vSMR/SMRPlugin.cpp +++ b/vSMR/SMRPlugin.cpp @@ -683,7 +683,7 @@ void CSMRPlugin::OnTimer(int Counter) HoppieConnected = false; } - if (((clock() - timer) / CLOCKS_PER_SEC) > 10 && HoppieConnected) { + if (((clock() - timer) / CLOCKS_PER_SEC) > 60 && HoppieConnected) { _beginthread(pollMessages, 0, NULL); timer = clock(); } From 6f0cfd3c31bb3758cee184cfe6688b744d337604 Mon Sep 17 00:00:00 2001 From: Ben Walker <146777065+BenWalker01@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:35:27 +0000 Subject: [PATCH 3/5] poll hoppies randomly --- vSMR/SMRPlugin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vSMR/SMRPlugin.cpp b/vSMR/SMRPlugin.cpp index 5ceb57f06..21cf57196 100644 --- a/vSMR/SMRPlugin.cpp +++ b/vSMR/SMRPlugin.cpp @@ -54,6 +54,7 @@ string ttype; int messageId = 0; clock_t timer; +int pollInterval = 45 + rand() % 31; // Random interval between 45-75 seconds string myfrequency; @@ -683,9 +684,10 @@ void CSMRPlugin::OnTimer(int Counter) HoppieConnected = false; } - if (((clock() - timer) / CLOCKS_PER_SEC) > 60 && 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 } for (auto &ac : AircraftWilco) From 81afa179f2f4d9e59142c020dba4b728d662e9d2 Mon Sep 17 00:00:00 2001 From: Ben Walker <146777065+BenWalker01@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:43:14 +0000 Subject: [PATCH 4/5] only send clearance finack to cleared aircraft --- vSMR/SMRPlugin.cpp | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/vSMR/SMRPlugin.cpp b/vSMR/SMRPlugin.cpp index 21cf57196..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; @@ -222,7 +224,8 @@ void pollMessages(void * arg) { } } 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); @@ -232,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 ){ @@ -314,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(); } }; @@ -511,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()); } @@ -662,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) @@ -690,6 +714,18 @@ void CSMRPlugin::OnTimer(int Counter) 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) { CRadarTarget RadarTarget = RadarTargetSelect(ac.c_str()); From 2f70593c4b0e5399fb1ea340a8ea981ff9b6b4d6 Mon Sep 17 00:00:00 2001 From: Ben Walker <146777065+BenWalker01@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:46:09 +0000 Subject: [PATCH 5/5] update pr target builds --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]