248 lines
6.9 KiB
C++
Executable File
248 lines
6.9 KiB
C++
Executable File
/**
|
|
* "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 <NGLLogger/NGLLoggerBootstrap.h>
|
|
#include <ProjectDataManagement/pdm_dtc.h>
|
|
#include <TrainingAreaBase/recv_from_tab.h>
|
|
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
|
|
|
|
namespace UAS
|
|
{
|
|
FromTab::FromTab(const std::shared_ptr<TrainingAreaBase::DdsHandler> &ddsHandler,
|
|
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &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<UAVPerformMission>::id())
|
|
{
|
|
return HandleState::YesConsume; // we're the only plugin able to fly drones ;)
|
|
}
|
|
|
|
if (telegramId == Constraints<UAVChangeState>::id())
|
|
{
|
|
return HandleState::YesConsume; // we're the only plugin able to fly drones ;)
|
|
}
|
|
|
|
if (telegramId == Constraints<CesHitRequest>::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<DemandVulnerabilityStateChange>::id())
|
|
{
|
|
return HandleState::YesConsume;
|
|
}
|
|
|
|
if (telegramId == Constraints<Init>::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
|