Files
qt5-legatus-legacy/Lts/Proxies/TrainingAreaBase/recv_from_dds_fts.cpp
T
torstenandCopilot 3028302f7b Qt6 Migration: Merge latest Qt5 devel content and apply migration fixes
- Merged 292 changed files from dlbo snapshot
- Fixed IDL enum collisions (PortType, PdmEventType)
- Fixed Grantlee template for C++11 scoped enums
- Fixed CMake VERSION_GREATER syntax
- Added missing directories (THP, LtsRestClient, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-15 18:20:51 +00:00

798 lines
34 KiB
C++
Executable File

/**
* Handle incoming Function Topic Requests (and send them to Tetra)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "recv_from_dds_fts.h"
#include "main_handler.h"
#include "ism_handler.h"
#include "settings.h"
#include <LtsUtilsCore/json.h>
namespace TrainingAreaBase
{
RecvFromDdsFts::RecvFromDdsFts(MainHandler *mainHandler, const std::shared_ptr<Interface::Fts> &ftsTab,
const std::shared_ptr<SendToTab> &txCallback)
: Interface::Fts::DemandBiteRequestHandler(ftsTab)
, Interface::Fts::DemandInitRequestHandler(ftsTab)
, Interface::Fts::SendSetVulnerabilityModelRequestHandler(ftsTab)
, Interface::Fts::DemandConfigurationReportRequestHandler(ftsTab)
, Interface::Fts::DemandVulnerabilityStateChangeRequestHandler(ftsTab)
, Interface::Fts::SendLanguageSelectionRequestHandler(ftsTab)
, Interface::Fts::SendEquipmentMessageRequestHandler(ftsTab)
, Interface::Fts::SendOcDataRequestHandler(ftsTab)
, Interface::Fts::SendFireSmokeMarkerDataRequestHandler(ftsTab)
, Interface::Fts::SendGeopairingDataRequestHandler(ftsTab)
, Interface::Fts::SendTargetDataRequestHandler(ftsTab)
, Interface::Fts::SendCesHitInformationRequestHandler(ftsTab)
, Interface::Fts::SendCesHitRequestHandler(ftsTab)
, Interface::Fts::SendParticipantSwVerionsRequestHandler(ftsTab)
, Interface::Fts::SendParticipantModeRequestHandler(ftsTab)
, Interface::Fts::DemandParticipantModeRequestHandler(ftsTab)
, Interface::Fts::SendParticipantConfigurationRequestHandler(ftsTab)
, Interface::Fts::DemandParticipantConfigurationRequestHandler(ftsTab)
, Interface::Fts::SendParticipantBlockedAreaRequestHandler(ftsTab)
, Interface::Fts::SendParticipantBeStillWarningRequestHandler(ftsTab)
, Interface::Fts::SendSetSanitationRequestHandler(ftsTab)
, Interface::Fts::SendResetAllDusMinesRequestHandler(ftsTab)
, Interface::Fts::SendSelectiveReammunitionRequestHandler(ftsTab)
, Interface::Fts::SetDevicePowerRequestHandler(ftsTab)
, Interface::Fts::AdlerCalculateTrajectoryRequestHandler(ftsTab)
, Interface::Fts::SendOcCommandRequestHandler(ftsTab)
, Interface::Fts::SendUasWaypointRequestHandler(ftsTab)
, Interface::Fts::SendModifyUasStateRequestHandler(ftsTab)
, Interface::Fts::SendExFireReadinessRequestHandler(ftsTab)
, Interface::Fts::SendExFiredReportRequestHandler(ftsTab)
, Interface::Fts::SendExConfirmationReportRequestHandler(ftsTab)
, m_mainHandler(mainHandler)
, m_ftsTab(ftsTab)
, m_txCallback(txCallback)
, m_logger(getLogger("RecvFromDdsFts"))
{
m_categorieData = loadRemainEffectStructMap();
}
void RecvFromDdsFts::onDemandBiteRequest(const rti::core::SampleIdentity &cookie, const DemandBiteRequest &request)
{
TetraIcd::DemandBite data;
data.withSelfTest = request.withSelfTest();
bool bRet = true;
// TODO: fixme
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->demandBiteReply(cookie, fillFro(request.requestId(), bRet));
}
void RecvFromDdsFts::onDemandInitRequest(const rti::core::SampleIdentity &cookie, const DemandInitRequest &request)
{
TetraIcd::Init data;
data.workstationId = request.workstationId();
data.resetManipulation = request.resetManipulation();
data.resetVulnerabilityState = request.resetVulnerabilityState();
data.restockCharges = request.restockCharges();
data.restockSanitationMaterial = request.restockSanitationMaterial();
bool bRet = true;
// TODO: fixme
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->demandInitReply(cookie, fillFro(request.requestId(), bRet));
}
void RecvFromDdsFts::onSendSetVulnerabilityModelRequest(const rti::core::SampleIdentity &cookie, const SendSetVulnerabilityModelRequest &request)
{
TetraIcd::SetVulnerabilityModel data;
data.header.equipmentNumber = request.equipmentNumber();
data.vulnerabilityModelMineIed = request.vulnerabilityModelMineIed();
data.vulnerabilityModelAreaFire = request.vulnerabilityModelAreaFire();
data.vulnerabilityModelOperatingResource = request.vulnerabilityModelOperationalResource();
data.vulnerabilityModelAcWeaponry = request.vulnerabilityModelACWeaponry();
m_ftsTab->sendSetVulnerabilityModelReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onDemandConfigurationReportRequest(const rti::core::SampleIdentity &cookie, const DemandConfigurationReportRequest &request)
{
TetraIcd::DemandEquipmentConfigurationReport data;
data.header.equipmentNumber = request.equipmentNumber();
m_ftsTab->demandConfigurationReportReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onDemandVulnerabilityStateChangeRequest(const rti::core::SampleIdentity &cookie, const DemandVulnerabilityStateChangeRequest &request)
{
TetraIcd::DemandVulnerabilityStateChange data;
data.reqestedState = static_cast<TetraIcd::VulnerabilityState>(request.vulnerabilityState().underlying());
data.workstationId = request.workstationId();
data.vulnerabilityVitalityIndex = getVulnerabilityVitalityIndexFromVitalityAndVba(request.vulnerabilityKind(), request.vitality());
bool bRet = true;
// TODO: fixme
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->demandVulnerabilityStateChangeReply(cookie, fillFro(request.requestId(), bRet));
}
void RecvFromDdsFts::onSendLanguageSelectionRequest(const rti::core::SampleIdentity &cookie, const SendLanguageSelectionRequest &request)
{
TetraIcd::LanguageSelection data;
data.header.equipmentNumber = request.equipmentNumber();
data.languageSelection = static_cast<TetraIcd::Language>(request.language().underlying());
m_ftsTab->sendLanguageSelectionReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendEquipmentMessageRequest(const rti::core::SampleIdentity &cookie, const SendEquipmentMessageRequest &request)
{
if (request.sender().is_set() &&
request.subject().is_set() &&
request.message().is_set())
{
// Message to O/C
TetraIcd::EquipmentMessageOC data;
data.senderId = request.sender().get();
data.subject = request.subject().get();
data.message = request.message().get();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
bool bRet = true;
// TODO: fixme
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
data.receiverId = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->sendEquipmentMessageReply(cookie, fillFro(0, bRet));
}
else
{
TetraIcd::EquipmentMessage data;
if (request.messageId().is_set())
data.msgId = request.messageId().get();
else if (request.message().is_set())
data.message = request.message().get();
else
{
m_ftsTab->sendEquipmentMessageReply(cookie, fillFro(0, false));
ERROR_LOG(m_logger) << "Got SendEquipmentMessageRequest but neither message nor messageId is set!";
return;
}
bool bRet = true;
// TODO: fixme
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->sendEquipmentMessageReply(cookie, fillFro(request.requestId(), bRet));
}
}
void RecvFromDdsFts::onSendOcDataRequest(const rti::core::SampleIdentity &cookie, const SendOcDataRequest &request)
{
TetraIcd::OpaquePayloadDataOut data;
data.payloadType = TetraIcd::OpaquePayloadDataBase::Type::OC;
data.header.equipmentNumber = request.equipmentNumber();
data.payload = request.payload();
m_ftsTab->sendOcDataReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendFireSmokeMarkerDataRequest(const rti::core::SampleIdentity &cookie, const SendFireSmokeMarkerDataRequest &request)
{
TetraIcd::OpaquePayloadDataOut data;
data.payloadType = TetraIcd::OpaquePayloadDataBase::Type::FireSmokeMarker;
data.header.equipmentNumber = request.equipmentNumber();
data.payload = request.payload();
m_ftsTab->sendFireSmokeMarkerDataReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendGeopairingDataRequest(const rti::core::SampleIdentity &cookie, const SendGeopairingDataRequest &request)
{
TetraIcd::OpaquePayloadDataOut data;
data.payloadType = TetraIcd::OpaquePayloadDataBase::Type::Geopairing;
data.header.equipmentNumber = request.equipmentNumber();
data.payload = request.payload();
m_ftsTab->sendGeopairingDataReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendTargetDataRequest(const rti::core::SampleIdentity &cookie, const SendTargetDataRequest &request)
{
TetraIcd::OpaquePayloadDataOut data;
data.payloadType = TetraIcd::OpaquePayloadDataBase::Type::Target;
data.header.equipmentNumber = request.equipmentNumber();
data.payload = request.payload();
m_ftsTab->sendTargetDataReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendCesHitInformationRequest(const rti::core::SampleIdentity &cookie, const SendCesHitInformation &request)
{
TetraIcd::CesHitInformation data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = request.effectTime();
data.originatorEquipmentNumber = request.originatorEquipmentNumber();
const auto &ct = m_mainHandler->pdmHandler()->chargeTypeFromId(request.chargeTypeId());
data.chargeTasCodeDirect = ct.id();
data.chargeTasCodeIndirect = ct.id();
data.directionDegree = request.directionDegree();
data.distance = request.distanceToOrignator();
data.effectPercent = request.effectPercent();
m_ftsTab->sendCesHitInformationReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendCesHitRequest(const rti::core::SampleIdentity &cookie, const SendCesHitRequest &request)
{
DEBUG_LOG(m_logger) << "onSendCesHitRequest: " << request.equipmentNumber() << " - " << request.effectTime()
<< " request.chargeTypeId=" << request.chargeTypeId()
<< " request.eventType()=" << request.eventType()
<< " request.aesId()=" << request.aesId()
<< " aesTypeFromId=" << m_mainHandler->aesHandler()->aesTypeFromId(request.aesId());
// NOTE: igniterType/IgniterFunciton = 0 as long as SendCesHitRequest does not contain values
if (m_mainHandler->pdmHandler()->isSmartChargeType({request.chargeTypeId(), 0,0}))
{
// special handling for smart - must be send as singleFire
m_ftsTab->sendCesHitReply(cookie,
fillFro(request.participantId(),
m_mainHandler->aesHandler()->sendSingleFireSMArt(request)));
return;
}
TetraIcd::CesHitRequest data;
//test
data.reserve2 = request.originatorEquipmentNumber();
data.reserve1 = request.chargeTypeId();
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = request.effectTime();
const auto &ct = m_mainHandler->pdmHandler()->chargeTypeFromId(request.chargeTypeId());
// GUEZE-359 Steilfeuer mit Sekundaerwirkung wird als Mun 371, ... gesendet. Fuehrt zu Treffer DUS statt WirkSim
//#ifdef GUEZ_MODE
// if ( request.chargeTypeId() > 370 && request.chargeTypeId() < 390 )
// {
// data.chargeTasCodeDirect = 201; // immer den direkten code (fuer wirkfelder: pseudo-osag code >= 201)
// data.chargeTasCodeIndirect = 201;
// }
// else
// {
// data.chargeTasCodeDirect = ct.id(); // immer den direkten code (fuer wirkfelder: pseudo-osag code >= 201)
// data.chargeTasCodeIndirect = ct.id();
// }
//#else
if ((request.eventType() == ProjectDataManagement::EventType::HitBuilding) && (ct.legacyId() > 0))
{
data.chargeTasCodeDirect = 201; // immer den direkten code (fuer wirkfelder: pseudo-osag code >= 201)
data.chargeTasCodeIndirect = 201;
}
else if (ct.legacyId() > 0)
{
data.chargeTasCodeDirect = ct.legacyId();
data.chargeTasCodeIndirect = ct.legacyId();
}
else
{
data.chargeTasCodeDirect = ct.id();
data.chargeTasCodeIndirect = ct.id();
}
//#endif
data.mineId = request.mineId();
if (request.aesId() != 0)
{
//data.aesTetraIdUnused = m_mainHandler->aesHandler()->tetraIdFromDdsId(request.aesId());
data.aesDdsId = request.aesId();
//TODO: !!!!!! Use new EventType to check which AreaEffectSimulationType will be chosen.
if (request.eventType() == ProjectDataManagement::EventType::ExplosionCluster)
data.aesType = TetraIcd::AreaEffectSimulationType::ExplosionArea;
else
data.aesType = m_mainHandler->aesHandler()->aesTypeFromId(request.aesId());
/*!
\brief Take the new event type attribute to check if its is a HazardArea(DangerZone/Gefahrenbereich)
*
* */
if ((request.eventType() == ProjectDataManagement::EventType::LeaveHazardDistance) ||
(request.eventType() == ProjectDataManagement::EventType::EnterHazardDistance))
{
INFO_LOG(m_logger) << "HarzardArea: " << request.effectTime();
data.reserve1 = request.mineId();
data.aesType = TetraIcd::AreaEffectSimulationType::DangerZoneExplosion;
}
else if (request.eventType() == ProjectDataManagement::EventType::AirSupport)
{
data.aesType = TetraIcd::AreaEffectSimulationType::AirSupport;
}
}
else
data.originatorEquipmentNumber = request.originatorEquipmentNumber();
const auto &tabPos = request.position();
data.buildingId = tabPos.moutObjectId().is_set() ? tabPos.moutObjectId().get() : 0;
data.roomId = tabPos.moutRoomId().is_set() ? tabPos.moutRoomId().get() : 0;
data.remainEffectPercent = request.remainEffectPercent();
data.relPosition = m_mainHandler->posHandler()->geographicToRelative(tabPos.position());
// NOTE: igniterType/IgniterFunciton = 0 as long as SendCesHitRequest does not contain values
if (m_mainHandler->pdmHandler()->isSmartChargeType({request.chargeTypeId(),0,0}))
data.remainEffectTasCodeDirect = calculateRemainEffectTasCode(ct.id(), request.remainEffectPercent());
else if ((request.eventType() == ProjectDataManagement::EventType::HitBuilding) ||
(request.eventType() == ProjectDataManagement::EventType::HitEffectSimulation) // GUEZE-2873 / GUEZE-2888
) //Gebäude Sekudärwirkung
{
data.remainEffectTasCodeDirect = calculateRemainEffectTasCode(ct.id(), request.remainEffectPercent());
DEBUG_LOG(m_logger) << "PDM::EventType = " << request.eventType()
<< " equipmentNumber=" << request.equipmentNumber()
<< " originatorEquipmentNumber=" << data.originatorEquipmentNumber
<< " chargeType=" << ct.id()
<< " remainEffectPercent()=" << request.remainEffectPercent()
<< " -> remainEffectTasCodeDirect=" << data.remainEffectTasCodeDirect ;
}
else
data.remainEffectTasCodeDirect = request.remainEffectPercent();//calculateRemainEffectTasCode(ct.id(), request.remainEffectPercent());
// [GUEZE-3469] Funktionsraum dekontaminiert faelschlicherweise
if (m_mainHandler->aesHandler()->aesTypeFromId(request.aesId()) == TetraIcd::AreaEffectSimulationType::FunctionalArea)
{
// GUEZSB60_ICD_52_Zentrale-TNE
// 3.3.2.5.9.6 Trefferereignis Sekundärwirkung
// 6 = Funktionsraum 0 = verlassen
// 1 = betreten Meldung wird einmalig beim Betreten des Funktionraums und beim Verlassen gesendet.
// Feld Munitionsart: Betriebsmodus (MS-Byte) / Wartezeit (LS-Byte) für Entgiftungsmaßnahmen
// Feld Verursacher: Funktionsraumkennung
// Feld Reserve1: Betriebsmodus (MS-Byte) / Wartezeit (LS-Byte) für Instandsetzungsmaßnahmen
// Feld Reserve2: Betriebsmodus (MS-Byte) / Wartezeit (LS-Byte) für San.-dienstliche Versorgung
AreaEffectSimulation::FunctionalArea fa = m_mainHandler->aesHandler()->dtcAes()->functionalArea(request.aesId());
DEBUG_LOG(m_logger) << "fa maintMode=" << fa.maintMode()
<< " maintTime=" <<fa.maintTime()
<< " deconMode=" << fa.deconMode()
<< " deconTime=" << fa.deconTime()
<< " medicMode=" << fa.medicMode()
<< " medicTime=" << fa.medicTime();
data.chargeTasCodeDirect = 0;
data.reserve1 = 0;
data.reserve2 = 0;
if (fa.deconMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime)
{
qint32 msb = AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime << 8;
qint32 lsb = fa.deconTime() / 1000 / 60 / 10; // dissolution in 10 minute steps
data.chargeTasCodeIndirect = msb | lsb;
DEBUG_LOG(m_logger) << "deconMode: remainEffectTasCodeDirect=" << data.chargeTasCodeIndirect
<< " msb=" << msb
<< " lsb=" << lsb;
}
if (fa.maintMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime)
{
qint32 msb = AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime << 8;
qint32 lsb = fa.maintTime() / 1000 / 60 / 10; // dissolution in 10 minute steps
data.reserve1 = msb | lsb;
DEBUG_LOG(m_logger) << "maintMode: reserve1=" << data.reserve1
<< " msb=" << msb
<< " lsb=" << lsb;
}
if (fa.medicMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime)
{
qint32 msb = AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime << 8;
qint32 lsb = fa.medicTime() / 1000 / 60 / 10; // dissolution in 10 minute steps
data.reserve2 = msb | lsb;
DEBUG_LOG(m_logger) << "medicMode: reserve2=" << data.reserve2
<< " msb=" << msb
<< " lsb=" << lsb;
}
}
m_ftsTab->sendCesHitReply(cookie, fillFro(request.participantId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendParticipantSwVerionsRequest(const rti::core::SampleIdentity &cookie, const SendParticipantSwVerionsRequest &request)
{
DEBUG_LOG(m_logger) << "onSendParticipantSwVerionsRequest: " << request.equipmentNumber() << " - " << request.equipmentFunctionId();
TetraIcd::ParticipantSwVersionsRequest data;
data.header.equipmentNumber = request.equipmentNumber();
data.equipmentFunctionId = request.equipmentFunctionId();
m_ftsTab->sendParticipantSwVerionsReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendParticipantModeRequest(const rti::core::SampleIdentity &cookie, const SendParticipantModeRequest &request)
{
TetraIcd::ParticipantMode data;
data.header.equipmentNumber = request.equipmentNumber();
data.language = static_cast<TetraIcd::Language>(request.language().underlying());
data.operationMode = static_cast<TetraIcd::ParticipantMode::OperationMode>(request.operationMode().underlying());
data.reactivationDetoxication = request.reactivationDetoxication();
data.reactivationMaintenance = request.reactivationMaintenance();
data.reactivationMedic = request.reactivationMedic();
data.modeVest = static_cast<TetraIcd::ParticipantMode::WphMode>(request.protectionModeVest().underlying());
data.modeHelmet = static_cast<TetraIcd::ParticipantMode::WphMode>(request.protectionModeHelmet().underlying());
data.personellProtectionMode = static_cast<TetraIcd::ParticipantMode::PersonellProtection>(request.personellProtection().underlying());
data.protectionLevel = static_cast<TetraIcd::ParticipantMode::ProtectionLevel>(request.protectionLevel().underlying());
data.handgrenadeSearchMode = static_cast<TetraIcd::ParticipantMode::HandgrenadeSearchMode>(request.handgrenadeSearchMode().underlying());
data.internationalMode = static_cast<TetraIcd::ParticipantMode::InternationalMode>(request.internationalMode().underlying());
data.abcProtectionMode = static_cast<TetraIcd::ParticipantMode::ABCProtectionMode>(request.abcProtectionMode().underlying());
m_ftsTab->sendParticipantModeReply(cookie, fillFro(request.requestId(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onDemandParticipantModeRequest(const rti::core::SampleIdentity &cookie, const DemandParticipantModeRequest &request)
{
TetraIcd::DemandParticipantMode data;
data.header.equipmentNumber = request.equipmentNumber();
m_ftsTab->demandParticipantModeReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendParticipantConfigurationRequest(const rti::core::SampleIdentity &cookie, const SendParticipantConfigurationRequest &request)
{
TetraIcd::ParticipantConfiguration data;
data.header.equipmentNumber = request.equipmentNumber();
// positioning
data.positionIntervallVehicle = request.positionIntervallVehicle();
data.positionIntervallPersonell = request.positionIntervallPersonell();
data.positionIntervallAircraft = request.positionIntervallAircraft();
data.positionTransmissionIntervall = request.positionTransmissionIntervall();
data.heightbarrier = request.heightbarrier();
data.faultPositionHandling = static_cast<TetraIcd::ParticipantConfiguration::FaultPositionHandling>(request.faultPositionHandling().underlying());
data.switchingPositionIntervall = static_cast<TetraIcd::ParticipantConfiguration::SwitchingPositionIntervall>(request.switchingPositionIntervall().underlying());
// radio protocoll parameter
data.waittimeAdditionalBroadcastDemand = request.waittimeAdditionalBroadcastDemand();
data.factorWaittimeIncreaseAtHighload = request.factorWaittimeIncreaseHighload();
// automatic vulnerability increase
data.waittimeAutomaticVulnerabilityIncreaseLevel1 = request.waittimeAutomaticVulnerabilityIncreaseLevel1();
data.waittimeAutomaticVulnerabilityIncreaseLevel2 = request.waittimeAutomaticVulnerabilityIncreaseLevel2();
data.waittimeAutomaticVulnerabilityIncreaseLevel3 = request.waittimeAutomaticVulnerabilityIncreaseLevel3();
// optical code
data.opticalCode = static_cast<TetraIcd::ParticipantConfiguration::OpticalCode>(request.opticalCode().underlying());
// vulnerability model
data.vulnerabilityModel = request.vulnerabilityModel();
data.validTimeOps = request.validTimeOps();
m_ftsTab->sendParticipantConfigurationReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendParticipantBlockedAreaRequest(const rti::core::SampleIdentity &cookie, const SendParticipantBlockedAreaRequest &request)
{
TetraIcd::CesHitRequest data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); // TODO
data.aesType = TetraIcd::AreaEffectSimulationType::SpecialArea;
data.remainEffectPercent = request.blockedAreaMode() == BlockedAreaMode::Enter ? 1 : 0;
m_ftsTab->sendParticipantBlockedAreaReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendParticipantBeStillWarningRequest(const rti::core::SampleIdentity &cookie, const SendParticipantBeStillWarningRequest &request)
{
TetraIcd::CesHitRequest data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); // TODO
data.aesType = TetraIcd::AreaEffectSimulationType::BeStillWarning;
data.remainEffectPercent = 0;
WARNING_LOG(m_logger) << "sendParticipantBeStillWarningReply equipmentNumber=" << request.equipmentNumber();
m_ftsTab->sendParticipantBeStillWarningReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendSetSanitationRequest(const rti::core::SampleIdentity &cookie, const SendSetSanitationRequest &request)
{
TetraIcd::Sanitation data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
data.proceduresTaken = request.sanitationProceduresTaken();
data.sanitationResult = TetraIcd::SanitationResult::NoEffect;
data.sanitationEvaluation = TetraIcd::SanitationEvaluation::Okay; // To have a 0 for TETRA
data.uniqeId = 0;
data.originatorEquipmentNumber = request.originatorEquipmentNumber();
data.qualification = static_cast<TetraIcd::Qualification>(request.qualification().underlying());
m_ftsTab->sendSetSanitationReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendSelectiveReammunitionRequest(const rti::core::SampleIdentity &cookie, const SendSelectiveReammunitionRequest &request)
{
DEBUG_LOG(m_logger) << "onSendSelectiveReammunitionRequest for equipment number: " << request.equipmentNumber();
TetraIcd::SelectiveReammunition data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
data.gearId = request.gearId();
for(auto ra : request.reammunition())
{
TetraIcd::Reammunition tra;
tra.chargeTypeId = ra.chargeTypeId();
tra.newDefaultStock = ra.newDefaultStock();
tra.newStock = ra.newStock();
tra.tracerRatio = ra.tracerRatio();
data.reammunitions.push_back(tra);
}
m_ftsTab->sendSelectiveReammunitionReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSendResetAllDusMinesRequest(const rti::core::SampleIdentity &cookie, const SendResetAllDusMinesRequest &request)
{
// We actually just need to have the call, no contents.
Q_UNUSED(request);
m_mainHandler->aesHandler()->resetAllDusMines();
m_ftsTab->sendResetAllDusMinesReply(cookie, fillFro(0, m_txCallback->txData(TetraIcd::DusMineReactivation())));
}
void RecvFromDdsFts::onDemandParticipantConfigurationRequest(const rti::core::SampleIdentity &cookie, const DemandParticipantConfigurationRequest &request)
{
TetraIcd::DemandParticipantConfiguration data;
data.header.equipmentNumber = request.equipmentNumber();
m_ftsTab->demandParticipantConfigurationReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onSetDevicePowerRequest(const rti::core::SampleIdentity &cookie, const SetDevicePowerRequest &request)
{
TetraIcd::SetDevicePowerRequest data;
data.header.equipmentNumber = request.equipmentNumber();
data.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
data.powerType = static_cast<TetraIcd::PowerMethod>(request.powerType().underlying());
data.subdeviceId = request.subdeviceId();
m_ftsTab->setDevicePowerReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(data)));
}
void RecvFromDdsFts::onAdlerCalculateTrajectoryRequest(const rti::core::SampleIdentity &cookie, const AdlerCalculateTrajectoryRequest &request)
{
DEBUG_LOG(m_logger) << "onSendCalculateTrajectoryAdlerRequest";
}
void RecvFromDdsFts::onSendOcCommandRequest(const rti::core::SampleIdentity &cookie, const SendOcCommandRequest &request)
{
TetraIcd::OcCommand data;
data.action = request.action();
bool bRet = true;
for (const int equipNo : request.equipmentNumbers())
{
data.header.equipmentNumber = equipNo;
if (!m_txCallback->txData(data))
bRet = false;
}
m_ftsTab->sendOcCommandReply(cookie, fillFro(request.requestId(), bRet));
}
void RecvFromDdsFts::onSendUasWaypointRequest(const rti::core::SampleIdentity &cookie, const SendUasWaypointRequest &request)
{
TetraIcd::UAVPerformMission mission;
mission.header.equipmentNumber = request.equipmentNumber();
mission.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
mission.missionName = QString::fromStdString(request.name());
mission.missionId = request.planId();
ERROR_LOG(m_logger) << "####################### request.equipmentNumber(): " << request.equipmentNumber() << ", request.name(): " << request.name() << ", mission.header.equipmentNumber: " << mission.header.equipmentNumber << ", properties: " << request.properties();
TetraIcd::UAVAction action;
action.task = TetraIcd::UAVActionTask::Loiter;
auto &pos = action.absPosition;
double lat = 0, lon = 0, z = 0;
try
{
const auto props = LtsUtils::JsonObject::fromJsonSafe(request.properties());
lat = props.value<double>("location_y");
lon = props.value<double>("location_x");
z = props.valueOr<double>("location_z", 0);
}
catch (const std::exception &ex)
{
ERROR_LOG(m_logger) << "props is missing critical values: " << ex.what();
m_ftsTab->sendUasWaypointReply(cookie, fillFro(request.equipmentNumber(), false));
return;
}
pos.lat = lat;
pos.lon = lon;
pos.z = z;
mission.actions.push_back(action);
bool ret = m_txCallback->txData(mission); // send waypoint to uav via uas tab plugin
m_ftsTab->sendUasWaypointReply(cookie, fillFro(request.equipmentNumber(), ret));
}
void RecvFromDdsFts::onSendModifyUasStateRequest(const rti::core::SampleIdentity &cookie, const SendModifyUasStateRequest &request)
{
TetraIcd::UAVChangeState changeState;
changeState.header.equipmentNumber = request.equipmentNumber();
changeState.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
changeState.requestedState = static_cast<TetraIcd::UAVState>(request.uasState().underlying());
m_ftsTab->sendModifyUasStateReply(cookie, fillFro(request.equipmentNumber(), m_txCallback->txData(changeState)));
}
void RecvFromDdsFts::onSendExFireReadinessRequest(const rti::core::SampleIdentity &cookie, const SendExFireReadinessRequest &request)
{
TetraIcd::ExFireReadiness fireReadiness;
fireReadiness.header.equipmentNumber = 100;
fireReadiness.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
fireReadiness.partyId = request.partyId();
fireReadiness.reference = QString::fromStdString(request.reference());
m_ftsTab->sendExFireReadinessReply(cookie, fillFro(request.participantId(), m_txCallback->txData(fireReadiness)));
}
void RecvFromDdsFts::onSendExFiredReportRequest(const rti::core::SampleIdentity &cookie, const SendExFiredReportRequest &request)
{
TetraIcd::ExFiredReport firedReport;
firedReport.header.equipmentNumber = request.participantId();
firedReport.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
firedReport.partyId = request.partyId();
firedReport.reference = QString::fromStdString(request.reference());
firedReport.unitIdentifier = QString::fromStdString(request.unitIdentifier());
firedReport.identifier = QString::fromStdString(request.identifier());
m_ftsTab->sendExFiredReportReply(cookie, fillFro(request.participantId(), m_txCallback->txData(firedReport)));
}
void RecvFromDdsFts::onSendExConfirmationReportRequest(const rti::core::SampleIdentity &cookie, const SendExConfirmationReportRequest &request)
{
TetraIcd::ExConfirmationReport confirmationReport;
confirmationReport.header.equipmentNumber = request.participantId();
confirmationReport.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
confirmationReport.partyId = request.partyId();
confirmationReport.reference = QString::fromStdString(request.reference());
confirmationReport.unitIdentifier = QString::fromStdString(request.unitIdentifier());
confirmationReport.identifier = QString::fromStdString(request.identifier());
m_ftsTab->sendExConfirmationReportReply(cookie, fillFro(request.participantId(), m_txCallback->txData(confirmationReport)));
}
Core::FunctionReplyObject RecvFromDdsFts::fillFro(int participantId, bool bSuccess)
{
if (bSuccess)
return Core::FunctionReplyObject(participantId);
return Core::FunctionReplyObject(participantId, tr_lts("dds", "Error sending telegram to tetra."));
}
// Charge Type ID is already baseChargeType
int RecvFromDdsFts::getDestructiveCategorie(const int destructiveFactor) const
{
int categorie = 0;
if (destructiveFactor > 100)
categorie = 5;
else if (destructiveFactor > 50)
categorie = 4;
else if (destructiveFactor > 10)
categorie = 3;
else if (destructiveFactor > 1)
categorie = 2;
else if (destructiveFactor > 0)
categorie = 1;
else
categorie = 0;
return categorie;
}
QMap<int, QVector<RecvFromDdsFts::RemainEffectStruct>> RecvFromDdsFts::loadRemainEffectStructMap()
{
QMap<int, QVector<RemainEffectStruct>> map;
// remainingEffects liefert ein Array, in einem QJsonObject "verkleidet".
// Dann werden alle keys ermittelt, damit man aus dem Array/QJsonObject
// per value() wieder an die eigentlichen values kommt...
// Sieht irgendwie sehr kompliziert aus. Sollte remainingEffects vielleicht besser ein array liefern???
QJsonObject obj = Settings::remainingEffects();
QVector<RemainEffectStruct> resVec;
QStringList keyList = obj.keys();
for (const auto &key : qAsConst(keyList))
{
const auto &val = obj.value(key).toObject();
resVec.clear();
resVec.resize(val.size());
QStringList x = val.keys();
int i=0;
for (const auto &resElement : qAsConst(x))
{
const auto val2 = val.value(resElement).toInt();
RemainEffectStruct res(resElement.toInt(), static_cast<RemainEffectStruct::Category>(val2));
resVec[i++] = res;
}
std::sort(resVec.begin(), resVec.end(), [](const RemainEffectStruct &a, const RemainEffectStruct &b)
{
return a.remainEffectMax < b.remainEffectMax;
});
map.insert(key.toInt(), resVec);
}
return map;
}
int RecvFromDdsFts::calculateRemainEffectTasCode(int chargeTypeIdBase, int remainEffectPercent) const
{
if (remainEffectPercent < 0)
return 0;
if (remainEffectPercent > 100)
remainEffectPercent = 100;
const int destructiveFactor = m_mainHandler->pdmHandler()->buildingChargeEffect(chargeTypeIdBase).destructiveFactor();
const int categorie = getDestructiveCategorie(destructiveFactor);
const auto &value = m_categorieData.value(categorie);
// must be sorted, but loadRemainEffectStructMap() ensures this.
for (const auto &remainEffect : value)
{
if (remainEffectPercent <= remainEffect.remainEffectMax)
return (remainEffect.chargeTypeId()); // always return OSAG as the TNE is not capable of handling ULEIS IED charges (yet).
}
return 0;
}
uint32_t RecvFromDdsFts::getVulnerabilityVitalityIndexFromVitalityAndVba(uint32_t vulnerabilityKind, uint32_t vitality)
{
uint32_t ret = vulnerabilityKind;
if (vitality == UINT16_MAX || vitality == 0)
vitality = 0;
else
{
vitality /= 10;
vitality += 1;
if (vitality > 11)
{
ERROR_LOG(m_logger) << "Cant convert Vitality!";
return 0;
}
}
ret += vitality << 12;
return ret;
}
}