/** * "SendToTab" implementation to receive requests from TAB (which originate from the OpApp) * $Id$ * $HeadURL$ * $Author$ * Created by Mike Wille, ESZS, 2025-04-17 */ #include "from_tab.h" #include "uav_ia_manager.h" #include #include #include #include #include namespace UAS { FromTab::FromTab(const std::shared_ptr &ddsHandler, const std::shared_ptr &sendToDds, UAVInterfaceAdapterManager *uavIAManager, int exerciseId) : m_isConnected(false) , m_dtcPdm(ProjectDataManagement::Interface::Dtc::create(ddsHandler->ddsConnector())) , m_dtcPpm(ParticipantManagement::Interface::Dtc::create(ddsHandler->ddsConnector())) , m_sendToDds(sendToDds) , m_uavIAManager(uavIAManager) , m_exerciseId(exerciseId) , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("FromTab")) { m_dtcPpm->enableUAS(); m_dtcPpm->enableParticipant(); } TrainingAreaBase::SendToTab::HandleState FromTab::canHandleTelegram(int equipmentNumber, int telegramId) const { bool found = false; const auto &uasList = m_dtcPpm->uASs(); for (const auto &uas : uasList) { if (uas.exerciseId() != m_exerciseId) { continue; } const auto &part = m_dtcPpm->participant(uas.participantId()); if (!part.equipmentNumber().is_set()) { continue; } if (part.equipmentNumber().get() == equipmentNumber) { found = true; break; } } using namespace TrainingAreaBase::TetraIcd; if (!found) { return HandleState::No; } if (telegramId == Constraints::id()) { return HandleState::YesConsume; // we're the only plugin able to fly drones ;) } if (telegramId == Constraints::id()) { return HandleState::YesConsume; // we're the only plugin able to fly drones ;) } if (telegramId == Constraints::id()) { return HandleState::YesShare; // participants hit (jam) the drone, we need this info to tell the drone to e.g. return to home after a hit } if (telegramId == Constraints::id()) { return HandleState::YesConsume; } if (telegramId == Constraints::id()) { return HandleState::YesConsume; } return HandleState::No; // we handle drone telegrams ONLY } bool FromTab::txData(const TrainingAreaBase::TetraIcd::Init &data) { if (!data.resetVulnerabilityState) { return false; } //send statechange init TrainingAreaBase::TetraIcd::StateChange msg; msg.header.equipmentNumber = data.header.equipmentNumber; msg.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); //data.timestamp * 1000; msg.originatorId = data.workstationId; msg.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::ExerciseControl; msg.tasVitality = 100; msg.vulnerabilityBits = 0; msg.vulnerabilityState = TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady; m_sendToDds->rxData(msg); return true; } bool FromTab::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data) { const int eqId = data.header.equipmentNumber; DEBUG_LOG(m_logger) << "eqId: " << eqId; const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId)); if (p.id() <= 0) { WARNING_LOG(m_logger) << "participant not found - stop"; return false; } // NOTE: only first action is performed ... const auto &action = data.actions.front(); if (!m_uavIAManager->waypoint(p.id(), action.absPosition, QStringLiteral("%1_%2").arg(data.missionId).arg(data.missionName))) // send waypoint to uav { WARNING_LOG(m_logger) << "sending waypoint failed!"; return false; } return true; } bool FromTab::txData(const TrainingAreaBase::TetraIcd::UAVChangeState &data) { const int eqId = data.header.equipmentNumber; const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId)); if (p.id() <= 0) { WARNING_LOG(m_logger) << "participant not found - stop"; return false; } // NOTE: only first action is performed ... switch (data.requestedState) { case TrainingAreaBase::TetraIcd::UAVState::Auto: return m_uavIAManager->tryChangeModeToAuto(p.id()); default: return true; } return true; } bool FromTab::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data) { // drone was hit by jamming DEBUG_LOG(m_logger) << "data.chargeTasCodeDirect = " << data.chargeTasCodeDirect; // NOTE: igniterType/IgniterFunciton = 0 as long as CesHitRequest does not contain values if (!m_dtcPdm->isJamming(data.chargeTasCodeDirect,0,0)) { WARNING_LOG(m_logger) << "not jamming"; return false; } DEBUG_LOG(m_logger) << "participantEventChanged: JAMMING! chargetasCodeDirect = " << data.chargeTasCodeDirect; const int eqId = data.header.equipmentNumber; const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId)); if (p.id() <= 0) { WARNING_LOG(m_logger) << "participant not found - stop"; return false; } m_uavIAManager->kill(p.id()); // kill UAV in EXCON and return UAV home TrainingAreaBase::TetraIcd::StateChangeDirect msg; msg.chargeTypeId = data.chargeTasCodeDirect; // = jamming msg.header.equipmentNumber = eqId; msg.header.timeStamp = data.header.timeStamp; msg.vulnerabilityState = TrainingAreaBase::TetraIcd::VulnerabilityState::CatastrophicKill; msg.originatorId = data.originatorEquipmentNumber; DEBUG_LOG(m_logger) << "sending state change direct (kill) with jamming for eqId " << msg.header.equipmentNumber; m_sendToDds->rxData(msg); return true; } bool FromTab::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data) { const auto p = m_dtcPpm->participantIdByEquipmentNumber(data.header.equipmentNumber); // we could trigger RTH if needed with: // if (p > 0 && m_uavIAManager) // m_uavIAManager->kill(p); // kill UAV in EXCON and return UAV home const auto &pData = m_dtcPpm->dynamicParticipantData(p); for (const auto &dyn : pData.stateHistory()) { if (dyn.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CatastrophicKill) { return false; } } //send statechange init TrainingAreaBase::TetraIcd::StateChange msg; msg.header.equipmentNumber = data.header.equipmentNumber; msg.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); //data.timestamp * 1000; msg.originatorId = data.workstationId; msg.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::ExerciseControl; msg.tasVitality = 0; msg.vulnerabilityBits = 0; msg.vulnerabilityState = data.reqestedState; m_sendToDds->rxData(msg); return true; } bool FromTab::txData(const TrainingAreaBase::TetraIcd::OcCommand &data) { Q_UNUSED(data) return false; } } // namespace UAS