Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+367
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* 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 <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::inner_enum>(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::inner_enum>(data.pairingState());
|
||||
switch (newData.pairingStateId.underlying())
|
||||
{
|
||||
case IedPairingState_def::PairedToParticipant:
|
||||
newData.pairedParticipantId.setValue(data.pairedId().get());
|
||||
break;
|
||||
case IedPairingState_def::PairedToOps:
|
||||
newData.pairedOpsId.setValue(data.pairedId().get());
|
||||
break;
|
||||
case IedPairingState_def::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.underlying())
|
||||
{
|
||||
case IedType_def::SuicideIed:
|
||||
newData.symbol = QStringLiteral("AP6D|CMPL|10014000001103040000"); //SIDC for suicide bomber
|
||||
break;
|
||||
case IedType_def::IedSmallPyro:
|
||||
case IedType_def::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().underlying())
|
||||
{
|
||||
case IedPairingState_def::PairedToParticipant:
|
||||
{
|
||||
data.pairedParticipantId.setValue(request.pairedParticipantId().get());
|
||||
data.partyId = m_ppmDtc->participant(request.pairedParticipantId().get()).partyId();
|
||||
break;
|
||||
}
|
||||
case IedPairingState_def::PairedToOps:
|
||||
{
|
||||
data.pairedOpsId.setValue(request.pairedOpsId().get());
|
||||
break;
|
||||
}
|
||||
case IedPairingState_def::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
|
||||
Reference in new issue
Block a user