Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Commmunication with WlsProxy
|
||||
# $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
|
||||
|
||||
tetra_dispatcher.cpp
|
||||
tetra_dispatcher.h
|
||||
tetra_handler_rx.cpp
|
||||
tetra_handler_rx.h
|
||||
tetra_handler_tx.cpp
|
||||
tetra_handler_tx.h
|
||||
tetra_prtcnv.cpp
|
||||
tetra_prtcnv.h
|
||||
|
||||
wls_dispatcher.cpp
|
||||
wls_dispatcher.h
|
||||
wls_handler_rx.cpp
|
||||
wls_handler_rx.h
|
||||
wls_handler_tx.cpp
|
||||
wls_handler_tx.h
|
||||
)
|
||||
QT5_ADD_RESOURCES(SRCS tetra.qrc)
|
||||
NGL_ADD_LIBRARY(AAR SV tabPluginWlsTetra MODULE ${SRCS})
|
||||
NGL_INSTALL_TARGET(tabPluginWlsTetra)
|
||||
NGL_TARGET_LINK_LIBRARIES(tabPluginWlsTetra
|
||||
CoPrtCnv
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PrtCnvLib
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
Qt5::Sql
|
||||
Qt5::WebSockets
|
||||
tabPluginInterface
|
||||
tabTelegrams
|
||||
)
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
[Common]
|
||||
LogCentralTelegrams=1
|
||||
LogRadioTelegrams=1
|
||||
LogTelegramPath=logdata
|
||||
LogTelegramPrefix=PrtCnv_
|
||||
; virtual TeilnehmerId of protocol-converter
|
||||
VirtualIdPrtCnv=90
|
||||
MaxEqID=50000
|
||||
;or max unsigned short: 65535
|
||||
|
||||
[Db]
|
||||
DatabaseFileName=db/telegrams.db
|
||||
|
||||
[Central]
|
||||
UseSocketsInsteadFiles=1
|
||||
HostName=EXCTDS01
|
||||
Port=9600
|
||||
; Milliseconds
|
||||
AckTimeout=900
|
||||
ConnectTimeout=2000
|
||||
DisconnectTimeout=10000
|
||||
AliveTimeout=3000
|
||||
; nbr of unsuccessful send-attempts, before telegram will be deleted without sending it
|
||||
NbrOfAttempts=5
|
||||
|
||||
[Radio]
|
||||
UseScrambling=1
|
||||
EmergencyCallISSI=9000
|
||||
BroadcastISSI=5000
|
||||
ConnectTimeout=2000
|
||||
HostName=CCSTSW01
|
||||
Port=52010
|
||||
HostName1=CCSTSW02
|
||||
Port1=52010
|
||||
HostISSI=9998
|
||||
; Seconds
|
||||
CyclicEnvironmentTime=30
|
||||
HostISSI=9999
|
||||
; Milliseconds
|
||||
DisconnectTimeout=10000
|
||||
AliveTimeout=3000
|
||||
; 1 - UseSDS_TL
|
||||
UseSDS_TL=0
|
||||
DumpReceivedTelegrams=1
|
||||
DumpSentTelegrams=1
|
||||
; GSSIs which we would like to subscribe to - make sure to not subscribe to our own BroadcastISSI !
|
||||
ListenGroups=5001
|
||||
|
||||
[Login]
|
||||
LoginFilePathWithPrefix=login/pk_
|
||||
DoLicenseDespiteSelftestOrConfigFailure=0
|
||||
DoCheckPlayerId=1
|
||||
LowestPlayerId=500
|
||||
HighestPlayerId=65535
|
||||
PlayerIdFilePath=playerIds.dat
|
||||
|
||||
[Broadcast]
|
||||
; Count, how often a Broadcast telegram will be send (minimum 1, 0 will be ignored and the telegram is sent anyway)
|
||||
MaxBroadcastSendCount=1
|
||||
; In seconds, delay between sending 1st and 2nd broadcast (< 0 -> disable)
|
||||
BroadcastDelay2=10
|
||||
; In seconds, delay between sending 2nd and 3rd broadcast (< 0 -> disable)
|
||||
BroadcastDelay3=20
|
||||
; the time to wait for NachforderungBroadcast from TNEs, before begin sending the broadcasts
|
||||
ClaimWindow=30
|
||||
; factor for extend the claimwindow when we have full load in downlink
|
||||
FullLoadFactor=3
|
||||
; if less TNEs ask for broadcasts, they will be send directed
|
||||
BroadcastLimit=10
|
||||
; the time to wait before sending next broadcast in milliseconds
|
||||
SendGap=500
|
||||
; minimum id of DUS-Mines to be able to get reactivated
|
||||
MinimumDusMineId=2048
|
||||
|
||||
[TrafficControl]
|
||||
; from PrtCnv to Tetra (Telegram-Counting)
|
||||
; Number of telegrams (0..255) reported by air-interface-report telegram when we have high load
|
||||
SendQueueHighLoad=150
|
||||
; Number of telegrams that will be sent per second, when we have high-load
|
||||
SendTelegramsHighLoad=50
|
||||
; Number of telegrams (0..255) reported by air-interface-report telegram when we have full load
|
||||
SendQueueFullLoad=200
|
||||
; Number of telegrams that will be sent per second, when we have full-load
|
||||
SendTelegramsFullLoad=10
|
||||
; from Tetra to PrtCnv (Byte-Counting)
|
||||
; high load in percent (0 .. 100)
|
||||
ReceiveQueueHighLoad=50
|
||||
; full load in percent (ReceiveQueueHighLoad .. 100)
|
||||
ReceiveQueueFullLoad=75
|
||||
; hysteresis in percent (0 .. 10)
|
||||
ReceiveQueueHysteresis=5
|
||||
; Averaging time in seconds
|
||||
ReceiveAveragingTime=5
|
||||
; Throughput in KB/s per Transceiver
|
||||
ReceiveThroughput=3.6
|
||||
; Transceiver count
|
||||
TransceiverCount=6
|
||||
|
||||
[Injection]
|
||||
Enable=true
|
||||
Port=46666
|
||||
@@ -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 WlsTetra
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "TAB.WLS.";
|
||||
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 WlsTetra
|
||||
+23
@@ -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 WlsTetra
|
||||
{
|
||||
using LOGGER_T = NGL::INGLLogger&;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from Wls
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "main_dispatcher.h"
|
||||
#include "main_handler_tx.h"
|
||||
#include "wls_dispatcher.h"
|
||||
#include "wls_handler_tx.h"
|
||||
#include "tetra_dispatcher.h"
|
||||
#include "tetra_handler_tx.h"
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
#include <QSettings>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
MainDispatcher::MainDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
NGL::Settings *settings)
|
||||
: m_wlsDispatcher(new WlsDispatcher(pdp, recvFromTabCb, settings))
|
||||
, m_tetraDispatcher(new TetraDispatcher(pdp, recvFromTabCb))
|
||||
, m_recvFromTabCb(recvFromTabCb)
|
||||
, m_mainHandlerTx(std::make_shared<MainHandlerTx>(std::dynamic_pointer_cast<WlsHandlerTx>(m_wlsDispatcher->sendToTab()),
|
||||
std::dynamic_pointer_cast<TetraHandlerTx>(m_tetraDispatcher->sendToTab())))
|
||||
, m_logger(getLogger("MainDispatcher"))
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvTelegramConverter::setUse2BytesForSingleFireDiameter(
|
||||
settings->settings()->value(QLatin1String("AES/use2BytesForSingleFireDiameter"), true).toBool());
|
||||
connect(m_wlsDispatcher, &WlsDispatcher::broadcastTelegramsRequest,
|
||||
m_tetraDispatcher, &TetraDispatcher::onBroadcastTelegramsRequest);
|
||||
connect(m_wlsDispatcher, &WlsDispatcher::wlsTelegramReceived,
|
||||
m_tetraDispatcher, &TetraDispatcher::onWlsTelegramReceived);
|
||||
connect(m_wlsDispatcher, &WlsDispatcher::wlsTelegramSent,
|
||||
m_tetraDispatcher, &TetraDispatcher::onWlsTelegramSent);
|
||||
connect(m_wlsDispatcher, &WlsDispatcher::connectionState,
|
||||
this, &MainDispatcher::connectionState);
|
||||
connect(m_tetraDispatcher, &TetraDispatcher::connectionState,
|
||||
this, &MainDispatcher::connectionState);
|
||||
connect(m_tetraDispatcher, &TetraDispatcher::participantLicenseChange,
|
||||
m_wlsDispatcher, &WlsDispatcher::onParticipantLicenseChange);
|
||||
}
|
||||
|
||||
MainDispatcher::~MainDispatcher()
|
||||
{
|
||||
m_mainHandlerTx = nullptr;
|
||||
m_recvFromTabCb = nullptr;
|
||||
delete m_wlsDispatcher;
|
||||
delete m_tetraDispatcher;
|
||||
}
|
||||
|
||||
bool MainDispatcher::init()
|
||||
{
|
||||
return m_wlsDispatcher->init() && m_tetraDispatcher->init();
|
||||
}
|
||||
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> MainDispatcher::sendToTab()
|
||||
{
|
||||
return m_mainHandlerTx;
|
||||
}
|
||||
|
||||
bool MainDispatcher::canSendData() const
|
||||
{
|
||||
return m_wlsDispatcher->canSendData() || m_tetraDispatcher->canSendData();
|
||||
}
|
||||
|
||||
void MainDispatcher::exerciseChanged()
|
||||
{
|
||||
m_wlsDispatcher->exerciseChanged();
|
||||
m_tetraDispatcher->exerciseChanged();
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from Wls
|
||||
* $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 "logger.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
class WlsDispatcher;
|
||||
class TetraDispatcher;
|
||||
class MainDispatcher final : public TrainingAreaBase::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
NGL::Settings *settings);
|
||||
~MainDispatcher();
|
||||
|
||||
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;
|
||||
const char *name() const override { return tr_lts("dds", "WlsTetra"); }
|
||||
|
||||
private:
|
||||
WlsDispatcher *m_wlsDispatcher;
|
||||
TetraDispatcher *m_tetraDispatcher;
|
||||
|
||||
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_recvFromTabCb;
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> m_mainHandlerTx;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* 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 "tetra_handler_tx.h"
|
||||
#include "wls_handler_tx.h"
|
||||
|
||||
using namespace TrainingAreaBase;
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
template<typename T>
|
||||
struct HasHeaderStruct
|
||||
{
|
||||
struct Fallback { TetraIcd::Header header; };
|
||||
struct Derived : T, Fallback { };
|
||||
|
||||
template<typename C, C> struct ChT;
|
||||
|
||||
template<typename C> static char (&f(ChT<TetraIcd::Header Fallback::*, &C::header> *))[1];
|
||||
template<typename C> static char (&f(...))[2];
|
||||
|
||||
public:
|
||||
static bool const value = sizeof(f<Derived>(nullptr)) == 2;
|
||||
};
|
||||
|
||||
template <typename T, typename std::enable_if<HasHeaderStruct<T>::value, int>::type = 0>
|
||||
static inline int getEquipNo(const T *data)
|
||||
{
|
||||
return data->header.equipmentNumber;
|
||||
}
|
||||
|
||||
template < typename T, typename std::enable_if < !HasHeaderStruct<T>::value, int >::type = 0 >
|
||||
static inline int getEquipNo(const T *)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
MainHandlerTx::MainHandlerTx(const std::shared_ptr<WlsHandlerTx> &wlsTx,
|
||||
const std::shared_ptr<TetraHandlerTx> &tetraTx)
|
||||
: m_wlsHandlerTx(wlsTx)
|
||||
, m_tetraHandlerTx(tetraTx)
|
||||
, m_logger(getLogger("MainHandlerTx"))
|
||||
{}
|
||||
|
||||
SendToTab::HandleState MainHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
|
||||
{
|
||||
SendToTab::HandleState hsWls = m_wlsHandlerTx->canHandleTelegram(equipmentNumber, telegramId);
|
||||
if (hsWls == SendToTab::HandleState::YesConsume ||
|
||||
hsWls == SendToTab::HandleState::YesShare)
|
||||
return hsWls;
|
||||
SendToTab::HandleState hsTetra = m_tetraHandlerTx->canHandleTelegram(equipmentNumber, telegramId);
|
||||
if (hsTetra == SendToTab::HandleState::YesConsume ||
|
||||
hsTetra == SendToTab::HandleState::YesShare)
|
||||
return hsTetra;
|
||||
if (hsWls == SendToTab::HandleState::YesFallback)
|
||||
return hsWls;
|
||||
if (hsTetra == SendToTab::HandleState::YesFallback)
|
||||
return hsTetra;
|
||||
if (hsWls == SendToTab::HandleState::Debug)
|
||||
return hsWls;
|
||||
if (hsTetra == SendToTab::HandleState::Debug)
|
||||
return hsTetra;
|
||||
return SendToTab::HandleState::No;
|
||||
}
|
||||
|
||||
void MainHandlerTx::resetSendCounter()
|
||||
{
|
||||
m_wlsHandlerTx->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)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "MainHandlerTx::txData SelectiveReammunition";
|
||||
return sendToTxMixin(&data);
|
||||
}
|
||||
bool MainHandlerTx::txData(const TetraIcd::SetDevicePowerRequest &data)
|
||||
{
|
||||
return sendToTxMixin(&data);
|
||||
}
|
||||
template <typename T>
|
||||
bool MainHandlerTx::sendToTxMixin(const T *data)
|
||||
{
|
||||
const int equipmentNumber = getEquipNo(data);
|
||||
SendToTab::HandleState hsWls = m_wlsHandlerTx->canHandleTelegram(equipmentNumber, data->id());
|
||||
SendToTab::HandleState hsTetra = m_tetraHandlerTx->canHandleTelegram(equipmentNumber, data->id());
|
||||
if (hsWls == SendToTab::HandleState::Debug)
|
||||
m_wlsHandlerTx->txData(*data);
|
||||
if (hsTetra == SendToTab::HandleState::Debug)
|
||||
m_tetraHandlerTx->txData(*data);
|
||||
|
||||
if (hsWls == SendToTab::HandleState::YesConsume)
|
||||
return m_wlsHandlerTx->txData(*data);
|
||||
if (hsTetra == SendToTab::HandleState::YesConsume)
|
||||
return m_tetraHandlerTx->txData(*data);
|
||||
|
||||
bool bRet = false;
|
||||
if (hsWls == SendToTab::HandleState::YesShare)
|
||||
bRet |= m_wlsHandlerTx->txData(*data);
|
||||
if (hsTetra == SendToTab::HandleState::YesShare)
|
||||
bRet |= m_tetraHandlerTx->txData(*data);
|
||||
|
||||
if (bRet)
|
||||
return bRet;
|
||||
|
||||
if (hsWls == SendToTab::HandleState::YesFallback)
|
||||
return m_wlsHandlerTx->txData(*data);
|
||||
if (hsTetra == SendToTab::HandleState::YesFallback)
|
||||
return m_tetraHandlerTx->txData(*data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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 WlsTetra
|
||||
{
|
||||
class WlsHandlerTx;
|
||||
class TetraHandlerTx;
|
||||
|
||||
class MainHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainHandlerTx(const std::shared_ptr<WlsHandlerTx> &wlsTx,
|
||||
const std::shared_ptr<TetraHandlerTx> &tetraTx);
|
||||
|
||||
const char *name() const override { return "WlsTetra"; }
|
||||
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;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data) override;
|
||||
private:
|
||||
template <typename T>
|
||||
bool sendToTxMixin(const T *data);
|
||||
private:
|
||||
std::shared_ptr<WlsHandlerTx> m_wlsHandlerTx;
|
||||
std::shared_ptr<TetraHandlerTx> m_tetraHandlerTx;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1-65535
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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 WlsTetra
|
||||
{
|
||||
|
||||
//
|
||||
// TetraXdrPlugin
|
||||
//
|
||||
std::shared_ptr<TrainingAreaBase::Plugin::Interface> TabWlsPlugin::createInterface(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
const std::shared_ptr<TrainingAreaBase::TxMixin> &sendToTabCb,
|
||||
NGL::Settings *settings)
|
||||
{
|
||||
Q_UNUSED(sendToTabCb);
|
||||
return std::make_shared<MainDispatcher>(pdp, recvFromTabCb, settings);
|
||||
}
|
||||
} // namespace WlsTetra
|
||||
+30
@@ -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 WlsTetra
|
||||
{
|
||||
class TabWlsPlugin : public QObject, public TrainingAreaBase::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:tab.wls")
|
||||
Q_INTERFACES(TrainingAreaBase::Plugin::Plugin)
|
||||
public:
|
||||
TabWlsPlugin() = default;
|
||||
~TabWlsPlugin() = 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> &sendToTabCb,
|
||||
NGL::Settings *settings) override;
|
||||
};
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>playerIds.dat</file>
|
||||
<file>PrtCnv.dat</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from PrtCnv
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "tetra_dispatcher.h"
|
||||
#include "tetra_handler_rx.h"
|
||||
#include "tetra_handler_tx.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
|
||||
//
|
||||
// TetraDispatcher
|
||||
//
|
||||
TetraDispatcher::TetraDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb)
|
||||
: TrainingAreaBase::Plugin::Interface()
|
||||
, m_rxHandler(std::make_shared<TetraHandlerRx>(recvFromTabCb))
|
||||
, m_txHandler(std::make_shared<TetraHandlerTx>())
|
||||
, m_tetraPrtCnv(new TetraPrtCnv(pdp, this))
|
||||
, m_dataProvider(pdp)
|
||||
, m_logger(getLogger("TetraDispatcher"))
|
||||
{
|
||||
connect(m_tetraPrtCnv, &TetraPrtCnv::tetraConnectionChanged,
|
||||
this, &TetraDispatcher::onTetraConnectionChanged);
|
||||
connect(m_rxHandler.get(), &TetraHandlerRx::tetraConnectionChanged,
|
||||
this, &TetraDispatcher::onTetraConnectionChanged);
|
||||
connect(m_rxHandler.get(), &TetraHandlerRx::participantLicenseChange,
|
||||
this, &TetraDispatcher::participantLicenseChange);
|
||||
connect(m_tetraPrtCnv, &TetraPrtCnv::textMessageFromPrtCnv,
|
||||
m_rxHandler.get(), &TetraHandlerRx::handleTelegram);
|
||||
connect(m_rxHandler.get(), &TetraHandlerRx::initialAckReceived,
|
||||
this, &TetraDispatcher::onSendInitialData);
|
||||
connect(m_rxHandler.get(), &TetraHandlerRx::txData,
|
||||
m_txHandler.get(), QOverload<const TrainingAreaBase::TetraIcd::Acknowledge &>::of(&TetraHandlerTx::txData));
|
||||
connect(m_txHandler.get(), &TetraHandlerTx::outgoingMessage,
|
||||
m_tetraPrtCnv, &TetraPrtCnv::textMessageToPrtCnv);
|
||||
}
|
||||
|
||||
bool TetraDispatcher::init()
|
||||
{
|
||||
onTetraConnectionChanged(false);
|
||||
if (!m_tetraPrtCnv->init())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TetraDispatcher::onBroadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter)
|
||||
{
|
||||
emit m_tetraPrtCnv->broadcastTelegramsRequest(equipmentNumber, broadcastIndex, resetCounter);
|
||||
}
|
||||
|
||||
void TetraDispatcher::onWlsTelegramReceived(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele)
|
||||
{
|
||||
m_tetraPrtCnv->logWlsTelegram(tele, false);
|
||||
}
|
||||
|
||||
void TetraDispatcher::onWlsTelegramSent(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele)
|
||||
{
|
||||
m_tetraPrtCnv->logWlsTelegram(tele, true);
|
||||
}
|
||||
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> TetraDispatcher::sendToTab()
|
||||
{
|
||||
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_txHandler);
|
||||
}
|
||||
|
||||
bool TetraDispatcher::canSendData() const
|
||||
{
|
||||
return m_txHandler->isConnected();
|
||||
}
|
||||
|
||||
void TetraDispatcher::exerciseChanged()
|
||||
{
|
||||
m_tetraPrtCnv->onExerciseChanged();
|
||||
}
|
||||
|
||||
void TetraDispatcher::onTetraConnectionChanged(bool bConnected)
|
||||
{
|
||||
NOTICE_LOG(m_logger) << "onTetraConnectionChanged: " << bConnected;
|
||||
m_txHandler->setConnected(false);
|
||||
if (!bConnected)
|
||||
{
|
||||
m_txHandler->resetSendCounter();
|
||||
m_rxHandler->resetConnection();
|
||||
}
|
||||
emit connectionState(QString::fromUtf8(name()), bConnected);
|
||||
}
|
||||
|
||||
void TetraDispatcher::onSendInitialData()
|
||||
{
|
||||
m_txHandler->setConnected(true);
|
||||
if (m_dataProvider)
|
||||
{
|
||||
INFO_LOG(m_logger) << "sending initial data";
|
||||
// on connect we must send:
|
||||
if (m_dataProvider->exerciseId() > 0)
|
||||
{
|
||||
// - Umgebungsmeldung
|
||||
m_txHandler->txData(m_dataProvider->exerciseEnvironmentData());
|
||||
}
|
||||
// - Betriebszustandsmeldung
|
||||
m_txHandler->txData(m_dataProvider->exerciseStateData());
|
||||
m_txHandler->txData(m_dataProvider->exerciseEquipmentAssignment());
|
||||
const auto &aesTeles = m_dataProvider->aesTelegrams();
|
||||
for (TrainingAreaBase::TetraIcd::TrainingAreaTelegram *aesTele : aesTeles)
|
||||
m_txHandler->sendToTx(aesTele);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from PrtCnv
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QWebSocketServer>
|
||||
#include <QWebSocket>
|
||||
#include <QTimer>
|
||||
#include <TrainingAreaBase/tab_plugin_interface.h>
|
||||
#include <PrtCnv/PrtCnvApplication.hpp>
|
||||
#include <DDS/Core/function_reply_object.h> // tr_lts
|
||||
#include "tetra_prtcnv.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
class TetraHandlerRx;
|
||||
class TetraHandlerTx;
|
||||
class TetraDispatcher final : public TrainingAreaBase::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TetraDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb);
|
||||
|
||||
public Q_SLOTS:
|
||||
bool init() override;
|
||||
void onBroadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter);
|
||||
void onWlsTelegramReceived(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele);
|
||||
void onWlsTelegramSent(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele);
|
||||
Q_SIGNALS:
|
||||
void participantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc);
|
||||
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", "TETRA"); }
|
||||
|
||||
private:
|
||||
bool init(PrtCnv::PrtCnvApplication *prtCnvApp);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onTetraConnectionChanged(bool bConnected);
|
||||
void onSendInitialData();
|
||||
|
||||
private:
|
||||
void disconnectSocket(QWebSocket *s);
|
||||
|
||||
private:
|
||||
std::shared_ptr<TetraHandlerRx> m_rxHandler;
|
||||
std::shared_ptr<TetraHandlerTx> m_txHandler;
|
||||
TetraPrtCnv *m_tetraPrtCnv;
|
||||
TrainingAreaBase::Plugin::DataProvider *m_dataProvider;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* Read XDR telegrams from a directory and convert it to EtsTetraIcd structures
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "tetra_handler_rx.h"
|
||||
#include <TrainingAreaBase/training_area_telegrams.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QTimer>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
|
||||
TetraHandlerRx::TetraHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &rxHandler)
|
||||
: m_rxHandler(rxHandler)
|
||||
, m_ackTimer(new QTimer(this))
|
||||
, m_receiveCounter(0)
|
||||
, m_bWarnedOnce(false)
|
||||
, m_bWaitForInitialAck(true)
|
||||
, m_logger(getLogger("TetraHandlerRx"))
|
||||
{
|
||||
m_ackTimer->setInterval(1000);
|
||||
m_ackTimer->setSingleShot(false);
|
||||
connect(m_ackTimer, &QTimer::timeout,
|
||||
this, &TetraHandlerRx::onAckTimeout);
|
||||
|
||||
}
|
||||
|
||||
bool TetraHandlerRx::handleTelegram(const QByteArray &baJson)
|
||||
{
|
||||
using namespace TrainingAreaBase::TetraIcd;
|
||||
|
||||
if (baJson.isEmpty())
|
||||
return false;
|
||||
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
|
||||
const QJsonValue sendCounter = obj.value(QStringLiteral("counter"));
|
||||
if (!sendCounter.isUndefined())
|
||||
{
|
||||
if (!sendCounter.isDouble())
|
||||
return false;
|
||||
m_receiveCounter = sendCounter.toInt(-1);
|
||||
DEBUG_LOG(m_logger) << "Incoming telegram with Id " << obj.value(QStringLiteral("type")).toString();
|
||||
if (m_receiveCounter < 0)
|
||||
return false;
|
||||
}
|
||||
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();
|
||||
try
|
||||
{
|
||||
switch (typeId.toInt())
|
||||
{
|
||||
case Constraints<Acknowledge>::id(): // 0
|
||||
{
|
||||
auto ack = TrainingAreaBase::TetraIcd::Acknowledge::fromJson(data);
|
||||
handleAcknowledge(ack.timeStamp, ack.ackCounter);
|
||||
break;
|
||||
}
|
||||
case Constraints<ManipulationReport>::id(): // 2
|
||||
rxData(ManipulationReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentOperationalState>::id(): // 7
|
||||
rxData(EquipmentOperationalState::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentConfigurationReport>::id(): // 11
|
||||
rxData(EquipmentConfigurationReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<CtaDataError>::id(): // 12
|
||||
rxData(CtaDataError::fromJson(data));
|
||||
break;
|
||||
case Constraints<PositionReport>::id(): // 21
|
||||
rxData(PositionReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<PositionReportWithMountedEquipments>::id(): // 22
|
||||
rxData(PositionReportWithMountedEquipments::fromJson(data));
|
||||
break;
|
||||
case Constraints<MineTriggered>::id(): // 40
|
||||
rxData(MineTriggered::fromJson(data));
|
||||
break;
|
||||
case Constraints<DefinitionIed>::id(): // 43
|
||||
rxData(DefinitionIed::fromJson(data));
|
||||
break;
|
||||
case Constraints<StateIed>::id(): // 44
|
||||
rxData(StateIed::fromJson(data));
|
||||
break;
|
||||
case Constraints<DusSingleMineState>::id(): // 45
|
||||
rxData(DusSingleMineState::fromJson(data));
|
||||
break;
|
||||
case Constraints<StateChangeDirect>::id(): // 52
|
||||
rxData(StateChangeDirect::fromJson(data));
|
||||
break;
|
||||
case Constraints<StateChangeIndirect>::id(): // 53
|
||||
rxData(StateChangeIndirect::fromJson(data));
|
||||
break;
|
||||
case Constraints<OperatorAction>::id(): // 55
|
||||
rxData(OperatorAction::fromJson(data));
|
||||
break;
|
||||
case Constraints<SelectiveReammunition>::id(): // 56
|
||||
rxData(SelectiveReammunition::fromJson(data));
|
||||
break;
|
||||
case Constraints<StateChange>::id(): // 61
|
||||
rxData(StateChange::fromJson(data));
|
||||
break;
|
||||
case Constraints<FunctionalAreaEntry>::id(): // 63
|
||||
rxData(FunctionalAreaEntry::fromJson(data));
|
||||
break;
|
||||
case Constraints<OpaquePayloadDataIn>::id(): // 71
|
||||
rxData(OpaquePayloadDataIn::fromJson(data));
|
||||
break;
|
||||
case Constraints<SpecialSensorData>::id(): // 92
|
||||
rxData(SpecialSensorData::fromJson(data));
|
||||
break;
|
||||
case Constraints<MinelayerTrailerData>::id(): // 95
|
||||
rxData(MinelayerTrailerData::fromJson(data));
|
||||
break;
|
||||
case Constraints<MinelayerThrowerData>::id(): // 96
|
||||
rxData(MinelayerThrowerData::fromJson(data));
|
||||
break;
|
||||
case Constraints<MinelayerTrailerPosition>::id(): // 97
|
||||
rxData(MinelayerTrailerPosition::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentEvent>::id(): // 185
|
||||
rxData(EquipmentEvent::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentGearAssignment>::id(): // 200
|
||||
rxData(EquipmentGearAssignment::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentGearChargeState>::id(): // 202
|
||||
rxData(EquipmentGearChargeState::fromJson(data));
|
||||
break;
|
||||
case Constraints<BiteReport>::id(): // 205
|
||||
rxData(BiteReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<EquipmentGearEvent>::id(): // 210
|
||||
rxData(EquipmentGearEvent::fromJson(data));
|
||||
break;
|
||||
case Constraints<ParticipantSwVersions>::id(): // 213
|
||||
rxData(ParticipantSwVersions::fromJson(data));
|
||||
break;
|
||||
case Constraints<ParticipantModeReport>::id(): // 231
|
||||
rxData(ParticipantModeReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<ParticipantConfigurationReport>::id(): // 233
|
||||
rxData(ParticipantConfigurationReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<EmergencyCall>::id(): // 1120
|
||||
rxData(EmergencyCall::fromJson(data));
|
||||
break;
|
||||
case Constraints<SanitationRepair>::id(): // 240
|
||||
rxData(SanitationRepair::fromJson(data));
|
||||
break;
|
||||
case Constraints<SanitaryMaterialStockReport>::id(): // 241
|
||||
rxData(SanitaryMaterialStockReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<Sanitation>::id(): // 242
|
||||
rxData(Sanitation::fromJson(data));
|
||||
break;
|
||||
case Constraints<ApacheLaserDesignation>::id():
|
||||
rxData(ApacheLaserDesignation::fromJson(data));
|
||||
break;
|
||||
case Constraints<ProxyConnectionState>::id(): // 2013
|
||||
emit tetraConnectionChanged(ProxyConnectionState::fromJson(data).connectedToSystem);
|
||||
break;
|
||||
case Constraints<ParticipantLicenseChange>::id(): // 2014
|
||||
emit participantLicenseChange(ParticipantLicenseChange::fromJson(data));
|
||||
break;
|
||||
default:
|
||||
WARNING_LOG(m_logger) << "Handler for telegram Id " << typeId.toInt()
|
||||
<< " not yet implemented (" << baJson << ")";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << baJson << ")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TetraHandlerRx::handleAcknowledge(qint64 timeStamp, int counter)
|
||||
{
|
||||
TRACE_LOG(m_logger) << "Ack from Socket for time " << timeStamp
|
||||
<< " with counter " << counter
|
||||
<< ", initial: " << m_bWaitForInitialAck;
|
||||
if (m_bWaitForInitialAck)
|
||||
{
|
||||
m_bWaitForInitialAck = false;
|
||||
emit initialAckReceived();
|
||||
m_ackTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void TetraHandlerRx::onAckTimeout()
|
||||
{
|
||||
TrainingAreaBase::TetraIcd::Acknowledge ack;
|
||||
ack.timeStamp = time(nullptr) * 1000;
|
||||
ack.ackCounter = m_receiveCounter;
|
||||
|
||||
emit txData(ack);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TetraHandlerRx::rxData(const T &data)
|
||||
{
|
||||
if (!m_rxHandler)
|
||||
{
|
||||
if (!m_bWarnedOnce)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "No RecvFromTab available";
|
||||
m_bWarnedOnce = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return m_rxHandler->rxData(data);
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Read XDR telegrams from a directory and convert it to EtsTetraIcd structures
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <TrainingAreaBase/recv_from_tab.h>
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
#include "logger.h"
|
||||
|
||||
class QTimer;
|
||||
namespace WlsTetra
|
||||
{
|
||||
class TetraHandlerRx : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TetraHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &rxHandler);
|
||||
|
||||
bool handleTelegram(const QByteArray &baJson);
|
||||
void resetConnection() { m_bWaitForInitialAck = true; }
|
||||
Q_SIGNALS:
|
||||
void tetraConnectionChanged(bool bConnected);
|
||||
void participantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc);
|
||||
void initialAckReceived();
|
||||
void txData(const TrainingAreaBase::TetraIcd::Acknowledge &ack);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onAckTimeout();
|
||||
|
||||
private:
|
||||
void handleAcknowledge(qint64 timeStamp, int counter);
|
||||
template<typename T>
|
||||
void rxData(const T &data);
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> m_rxHandler;
|
||||
QTimer *m_ackTimer;
|
||||
int m_receiveCounter;
|
||||
bool m_bWarnedOnce;
|
||||
bool m_bWaitForInitialAck;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* Write XDR telegrams to a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "tetra_handler_tx.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
TetraHandlerTx::TetraHandlerTx()
|
||||
: QObject()
|
||||
, SendToTab()
|
||||
, m_logger(getLogger("TetraHandlerTx"))
|
||||
{
|
||||
resetSendCounter();
|
||||
}
|
||||
|
||||
TrainingAreaBase::SendToTab::HandleState TetraHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
|
||||
{
|
||||
if (!m_bConnected)
|
||||
return HandleState::No;
|
||||
|
||||
using namespace TrainingAreaBase::TetraIcd;
|
||||
if (telegramId == Constraints<ExerciseEquipmentAssignmentComplete>::id() ||
|
||||
telegramId == Constraints<ExerciseStateData>::id())
|
||||
return HandleState::YesShare;
|
||||
|
||||
Q_UNUSED(equipmentNumber)
|
||||
return HandleState::YesFallback;
|
||||
}
|
||||
|
||||
void TetraHandlerTx::resetSendCounter()
|
||||
{
|
||||
m_sendCounter = 1; // start at 1
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::sendTele(const QByteArray &ba)
|
||||
{
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(ba));
|
||||
QJsonObject obj = doc.object();
|
||||
const QJsonValue typeId = obj[QStringLiteral("typeId")];
|
||||
if (typeId.toInt() == TrainingAreaBase::TetraIcd::TelegramId::BESTAETIGUNG)
|
||||
{
|
||||
TRACE_LOG(m_logger) << "Outgoing ack";
|
||||
emit outgoingMessage(ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
obj[QStringLiteral("counter")] = m_sendCounter++;
|
||||
const QByteArray baToSend = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
DEBUG_LOG(m_logger) << "Outgoing message: " << typeId.toInt();
|
||||
emit outgoingMessage(baToSend);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::Acknowledge &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandBite &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::Init &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineTriggered &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::Sanitation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " TetraHandlerTx::txData: SelectiveReammunition";
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TetraHandlerTx::sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data)
|
||||
{
|
||||
if (!m_bConnected)
|
||||
return false;
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("data")] = data->toJson();
|
||||
obj[QStringLiteral("type")] = data->type();
|
||||
obj[QStringLiteral("typeId")] = data->id();
|
||||
if (data->id() != TrainingAreaBase::TetraIcd::TelegramId::BESTAETIGUNG)
|
||||
obj[QStringLiteral("counter")] = m_sendCounter++;
|
||||
const QByteArray ba = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
if (data->id() != TrainingAreaBase::TetraIcd::TelegramId::BESTAETIGUNG)
|
||||
DEBUG_LOG(m_logger) << "Sending tele: " << ba;
|
||||
emit outgoingMessage(ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Write XDR telegrams to a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QWebSocket>
|
||||
#include <TrainingAreaBase/send_to_tab.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
class TetraHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TetraHandlerTx();
|
||||
|
||||
const char *name() const override { return "Tetra"; }
|
||||
HandleState canHandleTelegram(int equipmentNumber, int telegramId) const override;
|
||||
void resetSendCounter() override;
|
||||
bool sendTele(const QByteArray &ba);
|
||||
|
||||
void setConnected(bool bConnected) { m_bConnected = bConnected; }
|
||||
bool isConnected() const { return m_bConnected; }
|
||||
public:
|
||||
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::ParticipantSwVersionsRequest &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &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;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data) override;
|
||||
|
||||
bool sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data);
|
||||
Q_SIGNALS:
|
||||
void outgoingMessage(const QByteArray &msg);
|
||||
protected:
|
||||
protected:
|
||||
int m_sendCounter = 1;
|
||||
bool m_bConnected = false;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from PrtCnv
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "tetra_prtcnv.h"
|
||||
#include <nglsettings/nglsettings_connections.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSettings>
|
||||
#include <QTcpServer>
|
||||
#include <ngldb/dbcommon.h>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
TetraPrtCnv::TetraPrtCnv(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_pdp(pdp)
|
||||
, m_prtCnvApp(nullptr)
|
||||
, m_exerciseId(0)
|
||||
, m_radioGrpId(0)
|
||||
, m_logger(getLogger("TetraPrtCnv"))
|
||||
{}
|
||||
|
||||
TetraPrtCnv::~TetraPrtCnv()
|
||||
{
|
||||
cleanupProcess();
|
||||
}
|
||||
|
||||
bool TetraPrtCnv::init()
|
||||
{
|
||||
m_exerciseId = m_pdp->exerciseId();
|
||||
NOTICE_LOG(m_logger) << "Our exercise id is " << m_exerciseId;
|
||||
|
||||
if (m_exerciseId == 0) // its sufficient to check only in exercise 0
|
||||
if (!checkConfigTemplates())
|
||||
return false;
|
||||
|
||||
return updatePrtCnv();
|
||||
}
|
||||
|
||||
void TetraPrtCnv::onExerciseChanged()
|
||||
{
|
||||
if (m_pdp->exerciseRadioGroup().id() != m_radioGrpId) // radio grp changed
|
||||
if (!updatePrtCnv())
|
||||
ERROR_LOG(m_logger) << "Error changing PrtCnv state from radio grp id: "
|
||||
<< m_radioGrpId
|
||||
<< " to " << m_pdp->exerciseRadioGroup().id();
|
||||
}
|
||||
|
||||
void TetraPrtCnv::logWlsTelegram(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele, bool bIsSend)
|
||||
{
|
||||
if (m_prtCnvApp)
|
||||
m_prtCnvApp->logWlsTelegram(tele, bIsSend);
|
||||
}
|
||||
|
||||
bool TetraPrtCnv::updatePrtCnv()
|
||||
{
|
||||
int newRadioGrpId = m_pdp->exerciseRadioGroup().id();
|
||||
|
||||
if (newRadioGrpId == m_radioGrpId) //nothing changed for PrtCnv
|
||||
{
|
||||
NOTICE_LOG(m_logger) << "No need to update PrtCnv configuration - radio group did not change: " << m_radioGrpId;
|
||||
return true;
|
||||
}
|
||||
|
||||
NOTICE_LOG(m_logger) << "Our radio group id is " << newRadioGrpId;
|
||||
if (newRadioGrpId > 0)
|
||||
{
|
||||
// Create Prtcnv.dat with specific config
|
||||
QFile::remove(iniFileOut());
|
||||
if (!QFile::copy(QStringLiteral(":/PrtCnv.dat"), iniFileOut()) ||
|
||||
!QFile::setPermissions(iniFileOut(), QFile::ReadOwner | QFile::WriteOwner))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error creating ini file for PrtCnv: " << iniFileOut();
|
||||
return false;
|
||||
}
|
||||
|
||||
ProjectDataManagement::RadioGroup radioGrp = m_pdp->exerciseRadioGroup();
|
||||
|
||||
{
|
||||
QSettings s(iniFileOut(), QSettings::IniFormat);
|
||||
s.setValue(QStringLiteral("Common/LogTelegramPath"), QStringLiteral("logdata/ex_%1").arg(m_exerciseId));
|
||||
s.setValue(QStringLiteral("Common/LogTelegramPrefix"), QStringLiteral("PrtCnv_ex_%1").arg(m_exerciseId));
|
||||
s.setValue(QStringLiteral("Central/HostName"), QStringLiteral("directConnection")); // direct connection thorugh signals/slots
|
||||
s.setValue(QStringLiteral("Radio/HostName"), QString::fromStdString(radioGrp.radioHostname()));
|
||||
s.setValue(QStringLiteral("Radio/Port"), radioGrp.radioPort());
|
||||
s.setValue(QStringLiteral("Radio/HostName1"), QString::fromStdString(radioGrp.radioBackupHostname()));
|
||||
s.setValue(QStringLiteral("Radio/Port1"), radioGrp.radioBackupPort());
|
||||
s.setValue(QStringLiteral("Radio/HostISSI"), radioGrp.issi());
|
||||
s.setValue(QStringLiteral("Radio/BroadcastISSI"), radioGrp.group_issi1());
|
||||
s.setValue(QStringLiteral("Radio/ListenGroups"), radioGrp.group_issi2());
|
||||
s.setValue(QStringLiteral("Radio/UseScrambling"), m_pdp->useTetraScrambling() ? 1 : 0);
|
||||
s.setValue(QStringLiteral("Injection/Port"), randomListenPort());
|
||||
s.sync();
|
||||
}
|
||||
|
||||
// Start PrtCnv
|
||||
if (!startPrtCnv())
|
||||
return false;
|
||||
}
|
||||
else // new radio grp ID is 0 and PrtCnv has ben running
|
||||
cleanupProcess(); // quit running PrtCnv
|
||||
|
||||
// set radio grp at the end of update process
|
||||
m_radioGrpId = newRadioGrpId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TetraPrtCnv::checkConfigTemplates()
|
||||
{
|
||||
if (!QFile::exists(playerIdsFile()))
|
||||
{
|
||||
INFO_LOG(m_logger) << "Creating " << playerIdsFile();
|
||||
if (!QFile::copy(QStringLiteral(":/playerIds.dat"), playerIdsFile()))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error creating " << playerIdsFile();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
QFile(playerIdsFile()).setPermissions(QFile::ReadOwner | QFile::ReadGroup | QFile::ReadOther | QFile::WriteOwner);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TetraPrtCnv::startPrtCnv()
|
||||
{
|
||||
NOTICE_LOG(m_logger) << "Starting PrtCnv (intern)";
|
||||
cleanupProcess();
|
||||
m_prtCnvApp = new PrtCnv::PrtCnvApplication;
|
||||
const QSqlDatabase db = m_pdp->databaseConnection();
|
||||
m_prtCnvApp->setDatabaseConnectionParams(db.driverName(),
|
||||
db.hostName(),
|
||||
db.databaseName(),
|
||||
m_pdp->databaseSchemaName(),
|
||||
db.userName(),
|
||||
db.password());
|
||||
m_prtCnvApp->setExerciseId(m_pdp->exerciseId());
|
||||
m_prtCnvApp->setConfigFile(iniFileOut());
|
||||
|
||||
connect(m_prtCnvApp, &PrtCnv::PrtCnvApplication::textMessageFromPrtCnvToCentral,
|
||||
this, &TetraPrtCnv::textMessageFromPrtCnv);
|
||||
connect(this, &TetraPrtCnv::textMessageToPrtCnv,
|
||||
m_prtCnvApp, &PrtCnv::PrtCnvApplication::textMessageFromCentralToPrtCnv);
|
||||
connect(this, &TetraPrtCnv::broadcastTelegramsRequest,
|
||||
m_prtCnvApp, &PrtCnv::PrtCnvApplication::outgoingBroadcastTelegramsRequest);
|
||||
|
||||
m_prtCnvApp->startApp();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TetraPrtCnv::cleanupProcess()
|
||||
{
|
||||
if (!m_prtCnvApp)
|
||||
return;
|
||||
m_prtCnvApp->shutdownApp();
|
||||
delete m_prtCnvApp;
|
||||
m_prtCnvApp = nullptr;
|
||||
|
||||
emit tetraConnectionChanged(false); // initial
|
||||
}
|
||||
|
||||
QString TetraPrtCnv::iniFileOut() const
|
||||
{
|
||||
return iniPath() + QStringLiteral("/PrtCnv_ex_%1.dat").arg(m_exerciseId);
|
||||
}
|
||||
|
||||
QString TetraPrtCnv::iniPath()
|
||||
{
|
||||
return QCoreApplication::applicationDirPath() + QLatin1Char('/');
|
||||
}
|
||||
|
||||
QString TetraPrtCnv::playerIdsFile()
|
||||
{
|
||||
return iniPath() + QStringLiteral("/playerIds.dat");
|
||||
}
|
||||
|
||||
quint16 TetraPrtCnv::randomListenPort() const
|
||||
{
|
||||
QTcpServer *s = new QTcpServer;
|
||||
s->listen(QHostAddress::Any, 0);
|
||||
while (!s->isListening())
|
||||
QCoreApplication::processEvents();
|
||||
quint16 port = s->serverPort();
|
||||
delete s;
|
||||
return port;
|
||||
}
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from PrtCnv
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
#include <TrainingAreaBase/tab_plugin_interface.h>
|
||||
#include <PrtCnv/PrtCnvApplication.hpp>
|
||||
#include "logger.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
|
||||
class TetraPrtCnv final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TetraPrtCnv(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
QObject *parent = nullptr);
|
||||
~TetraPrtCnv();
|
||||
|
||||
bool init();
|
||||
|
||||
public Q_SLOTS:
|
||||
void onExerciseChanged();
|
||||
void logWlsTelegram(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele, bool bIsSend);
|
||||
Q_SIGNALS:
|
||||
void tetraConnectionChanged(bool bConnected);
|
||||
void textMessageFromPrtCnv(const QByteArray &message);
|
||||
void textMessageToPrtCnv(const QByteArray &message);
|
||||
void broadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter);
|
||||
private:
|
||||
void cleanupProcess();
|
||||
static QString iniFileIn();
|
||||
QString iniFileOut() const;
|
||||
static QString iniPath();
|
||||
static QString playerIdsFile();
|
||||
bool updatePrtCnv();
|
||||
bool checkConfigTemplates();
|
||||
bool startPrtCnv();
|
||||
quint16 randomListenPort() const;
|
||||
|
||||
private:
|
||||
TrainingAreaBase::Plugin::DataProvider *m_pdp;
|
||||
PrtCnv::PrtCnvApplication *m_prtCnvApp;
|
||||
int m_exerciseId;
|
||||
int m_radioGrpId;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from Wls
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "wls_dispatcher.h"
|
||||
#include "wls_handler_rx.h"
|
||||
#include "wls_handler_tx.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QWebSocket>
|
||||
#include <QTimer>
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
WlsDispatcher::WlsDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
NGL::Settings *settings)
|
||||
: m_recvFromTabCb(recvFromTabCb)
|
||||
, m_recvFromWls(std::make_shared<WlsHandlerRx>(recvFromTabCb, this))
|
||||
, m_sendToWls(std::make_shared<WlsHandlerTx>(pdp, this))
|
||||
, m_settings(settings)
|
||||
, m_webSocket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
|
||||
, m_webSocketReconnectTimer(new QTimer(this))
|
||||
, m_bWarnedOnce(false)
|
||||
, m_logger(getLogger("WlsDispatcher"))
|
||||
{
|
||||
connect(m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
|
||||
this, &WlsDispatcher::onWebSocketError);
|
||||
connect(m_webSocket, &QWebSocket::connected,
|
||||
this, &WlsDispatcher::onWlsConnected);
|
||||
connect(m_webSocket, &QWebSocket::disconnected,
|
||||
this, &WlsDispatcher::onWlsDisconnected);
|
||||
connect(m_webSocket, &QWebSocket::textMessageReceived,
|
||||
this, &WlsDispatcher::onTextMessageReceived);
|
||||
connect(m_webSocketReconnectTimer, &QTimer::timeout,
|
||||
this, &WlsDispatcher::init);
|
||||
connect(m_recvFromWls.get(), &WlsHandlerRx::participantConnectionState,
|
||||
m_sendToWls.get(), &WlsHandlerTx::onParticipantConnectionState);
|
||||
}
|
||||
|
||||
bool WlsDispatcher::init()
|
||||
{
|
||||
emit connectionState(QString::fromUtf8(name()), false);
|
||||
const QUrl url(webSocketUrl());
|
||||
if (!m_bWarnedOnce)
|
||||
NOTICE_LOG(m_logger) << "Using WebSocket url: " << url.toString();
|
||||
m_webSocket->open(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> WlsDispatcher::sendToTab()
|
||||
{
|
||||
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_sendToWls);
|
||||
}
|
||||
|
||||
bool WlsDispatcher::canSendData() const
|
||||
{
|
||||
return m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState;
|
||||
}
|
||||
|
||||
void WlsDispatcher::onWlsConnected()
|
||||
{
|
||||
QWebSocket *ws = qobject_cast<QWebSocket *>(sender());
|
||||
m_sendToWls->onWlsConnected(ws);
|
||||
m_webSocketReconnectTimer->stop();
|
||||
m_bWarnedOnce = false;
|
||||
}
|
||||
|
||||
void WlsDispatcher::onWlsDisconnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Wls socket disconnected";
|
||||
m_webSocketReconnectTimer->start(5000);
|
||||
m_sendToWls->onWlsDisconnected();
|
||||
|
||||
emit connectionState(QString::fromUtf8(name()), false);
|
||||
}
|
||||
|
||||
void WlsDispatcher::onWlsExternalConnectionStateChanged(bool bConnected)
|
||||
{
|
||||
m_sendToWls->onWlsConnectedToExternalSystem(bConnected);
|
||||
emit connectionState(QString::fromUtf8(name()), bConnected);
|
||||
}
|
||||
|
||||
void WlsDispatcher::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 WlsDispatcher::onTextMessageReceived(const QString &message)
|
||||
{
|
||||
// convert from json to internal representation, send to TAB
|
||||
m_recvFromWls->handleTelegram(message.toUtf8());
|
||||
}
|
||||
|
||||
void WlsDispatcher::onParticipantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onParticipantLicenseChange id=" << lc.id()
|
||||
<< " equipmentNumber=" << lc.equipmentNumber;
|
||||
m_recvFromWls->participantLicenseChange(lc);
|
||||
}
|
||||
|
||||
QUrl WlsDispatcher::webSocketUrl() const
|
||||
{
|
||||
const quint16 port = m_settings->settings()->value(QStringLiteral("WLS/webSocketListenPort"), 12346).toInt();
|
||||
const QString addr = m_settings->settings()->value(QStringLiteral("WLS/webSocketHostname"), QStringLiteral("localhost")).toString();
|
||||
return QUrl(QStringLiteral("ws://%1:%2/").arg(addr).arg(port));
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from Wls
|
||||
* $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"
|
||||
|
||||
class QTimer;
|
||||
namespace WlsTetra
|
||||
{
|
||||
class WlsHandlerRx;
|
||||
class WlsHandlerTx;
|
||||
|
||||
class WlsDispatcher final : public TrainingAreaBase::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WlsDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
NGL::Settings *settings);
|
||||
|
||||
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", "WLS"); }
|
||||
public Q_SLOTS:
|
||||
void onWlsConnected();
|
||||
void onWlsDisconnected();
|
||||
void onWlsExternalConnectionStateChanged(bool bConnected);
|
||||
void onWebSocketError();
|
||||
void onTextMessageReceived(const QString &message);
|
||||
void onParticipantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc);
|
||||
Q_SIGNALS:
|
||||
void broadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter);
|
||||
void wlsTelegramReceived(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele);
|
||||
void wlsTelegramSent(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele);
|
||||
private:
|
||||
QUrl webSocketUrl() const;
|
||||
private:
|
||||
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_recvFromTabCb;
|
||||
std::shared_ptr<WlsHandlerRx> m_recvFromWls;
|
||||
std::shared_ptr<WlsHandlerTx> m_sendToWls;
|
||||
NGL::Settings *m_settings;
|
||||
QWebSocket *m_webSocket;
|
||||
QTimer *m_webSocketReconnectTimer;
|
||||
bool m_bWarnedOnce;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* Convert Json from WLS to internal telegrams
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "wls_handler_rx.h"
|
||||
#include "wls_dispatcher.h"
|
||||
|
||||
#include <TrainingAreaBase/training_area_telegrams.h>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
|
||||
WlsHandlerRx::WlsHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
WlsDispatcher *dispatcher)
|
||||
: m_rxHandler(recvFromTabCb)
|
||||
, m_dispatcher(dispatcher)
|
||||
, m_bWarnedOnce(false)
|
||||
, m_logger(getLogger("WlsHandlerRx"))
|
||||
{}
|
||||
|
||||
bool WlsHandlerRx::handleTelegram(const QByteArray &baJson)
|
||||
{
|
||||
using namespace TrainingAreaBase::TetraIcd;
|
||||
|
||||
if (baJson.isEmpty())
|
||||
return false;
|
||||
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
|
||||
TRACE_LOG(m_logger) << "incoming telegram: " << baJson;
|
||||
|
||||
// const QJsonValue sendCounter = obj.value(QStringLiteral("counter"));
|
||||
// if (!sendCounter.isUndefined())
|
||||
// {
|
||||
// if (!sendCounter.isDouble())
|
||||
// return false;
|
||||
// recvCounter = sendCounter.toInt(-1);
|
||||
// DEBUG_LOG(m_logger) << "Incoming telegram with Id " << obj.value(QStringLiteral("type")).toString();
|
||||
// if (recvCounter < 0)
|
||||
// return false;
|
||||
// }
|
||||
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();
|
||||
try
|
||||
{
|
||||
switch (typeId.toInt())
|
||||
{
|
||||
case Constraints<PositionReport>::id(): // 21
|
||||
rxData(PositionReport::fromJson(data));
|
||||
break;
|
||||
case Constraints<ProxyConnectionState>::id(): // 2013
|
||||
m_dispatcher->onWlsExternalConnectionStateChanged(ProxyConnectionState::fromJson(data).connectedToSystem);
|
||||
break;
|
||||
case Constraints<WlsBinarySfmData>::id(): // 3003
|
||||
sfmData(WlsBinarySfmData::fromJson(data));
|
||||
break;
|
||||
case Constraints<WlsParticipantsConnectionState>::id(): // 3004
|
||||
{
|
||||
const auto tele = WlsParticipantsConnectionState::fromJson(data);
|
||||
emit participantConnectionState(tele.equipmentNumber, tele.dataCommunicationPossible);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << baJson << ")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WlsHandlerRx::participantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc)
|
||||
{
|
||||
if (lc.equipmentNumber <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (lc.licenseState)
|
||||
{
|
||||
case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Licensed:
|
||||
m_licensedEquipmentNumbers.insert(lc.equipmentNumber);
|
||||
break;
|
||||
case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Rejected:
|
||||
case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unlicense:
|
||||
m_licensedEquipmentNumbers.remove(lc.equipmentNumber);
|
||||
break;
|
||||
case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unknown:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void WlsHandlerRx::rxData(const TrainingAreaBase::TetraIcd::RequestBroadcastTelegrams &data)
|
||||
{
|
||||
emit m_dispatcher->broadcastTelegramsRequest(data.header.equipmentNumber,
|
||||
data.broadcastIndex,
|
||||
data.resetCounter);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T toSpecialized(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele)
|
||||
{
|
||||
return *(static_cast<T*>(tabTele));
|
||||
}
|
||||
|
||||
bool WlsHandlerRx::handleTelegram(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele)
|
||||
{
|
||||
using namespace TrainingAreaBase::TetraIcd;
|
||||
switch (tabTele->id())
|
||||
{
|
||||
// Telegrams converted from WlsBinarySfmData
|
||||
case Constraints<ManipulationReport>::id(): // 2
|
||||
rxData(toSpecialized<ManipulationReport>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentOperationalState>::id(): // 7
|
||||
rxData(toSpecialized<EquipmentOperationalState>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentConfigurationReport>::id(): // 11
|
||||
rxData(toSpecialized<EquipmentConfigurationReport>(tabTele));
|
||||
break;
|
||||
case Constraints<CtaDataError>::id(): // 12
|
||||
rxData(toSpecialized<CtaDataError>(tabTele));
|
||||
break;
|
||||
case Constraints<MineTriggered>::id(): // 41
|
||||
rxData(toSpecialized<MineTriggered>(tabTele));
|
||||
break;
|
||||
case Constraints<DefinitionIed>::id(): // 43
|
||||
rxData(toSpecialized<DefinitionIed>(tabTele));
|
||||
break;
|
||||
case Constraints<StateIed>::id(): // 44
|
||||
rxData(toSpecialized<StateIed>(tabTele));
|
||||
break;
|
||||
case Constraints<DusSingleMineState>::id(): // 45
|
||||
rxData(toSpecialized<DusSingleMineState>(tabTele));
|
||||
break;
|
||||
case Constraints<StateChangeDirect>::id(): // 52
|
||||
rxData(toSpecialized<StateChangeDirect>(tabTele));
|
||||
break;
|
||||
case Constraints<StateChangeIndirect>::id(): // 53
|
||||
rxData(toSpecialized<StateChangeIndirect>(tabTele));
|
||||
break;
|
||||
case Constraints<OperatorAction>::id(): // 55
|
||||
rxData(toSpecialized<OperatorAction>(tabTele));
|
||||
break;
|
||||
case Constraints<SelectiveReammunition>::id(): // 56
|
||||
rxData(toSpecialized<SelectiveReammunition>(tabTele));
|
||||
break;
|
||||
case Constraints<StateChange>::id(): // 61
|
||||
rxData(toSpecialized<StateChange>(tabTele));
|
||||
break;
|
||||
case Constraints<OpaquePayloadDataIn>::id(): // 71
|
||||
rxData(toSpecialized<OpaquePayloadDataIn>(tabTele));
|
||||
break;
|
||||
case Constraints<RequestBroadcastTelegrams>::id(): // 82
|
||||
rxData(toSpecialized<RequestBroadcastTelegrams>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentEvent>::id(): // 185
|
||||
rxData(toSpecialized<EquipmentEvent>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentGearAssignment>::id(): // 200
|
||||
rxData(toSpecialized<EquipmentGearAssignment>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentGearChargeState>::id(): // 202
|
||||
rxData(toSpecialized<EquipmentGearChargeState>(tabTele));
|
||||
break;
|
||||
case Constraints<BiteReport>::id(): // 205
|
||||
rxData(toSpecialized<BiteReport>(tabTele));
|
||||
break;
|
||||
case Constraints<EquipmentGearEvent>::id(): // 210
|
||||
rxData(toSpecialized<EquipmentGearEvent>(tabTele));
|
||||
break;
|
||||
case Constraints<ParticipantSwVersions>::id(): // 213
|
||||
rxData(toSpecialized<ParticipantSwVersions>(tabTele));
|
||||
break;
|
||||
case Constraints<ParticipantModeReport>::id(): // 231
|
||||
rxData(toSpecialized<ParticipantModeReport>(tabTele));
|
||||
break;
|
||||
case Constraints<ParticipantConfigurationReport>::id(): // 233
|
||||
rxData(toSpecialized<ParticipantConfigurationReport>(tabTele));
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "WlsHandlerRx::handleTelegram no Handler for " << tabTele->id();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class RadioTelegram : public N_CoPrtCnv::CoPrtCnvRadioTelegram
|
||||
{
|
||||
public:
|
||||
RadioTelegram(const QByteArray &data)
|
||||
: N_CoPrtCnv::CoPrtCnvRadioTelegram(data)
|
||||
{}
|
||||
|
||||
uint16_t getPayloadSize() const override
|
||||
{
|
||||
return m_data.size() - CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH;
|
||||
}
|
||||
};
|
||||
|
||||
void WlsHandlerRx::sfmData(const TrainingAreaBase::TetraIcd::WlsBinarySfmData &data)
|
||||
{
|
||||
if (data.payload.size() < 2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid binary data from WLS: " << QJsonDocument(data.toJson()).toJson(QJsonDocument::Compact);
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace N_CoPrtCnv;
|
||||
const int offset = CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH;
|
||||
QByteArray ba(data.payload.size() + offset, Qt::Uninitialized);
|
||||
memcpy(&ba.data()[offset], data.payload.data(), data.payload.size());
|
||||
const RadioTelegram radio(ba);
|
||||
TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele = CoPrtCnvTelegramConverter::convertToTabTele(&radio);
|
||||
if (!tabTele)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not convert binary sfm data to a valid tetra telegram - ignoring ("
|
||||
<< data.header.equipmentNumber << "): " << QByteArray::fromRawData(reinterpret_cast<const char *>(data.payload.data()),
|
||||
data.payload.size()).toHex();
|
||||
return;
|
||||
}
|
||||
handleTelegram(tabTele);
|
||||
delete tabTele;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void WlsHandlerRx::rxData(const T &data)
|
||||
{
|
||||
if (!m_rxHandler)
|
||||
{
|
||||
if (!m_bWarnedOnce)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "No RecvFromTab available";
|
||||
m_bWarnedOnce = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (data.header.equipmentNumber != 0 &&
|
||||
data.id() != TrainingAreaBase::TetraIcd::BITE_MELDUNG2 &&
|
||||
!m_licensedEquipmentNumbers.contains(data.header.equipmentNumber))
|
||||
return;
|
||||
emit m_dispatcher->wlsTelegramReceived(&data);
|
||||
return m_rxHandler->rxData(data);
|
||||
}
|
||||
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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 <QObject>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <memory>
|
||||
#include "logger.h"
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
class WlsDispatcher;
|
||||
class WlsHandlerRx : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WlsHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
WlsDispatcher *dispatcher);
|
||||
|
||||
bool handleTelegram(const QByteArray &baJson);
|
||||
bool handleTelegram(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele);
|
||||
|
||||
void participantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc);
|
||||
Q_SIGNALS:
|
||||
void participantConnectionState(int equipmentNumber, bool dataCommunicationPossible);
|
||||
private:
|
||||
void sfmData(const TrainingAreaBase::TetraIcd::WlsBinarySfmData &data);
|
||||
|
||||
template<typename T>
|
||||
void rxData(const T &data);
|
||||
private:
|
||||
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_rxHandler;
|
||||
QSet<int> m_licensedEquipmentNumbers;
|
||||
WlsDispatcher *m_dispatcher;
|
||||
bool m_bWarnedOnce;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} // namespace WlsTetra
|
||||
@@ -0,0 +1,361 @@
|
||||
/**
|
||||
* Convert telegrams to Json and sent to WLS proxy
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "wls_handler_tx.h"
|
||||
#include "wls_dispatcher.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QWebSocket>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
|
||||
namespace WlsTetra
|
||||
{
|
||||
|
||||
WlsHandlerTx::WlsHandlerTx(TrainingAreaBase::Plugin::DataProvider *pdp, WlsDispatcher *dispatcher)
|
||||
: m_pdp(pdp)
|
||||
, m_webSocket(nullptr)
|
||||
, m_dispatcher(dispatcher)
|
||||
, m_bWlsConnectedToExternalSystem(false)
|
||||
, m_logger(getLogger("WlsHandlerTx"))
|
||||
{}
|
||||
|
||||
void WlsHandlerTx::onWlsConnected(QWebSocket *webSocket)
|
||||
{
|
||||
m_webSocket = webSocket;
|
||||
if (!m_webSocket)
|
||||
return;
|
||||
|
||||
NOTICE_LOG(m_logger) << "Connected to WLS - sending exercise state data and exequipment exercise mapping";
|
||||
const auto eea = m_pdp->exerciseEquipmentAssignment();
|
||||
sendToTx(&eea, true);
|
||||
const auto esd = m_pdp->exerciseStateData();
|
||||
sendToTx(&esd, true);
|
||||
}
|
||||
|
||||
void WlsHandlerTx::onWlsDisconnected()
|
||||
{
|
||||
m_webSocket = nullptr;
|
||||
}
|
||||
|
||||
void WlsHandlerTx::onWlsConnectedToExternalSystem(bool bConnected)
|
||||
{
|
||||
m_bWlsConnectedToExternalSystem = bConnected;
|
||||
}
|
||||
|
||||
TrainingAreaBase::SendToTab::HandleState WlsHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
|
||||
{
|
||||
if (!m_webSocket || !m_bWlsConnectedToExternalSystem)
|
||||
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<DemandBite>::id() ||
|
||||
telegramId == Constraints<Init>::id() ||
|
||||
telegramId == Constraints<DemandVulnerabilityStateChange>::id() ||
|
||||
telegramId == Constraints<CesHitRequest>::id() ||
|
||||
telegramId == Constraints<SetVulnerabilityModel>::id() ||
|
||||
telegramId == Constraints<DemandEquipmentConfigurationReport>::id() ||
|
||||
telegramId == Constraints<LanguageSelection>::id() ||
|
||||
telegramId == Constraints<EquipmentMessage>::id() ||
|
||||
telegramId == Constraints<ParticipantMode>::id() ||
|
||||
telegramId == Constraints<DemandParticipantMode>::id() ||
|
||||
telegramId == Constraints<ParticipantConfiguration>::id() ||
|
||||
telegramId == Constraints<DemandParticipantConfiguration>::id()
|
||||
)
|
||||
return HandleState::YesConsume;
|
||||
|
||||
// currently no data to wls, TODO
|
||||
return HandleState::No;
|
||||
}
|
||||
|
||||
void WlsHandlerTx::resetSendCounter()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::Acknowledge &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandBite &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::Init &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineTriggered &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false; // only for Tetra - really?
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTxBinary(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::Sanitation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WlsHandlerTx::onParticipantConnectionState(int equipmentNumber, bool dataCommunicationPossible)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onParticipantConnectionState - " << equipmentNumber
|
||||
<< ", communication possible: " << dataCommunicationPossible;
|
||||
m_dataCommunicationPossible[equipmentNumber] = dataCommunicationPossible;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool WlsHandlerTx::sendToTxBinary(const T *data)
|
||||
{
|
||||
if (!m_webSocket || !m_bWlsConnectedToExternalSystem || !data)
|
||||
return false;
|
||||
|
||||
using namespace N_CoPrtCnv;
|
||||
CoPrtCnvRadioTelegram *radio = CoPrtCnvTelegramConverter::convertToRadio(data);
|
||||
if (!radio)
|
||||
return false;
|
||||
|
||||
emit m_dispatcher->wlsTelegramSent(data);
|
||||
TrainingAreaBase::TetraIcd::WlsBinarySfmData tele;
|
||||
tele.header = data->header;
|
||||
|
||||
const int offset = CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH;
|
||||
const char *dataPtr = radio->getData() + offset;
|
||||
tele.payload.resize(radio->getSize() - offset);
|
||||
memcpy(tele.payload.data(), dataPtr, tele.payload.size());
|
||||
|
||||
delete radio;
|
||||
return sendToTx(&tele, false, true);
|
||||
}
|
||||
|
||||
bool WlsHandlerTx::sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data, bool bForce, bool bIsAlreadyLogged)
|
||||
{
|
||||
if (!m_webSocket || (!m_bWlsConnectedToExternalSystem && !bForce))
|
||||
return false;
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("data")] = data->toJson();
|
||||
obj[QStringLiteral("type")] = data->type();
|
||||
obj[QStringLiteral("typeId")] = data->id();
|
||||
// if (data->id() != TrainingAreaBase::TetraIcd::TelegramId::BESTAETIGUNG)
|
||||
// obj[QStringLiteral("counter")] = m_sendCounter++;
|
||||
const QByteArray ba = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
if (data->id() != TrainingAreaBase::TetraIcd::TelegramId::BESTAETIGUNG)
|
||||
DEBUG_LOG(m_logger) << "Sending tele: " << ba;
|
||||
m_webSocket->sendTextMessage(QString::fromUtf8(ba));
|
||||
if (!bIsAlreadyLogged)
|
||||
emit m_dispatcher->wlsTelegramSent(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace WlsTetra
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Convert telegrams to Json and sent to WLS proxy
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
#include <TrainingAreaBase/send_to_tab.h>
|
||||
#include <TrainingAreaBase/tab_plugin_interface.h>
|
||||
#include <QHash>
|
||||
|
||||
class QWebSocket;
|
||||
namespace WlsTetra
|
||||
{
|
||||
class WlsDispatcher;
|
||||
class WlsHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WlsHandlerTx(TrainingAreaBase::Plugin::DataProvider *pdp, WlsDispatcher *dispatcher);
|
||||
|
||||
void onWlsConnected(QWebSocket *webSocket);
|
||||
void onWlsDisconnected();
|
||||
void onWlsConnectedToExternalSystem(bool bConnected);
|
||||
|
||||
const char *name() const override { return "Wls"; }
|
||||
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;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void onParticipantConnectionState(int equipmentNumber, bool dataCommunicationPossible);
|
||||
private:
|
||||
template <typename T>
|
||||
bool sendToTxBinary(const T *data);
|
||||
bool sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data,
|
||||
bool bForce = false,
|
||||
bool bIsAlreadyLogged = false);
|
||||
private:
|
||||
QHash<int, bool> m_dataCommunicationPossible; // equioNo, reachable
|
||||
TrainingAreaBase::Plugin::DataProvider *m_pdp;
|
||||
QWebSocket *m_webSocket;
|
||||
WlsDispatcher *m_dispatcher;
|
||||
bool m_bWlsConnectedToExternalSystem;
|
||||
LOGGER_T m_logger;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user