/** * Handler for all oc situation data at the client * $Id: handler_oc_situation_data.cpp 57655 2022-07-20 11:38:28Z karwat $ * $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Services/OcSituationClient/handler_oc_situation_data.cpp $ * $Author: karwat $ * Created by Philipp Dassow, NLST, 01-03-2018 */ #include "handler_oc_central_aes_data.h" #include #include #include #include #include #include "central_aes_byte_reader.h" #include "main_handler.h" #include "settings.h" namespace OcSituationClient { HandlerOcCentralAesData::HandlerOcCentralAesData(const std::shared_ptr &aesDtc, const std::shared_ptr &aesFtc, const std::shared_ptr &tabocDts, QObject *parent) : QObject(parent), m_aesDtc(aesDtc), m_aesFtc(aesFtc), m_tabocDts(tabocDts), m_logger(getLogger("HandlerOcCentralAesData")) { } HandlerOcCentralAesData::~HandlerOcCentralAesData() {} bool HandlerOcCentralAesData::init() { // AES DTC enable if (!m_aesDtc->enableNContamination() || !m_aesDtc->enableBCContamination() || !m_aesDtc->enableExplosionArea() || !m_aesDtc->enableExplosionSingle() || !m_aesDtc->enableMineArea() || !m_aesDtc->enableFunctionalArea() || !m_aesDtc->enableBoobyTrap() || !m_aesDtc->enableOffRouteMine() || !m_aesDtc->enableExplosionCluster()) { ERROR_LOG(m_logger) << "Enabling AES Data-Topics failed."; return false; } // AES FTC enable if (!m_aesFtc->enableNContaminationModify() || !m_aesFtc->enableNContaminationRemove() || !m_aesFtc->enableBCContaminationModify() || !m_aesFtc->enableBCContaminationRemove() || !m_aesFtc->enableExplosionAreaModify() || !m_aesFtc->enableExplosionAreaRemove() || !m_aesFtc->enableExplosionSingleModify() || !m_aesFtc->enableExplosionSingleRemove() || !m_aesFtc->enableMineAreaModify() || !m_aesFtc->enableMineAreaRemove() || !m_aesFtc->enableFunctionalAreaModify() || !m_aesFtc->enableFunctionalAreaRemove() || !m_aesFtc->enableBoobyTrapModify() || !m_aesFtc->enableBoobyTrapRemove() || !m_aesFtc->enableOffRouteMineModify() || !m_aesFtc->enableOffRouteMineRemove() || !m_aesFtc->enableExplosionClusterOcModify() || !m_aesFtc->enableExplosionClusterRemove() || !m_aesFtc->enableMineAreaReferenceModify()) { ERROR_LOG(m_logger) << "Enabling AES Function-Topics failed."; return false; } // TABOC DTS enable if (!m_tabocDts->enableCentralAesOverload()) { ERROR_LOG(m_logger) << "Enabling TABOC Data-Topics failed."; return false; } m_aesDtc->nContaminations( [this](const AreaEffectSimulation::NContamination &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtNContamination); }); m_aesDtc->bCContaminations( [this](const AreaEffectSimulation::BCContamination &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtBCContamination); }); m_aesDtc->explosionAreas( [this](const AreaEffectSimulation::ExplosionArea &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtExplosionArea); }); m_aesDtc->explosionSingles( [this](const AreaEffectSimulation::ExplosionSingle &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtExplosionSingle); }); m_aesDtc->mineAreas( [this](const AreaEffectSimulation::MineArea &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtMineArea); }); m_aesDtc->functionalAreas( [this](const AreaEffectSimulation::FunctionalArea &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtFunctionalArea); }); m_aesDtc->boobyTraps( [this](const AreaEffectSimulation::BoobyTrap &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtBoobyTrap); }); m_aesDtc->offRouteMines( [this](const AreaEffectSimulation::OffRouteMine &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtOffRouteMine); }); m_aesDtc->explosionClusters( [this](const AreaEffectSimulation::ExplosionCluster &data) { if (!data.isCentral()) return; m_allCentralAesItems.insert(data.id(), AreaEffectSimulation::AesType::AtExplosionCluster); }); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::nContaminationChanged, this, &HandlerOcCentralAesData::onNContaminationChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::bCContaminationChanged, this, &HandlerOcCentralAesData::onBCContaminationChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionAreaChanged, this, &HandlerOcCentralAesData::onExplosionAreaChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged, this, &HandlerOcCentralAesData::onExplosionSingleChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::mineAreaChanged, this, &HandlerOcCentralAesData::onMineAreaChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::functionalAreaChanged, this, &HandlerOcCentralAesData::onFunctionalAreaChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::boobyTrapChanged, this, &HandlerOcCentralAesData::onBoobyTrapChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::offRouteMineChanged, this, &HandlerOcCentralAesData::onOffRouteMineChanged); connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionClusterChanged, this, &HandlerOcCentralAesData::onExplosionClusterChanged); DEBUG_LOG(m_logger) << "Initialisation HandlerOcCentralAesData succesful."; return true; } void HandlerOcCentralAesData::process(const QByteArray &data, bool bIsInitial) { DEBUG_LOG(m_logger) << "Starting to parse central aes data."; if (bIsInitial) { DEBUG_LOG(m_logger) << "Data is initial --> removing central aes items."; removeAllCentralAesItems(); if (!m_allCentralAesItems.isEmpty()) { QTimer::singleShot(500, this, [this, data, bIsInitial]() { process(data, bIsInitial); }); return; } } if (data.isEmpty()) { ERROR_LOG(m_logger) << "Got an empty QByteArray to decode."; return; } bool centralAesItemsOverloaded = false; LtsUtils::get1Byte(data, centralAesItemsOverloaded); TrainingAreaBaseOC::CentralAesOverload centralAesOverload; centralAesOverload.id(1); centralAesOverload.hasOverload(centralAesItemsOverloaded); m_tabocDts->publish(centralAesOverload); DEBUG_LOG(m_logger) << "Central AesItems overloaded: " << centralAesItemsOverloaded; // TODO: Further processing of overloaded info QByteArray data2 = data; data2.remove(0, 1); QByteArray uncompressed = MainHandler::tryUncompress(data2, m_bWithCompression); if (uncompressed.isEmpty()) { INFO_LOG(m_logger) << "Got an empty QByteArray after uncompression."; return; } CentralAesByteReader reader(uncompressed); TRACE_LOG(m_logger) << "Uncompressed Data: " << uncompressed.toHex(' '); size_t pos = 0; AreaEffectSimulation::AesType aesType; OcSituation::CentralAesChangeType changeType; while (pos < static_cast(uncompressed.size())) { if (!reader.getCentralAesChangeType(pos, changeType)) { FATAL_LOG(m_logger) << "Coul not read CentralAesChangeType --> aborting."; return; } DEBUG_LOG(m_logger) << "Got AesChangeType " << changeType; switch (changeType) { case OcSituation::AddMod: if (!reader.getAesType(pos, aesType)) { FATAL_LOG(m_logger) << "Coul not read AesType --> aborting."; return; } DEBUG_LOG(m_logger) << "Got AesType " << aesType; switch (aesType.underlying()) { case AreaEffectSimulation::AesType::AtUnknown: case AreaEffectSimulation::AesType::AtDangerArea: case AreaEffectSimulation::AesType::AtMineCorridor: case AreaEffectSimulation::AesType::AtBorderline: case AreaEffectSimulation::AesType::AtTechnicalArea: case AreaEffectSimulation::AesType::AtExplosionSingleCentral: case AreaEffectSimulation::AesType::AtReconArea: case AreaEffectSimulation::AesType::AtDusSingleMine: case AreaEffectSimulation::AesType::AtExplosionAreaSingleExplosions: case AreaEffectSimulation::AesType::AtMineAreaSingleMines: case AreaEffectSimulation::AesType::AtGasPipe: case AreaEffectSimulation::AesType::AtAirSupportImpact: case AreaEffectSimulation::AesType::AtExplosionSingleCentralTrajectory: case AreaEffectSimulation::AesType::AtBoobyTrapSecondary: case AreaEffectSimulation::AesType::AtOffRouteMineSecondary: FATAL_LOG(m_logger) << "Got false AesType: " << aesType.underlying() << " --> aborting."; return; case AreaEffectSimulation::AesType::AtNContamination: { AreaEffectSimulation::NContaminationModifyRequest nContamination; if (!reader.getNContamination(pos, nContamination)) { FATAL_LOG(m_logger) << "Could not read NContamination --> aborting."; return; } else DEBUG_LOG(m_logger) << "NContamination added/modified."; checkId(nContamination); m_aesFtc->nContaminationModifyRequest(nContamination, this); break; } case AreaEffectSimulation::AesType::AtBCContamination: { AreaEffectSimulation::BCContaminationModifyRequest bCContamination; if (!reader.getBCContamination(pos, bCContamination)) { FATAL_LOG(m_logger) << "Could not read BCContamination --> aborting."; return; } else DEBUG_LOG(m_logger) << "BCContamination added/modified."; checkId(bCContamination); m_aesFtc->bCContaminationModifyRequest(bCContamination, this); break; } case AreaEffectSimulation::AesType::AtExplosionArea: { AreaEffectSimulation::ExplosionAreaModifyRequest explosionArea; if (!reader.getExplosionArea(pos, explosionArea)) { FATAL_LOG(m_logger) << "Could not read ExplosionArea --> aborting."; return; } else DEBUG_LOG(m_logger) << "ExplosionArea added/modified."; checkId(explosionArea); m_aesFtc->explosionAreaModifyRequest(explosionArea, this); break; } case AreaEffectSimulation::AesType::AtExplosionSingle: { AreaEffectSimulation::ExplosionSingleModifyRequest explosionSingle; if (!reader.getExplosionSingle(pos, explosionSingle)) { FATAL_LOG(m_logger) << "Could not read ExplosionSingle --> aborting."; return; } else DEBUG_LOG(m_logger) << "ExplosionSingle added/modified."; checkId(explosionSingle); m_aesFtc->explosionSingleModifyRequest(explosionSingle, this); break; } case AreaEffectSimulation::AesType::AtMineArea: { AreaEffectSimulation::MineAreaModifyRequest mineArea; if (!reader.getMineArea(pos, mineArea)) { FATAL_LOG(m_logger) << "Could not read MineArea --> aborting."; return; } else DEBUG_LOG(m_logger) << "MineArea added/modified."; mineArea.distance() = 0.5; checkId(mineArea); m_aesFtc->mineAreaModifyRequest(mineArea, this); break; } case AreaEffectSimulation::AesType::AtFunctionalArea: { AreaEffectSimulation::FunctionalAreaModifyRequest functionalArea; if (!reader.getFunctionalArea(pos, functionalArea)) { FATAL_LOG(m_logger) << "Could not read FunctionalArea --> aborting."; return; } else DEBUG_LOG(m_logger) << "FunctionalArea added/modified."; checkId(functionalArea); m_aesFtc->functionalAreaModifyRequest(functionalArea, this); break; } case AreaEffectSimulation::AesType::AtBoobyTrap: { AreaEffectSimulation::BoobyTrapModifyRequest boobyTrap; if (!reader.getBoobyTrap(pos, boobyTrap)) { FATAL_LOG(m_logger) << "Could not read BoobyTrap --> aborting."; return; } else DEBUG_LOG(m_logger) << "BoobyTrap added/modified."; checkId(boobyTrap); m_aesFtc->boobyTrapModifyRequest(boobyTrap, this); break; } case AreaEffectSimulation::AesType::AtOffRouteMine: { AreaEffectSimulation::OffRouteMineModifyRequest offRouteMine; if (!reader.getOffRouteMine(pos, offRouteMine)) { FATAL_LOG(m_logger) << "Could not read OffRouteMine --> aborting."; return; } else DEBUG_LOG(m_logger) << "OffRouteMine added/modified."; checkId(offRouteMine); m_aesFtc->offRouteMineModifyRequest(offRouteMine, this); break; } case AreaEffectSimulation::AesType::AtExplosionCluster: { AreaEffectSimulation::ExplosionClusterOcModifyRequest explosionCluster; if (!reader.getExplosionCluster(pos, explosionCluster)) { FATAL_LOG(m_logger) << "Could not read ExplosionCluster --> aborting."; return; } else DEBUG_LOG(m_logger) << "ExplosionCluster added/modified."; checkId(explosionCluster); m_aesFtc->explosionClusterOcModifyRequest(explosionCluster, this); break; } default: break; } break; case OcSituation::Remove: { CentralAesByteReader::RemoveMessage removeMessage; if (!reader.getRemoveMessage(pos, removeMessage)) { FATAL_LOG(m_logger) << "Could not read RemoveMessage --> aborting."; return; } if (!m_allCentralAesItems.contains(removeMessage.aesItemId)) { INFO_LOG(m_logger) << "Got remove message for unknown aesItemId " << removeMessage.aesItemId; break; } DEBUG_LOG(m_logger) << "Sending remove request: aesItemId = " << removeMessage.aesItemId << " ,aesType = " << removeMessage.aesType; tryRemoveAesItem(removeMessage.aesItemId, removeMessage.aesType); break; } } } DEBUG_LOG(m_logger) << "All central aes data parsed."; } void HandlerOcCentralAesData::removeAllCentralAesItems() { using namespace AreaEffectSimulation; for (auto it = m_allCentralAesItems.constBegin(); it != m_allCentralAesItems.constEnd(); ++it) tryRemoveAesItem(it.key(), it.value()); } void HandlerOcCentralAesData::onNContaminationChanged(const AreaEffectSimulation::NContamination &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtNContamination); } void HandlerOcCentralAesData::onBCContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtBCContamination); } void HandlerOcCentralAesData::onExplosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtExplosionArea); } void HandlerOcCentralAesData::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtExplosionSingle); } void HandlerOcCentralAesData::onMineAreaChanged(const AreaEffectSimulation::MineArea &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtMineArea); } void HandlerOcCentralAesData::onFunctionalAreaChanged(const AreaEffectSimulation::FunctionalArea &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtFunctionalArea); } void HandlerOcCentralAesData::onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtBoobyTrap); } void HandlerOcCentralAesData::onOffRouteMineChanged(const AreaEffectSimulation::OffRouteMine &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtOffRouteMine); } void HandlerOcCentralAesData::onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, DataModification modType) { onAesItemChanged(data, modType, AreaEffectSimulation::AesType::AtExplosionCluster); } void HandlerOcCentralAesData::tryRemoveAesItem(qint32 aesItemId, AreaEffectSimulation::AesType aesType) { using namespace AreaEffectSimulation; switch (aesType.underlying()) { case AesType::AtUnknown: case AesType::AtDangerArea: case AesType::AtMineCorridor: case AesType::AtBorderline: case AesType::AtTechnicalArea: case AesType::AtExplosionSingleCentral: case AesType::AtReconArea: case AesType::AtDusSingleMine: case AesType::AtExplosionAreaSingleExplosions: case AesType::AtMineAreaSingleMines: case AesType::AtGasPipe: case AesType::AtAirSupportImpact: case AesType::AtExplosionSingleCentralTrajectory: case AesType::AtBoobyTrapSecondary: case AesType::AtOffRouteMineSecondary: WARNING_LOG(m_logger) << "Got false AesType: " << aesType.underlying() << " --> aborting."; break; case AesType::AtNContamination: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::nContaminationRemoveRequest); break; case AesType::AtBCContamination: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::bCContaminationRemoveRequest); break; case AesType::AtExplosionArea: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::explosionAreaRemoveRequest); break; case AesType::AtExplosionSingle: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::explosionSingleRemoveRequest); break; case AesType::AtMineArea: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::mineAreaRemoveRequest); break; case AesType::AtFunctionalArea: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::functionalAreaRemoveRequest); break; case AesType::AtBoobyTrap: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::boobyTrapRemoveRequest); break; case AesType::AtOffRouteMine: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::offRouteMineRemoveRequest); break; case AesType::AtExplosionCluster: removeAesItem(aesItemId, &AreaEffectSimulation::Interface::Ftc::explosionClusterRemoveRequest); break; default: break; } } void HandlerOcCentralAesData::onOffRouteMineModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onBoobyTrapModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onFunctionalAreaModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onMineAreaModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onExplosionSingleModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onExplosionAreaModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onBCContaminationModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onNContaminationModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onExplosionClusterOcModifyReply(const Core::FunctionReplyObject &reply) { onReply(reply); } void HandlerOcCentralAesData::onReply(const Core::FunctionReplyObject &reply) const { if (reply.error()) ERROR_LOG(m_logger) << reply.str(); } template void HandlerOcCentralAesData::onAesItemChanged(const T &aesItem, DataModification modType, AreaEffectSimulation::AesType aesType) { if (!aesItem.isCentral()) return; switch (modType) { case DataModification::eAdded: m_allCentralAesItems[aesItem.id()] = aesType; DEBUG_LOG(m_logger) << "Added new AES Item: id=" << aesItem.id() << ", type=" << aesType; break; case DataModification::eRemoved: m_allCentralAesItems.remove(aesItem.id()); DEBUG_LOG(m_logger) << "Removed AES Item with id=" << aesItem.id(); break; case DataModification::eModified: default: break; } } template void HandlerOcCentralAesData::checkId(T &aesItem) const { if (!m_allCentralAesItems.contains(aesItem.id())) aesItem.id(aesItem.id() * -1); } void HandlerOcCentralAesData::removeAesItem( qint32 aesItemId, int64_t (AreaEffectSimulation::Interface::Ftc::*removeFunction)(const Core::RemoveElementRequest &, const std::function &)) { (*m_aesFtc.get().*removeFunction)(Core::RemoveElementRequest(aesItemId * -1), [this](const Core::FunctionReplyObject &replyObject) { if (replyObject.error()) ERROR_LOG(m_logger) << replyObject.str(); }); } } // namespace OcSituationClient