/** * Aes Handler for TetraRadioProxy * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-07-12 */ #pragma once #include #include #include #include #include #include #include #include #include "pdm_handler.h" #include "tab_db.h" #include "logger.h" #include "send_to_tab.h" #include "training_area_telegrams.h" namespace TrainingAreaBase { class DatabaseInterface; class MainHandler; class PositionHandler; class SendCesHitRequest; class AesStateHandler { public: explicit AesStateHandler(MainHandler *mainHandler); bool init(); int createAesTetraId(int aesDdsId, bool &alreadyExists); int getAesTetraId(int aesDdsId) const { return m_ddsId2TetraId.value(aesDdsId); } int getAesDdsId(int aesTetraId) const { return m_tetraId2ddsId.value(aesTetraId); } // we assume, that aesDdsId and aesTetraId are correct bool update(int aesDdsId, int aesTetraId, bool bSentToTetra); bool isAlreadySentToTetra(int aesDdsId) const { return m_aesInTetraAvailable.contains(aesDdsId); } private: // must be in sync ... QMap m_tetraId2ddsId; QMap m_ddsId2TetraId; QSet m_aesInTetraAvailable; std::shared_ptr m_dbInterface; int m_exerciseId; LOGGER_T m_logger; }; /** * Listen on Aes Topics and create appropriate Tetra-Telegrams (current XDR-Telegrams) * Make sure to assign a proper id and only publish aes which needs to go to tetra */ class RecvFromDdsAes : public QObject { Q_OBJECT public: RecvFromDdsAes(MainHandler *mainHandler, const std::shared_ptr &txCallback, QObject *parent = nullptr); ~RecvFromDdsAes(); bool init(); std::shared_ptr aesStateHandler() const { return m_aesStateHandler; } int ddsIdFromTetraId(int aesTetraId) const { return m_aesStateHandler->getAesDdsId(aesTetraId); } int tetraIdFromDdsId(int aesId) const { return m_aesStateHandler->getAesTetraId(aesId); } int aesChargeId(int aesId) const; TetraIcd::AreaEffectSimulationType aesTypeFromId(int aesId) const; bool sendSingleFireSMArt(const SendCesHitRequest &request); const QVector sentAesTelegrams() const { return m_sentAesTelegrams; } void resetAllDusMines(); // [GUEZE-3469] Funktionsraum dekontaminiert faelschlicherweise: std::shared_ptr dtcAes() const { return m_dtcAes;} ///< Pointer to DTC AreaEffectSimulation interface object private: template void handleEffectSimulation(const T &data, DataModification modType, TetraIcd::AreaEffectSimulationType aesType); /*! *\details Save all central area effect siumulations ยด, dont send to tetra, needed for CesHitRequest */ template void fillCentralChangesTable(const T &data); template void handleSendToTetra(const T &data, TetraIcd::AreaEffectSimulationType aesType); void onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType); void onBcContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType); void onExplosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, DataModification modType); void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType); void onMineAreaChanged(const AreaEffectSimulation::MineArea &data, DataModification modType); void onNContaminationChanged(const AreaEffectSimulation::NContamination &data, DataModification modType); void onFunctionalAreaChanged(const AreaEffectSimulation::FunctionalArea &data, DataModification modType); void onTechnicalAreaChanged(const AreaEffectSimulation::TechnicalArea &data, DataModification modType); void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType); void onDusMineStateChanged(const AreaEffectSimulation::DusMineState &data, DataModification modType); void onDusSingleMineChanged(const AreaEffectSimulation::DusSingleMine &data, DataModification modType); void onGasPipeChanged(const AreaEffectSimulation::GasPipe &data, DataModification modType); void onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType); void onOffRouteMineChanged(const AreaEffectSimulation::OffRouteMine &data, DataModification modType); void onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, DataModification modType); void onEffectsChanged(const AreaEffectSimulation::Effects &data, DataModification modType); void sendCreateEffectSimulation(const AreaEffectSimulation::AirSupportImpact &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::BCContamination &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::ExplosionArea &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::ExplosionCluster &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::ExplosionSingle &aes, int aesTetraId, int equipmentNumber = 0); void sendCreateEffectSimulation(const AreaEffectSimulation::MineArea &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::NContamination &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::FunctionalArea &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::TechnicalArea &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::DusSingleMine &aes, int aesTetraId); void sendCreateEffectSimulation(const AreaEffectSimulation::GasPipe &aes, int aesTetraId); void sendModifyEffectSimulationName(TetraIcd::AreaEffectSimulationType aesType, int aesTetraId, const std::string &name, int aesId); void sendRemoveEffectSimulation(TetraIcd::AreaEffectSimulationType aesType, int aesDdsId); void sendPauseEffectSimulation(int aesDdsId); template void sendResumeEffectSimulation(const T &) { static_assert(std::is_base_of::value, "Given type for sendResumeEffectSimulation is not an aes item!"); } // If you to do anything special for type X in dataChanged, do it here void doSpecialization(const AreaEffectSimulation::ExplosionArea &data, std::unordered_map &cont) { cont[data.id()].remainExplosionNumber(data.remainExplosionNumber()); } template void doSpecialization(const T &data, std::unordered_map &cont) { Q_UNUSED(data); Q_UNUSED(cont); } template bool dataChanged(const T &data, std::unordered_map &cont, bool &onlyNameChanged) { onlyNameChanged = false; auto it = cont.find(data.id()); T dataTmp(data); dataTmp.sampleTime(0); if (it == cont.end()) { cont.emplace(std::make_pair(data.id(), std::move(dataTmp))); DEBUG_LOG(m_logger) << "new AES Item: " << data; return true; } // do not check AES state, it is handled beforehand it->second.effectStateId(data.effectStateId()); // for Explosion Area we have to always save the remainExplosionNumber value doSpecialization(data, cont); if (it->second == dataTmp) { DEBUG_LOG(m_logger) << "nothing changed for AES Item: " << data; return false; } // check if only name changed T tmp(it->second); tmp.name(data.name()); tmp.sampleTime(data.sampleTime()); // sample time always 0 for objects in map onlyNameChanged = (tmp == data); std::swap(it->second, dataTmp); // with sampleTime = 0 DEBUG_LOG(m_logger) << "changed AES Item: " << data; return true; } bool dataChanged(const AreaEffectSimulation::AirSupportImpact ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentAirSupportImpacts, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::BCContamination ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentBCContaminations, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::ExplosionArea ¤t, bool &onlyNameChanged) { AreaEffectSimulation::ExplosionArea copy(current); // Todo: Something else to set? copy.remainExplosionNumber(0); return dataChanged(copy, m_currentExplosionArea, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::ExplosionCluster ¤t, bool &onlyNameChanged) { AreaEffectSimulation::ExplosionCluster copy(current); // Todo: Something else to set? copy.remainExplosionNumber(0); return dataChanged(copy, m_currentExplosionCluster, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::ExplosionSingle ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentExplosionSingle, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::MineArea ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentMineArea, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::NContamination ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentNContamination, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::FunctionalArea ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentFunctionalArea, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::TechnicalArea ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentTechnicalArea, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::DusSingleMine ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentDusSingleMine, onlyNameChanged); } bool dataChanged(const AreaEffectSimulation::GasPipe ¤t, bool &onlyNameChanged) { return dataChanged(current, m_currentGasPipes, onlyNameChanged); } /*! * \brief dataChanged * \param current * \details BoobyTrap is complete central, not going to tetra, the bool is just used as a placeholder * \return */ bool dataChanged(const AreaEffectSimulation::BoobyTrap ¤t) { bool placeholder; Q_UNUSED(placeholder); return dataChanged(current, m_currentBoobyTraps, placeholder); } /*! * \brief dataChanged * \param current * \details OffRouteMine is complete central, not going to tetra, the bool is just used as a placeholder * \return */ bool dataChanged(const AreaEffectSimulation::OffRouteMine ¤t) { bool placeholder; Q_UNUSED(placeholder); return dataChanged(current, m_currentOffRouteMines, placeholder); } template void resetStartTime(int aesDdsId, T &cont) { auto it = cont.find(aesDdsId); if (it == cont.end()) return; it->second.effectStart(0); } void resetStartTime(const AreaEffectSimulation::AirSupportImpact ¤t) { resetStartTime(current.id(), m_currentBCContaminations); } void resetStartTime(const AreaEffectSimulation::BCContamination ¤t) { resetStartTime(current.id(), m_currentBCContaminations); } void resetStartTime(const AreaEffectSimulation::ExplosionArea ¤t) { resetStartTime(current.id(), m_currentExplosionArea); } void resetStartTime(const AreaEffectSimulation::ExplosionCluster ¤t) { resetStartTime(current.id(), m_currentExplosionCluster); } void resetStartTime(const AreaEffectSimulation::ExplosionSingle ¤t) { resetStartTime(current.id(), m_currentExplosionSingle); } void resetStartTime(const AreaEffectSimulation::MineArea ¤t) { resetStartTime(current.id(), m_currentMineArea); } void resetStartTime(const AreaEffectSimulation::NContamination ¤t) { resetStartTime(current.id(), m_currentNContamination); } void resetStartTime(const AreaEffectSimulation::FunctionalArea ¤t) { resetStartTime(current.id(), m_currentFunctionalArea); } void resetStartTime(const AreaEffectSimulation::TechnicalArea ¤t) { resetStartTime(current.id(), m_currentTechnicalArea); } void resetStartTime(const AreaEffectSimulation::DusSingleMine ¤t) { resetStartTime(current.id(), m_currentDusSingleMine); } void resetStartTime(const AreaEffectSimulation::GasPipe ¤t) { resetStartTime(current.id(), m_currentGasPipes); } void resetStartTime(const AreaEffectSimulation::BoobyTrap ¤t) { resetStartTime(current.id(), m_currentBoobyTraps); } void resetStartTime(const AreaEffectSimulation::OffRouteMine ¤t) { resetStartTime(current.id(), m_currentOffRouteMines); } std::shared_ptr pdm(); template void txData(const T &tele) { m_txCallback->txData(tele); m_sentAesTelegrams.push_back(new T(tele)); m_sentAesTelegramsAesIds.push_back(tele.aesDdsId); m_checkOutdatedTelegramsTimer->start(); DEBUG_LOG(m_logger) << "Appending " << tele.type()<< " to m_sentAesTelegrams"; } void onCheckOutdatedTelegrams(); void onSendDusMineReactivationTimeout(); private: std::unordered_map m_currentAirSupportImpacts; std::unordered_map m_currentBCContaminations; std::unordered_map m_currentExplosionArea; std::unordered_map m_currentExplosionCluster; std::unordered_map m_currentExplosionSingle; std::unordered_map m_currentMineArea; std::unordered_map m_temporarySingleMineState; std::unordered_map m_currentNContamination; std::unordered_map m_currentFunctionalArea; std::unordered_map m_currentTechnicalArea; std::unordered_map m_currentDusSingleMine; std::unordered_map m_currentGasPipes; /*! * \brief m_currentBoobyTraps (Verdeckte Ladung) * \details Added for 3D Wirksim * \author Niklas Schmidt */ std::unordered_map m_currentBoobyTraps; /*! * \brief m_currentOffRouteMines * \details Added for 3D Wirksim * \author Niklas Schmidt */ std::unordered_map m_currentOffRouteMines; //std::unordered_map m_currentDangerExplosionZones; //TODO: Not yet implemented in Aes (Gefahrenbereich Steilfeuer) std::shared_ptr m_ddsConnector; std::shared_ptr m_txCallback; std::shared_ptr m_dtcAes; std::shared_ptr m_aesStateHandler; QMap m_currentEffectState; QMap m_allReactivatableDusMines; // united map of all DUS-mines independet of matched minearea/status QVector m_minesToSend; std::shared_ptr m_posHandler; MainHandler *m_mainHandler; QTimer *m_checkOutdatedTelegramsTimer; QTimer *m_sendDusMineReactivtionTimer; QVector m_sentAesTelegrams; QVector m_sentAesTelegramsAesIds; LOGGER_T m_logger; }; }