Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/GuezIedManagement/handler_ied.cpp
T

368 lines
10 KiB
C++
Executable File

/**
* Handler definition and state IED
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLEA, 2017-07-20
*/
#include "handler_ied.h"
#include "object_ied.h"
#include "main_handler.h"
#include "gim_db.h"
#include <Proxies/TrainingAreaBase/tab_dtc.h>
#include <QtCore/QCoreApplication>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <ngldb/dbtransaction.h>
#include <ngldb/nsqlquery.h>
#include <GuezIedManagement/gim_record_replay_plugin.h>
namespace GuezIedManagement
{
HandlerIed::HandlerIed(MainHandler *mainHandler,
const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
QObject *parent)
: QObject(parent)
, Interface::Fts::PairIedRequestHandler(ddsHandler->fts())
, m_mainHandler(mainHandler)
, m_ddsHandler(ddsHandler)
, m_tabDtc(nullptr)
, m_ppmDtc(nullptr)
, m_db(db)
, m_logger(getLogger("HandlerIed"))
{}
HandlerIed::~HandlerIed()
{
qDeleteAll(m_iedObjMap);
m_db = nullptr;
m_tabDtc = nullptr;
m_ppmDtc = nullptr;
m_ddsHandler = nullptr;
}
bool HandlerIed::init()
{
// initialize PPM DTC
m_ppmDtc = ParticipantManagement::Interface::Dtc::create(m_ddsHandler->dds());
if (!m_ppmDtc->enableParticipantPosition())
{
ERROR_LOG(m_logger) << "PPM DTC enableParticipantPosition() failed.";
return false;
}
if (!m_ppmDtc->enableParticipant())
{
ERROR_LOG(m_logger) << "PPM DTC enableParticipant() failed.";
return false;
}
if (!m_ppmDtc->enableParty())
{
ERROR_LOG(m_logger) << "PPM DTC enableParty() failed.";
return false;
}
QVector<Database::GimIed> dataVec;
// read all Ieds from database
if (!m_db->select(dataVec))
{
ERROR_LOG(m_logger) << "Error reading data from database!";
return false;
}
// create Ied objects
for (const Database::GimIed &data : qAsConst(dataVec))
{
ObjectIed *ifs(new ObjectIed(m_ddsHandler, m_db, m_ppmDtc, this));
Core::FunctionReplyObject ret = ifs->createObject(data);
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
return false;
}
m_iedObjMap.insert(ifs->getId(), ifs);
}
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_iedObjMap.size();
// Initialize RecordReplay to get initial IedPosition
RecordReplayPlugin recordReplay;
// no ddsconnector - we don't want to publish data here
recordReplay.initDtc(nullptr, m_mainHandler->exerciseId());
NSqlQuery q(m_db->database());
recordReplay.readIedPositionAt(q, QDateTime::currentMSecsSinceEpoch());
// key is sampleTime -> multiMap
QMultiMap<qint64, GuezIedManagement::IedPosition> latestPositions = recordReplay.getIedPositionMap();
DEBUG_LOG(m_logger) << "Starting to read IED positions from record replay. Size: "
<< latestPositions.size();
for (auto it = latestPositions.begin(); it != latestPositions.end(); ++it)
{
const auto &pos = it.value();
ObjectIed *currentIed = m_iedObjMap.value(pos.id);
if (currentIed == nullptr)
{
INFO_LOG(m_logger) << "Got position for non existing IED-Id: " << pos.id;
continue;
}
DEBUG_LOG(m_logger) << "Setting position for IED-Id " << pos.id;
currentIed->setPosition(it.value());
}
m_tabDtc = TrainingAreaBase::Interface::Dtc::create(m_ddsHandler->dds());
if (!m_tabDtc->enableDefinitionIed() ||
!m_tabDtc->enableStateIed())
{
ERROR_LOG(m_logger) << "Could not initialize TraininAreaBase data topic client";
return false;
}
connect(m_tabDtc.get(), &TrainingAreaBase::Interface::Dtc::definitionIedChanged,
this, &HandlerIed::onDefinitionIed);
connect(m_tabDtc.get(), &TrainingAreaBase::Interface::Dtc::stateIedChanged,
this, &HandlerIed::onStateIed);
return true;
}
static inline IedTacticalState toTacticalState(int tacticalState)
{
switch (tacticalState)
{
case 0:
return IedTacticalState::NotActive;
case 1:
return IedTacticalState::Active;
case 2:
return IedTacticalState::Defused;
case 3:
return IedTacticalState::TriggeredBySwitch;
case 4:
return IedTacticalState::TriggeredByRemote;
case 5:
return IedTacticalState::TriggeredByLightBarrier;
case 6:
return IedTacticalState::TriggeredByTautWire;
case 7:
return IedTacticalState::TriggeredByControlDevice;
case 255:
break;
default:
Q_ASSERT(false);
break;
}
return IedTacticalState::Unknown;
}
static void assignBaseData(const TrainingAreaBase::IedBaseData &inData, Database::GimIed &outData)
{
outData.equipmentNumber = inData.iedId;
outData.tacticalStateId = toTacticalState(inData.tacticalState);
outData.pyrotechnics = inData.statePyrotechnics;
outData.sampleTime = inData.sampleTime;
}
void HandlerIed::onDefinitionIed(const TrainingAreaBase::DefinitionIed &data, DataModification modType)
{
if (modType != DataModification::eAdded && modType != DataModification::eModified)
return;
DEBUG_LOG(m_logger) << "onDefinitionIed: " << data;
Database::GimIed newData;
assignBaseData(data, newData);
newData.typeId = static_cast<IedType>(data.type);
newData.remoteTrigger = data.remoteTrigger;
newData.switchTrigger = data.switchTrigger;
newData.lightBarrierTrigger = data.lightBarrierTrigger;
newData.tautWireTrigger = data.tautWireTrigger;
newData.explosiveForce = data.explosiveForce;
if (m_ppmDtc->party(data.partyId).id > 0)
newData.partyId = data.partyId; // use party from telegram
else
newData.partyId = getPartyIdFromParticipantEquipmentNumber(data.equipmentNumber); // use party from equipmentNumber
newData.pairingStateId = static_cast<IedPairingState>(data.pairingState);
switch (newData.pairingStateId)
{
case IedPairingState::PairedToParticipant:
newData.pairedParticipantId.setValue(data.pairedId.get());
break;
case IedPairingState::PairedToOps:
newData.pairedOpsId.setValue(data.pairedId.get());
break;
case IedPairingState::NotPaired:
break;
}
// set symbol / sidc
// Note:
// Special: triggered Ied<Small|Big> has seperate SIDC:
// "M25D|CMPL|10014000001103000000"); // SIDC for IED (OHNE ZickZack)
// "M25D|CMPL|10014000001103010000"); // SIDC for IED (MIT ZickZack)
// ^
// | -> Therefore suppress Injury
// handled at guez_ied_to_map.cpp and gim_info_dialog.cpp
switch (newData.typeId)
{
case IedType::SuicideIed:
newData.symbol = QStringLiteral("AP6D|CMPL|10014000001103040000"); //SIDC for suicide bomber
break;
case IedType::IedSmallPyro:
case IedType::IedBigPyro:
newData.symbol = QStringLiteral("AP6D|CMPL|10014000001103000000"); // SIDC for IED (OHNE ZickZack)
break;
} // switch
int id = getIdByEquipmentnumber(newData.equipmentNumber);
if (m_iedObjMap.contains(id))
m_iedObjMap[id]->updateDefinition(newData);
else
{
ObjectIed *ifs(new ObjectIed(m_ddsHandler, m_db, m_ppmDtc, this));
Core::FunctionReplyObject ret = ifs->createObject(newData);
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
return;
}
m_iedObjMap.insert(ifs->getId(), ifs);
auto it = m_orphanedStateIed.find(data.iedId);
if (it != m_orphanedStateIed.end())
{
auto defState = it.value();
m_orphanedStateIed.erase(it);
defState.tacticalState = data.tacticalState;
defState.statePyrotechnics = data.statePyrotechnics;
defState.sampleTime = data.sampleTime;
onStateIed(defState, DataModification::eAdded);
}
id = ifs->getId();
}
m_iedObjMap[id]->setPosition(newData.sampleTime, Core::GeoPosition(data.position.lon, data.position.lat, 0));
}
static inline IedError toIedError(int err)
{
switch (err)
{
case 0:
return IedError::NoError;
case 1:
return IedError::DeviceMissing;
}
Q_ASSERT(false);
return IedError::DeviceMissing;
}
void HandlerIed::onStateIed(const TrainingAreaBase::StateIed &data, DataModification modType)
{
if (modType != DataModification::eAdded && modType != DataModification::eModified)
return;
DEBUG_LOG(m_logger) << "onStateIed: " << data;
// only overwrite state for existing IEDs
if (m_iedObjMap.contains(getIdByEquipmentnumber(data.iedId)))
{
Database::GimIed newData;
assignBaseData(data, newData);
newData.batterywarnings = data.batteryWarnings;
newData.electronicsErrorStateId = toIedError(data.errorStateElectronics);
newData.pyrotechnics1ErrorStateId = toIedError(data.errorStatePyrotechnics1);
newData.pyrotechnics2ErrorStateId = toIedError(data.errorStatePyrotechnics2);
newData.pyrotechnics3ErrorStateId = toIedError(data.errorStatePyrotechnics3);
m_iedObjMap[getIdByEquipmentnumber(newData.equipmentNumber)]->updateState(newData);
}
else
{
WARNING_LOG(m_logger) << "StateIed without an existing IED - got no DefinitionIED? " << data;
m_orphanedStateIed.insert(data.iedId, data);
}
}
void HandlerIed::onPairIedRequest(const rti::core::SampleIdentity &cookie,
const PairIedRequest &request)
{
Core::FunctionReplyObject ret;
INFO_LOG(m_logger) << "onPairIedRequest id = " << request.id;
ObjectIed *ifs = m_iedObjMap.value(request.id);
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id, tr_lts("dds", "IED with id %1 not found")).arg(request.id);
m_ddsHandler->fts()->pairIedReply(cookie, ret);
return;
}
Database::GimIed data;
data.pairingStateId = request.pairingState;
switch (request.pairingState)
{
case IedPairingState::PairedToParticipant:
{
data.pairedParticipantId.setValue(request.pairedParticipantId.get());
data.partyId = m_ppmDtc->participant(request.pairedParticipantId.get()).partyId;
break;
}
case IedPairingState::PairedToOps:
{
data.pairedOpsId.setValue(request.pairedOpsId.get());
break;
}
case IedPairingState::NotPaired:
break;
}
ret = ifs->updatePairingState(data);
if (ret.error())
ERROR_LOG(m_logger) << ret();
m_ddsHandler->fts()->pairIedReply(cookie, ret);
}
int HandlerIed::getIdByEquipmentnumber(const int number) const
{
for (const auto &obj : m_iedObjMap)
{
if (obj->getEquipmentnumber() == number)
return obj->getId();
}
return -1;
}
int HandlerIed::getPartyIdFromParticipantEquipmentNumber(const int equipmentNumber) const
{
const QMap<int, ParticipantManagement::Participant> participants = m_ppmDtc->participants();
for (const auto &participant : participants)
{
if (participant.equipmentNumber == equipmentNumber)
return participant.partyId;
}
return 0;
}
} // Namespace GuezIedManagement