Files
qt5-legatus-legacy/Lts/Proxies/Buildings/building_control_handler.cpp
T
2026-08-13 18:33:10 +02:00

386 lines
16 KiB
C++
Executable File
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