From 980f506b6e1bf6f4f781a9430c41affccfc7d5ac Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Mon, 2 Feb 2026 12:39:33 +0100
Subject: [PATCH 01/13] Update Changelog.txt
---
Changelog.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Changelog.txt b/Changelog.txt
index 1332840..67262a6 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,3 +1,7 @@
+[Changelog v0.14.4]
+:lady_beetle: **Fixes**
+* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this
+
[Changelog v0.14.3.1]
>[!NOTE]
> This Hotfix is only needed if SIDs without any route (no waypoint after the last ':') is present
From 25c12cfd3d010db9967a9685821b22dd1130eb7b Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Mon, 2 Feb 2026 12:40:53 +0100
Subject: [PATCH 02/13] Update version
---
vSIDPlugin.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vSIDPlugin.h b/vSIDPlugin.h
index e7ba294..e9e89f5 100644
--- a/vSIDPlugin.h
+++ b/vSIDPlugin.h
@@ -46,7 +46,7 @@ along with this program. If not, see .
namespace vsid
{
const std::string pluginName = "vSID";
- const std::string pluginVersion = "0.14.3.1";
+ const std::string pluginVersion = "0.14.4";
const std::string pluginAuthor = "Gameagle";
const std::string pluginCopyright = "GPL v3";
const std::string pluginViewAviso = "";
From 7e10d4099b3115b38a397c44c0492d2c89686139 Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Mon, 2 Feb 2026 12:41:18 +0100
Subject: [PATCH 03/13] Move squawk item out of adep check
#401
---
vSIDPlugin.cpp | 106 ++++++++++++++++++++++++++-----------------------
1 file changed, 56 insertions(+), 50 deletions(-)
diff --git a/vSIDPlugin.cpp b/vSIDPlugin.cpp
index 97ae174..eb93527 100644
--- a/vSIDPlugin.cpp
+++ b/vSIDPlugin.cpp
@@ -3127,56 +3127,6 @@ void vsid::VSIDPlugin::OnGetTagItem(EuroScopePlugIn::CFlightPlan FlightPlan, Eur
}
}
- if (ItemCode == TAG_ITEM_VSID_SQW)
- {
- if (auto it = std::find(this->squawkQueue.begin(), this->squawkQueue.end(), callsign); it != this->squawkQueue.end())
- {
- *pRGB = RGB(255, 255, 255);
-
- if(it == this->squawkQueue.begin()) strcpy_s(sItemString, 16, "NEXT");
- else strcpy_s(sItemString, 16, "STBY");
-
- return; // prevent displaying of old squawk until new is set
- }
- std::string setSquawk = FlightPlan.GetFPTrackPosition().GetSquawk();
- std::string assignedSquawk = FlightPlan.GetControllerAssignedData().GetSquawk();
-
- if (setSquawk != assignedSquawk)
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_RGB_DEFINED;
- *pRGB = this->configParser.getColor("squawkNotSet");
- }
- else
- {
- if (this->configParser.getColor("squawkSet") == RGB(300, 300, 300))
- {
- if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_NON_CONCERNED)
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_NON_CONCERNED;
- }
- else if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_NOTIFIED)
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_NOTIFIED;
- }
- else if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_ASSUMED)
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_ASSUMED;
- }
- else
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_DEFAULT;
- }
- }
- else
- {
- *pColorCode = EuroScopePlugIn::TAG_COLOR_RGB_DEFINED;
- *pRGB = this->configParser.getColor("squawkSet");
- }
- }
-
- if (assignedSquawk != "0000" && assignedSquawk != "1234") strcpy_s(sItemString, 16, assignedSquawk.c_str());
- }
-
if (ItemCode == TAG_ITEM_VSID_REQ)
{
if (this->processed.contains(callsign) && this->processed[callsign].request != "")
@@ -3387,6 +3337,62 @@ void vsid::VSIDPlugin::OnGetTagItem(EuroScopePlugIn::CFlightPlan FlightPlan, Eur
}
}
}
+
+
+
+ if (ItemCode == TAG_ITEM_VSID_SQW)
+ {
+ if (this->activeAirports.contains(adep))
+ {
+ if (auto it = std::find(this->squawkQueue.begin(), this->squawkQueue.end(), callsign); it != this->squawkQueue.end())
+ {
+ *pRGB = RGB(255, 255, 255);
+
+ if (it == this->squawkQueue.begin()) strcpy_s(sItemString, 16, "NEXT");
+ else strcpy_s(sItemString, 16, "STBY");
+
+ return; // prevent displaying of old squawk until new is set
+ }
+ }
+
+ std::string setSquawk = FlightPlan.GetFPTrackPosition().GetSquawk();
+ std::string assignedSquawk = FlightPlan.GetControllerAssignedData().GetSquawk();
+
+ if (setSquawk != assignedSquawk)
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_RGB_DEFINED;
+ *pRGB = this->configParser.getColor("squawkNotSet");
+ }
+ else
+ {
+ if (this->configParser.getColor("squawkSet") == RGB(300, 300, 300))
+ {
+ if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_NON_CONCERNED)
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_NON_CONCERNED;
+ }
+ else if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_NOTIFIED)
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_NOTIFIED;
+ }
+ else if (FlightPlan.GetState() == EuroScopePlugIn::FLIGHT_PLAN_STATE_ASSUMED)
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_ASSUMED;
+ }
+ else
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_DEFAULT;
+ }
+ }
+ else
+ {
+ *pColorCode = EuroScopePlugIn::TAG_COLOR_RGB_DEFINED;
+ *pRGB = this->configParser.getColor("squawkSet");
+ }
+ }
+
+ if (assignedSquawk != "0000" && assignedSquawk != "1234") strcpy_s(sItemString, 16, assignedSquawk.c_str());
+ }
}
bool vsid::VSIDPlugin::OnCompileCommand(const char* sCommandLine)
From 766aa6d757343abcdf32003c8f9ad6d8d6a71baa Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Wed, 25 Feb 2026 21:14:50 +0100
Subject: [PATCH 04/13] Update Changelog.txt
---
Changelog.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Changelog.txt b/Changelog.txt
index 67262a6..29f7120 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,6 +1,12 @@
[Changelog v0.14.4]
+:gear: **Changed Features / Behaviour**
+* FPLN - startup requests are now blocked if no runway is set (both "normal" startup and rwy startup)
+ * request system refactored - requests and rwy requests share the same type now (distinction is now stored with the flight plan)
+ * other smaller improvements to the request system (mainly startup request related)
+
:lady_beetle: **Fixes**
* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this
+* FPLN - rwy request indicators shouldn't be overwritten anymore (#406)
[Changelog v0.14.3.1]
>[!NOTE]
From 21665a111aeba7b84c1a5b50b2fc28cf0df8135f Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Wed, 25 Feb 2026 21:15:46 +0100
Subject: [PATCH 05/13] Refactor request system (#406)
---
configparser.cpp | 2 +-
constants.h | 1 +
display.cpp | 32 ++++---
vSIDPlugin.cpp | 220 ++++++++++++++++++++++++++++++++---------------
4 files changed, 173 insertions(+), 82 deletions(-)
diff --git a/configparser.cpp b/configparser.cpp
index 55fd29f..4226927 100644
--- a/configparser.cpp
+++ b/configparser.cpp
@@ -477,7 +477,7 @@ void vsid::ConfigParser::loadAirportConfig(std::map
aptInfo.requests["taxi"] = {};
aptInfo.requests["departure"] = {};
aptInfo.requests["vfr"] = {};
- aptInfo.rwyrequests["rwy startup"] = {};
+ aptInfo.rwyrequests["startup"] = {};
// customRules
diff --git a/constants.h b/constants.h
index 295483e..811eb1b 100644
--- a/constants.h
+++ b/constants.h
@@ -70,6 +70,7 @@ const int MENU_BOTTOM_BAR = 112;
// errors
const std::string ERROR_FPLN_ATCBLOCK = "E010";
+const std::string ERROR_FPLN_REQSPLIT = "E010-1";
const std::string ERROR_FPLN_SIDWPT = "E011";
const std::string ERROR_FPLN_SPLITWPT = "E012";
const std::string ERROR_FPLN_EXTFUNC = "E013";
diff --git a/display.cpp b/display.cpp
index c56d46a..9f4507b 100644
--- a/display.cpp
+++ b/display.cpp
@@ -152,19 +152,30 @@ void vsid::Display::OnRefresh(HDC hDC, int Phase)
this->getZoomLevel() <= sharedPlugin->getConfigParser().getIndicatorDefaultValues().showBelowZoom)
{
std::string adep = target.GetCorrelatedFlightPlan().GetFlightPlanData().GetOrigin();
- std::string fplnRwy = target.GetCorrelatedFlightPlan().GetFlightPlanData().GetDepartureRwy(); // # refactor - use rwy from actual flight plan (icao block)
+ std::string fplnRwy = vsid::fplnhelper::getAtcBlock(target.GetCorrelatedFlightPlan()).second;
+ std::string reqType = fplnInfo.request;
+ bool isRwyReq = fplnInfo.request.find("rwy") != std::string::npos;
- if (fplnInfo.request != "" && adep != "")
+ if (isRwyReq)
+ {
+ try
+ {
+ reqType = vsid::utils::split(reqType, ' ').at(1);
+ }
+ catch (std::out_of_range&) {}
+ }
+
+ if (!reqType.empty() && !adep.empty() && sharedPlugin->getActiveApts().contains(adep))
{
EuroScopePlugIn::CPosition offsetPos = this->getIndicatorOffset(targetPos, offset, zoomScale, 180.0);
POINT offsetPx = this->ConvertCoordFromPositionToPixel(offsetPos);
- try
+ if (!isRwyReq)
{
for (auto& [type, req] : sharedPlugin->getActiveApts().at(adep).requests)
{
- if (type != fplnInfo.request) continue;
+ if (type != reqType) continue;
for (std::set>::iterator it = req.begin(); it != req.end(); ++it)
{
@@ -188,21 +199,23 @@ void vsid::Display::OnRefresh(HDC hDC, int Phase)
dc.DrawText(reqPos.c_str(), &area, DT_BOTTOM);
}
}
-
+ }
+ else
+ {
for (auto& [type, rwys] : sharedPlugin->getActiveApts().at(adep).rwyrequests)
{
- if (type != fplnInfo.request) continue;
+ if (type != reqType) continue;
for (auto& [rwy, rwyReq] : rwys)
{
- if (fplnRwy == "" || fplnRwy != rwy) continue;
+ if (fplnRwy.empty() || fplnRwy != rwy) continue;
for (std::set>::iterator it = rwyReq.begin(); it != rwyReq.end(); ++it)
{
if (it->first != callsign) continue;
size_t pos = std::distance(it, rwyReq.end());
- std::string reqPos = vsid::utils::toupper(type).at(0) + std::to_string(pos);
+ std::string reqPos = "R" + std::to_string(pos);
CRect area;
@@ -219,8 +232,7 @@ void vsid::Display::OnRefresh(HDC hDC, int Phase)
}
}
}
- }
- catch (std::out_of_range) {};
+ }
}
}
diff --git a/vSIDPlugin.cpp b/vSIDPlugin.cpp
index eb93527..614d235 100644
--- a/vSIDPlugin.cpp
+++ b/vSIDPlugin.cpp
@@ -2380,97 +2380,138 @@ void vsid::VSIDPlugin::OnFunctionCall(int FunctionId, const char * sItemString,
if (FunctionId == TAG_FUNC_VSID_REQMENU)
{
+ if (!this->activeAirports.contains(adep))
+ {
+ messageHandler->writeMessage("WARNING", "[" + callsign + "] - Airport " + adep + " not active, can't process request!");
+ return;
+ }
if (strlen(sItemString) == 0)
{
this->OpenPopupList(Area, "REQ", 1);
this->AddPopupListElement("No Req", "No Req", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- if (this->activeAirports.contains(adep))
+ this->AddPopupListElement("Clearance", "Clearance", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ this->AddPopupListElement("Startup", "Startup", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ this->AddPopupListElement("RWY Startup", "RWY Startup", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ this->AddPopupListElement("Pushback", "Pushback", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ this->AddPopupListElement("Taxi", "Taxi", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ this->AddPopupListElement("Departure", "Departure", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
+ if (fpln.GetFlightPlanData().GetPlanType() == std::string("V"))
{
- this->AddPopupListElement("Clearance", "Clearance", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- this->AddPopupListElement("Startup", "Startup", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- this->AddPopupListElement("RWY Startup", "RWY Startup", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- this->AddPopupListElement("Pushback", "Pushback", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- this->AddPopupListElement("Taxi", "Taxi", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- this->AddPopupListElement("Departure", "Departure", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- if (fpln.GetFlightPlanData().GetPlanType() == std::string("V"))
- {
- this->AddPopupListElement("VFR", "VFR", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
- }
+ this->AddPopupListElement("VFR", "VFR", TAG_FUNC_VSID_REQMENU, false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false, false);
}
}
else if (strlen(sItemString) != 0)
{
std::string req = vsid::utils::tolower(sItemString);
+ bool isRwyReq = req.find("rwy") != std::string::npos;
+
+ if (isRwyReq)
+ {
+ try
+ {
+ req = vsid::utils::split(vsid::utils::tolower(sItemString), ' ').at(1);
+ }
+ catch (std::out_of_range&)
+ {
+ messageHandler->writeMessage("ERROR", "[" + callsign + "] failed to split RWY from request: " + sItemString);
+ return;
+ }
+ }
+
+ bool isFplRwyReq = this->processed[callsign].request.find("rwy") != std::string::npos;
std::string newScratch = "";
long long now = std::chrono::floor(std::chrono::utc_clock::now()).time_since_epoch().count();
- if (this->processed[callsign].request == req)
+ // check existing requests to preserve request times when switching from norm to rwy request and vice versa
+
+ if (!isRwyReq && !isFplRwyReq && this->processed[callsign].request == req) // all req other than rwq requests
{
- if (this->activeAirports[adep].requests.contains(req)) return;
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] no rwy req and stored req matches current req", vsid::MessageHandler::DebugArea::Req);
- if (this->activeAirports[adep].rwyrequests.contains(req))
+ if (this->activeAirports[adep].requests.contains(req))
{
- for (auto& [rwy, rwyReq] : this->activeAirports[adep].rwyrequests[req])
+ for (auto& [reqCallsign, _] : this->activeAirports[adep].requests[req])
{
- if (rwy != fplnData.GetDepartureRwy()) continue;
-
- for (auto& [reqCallsign, reqTime] : rwyReq)
+ if (reqCallsign == callsign)
{
- if (reqCallsign == callsign) return;
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] already in request list: " + req, vsid::MessageHandler::DebugArea::Req);
+ return;
}
}
}
}
- else if (req.find(this->processed[callsign].request) != std::string::npos)
+ else if (isRwyReq && isFplRwyReq && this->processed[callsign].request.find(req)) // both current and stored req are rwy req and a (partial) match
{
- if (req.find("rwy") != std::string::npos)
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] rwy req and stored req (partial) matches current req", vsid::MessageHandler::DebugArea::Req);
+
+ if (this->activeAirports[adep].rwyrequests.contains(req))
{
- try
+ for (auto& [reqRwy, fp] : this->activeAirports[adep].rwyrequests[req])
{
- std::string normReq = vsid::utils::split(req, ' ').at(1);
-
- if (this->activeAirports[adep].requests.contains(normReq))
+ for (auto& [reqCallsign, _] : fp)
{
- for (auto& [reqCallign, reqTime] : this->activeAirports[adep].requests[normReq])
+ if (reqCallsign == callsign)
{
- if (reqCallign != callsign) continue;
- now = reqTime;
- break;
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] already in request list: " + req + " for rwy: " + reqRwy,
+ vsid::MessageHandler::DebugArea::Req);
+ return;
}
}
}
- catch (std::out_of_range) {};
}
}
- else if (this->processed[callsign].request.find(req) != std::string::npos)
+ else if (!isRwyReq && isFplRwyReq && this->processed[callsign].request.find(req))
{
- try
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] has rwy request and current non-rwy req (partial) matches",
+ vsid::MessageHandler::DebugArea::Req);
+
+ if (this->activeAirports[adep].rwyrequests.contains(req))
{
bool stop = false;
- for (auto& [rwy, rwyReq] : this->activeAirports[adep].rwyrequests.at(this->processed[callsign].request))
+ for (auto& [reqRwy, _req] : this->activeAirports[adep].rwyrequests[req])
{
- if (rwy != fplnData.GetDepartureRwy()) continue;
-
- for (auto& [reqCallsign, reqTime] : rwyReq)
+ for (auto& [reqCallsign, reqTime] : _req)
{
if (reqCallsign != callsign) continue;
now = reqTime;
stop = true;
-
break;
}
+
if (stop) break;
}
}
- catch (std::out_of_range) {};
+ }
+ else if (isRwyReq && !isFplRwyReq && this->processed[callsign].request == req)
+ {
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] has no rwy req, but current req is a rwy req", vsid::MessageHandler::DebugArea::Req);
+
+ if (this->activeAirports[adep].requests.contains(req))
+ {
+ for (auto& [reqCallsign, reqTime] : this->activeAirports[adep].requests[req])
+ {
+ if (reqCallsign != callsign) continue;
+
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] found in req list: " + req + ". Storing time.", vsid::MessageHandler::DebugArea::Req);
+
+ now = reqTime;
+ break;
+ }
+ }
+ }
+
+ if (vsid::fplnhelper::getAtcBlock(fpln).second.empty())
+ {
+ messageHandler->writeMessage("WARNING", "[" + callsign + "] no departure runway found in flight plan for request: " + req + ". Not setting the request!");
+ return;
}
newScratch = ".vsid_req_" + std::string(sItemString) + "/" + std::to_string(now); // #refactor - now check for empty string needed
- if (newScratch != "") this->addSyncQueue(callsign, newScratch, fpln.GetControllerAssignedData().GetScratchPadString());
+ if (!newScratch.empty()) this->addSyncQueue(callsign, newScratch, fpln.GetControllerAssignedData().GetScratchPadString());
}
}
@@ -3129,13 +3170,34 @@ void vsid::VSIDPlugin::OnGetTagItem(EuroScopePlugIn::CFlightPlan FlightPlan, Eur
if (ItemCode == TAG_ITEM_VSID_REQ)
{
- if (this->processed.contains(callsign) && this->processed[callsign].request != "")
+ if (this->processed.contains(callsign) && !this->processed[callsign].request.empty())
{
- std::string& request = this->processed[callsign].request;
+
+ std::string request = this->processed[callsign].request;
+ bool isFplRwyReq = request.find("rwy") != std::string::npos;
+
+ if (isFplRwyReq)
+ {
+ try
+ {
+ request = vsid::utils::split(request, ' ').at(1);
+
+ messageHandler->removeFplnError(callsign, ERROR_FPLN_REQSPLIT);
+ }
+ catch (std::out_of_range&)
+ {
+ if (!messageHandler->getFplnErrors(callsign).contains(ERROR_FPLN_REQSPLIT))
+ {
+ messageHandler->writeMessage("ERROR", "[" + callsign + "] failed to split stored request (" + request +
+ ") on tagItem update. Code: " + ERROR_FPLN_REQSPLIT);
+ messageHandler->addFplnError(callsign, ERROR_FPLN_REQSPLIT);
+ }
+ }
+ }
// check rwy requests first
- if(this->activeAirports[adep].rwyrequests.contains(request))
+ if(isFplRwyReq && this->activeAirports[adep].rwyrequests.contains(request))
{
for (auto& [rwy, rwyreq] : this->activeAirports[adep].rwyrequests[request])
{
@@ -3144,7 +3206,7 @@ void vsid::VSIDPlugin::OnGetTagItem(EuroScopePlugIn::CFlightPlan FlightPlan, Eur
if (it->first == callsign)
{
int pos = std::distance(it, rwyreq.end());
- std::string req = vsid::utils::toupper(request).at(0) + std::to_string(pos);
+ std::string req = "R" + std::to_string(pos);
strcpy_s(sItemString, 16, req.c_str());
break;
}
@@ -3152,7 +3214,7 @@ void vsid::VSIDPlugin::OnGetTagItem(EuroScopePlugIn::CFlightPlan FlightPlan, Eur
}
}
// check normal requests
- else if (this->activeAirports[adep].requests.contains(request))
+ else if (!isFplRwyReq&& this->activeAirports[adep].requests.contains(request))
{
for (std::set>::iterator it = this->activeAirports[adep].requests[request].begin();
it != this->activeAirports[adep].requests[request].end(); ++it)
@@ -4203,7 +4265,7 @@ void vsid::VSIDPlugin::OnFlightPlanFlightPlanDataUpdate(EuroScopePlugIn::CFlight
{
if (!messageHandler->getFplnErrors(callsign).contains(ERROR_FPLN_AMEND))
{
- messageHandler->writeMessage("ERROR", "[" + callsign + "] - Failed to amend flight plan! - #FFDU");
+ messageHandler->writeMessage("ERROR", "[" + callsign + "] - Failed to amend flight plan! Code: " + ERROR_FPLN_AMEND);
messageHandler->addFplnError(callsign, ERROR_FPLN_AMEND);
}
@@ -4372,10 +4434,10 @@ void vsid::VSIDPlugin::OnFlightPlanControllerAssignedDataUpdate(EuroScopePlugIn:
if (this->spReleased.contains(callsign)) this->updateSPSyncRelease(callsign);
}
- // set intersection
-
if (this->processed.contains(callsign) && scratchpad.size() > 0)
{
+ // set intersection
+
if (scratchpad.size() <= 4 && this->activeAirports.contains(adep))
{
if (size_t pos = scratchpad.find("+"); pos != std::string::npos)
@@ -4457,6 +4519,19 @@ void vsid::VSIDPlugin::OnFlightPlanControllerAssignedDataUpdate(EuroScopePlugIn:
{
std::vector req = vsid::utils::split(scratchpad.substr(pos + toFind.size(), scratchpad.size()), '/');
std::string reqType = vsid::utils::tolower(req.at(0));
+ bool isRwyReq = reqType.find("rwy") != std::string::npos;
+ if (isRwyReq)
+ {
+ try
+ {
+ reqType = vsid::utils::split(reqType, ' ').at(1);
+ }
+ catch (std::out_of_range&)
+ {
+ messageHandler->writeMessage("ERROR", "[" + callsign + "] failed to split req type (" + reqType + ") in scratch pad update. Stopping setting request!");
+ return;
+ }
+ }
long long reqTime = std::stoll(req.at(1));
// clear all possible requests before setting a new one
@@ -4488,23 +4563,22 @@ void vsid::VSIDPlugin::OnFlightPlanControllerAssignedDataUpdate(EuroScopePlugIn:
}
if (it->first == reqType)
{
- messageHandler->writeMessage("DEBUG", "[" + callsign + "] setting in requests in: " +
+ messageHandler->writeMessage("DEBUG", "[" + callsign + "] (equal reqType) setting in requests in: " +
it->first, vsid::MessageHandler::DebugArea::Req);
it->second.insert({ callsign, reqTime });
- this->processed[callsign].request = reqType;
- this->processed[callsign].reqTime = reqTime;
- reqActive = true;
- }
- else if (reqType.find(it->first) != std::string::npos)
- {
- it->second.insert({ callsign, reqTime });
+
+ if (!isRwyReq)
+ {
+ this->processed[callsign].request = reqType;
+ this->processed[callsign].reqTime = reqTime;
+ reqActive = true;
+ }
}
}
for (auto& [type, rwys] : this->activeAirports[adep].rwyrequests)
{
- messageHandler->writeMessage("DEBUG", "[" + callsign + "] rwy req type : " + type, vsid::MessageHandler::DebugArea::Dev);
for (auto it = rwys.begin(); it != rwys.end(); ++it)
{
for (std::set>::iterator jt = it->second.begin(); jt != it->second.end();)
@@ -4527,21 +4601,21 @@ void vsid::VSIDPlugin::OnFlightPlanControllerAssignedDataUpdate(EuroScopePlugIn:
jt = it->second.erase(jt);
}
}
- if (type == reqType && fplnRwy != "")
+ if (type == reqType && !fplnRwy.empty())
{
messageHandler->writeMessage("DEBUG", "[" + callsign + "] setting in rwy requests in: " +
type + "/" + std::string(FlightPlan.GetFlightPlanData().GetDepartureRwy()), vsid::MessageHandler::DebugArea::Req);
rwys[fplnRwy].insert({ callsign, reqTime });
- this->processed[callsign].request = reqType;
- this->processed[callsign].reqTime = reqTime;
- reqActive = true;
- }
- else if (type.find(reqType) != std::string::npos && fplnRwy != "") // #evaluate - if still needed
- {
- rwys[fplnRwy].insert({ callsign, reqTime });
+
+ if (isRwyReq)
+ {
+ this->processed[callsign].request = "rwy " + reqType;
+ this->processed[callsign].reqTime = reqTime;
+ reqActive = true;
+ }
}
- else if (type == reqType && fplnRwy == "")
+ else if (isRwyReq && type == reqType && fplnRwy.empty())
messageHandler->writeMessage("WARNING", "[" + callsign + "] to be set in runway requests, but runway hasn't been set in the flight plan.");
}
}
@@ -4648,14 +4722,18 @@ void vsid::VSIDPlugin::OnFlightPlanControllerAssignedDataUpdate(EuroScopePlugIn:
break;
}
- for (auto& fp : this->activeAirports[adep].requests["rwy startup"])
+ for (auto& [rwy, rwyReq] : this->activeAirports[adep].rwyrequests["startup"])
{
- if (fp.first != callsign) continue;
+ for (auto& fp : rwyReq)
+ {
+ if (fp.first != callsign) continue;
- this->activeAirports[adep].requests["rwy startup"].erase(fp);
- this->processed[callsign].request = "";
- this->processed[callsign].reqTime = -1;
- break;
+ this->activeAirports[adep].rwyrequests["startup"][rwy].erase(fp);
+ this->processed[callsign].request = "";
+ this->processed[callsign].reqTime = -1;
+ break;
+ }
+
}
}
else if (state == "PUSH")
From b60f60a8c75364415d04eceb8062f0eb22f21db8 Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Thu, 26 Feb 2026 22:37:33 +0100
Subject: [PATCH 06/13] Typo
---
area.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/area.h b/area.h
index 78011fb..9cd9b32 100644
--- a/area.h
+++ b/area.h
@@ -65,7 +65,7 @@ namespace vsid
std::vector lines;
/**
- * @brief Creates a decimal position pair // #refacotr - change to utils.h version
+ * @brief Creates a decimal position pair // #refactor - change to utils.h version
*
* @param pos the fpln position as pair of lat/long coordinates
*/
From 498264385611a5c933a3ea78bfe699096c739443 Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Fri, 27 Feb 2026 09:55:56 +0100
Subject: [PATCH 07/13] Update Changelog.txt
---
Changelog.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Changelog.txt b/Changelog.txt
index 29f7120..3c68235 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -3,6 +3,8 @@
* FPLN - startup requests are now blocked if no runway is set (both "normal" startup and rwy startup)
* request system refactored - requests and rwy requests share the same type now (distinction is now stored with the flight plan)
* other smaller improvements to the request system (mainly startup request related)
+* CONF - improved checking for military SIDs (OID) to validate against the .ese file. As per previous version OIDs have to be written like found in the .ese file (there is no mastering like with normal SIDs)
+ * added a health check to warn about OIDs in the config that haven't been found in the .ese file
:lady_beetle: **Fixes**
* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this
From 4ff12791fcc757a6388de693858068013d8f2cd5 Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Fri, 27 Feb 2026 09:56:29 +0100
Subject: [PATCH 08/13] Add health check for OIDs
+ Update fpln update rwy change to changed request system
---
configparser.cpp | 1 +
vSIDPlugin.cpp | 99 +++++++++++++++++++++++++++++++++++-------------
2 files changed, 73 insertions(+), 27 deletions(-)
diff --git a/configparser.cpp b/configparser.cpp
index 4226927..475d46d 100644
--- a/configparser.cpp
+++ b/configparser.cpp
@@ -703,6 +703,7 @@ void vsid::ConfigParser::loadAirportConfig(std::map
else if (!this->isConfigValue(sidField.key()))
{
// special check for possible military SIDs / OIDs (format: XY12)
+
if (vsid::utils::lastIsDigit(sidField.key()) && vsid::utils::countDigits(sidField.key()) > 1 && sidField.key().length() > 2)
{
fieldSetting.base = sidField.key().substr(0, sidField.key().length() - 1);
diff --git a/vSIDPlugin.cpp b/vSIDPlugin.cpp
index 614d235..18d87ec 100644
--- a/vSIDPlugin.cpp
+++ b/vSIDPlugin.cpp
@@ -4297,19 +4297,22 @@ void vsid::VSIDPlugin::OnFlightPlanFlightPlanDataUpdate(EuroScopePlugIn::CFlight
// update possible rwy requests
- if (this->processed[callsign].request != "")
+ if (!this->processed[callsign].request.empty())
{
- std::string fplnRwy = fplnData.GetDepartureRwy();
+ std::string fplnRwy = vsid::fplnhelper::getAtcBlock(FlightPlan).second;
// update rwy requests directly if a rwy request is stored for the flight plan
- if (this->processed[callsign].request.find("rwy") != std::string::npos && fplnRwy != "")
+ if (this->processed[callsign].request.find("rwy") != std::string::npos &&
+ !fplnRwy.empty() && vsid::utils::contains(this->activeAirports[adep].allRwys, fplnRwy))
{
- try
+ std::string normReq = vsid::utils::split(this->processed[callsign].request, ' ').at(1);
+
+ if (this->activeAirports[adep].rwyrequests.contains(normReq))
{
bool stop = false;
- for (auto& [rwy, rwyReq] : this->activeAirports[adep].rwyrequests.at(this->processed[callsign].request))
+ for (auto& [rwy, rwyReq] : this->activeAirports[adep].rwyrequests[normReq])
{
for (std::set>::iterator it = rwyReq.begin(); it != rwyReq.end();)
{
@@ -4321,7 +4324,7 @@ void vsid::VSIDPlugin::OnFlightPlanFlightPlanDataUpdate(EuroScopePlugIn::CFlight
if (rwy != fplnRwy)
{
- this->activeAirports[adep].rwyrequests.at(this->processed[callsign].request)[fplnRwy].insert({ callsign, it->second });
+ this->activeAirports[adep].rwyrequests[normReq][fplnRwy].insert({ callsign, it->second });
rwyReq.erase(it);
stop = true;
break;
@@ -4330,15 +4333,14 @@ void vsid::VSIDPlugin::OnFlightPlanFlightPlanDataUpdate(EuroScopePlugIn::CFlight
if (stop) break;
}
}
- catch (std::out_of_range) {};
}
// check if a rwy request is available for stored non-rwy request and update the rwy
- else if(fplnRwy != "")
+ else if(!fplnRwy.empty() && vsid::utils::contains(this->activeAirports[adep].allRwys, fplnRwy))
{
bool stop = false;
for (auto& [type, rwys] : this->activeAirports[adep].rwyrequests)
{
- if (type.find(this->processed[callsign].request) == std::string::npos) continue;
+ if (this->processed[callsign].request.find(type) == std::string::npos) continue;
for (auto& [rwy, rwyReq] : rwys)
{
@@ -4352,7 +4354,7 @@ void vsid::VSIDPlugin::OnFlightPlanFlightPlanDataUpdate(EuroScopePlugIn::CFlight
if (rwy != fplnRwy)
{
- this->activeAirports[adep].rwyrequests.at(type)[fplnRwy].insert({ callsign, it->second });
+ this->activeAirports[adep].rwyrequests[type][fplnRwy].insert({ callsign, it->second });
rwyReq.erase(it);
stop = true;
break;
@@ -5143,6 +5145,13 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
this->configParser.loadAirportConfig(this->activeAirports, this->savedRules, this->savedSettings, this->savedAreas, this->savedRequests, this->savedRwyRequests);
messageHandler->writeMessage("DEBUG", "Checking .ese file for SID mastering...", vsid::MessageHandler::DebugArea::Conf);
+ //************************************
+ // temp storage for OID mismatches
+ // Parameter: > - map of OID to whether it has been matched with a section SID or not
+ //************************************
+ std::map> incompOIDs;
+
// if there are configured airports check for remaining sid data
for(auto §ionSid : this->sectionSids)
@@ -5153,7 +5162,7 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
{
if (sid.base != sectionSid.base)
{
- // skip unmatching first two char comparison (filter)
+ // skip unmatching first three char comparison (filter)
if (sid.base.length() > 2 && sectionSid.base.length() > 2)
{
if (sid.base[0] != sectionSid.base[0]) continue;
@@ -5164,6 +5173,11 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
if (!sid.collapsedBaseMatch(sectionSid.base))
{
messageHandler->writeMessage("DEBUG", "[" + sid.base + "] sid collapsed didn't match [" + sectionSid.base + "]", vsid::MessageHandler::DebugArea::Dev);
+
+ // if OID is skipped due to unmatching bases mark it has incompatible to yield warnings
+ if (vsid::utils::containsDigit(sid.base) && !incompOIDs[sectionSid.apt].contains(sid.base + sid.number + sid.designator))
+ incompOIDs[sectionSid.apt][sid.base + sid.number + sid.designator] = false;
+
continue;
}
else messageHandler->writeMessage("DEBUG", "[" + sid.base + "] sid collapsed matched [" + sectionSid.base + "]", vsid::MessageHandler::DebugArea::Dev);
@@ -5193,14 +5207,32 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
vsid::MessageHandler::DebugArea::Conf);
}
}
- else if (!sid.number.empty() && sid.number == std::string(1, sectionSid.number)) // #dev - debugging only for MIL / OIDs
- {
- messageHandler->writeMessage("DEBUG", "[" + sid.base + sid.number + sid.designator +
- "] matched with section SID [" + sectionSid.base + sectionSid.number + std::string(1, sectionSid.desig.value_or(' ')) + "]",
- vsid::MessageHandler::DebugArea::Dev);
- }
- else if (sid.number != "") // health check for possible errors in .ese config
+ else if (!sid.number.empty()) // health check for possible errors in .ese config
{
+ if (vsid::utils::containsDigit(sid.base))
+ {
+ if(!incompOIDs[sectionSid.apt].contains(sid.base + sid.number + sid.designator))
+ incompOIDs[sectionSid.apt][sid.base + sid.number + sid.designator] = false;
+
+ if (vsid::utils::trim(sid.base + sid.number + sid.designator) ==
+ vsid::utils::trim(sectionSid.base + sectionSid.number + sectionSid.desig.value_or(' ')))
+ {
+ messageHandler->writeMessage("DEBUG", "[MIL SID] " +
+ sid.base + sid.number + sid.designator + " equal: " +
+ sectionSid.base + sectionSid.number + sectionSid.desig.value_or(' '), vsid::MessageHandler::DebugArea::Conf);
+
+ incompOIDs[sectionSid.apt][sid.base + sid.number + sid.designator] = true;
+ }
+ else
+ {
+ messageHandler->writeMessage("DEBUG", "[MIL SID] " +
+ sid.base + sid.number + sid.designator + " NOT equal: " +
+ sectionSid.base + sectionSid.number + sectionSid.desig.value_or(' '), vsid::MessageHandler::DebugArea::Dev);
+ }
+
+ continue;
+ }
+
int currNumber = -1;
try
@@ -5305,18 +5337,31 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
}
}
}
+ }
+ }
- /*if (sid.designator != "")
- {
-
- }
- else
+ for (auto& [apt, oids] : incompOIDs)
+ {
+ if (oids.empty()) continue;
+
+ std::ostringstream ss;
+ ss << "[" << apt << "] Check your config file for the following OIDs that couldn't be mastered: ";
+ std::string separator = "";
+ int mismatchCount = 0;
+
+ for (auto& [oid, matched] : oids)
+ {
+ if (!matched)
{
- if (sectionSid.base != sid.base) continue;
- sid.number = 'X';
- messageHandler->writeMessage("DEBUG", "[" + sid.base + "] has no designator but the base could be mastered", vsid::MessageHandler::DebugArea::Conf);
- }*/
+ ss << separator << oid;
+ separator = ", ";
+ mismatchCount++;
+ }
}
+
+ if (mismatchCount > 0) messageHandler->writeMessage("WARNING", ss.str());
+
+ ss.clear();
}
}
From 57614bf978a207f398d8e8270b457f75369ee39a Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Fri, 27 Feb 2026 12:00:22 +0100
Subject: [PATCH 09/13] Update Changelog.txt
---
Changelog.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Changelog.txt b/Changelog.txt
index 3c68235..2ef9f54 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -9,6 +9,7 @@
:lady_beetle: **Fixes**
* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this
* FPLN - rwy request indicators shouldn't be overwritten anymore (#406)
+* CONF - military SIDs (OIDs) had to be at the end of the config due to missing reset of special OID/SID numbering
[Changelog v0.14.3.1]
>[!NOTE]
From f91396131b5b525977289fcc7f23c4b6b544c64a Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Fri, 27 Feb 2026 12:00:58 +0100
Subject: [PATCH 10/13] Text formatting
---
vSIDPlugin.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vSIDPlugin.cpp b/vSIDPlugin.cpp
index 18d87ec..e0b8b0c 100644
--- a/vSIDPlugin.cpp
+++ b/vSIDPlugin.cpp
@@ -5255,7 +5255,7 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
if (currNumber > newNumber || (currNumber == 1 && newNumber == 9))
{
- messageHandler->writeMessage("WARNING", "[" + sectionSid.apt + "] Check your .ese - file for " + sid.base + " ? " + sid.designator + " SID!Already set number : " +
+ messageHandler->writeMessage("WARNING", "[" + sectionSid.apt + "] Check your .ese - file for " + sid.base + "?" + sid.designator + " SID! Already set number : " +
std::to_string(currNumber) + " (ID: " + sid.id + "). Now found additional number: " + std::to_string(newNumber) +
" - (Runway: " + sectionSid.rwy + "). Skipping additional number (is lower or before restarting count) due to possible sectore file error!");
}
From 5fcbd34a1c4a147311fa19ddb3084f9c1bbc0926 Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Fri, 27 Feb 2026 12:01:09 +0100
Subject: [PATCH 11/13] Fix fixednumber not being reset
---
configparser.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/configparser.cpp b/configparser.cpp
index 475d46d..35e2afa 100644
--- a/configparser.cpp
+++ b/configparser.cpp
@@ -603,12 +603,12 @@ void vsid::ConfigParser::loadAirportConfig(std::map
vsid::tmpSidSettings desSetting;
vsid::tmpSidSettings idSetting;
- std::string fixedNumber = "";
-
// "field level" - iterates over restrictions and sid way points / bases
for (auto &sidField : this->parsedConfig.at(icao).at("sids").items())
{
+ std::string fixedNumber = "";
+
if (sidField.key() == "allowDiffNumbers") fieldSetting.allowDiffNumbers = this->parsedConfig.at(icao).at("sids").at(sidField.key());
else if (sidField.key() == "initial") fieldSetting.initial = this->parsedConfig.at(icao).at("sids").at(sidField.key());
else if (sidField.key() == "climbvia") fieldSetting.via = this->parsedConfig.at(icao).at("sids").at(sidField.key());
@@ -708,6 +708,9 @@ void vsid::ConfigParser::loadAirportConfig(std::map
{
fieldSetting.base = sidField.key().substr(0, sidField.key().length() - 1);
fixedNumber = sidField.key().back();
+
+ messageHandler->writeMessage("DEBUG", "[" + sidField.key() + "] contained a number - setting as fixed SID number: " +
+ fixedNumber, vsid::MessageHandler::DebugArea::Conf);
}
else
{
From f8d059fa8a2e6b248493799eb6ef2fea659950de Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Thu, 19 Mar 2026 16:44:42 +0100
Subject: [PATCH 12/13] Update Changelog.txt
---
Changelog.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Changelog.txt b/Changelog.txt
index 2ef9f54..b5743cb 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -7,9 +7,9 @@
* added a health check to warn about OIDs in the config that haven't been found in the .ese file
:lady_beetle: **Fixes**
-* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this
+* FPLN - Squawks are now also displayed if the departure airport is inactive. Only CTR controllers were affected by this (#401)
* FPLN - rwy request indicators shouldn't be overwritten anymore (#406)
-* CONF - military SIDs (OIDs) had to be at the end of the config due to missing reset of special OID/SID numbering
+* CONF - military SIDs (OIDs) had to be at the end of the config due to missing reset of special OID/SID numbering (#402)
[Changelog v0.14.3.1]
>[!NOTE]
From 837e98645d21f1ddf90a1e1888ac49a99fe4481b Mon Sep 17 00:00:00 2001
From: Phil7789 <87429599+Phil7789@users.noreply.github.com>
Date: Thu, 19 Mar 2026 16:45:16 +0100
Subject: [PATCH 13/13] Move OID base checking
---
vSIDPlugin.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/vSIDPlugin.cpp b/vSIDPlugin.cpp
index e0b8b0c..c81e508 100644
--- a/vSIDPlugin.cpp
+++ b/vSIDPlugin.cpp
@@ -5162,6 +5162,11 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
{
if (sid.base != sectionSid.base)
{
+
+ // if OID is skipped due to unmatching bases mark it has incompatible to yield warnings
+ if (vsid::utils::containsDigit(sid.base) && !incompOIDs[sectionSid.apt].contains(sid.base + sid.number + sid.designator))
+ incompOIDs[sectionSid.apt][sid.base + sid.number + sid.designator] = false;
+
// skip unmatching first three char comparison (filter)
if (sid.base.length() > 2 && sectionSid.base.length() > 2)
{
@@ -5173,11 +5178,6 @@ void vsid::VSIDPlugin::UpdateActiveAirports()
if (!sid.collapsedBaseMatch(sectionSid.base))
{
messageHandler->writeMessage("DEBUG", "[" + sid.base + "] sid collapsed didn't match [" + sectionSid.base + "]", vsid::MessageHandler::DebugArea::Dev);
-
- // if OID is skipped due to unmatching bases mark it has incompatible to yield warnings
- if (vsid::utils::containsDigit(sid.base) && !incompOIDs[sectionSid.apt].contains(sid.base + sid.number + sid.designator))
- incompOIDs[sectionSid.apt][sid.base + sid.number + sid.designator] = false;
-
continue;
}
else messageHandler->writeMessage("DEBUG", "[" + sid.base + "] sid collapsed matched [" + sectionSid.base + "]", vsid::MessageHandler::DebugArea::Dev);