Files
qt-migration-legatus/qt5-before/dlbo/Lts/Proxies/Buildings/building_control_handler.cpp
T
torstenandCopilot 7173785915 Qt6 Migration: Complete migration with DDS/RTI support and build validation
Major Changes:
- Merged latest Qt5 devel content from dlbo (292 files changed, 7 new dirs)
- Consolidated forward-declarations and include folders
- Removed unneeded modules per Niklas' repo check list

Build System Fixes:
- Fixed CMake VERSION_GREATER syntax in ParticipantManagement/CMakeLists.txt
- Added VLC packages (libvlc-dev, vlc-plugin-base) to docker_build.sh
- Added PostgreSQL dev packages (libpq-dev, postgresql-server-dev-all) to Dockerfile
- Fixed locale warnings (ANSI_X3.4-1968 → C.UTF-8)
- Fixed ArcGIS SDK path warnings when BUILD_ARCGIS=OFF

Code Generation Fixes:
- Fixed IDL enum collisions (PortType→CorePortType/DdsutPortType, PdmEventType)
- Fixed Grantlee template svc_translation.cpp.grantlee:
  - Changed {{ idl_enum.name }}_def:: to {{ idl_enum.name }}::
  - Fixed .underlying() calls for C++11 scoped enums (enum class)
- Removed generated files from repo (moc_*, *_dtc.h, *_ftc.h)

Validation:
- BUILD_RTI=ON: SUCCESS
- BUILD_RTI=OFF: SUCCESS
- C++17 standard maintained for RTI 7.7 compatibility
- Ubuntu 26.04 Docker environment verified

Remaining Warnings (expected):
- BgViewer, KDChart, KDReports, Poppler-Qt6 not found (optional features)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-15 18:20:26 +00:00

