- Merged 292 changed files from dlbo snapshot - Fixed IDL enum collisions (PortType, PdmEventType) - Fixed Grantlee template for C++11 scoped enums - Fixed CMake VERSION_GREATER syntax - Added missing directories (THP, LtsRestClient, etc.) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1004 lines
42 KiB
C++
Executable File
1004 lines
42 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* JsonDispatcher for Apache Plugin
|
|
* $Id: hla_dispatcher.cpp 62304 2024-03-21 08:17:45Z ewert_j $
|
|
* $HeadURL: svn://slssvn/TDS/branches/product/features/ufom/Lts/Proxies/TrainingAreaBase/Plugins/AdlerJson/hla_dispatcher.cpp $
|
|
* $Author: ewert_j $
|
|
* Created by Julius Ewert, ESIM, 2024-03-20
|
|
*/
|
|
|
|
#include "json_dispatcher.h"
|
|
#include "json_handler_rx.h"
|
|
#include "json_handler_tx.h"
|
|
#include "settings.h"
|
|
#include "ws_handler.h"
|
|
#include <AreaEffectSimulation/aes_operator_rights.h>
|
|
|
|
#include <QHostInfo>
|
|
#include <QJsonDocument>
|
|
#include <QSettings>
|
|
#include <QStringList>
|
|
#include <QTimer>
|
|
#include <QWebSocket>
|
|
#include <nglsettings/nglsettings_settings.h>
|
|
#include <vector>
|
|
|
|
namespace AdlerJson
|
|
{
|
|
JsonDispatcher::JsonDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
|
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
|
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
|
|
NGL::Settings *settings,
|
|
std::shared_ptr<TrainingAreaBase::DdsHandler> &ddsHandler,
|
|
std::shared_ptr<FlmHandler> &flmHandler,
|
|
MainDispatcher *mainDispatcher)
|
|
: TrainingAreaBase::Interface::Fts::AdlerCalculateTrajectoryRequestHandler(ddsHandler->ftsTab())
|
|
, m_recvFromTabCb(recvFromTabCb)
|
|
, m_recvFromWebsocket(std::make_shared<JsonHandlerRx>(recvFromTabCb, sendToTabCb, this, mainDispatcher->aesHandler().get(), mainDispatcher->ppmHandler().get()))
|
|
, m_sendToWebsocket(std::make_shared<JsonHandlerTx>(pdp, mainDispatcher))
|
|
// , m_ddsHandler(ddsHandler)
|
|
, m_mainDispatcher(mainDispatcher)
|
|
, m_flmHandler(flmHandler)
|
|
, m_ppmHandler(mainDispatcher->ppmHandler())
|
|
, m_ftsTab(ddsHandler->ftsTab())
|
|
, m_dtsTab(ddsHandler->dtsTab())
|
|
, m_ftcNom(ddsHandler->ftcNom())
|
|
, m_settings(settings)
|
|
, m_webSocket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
|
|
, m_webSocketInterface(std::make_shared<TrainingAreaBase::WebSocketHandler>())
|
|
, m_webSocketReconnectTimer(new QTimer(this))
|
|
, m_bWarnedOnce(false)
|
|
, m_logger(getLogger("JsonDispatcher"))
|
|
{
|
|
DEBUG_LOG(m_logger) << "JsonDispatcher::JsonDispatcher";
|
|
|
|
m_sendToWebsocket->setWSInterface(m_webSocketInterface);
|
|
connect(m_webSocketInterface.get(), &TrainingAreaBase::WebSocketInterface::recivedTelegram, this, &JsonDispatcher::onRecivedTelegram, Qt::UniqueConnection);
|
|
connect(m_webSocketInterface.get(), &TrainingAreaBase::WebSocketInterface::newConnection, this, &JsonDispatcher::onNewWebsocketConnected, Qt::UniqueConnection);
|
|
connect(m_webSocketInterface.get(), &TrainingAreaBase::WebSocketInterface::wsDisconnected, this, &JsonDispatcher::onWSDisconnected);
|
|
}
|
|
|
|
bool JsonDispatcher::init() { return true; }
|
|
void JsonDispatcher::connectWebsocket()
|
|
{
|
|
DEBUG_LOG(m_logger) << "JsonDispatcher::connectWebsocket()";
|
|
if (!m_webSocketInterface->init(Settings::getWebSocketServerPortRange(3)))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Adler Could not open WebSocketInterface";
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "Adler Could open WebSocketInterface on port " << m_webSocketInterface->getPort();
|
|
}
|
|
emit websocketConnected(m_webSocketInterface->getPort());
|
|
const QUrl url(webSocketUrl());
|
|
if (!m_bWarnedOnce)
|
|
DEBUG_LOG(m_logger) << "Adler: Using WebSocket url: " << url.toString();
|
|
if (m_webSocket->state() != QAbstractSocket::ConnectedState)
|
|
m_webSocket->open(url);
|
|
}
|
|
|
|
void JsonDispatcher::onKeepAliveTimerTimeout()
|
|
{
|
|
QTimer *timer = qobject_cast<QTimer *>(sender());
|
|
int wsId = m_connectionKeepaliveTimer.key(timer);
|
|
DEBUG_LOG(m_logger) << "onKeepAliveTimerTimeout Timeout from " << wsId << " still in list " << (getSAAByWs(wsId) != nullptr);
|
|
|
|
auto saa = getSAAByWs(wsId);
|
|
|
|
if (saa)
|
|
{
|
|
const QUrl saaUrl = m_webSocketInterface->getPeerUrl(wsId);
|
|
const ParticipantManagement::ConnectState connectState = ParticipantManagement::ConnectState::NoHeartbeat;
|
|
const bool isSaaConnected = (connectState == ParticipantManagement::ConnectState::Connected);
|
|
const int assetId = getAssetId(saa->getSAAName());
|
|
DEBUG_LOG(m_logger) << "Timeout from " << saa->getSAAName() << " ==> SAA URL: " << saaUrl.toString();
|
|
m_ppmHandler
|
|
->modifyPartyAdlerProperties(wsId, assetId, saa->getPartyId(), saa->getSAAName(), saa->getSzenarName(), connectState, saa->getIsVerbund());
|
|
m_mainDispatcher->asmHandler()->modifyAssetAdlerProperties(assetId, isSaaConnected);
|
|
saa->setIsAlive(false);
|
|
}
|
|
else
|
|
ERROR_LOG(m_logger) << "Trying to remove an saa after timeout with the websocketId: " << wsId << " that is not connected";
|
|
|
|
m_connectionKeepaliveTimer.remove(wsId);
|
|
timer->stop();
|
|
timer->deleteLater();
|
|
}
|
|
|
|
int JsonDispatcher::getAssetId(const QString &saaName) const
|
|
{
|
|
std::function<QString(const std::string &)> saaNameFromProps = [](const std::string &props) -> QString
|
|
{
|
|
const QJsonObject propObj = QJsonDocument::fromJson(QByteArray::fromStdString(props)).object();
|
|
if (!propObj.contains(QStringLiteral("credentials")))
|
|
return {};
|
|
|
|
const QJsonObject adlerObj = propObj[QStringLiteral("credentials")].toObject();
|
|
return adlerObj.value(QStringLiteral("saaName")).toString();
|
|
};
|
|
|
|
for (const auto &currAsset : m_mainDispatcher->asmHandler()->getDtc()->assets())
|
|
{
|
|
if (currAsset.assetTypeId() != AssetManagement::AssetType_def::AdlerSAA)
|
|
continue;
|
|
const auto &dbSaa = saaNameFromProps(currAsset.properties());
|
|
|
|
if (dbSaa.toLower() != saaName.toLower())
|
|
continue;
|
|
|
|
return currAsset.id();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
std::shared_ptr<TrainingAreaBase::SendToTab> JsonDispatcher::sendToTab() { return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_sendToWebsocket); }
|
|
|
|
bool JsonDispatcher::canSendData() const { return m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState; }
|
|
void JsonDispatcher::onNewWebsocketConnected(const int wsId, const QString &address, qint16 port)
|
|
{
|
|
DEBUG_LOG(m_logger) << "New Connection from: " << address << ", port: " << port << ", with id: " << wsId;
|
|
}
|
|
void JsonDispatcher::onWSDisconnected(const int wsId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Connection disconnect wsId: " << wsId;
|
|
auto saa = getSAAByWs(wsId);
|
|
|
|
if (saa)
|
|
onSAADeregistration(wsId, saa->getPartyId());
|
|
}
|
|
std::shared_ptr<SAAInterface> JsonDispatcher::getSAAByParty(const int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "getSAAByParty partyId: " << partyId;
|
|
if (m_saaInterfaces.empty())
|
|
return nullptr;
|
|
auto it
|
|
= std::find_if(m_saaInterfaces.begin(), m_saaInterfaces.end(), [partyId](const std::shared_ptr<SAAInterface> &saa) { return saa.get()->getPartyId() == partyId; });
|
|
return it != m_saaInterfaces.end() ? *it : nullptr;
|
|
}
|
|
std::shared_ptr<SAAInterface> JsonDispatcher::getSAAByName(const QString &saaName)
|
|
{
|
|
auto it
|
|
= std::find_if(m_saaInterfaces.begin(), m_saaInterfaces.end(), [saaName](const std::shared_ptr<SAAInterface> &saa) { return saa.get()->getSAAName() == saaName; });
|
|
return it != m_saaInterfaces.end() ? *it : nullptr;
|
|
}
|
|
|
|
std::shared_ptr<SAAInterface> JsonDispatcher::getSAAByWs(const int wsId)
|
|
{
|
|
TRACE_LOG(m_logger) << "m_saaInterfaces.size :" << m_saaInterfaces.size() << ", wsId=" << wsId;
|
|
for (int i = 0; i < m_saaInterfaces.size(); i++)
|
|
TRACE_LOG(m_logger) << "i=" << i << ", getPartyId :" << m_saaInterfaces[i]->getPartyId() << ", getWsId :" << m_saaInterfaces[i]->getWsId();
|
|
|
|
auto it = std::find_if(m_saaInterfaces.begin(), m_saaInterfaces.end(), [wsId](const std::shared_ptr<SAAInterface> &saa) { return saa.get()->getWsId() == wsId; });
|
|
return it != m_saaInterfaces.end() ? *it : nullptr;
|
|
}
|
|
|
|
bool JsonDispatcher::sendExFeuerbereit(const ExFeuerbereit &exFBDataIn, const int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TRY SEND EXFeuerbereit attempt for party " << partyId;
|
|
auto saa = getSAAByParty(partyId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "sendExFeuerbereit no saa for paty:" << partyId;
|
|
return false;
|
|
}
|
|
|
|
ExFeuerbereit exFB = exFBDataIn;
|
|
exFB.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
exFB.receiver = saa->getSAAName();
|
|
exFB.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
WARNING_LOG(m_logger) << "TRY SEND EXFeuerbereit attempt for SAA NAME " << saa->getSAAName() << " esid " << saa->getWsId();
|
|
m_sendToWebsocket->onGenericTelegram1(saa->getWsId(), exFB.toJson());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JsonDispatcher::sendExAbgefeuert(const ExAbgefeuert &exAFDataIn, const int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TRY SEND EXFeuerbereit attempt for party " << partyId;
|
|
auto saa = getSAAByParty(partyId);
|
|
if (!saa)
|
|
return false;
|
|
|
|
ExAbgefeuert exAF = exAFDataIn;
|
|
exAF.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
exAF.receiver = saa->getSAAName();
|
|
exAF.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
WARNING_LOG(m_logger) << "TRY SEND sendExAbgefeuert attempt for SAA NAME " << saa->getSAAName() << " esid " << saa->getWsId();
|
|
m_sendToWebsocket->onGenericTelegram1(saa->getWsId(), exAF.toJson());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JsonDispatcher::sendExMqManuelleQuittung(const ExMqManuelleQuittung &exMQDataIn, int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TRY SEND ExMqManuelleQuittung attempt for party " << partyId;
|
|
auto saa = getSAAByParty(partyId);
|
|
if (!saa)
|
|
return false;
|
|
|
|
ExMqManuelleQuittung exMQ = exMQDataIn;
|
|
exMQ.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
exMQ.receiver = saa->getSAAName();
|
|
exMQ.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
DEBUG_LOG(m_logger) << "TRY SEND ExMqManuelleQuittung attempt for SAA NAME " << saa->getSAAName() << " esid " << saa->getWsId();
|
|
m_sendToWebsocket->onGenericTelegram1(saa->getWsId(), exMQ.toJson());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JsonDispatcher::sendExTqTechnischeQuittung(const ExTqTechnischeQuittung &exTQDataIn, int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TRY SEND ExTqTechnischeQuittung attempt for party " << partyId;
|
|
auto saa = getSAAByParty(partyId);
|
|
if (!saa)
|
|
return false;
|
|
|
|
ExTqTechnischeQuittung exMQ = exTQDataIn;
|
|
exMQ.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
exMQ.receiver = saa->getSAAName();
|
|
exMQ.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
DEBUG_LOG(m_logger) << "TRY SEND ExMqManuelleQuittung attempt for SAA NAME " << saa->getSAAName() << " esid " << saa->getWsId();
|
|
m_sendToWebsocket->onGenericTelegram1(saa->getWsId(), exMQ.toJson());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JsonDispatcher::sendExVollzugsmeldung(const ExVollzugsmeldung &exVZDataIn, int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TRY SEND ExVollzugsmeldung attempt for party " << partyId;
|
|
auto saa = getSAAByParty(partyId);
|
|
if (!saa)
|
|
return false;
|
|
|
|
ExVollzugsmeldung exVZ = exVZDataIn;
|
|
exVZ.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
exVZ.receiver = saa->getSAAName();
|
|
exVZ.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
WARNING_LOG(m_logger) << "TRY SEND ExVollzugsmeldung attempt for SAA NAME " << saa->getSAAName() << " WSID " << saa->getWsId();
|
|
m_sendToWebsocket->onGenericTelegram1(saa->getWsId(), exVZ.toJson());
|
|
return true;
|
|
}
|
|
|
|
void JsonDispatcher::onSAARegistration(const int wsId, const int partyId, const QString &saaName, const QString &szenarName, bool isVerbund, const QString &uuid)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Registration attempt from " << saaName << " for party " << partyId << ", saaName: " << saaName << ", uuid: " << uuid << ", wsId: " << wsId;
|
|
ExAnmeldebestaetigung exRC;
|
|
exRC.referenceUuid = uuid;
|
|
exRC.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
exRC.anBestaetigungsdaten.error = AdlerJson::L45_AnmeldebestaetigungFehlercode::Ok;
|
|
auto saa = getSAAByName(saaName);
|
|
DEBUG_LOG(m_logger) << "is saa " << saa;
|
|
if (saa)
|
|
{
|
|
DEBUG_LOG(m_logger) << "saa.get()->getPartyId(): " << saa.get()->getPartyId() << " partyId: " << partyId;
|
|
if (saa.get()->getPartyId() == partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "saa already connected, reconnect!";
|
|
// exRC.anBestaetigungsdaten.error = AdlerJson::L45_AnmeldebestaetigungFehlercode::Doppelt;
|
|
onSAADeregistration(saa.get()->getWsId(), partyId);
|
|
// TODO: emit or answer with saa already connected
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "other saa connected to this party";
|
|
|
|
// exRC.anBestaetigungsdaten.error = AdlerJson::L45_AnmeldebestaetigungFehlercode::Mehrfach;
|
|
// TODO: emit or answer with other saa connected to this party
|
|
}
|
|
}
|
|
else if (getSAAByParty(partyId))
|
|
{
|
|
DEBUG_LOG(m_logger) << "party is used by other saa";
|
|
// exRC.anBestaetigungsdaten.error = AdlerJson::L45_AnmeldebestaetigungFehlercode::Belegt;
|
|
// TODO: emit or answer party is used by other saa
|
|
}
|
|
// else
|
|
{
|
|
auto newSaa = std::make_shared<SAAInterface>(wsId, partyId, saaName, szenarName, isVerbund);
|
|
newSaa->init(m_ppmHandler, m_mainDispatcher->pdmHandler(), m_mainDispatcher->aesHandler(), m_dtsTab);
|
|
// cleanUp first
|
|
cleanupSaaInterfaces(saaName, wsId, partyId);
|
|
m_saaInterfaces.append(newSaa);
|
|
// We created a new SAA, start keep alive procedure
|
|
int adlerOffset = m_settings->settings()->value(QLatin1String("TrainingAreaBase/AdlerKeepalive"), 30000).toInt();
|
|
DEBUG_LOG(m_logger) << "adlerOffset =" << adlerOffset;
|
|
if (adlerOffset > 0)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Started SAA with Keppalive Timer: " << adlerOffset;
|
|
QTimer *keepaliveTimer = new QTimer(this);
|
|
keepaliveTimer->setInterval(adlerOffset);
|
|
m_connectionKeepaliveTimer.insert(wsId, keepaliveTimer);
|
|
connect(keepaliveTimer, &QTimer::timeout, this, &JsonDispatcher::onKeepAliveTimerTimeout);
|
|
keepaliveTimer->start();
|
|
}
|
|
saa = newSaa;
|
|
// Won't cleanup in Debug as the simulator won't send continous EX_VerbindugsAnfrage
|
|
|
|
DEBUG_LOG(m_logger) << "emit or answer without error wsId: " << wsId;
|
|
}
|
|
exRC.sender = getSender();
|
|
exRC.receiver = saa->getSAAName();
|
|
// Send Answer to SAA
|
|
m_sendToWebsocket->onGenericTelegram1(wsId, exRC.toJson());
|
|
|
|
// if we declined the registration don't update ppm/asm
|
|
if (exRC.anBestaetigungsdaten.error != AdlerJson::L45_AnmeldebestaetigungFehlercode::Ok)
|
|
return;
|
|
|
|
// Initialize HQ-Folders if not exist
|
|
m_flmHandler->initHQFolders(partyId);
|
|
// Modify Party
|
|
const ParticipantManagement::ConnectState connectState = ParticipantManagement::ConnectState::Connected;
|
|
const bool isSaaConnected = (connectState == ParticipantManagement::ConnectState::Connected);
|
|
const int assetId = getAssetId(saaName);
|
|
DEBUG_LOG(m_logger) << "onSAARegistration modifyParty"
|
|
<< " ==> SAA name " << saaName;
|
|
createNotificationRequest(wsId, QString::fromUtf8(tr_lts("Notification", "Reconnect to SAA")),
|
|
NotificationManagement::MessageType_def::Success,
|
|
NotificationManagement::NotificationType::AdlerNotification,
|
|
saaName,
|
|
{});
|
|
|
|
m_ppmHandler->modifyPartyAdlerProperties(wsId, assetId, partyId, saaName, szenarName, connectState, saa->getIsVerbund());
|
|
m_mainDispatcher->asmHandler()->modifyAssetAdlerProperties(assetId, isSaaConnected);
|
|
}
|
|
|
|
void JsonDispatcher::onSAADeregistration(const int wsId, const int partyId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAADeregistration"
|
|
<< " wsId: " << wsId << ", partyId: " << partyId;
|
|
auto saa = getSAAByWs(wsId);
|
|
|
|
if (saa)
|
|
{
|
|
const ParticipantManagement::ConnectState connectState = ParticipantManagement::ConnectState::Disconnected;
|
|
const bool isSaaConnected = (connectState == ParticipantManagement::ConnectState::Connected);
|
|
const int assetId = getAssetId(saa->getSAAName());
|
|
DEBUG_LOG(m_logger) << "Deregistation from " << saa->getSAAName();
|
|
createNotificationRequest(wsId, QString::fromUtf8(tr_lts("Notification", "SAADeregistration")),
|
|
NotificationManagement::MessageType_def::Info,
|
|
NotificationManagement::NotificationType::AdlerNotification,
|
|
saa->getSAAName(),
|
|
{});
|
|
m_ppmHandler->modifyPartyAdlerProperties(wsId, assetId, partyId, {}, {}, connectState, saa->getIsVerbund());
|
|
m_mainDispatcher->asmHandler()->modifyAssetAdlerProperties(assetId, isSaaConnected);
|
|
m_saaInterfaces.removeOne(saa);
|
|
}
|
|
else
|
|
ERROR_LOG(m_logger) << "Trying to remove an saa with the websocketId: " << wsId << " that is not connected";
|
|
}
|
|
|
|
void JsonDispatcher::onSAAConnectionTest(const int wsId, const QString &uuid)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAAConnectionTest"
|
|
<< " wsId: " << wsId << ", uuid: " << uuid;
|
|
|
|
auto saa = getSAAByWs(wsId);
|
|
if (saa)
|
|
{
|
|
if (!saa->getIsAlive())
|
|
{
|
|
saa->setIsAlive(true);
|
|
}
|
|
|
|
QTimer *connectionTimer = m_connectionKeepaliveTimer.value(wsId);
|
|
if (connectionTimer)
|
|
{
|
|
DEBUG_LOG(m_logger) << "connectionTimer->start()";
|
|
connectionTimer->start(); // Restarts the KeepAlive Timer
|
|
}
|
|
DEBUG_LOG(m_logger) << "ConnectionTest from " << saa->getSAAName();
|
|
EXConnectionTestReply exCTR;
|
|
exCTR.referenceUuid = uuid;
|
|
exCTR.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
QJsonObject reply = exCTR.toJson();
|
|
m_sendToWebsocket->onGenericTelegram1(wsId, reply);
|
|
}
|
|
}
|
|
void JsonDispatcher::onSAAStatus(const int wsId, const EXStatus &status)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAAStatus"
|
|
<< " wsId: " << wsId << ", status: " << static_cast<int>(status.status);
|
|
auto saa = getSAAByWs(wsId);
|
|
|
|
if (saa)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Status from " << saa->getSAAName() << AdlerJson::szenarstatusToStr(status.status);
|
|
saa->setStatus(status.status);
|
|
QString title;
|
|
switch (status.status)
|
|
{
|
|
case AdlerJson::Szenarstatus::Inaktiv:
|
|
title = QString::fromUtf8(tr_lts("Notification", "Inactive"));
|
|
break;
|
|
case AdlerJson::Szenarstatus::Geplant:
|
|
title = QString::fromUtf8(tr_lts("Notification", "Planned"));
|
|
break;
|
|
case AdlerJson::Szenarstatus::Aktiv:
|
|
title = QString::fromUtf8(tr_lts("Notification", "Active"));
|
|
break;
|
|
case AdlerJson::Szenarstatus::Gestoppt:
|
|
title = QString::fromUtf8(tr_lts("Notification", "Stopped"));
|
|
break;
|
|
}
|
|
createNotificationRequest(wsId,
|
|
title,
|
|
NotificationManagement::MessageType_def::Success,
|
|
NotificationManagement::NotificationType::AdlerNotification,
|
|
saa->getSAAName(),
|
|
{});
|
|
|
|
}
|
|
}
|
|
|
|
QString JsonDispatcher::getParticipantInfoLink(const QString &verein, const int partyId, const bool isVerbund)
|
|
{
|
|
const ParticipantManagement::Participant &part = m_ppmHandler->findParticipantByInternalName(verein, partyId, isVerbund);
|
|
DEBUG_LOG(m_logger) << "ParticipantId=" << part.id();
|
|
|
|
QString ppmlink = QString::fromUtf8(tr_lts("Notification","<a href='lts://ParticipantInfo/%1'>Show Participant Info</a><br />"))
|
|
.arg(part.id());
|
|
|
|
|
|
return ppmlink;
|
|
}
|
|
|
|
void JsonDispatcher::onSAAExceptionStatus(const int wsId, const TechnischeDaten &exceptionStatus)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAAExceptionStatus"
|
|
<< ", wsId: " << wsId << ", status: " << StatusL32Map.key(exceptionStatus.status) << ", beschreibung: " << exceptionStatus.beschreibung;
|
|
const auto saa = getSAAByWs(wsId);
|
|
|
|
DEBUG_LOG(m_logger) << "Sende Notification Technische Quittung";
|
|
|
|
QString content = QString::fromUtf8(tr_lts("Notification", "<B>Status: </B>%1<br /><B> Description: </B>%2"));
|
|
|
|
QStringList args;
|
|
// INV = Meldung nicht gültig nach JSON-Schema.
|
|
// DAT = Datenkonsistenzfehler.
|
|
if (StatusL32Map.key(exceptionStatus.status) == QStringLiteral("INV"))
|
|
args << QString::fromUtf8(tr_lts("Notification", "Message is not valid according to JSON schema."));
|
|
|
|
else
|
|
args << QString::fromUtf8(tr_lts("Notification", "Data Consistency Error"));
|
|
|
|
args << exceptionStatus.beschreibung;
|
|
createNotificationRequest(wsId, QString::fromUtf8(tr_lts("Notification","Error Message from SAA")),
|
|
NotificationManagement::MessageType_def::Error,
|
|
NotificationManagement::NotificationType::AdlerNotification,
|
|
content,
|
|
args);
|
|
}
|
|
|
|
void JsonDispatcher::onSAASQWS(const int wsId, const Waffensystemdaten &exSQWS)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAASQWS";
|
|
const bool isVerbund = true;
|
|
auto saa = getSAAByWs(wsId);
|
|
int partyId = saa->getPartyId();
|
|
const ParticipantManagement::Participant &part = m_ppmHandler->findParticipantByInternalName(exSQWS.einheit.verein, partyId, isVerbund);
|
|
|
|
m_ppmHandler->parseSQWS(exSQWS, wsId);
|
|
if (part.id() > 0)
|
|
{
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQWS.einheit);
|
|
return;
|
|
}
|
|
QTimer::singleShot(5000, this, [this, wsId, partyId, isVerbund, exSQWS]() {
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQWS.einheit);
|
|
});
|
|
}
|
|
|
|
void JsonDispatcher::onSAASQFS(const int wsId, const Feuerstellungsdaten &exSQFS)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAASQFS";
|
|
auto saa = getSAAByWs(wsId);
|
|
int partyId = saa->getPartyId();
|
|
const bool isVerbund = true;
|
|
|
|
m_ppmHandler->parseSQFS(exSQFS, wsId);
|
|
const ParticipantManagement::Participant &part = m_ppmHandler->findParticipantByInternalName(exSQFS.feuereinheit.verein, partyId, isVerbund);
|
|
if (part.id() > 0)
|
|
{
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQFS.feuereinheit);
|
|
return;
|
|
}
|
|
QTimer::singleShot(5000, this, [this, wsId, partyId, isVerbund, exSQFS]() {
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQFS.feuereinheit);
|
|
});
|
|
}
|
|
|
|
void JsonDispatcher::onSAASQLP(const int wsId, const Ladeplatzdaten &exSQLP)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAASQLP";
|
|
auto saa = getSAAByWs(wsId);
|
|
int partyId = saa->getPartyId();
|
|
const bool isVerbund = true;
|
|
|
|
const ParticipantManagement::Participant &part = m_ppmHandler->findParticipantByInternalName(exSQLP.einheit.verein, partyId, isVerbund);
|
|
|
|
|
|
m_ppmHandler->parseSQLP(exSQLP, wsId);
|
|
if (part.id() > 0)
|
|
{
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQLP.einheit);
|
|
return;
|
|
}
|
|
QTimer::singleShot(5000, this, [this, wsId, partyId, exSQLP]() {
|
|
sendParticipantInfoNotification(wsId, partyId, isVerbund, exSQLP.einheit);
|
|
});
|
|
}
|
|
|
|
void JsonDispatcher::sendParticipantInfoNotification(const int wsId, const int partyId, const bool isVerbund, const Einheit &einheit)
|
|
{
|
|
DEBUG_LOG(m_logger) << "sendParticipantInfoNotification";
|
|
QStringList args;
|
|
|
|
const ParticipantManagement::Participant &part = m_ppmHandler->findParticipantByInternalName(einheit.verein, partyId, isVerbund);
|
|
DEBUG_LOG(m_logger) << "sendParticipantInfoNotification ParticipantId=" << part.id();
|
|
|
|
QString content = QString::fromUtf8(tr_lts("Notification","<a href='lts://ParticipantInfo/%1'>Show Participant Info</a><br /><B>Unit:</B> %2/%3/%4"));
|
|
|
|
args.append(QString::number(part.id()));
|
|
args.append(ortsIdMap.key(einheit.oi));
|
|
args.append(QString::number(einheit.r));
|
|
args.append(einheit.verein);
|
|
|
|
createNotificationRequest(wsId,
|
|
QString::fromUtf8(tr_lts("Notification","Loading Point Position Report")),
|
|
NotificationManagement::MessageType_def::Info,
|
|
NotificationManagement::NotificationType::AdlerNotification,
|
|
content,
|
|
args);
|
|
DEBUG_LOG(m_logger) << "Stellungsmeldung content=" << content;
|
|
}
|
|
|
|
void JsonDispatcher::onSAATrajectoryData(const int wsId, const Flugbahndaten &exFlugbahndaten, const QString referenceUuid)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onSAATrajectoryData wsId=" << wsId << ", referenceUuid :" << referenceUuid;
|
|
auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "onSAATrajectoryData but SAA with wsId " << wsId << " not found";
|
|
return;
|
|
}
|
|
QString referenceUuidAlt = referenceUuid;
|
|
referenceUuidAlt = referenceUuidAlt.replace(QStringLiteral("-"), QStringLiteral(""));
|
|
if (!m_trajectoryIdentifier.contains(referenceUuidAlt))
|
|
{
|
|
DEBUG_LOG(m_logger) << "referenceUuid not found in m_trajectoryIdentifier"
|
|
<< ", referenceUuid : " << referenceUuidAlt;
|
|
for (auto it = m_trajectoryIdentifier.constBegin(); it != m_trajectoryIdentifier.constEnd(); ++it)
|
|
{
|
|
DEBUG_LOG(m_logger) << "m_trajectoryIdentifier key : " << it.key() << ", value aesItemId :" << it.value().aesItemId << ", explosionId :" << it.value().explosionId;
|
|
}
|
|
}
|
|
|
|
TrajectoryIdentifier trajectoryIdentifier = m_trajectoryIdentifier.value(referenceUuidAlt);
|
|
m_trajectoryIdentifier.remove(referenceUuidAlt);
|
|
|
|
// Parse in party SAA
|
|
const Core::GeoPosition positionLaunch = m_positionsLaunch.value(referenceUuidAlt);
|
|
m_positionsLaunch.remove(referenceUuidAlt);
|
|
saa->parseFlugbahndaten(exFlugbahndaten, trajectoryIdentifier.aesItemId, trajectoryIdentifier.explosionId, positionLaunch);
|
|
}
|
|
|
|
void JsonDispatcher::onSAAHXGuidingLines(const int wsId, const Koordinierungsdaten &koordinierungsdaten)
|
|
{
|
|
auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "SQ HX (K) from SAA but SAA with id " << wsId << " not found";
|
|
return;
|
|
}
|
|
|
|
int partyId = saa->getPartyId();
|
|
QJsonObject obj;
|
|
koordinierungsdatenToJson(obj, koordinierungsdaten);
|
|
m_flmHandler->processHQMessage(partyId, koordinierungsdaten.name, koordinierungsdaten.meldungsnummer, obj);
|
|
}
|
|
|
|
void JsonDispatcher::onSAAHXGuidingLinesAndBoundaries(const int wsId, const Fuehrungsdaten &fuehrungsdaten)
|
|
{
|
|
auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "SQ HX (G) from SAA but SAA with id " << wsId << " not found";
|
|
return;
|
|
}
|
|
|
|
int partyId = saa->getPartyId();
|
|
QJsonObject obj;
|
|
fuehrungsdatenToJson(obj, fuehrungsdaten);
|
|
|
|
m_flmHandler->processHQMessage(partyId, fuehrungsdaten.name, fuehrungsdaten.meldungsnummer, obj);
|
|
}
|
|
|
|
void JsonDispatcher::onSSAEXFIREHALT(const int wsId, const FeuerHaltDaten &feuerhaltdaten)
|
|
{
|
|
const auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "EX-FH from SSA but SAA with id " << wsId << " not found";
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << "[EX-FH] data from SSA " << wsId << " : "
|
|
<< "verein: " << feuerhaltdaten.verein << " "
|
|
<< "kenner: " << feuerhaltdaten.kenner.underlying() << " "
|
|
<< "kategorie: " << feuerhaltdaten.kategorie.underlying() << " "
|
|
<< "feuerkampfReferenz: " << feuerhaltdaten.feuerkampfReferenz << " "
|
|
<< "zpNummer: " << feuerhaltdaten.zpNummer << " "
|
|
<< "koordinaten: "
|
|
<< "{ lat: " << feuerhaltdaten.koordinate.latitude << " | lng: " << feuerhaltdaten.koordinate.longitude << "} "
|
|
<< "radius: " << feuerhaltdaten.radius << " "
|
|
<< "entladenSchuss: " << feuerhaltdaten.entladenSchuss << " ";
|
|
|
|
const int partyId = saa->getPartyId();
|
|
|
|
const ProjectDataManagement::L22_FireHaltCategory kategorie = feuerhaltdaten.kategorie;
|
|
const ProjectDataManagement::L27_EffectorId kenner = feuerhaltdaten.kenner;
|
|
|
|
AreaEffectSimulation::EffectClusterFireHaltRequest req;
|
|
|
|
req.partyId(partyId);
|
|
req.fireHaltCategory(kategorie);
|
|
req.kenner(kenner);
|
|
req.longitude(feuerhaltdaten.koordinate.longitude);
|
|
req.latitude(feuerhaltdaten.koordinate.latitude);
|
|
req.radius(feuerhaltdaten.radius);
|
|
req.entladenSchuss(feuerhaltdaten.entladenSchuss);
|
|
|
|
const bool bRet = m_mainDispatcher->aesHandler()->getFtc()->effectClusterFireHaltRequest(req);
|
|
|
|
if (bRet && kategorie == ProjectDataManagement::L22_FireHaltCategory::E && !feuerhaltdaten.entladenSchuss) //we can send the EXVollzugsmeldung immediatly
|
|
{
|
|
Feuerkampfdaten fkd;
|
|
fkd.feuerkampfReferenz = feuerhaltdaten.feuerkampfReferenz;
|
|
fkd.kenner = feuerhaltdaten.kenner;
|
|
fkd.verein = feuerhaltdaten.verein;
|
|
|
|
ExVollzugsmeldung exvm;
|
|
exvm.feuerkampfdaten = fkd;
|
|
sendExVollzugsmeldung(exvm, partyId);
|
|
}
|
|
createNotificationRequest(wsId,
|
|
QString::fromUtf8(tr_lts("Notification","Hold your fire")),
|
|
NotificationManagement::MessageType_def::Info,
|
|
NotificationManagement::NotificationType::CombatOrder,
|
|
saa->getSAAName(),
|
|
{});
|
|
}
|
|
|
|
void JsonDispatcher::onWebSocketConnected()
|
|
{
|
|
QWebSocket *ws = qobject_cast<QWebSocket *>(sender());
|
|
m_sendToWebsocket->onWebSocketConnected(ws);
|
|
m_webSocketReconnectTimer->stop();
|
|
m_bWarnedOnce = false;
|
|
}
|
|
|
|
void JsonDispatcher::onWebsocketExternalConnectionStateChanged(bool bConnected)
|
|
{
|
|
m_sendToWebsocket->onWebsocketConnectedToExternalSystem(bConnected);
|
|
emit connectionState(QString::fromUtf8(name()), bConnected);
|
|
}
|
|
|
|
void JsonDispatcher::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);
|
|
}
|
|
|
|
bool JsonDispatcher::isConnectionTest(QJsonDocument &doc)
|
|
{
|
|
QJsonObject obj = doc.object();
|
|
QString key = QStringLiteral("type");
|
|
QString value = QStringLiteral("EX-Verbindungsanfrage");
|
|
|
|
if (obj.contains(key))
|
|
{
|
|
QJsonValue val = obj.value(key);
|
|
|
|
if (val.toString() == value)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void JsonDispatcher::onRecivedTelegram(int wsId, const QJsonObject &telegram)
|
|
{
|
|
|
|
QJsonDocument doc(telegram);
|
|
if (!isConnectionTest(doc))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Text Message received: " << doc.toJson() << ", wsId: " << wsId;
|
|
}
|
|
else
|
|
{
|
|
TRACE_LOG(m_logger) << "Text Message received: " << doc.toJson() << ", wsId: " << wsId;
|
|
}
|
|
// convert from json to internal representation, send to TAB
|
|
int errorcode = 0;
|
|
m_recvFromWebsocket->handleTelegram(wsId, telegram, errorcode);
|
|
|
|
// now that it's handled look at the error code and if it's EX_FLUGDATEN
|
|
// then return errorcode
|
|
|
|
TRACE_LOG(m_logger) << "errorcode = " << errorcode;
|
|
const int typeId = telegram[JsonKeys::TYPE_ID()].toInt();
|
|
if (typeId != TelegramIds::EX_FLUGBAHNDATEN())
|
|
return;
|
|
if (errorcode > 0)
|
|
{
|
|
FlugbahnberechnungFehlercode fehlercode = static_cast<FlugbahnberechnungFehlercode>(errorcode);
|
|
QString errorStr = FehlercodeMap.key(fehlercode);
|
|
|
|
QString completeErrorStr = QStringLiteral("Calculate Trajectory failed: ") + errorStr;
|
|
DEBUG_LOG(m_logger) << "errorStr :" << errorStr << ", completeErrorStr :" << completeErrorStr;
|
|
|
|
Core::FunctionReplyObject reply = Core::FunctionReplyObject(-1, tr_lts("dds", completeErrorStr.toStdString()), {errorStr.toStdString()});
|
|
reply.setId(m_explosionIndex);
|
|
m_ftsTab->adlerCalculateTrajectoryReply(m_cookieCalculateTrajectoryAdler, reply);
|
|
}
|
|
else
|
|
{
|
|
Core::FunctionReplyObject reply;
|
|
reply.setId(m_explosionIndex);
|
|
m_ftsTab->adlerCalculateTrajectoryReply(m_cookieCalculateTrajectoryAdler, reply);
|
|
}
|
|
}
|
|
void JsonDispatcher::onTextMessageReceived(const QByteArray &message)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Text Message received: " << message;
|
|
// convert from json to internal representation, send to TAB
|
|
m_recvFromWebsocket->handleTelegram(message);
|
|
}
|
|
|
|
QUrl JsonDispatcher::webSocketUrl() const { return QUrl(QStringLiteral("ws://127.0.0.1:7069")); }
|
|
|
|
void JsonDispatcher::onAdlerCalculateTrajectoryRequest(const rti::core::SampleIdentity &cookie, const AdlerCalculateTrajectoryRequest &request)
|
|
{
|
|
Core::FunctionReplyObject ret;
|
|
m_explosionIndex = request.explosionIndex();
|
|
m_cookieCalculateTrajectoryAdler = cookie;
|
|
DEBUG_LOG(m_logger) << "Adler Plugin onSendCalculateTrajectoryAdlerRequest"
|
|
<< ", m_saaInterfaces.size=" << m_saaInterfaces.size();
|
|
|
|
int wsId = 0;
|
|
std::shared_ptr<SAAInterface> saaInterface = getSAAByParty(request.partyId());
|
|
if (saaInterface)
|
|
wsId = saaInterface->getWsId();
|
|
|
|
if (wsId == 0)
|
|
{
|
|
DEBUG_LOG(m_logger) << " No wsId found wsId=" << wsId << " return";
|
|
ret.setId(request.explosionIndex());
|
|
m_ftsTab->adlerCalculateTrajectoryReply(cookie, ret);
|
|
|
|
return;
|
|
}
|
|
DEBUG_LOG(m_logger) << "Adler Plugin onSendCalculateTrajectoryAdlerRequest"
|
|
<< " connect to SAA and send data"
|
|
<< ", partyId :" << request.partyId() << ", wsId :" << wsId;
|
|
ExFlugbahnberechnung exFlugbahnberechnung;
|
|
|
|
exFlugbahnberechnung.sender = QStringLiteral("EXCON@GUEZ.DE");
|
|
auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
ERROR_LOG(m_logger) << "SQ WS from SAA but SAA with id " << wsId << " not found";
|
|
return;
|
|
}
|
|
exFlugbahnberechnung.receiver = saa->getSAAName();
|
|
exFlugbahnberechnung.timestamp = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate);
|
|
exFlugbahnberechnung.version = QStringLiteral("0.0.5");
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.standort.koordinate.latitude = request.positionLaunch().lat() * 180.0 / M_PI;
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.standort.koordinate.longitude = request.positionLaunch().lon() * 180.0 / M_PI;
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.standort.hoehe = request.positionLaunch().z();
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.zielkoordinate.koordinate.latitude = request.positionTarget().lat() * 180.0 / M_PI;
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.zielkoordinate.koordinate.longitude = request.positionTarget().lon() * 180.0 / M_PI;
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.zielkoordinate.hoehe = request.positionTarget().z();
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.waffensystem = ProjectDataManagement::L26_EffectingSystemType::inner_enum(request.weaponSystemType().underlying() + 1);
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 weaponSystemType " << request.weaponSystemType().underlying();
|
|
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 L26_EffectingSystemType " << exFlugbahnberechnung.flugbahnberechnungDaten.waffensystem;
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.geschosssorte
|
|
= m_mainDispatcher->pdmHandler()->getDtc()->adlerChargeTypeName(request.trajectory().chargeTypeId());
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 chargeTypeId " << request.trajectory().chargeTypeId();
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 geschosssorte " << exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.geschosssorte;
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.zuender = m_mainDispatcher->pdmHandler()->getDtc()->adlerIgniterTypeName(request.trajectory().igniterTypeId());
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 igniterTypeId " << request.trajectory().igniterTypeId();
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 zuender " << exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.zuender;
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.zuenderFunktion
|
|
= m_mainDispatcher->pdmHandler()->getDtc()->adlerIgniterFunctionName(request.trajectory().igniterFunctionId());
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 igniterFunctionId " << request.trajectory().igniterFunctionId();
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 zuenderFunktion " << exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.zuenderFunktion;
|
|
|
|
if (request.trajectory().loadTypeId() > 0)
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.ladung = m_mainDispatcher->pdmHandler()->getDtc()->adlerLoadTypeName(request.trajectory().loadTypeId());
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 ladung " << exFlugbahnberechnung.flugbahnberechnungDaten.geschoss.ladung;
|
|
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.sprenghoehe = static_cast<int>(request.explosionHeight());
|
|
exFlugbahnberechnung.flugbahnberechnungDaten.winkelgruppe = AdlerJson::Winkelgruppe(request.angleGroup().underlying());
|
|
|
|
//////////////////////////////////////////////////
|
|
/// Daten aus dem ESG-Simulator
|
|
|
|
if (request.properties().empty())
|
|
ERROR_LOG(m_logger) << "No properties available";
|
|
DEBUG_LOG(m_logger) << ", request.aesItemId() :" << request.aesItemId();
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
DEBUG_LOG(m_logger) << "UUID=" << exFlugbahnberechnung.uuid;
|
|
TrajectoryIdentifier trajectoryIdentifier;
|
|
|
|
trajectoryIdentifier.aesItemId = request.aesItemId();
|
|
trajectoryIdentifier.explosionId = request.explosionIndex();
|
|
QString uuidCleaned = exFlugbahnberechnung.uuid.remove(QStringLiteral("-"));
|
|
m_trajectoryIdentifier.insert(uuidCleaned, trajectoryIdentifier);
|
|
m_positionsLaunch.insert(uuidCleaned, request.positionLaunch());
|
|
|
|
QJsonObject telegram;
|
|
telegram = exFlugbahnberechnung.toJson();
|
|
DEBUG_LOG(m_logger) << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!77 " << QJsonDocument(telegram).toJson(QJsonDocument::JsonFormat::Compact);
|
|
m_sendToWebsocket->onGenericTelegram1(wsId, telegram);
|
|
}
|
|
|
|
void JsonDispatcher::cleanupSaaInterfaces(const QString &saaName, int wsId, int partyId)
|
|
{
|
|
// as the saaInterfaces are a vector, you can append multiple saa by the same name or ws id or party Id and it will always return the first one.
|
|
// so we add a cleanup function
|
|
DEBUG_LOG(m_logger) << "cleanup saa partyId: " << partyId << " name: " << saaName << " wsId " << wsId;
|
|
|
|
const auto copy = m_saaInterfaces;
|
|
for (const auto &saa : copy)
|
|
{
|
|
if ((partyId > 0 && saa.get()->getPartyId() == partyId) || (!saaName.isEmpty() && saa.get()->getSAAName() == saaName) // the name should be uniqe!
|
|
|| (wsId > 0 && saa.get()->getWsId() == wsId))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Cleanup SAA " << saa->getSAAName() << " for Party: " << saa->getPartyId();
|
|
m_saaInterfaces.removeOne(saa);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Notifications:
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void JsonDispatcher::getCreateNotificationRequestData(const int wsId,
|
|
const QString &title,
|
|
NotificationManagement::CreateNotification &data,
|
|
const QString &content,
|
|
const QStringList &contentArgs)
|
|
{
|
|
const qint64 currentTime = m_mainDispatcher->ddsHandler()->partitionTime();
|
|
|
|
// 100 seconds
|
|
const qint64 expiryTime = currentTime + 100 * 1000;
|
|
NotificationManagement::NomNotification notif;
|
|
|
|
notif.title(title.toStdString());
|
|
|
|
const auto saa = getSAAByWs(wsId);
|
|
if (!saa)
|
|
{
|
|
WARNING_LOG(m_logger) << "No valid SAA for wsId";
|
|
return;
|
|
}
|
|
//QString content = QStringLiteral("[Open Notification List ](//nomEditGuiPlugin/)") + QStringLiteral("<br />");
|
|
const int partyId = saa->getPartyId();
|
|
const ParticipantManagement::Party party = m_ppmHandler->getDtc()->party(partyId);
|
|
const QString partyStr = QString::fromStdString(party.name());
|
|
|
|
std::vector<std::string> args;
|
|
args.reserve(contentArgs.size());
|
|
for (const auto & str : qAsConst(contentArgs))
|
|
args.emplace_back(str.toStdString());
|
|
|
|
notif.content(content.toStdString());
|
|
notif.contentArgs(args);
|
|
notif.timeStamp(currentTime);
|
|
notif.expiryTime(expiryTime);
|
|
notif.priority(NotificationManagement::Priority_def::High);
|
|
notif.processedPriority(NotificationManagement::Priority_def::High);
|
|
notif.exerciseId(m_mainDispatcher->exerciseId());
|
|
|
|
const QVector<int> recipientIds = m_mainDispatcher->ddsHandler()->dtcOpm()->getNotificationRecipents(m_mainDispatcher->exerciseId(),
|
|
partyId,
|
|
OperatorRights::AdlerExplosionClusterEdit,
|
|
data.notification().notificationType().underlying());
|
|
DEBUG_LOG(m_logger) << "getCreateNotificationRequestData recipientIds.size=" << recipientIds.size()
|
|
<< ", exerciseId=" << m_mainDispatcher->exerciseId();
|
|
std::vector<NotificationManagement::Address> recipientIdsDds;
|
|
recipientIdsDds.reserve(recipientIds.size());
|
|
|
|
for (const auto &recipientId : qAsConst(recipientIds))
|
|
{
|
|
NotificationManagement::Address addr;
|
|
addr.addressId(recipientId);
|
|
addr.isRead(false);
|
|
const OperatorManagement::User user = m_mainDispatcher->ddsHandler()->dtcOpm()->user(recipientId);
|
|
addr.name(user.name());
|
|
addr.addressType(NotificationManagement::AddressType_def::Operator);
|
|
notif.recipientIds().push_back(addr);
|
|
DEBUG_LOG(m_logger) << "recipientId=" << addr.name()
|
|
<< ", addr.addressId=" << addr.addressId();
|
|
}
|
|
|
|
NotificationManagement::Address addrSender;
|
|
addrSender.name(saa->getSAAName().toStdString());
|
|
addrSender.addressType(NotificationManagement::AddressType_def::Service);
|
|
notif.sender(addrSender);
|
|
|
|
data.notification(notif);
|
|
} // end of getCreateNotificationRequestData()
|
|
|
|
void JsonDispatcher::createNotificationRequest(const int wsId,
|
|
const QString &title,
|
|
const NotificationManagement::MessageType messageType,
|
|
const NotificationManagement::NotificationType notificationType,
|
|
const QString &content,
|
|
const QStringList &args)
|
|
{
|
|
DEBUG_LOG(m_logger) << "createNotificationRequest"
|
|
<< ", content=" << content;
|
|
NotificationManagement::CreateNotification req;
|
|
getCreateNotificationRequestData(wsId, title, req, content, args);
|
|
if (req.notification().content().empty())
|
|
{
|
|
INFO_LOG(m_logger) << "req.notification().content().empty()";
|
|
return;
|
|
}
|
|
req.notification().messageType(messageType);
|
|
req.notification().notificationType(notificationType);
|
|
|
|
INFO_LOG(m_logger) << "trying to send CreateNotificationRequest";
|
|
if (req.notification().recipientIds().size() == 0)
|
|
{
|
|
INFO_LOG(m_logger) << "req.notification().recipientIds().size() == 0";
|
|
return;
|
|
}
|
|
INFO_LOG(m_logger) << "CreateNotificationRequest";
|
|
if (!m_ftcNom->createNotificationRequest(req, this))
|
|
{
|
|
ERROR_LOG(m_logger) << "Error requesting create data";
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void JsonDispatcher::onCreateNotificationReply(const Core::FunctionReplyObject &replyObject)
|
|
{
|
|
INFO_LOG(m_logger) << "Got createReply with id " << replyObject.id() << " and errorString " << replyObject.translated();
|
|
|
|
if (replyObject.error())
|
|
{
|
|
ERROR_LOG(m_logger) << "Error requesting CreateNotification";
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "Requesting create data ok. Got new id:" << replyObject.id() << " ... ok.";
|
|
}
|
|
|
|
} // end of onNotificationCreateReply()
|
|
|
|
} // namespace AdlerJson
|