/** * Send telegrams - mix in -> send it to a directory and to socket connections (if available) * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-04-14 */ #include "tx_mixin.h" namespace TrainingAreaBase { TxMixin::TxMixin() : m_logger(getLogger("TxMixin")) {} void TxMixin::addTxHandler(const std::shared_ptr &txCallback) { m_txHandler.push_back(txCallback); } bool TxMixin::removeTxHandler(const std::shared_ptr &txCallback) { return (m_txHandler.removeAll(txCallback) > 0); } void TxMixin::resetSendCounter() { for (const std::shared_ptr &tx : qAsConst(m_txHandler)) tx->resetSendCounter(); } bool TxMixin::txData(const TetraIcd::Acknowledge &data) { return txDataToAll(data); } bool TxMixin::txData(const TrainingAreaBase::TetraIcd::DemandBite &data) { return txDataToAll(data); } bool TxMixin::txData(const TrainingAreaBase::TetraIcd::Init &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::SetVulnerabilityModel &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::DemandEquipmentConfigurationReport &data) { return txDataToAll(data); } bool TxMixin::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::LanguageSelection &data) { return txDataToAll(data); } bool TxMixin::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data) { return txDataToAll(data); } bool TxMixin::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateSingleExplosion &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateAreaExplosion &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateMineArea &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::MineAreaSingleMineState &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateNContamination &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateCContamination &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::DeactivateEffectSimulation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ModifyAreaEffectSimulationName &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::PauseEffectSimulation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ResumeEffectSimulation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::MineTriggered &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::DusMineReactivation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateDusSingleMine &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExerciseEnvironmentData &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExerciseStateData &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::OpaquePayloadDataOut &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::TechnicalArea &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CesHitInformation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CesHitRequest &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::CreateFunctionalArea &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ParticipantSwVersionsRequest &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ParticipantMode &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::DemandParticipantMode &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ParticipantConfiguration &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::DemandParticipantConfiguration &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExerciseEquipmentAssignmentComplete &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::Sanitation &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::SelectiveReammunition &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::SetDevicePowerRequest &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::OcCommand &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::UAVPerformMission &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::UAVChangeState &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExFiredReport &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExFireReadiness &data) { return txDataToAll(data); } bool TxMixin::txData(const TetraIcd::ExConfirmationReport &data) { return txDataToAll(data); } template struct HasHeaderStruct { struct Fallback { TetraIcd::Header header; }; struct Derived : T, Fallback { }; template struct ChT; template static char (&f(ChT*))[1]; template static char (&f(...))[2]; public: static bool const value = sizeof(f(nullptr)) == 2; }; template ::value, int>::type = 0> int getEquipmentNumber(const T &data) { return data.header.equipmentNumber; } template ::value, int>::type = 0> int getEquipmentNumber(const T &data) { Q_UNUSED(data); return 0; // broadcast } template bool TxMixin::txDataToAll(const T &data) { if (m_txHandler.empty()) return false; bool bSent = false; const int equipmentNumber = getEquipmentNumber(data); // broadcast? -> sent to all if (equipmentNumber == 0) { for (const std::shared_ptr &tx : qAsConst(m_txHandler)) { const HandleState hs = tx->canHandleTelegram(equipmentNumber, TrainingAreaBase::TetraIcd::Constraints::id()); if (hs == HandleState::No) continue; if (tx->txData(data)) bSent = true; else WARNING_LOG(m_logger) << "Can not sent broadcast telegram with id " << (int)data.id() << " to handler " << tx->name() << " but it was requested by this handler ..."; } } else { bool bConsumed = false; std::shared_ptr fallbackHandler; for (const std::shared_ptr &tx : qAsConst(m_txHandler)) { const HandleState hs = tx->canHandleTelegram(equipmentNumber, TrainingAreaBase::TetraIcd::Constraints::id()); switch (hs) { case HandleState::No: break; case HandleState::Debug: tx->txData(data); break; case HandleState::YesConsume: if (bConsumed || bSent) WARNING_LOG(m_logger) << "Handler " << tx->name() << " will consume telegram with id " << (int)data.id() << " and equipment number " << equipmentNumber << " but it was already consumed/sent!"; if (tx->txData(data)) { bSent = true; bConsumed = true; } break; case HandleState::YesFallback: fallbackHandler = tx; // remember for later use break; case HandleState::YesShare: if (bConsumed) WARNING_LOG(m_logger) << "Handler " << tx->name() << " will share telegram with id " << (int)data.id() << " and equipment number " << equipmentNumber << " but it was already consumed!"; if (tx->txData(data)) bSent = true; break; } } if (!bSent && fallbackHandler) { if (fallbackHandler->txData(data)) bSent = true; } } if (!bSent) WARNING_LOG(m_logger) << "Could not sent telegram with id " << (int)data.id() << " and equipment number " << equipmentNumber << " - no handler found!"; return bSent; } } // namespace TrainingAreaBase