386 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Handle the single building instances
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-02-06
*/
#include "building_control_handler.h"
#include "building_process.h"
#include "main_handler.h"
#include <QCoreApplication>
#include <QStandardPaths>
#include <QDateTime>
#include <ngldb/nsqlquery.h>
#include <Buildings/bld_record_replay_plugin.h>
#include <AssetManagement/asm.hpp>
namespace Buildings
{
BuildingControlHandler::BuildingControlHandler(MainHandler *mainHandler)
: QObject()
, Interface::Fts::SetBuildingStatesRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::SetBuildingContaminationStateRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::SetFortifyFactorRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::SendCesHitOnBuildingRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::SendCesHit3DonBuildingRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::TriggerBsmFlashRequestHandler(mainHandler->ddsHandler()->fts())
, Interface::Fts::SwitchRelayRequestHandler(mainHandler->ddsHandler()->fts())
, m_mainHandler(mainHandler)
, m_logger(getLogger("BuildingControlHandler"))
{}
BuildingControlHandler::~BuildingControlHandler()
{
for (BuildingProcess *bldg : qAsConst(m_buildings))
{
bldg->shutdown();
delete bldg;
}
m_buildings.clear();
}
bool BuildingControlHandler::init()
{
DEBUG_LOG(m_logger)<<"BuildingControlHandler::init exerciseId="<<m_mainHandler->exerciseId();
const QString bcuName = QStringLiteral("BuildingControlUnit");
m_bcuExecutableName = QStandardPaths::findExecutable(bcuName, { QCoreApplication::applicationDirPath()});
if (m_bcuExecutableName.isEmpty())
{
WARNING_LOG(m_logger) << "Executable " << bcuName << " not found - can not start building control unit processes!";
return false;
}
if (m_mainHandler->exerciseId() > 0)
{
// Initialize RecordReplay to get initial participantPosition
RecordReplayPlugin recordReplay;
// no ddsconnector - we don't want to publish data here
recordReplay.initDtc(nullptr, m_mainHandler->exerciseId());
NSqlQuery q(m_mainHandler->db()->database());
recordReplay.readHistoryStateAt(q, QDateTime::currentMSecsSinceEpoch());
// key is sampleTime -> multiMap
const QMultiMap<qint64, Buildings::HistoryState> latestStates = recordReplay.getHistoryStateMap();
DEBUG_LOG(m_logger) << "Starting to read HistoryStatedata from record replay. Size: "
<< latestStates.size();
for (auto it = latestStates.begin(); it != latestStates.end(); ++it)
{
const Buildings::HistoryState &historyState = it.value();
if (!m_mainHandler->ismHandler()->isElementAssignedToExercise(historyState.mseId(),m_mainHandler->exerciseId() ))
{
DEBUG_LOG(m_logger)<<"[INIT] [recordReplay]>>>>>>> mseId=" << historyState.mseId() << " not in execise";
continue;
}
m_historyStates.insert(historyState.mseId(), historyState);
DEBUG_LOG(m_logger)<<"[INIT] [recordReplay]>>>>>>> "<<historyState;
}
}
return true;
}
void BuildingControlHandler::onBuildingRemoved(int buildingId)
{
auto it = m_buildings.find(buildingId);
if (it == m_buildings.end())
return;
BuildingProcess *bldg = it.value();
bldg->shutdown();
bldg->deleteLater();
m_buildings.erase(it);
m_historyStates.remove(buildingId);
}
void BuildingControlHandler::onBuildingChanged(const BuildingInfo &buildingInfo, bool damageInit = false)
{
DEBUG_LOG(m_logger) << "onBuildingChanged damageInit=" << damageInit
<< " mseId=" << buildingInfo.mseId;
auto it = m_buildings.find(buildingInfo.mseId);
BuildingProcess *bldg = nullptr;
if (it == m_buildings.end())
{
bldg = new BuildingProcess(m_mainHandler,
m_bcuExecutableName,
buildingInfo,
damageInit,
this);
DEBUG_LOG(m_logger) << "onBuildingChanged m_buildings.insert mseId=" << buildingInfo.mseId;
m_buildings.insert(buildingInfo.mseId, bldg);
bldg->newRelayInfos(m_relayInfos);
bldg->start();
}
else
{
bldg = it.value();
bldg->setBuildingInfo(buildingInfo);
bldg->newRelayInfos(m_relayInfos);
}
Buildings::HistoryState historyState;
if ( m_historyStates.contains(buildingInfo.mseId))
{
historyState = m_historyStates.value(buildingInfo.mseId);
DEBUG_LOG(m_logger) << "onBuildingChanged setHistoryState contains historyState.mseId=" << historyState.mseId()
<< " buildingInfo.mseId=" << buildingInfo.mseId;
}
else
{
historyState.mseId (buildingInfo.mseId);
DEBUG_LOG(m_logger) << "onBuildingChanged setHistoryState insert historyState.mseId=" << historyState.mseId()
<< " buildingInfo.mseId=" << buildingInfo.mseId;
m_historyStates.insert(historyState.mseId(), historyState);
}
DEBUG_LOG(m_logger) << "onBuildingChanged setHistoryState historyState.mseId=" << historyState.mseId()
<< " buildingInfo.mseId=" << buildingInfo.mseId;
bldg->setHistoryState(m_historyStates.value(buildingInfo.mseId));
}
void BuildingControlHandler::onSetBuildingContaminationStateRequest(const rti::core::SampleIdentity &cookie,
const SetBuildingContaminationStateRequest &request)
{
DEBUG_LOG(m_logger) << "onSetBuildingContaminationStateRequest " << request;
const Core::FunctionReplyObject fro = onSetBuildingContaminationStateRequestInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->setBuildingContaminationStateReply(cookie, fro);
}
void BuildingControlHandler::onSetBuildingStatesRequest(const rti::core::SampleIdentity &cookie,
const SetBuildingStatesRequest &request)
{
DEBUG_LOG(m_logger) << "onSetBuildingStatesRequest " << request;
const Core::FunctionReplyObject fro = onSetBuildingStatesRequestInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->setBuildingStatesReply(cookie, fro);
}
void BuildingControlHandler::onSetFortifyFactorRequest(const rti::core::SampleIdentity &cookie,
const SetFortifyFactorRequest &request)
{
DEBUG_LOG(m_logger) << "onSetFortifyFactorRequest " << request;
const Core::FunctionReplyObject fro = onSetFortifyFactorRequestInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->setFortifyFactorReply(cookie, fro);
}
void BuildingControlHandler::onSendCesHitOnBuildingRequest(const rti::core::SampleIdentity &cookie,
const SendCesHitOnBuildingRequest &request)
{
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingRequest " << request;
const Core::FunctionReplyObject fro = onSendCesHitOnBuildingRequestInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->sendCesHitOnBuildingReply(cookie, fro);
}
void BuildingControlHandler::onSendCesHit3DonBuildingRequest(const rti::core::SampleIdentity &cookie, const SendCesHit3DonBuildingRequest &request)
{
DEBUG_LOG(m_logger) << "onSendCesHit3DonBuildingRequest " << request;
const Core::FunctionReplyObject fro = onSendCesHit3DonBuildingRequestInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->sendCesHit3DonBuildingReply(cookie, fro);
}
void BuildingControlHandler::onTriggerBsmFlashRequest(const rti::core::SampleIdentity &cookie,
const TriggerBsmFlashRequest &request)
{
DEBUG_LOG(m_logger) << "onTriggerBsmFlashRequest " << request;
const Core::FunctionReplyObject fro = onTriggerBsmFlashInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->triggerBsmFlashReply(cookie, fro);
}
Core::FunctionReplyObject BuildingControlHandler::onSetBuildingContaminationStateRequestInternal(const SetBuildingContaminationStateRequest &data)
{
const auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
BuildingProcess *bldg = it.value();
if (!bldg->setContaminationState(data.buildingId(), data.contaminationState()))
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not send contamination state to building control process."));
return Core::FunctionReplyObject();
}
Core::FunctionReplyObject BuildingControlHandler::onSetBuildingStatesRequestInternal(const SetBuildingStatesRequest &data)
{
std::vector<int> roomIds; // prefer std::vector here since building.roomIds() has also std::vector, so it´s easier
for (const auto &building : data.buildings())
{
const auto it = m_buildings.find(building.buildingId());
if (it == m_buildings.end())
return Core::FunctionReplyObject(building.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(building.buildingId());
BuildingProcess *bldg = it.value();
if (data.resetContamination().is_set())
{
if (data.resetContamination().get() && !bldg->resetContaminationState())
return Core::FunctionReplyObject(building.buildingId(), tr_lts("dds", "reset contamination of building with id %1 failed.")).arg(building.buildingId());
}
if (data.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::NoChange)
continue;
if (data.vulnerabilityState() != ProjectDataManagement::VulnerabilityState::CatastrophicKill &&
data.vulnerabilityState() != ProjectDataManagement::VulnerabilityState::CombatReady )
return Core::FunctionReplyObject(building.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(building.buildingId());
if (building.roomIds().is_set())
roomIds = building.roomIds().get();
if (!bldg->setVulnerabilityState(data.vulnerabilityState(), roomIds))
return Core::FunctionReplyObject(building.buildingId(), tr_lts("dds", "Can not send vulnerability state to building control process."));
}
return Core::FunctionReplyObject();
}
Core::FunctionReplyObject BuildingControlHandler::onSetFortifyFactorRequestInternal(const SetFortifyFactorRequest &data)
{
auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
BuildingProcess *bldg = it.value();
if (!bldg->setFortifyFactors(data.fortifyFactors()))
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not send fortify factors to building control process."));
return Core::FunctionReplyObject();
}
void BuildingControlHandler::setEffectStates(const int buildingId, const int assetId, const QByteArray &properties)
{
DEBUG_LOG(m_logger) << "BuildingControlHandler::setEffectStates"
<< " buildingId=" << buildingId
<< " assetId=" << assetId
<< " properties=" << properties;
auto it = m_buildings.find(buildingId);
if (it == m_buildings.end())
return;
BuildingProcess *bldg = it.value();
if (bldg)
bldg->setEffectStates( assetId, properties);
}
void BuildingControlHandler::onRelayInfoChanged(const AssetManagement::RelayInfo &info, const DataModification mod)
{
if (mod != DataModification::eRemoved)
m_relayInfos.insert(info.id(), info);
else
m_relayInfos.remove(info.id());
for(auto *bldg : qAsConst(m_buildings))
bldg->newRelayInfos(m_relayInfos);
}
Core::FunctionReplyObject BuildingControlHandler::onSendCesHitOnBuildingRequestInternal(const SendCesHitOnBuildingRequest &data)
{
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingRequestInternal";
auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
{
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingRequestInternal return";
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
}
BuildingProcess *bldg = it.value();
if (!bldg->sendCesHitOnBuilding(data.effectTime(), data.chargeTypeId(), data.destructiveFactor(), data.penetrationFactor(),
data.aesId(), data.impactPosition(),
QString::fromStdString(data.properties())))
{
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingRequestInternal return Can not send ces hit to building control process";
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not send ces hit to building control process."));
}
DEBUG_LOG(m_logger) << "FunctionReplyObject";
return Core::FunctionReplyObject();
}
Core::FunctionReplyObject BuildingControlHandler::onSendCesHit3DonBuildingRequestInternal(const SendCesHit3DonBuildingRequest &data)
{
DEBUG_LOG(m_logger) << "onSendCesHit3DonBuildingRequestInternal";
auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
{
DEBUG_LOG(m_logger) << "onSendCesHit3DonBuildingRequestInternal return";
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
}
BuildingProcess *bldg = it.value();
if (!bldg->sendCesHit3DonBuilding(data.effectTime(), data.chargeTypeId(), data.destructiveFactor(), data.penetrationFactor(),
data.aesId(), data.impactPosition(), data.detonationLocation(), data.detonationDistance(),
QString::fromStdString(data.properties())))
{
DEBUG_LOG(m_logger) << "onSendCesHit3DonBuildingRequestInternal return Can not send ces hit to building control process";
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not send ces hit to building control process."));
}
DEBUG_LOG(m_logger) << "FunctionReplyObject";
return Core::FunctionReplyObject();
}
Core::FunctionReplyObject BuildingControlHandler::onTriggerBsmFlashInternal(const TriggerBsmFlashRequest &data)
{
DEBUG_LOG(m_logger) << "onTriggerBsmFlashInternal";
{
auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
BuildingProcess *bldg = it.value();
BuildingInfo buildingInfo= bldg->buildingInfo();
BsmInfo bsmInfo = buildingInfo.bsms.value(data.assetId());
DEBUG_LOG(m_logger) << " BuildingId=" << data.buildingId()
<< " assetId=" << bsmInfo.assetId
<< " hostname=" << bsmInfo.hostname;
if (!bldg->triggerFlashlight(data))
{
DEBUG_LOG(m_logger) << "onTriggerBsmFlashInternal return Can not send trigger flashlight to building control process";
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not send trigger flashlight to building control process"));
}
}
DEBUG_LOG(m_logger) << "FunctionReplyObject";
return Core::FunctionReplyObject();
}
void BuildingControlHandler::onSwitchRelayRequest(const rti::core::SampleIdentity &cookie,
const SwitchRelayRequest &request)
{
DEBUG_LOG(m_logger) << "SwitchRelayRequest " << request;
// Request als Json-Telegramm an den entsprechenden Gebaeudeprozess wer websocket weiterleiten.
const Core::FunctionReplyObject fro = onSwitchRelayInternal(request);
if (fro.error())
WARNING_LOG(m_logger) << fro();
m_mainHandler->ddsHandler()->fts()->switchRelayReply(cookie, fro);
}
Core::FunctionReplyObject BuildingControlHandler::onSwitchRelayInternal(const SwitchRelayRequest &data)
{
DEBUG_LOG(m_logger) << "onSwitchRelayInternal " << data;
auto it = m_buildings.find(data.buildingId());
if (it == m_buildings.end())
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Building with id %1 not found.")).arg(data.buildingId());
BuildingProcess *bldg = it.value();
if (!bldg->switchRelay(data))
return Core::FunctionReplyObject(data.buildingId(), tr_lts("dds", "Can not set relay to building control process."));
return Core::FunctionReplyObject();
}
} // namespace Buildings