Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,53 @@
#
# Commmunication with HlaApacheProxy
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS
logger.cpp
logger.h
main_dispatcher.cpp
main_dispatcher.h
main_handler_tx.cpp
main_handler_tx.h
plugin.cpp
plugin.h
hla_dispatcher.cpp
hla_dispatcher.h
hla_handler_rx.cpp
hla_handler_rx.h
hla_handler_tx.cpp
hla_handler_tx.h
ppm_handler.cpp
ppm_handler.h
pdm_handler.cpp
pdm_handler.h
aes_handler.cpp
aes_handler.h
dds_handler.cpp
dds_handler.h
)
NGL_ADD_LIBRARY(AAR SV tabPluginApHla MODULE ${SRCS})
NGL_INSTALL_TARGET(tabPluginApHla)
NGL_TARGET_LINK_LIBRARIES(tabPluginApHla
svcTabServer
NGLLogger
nglsettings
ngltools
Qt5::Core
Qt5::Network
Qt5::WebSockets
tabPluginInterface
tabTelegrams
svcTabCommon
svcPpmClient
svcPdmClient
svcExmClient
svcAesClient
svcCoreClient
ddsconnector
LtsUtilsDds
)
@@ -0,0 +1,120 @@
All Telegrams only defined for communication between TAB-Plugin and Apache Virtual Machine
AddParticipant Telegram(Sending updated or added participant to Apache)
Example Telegram:
<pre><code>
{
typeId:8000,
type: ApacheHlaAddParticipant,
data:
{
header: {
equipmentNumber: 42,
timeStamp: MsecsSinceEpoch
},
status: 11,
forceIdentifier: 42,
ets: "2.0.0.0.0.0.1",
GeoPosition: {
lon: 15.145274,
lat: 24.5554556,
z: 55.000124
}
}
}
</pre></code>
RemoveParticipant Telegram(Sending deleted participant to Apache)
Example Telegram:
<pre><code>
{
typeId:8001,
type: ApacheHlaRemoveParticipant,
data:
{
header: {
equipmentNumber: 42,
timeStamp: MsecsSinceEpoch
}
}
}
</pre></code>
Change Position Telegram( Send new Position of participant to Apache)
Example Telegram:
<pre><code>
{
typeId:8002,
type: ApacheHlaPositionChanged,
data:
{
header: {
equipmentNumber: 42,
timeStamp: MsecsSinceEpoch
},
lon: 15.275884,
lat: 37.854856,
z: 42.255278
}
}
</pre></code>
Change VulnerabilityState Telegram(Sending updated VulnerabilityState to Apache)
Example Telegram:
<pre><code>
{
typeId:8003,
type: ApacheHlaVulnerabilityStateChanged,
data:
{
header: {
equipmentNumber: 42,
timeStamp: MsecsSinceEpoch
},
status: 11
}
}
</pre></code>
AllChargeTypes Telegram(Sending all Charge Types at the beginning of an exercise to Apache)
Example Telegram:
<pre><code>
{
typeId:8005,
type: ApacheHlaSendChargeTypes,
data:
[
{
id: 420,
name: 42mm,
entityTypeStruct: TestTest,
primaryGearTasCode: 11,
radius: 7
},
{
id: 777,
name: 77mm,
entityTypeStruct: TestTest,
primaryGearTasCode: 77,
radius: 77
},
{
...
}
]
}
</pre></code>
@@ -0,0 +1,78 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "aes_handler.h"
#include <QJsonArray>
#include <QJsonDocument>
namespace ApHlaJson
{
/**
* @brief
* @author Niklas Schmidt
* @details Receives AesModifyRequests from HLA and publish them with Ftc for Aes
* HLA -> Excon
* @param parent
*/
AesHandler::AesHandler(QObject *parent)
: QObject(parent)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("AesHandler"))
{}
bool AesHandler::init(MainDispatcher* mainDispatcher)
{
m_ftcAes = AreaEffectSimulation::Interface::Ftc::create(mainDispatcher->ddsHandler()->ddsConnector());
m_dtcPpm = ParticipantManagement::Interface::Dtc::create(mainDispatcher->ddsHandler()->ddsConnector());
if (!m_ftcAes)
return false;
if (!m_ftcAes->enableAirSupportImpactModify())
{
ERROR_LOG(m_logger) << "Can not enableAirSupportImpactModify ";
return false;
}
return true;
}
bool AesHandler::sendAesModifyRequest(const QJsonObject &data)
{
int equipmentNumber = data[QStringLiteral("header")].toObject()[QStringLiteral("equipmentNumber")].toInt();
AreaEffectSimulation::AirSupportImpactModifyRequest request;
request.chargeTypeId(data[QStringLiteral("chargeTypeId")].toInt());
request.externalId(data[QStringLiteral("eventId")].toInt());
request.name(data[QStringLiteral("name")].toString().toStdString());
request.impactPosition(Core::GeoPosition2D(data[QStringLiteral("impactPosition")].toObject()[QStringLiteral("lon")].toDouble(),
data[QStringLiteral("impactPosition")].toObject()[QStringLiteral("lat")].toDouble()));
request.flightTime(0);
qint64 requestedTime = static_cast<qint64>(data[QStringLiteral("header")].toObject()[QStringLiteral("timeStamp")].toDouble());
if (requestedTime < QDateTime::currentMSecsSinceEpoch())
requestedTime = QDateTime::currentMSecsSinceEpoch() + 500;
request.effectStart(requestedTime);
QJsonDocument doc(data);
if (equipmentNumber)
request.participantId(m_dtcPpm->participantIdByEquipmentNumber(equipmentNumber));
m_requestHelper->startSingleRequest([this, request]()
{
return m_ftcAes->airSupportImpactModifyRequest(request, this);
});
return true;
}
void AesHandler::onAirSupportImpactModifyReply(const Core::FunctionReplyObject &reply)
{
m_requestHelper->requestReply(reply);
}
} // namespace ApHlaJson
@@ -0,0 +1,49 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include "main_dispatcher.h"
#include "logger.h"
#include "dds_handler.h"
#include <AreaEffectSimulation/aes.hpp>
#include <AreaEffectSimulation/aes_ftc.h>
#include <ParticipantManagement/ppm.hpp>
#include <ParticipantManagement/ppm_dtc.h>
#include <LtsUtilsCore/data_modification_enum.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <QObject>
#include <QHash>
#include <QUrl>
#include <QDateTime>
namespace ApHlaJson
{
class MainDispatcher;
class AesHandler : public QObject
, protected AreaEffectSimulation::Interface::Ftc::AirSupportImpactModifyReplyHandler
{
Q_OBJECT
public:
explicit AesHandler(QObject *parent = nullptr);
bool init(MainDispatcher* mainDispatcher);
bool sendAesModifyRequest(const QJsonObject &obj);
void onAirSupportImpactModifyReply(const Core::FunctionReplyObject &reply);
private:
std::shared_ptr<AreaEffectSimulation::Interface::Ftc> m_ftcAes;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_dtcPpm;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
} // namespace ApHlaJson
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,40 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "dds_handler.h"
#include <DDS/Core/pacemaker.h>
namespace ApHlaJson
{
DdsHandler::DdsHandler(int domainId, int exerciseId)
: m_ddsConnector(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Exercise, exerciseId))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if (!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
// Pacemaker
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
return true;
}
} // namespace PatSimJson
@@ -0,0 +1,44 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include "logger.h"
namespace Core
{
class Pacemaker;
}
namespace ApHlaJson
{
class DdsHandler
{
public:
DdsHandler(int domainId, int exerciseId);
bool init(const QStringList &qosFileList = QStringList());
std::shared_ptr<Core::Pacemaker> pacemaker() const
{
return m_pacemaker;
}
std::shared_ptr<DDSConnector::DdsConnector> ddsConnector() const
{
return m_ddsConnector;
}
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<Core::Pacemaker> m_pacemaker;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,126 @@
/**
* Send / Receive telegrams to/from Hla
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "hla_dispatcher.h"
#include "hla_handler_rx.h"
#include "hla_handler_tx.h"
#include <QSettings>
#include <QWebSocket>
#include <QTimer>
#include <nglsettings/nglsettings_settings.h>
namespace ApHlaJson
{
HlaDispatcher::HlaDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
NGL::Settings *settings,
std::shared_ptr<PpmHandler> ppmHandler,
std::shared_ptr<PdmHandler> pdmHandler,
std::shared_ptr<AesHandler> aesHandler)
: m_recvFromTabCb(recvFromTabCb)
, m_recvFromHla(std::make_shared<HlaHandlerRx>(recvFromTabCb, sendToTabCb, this, aesHandler.get(), ppmHandler.get()))
, m_sendToHla(std::make_shared<HlaHandlerTx>(pdp, ppmHandler.get(), pdmHandler.get()))
, m_settings(settings)
, m_webSocket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
, m_webSocketReconnectTimer(new QTimer(this))
, m_bWarnedOnce(false)
, m_logger(getLogger("HlaDispatcher"))
{
connect(m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
this, &HlaDispatcher::onWebSocketError);
connect(m_webSocket, &QWebSocket::connected,
this, &HlaDispatcher::onWebSocketConnected);
connect(m_webSocket, &QWebSocket::disconnected,
this, &HlaDispatcher::onWebsocketDisconnected);
connect(m_webSocket, &QWebSocket::binaryMessageReceived,
this, &HlaDispatcher::onTextMessageReceived, Qt::UniqueConnection);
connect(m_webSocketReconnectTimer, &QTimer::timeout,
this, &HlaDispatcher::reallyConnectWebsocket);
connect(m_recvFromHla.get(), &HlaHandlerRx::participantConnectionState,
m_sendToHla.get(), &HlaHandlerTx::onParticipantConnectionState);
}
bool HlaDispatcher::init()
{
return true;
}
void HlaDispatcher::connectWebsocket()
{
const QUrl url(webSocketUrl());
if (!m_bWarnedOnce)
NOTICE_LOG(m_logger) << "Using WebSocket url: " << url.toString();
if (m_webSocket->state() != QAbstractSocket::ConnectedState)
m_webSocket->open(url);
}
std::shared_ptr<TrainingAreaBase::SendToTab> HlaDispatcher::sendToTab()
{
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_sendToHla);
}
bool HlaDispatcher::canSendData() const
{
return m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState;
}
void HlaDispatcher::onWebSocketConnected()
{
INFO_LOG(m_logger) << "WebSocket connected";
QWebSocket *ws = qobject_cast<QWebSocket *>(sender());
m_sendToHla->onWebSocketConnected(ws);
m_webSocketReconnectTimer->stop();
m_bWarnedOnce = false;
}
void HlaDispatcher::onWebsocketDisconnected()
{
INFO_LOG(m_logger) << "Hla socket disconnected";
m_sendToHla->onWebSocketDisconnected();
emit connectionState(QString::fromUtf8(name()), false);
m_webSocketReconnectTimer->start(5000);
}
void HlaDispatcher::onHlaExternalConnectionStateChanged(bool bConnected)
{
m_sendToHla->onHlaConnectedToExternalSystem(bConnected);
emit connectionState(QString::fromUtf8(name()), bConnected);
}
void HlaDispatcher::onWebSocketError()
{
if (!m_webSocket)
return;
if (!m_bWarnedOnce)
WARNING_LOG(m_logger) << "Error connecting to " << webSocketUrl().toString() << ": " << m_webSocket->errorString();
m_webSocket->close();
m_webSocketReconnectTimer->start(5000);
m_bWarnedOnce = true;
emit connectionState(QString::fromUtf8(name()), false);
}
void HlaDispatcher::onTextMessageReceived(const QByteArray &message)
{
INFO_LOG(m_logger) << "Text Message received: " << message;
// convert from json to internal representation, send to TAB
m_recvFromHla->handleTelegram(message);
}
QUrl HlaDispatcher::webSocketUrl() const
{
const quint16 port = m_settings->settings()->value(QStringLiteral("aphla/webSocketListenPort"), 12345).toInt();
const QString addr = m_settings->settings()->value(QStringLiteral("aphla/webSocketHostname"), QStringLiteral("172.25.160.11")).toString();
return QUrl(QStringLiteral("ws://%1:%2/").arg(addr).arg(port));
}
} // namespace HlaJson
@@ -0,0 +1,71 @@
/**
* Send / Receive telegrams to/from Hla
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include <QObject>
#include <QWebSocket>
#include <TrainingAreaBase/tab_plugin_interface.h>
#include <DDS/Core/function_reply_object.h> // tr_lts
#include "logger.h"
#include "ppm_handler.h"
#include "aes_handler.h"
#include "pdm_handler.h"
class QTimer;
namespace ApHlaJson
{
class HlaHandlerRx;
class HlaHandlerTx;
class HlaDispatcher final : public TrainingAreaBase::Plugin::Interface
{
Q_OBJECT
public:
HlaDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
NGL::Settings *settings,
std::shared_ptr<PpmHandler> ppmHandler,
std::shared_ptr<PdmHandler> pdmHandler,
std::shared_ptr<AesHandler> aesHandler);
public Q_SLOTS:
bool init() override;
public:
std::shared_ptr<TrainingAreaBase::SendToTab> sendToTab() override;
bool isDebugInterface() const override { return false; }
bool canSendData() const override;
void exerciseChanged() override { return; }
const char *name() const override { return tr_lts("dds", "APHLA"); }
public Q_SLOTS:
void onWebSocketConnected();
void onWebsocketDisconnected();
void onHlaExternalConnectionStateChanged(bool bConnected);
void onWebSocketError();
void onTextMessageReceived(const QByteArray &message);
void connectWebsocket();
void reallyConnectWebsocket() { connectWebsocket(); }
Q_SIGNALS:
void broadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter);
void hlaTelegramReceived(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele);
private:
QUrl webSocketUrl() const;
private:
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_recvFromTabCb;
std::shared_ptr<HlaHandlerRx> m_recvFromHla;
std::shared_ptr<HlaHandlerTx> m_sendToHla;
NGL::Settings *m_settings;
QWebSocket *m_webSocket;
QTimer *m_webSocketReconnectTimer;
bool m_bWarnedOnce;
NGL::INGLLogger &m_logger;
};
} // namespace HlaJson
@@ -0,0 +1,176 @@
/**
* Convert Json from WLS to internal telegrams
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "hla_handler_rx.h"
#include "hla_dispatcher.h"
#include "aes_handler.h"
#include "ppm_handler.h"
#include <TrainingAreaBase/training_area_telegrams.h>
#include <QJsonDocument>
namespace ApHlaJson
{
/*!
* \brief HlaHandlerRx::HlaHandlerRx
* \param recvFromTabCb
* \param sendToTabCb
* \param dispatcher
* \param aesHandler
* \param ppmHandler
* \author Niklas Schmidt
* \details Handles all incoming telegrams from Apache
*/
HlaHandlerRx::HlaHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
HlaDispatcher *dispatcher,
AesHandler* aesHandler,
PpmHandler* ppmHandler)
: m_rxHandler(recvFromTabCb)
, m_txHandler(sendToTabCb)//std::static_pointer_cast<TrainingAreaBase::SendToTab>(sendToTabCb))
, m_dispatcher(dispatcher)
, m_bWarnedOnce(false)
, m_bWarnedOnceTx(false)
, m_aesHandler(aesHandler)
, m_ppmHandler(ppmHandler)
, m_logger(getLogger("HlaHandlerRx"))
{}
bool HlaHandlerRx::handleTelegram(const QByteArray &baJson)
{
using namespace TrainingAreaBase::TetraIcd;
if (baJson.isEmpty())
return false;
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
const QJsonValue typeId = obj.value(QStringLiteral("typeId"));
if (!typeId.isDouble())
{
ERROR_LOG(m_logger) << "Can not read type id: " << baJson;
return false;
}
const QJsonObject data = obj.value(QStringLiteral("data")).toObject();
if(typeId.toInt() != 21)
ERROR_LOG(m_logger) << "Telegram before filter: " << baJson;
try
{
QJsonValue header = data[QStringLiteral("header")];
QJsonObject obj = header.toObject();
if (!obj.isEmpty())
{
int eqNo = obj[QStringLiteral("equipmentNumber")].toInt(0);
if (eqNo <= 0)
return false;
if (!checkExercise(eqNo))
return false;
}
if(typeId.toInt() != 21)
ERROR_LOG(m_logger) << "Telegram after filter: " << baJson;
switch (typeId.toInt())
{
case Constraints<ProxyConnectionState>::id(): // 2013
{
bool connected = ProxyConnectionState::fromJson(data).connectedToSystem;
m_dispatcher->onHlaExternalConnectionStateChanged(connected);
}
break;
case Constraints<CesHitInformation>::id(): // 211
if(checkExercise(data[QStringLiteral("originatorEquipmentNumber")].toInt()))
txData(CesHitInformation::fromJson(data));
break;
case Constraints<PositionReport>::id(): // 21
rxData(PositionReport::fromJson(data));
break;
case Constraints<StateChangeDirect>::id(): //has originator
rxData(StateChangeDirect::fromJson(data));
break;
case Constraints<StateChange>::id(): //has originator
rxData(StateChange::fromJson(data));
break;
case Constraints<EquipmentGearEvent>::id():
rxData(EquipmentGearEvent::fromJson(data));
break;
case Constraints<EquipmentGearAssignment>::id():
rxData(EquipmentGearAssignment::fromJson(data));
break;
case Constraints<EquipmentGearChargeState>::id():
rxData(EquipmentGearChargeState::fromJson(data));
break;
case Constraints<SpecialSensorData>::id():
rxData(SpecialSensorData::fromJson(data));
break;
case 8006 :
m_aesHandler->sendAesModifyRequest(data);
break;
case Constraints<ApacheLaserDesignation>::id():
rxData(ApacheLaserDesignation::fromJson(data));
break;
case Constraints<WlsParticipantsConnectionState>::id(): // 3004
{
const auto tele = WlsParticipantsConnectionState::fromJson(data);
if (checkExercise(tele.equipmentNumber))
emit participantConnectionState(tele.equipmentNumber, tele.dataCommunicationPossible);
break;
}
default:
return false;
}
}
catch (const std::exception &e)
{
WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << baJson << ")";
return false;
}
return true;
}
/*!
\brief
\details Check if Participant is in same Exercise than the TAB-Process is
\param equipmentNumber
\return bool
*/
bool HlaHandlerRx::checkExercise(int equipmentNumber) const
{
return m_ppmHandler->isEqNumberInExercise(equipmentNumber);
}
template<typename T>
void HlaHandlerRx::rxData(const T &data)
{
if (!m_rxHandler)
{
if (!m_bWarnedOnce)
{
ERROR_LOG(m_logger) << "No RecvFromTab available";
m_bWarnedOnce = true;
}
return;
}
emit m_dispatcher->hlaTelegramReceived(&data);
return m_rxHandler->rxData(data);
}
template<typename T>
void HlaHandlerRx::txData(const T &data)
{
if (!m_txHandler)
{
if (!m_bWarnedOnceTx)
{
ERROR_LOG(m_logger) << "No RecvFromTab available";
m_bWarnedOnceTx = true;
}
return;
}
emit m_dispatcher->hlaTelegramReceived(&data);
m_txHandler->txData(data);
}
} // namespace HlaJson
@@ -0,0 +1,56 @@
/**
* Convert Json from WLS to internal telegrams
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include <TrainingAreaBase/recv_from_tab.h>
#include <TrainingAreaBase/tx_mixin.h>
#include <TrainingAreaBase/tab_plugin_interface.h>
#include <QObject>
#include <QString>
#include <memory>
#include "logger.h"
namespace ApHlaJson
{
class AesHandler;
class PpmHandler;
class HlaDispatcher;
class HlaHandlerRx : public QObject
{
Q_OBJECT
public:
explicit HlaHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
HlaDispatcher *dispatcher,
AesHandler* aesHandler,
PpmHandler* ppmHandler);
bool handleTelegram(const QByteArray &baJson);
bool handleTelegram(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele);
Q_SIGNALS:
void participantConnectionState(int equipmentNumber, bool dataCommunicationPossible);
private:
template<typename T>
void rxData(const T &data);
template<typename T>
void txData(const T &data);
private:
bool checkExercise(int equipmentNumber) const;
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_rxHandler;
std::shared_ptr<TrainingAreaBase::TxMixin> m_txHandler;
HlaDispatcher *m_dispatcher;
bool m_bWarnedOnce;
bool m_bWarnedOnceTx;
AesHandler* m_aesHandler;
PpmHandler* m_ppmHandler;
LOGGER_T m_logger;
};
} // namespace HlaJson
@@ -0,0 +1,343 @@
/**
* Convert telegrams to Json and sent to WLS proxy
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "hla_handler_tx.h"
#include "ppm_handler.h"
#include "pdm_handler.h"
#include <QJsonDocument>
#include <QWebSocket>
namespace ApHlaJson
{
class PpmHandler;
HlaHandlerTx::HlaHandlerTx(TrainingAreaBase::Plugin::DataProvider *pdp, PpmHandler* ppmHandler, PdmHandler* pdmHandler)
: m_pdp(pdp)
, m_ppmHandler(ppmHandler)
, m_pdmHandler(pdmHandler)
, m_webSocket(nullptr)
, m_bHlaConnectedToExternalSystem(false)
, m_logger(getLogger("HlaHandlerTx"))
{}
void HlaHandlerTx::onWebSocketConnected(QWebSocket *webSocket)
{
m_webSocket = webSocket;
if (!m_webSocket)
{
return;
}
}
void HlaHandlerTx::onWebSocketDisconnected()
{
m_ppmHandler->disconnect(this);
m_pdmHandler->disconnect(this);
m_webSocket = nullptr;
}
void HlaHandlerTx::onHlaConnectedToExternalSystem(bool bConnected)
{
m_bHlaConnectedToExternalSystem = bConnected;
NOTICE_LOG(m_logger) << "Connected to Old HLA Interface - exercise environment, charges and participants";
const auto tele2 = m_pdp->exerciseEnvironmentData();
sendToTx(&tele2, true);
connect(m_ppmHandler, &PpmHandler::participantChanged, this, &HlaHandlerTx::onGenericTelegram, Qt::UniqueConnection);
connect(m_pdmHandler, &PdmHandler::sendChargeTypes, this, &HlaHandlerTx::onGenericTelegram, Qt::UniqueConnection);
m_pdmHandler->getChargeTypes();
m_ppmHandler->getParticipants();
}
TrainingAreaBase::SendToTab::HandleState HlaHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
{
if (!m_webSocket || !m_bHlaConnectedToExternalSystem)
return HandleState::No;
using namespace TrainingAreaBase::TetraIcd;
// if (telegramId == Constraints<ExerciseEquipmentAssignmentComplete>::id() ||
// telegramId == Constraints<ExerciseStateData>::id())
// return HandleState::YesShare;
if (equipmentNumber <= 0 || !m_dataCommunicationPossible.value(equipmentNumber, false))
return HandleState::No;
if (telegramId == Constraints<Init>::id() ||
telegramId == Constraints<DemandVulnerabilityStateChange>::id() ||
telegramId == Constraints<SelectiveReammunition>::id() ||
telegramId == Constraints<CesHitInformation>::id()
)
return HandleState::YesConsume;
return HandleState::No;
}
void HlaHandlerTx::resetSendCounter()
{
// nothing to do
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Init &data)
{
return sendToTx(&data);
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
{
return sendToTx(&data);
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data)
{
return sendToTx(&data);
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Acknowledge &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandBite &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineTriggered &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data)
{
Q_UNUSED(data);
return false; // only for Tetra - really?
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Sanitation &data)
{
Q_UNUSED(data);
return false;
}
bool HlaHandlerTx::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
{
Q_UNUSED(data);
return false;
}
void HlaHandlerTx::onParticipantConnectionState(int equipmentNumber, bool dataCommunicationPossible)
{
INFO_LOG(m_logger) << "onParticipantConnectionState - " << equipmentNumber
<< ", communication possible: " << dataCommunicationPossible;
if (equipmentNumber == -1)
m_dataCommunicationPossible.clear();
m_dataCommunicationPossible[equipmentNumber] = dataCommunicationPossible;
}
void HlaHandlerTx::onGenericTelegram(const QJsonObject &telegram)
{
if (!m_webSocket || !m_bHlaConnectedToExternalSystem)
return;
const QByteArray ba = QJsonDocument(telegram).toJson(QJsonDocument::Compact);
DEBUG_LOG(m_logger) << "Sending tele: " << ba;
m_webSocket->sendTextMessage(QString::fromUtf8(ba));
}
bool HlaHandlerTx::sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data, bool bForce)
{
Q_UNUSED(bForce);
QJsonObject telegram;
telegram[QStringLiteral("data")] = data->toJson();
telegram[QStringLiteral("type")] = data->type();
telegram[QStringLiteral("typeId")] = data->id();
onGenericTelegram(telegram);
return true;
}
QHash<int, bool> HlaHandlerTx::dataCommunicationPossible() const
{
return m_dataCommunicationPossible;
}
} // namespace HlaJson
@@ -0,0 +1,95 @@
/**
* Convert telegrams to Json and sent to WLS proxy
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include "ppm_handler.h"
#include "pdm_handler.h"
#include "logger.h"
#include <TrainingAreaBase/send_to_tab.h>
#include <TrainingAreaBase/recv_from_tab.h>
#include <TrainingAreaBase/tab_plugin_interface.h>
#include <QHash>
class QWebSocket;
class PpmHandler;
class PdmHandler;
namespace ApHlaJson
{
class HlaHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
{
Q_OBJECT
public:
explicit HlaHandlerTx(TrainingAreaBase::Plugin::DataProvider *pdp, PpmHandler* ppmHandler, PdmHandler* pdmHandler);
void onWebSocketConnected(QWebSocket *webSocket);
void onWebSocketDisconnected();
void onHlaConnectedToExternalSystem(bool bConnected);
const char *name() const override { return "ApHla"; }
HandleState canHandleTelegram(int equipmentNumber, int telegramId) const override;
void resetSendCounter() override;
bool txData(const TrainingAreaBase::TetraIcd::Acknowledge &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandBite &data) override;
bool txData(const TrainingAreaBase::TetraIcd::Init &data) override;
bool txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data) override;
bool txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data) override;
bool txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data) override;
bool txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data) override;
bool txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::MineTriggered &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data) override;
bool txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data) override;
bool txData(const TrainingAreaBase::TetraIcd::Sanitation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data) override;
QHash<int, bool> dataCommunicationPossible() const;
public slots:
void onParticipantConnectionState(int equipmentNumber, bool dataCommunicationPossible);
void onGenericTelegram(const QJsonObject &telegram);
private:
bool sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data, bool bForce = false);
private:
QHash<int, bool> m_dataCommunicationPossible; // equioNo, reachable
TrainingAreaBase::Plugin::DataProvider *m_pdp;
PpmHandler* m_ppmHandler;
PdmHandler* m_pdmHandler;
QWebSocket *m_webSocket;
bool m_bHlaConnectedToExternalSystem;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,38 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace ApHlaJson
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "TAB.APHLA.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace HlaJson
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Logging for TrainingAreaBase
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
namespace ApHlaJson
{
using LOGGER_T = NGL::INGLLogger&;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace HlaJson
@@ -0,0 +1,89 @@
/**
* Send / Receive telegrams to/from Hla
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "main_dispatcher.h"
#include "main_handler_tx.h"
#include "hla_dispatcher.h"
#include "hla_handler_tx.h"
#include <nglsettings/nglsettings_settings.h>
#include <QTimer>
namespace ApHlaJson
{
MainDispatcher::MainDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTab,
NGL::Settings *settings)
: m_hlaDispatcher(nullptr)
, m_recvFromTabCb(recvFromTabCb)
, m_sendToTab(sendToTab)
, m_mainHandlerTx(nullptr)
, m_pdp(pdp)
, m_settings(settings)
, m_logger(getLogger("MainDispatcher"))
, m_domainId(pdp->domainId())
, m_exerciseId(pdp->exerciseId())
{
INFO_LOG(m_logger) << "ApHla started, Domain Id: " << m_domainId << " ExerciseId: " << m_exerciseId;
}
MainDispatcher::~MainDispatcher()
{
m_mainHandlerTx = nullptr;
m_recvFromTabCb = nullptr;
m_ddsHandler = nullptr;
m_ppmHandler = nullptr;
m_pdmHandler = nullptr;
m_aesHandler = nullptr;
delete m_hlaDispatcher;
}
bool MainDispatcher::init()
{
m_ddsHandler = std::make_shared<DdsHandler>(m_domainId, m_exerciseId);
if (!m_ddsHandler->init())
return false;
m_pdmHandler = std::make_shared<PdmHandler>();
m_pdmHandler->init(this);
m_ppmHandler = std::make_shared<PpmHandler>();
m_ppmHandler->init(this);
m_aesHandler = std::make_shared<AesHandler>();
m_aesHandler->init(this);
m_hlaDispatcher = new HlaDispatcher(m_pdp, m_recvFromTabCb, m_sendToTab, m_settings, m_ppmHandler, m_pdmHandler, m_aesHandler);
m_mainHandlerTx = std::make_shared<MainHandlerTx>(std::dynamic_pointer_cast<HlaHandlerTx>(m_hlaDispatcher->sendToTab()));
m_hlaDispatcher->init();
m_hlaDispatcher->connectWebsocket();
return true;
}
std::shared_ptr<TrainingAreaBase::SendToTab> MainDispatcher::sendToTab()
{
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_mainHandlerTx);
}
bool MainDispatcher::canSendData() const
{
return m_hlaDispatcher->canSendData();
}
void MainDispatcher::exerciseChanged()
{
m_hlaDispatcher->exerciseChanged();
}
} // namespace ApHlaJson
@@ -0,0 +1,85 @@
/**
* Send / Receive telegrams to/from Hla
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include <QObject>
#include <TrainingAreaBase/tab_plugin_interface.h>
#include <DDS/Core/function_reply_object.h> // tr_lts
#include "dds_handler.h"
#include "logger.h"
#include "ppm_handler.h"
#include "pdm_handler.h"
#include "aes_handler.h"
namespace ApHlaJson
{
class HlaDispatcher;
class PpmHandler;
class PdmHandler;
class AesHandler;
class MainDispatcher final : public TrainingAreaBase::Plugin::Interface
{
Q_OBJECT
public:
MainDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
NGL::Settings *settings);
~MainDispatcher();
std::shared_ptr<PpmHandler> ppmHandler() const
{
return m_ppmHandler;
}
std::shared_ptr<PdmHandler> pdmHandler() const
{
return m_pdmHandler;
}
std::shared_ptr<AesHandler> aesHandler() const
{
return m_aesHandler;
}
std::shared_ptr<DdsHandler> ddsHandler() const
{
return m_ddsHandler;
}
int exerciseId() const
{
return m_exerciseId;
}
public slots:
bool init() override;
public:
std::shared_ptr<TrainingAreaBase::SendToTab> sendToTab() override;
bool isDebugInterface() const override { return false; }
bool canSendData() const override;
void exerciseChanged() override;
const char *name() const override { return tr_lts("dds", "ApHlaJson"); }
private:
HlaDispatcher *m_hlaDispatcher;
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_recvFromTabCb;
const std::shared_ptr<TrainingAreaBase::TxMixin> m_sendToTab;
std::shared_ptr<TrainingAreaBase::SendToTab> m_mainHandlerTx;
TrainingAreaBase::Plugin::DataProvider *m_pdp;
NGL::Settings *m_settings;
std::shared_ptr<PpmHandler> m_ppmHandler;
std::shared_ptr<PdmHandler> m_pdmHandler;
std::shared_ptr<AesHandler> m_aesHandler;
std::shared_ptr<DdsHandler> m_ddsHandler;
NGL::INGLLogger &m_logger;
int m_domainId;
int m_exerciseId;
};
} // namespace HlaJson
@@ -0,0 +1,222 @@
/**
* Convert telegrams to Json and sent to WLS proxy
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "main_handler_tx.h"
#include "hla_handler_tx.h"
using namespace TrainingAreaBase;
namespace ApHlaJson
{
MainHandlerTx::MainHandlerTx(const std::shared_ptr<HlaHandlerTx> &hlaTx)
: m_hlaHandlerTx(hlaTx)
, m_logger(getLogger("MainHandlerTx"))
{}
SendToTab::HandleState MainHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
{
return m_hlaHandlerTx->canHandleTelegram(equipmentNumber, telegramId);
}
void MainHandlerTx::resetSendCounter()
{
m_hlaHandlerTx->resetSendCounter();
}
bool MainHandlerTx::txData(const TetraIcd::Acknowledge &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DemandBite &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::Init &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::SetVulnerabilityModel &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DemandEquipmentConfigurationReport &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DemandVulnerabilityStateChange &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::LanguageSelection &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::EquipmentMessage &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::EquipmentMessageOC &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateSingleExplosion &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateAreaExplosion &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateMineArea &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::MineAreaSingleMineState &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateNContamination &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateCContamination &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DeactivateEffectSimulation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ModifyAreaEffectSimulationName &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::PauseEffectSimulation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ResumeEffectSimulation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::MineTriggered &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DusMineReactivation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateFunctionalArea &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CreateDusSingleMine &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ExerciseEnvironmentData &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ExerciseStateData &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::OpaquePayloadDataOut &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ParticipantSwVersionsRequest &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::TechnicalArea &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CesHitInformation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::CesHitRequest &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ParticipantMode &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DemandParticipantMode &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ParticipantConfiguration &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::DemandParticipantConfiguration &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::ExerciseEquipmentAssignmentComplete &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::Sanitation &data)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::SelectiveReammunition &data)
{
return sendToTxMixin(&data);
}
template <typename T>
bool MainHandlerTx::sendToTxMixin(const T *data)
{
return m_hlaHandlerTx->txData(*data);
}
} // namespace HlaJson
@@ -0,0 +1,75 @@
/**
* Convert telegrams to Json and sent to WLS proxy
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include <QObject>
#include "logger.h"
#include <TrainingAreaBase/send_to_tab.h>
#include <memory>
class QWebSocket;
namespace ApHlaJson
{
class HlaHandlerTx;
class MainHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
{
Q_OBJECT
public:
explicit MainHandlerTx(const std::shared_ptr<HlaHandlerTx> &hlaTx);
const char *name() const override { return "HlaJson"; }
HandleState canHandleTelegram(int equipmentNumber, int telegramId) const override;
void resetSendCounter() override;
bool txData(const TrainingAreaBase::TetraIcd::Acknowledge &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandBite &data) override;
bool txData(const TrainingAreaBase::TetraIcd::Init &data) override;
bool txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data) override;
bool txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data) override;
bool txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data) override;
bool txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data) override;
bool txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::MineTriggered &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data) override;
bool txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data) override;
bool txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data) override;
bool txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data) override;
bool txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data) override;
bool txData(const TrainingAreaBase::TetraIcd::Sanitation &data) override;
bool txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data) override;
private:
template <typename T>
bool sendToTxMixin(const T *data);
private:
std::shared_ptr<HlaHandlerTx> m_hlaHandlerTx;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,120 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "pdm_handler.h"
#include <QJsonArray>
#include <QJsonDocument>
namespace ApHlaJson
{
/*!
\brief
\author Niklas Schmidt
\details Initially send all Charge Types to HLA
Excon -> HLA
\param parent
*/
PdmHandler::PdmHandler(QObject *parent)
: QObject(parent)
, m_logger(getLogger("PdmHandler"))
{}
bool PdmHandler::init(MainDispatcher* mainDispatcher)
{
m_dtcPdm = ProjectDataManagement::Interface::Dtc::create(mainDispatcher->ddsHandler()->ddsConnector());
if (!m_dtcPdm->enableChargeType())
{
ERROR_LOG(m_logger) << "Can not read data from Pdm";
return false;
}
m_dtcPdm->waitForHistoricalDataChargeType(5000); //NOTE: Unsure if necessary??, what if getChargeTypes started before waitForHistoricalData is finished
if (m_dtcPdm->chargeTypes().size() <= 0)
FATAL_LOG(m_logger) << "Could not fetch ChargeTypes (yet)!";
return true;
}
/*
* {
* typeId:8005,
* type: ApacheHlaSendChargeTypes,
* data:
* [
* {
* id: 420,
* name: 42mm,
* entityTypeStruct: TestTest,
* primaryGearTasCode: 11,
* radius: 7
* },
* {
* id: 777,
* name: 77mm,
* entityTypeStruct: TestTest,
* primaryGearTasCode: 77,
* radius: 77
* },
* {
* ...
* }
* ]
* }
*/
void PdmHandler::getChargeTypes()
{
DEBUG_LOG(m_logger) << "Get Charge Types";
QJsonObject obj;
QJsonArray dataArray;
obj[QStringLiteral("type")] = QStringLiteral("ApacheHlaSendChargeTypes");
obj[QStringLiteral("typeId")] = 8005;
QMap<qint32, ProjectDataManagement::ChargeType> chargeTypes = m_dtcPdm->chargeTypes();
QMap<qint32, ProjectDataManagement::GearType> gearTypes = m_dtcPdm->gearTypes();
QMap<qint32, ProjectDataManagement::GearTypeChargeType> gearTypeChargeTypes = m_dtcPdm->gearTypeChargeTypes();
DEBUG_LOG(m_logger) << "Fetched " << chargeTypes.size() << " ChargeTypes to send to WebSocket. Ommiting those without DIS-Entity though.";
for(const ProjectDataManagement::ChargeType &charge : chargeTypes)
{
if (charge.disEntity().empty())
continue;
QJsonObject chargeType;
chargeType[QStringLiteral("id")] = charge.id();
chargeType[QStringLiteral("name")] = QString::fromStdString(charge.name());
chargeType[QStringLiteral("entityTypeStruct")] = QString::fromStdString(charge.disEntity());
int gearTypeId = 0;
// Take first occurence...
for(const ProjectDataManagement::GearTypeChargeType &val : gearTypeChargeTypes)
{
if(val.chargeTypeId() == charge.id())
{
gearTypeId = val.gearTypeId();
break;
}
}
chargeType[QStringLiteral("primaryGearTasCode")] = gearTypes[gearTypeId].tasCode();
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(charge.properties()));
QJsonObject prop = doc.object();
chargeType[QStringLiteral("radius")] = prop[QStringLiteral("impactRadius")];
dataArray.push_back(chargeType);
}
obj[QStringLiteral("data")] = dataArray;
emit sendChargeTypes(obj);
}
} // namespace ApHlaJson
@@ -0,0 +1,43 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include "main_dispatcher.h"
#include "logger.h"
#include "dds_handler.h"
#include <ProjectDataManagement/pdm.hpp>
#include <LtsUtilsCore/data_modification_enum.h>
#include <QObject>
#include <QHash>
#include <QUrl>
#include <QDateTime>
namespace ApHlaJson
{
class MainDispatcher;
class PdmHandler : public QObject
{
Q_OBJECT
public:
explicit PdmHandler(QObject *parent = nullptr);
void getChargeTypes();
signals:
void sendChargeTypes(QJsonObject jsonObj);
public slots:
bool init(MainDispatcher* mainDispatcher);
private:
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_dtcPdm;
LOGGER_T m_logger;
};
} // namespace ApHlaJson
@@ -0,0 +1,58 @@
/**
* Send / Receive telegrams to/from TX/RX directory
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "plugin.h"
#include "main_dispatcher.h"
#include <nglsettings/nglsettings_settings.h>
namespace ApHlaJson
{
//
// TetraXdrPlugin
//
/*!
\brief
\author Niklas Schmidt
\details Plugin to integrate Apache with Hla Enviroment. The plugin receive data from HLA and forward
the data to Excon and Tetra.
Communication directions:
- Excon -> Hla
-# Init \ref hla_handler_rx.cpp
-# VulnerabilityStateChange \ref ppm_handler.cpp
-# ParticipantPositionChanged \ref ppm_handler.cpp
-# ParticipantChanged \ref ppm_handler.cpp
-# SendAllChargeTypes \ref pdm_handler.cpp
- HLA -> Tetra
-# CesHitInformation \ref hla_handler_tx.cpp
- HLA -> Excon
-# PositionReport \ref hla_handler_rx.cpp Defined in \ref training_area_telegrams.cpp
-# StateChangeDirect
-# StateChange
-# StateChangeIndirect
-# EquipmentGearEvent
-# EquipmentGearAssignment
-# EquipmentGearChargeState
-# SpecialSensorData
-# AesModifyRequest \ref aes_handler.cpp
-# ApacheLaserDesignation \ref hla_handler_rx.cpp
\param pdp
\param recvFromTabCb
\param sendToTabCb
\param settings
\return std::shared_ptr<TrainingAreaBase::Plugin::Interface>
*/
std::shared_ptr<TrainingAreaBase::Plugin::Interface> TabApHlaPlugin::createInterface(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
NGL::Settings *settings)
{
return std::make_shared<MainDispatcher>(pdp, recvFromTabCb, sendToTabCb, settings);
}
} // namespace HlaJson
@@ -0,0 +1,30 @@
/**
* Send / Receive telegrams to/from TX/RX directory
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#pragma once
#include <QObject>
#include <TrainingAreaBase/tab_plugin_interface.h>
namespace ApHlaJson
{
class TabApHlaPlugin : public QObject, public TrainingAreaBase::Plugin::Plugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "special:3:tab.aphla")
Q_INTERFACES(TrainingAreaBase::Plugin::Plugin)
public:
TabApHlaPlugin() = default;
~TabApHlaPlugin() = default;
std::shared_ptr<TrainingAreaBase::Plugin::Interface> createInterface(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTab,
NGL::Settings *settings) override;
};
} // namespace ApHlaJson
@@ -0,0 +1,322 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "ppm_handler.h"
#include <QJsonDocument>
namespace ApHlaJson
{
/*!
\brief
\author Niklas Schmidt
\details Recognize changes from PPM and creates new Telegram for these changes, than send to Hla
Excon -> HLA
\param parent
*/
PpmHandler::PpmHandler(QObject *parent)
: QObject(parent)
, m_logger(getLogger("PpmHandler"))
{}
bool PpmHandler::init(MainDispatcher* mainDispatcher)
{
if (m_dtcPpm)
return true;
m_dtcPpm = ParticipantManagement::Interface::Dtc::create(mainDispatcher->ddsHandler()->ddsConnector());
if (!m_dtcPpm->enableParticipant() || !m_dtcPpm->enableDynamicParticipantData() || !m_dtcPpm->enableParticipantPosition())
{
ERROR_LOG(m_logger) << "Can not read data from Ppm";
return false;
}
m_dtcPpm->waitForHistoricalDataParticipant(1000);
m_dtcPpm->waitForHistoricalDataDynamicParticipantData(1000);
m_dtcPpm->waitForHistoricalDataParticipantPosition(1000);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &PpmHandler::onParticipantChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &PpmHandler::onParticipantPositionChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
this, &PpmHandler::onDynamicParticipantDataChanged);
return true;
}
QString PpmHandler::fromDisInt(qint64 value)
{
QString s;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
s.prepend(QLatin1Literal("."));
value /= 1000;
s.prepend(QString::number(value % 1000));
return s;
}
void PpmHandler::getParticipants()
{
if(!m_dtcPpm)
return;
for (const auto participant : m_dtcPpm->participants())
{
onParticipantChanged(participant, DataModification::eAdded);
}
}
bool PpmHandler::isEqNumberInExercise(int equipmentNumber) const
{
bool result = m_dtcPpm->participantIdByEquipmentNumber(equipmentNumber) > 0;
return result;
//return m_participantIdsByEqNo.contains(equipmentNumber);
}
/**
* @brief AddParticipant Telegram
*
*
* @details Example Telegram:
* {
* typeId:8000,
* type: ApacheHlaAddParticipant,
* data:
* {
* header: {
* equipmentNumber: 42,
* timeStamp: MsecsSinceEpoch
* },
* status: 11,
* forceIdentifier: 42,
* ets: "2.0.0.0.0.0.1",
* GeoPosition: {
* lon: 15.145274,
* lat: 24.5554556,
* z: 55.000124
* }
* }
* }
*/
/**
* @brief RemoveParticipant Telegram
*
*
* @details Example Telegram:
* {
* typeId:8001,
* type: ApacheHlaRemoveParticipant,
* data:
* {
* header: {
* equipmentNumber: 42,
* timeStamp: MsecsSinceEpoch
* }
* }
* }
*/
void PpmHandler::onParticipantChanged(const ParticipantManagement::Participant &participant, DataModification modType)
{
//NOTE:Hier kommt er hin!
if(!participant.equipmentNumber().is_set())
{
for(auto it = m_participantIdsByEqNo.begin(); it != m_participantIdsByEqNo.end(); ++it)
if (it.value() == participant.id())
{
m_participantIdsByEqNo.remove(it.key());
break;
}
return;
}
if (participant.externalId() > 0)
return;
QJsonObject headerJson;
headerJson[QStringLiteral("equipmentNumber")] = participant.equipmentNumber().get();
headerJson[QStringLiteral("timeStamp")] = QDateTime::currentMSecsSinceEpoch();
if (modType == DataModification::eRemoved)
{
m_participantIdsByEqNo.remove(participant.equipmentNumber().get());
QJsonObject telegram;
QJsonObject data;
data[QStringLiteral("header")] = headerJson;
telegram[QStringLiteral("data")] = data;
telegram[QStringLiteral("type")] = QStringLiteral("ApacheHlaRemoveParticipant");
telegram[QStringLiteral("typeId")] = 8001;
emit participantChanged(telegram);
return;
}
if (m_participantIdsByEqNo.contains(participant.equipmentNumber().get()))
{
if (m_participantIdsByEqNo[participant.equipmentNumber().get()] != participant.id())
{
for(auto it = m_participantIdsByEqNo.begin(); it != m_participantIdsByEqNo.end(); ++it)
if (it.value() == participant.id())
{
m_participantIdsByEqNo.remove(it.key());
break;
}
m_participantIdsByEqNo[participant.equipmentNumber().get()] = participant.id();
}
}
else
m_participantIdsByEqNo[participant.equipmentNumber().get()] = participant.id();
ParticipantManagement::DynamicParticipantData dynamicData = m_dtcPpm->dynamicParticipantData(participant.id());
ParticipantManagement::Party party = m_dtcPpm->party(participant.partyId());
ParticipantManagement::Type type = m_dtcPpm->type(participant.typeId());
ParticipantManagement::ParticipantPosition partPos = m_dtcPpm->participantPosition(participant.id());
QJsonObject telegram;
QJsonObject geoPositionObj;
geoPositionObj[QStringLiteral("lon")] = partPos.pos().lon();
geoPositionObj[QStringLiteral("lat")] = partPos.pos().lat();
geoPositionObj[QStringLiteral("z")] = partPos.pos().z();
QJsonObject data;
data[QStringLiteral("header")] = headerJson;
data[QStringLiteral("status")] = static_cast<int>(m_dtcPpm->youngestStateInformation(dynamicData.stateHistory()).vulnerabilityState().underlying());
data[QStringLiteral("forceIdentifier")] = static_cast<int>(party.hlaForceIdentifier().underlying());
data[QStringLiteral("ets")] = type.disEntities().empty() ? QStringLiteral("2.0.0.0.0.0.1") : fromDisInt(type.disEntities().front());
data[QStringLiteral("geoPosition")] = geoPositionObj;
telegram[QStringLiteral("data")] = data;
telegram[QStringLiteral("type")] = QStringLiteral("ApacheHlaAddParticipant");
telegram[QStringLiteral("typeId")] = 8000;
emit participantChanged(telegram);
}
/**
* @brief Change Position Telegram
*
*
* @details Example Telegram:
* {
* typeId:8002,
* type: ApacheHlaPositionChanged,
* data:
* {
* header: {
* equipmentNumber: 42,
* timeStamp: MsecsSinceEpoch
* },
* lon: 15.275884,
* lat: 37.854856,
* z: 42.255278
* }
* }
*/
void PpmHandler::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &position, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
ParticipantManagement::Participant part = m_dtcPpm->participant(position.participantId());
if (part.externalId() > 0 || !part.equipmentNumber().is_set())
return;
QJsonObject telegram;
telegram[QStringLiteral("typeId")] = 8002;
telegram[QStringLiteral("type")] = QStringLiteral("ApacheHlaPositionChanged");
QJsonObject headerJson;
headerJson[QStringLiteral("equipmentNumber")] = part.equipmentNumber().get();
headerJson[QStringLiteral("timeStamp")] = QDateTime::currentMSecsSinceEpoch();
QJsonObject data;
data[QStringLiteral("header")] = headerJson;
data[QStringLiteral("lon")] = position.pos().lon();
data[QStringLiteral("lat")] = position.pos().lat();
data[QStringLiteral("z")] = position.pos().z();
telegram[QStringLiteral("data")] = data;
emit participantChanged(telegram);
}
/**
* @brief Change VulnerabilityState Telegram
*
*
* @details Example Telegram:
* {
* typeId:8003,
* type: ApacheHlaVulnerabilityStateChanged,
* data:
* {
* header: {
* equipmentNumber: 42,
* timeStamp: MsecsSinceEpoch
* },
* status: 11
* }
* }
*/
void PpmHandler::onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &dynPartData, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
ParticipantManagement::Participant part = m_dtcPpm->participant(dynPartData.participantId());
if (part.externalId() > 0 || !part.equipmentNumber().is_set())
return;
QJsonObject telegram;
telegram[QStringLiteral("typeId")] = 8003;
telegram[QStringLiteral("type")] = QStringLiteral("ApacheHlaVulnerabilityStateChanged");
QJsonObject headerJson;
headerJson[QStringLiteral("equipmentNumber")] = part.equipmentNumber().get();
headerJson[QStringLiteral("timeStamp")] = QDateTime::currentMSecsSinceEpoch();
QJsonObject data;
data[QStringLiteral("header")] = headerJson;
data[QStringLiteral("status")] = static_cast<int>(m_dtcPpm->youngestStateInformation(dynPartData.stateHistory()).vulnerabilityState().underlying());
telegram[QStringLiteral("data")] = data;
emit participantChanged(telegram);
}
} // namespace ApHlaJson
@@ -0,0 +1,52 @@
/**
* IsmHandler for WirelessLocationSystem
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include "main_dispatcher.h"
#include "logger.h"
#include "dds_handler.h"
#include <ParticipantManagement/ppm.hpp>
#include <ParticipantManagement/ppm_dtc.h>
#include <LtsUtilsCore/data_modification_enum.h>
#include <QObject>
#include <QHash>
#include <QUrl>
#include <QDateTime>
namespace ApHlaJson
{
class MainDispatcher;
class PpmHandler : public QObject
{
Q_OBJECT
public:
explicit PpmHandler(QObject *parent = nullptr);
bool init(MainDispatcher* mainDispatcher);
static QString fromDisInt(qint64 value);
void getParticipants();
bool isEqNumberInExercise(int equipmentNumber) const;
signals:
void participantChanged(const QJsonObject &jsonObj);
private slots:
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType);
void onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType);
void onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType);
private:
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_dtcPpm;
LOGGER_T m_logger;
/*!
* \brief m_participantIdsByEqNo
* \details Used to avoid using ppmDtc always the Apache send CesHitInformation
*/
QHash<int, int> m_participantIdsByEqNo; // eqNo, partId
};
} // namespace ApHlaJson