#include "send_to_dds.h" #include #include "main_handler.h" #include "settings.h" #include #include #include namespace TrainingAreaBase { static constexpr const int s_PartyIdOffset = 1; SendToDds::SendToDds(MainHandler *mainHandler) : m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()) , m_mainHandler(mainHandler) , m_dtsTab(mainHandler->ddsHandler()->dtsTab()) , m_aesStateHandler(m_mainHandler->aesHandler() ? mainHandler->aesHandler()->aesStateHandler() : nullptr) , m_aesHandler(m_mainHandler->aesHandler()) , m_posHandler(mainHandler->posHandler()) {} template static inline void assignBase(const S &src, T &dest) { dest.equipmentNumber = src.header.equipmentNumber; dest.sampleTime = src.header.timeStamp; } void SendToDds::rxData(const TetraIcd::ManipulationReport &inData) { TrainingAreaBase::EquipmentOperationalState outData; checkTimeStamp(inData); assignBase(inData, outData); outData.isManipulation = inData.isManipulation; outData.equipmentFunctionId = inData.equipmentFunctionId; publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentOperationalState &inData) { TrainingAreaBase::EquipmentOperationalState outData; checkTimeStamp(inData); assignBase(inData, outData); outData.nbcProtectionActive = inData.nbcProtectionActive; publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentConfigurationReport &inData) { TrainingAreaBase::EquipmentConfigurationReport outData; checkTimeStamp(inData); assignBase(inData, outData); outData.equipmentNumber = inData.equipmentNumber; outData.canStartupTime = inData.canStartUpTime; outData.equipmentType = inData.equipmentType; outData.loginWaittimeBitweenTrys = inData.loginWaittimeBitweenTrys; outData.loginMaxRetryCount = inData.loginMaxRetryCnt; outData.loginMasteringFlag = inData.loginMasteringFlag; outData.canDeviceConfiguration = inData.canDeviceConfiguration; outData.displayDeviceVoiceOutput = inData.displayDeviceVoiceOutput; outData.displayDeviceLanguage = static_cast(inData.displayDeviceLanguage); outData.pyrotechnics = inData.pyrotechnics; outData.mineHandgrenadeSensorMode = static_cast(inData.mhgrsMode); outData.mineHandgrenadeSensorEnergySaving = inData.mhgrsEnergySaving; outData.firMode = static_cast(inData.specialSensorFir); outData.minelayerMode = static_cast(inData.specialSensorMinelayer); outData.specialSensorStandard = static_cast(inData.specialSensorStandard); outData.agdusHwMode = static_cast(inData.agdusHwMode); outData.positionUpdateIntervall = static_cast(inData.positionUpdateInterval); outData.displayTextMainGroup = inData.displayTextMainGroup; outData.displayTextSubGroup = inData.displayTextSubGroup; outData.vulnerabilityModelAgdus = inData.vulnerabilityModelAgdus; outData.vulnerabilityModelMineIed = inData.vulnerabilityModelMineIed; outData.vulnerabilityModelAreaFire = inData.vulnerabilityModelAreaFire; outData.vulnerabilityModelOperatingResource = inData.vulnerabilityModelOperatingResource; outData.vulnerabilityModelACWeaponry = inData.vulnerabilityModelAcWeaponry; publish(outData); } void SendToDds::rxData(const TetraIcd::CtaDataError &inData) { TrainingAreaBase::CtaDataError outData; checkTimeStamp(inData); assignBase(inData, outData); outData.reason = static_cast(inData.reason); outData.originTelegramId = inData.originTelegramId; publish(outData); } template void setOptionalBuildingRoomId(S &in, const T &out) { if (out > 0) in = out; } void SendToDds::rxData(const TetraIcd::PositionReport &inData) { TrainingAreaBase::EquipmentPosition outData; checkTimeStamp(inData); assignBase(inData, outData); if (!setPosition(outData, inData.geoPosition, inData.relPosition, inData.opsPosition, inData.header.timeStamp)) { ctasErrorPosition(inData); return; } publish(outData); } void SendToDds::rxData(const TetraIcd::PositionReportWithMountedEquipments &inData) { TrainingAreaBase::EquipmentPosition outData; checkTimeStamp(inData); assignBase(inData, outData); if (!setPosition(outData, inData.geoPosition, inData.relPosition, inData.opsPosition, inData.header.timeStamp)) { ctasErrorPosition(inData); return; } outData.mountedParticipants = inData.mountedEquipments; publish(outData); } void SendToDds::rxData(const TetraIcd::MineTriggered &inData) { TrainingAreaBase::MineTriggered outData; checkTimeStamp(inData); assignBase(inData, outData); outData.mineAreaId = inData.mineAreaId; outData.mineIndex = inData.mineIndex; if (inData.chargeTypeId != 0) outData.chargeTypeId = inData.chargeTypeId; if (inData.relPositionValid) { if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } } publish(outData); } template static inline void assignIedBaseData(const S &inData, T &outData) { assignBase(inData, outData); outData.iedId = inData.iedId; outData.tacticalState = static_cast(inData.tacticalState); outData.statePyrotechnics = inData.statePyrotechnics; } void SendToDds::rxData(const TetraIcd::DefinitionIed &inData) { TrainingAreaBase::DefinitionIed outData; checkTimeStamp(inData); assignIedBaseData(inData, outData); if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } outData.type = static_cast(inData.iedType); outData.remoteTrigger = (inData.trigger & static_cast(TetraIcd::DefinitionIed::TriggerTypes::Remote)) ? true : false; outData.switchTrigger = (inData.trigger & static_cast(TetraIcd::DefinitionIed::TriggerTypes::Switch)) ? true : false; outData.lightBarrierTrigger = (inData.trigger & static_cast(TetraIcd::DefinitionIed::TriggerTypes::LightBarrier)) ? true : false; outData.tautWireTrigger = (inData.trigger & static_cast(TetraIcd::DefinitionIed::TriggerTypes::TautWire)) ? true : false; outData.explosiveForce = inData.explosiveForce; outData.pairingState = static_cast(inData.pairingState); if (inData.pairingState != TrainingAreaBase::TetraIcd::IedPairingState::NotPaired) outData.pairedId = inData.pairedId; if (inData.partyId != 0) outData.partyId = inData.partyId + s_PartyIdOffset; publish(outData); } void SendToDds::rxData(const TetraIcd::StateIed &inData) { TrainingAreaBase::StateIed outData; checkTimeStamp(inData); assignIedBaseData(inData, outData); outData.batteryWarnings = inData.batteryWarnings; outData.errorStateElectronics = static_cast(inData.errorStateElectronics); outData.errorStatePyrotechnics1 = static_cast(inData.errorStatePyrotechnics1); outData.errorStatePyrotechnics2 = static_cast(inData.errorStatePyrotechnics2); outData.errorStatePyrotechnics3 = static_cast(inData.errorStatePyrotechnics3); publish(outData); } void SendToDds::rxData(const TetraIcd::DusSingleMineState &inData) { TrainingAreaBase::DusSingleMineState outData; checkTimeStamp(inData); assignBase(inData, outData); outData.mineId = inData.mineId; outData.effectStart = inData.effectStart; setPosition2d(outData, inData.relPosition); outData.chargeTypeId = inData.chargeTypeId; outData.state = inData.state; publish(outData); } void SendToDds::rxData(const TetraIcd::StateChangeDirect &inData) { if (Settings::laserRangeCode() == inData.chargeTypeId) { DEBUG_LOG(m_logger) << "laserRangeCode chargeTypeId=" << inData.chargeTypeId << "vulnerabilityState=" << static_cast(inData.vulnerabilityState); return; } TrainingAreaBase::EquipmentState outData; checkTimeStamp(inData); if (!assignStateChangeBase(inData, outData)) return; const auto ct(pdm()->chargeTypeFromId(inData.chargeTypeId)); if (!pdm()->isIndirect(inData.chargeTypeId)) if (!setPosition(outData, inData.geoPosition, inData.relPosition, inData.opsPosition, inData.header.timeStamp)) ctasErrorPosition(inData); const auto gearClass(pdm()->gearClassFromChargeTypeId(inData.chargeTypeId)); if (gearClass == ProjectDataManagement::GearClass::GearClass_MineSingle || gearClass == ProjectDataManagement::GearClass::GearClass_MineArea) { TetraIcd::MineTriggered mt; mt.header.timeStamp = inData.header.timeStamp; if (outData.position.has_value()) { const TrainingAreaBase::TabPosition pos = outData.position.get(); mt.relPosition = m_posHandler->geographicToRelative(pos.position); mt.relPositionValid = true; mt.chargeTypeId = ct.id; mt.mineIndex = inData.originatorId; rxData(mt); } outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_DusMine; } else { if (pdm()->isIedChargeType({ct.id,0,0,})) outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ImprovisedExplosiveDevice; else { if (m_mainHandler->ppmHandler()->getDtc()->participantIdByEquipmentNumber(inData.originatorId) <= 0) { if (m_mainHandler->ppmHandler()->getDtc()->party(inData.originatorId).id) outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Party; else outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Participant; } else outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Participant; } } outData.originatorId = inData.originatorId; outData.originatorChargeTypeId = inData.chargeTypeId; if (outData.originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_DusMine) QTimer::singleShot(10, this, [this, outData]() { publish(outData); }); else publish(outData); } void SendToDds::rxData(const TetraIcd::StateChangeIndirect &inData) { TrainingAreaBase::EquipmentState outData; checkTimeStamp(inData); if (!assignStateChangeBase(inData, outData)) return; if (!setPosition(outData, inData.geoPosition, inData.relPosition, inData.opsPosition, inData.header.timeStamp)) ctasErrorPosition(inData); outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_AreaEffectSimulation; outData.originatorId = inData.originatorId; if (m_aesHandler) { int offsetIndirectHit = inData.isSecondaryEffect ? 500 : 0; outData.originatorChargeTypeId = offsetIndirectHit + m_aesHandler->aesChargeId(outData.originatorId); } publish(outData); } void SendToDds::rxData(const TetraIcd::OperatorAction &inData) { TrainingAreaBase::OperatorAction outData; checkTimeStamp(inData); assignBase(inData, outData); outData.operatorId = inData.operatorId; outData.action = inData.action; publish(outData); } void SendToDds::rxData(const TetraIcd::StateChange &inData) { TrainingAreaBase::EquipmentState outData; checkTimeStamp(inData); if (!assignStateChangeBase(inData, outData)) return; switch (inData.originatorType) { case TrainingAreaBase::TetraIcd::OriginatorType::ObserverController: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ObserverController; break; case TrainingAreaBase::TetraIcd::OriginatorType::ExerciseControl: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ExerciseControl; break; case TrainingAreaBase::TetraIcd::OriginatorType::MedicTimeout: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_MedicalTimeout; break; case TrainingAreaBase::TetraIcd::OriginatorType::Sanitation: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Sanitation; break; case TrainingAreaBase::TetraIcd::OriginatorType::MedicDecontamination: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_WoundTreatmentDevice; break; case TrainingAreaBase::TetraIcd::OriginatorType::MaintainanceRepair: case TrainingAreaBase::TetraIcd::OriginatorType::MaintainanceDecontamination: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_MaintainanceDevice; break; case TrainingAreaBase::TetraIcd::OriginatorType::FunctionalArea: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_FunctionalArea; break; case TrainingAreaBase::TetraIcd::OriginatorType::Initialisation: outData.originatorType = ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Initialization; break; } outData.originatorId = inData.originatorId; publish(outData); } void SendToDds::rxData(const TetraIcd::FunctionalAreaEntry &inData) { TrainingAreaBase::FunctionalAreaEntry outData; checkTimeStamp(inData); assignBase(inData, outData); if (!setPosition2d(outData, inData.relPosition)) ctasErrorPosition(inData); outData.aesItemId = inData.aesDdsId; publish(outData); } void SendToDds::rxData(const TetraIcd::SpecialSensorData &inData) { TrainingAreaBase::SpecialSensorData outData; checkTimeStamp(inData); assignBase(inData, outData); if ((inData.relPosition.offsetX != 0 || inData.relPosition.offsetY != 0) && !setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } int operationalState = inData.operationalState & 0xFF; if (inData.airSensor) operationalState |= 1 << 8; if (inData.tireSensor) operationalState |= 1 << 9; if (inData.pointSensor) operationalState |= 1 << 10; if (inData.solidMatterSampleExtractor) operationalState |= 1 << 11; operationalState |= (inData.type & 0x0F) << 12; operationalState |= (inData.nbcType & 0x03) << 16; outData.operationalState = operationalState; publish(outData); } template static inline void assignMinelayerData(T &inData, TrainingAreaBase::MinelayerTrailerData &outData) { assignBase(inData, outData); outData.barrierId = inData.barrierId; outData.layingDensity = inData.layingDensity; outData.effectStart = inData.effectStart; outData.effectDuration = inData.effectDuration; outData.mineCount = inData.mineCount; } void SendToDds::rxData(const TetraIcd::MinelayerTrailerData &inData) { TrainingAreaBase::MinelayerTrailerData outData; checkTimeStamp(inData); assignMinelayerData(inData, outData); outData.chargeTypeId = m_mainHandler->pdmHandler()->chargeTypeFromId(inData.indirectChargeTasCode).id; if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } publish(outData); } void SendToDds::rxData(const TetraIcd::MinelayerThrowerData &inData) { TrainingAreaBase::MinelayerThrowerData outData; checkTimeStamp(inData); assignMinelayerData(inData, outData); outData.chargeTypeId = m_mainHandler->pdmHandler()->chargeTypeFromId(inData.indirectChargeTasCode).id; if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } outData.throwingType = static_cast(inData.throwingType); publish(outData); } void SendToDds::rxData(const TetraIcd::MinelayerTrailerPosition &inData) { TrainingAreaBase::MinelayerTrailerPosition outData; checkTimeStamp(inData); assignBase(inData, outData); outData.dusSerialNo = inData.dusSerialNo; outData.chargeTypeId = m_mainHandler->pdmHandler()->chargeTypeFromId(inData.indirectChargeTasCode).id; if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } publish(outData); } void SendToDds::rxData(const TetraIcd::BiteReport &inData) { TrainingAreaBase::EquipmentBite outData; checkTimeStamp(inData); assignBase(inData, outData); outData.registerType = static_cast(inData.loginType); outData.biteState = inData.biteState; outData.configState = inData.configState; outData.batteryState = inData.batteryState; outData.configError = inData.configError; outData.biteErrors.resize(inData.biteErrors.size()); TrainingAreaBase::EquipmentBiteError ebe; for (size_t i = 0; i < inData.biteErrors.size(); ++i) { const TetraIcd::BiteError &be = inData.biteErrors.at(i); ebe.canDeviceNumber = be.canDeviceNumber; ebe.errorNumber = be.errorNumber; ebe.uniqueId = be.uniqueId; ebe.subdeviceNumber = be.subdeviceNumber; outData.biteErrors[i] = ebe; } publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentEvent &inData) { TrainingAreaBase::EquipmentEvent outData; checkTimeStamp(inData); assignBase(inData, outData); if (!setPosition2d(outData, inData.relPosition)) ctasErrorPosition(inData); TrainingAreaBase::Equipment src; src.equipmentFunctionId = inData.equipmentFunctionId; src.subDeviceId = inData.subDeviceId; src.unqiueId = inData.uniqueId; outData.source = src; outData.code = inData.code; outData.data = inData.payload; publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentGearAssignment &inData) { TrainingAreaBase::EquipmentGearAssignment outData; checkTimeStamp(inData); assignBase(inData, outData); outData.gears.resize(inData.gears.size()); TrainingAreaBase::Gear tabGear; for (size_t i = 0; i < inData.gears.size(); ++i) { const TetraIcd::Gear &gear = inData.gears.at(i); tabGear.gearId = gear.gearSerialNumber; tabGear.gearTypeId = pdm()->gearTypeIdFromTasGearTasCode(gear.gearTasCode); tabGear.chargeCounting = gear.chargeCounting; outData.gears[i] = tabGear; } publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentGearChargeState &inData) { TrainingAreaBase::EquipmentGearChargeState outData; checkTimeStamp(inData); assignBase(inData, outData); outData.charge.resize(inData.charges.size()); TrainingAreaBase::GearCharge tabGr; for (size_t i = 0; i < inData.charges.size(); ++i) { const TetraIcd::GearCharge &gr = inData.charges.at(i); tabGr.gearId = gr.gearSerialNumber; tabGr.gearTypeId = pdm()->gearTypeIdFromTasGearTasCode(gr.gearTasCode); tabGr.remain = gr.remain; tabGr.chargeTypeId = pdm()->chargeTypeIdFromGearAndChargeTasCode(tabGr.gearTypeId, gr.chargeTypeId); if (gr.gearSerialNumber == 0 && gr.gearTasCode == 0) tabGr.gearId = gr.location; outData.charge[i] = tabGr; } publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentGearEvent &inData) { TrainingAreaBase::EquipmentGearEvent outData; checkTimeStamp(inData); assignBase(inData, outData); outData.chargeAmount = inData.chargeAmount; TrainingAreaBase::GearCharge tabGr; tabGr.gearId = inData.charge.gearSerialNumber; tabGr.gearTypeId = pdm()->gearTypeIdFromTasGearTasCode(inData.charge.gearTasCode); tabGr.remain = inData.charge.remain; tabGr.chargeTypeId = pdm()->chargeTypeIdFromGearAndChargeTasCode(tabGr.gearTypeId, inData.charge.chargeTypeId); outData.charge = tabGr; publish(outData); } void SendToDds::rxData(const TetraIcd::ParticipantSwVersions &inData) { TrainingAreaBase::ParticipantSwVersions outData; checkTimeStamp(inData); assignBase(inData, outData); outData.equipments.resize(inData.equipments.size()); TrainingAreaBase::EquipmentSwVersion eqpmt; for (size_t i = 0; i < inData.equipments.size(); ++i) { const TetraIcd::EquipmentSwVersion data = inData.equipments.at(i); eqpmt.equipmentFunctionId = data.equipmentFunctionId; eqpmt.subDeviceId = data.subDeviceId; eqpmt.unqiueId = data.uniqueId; eqpmt.swVersion = data.swVersion; outData.equipments[i] = eqpmt; } publish(outData); } void SendToDds::rxData(const TetraIcd::EquipmentMessageOC &inData) { TrainingAreaBase::EquipmentMessage outData; checkTimeStamp(inData); assignBase(inData, outData); outData.subject = inData.subject; outData.text = inData.message; outData.sender = inData.senderId; outData.receiver = inData.receiverId; publish(outData); } void SendToDds::rxData(const TetraIcd::OpaquePayloadDataIn &inData) { switch (inData.payloadType) { case TetraIcd::OpaquePayloadDataIn::Type::FireSmokeMarker: { TrainingAreaBase::FireSmokeMarkerData outData; assignBase(inData, outData); outData.payload = inData.payload; publish(outData); break; } case TetraIcd::OpaquePayloadDataIn::Type::Geopairing: { TrainingAreaBase::GeopairingData outData; checkTimeStamp(inData); assignBase(inData, outData); if (!setPosition2d(outData, inData.relPosition)) { ctasErrorPosition(inData); return; } outData.payload = inData.payload; publish(outData); break; } case TetraIcd::OpaquePayloadDataIn::Type::Target: { TrainingAreaBase::TargetData outData; assignBase(inData, outData); outData.payload = inData.payload; publish(outData); break; } case TetraIcd::OpaquePayloadDataIn::Type::OC: { TrainingAreaBase::OcData outData; assignBase(inData, outData); outData.payload = inData.payload; publish(outData); } } } void SendToDds::rxData(const TetraIcd::ParticipantModeReport &inData) { TrainingAreaBase::ParticipantModeReport outData; checkTimeStamp(inData); assignBase(inData, outData); outData.language = static_cast(inData.language); outData.operationMode = static_cast(inData.operationMode); outData.reactivationDetoxication = inData.reactivationDetoxication; outData.reactivationMaintenance = inData.reactivationMaintenance; outData.reactivationMedic = inData.reactivationMedic; outData.protectionModeVest = static_cast(inData.modeVest); outData.protectionModeHelmet = static_cast(inData.modeHelmet); outData.personellProtectionMode = static_cast(inData.personellProtectionMode); outData.protectionLevel = static_cast(inData.protectionLevel); outData.handgrenadeSearchMode = static_cast(inData.handgrenadeSearchMode); outData.internationalMode = static_cast(inData.internationalMode); outData.abcProtectionMode = static_cast(inData.abcProtectionMode); publish(outData); } void SendToDds::rxData(const TetraIcd::ParticipantConfigurationReport &inData) { TrainingAreaBase::ParticipantConfigurationReport outData; checkTimeStamp(inData); assignBase(inData, outData); outData.positionIntervallVehicle = inData.positionIntervallVehicle; outData.positionIntervallPersonell = inData.positionIntervallPersonell; outData.positionIntervallAircraft = inData.positionIntervallAircraft; outData.positionTransmissionIntervall = inData.positionTransmissionIntervall; outData.heightbarrier = inData.heightbarrier; outData.faultPositionHandling = static_cast(inData.faultPositionHandling); outData.switchingPositionIntervall = static_cast(inData.switchingPositionIntervall); outData.waittimeAdditionalBroadcastRequest = inData.waittimeAdditionalBroadcastDemand; outData.factorWaittimeIncreaseHighload = inData.factorWaittimeIncreaseAtHighload; outData.waittimeAutomaticVulnerbilityIncreaseLevel1 = inData.waittimeAutomaticVulnerabilityIncreaseLevel1; outData.waittimeAutomaticVulnerbilityIncreaseLevel2 = inData.waittimeAutomaticVulnerabilityIncreaseLevel2; outData.waittimeAutomaticVulnerbilityIncreaseLevel3 = inData.waittimeAutomaticVulnerabilityIncreaseLevel3; outData.opticalCode = static_cast(inData.opticalCode); outData.vulnerabilityModel = inData.vulnerabilityModel; outData.validTimeOps = inData.validTimeOps; publish(outData); } void SendToDds::rxData(const TetraIcd::EmergencyCall &inData) { TrainingAreaBase::EmergencyCall outData; outData.equipmentNumber = inData.issi; outData.sampleTime = inData.timeStamp; const Core::GeoPosition2D pos(inData.absPosition.lon, inData.absPosition.lat); outData.position = pos; m_mainHandler->ddsHandler()->emergencyCall()->write(outData); QTimer *t = m_emergencyCallTimer[inData.issi]; if (!t) { t = new QTimer(this); t->setInterval(30 * 1000); const int issi = inData.issi; connect(t, &QTimer::timeout, this, [this, issi]() { onEmergencyCallTimerTimeout(issi); }); m_emergencyCallTimer[inData.issi] = t; } t->start(); } void SendToDds::rxData(const TetraIcd::SanitationRepair &inData) { TrainingAreaBase::ParticipantSanitationRepair sanRepair; sanRepair.equipmentNumber = inData.header.equipmentNumber; sanRepair.sampleTime = inData.header.timeStamp; sanRepair.originatorType = static_cast(inData.originatorType); sanRepair.equipmentNumberOrigin = inData.equipmentNumberOrigin; sanRepair.stateStart = static_cast(inData.stateStart); sanRepair.typeOfTreatment = inData.typeOfTreatment; sanRepair.triage = inData.triage; sanRepair.tyeOfDamage = inData.tyeOfDamage; sanRepair.stateResult = static_cast(inData.stateResult); sanRepair.treatmentResult = static_cast(inData.treatmentResult); sanRepair.triagePriority = inData.triagePriority; sanRepair.fullState = inData.fullState; sanRepair.timeOfTreatment = inData.timeOfTreatment; sanRepair.timeOfRecovery = inData.timeOfRecovery; publish(sanRepair); } void SendToDds::rxData(const TetraIcd::SanitaryMaterialStockReport &inData) { TrainingAreaBase::ParticipantSanitaryMaterialStockReport sanReport; sanReport.equipmentNumber = inData.header.equipmentNumber; sanReport.sampleTime = inData.header.timeStamp; sanReport.sanitaryMaterialCount = inData.sanitaryMaterialCount; sanReport.sanitaryMaterialStock = inData.sanitaryMaterialStock; sanReport.uniqueId = inData.uniqueId; sanReport.originatorEquipmentNumber = inData.originatorEquipmentNumber; sanReport.qualification = static_cast(inData.qualification); publish(sanReport); DEBUG_LOG(m_logger) << "SendToDds::rxData(const TetraIcd::SanitaryMaterialStockReport for " << sanReport.equipmentNumber; if (sanReport.qualification == TrainingAreaBase::Qualification::NotDefined) { int oldEquipNo = m_uniqueId2EquipmentNumber.value(sanReport.uniqueId); if (oldEquipNo > 0) { TrainingAreaBase::ParticipantSanitation sanitation; sanitation.equipmentNumber = oldEquipNo; sanitation.sampleTime = sanReport.sampleTime; sanitation.proceduresTaken = 0; sanitation.uniqueId = sanReport.uniqueId; sanitation.originatorEquipmentNumber = 0; sanitation.qualification = TrainingAreaBase::Qualification::NotDefined; sanitation.sanitationResult = TrainingAreaBase::SanitationResult::NoEffect; sanitation.sanitationEvaluation = TrainingAreaBase::SanitationEvaluation::NotApplicable; publish(sanitation); } m_uniqueId2EquipmentNumber.remove(sanReport.uniqueId); } onPvSanUniqueIdMapping(sanReport.uniqueId, sanReport.equipmentNumber, sanReport.sampleTime); } void SendToDds::rxData(const TetraIcd::Sanitation &inData) { TrainingAreaBase::ParticipantSanitation sanitation; sanitation.equipmentNumber = inData.header.equipmentNumber; sanitation.sampleTime = inData.header.timeStamp; sanitation.proceduresTaken = inData.proceduresTaken; sanitation.uniqueId = inData.uniqeId; sanitation.originatorEquipmentNumber = inData.originatorEquipmentNumber; sanitation.qualification = static_cast(inData.qualification); sanitation.sanitationResult = static_cast(inData.sanitationResult); sanitation.sanitationEvaluation = static_cast(inData.sanitationEvaluation); publish(sanitation); DEBUG_LOG(m_logger) << "SendToDds::rxData(const TetraIcd::Sanitation for " << sanitation.equipmentNumber; if (sanitation.qualification == TrainingAreaBase::Qualification::NotDefined) { TrainingAreaBase::ParticipantSanitaryMaterialStockReport sanReport; sanReport.equipmentNumber = sanitation.equipmentNumber; sanReport.sampleTime = sanitation.sampleTime; sanReport.sanitaryMaterialCount = 0; sanReport.sanitaryMaterialStock = std::vector(); sanReport.uniqueId = sanitation.uniqueId; sanReport.originatorEquipmentNumber = 0; sanReport.qualification = TrainingAreaBase::Qualification::NotDefined; publish(sanReport); m_uniqueId2EquipmentNumber.remove(sanitation.uniqueId); } else onPvSanUniqueIdMapping(sanitation.uniqueId, sanitation.equipmentNumber, sanitation.sampleTime); } void SendToDds::rxData(const TetraIcd::ApacheLaserDesignation &inData) { TrainingAreaBase::LaserDesignation laserDesignation; laserDesignation.equipmentNumber = inData.header.equipmentNumber; laserDesignation.sampleTime = inData.header.timeStamp; laserDesignation.spotLocation = Core::GeoPosition2D(inData.spotLocation.lon, inData.spotLocation.lat); laserDesignation.outputPower = inData.outputPower; laserDesignation.code = inData.code; laserDesignation.gearId = inData.gearId; publish(laserDesignation); } template void SendToDds::ctasErrorPosition(const S &data) { TrainingAreaBase::CtaDataError error; error.equipmentNumber = data.header.equipmentNumber; error.sampleTime = data.header.timeStamp; error.reason = ProjectDataManagement::DataErrorReason::DataErrorReason_InvalidPosition; error.originTelegramId = data.id(); publish(error); } void SendToDds::rxData(const TetraIcd::BatteryInfo &inData) { TrainingAreaBase::BatteryInfo batteryInfo; batteryInfo.equipmentNumber = inData.header.equipmentNumber; batteryInfo.sampleTime = inData.header.timeStamp; std::vector batteryStates; batteryStates.reserve(inData.batteryStates.size()); for(const TetraIcd::BatteryState &batState : std::as_const(inData.batteryStates)) { TrainingAreaBase::BatteryState batStateOut; batStateOut.batteryPort = batState.batteryPort(); batStateOut.batteryPercent = batState.batteryPercent(); batStateOut.current = batState.current(); batStateOut.frequency = batState.frequency(); batStateOut.generic = batState.generic(); batStateOut.serialNumber = batState.serialNumber().toStdString(); batStateOut.switchOrValue = batState.switchOrValue(); batStateOut.temperature = batState.temperature(); batStateOut.voltage = batState.voltage(); batteryStates.push_back(batStateOut); } batteryInfo.batteryStates = batteryStates; publish(batteryInfo); } void SendToDds::rxData(const TetraIcd::BatteryAlarm &inData) { TrainingAreaBase::BatteryAlarm batAlarm; batAlarm.acknowledge = inData.acknowledge(); batAlarm.alarmTime = inData.alarmTime(); batAlarm.condition = inData.condition(); batAlarm.description = inData.description().toStdString(); batAlarm.batteryPort = inData.id(); batAlarm.uniqueAlarmNumber = inData.uniqueAlarmNumber(); batAlarm.equipmentNumber = inData.header().equipmentNumber; batAlarm.sampleTime = inData.header().timeStamp; publish(batAlarm); } void SendToDds::rxData(const TetraIcd::ServiceControl &inData) { TrainingAreaBase::ServiceControl serviceControl; serviceControl.equipmentNumber = inData.header.equipmentNumber; serviceControl.sampleTime = inData.header.timeStamp; serviceControl.serviceControlState = static_cast(inData.serviceControlState); publish(serviceControl); } void SendToDds::rxData(const TetraIcd::RestoreRadioReadiness &inData) { struct PositionStruct { int equipmentNumber; Core::GeoPosition2D position; }; RestoreRadioReadiness restoreRadioReadiness; restoreRadioReadiness.equipmentNumber = inData.header.equipmentNumber; restoreRadioReadiness.sampleTime = inData.header.timeStamp; restoreRadioReadiness.readinessLossPosition = m_posHandler->relativeToGeographic(inData.readinessLossPosition); restoreRadioReadiness.readinessLossTime = inData.readinessLossTime; restoreRadioReadiness.readinessRestorePosition = m_posHandler->relativeToGeographic(inData.readinessRestorePosition); restoreRadioReadiness.readinessRestoreTime = inData.readinessRestoreTime; publish(restoreRadioReadiness); } void SendToDds::rxData(const TetraIcd::UAVRadioLinkConnectionStatus &inData) { TrainingAreaBase::UASRadioLinkConnectionState outData; assignBase(inData, outData); switch (inData.uavConnectionState) { case TetraIcd::UAVRadioLinkConnectionStatusType::Connected: outData.connectionStatus = ProjectDataManagement::UasState::UasState_On; break; case TetraIcd::UAVRadioLinkConnectionStatusType::Disconnected: outData.connectionStatus = ProjectDataManagement::UasState::UasState_Off; break; case TetraIcd::UAVRadioLinkConnectionStatusType::Connecting: outData.connectionStatus = ProjectDataManagement::UasState::UasState_Init; break; case TetraIcd::UAVRadioLinkConnectionStatusType::Diconnecting: outData.connectionStatus = ProjectDataManagement::UasState::UasState_Shutdown; break; case TetraIcd::UAVRadioLinkConnectionStatusType::Error: outData.connectionStatus = ProjectDataManagement::UasState::UasState_Undefined; break; case TetraIcd::UAVRadioLinkConnectionStatusType::Undefined: outData.connectionStatus = ProjectDataManagement::UasState::UasState_Undefined; break; } publish(outData); } void SendToDds::rxData(const TetraIcd::UAVMissionStatus &inData) { TrainingAreaBase::UASMissionStatus outData; assignBase(inData, outData); switch (inData.currentAction) { case TetraIcd::UAVActionTask::Undefined: outData.currentTask = ProjectDataManagement::UasActionTask::Undefined; break; case TetraIcd::UAVActionTask::Disarm: outData.currentTask = ProjectDataManagement::UasActionTask::Disarm; break; case TetraIcd::UAVActionTask::Arm: outData.currentTask = ProjectDataManagement::UasActionTask::Arm; break; case TetraIcd::UAVActionTask::Takeoff: outData.currentTask = ProjectDataManagement::UasActionTask::Takeoff; break; case TetraIcd::UAVActionTask::Connect: outData.currentTask = ProjectDataManagement::UasActionTask::Connect; break; case TetraIcd::UAVActionTask::Loiter: outData.currentTask = ProjectDataManagement::UasActionTask::Loiter; break; case TetraIcd::UAVActionTask::Return: outData.currentTask = ProjectDataManagement::UasActionTask::Return; break; case TetraIcd::UAVActionTask::Observe: outData.currentTask = ProjectDataManagement::UasActionTask::Observe; break; } outData.currentMissionName = inData.currentMissionName.toStdString(); outData.missionEnded = inData.missionEnded.toStdString(); publish(outData); } void SendToDds::rxData(const TetraIcd::UAVStatus &inData) { TrainingAreaBase::UASStatus outData; assignBase(inData, outData); switch (inData.uavState) { case TetraIcd::UAVState::On: outData.uasState = ProjectDataManagement::UasState::UasState_On; break; case TetraIcd::UAVState::Off: outData.uasState = ProjectDataManagement::UasState::UasState_Off; break; case TetraIcd::UAVState::Init: outData.uasState = ProjectDataManagement::UasState::UasState_Init; break; case TetraIcd::UAVState::Shutdown: outData.uasState = ProjectDataManagement::UasState::UasState_Shutdown; break; case TetraIcd::UAVState::Calibrating: outData.uasState = ProjectDataManagement::UasState::UasState_Calibrating; break; case TetraIcd::UAVState::Manual: outData.uasState = ProjectDataManagement::UasState::UasState_Manual; break; case TetraIcd::UAVState::Maintenance: outData.uasState = ProjectDataManagement::UasState::UasState_Maintenance; break; case TetraIcd::UAVState::Standby: outData.uasState = ProjectDataManagement::UasState::UasState_Standby; break; case TetraIcd::UAVState::Normal: outData.uasState = ProjectDataManagement::UasState::UasState_Normal; break; case TetraIcd::UAVState::Auto: outData.uasState = ProjectDataManagement::UasState::UasState_Auto; break; case TetraIcd::UAVState::Undefined: outData.uasState = ProjectDataManagement::UasState::UasState_Undefined; break; } publish(outData); } template bool SendToDds::setPosition(T &data, const TetraIcd::AbsolutePosition &geoPos, const TetraIcd::RelativePosition &relPos, const TetraIcd::OpsPosition &opsPos, const qint64 timeStamp) const { bool bRet = true; bool moutCheck = true; TrainingAreaBase::TabPosition tabPos; if (geoPos.isValid()) { tabPos.position = Core::GeoPosition(geoPos.lon, geoPos.lat, geoPos.z); setOptionalBuildingRoomId(tabPos.moutObjectId, opsPos.moutObjectId); setOptionalBuildingRoomId(tabPos.moutRoomId, opsPos.moutRoomId); const bool bWlsLocationLost = opsPos.moutObjectId == -2 && opsPos.moutRoomId == -2; if (bWlsLocationLost) { TrainingAreaBase::TabPosition lastTabPos = m_posHandler->lastPosition(data.equipmentNumber); if (lastTabPos.reportingSource == Core::PositionReportingSource::Wls || std::isnan(lastTabPos.position.lon)) tabPos.reportingSource = Core::PositionReportingSource::Gps; else std::swap(tabPos, lastTabPos); } else tabPos.reportingSource = Core::PositionReportingSource::Wls; } else if (opsPos.opsId == 0) { bool changeReportSource = true; DEBUG_LOG(m_logger) << "ops == 0 so check for marked invalid to use last position!"; if (PositionHandler::isPositionMarkedInvalid(relPos)) { tabPos = m_posHandler->lastPosition(data.equipmentNumber); DEBUG_LOG(m_logger) << "ops == 0 got last Position its source is " << tabPos.reportingSource; if (tabPos.reportingSource != Core::PositionReportingSource::Wls && tabPos.reportingSource != Core::PositionReportingSource::Ops && tabPos.reportingSource != Core::PositionReportingSource::OpsTunnel) tabPos = TrainingAreaBase::TabPosition(); else if (tabPos.reportingSource == Core::PositionReportingSource::Ops || tabPos.reportingSource == Core::PositionReportingSource::OpsTunnel) changeReportSource = false; DEBUG_LOG(m_logger) << "ops == 0 changeSource is " << changeReportSource ; } else { if (!m_posHandler->isInTrainingArea(relPos)) { DEBUG_LOG(m_logger) << "bret = false"; bRet = false; } tabPos.position = m_posHandler->relativeToGeographic(relPos); setOptionalBuildingRoomId(tabPos.moutObjectId, opsPos.moutObjectId); setOptionalBuildingRoomId(tabPos.moutRoomId, opsPos.moutRoomId); TrainingAreaBase::TabPosition lastPosition = m_posHandler->lastPosition(data.equipmentNumber); { DEBUG_LOG(m_logger) << "lastPosition.reportingSource=" << lastPosition.reportingSource; } if (lastPosition.reportingSource == Core::PositionReportingSource::Ops && lastPosition.moutObjectId.has_value()) { DEBUG_LOG(m_logger) << "Check leave Building equipmentNumber=" << data.equipmentNumber; DEBUG_LOG(m_logger) << "relPos=" << relPos.offsetX << "/" << relPos.offsetY; DEBUG_LOG(m_logger) << "posInExtendedBuildingFootprint"; const Core::GeoPosition &position = tabPos.position; int moutObjectId = lastPosition.moutObjectId.get(); const int lastMountPointTypeId = m_posHandler->lastMountPointTypeId(data.equipmentNumber); if (ism()->posInExtendedBuildingFootprint(moutObjectId, position, lastMountPointTypeId)) { moutCheck = false; bRet = false; } else { DEBUG_LOG(m_logger) << "lastMountPointTypeId =" << m_posHandler->lastMountPointTypeId(data.equipmentNumber); if ( m_posHandler->lastMountPointTypeId(data.equipmentNumber) == static_cast(InfrastructureManagement::MountingPointType::IndoorIPS)) { double speed = m_posHandler->speed(relPos, data.equipmentNumber, timeStamp); bool checkSpeed = !m_posHandler->isTimeToPerformSpeedCheckExceeded(data.equipmentNumber, timeStamp, Settings::maxSpeedCheckTimeout()); DEBUG_LOG(m_logger) << "Check Speed speed=" << speed << " MaxSoldierSpeed=" << Settings::maxSoldierSpeed() << " checkSpeed=" << checkSpeed; if (checkSpeed && speed > Settings::maxSoldierSpeed()) { DEBUG_LOG(m_logger) << "Check Speed bRet = false"; bRet = false; moutCheck = false; } } else { DEBUG_LOG(m_logger) << "Kein Speed check!"; } } } } if (changeReportSource) tabPos.reportingSource = Core::PositionReportingSource::Gps; } else { INFO_LOG(m_logger) << "Valid OpsData: " << opsPos.opsId; IsmHandler::OpsData opsData; if (ism()) { opsData = ism()->dataFromOpsCode(opsPos.opsId); DEBUG_LOG(m_logger) << "equipmentNumber=" << data.equipmentNumber << " AssetId=" << opsData.assetId << " opsData.structureElementId=" << opsData.structureElementId << " opsData.mseId=" << opsData.mainStructureElementId << " opsData.mptTypeId=" << opsData.mountingPointTypeId; if ( opsData.structureElementId != 0) m_posHandler->setLastMountPointTypeId(data.equipmentNumber, opsData.mountingPointTypeId); } if (opsData.opsCode != opsPos.opsId) { WARNING_LOG(m_logger) << "found no position data for ops id " << opsPos.opsId; bRet = false; } else if (opsData.structureElementId == 0) { WARNING_LOG(m_logger) << "ops id " << opsPos.opsId << " is not mounted"; bRet = false; } else { DEBUG_LOG(m_logger) << "ops id " << opsPos.opsId; tabPos.moutObjectId = opsData.mainStructureElementId; tabPos.moutRoomId = opsData.roomId; tabPos.position = opsData.position; m_posHandler->setLastBuildingId(data.equipmentNumber, opsData.mainStructureElementId); m_posHandler->setLastRoomId(data.equipmentNumber, opsData.roomId); } if (opsData.opsTunnel) tabPos.reportingSource = Core::PositionReportingSource::OpsTunnel; else tabPos.reportingSource = Core::PositionReportingSource::Ops; } if (!bRet) { if ( moutCheck ) { DEBUG_LOG(m_logger) << "POS = ungueltig"; tabPos.position.lon = nan(""); tabPos.position.lat = nan(""); } else { DEBUG_LOG(m_logger) << "POS = ungueltig => alte Pos mit aktueller Zeit verschicken"; TrainingAreaBase::TabPosition lastPosition = m_posHandler->lastPosition(data.equipmentNumber); tabPos.position.lon = lastPosition.position.lon; tabPos.position.lat = lastPosition.position.lat; tabPos.position.z = lastPosition.position.z; tabPos.reportingSource = Core::PositionReportingSource::OpsBuilding; tabPos.moutObjectId = m_posHandler->lastBuildingId(data.equipmentNumber); tabPos.moutRoomId = m_posHandler->lastRoomId(data.equipmentNumber); bRet = true; } } else { DEBUG_LOG(m_logger) << "set last Position"; if (tabPos.reportingSource == Core::PositionReportingSource::Ops) DEBUG_LOG(m_logger) << "ReportingSource=OPS"; else if (tabPos.reportingSource == Core::PositionReportingSource::Gps) DEBUG_LOG(m_logger) << "ReportingSource=GPS"; DEBUG_LOG(m_logger) << "tabPos.reportingSource=" << tabPos.reportingSource << " timeStamp=" << timeStamp; m_posHandler->setLastPosition(data.equipmentNumber, tabPos); m_posHandler->setLastTime(data.equipmentNumber, timeStamp); } data.position = tabPos; return bRet; } template bool SendToDds::setPosition2d(T &data, const TetraIcd::RelativePosition &relPos) const { TrainingAreaBase::TabPosition tabPos; bool bRet = true; if (PositionHandler::isPositionMarkedInvalid(relPos)) tabPos = m_posHandler->lastPosition(data.equipmentNumber); else { if (!m_posHandler->isInTrainingArea(relPos)) bRet = false; DEBUG_LOG(m_logger) << "tabPos.reportingSource=" << tabPos.reportingSource; tabPos.position = m_posHandler->relativeToGeographic(relPos); m_posHandler->setLastPosition(data.equipmentNumber, tabPos); } Core::GeoPosition2D pos2d; pos2d.lat = tabPos.position.lat; pos2d.lon = tabPos.position.lon; data.position = pos2d; return bRet; } template bool SendToDds::assignStateChangeBase(const S &inData, T &outData) { assignBase(inData, outData); if (inData.vulnerabilityState < TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady || inData.vulnerabilityState > TrainingAreaBase::TetraIcd::VulnerabilityState::VulnerabilityBitsChanged) { TrainingAreaBase::CtaDataError error; assignBase(inData, error); error.reason = ProjectDataManagement::DataErrorReason::DataErrorReason_InvalidTacticalState; error.originTelegramId = inData.id(); publish(error); return false; } outData.vulnerabilityState = static_cast(inData.vulnerabilityState); outData.vulnerabilityKindId = pdm()->vulnerabilityKindId(inData.tasVulnerabilityKindId, inData.header.equipmentNumber); outData.vitality = inData.tasVitality; outData.vulnerabilityBits = inData.vulnerabilityBits; return true; } template void SendToDds::checkTimeStamp(const S &data) { const auto partTime = m_mainHandler->ddsHandler()->partitionTime(); if (data.header.timeStamp > (partTime + Settings::timeDelayAhead()) || data.header.timeStamp < (partTime - Settings::timeDelayBack())) { TrainingAreaBase::CtaDataError error; error.equipmentNumber = data.header.equipmentNumber; error.sampleTime = data.header.timeStamp; error.reason = ProjectDataManagement::DataErrorReason::DataErrorReason_InvalidTime; error.originTelegramId = data.id(); publish(error); } } std::shared_ptr SendToDds::ism() const { return m_mainHandler->ismHandler(); } std::shared_ptr SendToDds::pdm() const { return m_mainHandler->pdmHandler(); } template void SendToDds::publish(const T &data) { try { m_dtsTab->publish(data); } catch (const std::exception &ex) { WARNING_LOG(m_logger) << "Could not send telegram: " << ex.what(); } } void SendToDds::onEmergencyCallTimerTimeout(int issi) { auto it = m_emergencyCallTimer.find(issi); if (it == m_emergencyCallTimer.end()) return; delete it.value(); m_emergencyCallTimer.erase(it); if (m_mainHandler->ddsHandler()->emergencyCall()) { TrainingAreaBase::EmergencyCall emergCallData; emergCallData.equipmentNumber = issi; if (!m_mainHandler->ddsHandler()->emergencyCall()->remove(emergCallData)) ERROR_LOG(m_logger) << Q_FUNC_INFO << " removing of TrainingAreaBase::EmergencyCall failed, issi = " << issi; } } void SendToDds::onPvSanUniqueIdMapping(int uniqueId, int equipNo, qint64 sampleTime) { DEBUG_LOG(m_logger) << Q_FUNC_INFO << "start pvSan mapping " << equipNo << " uniqueId " << uniqueId; if (m_uniqueId2EquipmentNumber.value(uniqueId) == equipNo) return; if (!m_uniqueId2EquipmentNumber.contains(uniqueId)) { m_uniqueId2EquipmentNumber.insert(uniqueId, equipNo); return; } int oldEquipNo = m_uniqueId2EquipmentNumber.value(uniqueId); if (oldEquipNo > 0) { TrainingAreaBase::ParticipantSanitaryMaterialStockReport sanReport; sanReport.equipmentNumber = oldEquipNo; sanReport.sampleTime = sampleTime; sanReport.sanitaryMaterialCount = 0; sanReport.sanitaryMaterialStock = std::vector(); sanReport.uniqueId = uniqueId; sanReport.originatorEquipmentNumber = 0; sanReport.qualification = TrainingAreaBase::Qualification::NotDefined; publish(sanReport); TrainingAreaBase::ParticipantSanitation sanitation; sanitation.equipmentNumber = oldEquipNo; sanitation.sampleTime = sampleTime; sanitation.proceduresTaken = 0; sanitation.uniqueId = uniqueId; sanitation.originatorEquipmentNumber = 0; sanitation.qualification = TrainingAreaBase::Qualification::NotDefined; sanitation.sanitationResult = TrainingAreaBase::SanitationResult::NoEffect; sanitation.sanitationEvaluation = TrainingAreaBase::SanitationEvaluation::NotApplicable; publish(sanitation); m_uniqueId2EquipmentNumber.insert(uniqueId, equipNo); } } }