/** * 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 namespace TrainingAreaBase { RecvFromDdsFts::RecvFromDdsFts(MainHandler *mainHandler, const std::shared_ptr &ftsTab, const std::shared_ptr &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(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(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=" <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(request.language().underlying()); data.operationMode = static_cast(request.operationMode().underlying()); data.reactivationDetoxication = request.reactivationDetoxication(); data.reactivationMaintenance = request.reactivationMaintenance(); data.reactivationMedic = request.reactivationMedic(); data.modeVest = static_cast(request.protectionModeVest().underlying()); data.modeHelmet = static_cast(request.protectionModeHelmet().underlying()); data.personellProtectionMode = static_cast(request.personellProtection().underlying()); data.protectionLevel = static_cast(request.protectionLevel().underlying()); data.handgrenadeSearchMode = static_cast(request.handgrenadeSearchMode().underlying()); data.internationalMode = static_cast(request.internationalMode().underlying()); data.abcProtectionMode = static_cast(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(request.faultPositionHandling().underlying()); data.switchingPositionIntervall = static_cast(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(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(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(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("location_y"); lon = props.value("location_x"); z = props.valueOr("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(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> RecvFromDdsFts::loadRemainEffectStructMap() { QMap> 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 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(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; } }