/** * 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); 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); 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.pdmEventType=" << request.pdmEventType << " 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.pdmEventType == ProjectDataManagement::PdmEventType::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.pdmEventType == ProjectDataManagement::PdmEventType::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.pdmEventType == ProjectDataManagement::PdmEventType::EventType_LeaveHazardDistance) || (request.pdmEventType == ProjectDataManagement::PdmEventType::EventType_EnterHazardDistance)) { INFO_LOG(m_logger) << "HarzardArea: " << request.effectTime; data.reserve1 = request.mineId; data.aesType = TetraIcd::AreaEffectSimulationType::DangerZoneExplosion; } else if (request.pdmEventType == ProjectDataManagement::PdmEventType::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.pdmEventType == ProjectDataManagement::PdmEventType::EventType_HitBuilding) || (request.pdmEventType == ProjectDataManagement::PdmEventType::EventType_HitEffectSimulation) // GUEZE-2873 / GUEZE-2888 ) //Gebäude Sekudärwirkung { data.remainEffectTasCodeDirect = calculateRemainEffectTasCode(ct.id, request.remainEffectPercent); DEBUG_LOG(m_logger) << "PDM::EventType = " << request.pdmEventType << " 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); data.operationMode = static_cast(request.operationMode); data.reactivationDetoxication = request.reactivationDetoxication; data.reactivationMaintenance = request.reactivationMaintenance; data.reactivationMedic = request.reactivationMedic; data.modeVest = static_cast(request.protectionModeVest); data.modeHelmet = static_cast(request.protectionModeHelmet); data.personellProtectionMode = static_cast(request.personellProtection); data.protectionLevel = static_cast(request.protectionLevel); data.handgrenadeSearchMode = static_cast(request.handgrenadeSearchMode); data.internationalMode = static_cast(request.internationalMode); data.abcProtectionMode = static_cast(request.abcProtectionMode); 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); data.switchingPositionIntervall = static_cast(request.switchingPositionIntervall); // 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); // 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); 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); 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); 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; } }