Initial commit

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

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
#
# 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
nmea_dispatcher.cpp
nmea_dispatcher.h
nmea_handler_rx.cpp
nmea_handler_rx.h
nmea_handler_tx.cpp
nmea_handler_tx.h
)
NGL_ADD_LIBRARY(AAR SV tabPluginNmea MODULE ${SRCS})
NGL_INSTALL_TARGET(tabPluginNmea)
NGL_TARGET_LINK_LIBRARIES(tabPluginNmea
CoPrtCnv
NGLLogger
nglsettings
PrtCnvLib
Qt5::Core
Qt5::Network
Qt5::Sql
Qt5::WebSockets
tabPluginInterface
tabTelegrams
)
@@ -0,0 +1,113 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title></head><body><h1>Nmea/ComMaster TAB Plugin Description</h1>
<pre><code>Always use EqNumber 1 to guarantee that the telegram is used for ComMaster
</code></pre>
<p>This TAB Plugin manages the whole communication between ComMaster/RadioMaster Backpack and Excon.
The plugin use a Udp Socket to read and write data.</p>
<ol>
<li>General Description for Telegrams for direction</li>
<li>More detailed description for each Telegram</li>
<li>Which telegrams should be send in which order</li>
</ol>
<h2>1. General Description for Telegrams for direction</h2>
<h3>Excon to Nmea/ComMaster</h3>
<ul>
<li>SetPowerDeviceRequest</li>
</ul>
<h3>Nmea/ComMaster to Excon</h3>
<ul>
<li>PositionReport</li>
<li>BatteryInfo</li>
<li>BatteryAlarm</li>
<li>ServiceControl</li>
</ul>
<h2>2. More detailed description for each telegram</h2>
<h3>SetPowerDeviceRequest Telegram</h3>
<p>The telegram need to be send with <strong>Equipment Number 1</strong>.
The <strong>PowerMethod</strong> need to be <strong>PowerOff</strong>.
The ComMaster will immediately shut down after the command was send.
<strong>Structur SetPowerDeviceRequest:</strong></p>
<blockquote>
<p>Header<br>
- EqNumber : <em>Integer</em><br>
- Timestamp : <em>MsecsSinceEpoch</em><br>
powerType : <em>Enum</em> | Unknown = 0, PowerOn = 1, PowerOff = 2, <strong>Need to be PowerOff for ComMaster</strong><br>
subdeviceId : <em>Integer</em> | Not necessary for ComMaster<br></p>
</blockquote>
<h3>Position Report</h3>
<p>Under construction&hellip;</p>
<h3>BatteryInfo Telegram</h3>
<p>The telegram hold the informnation for each battery.<br>
<strong>Structure BatteryInfo:</strong></p>
<blockquote>
<p>Header<br>
- EqNumber : <em>Integer</em><br>
- Timestamp : <em>MsecsSinceEpoch</em><br>
Vector of BatteryStates</p>
</blockquote>
<p><strong>Structure BatteryState:</strong></p>
<blockquote>
<p>batteryPort : <em>Integer</em> | Right or left battery slot in Backup<br>
battery : <em>Integer</em> | State of charge 0-5, 0 = Empty , 5 = Full <br>
voltage : <em>Integer</em> | Maybe in mV <br>
temperature : <em>Integer</em> | In °C<br>
frequency : <em>Integer</em><br>
generic : <em>Integer</em><br>
current : <em>Integer</em><br>
switchOrValue : <em>Boolean</em><br>
serialNumber : <em>String</em><br></p>
</blockquote>
<h3>BatteryAlarm Telegram</h3>
<p><strong>Structure of BatteryAlarm:</strong></p>
<blockquote>
<p>Header<br>
- EqNumber : <em>Integer</em><br>
- Timestamp : <em>MsecsSinceEpoch</em><br>
id : <em>Integer</em><br>
description : <em>String</em><br>
acknowledge : <em>Boolean</em><br>
condition : <em>Boolean</em><br>
uniqueAlarmNumber : <em>Integer</em><br>
alarmTime : <em>Uint64</em><br></p>
</blockquote>
<h3>ServiceControl Telegram</h3>
<p>Hold the current power state of the ComMaster Backpack</p>
<p><strong>Structure of ServiceControl:</strong></p>
<blockquote>
<p>Header<br>
- EqNumber : <em>Integer</em><br>
- Timestamp : <em>MsecsSinceEpoch</em><br>
serviceControlState : <em>ServiceControlEnum</em> | 0 = PRESHUTDOWN (Device will prepare shutdown), 1 = SHUTDOWN (The devive will shutdown now), 2 = STOP (The device is off now)</p>
</blockquote>
<hr>
<p>Author: Niklas Schmidt</p>
<p>Last Update: 05.06.22</p>
</body></html>
+38
View File
@@ -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 Nmea
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "TAB.NME.";
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
View File
@@ -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 Nmea
{
using LOGGER_T = NGL::INGLLogger&;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace NmeaTabPlugin
@@ -0,0 +1,57 @@
/**
* 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 "nmea_dispatcher.h"
#include "nmea_handler_tx.h"
//#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
#include <QSettings>
namespace Nmea
{
MainDispatcher::MainDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
NGL::Settings *settings)
: m_tetraDispatcher(new NmeaDispatcher(pdp, recvFromTabCb, settings))
, m_recvFromTabCb(recvFromTabCb)
, m_mainHandlerTx(std::make_shared<MainHandlerTx>(
std::dynamic_pointer_cast<NmeaHandlerTx>(m_tetraDispatcher->sendToTab())))
, m_settings(settings)
, m_logger(getLogger("MainDispatcher"))
{
}
MainDispatcher::~MainDispatcher()
{
m_mainHandlerTx = nullptr;
m_recvFromTabCb = nullptr;
delete m_tetraDispatcher;
}
bool MainDispatcher::init()
{
return true;
}
std::shared_ptr<TrainingAreaBase::SendToTab> MainDispatcher::sendToTab()
{
return m_mainHandlerTx;
}
bool MainDispatcher::canSendData() const
{
return true;
}
void MainDispatcher::exerciseChanged()
{
m_tetraDispatcher->exerciseChanged();
}
} // namespace NmeaTabPlugin
@@ -0,0 +1,47 @@
/**
* 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 Nmea
{
class NmeaDispatcher;
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 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", "Nme"); }
private:
NmeaDispatcher *m_tetraDispatcher;
NGL::Settings *m_settings;
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_recvFromTabCb;
std::shared_ptr<TrainingAreaBase::SendToTab> m_mainHandlerTx;
NGL::INGLLogger &m_logger;
};
} // namespace NmeaTabPlugin
@@ -0,0 +1,234 @@
/**
* 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 "nmea_handler_tx.h"
using namespace TrainingAreaBase;
namespace Nmea
{
MainHandlerTx::MainHandlerTx(
const std::shared_ptr<NmeaHandlerTx> &nmeaTx)
: m_nmeaHandlerTx(nmeaTx)
, m_logger(getLogger("MainHandlerTx"))
{}
SendToTab::HandleState MainHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
{
return m_nmeaHandlerTx->canHandleTelegram(equipmentNumber, telegramId);
}
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)
{
return sendToTxMixin(&data);
}
bool MainHandlerTx::txData(const TetraIcd::SetDevicePowerRequest &data)
{
//Consume
return sendToTxMixin(&data);
}
template <typename T>
bool MainHandlerTx::sendToTxMixin(const T *data)
{
return m_nmeaHandlerTx->txData(*data);
}
} // namespace NmeaTabPlugin
@@ -0,0 +1,77 @@
/**
* 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>
namespace Nmea
{
class NmeaHandlerTx;
class MainHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
{
Q_OBJECT
public:
explicit MainHandlerTx(
const std::shared_ptr<NmeaHandlerTx> &nmeaTx);
const char *name() const override { return "Nmea"; }
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<NmeaHandlerTx> m_nmeaHandlerTx;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,148 @@
/**
* Send / Receive telegrams to/from PrtCnv
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-09-26
*/
#include "nmea_dispatcher.h"
#include "nmea_handler_rx.h"
#include "nmea_handler_tx.h"
#include <QSettings>
namespace Nmea
{
NmeaDispatcher::NmeaDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
NGL::Settings *settings)
: TrainingAreaBase::Plugin::Interface()
, m_rxHandler(std::make_shared<NmeaHandlerRx>(recvFromTabCb))
, m_txHandler(std::make_shared<NmeaHandlerTx>())
, m_dataProvider(pdp)
, m_settings(settings)
, m_logger(getLogger("NmeaDispatcher"))
{
m_reconnectTimer = new QTimer(this);
// setup signal and slot
connect(m_reconnectTimer, &QTimer::timeout,
this, &NmeaDispatcher::reconnectTimerSlot);
m_nmeaHost = getNmeaHost();
m_nmeaPort = getNmeaPort();
DEBUG_LOG(m_logger) << "Host: " << m_nmeaHost << " Port: " << m_nmeaPort;
m_socket = new QUdpSocket(this);
connect(m_socket, &QUdpSocket::connected, this, &NmeaDispatcher::connected);
connect(m_socket, &QUdpSocket::disconnected, this, &NmeaDispatcher::disconnected);
connect(m_socket, &QUdpSocket::readyRead, this, &NmeaDispatcher::readyRead);
connect(m_socket, &QUdpSocket::bytesWritten, this, &NmeaDispatcher::bytesWritten);
reconnect();
}
bool NmeaDispatcher::init()
{
return true;
}
std::shared_ptr<TrainingAreaBase::SendToTab> NmeaDispatcher::sendToTab()
{
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_txHandler);
}
bool NmeaDispatcher::canSendData() const
{
return m_txHandler->isConnected();
}
void NmeaDispatcher::exerciseChanged()
{
}
void NmeaDispatcher::reconnect()
{
INFO_LOG(m_logger) << "Connecting,.." << " host = " << m_nmeaHost
<< " port = " << m_nmeaPort;;
if(!m_socket->bind(m_nmeaPort, QAbstractSocket::BindFlag::ShareAddress | QAbstractSocket::BindFlag::ReuseAddressHint))
{
ERROR_LOG(m_logger) << "Error from Socket: " << m_socket->errorString();
m_reconnectTimer->start(10000);
}
else
m_txHandler->onUdpSocketConnected(m_socket, m_nmeaPort, m_nmeaHost);
}
void NmeaDispatcher::connected()
{
m_reconnectTimer->stop();
m_txHandler->onUdpSocketConnected(m_socket, m_nmeaPort, m_nmeaHost);
DEBUG_LOG(m_logger) << "Connected!";
}
void NmeaDispatcher::disconnected()
{
m_reconnectTimer->start();
DEBUG_LOG(m_logger) << "Disconnected!";
}
void NmeaDispatcher::bytesWritten(qint64 bytes)
{
DEBUG_LOG(m_logger) << "We wrote: " << bytes;
}
void NmeaDispatcher::reconnectTimerSlot()
{
m_reconnectTimer->stop();
INFO_LOG(m_logger) << "Reconnect NMEA-Socket "
<< " host = " << m_nmeaHost
<< " port = " << m_nmeaPort;
reconnect();
}
void NmeaDispatcher::readyRead()
{
DEBUG_LOG(m_logger) << "Reading...";
// QByteArray ba = socket->readDatagram();
QByteArray ba;
while (m_socket->hasPendingDatagrams())
{
ba.resize(int(m_socket->pendingDatagramSize()));
m_socket->readDatagram(ba.data(), ba.size());
INFO_LOG(m_logger) << ba;
QByteArray nmeaDataBa = ba; // ba.mid(startNmeaData, endNmeaData);
std::string nmeaDataStd = nmeaDataBa.toStdString() ;
QString nmeaData = QString::fromLocal8Bit(nmeaDataStd.c_str());
DEBUG_LOG(m_logger) << "nmeaDecoder :" << nmeaData;
//ba = ba.mid(endNmeaData, ba.length());
m_rxHandler->handleTelegram(nmeaData);
DEBUG_LOG(m_logger) << "NMEA-Data=" << nmeaData;
DEBUG_LOG(m_logger) << "NMEA-Data ba=" << ba;
}
}
QString NmeaDispatcher::getNmeaHost()
{
return m_settings->settings()->value(QStringLiteral("NME/nmeaHost"), QStringLiteral("localhost")).toString();
}
int NmeaDispatcher::getNmeaPort()
{
return m_settings->settings()->value(QStringLiteral("NME/nmeaPort"), 10110).toInt();
}
} // namespace NmeaTabPlugin
@@ -0,0 +1,66 @@
/**
* 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 <QUdpSocket>
#include <TrainingAreaBase/tab_plugin_interface.h>
#include <nglsettings/nglsettings_settings.h>
#include <DDS/Core/function_reply_object.h> // tr_lts
#include "logger.h"
namespace Nmea
{
class NmeaHandlerRx;
class NmeaHandlerTx;
class NmeaDispatcher final : public TrainingAreaBase::Plugin::Interface
{
Q_OBJECT
public:
explicit NmeaDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb, NGL::Settings *settings);
public slots:
bool init() override;
public:
std::shared_ptr<TrainingAreaBase::SendToTab> sendToTab() override;
bool isDebugInterface() const override { return false; }
bool canSendData() const override;
void exerciseChanged() override;
const char *name() const override { return tr_lts("dds", "TETRA"); }
private slots:
void connected();
void disconnected();
void bytesWritten(qint64 bytes);
void readyRead();
void reconnectTimerSlot();
private:
void reconnect();
QString getNmeaHost();
int getNmeaPort();
private:
std::shared_ptr<NmeaHandlerRx> m_rxHandler;
std::shared_ptr<NmeaHandlerTx> m_txHandler;
TrainingAreaBase::Plugin::DataProvider *m_dataProvider;
int m_nmeaPort;
QString m_nmeaHost;
QUdpSocket *m_socket;
QTimer *m_reconnectTimer;
NGL::INGLLogger &m_logger;
NGL::Settings *m_settings;
};
} // namespace WlsTetra
@@ -0,0 +1,436 @@
/**
* Read XDR telegrams from a directory and convert it to EtsTetraIcd structures
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "nmea_handler_rx.h"
#include <TrainingAreaBase/training_area_telegrams.h>
#include <QDateTime>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
namespace Nmea
{
NmeaHandlerRx::NmeaHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &rxHandler)
: m_rxHandler(rxHandler)
, m_bWarnedOnce(false)
, m_logger(getLogger("TetraHandlerRx"))
{
// NOTE: Just for checking if the communication is working
// QTimer *testTimer = new QTimer(this);
// testTimer->setInterval(4000);
// testTimer->start();
// connect(testTimer, &QTimer::timeout, this, &NmeaHandlerRx::sendTestMessages);
}
bool NmeaHandlerRx::handleTelegram(const QString &data)
{
decode(data);
return true;
}
void NmeaHandlerRx::decode(QString nmeaPackage)
{
QString nmeaType;
int startingPoint;
startingPoint = 0;
if (nmeaPackage == QStringLiteral(""))
return;
while (nmeaPackage.at(startingPoint) != QStringLiteral("$"))
{
startingPoint++;
if (startingPoint >= nmeaPackage.size())
return;
}
nmeaPackage.remove(0, startingPoint);
nmeaType = nmeaPackage.mid(1, 5);
INFO_LOG(m_logger) << "nmeaType=" << nmeaType;
if (nmeaType == QStringLiteral("IIXDR"))
{
NOTICE_LOG(m_logger) << "IIXDR Battery-State";
}
if (nmeaType == QStringLiteral("GPGGA"))
{
INFO_LOG(m_logger) << "Eigenposition";
if (checksum(nmeaPackage))
{
INFO_LOG(m_logger) << "Eigenposition checksum ok";
GPGGA(nmeaPackage);
}
}
else if (nmeaType == QStringLiteral("GPRMC"))
{
if (checksum(nmeaPackage))
GPRMC(nmeaPackage);
}
else if (nmeaType == QStringLiteral("IIXDR"))
{
NOTICE_LOG(m_logger) << "IIXDR";
if (checksum(nmeaPackage))
{
NOTICE_LOG(m_logger) << "IIXDR checksum OK";
IIXDR(nmeaPackage);
}
else
NOTICE_LOG(m_logger) << "IIXDR checksum NOT OK";
}
else if (nmeaType == QStringLiteral("IIALR"))
{
if (checksum(nmeaPackage))
IIALR(nmeaPackage);
}
else
packagesInvalid++;
}
bool NmeaHandlerRx::checksum(QString package)
{
short start = 0;
start = package.indexOf(QStringLiteral("*"));
if (start < 0)
packagesInvalid++;
QString to_chk = package.mid(1, start - 1);
package.remove(0, start + 1);
int cksm = 0;
for (int i = 0; i < to_chk.size(); i++)
{
QChar letra = to_chk.at(i);
cksm = cksm ^ letra.toLatin1();
}
if (cksm == package.toInt(nullptr, 16))
return true;
packagesInvalid++;
return false;
}
void NmeaHandlerRx::IIXDR(const QString &package)
{
int battery;
int temperature;
int frequency;
double generic;
int current;
bool switchOrValue;
int voltage;
QString serialNumber = QStringLiteral("");
QString timeStr;
using namespace TrainingAreaBase::TetraIcd;
BatteryInfo batteryInfo;
BatteryState batteryState;
ServiceControl serviceControl;
QRegExp sep(QStringLiteral("(\\,|\\*)"));
QStringList pkt_data = package.split(sep);
INFO_LOG(m_logger) << "----------------------------------------------------";
INFO_LOG(m_logger) << "batteryState pkt_data.size=" << pkt_data.size();
for (int i = 0; i < pkt_data.size(); i++)
INFO_LOG(m_logger) << "i=" << i << "Value=" << pkt_data[i];
int index = pkt_data.indexOf(QLatin1String("S")) + 1;
if ( index >= 1)
{
INFO_LOG(m_logger) << "Ausschalten!!!";
if (pkt_data[4] == QStringLiteral("SERVICE_CONTROL_PRESHUTDOWN"))
{
INFO_LOG(m_logger) << "SERVICE_CONTROL_PRESHUTDOWN";
serviceControl.serviceControlState = ServiceControlEnum::PRESHUTDOWN;
}
if (pkt_data[4] == QStringLiteral("SERVICE_CONTROL_SHUTDOWN"))
{
INFO_LOG(m_logger) << "SERVICE_CONTROL_SHUTDOWN";
serviceControl.serviceControlState = ServiceControlEnum::SHUTDOWN;
}
if (pkt_data[4] == QStringLiteral("SERVICE_CONTROL_STOP"))
{
INFO_LOG(m_logger) << "SERVICE_CONTROL_STOP";
serviceControl.serviceControlState = ServiceControlEnum::STOP;
}
serviceControl.header.equipmentNumber = 1;
serviceControl.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
rxData(serviceControl);
return;
}
if ( pkt_data.size()>=4)
serialNumber = (pkt_data[4]);
{
if ( !m_batteries.contains(serialNumber))
{
if (m_batteries.size() == 2)
{
m_batteries.clear();
}
m_batteries.append(serialNumber);
}
batteryState.batteryPort = m_batteries.indexOf(serialNumber);
}
index = pkt_data.indexOf(QLatin1String("B")) + 1;
if ( index >= 0)
battery = pkt_data[index].toInt() ;
else
battery = -1;
batteryState.batteryPercent = battery * 20 ;
index = pkt_data.indexOf(QLatin1String("C")) + 1;
if ( index >= 0)
temperature = pkt_data[index].toInt() ;
else
temperature = -1;
batteryState.temperature = temperature;
index = pkt_data.indexOf(QLatin1String("F")) + 1;
if ( index >= 0)
frequency = pkt_data[index].toInt() ;
else
frequency = -1;
batteryState.frequency = frequency;
index = pkt_data.indexOf(QLatin1String("F")) + 1;
if ( index >= 0)
generic = pkt_data[index].toDouble() ;
else
generic = -1.0;
batteryState.generic = generic;
index = pkt_data.lastIndexOf(QLatin1String("I")) + 1;
if ( index >= 0)
current = pkt_data[index].toInt();
else
current = -1;
batteryState.current = current;
index = pkt_data.indexOf(QLatin1String("S")) + 1;
switchOrValue = false;
if ( index >= 0)
if ( pkt_data[index].toInt() == 1 )
switchOrValue = true;
batteryState.switchOrValue = switchOrValue;
index = pkt_data.indexOf(QLatin1String("U")) + 1;
if ( index >= 0)
voltage = pkt_data[index].toInt() ;
else
voltage = -1;
batteryState.voltage = voltage;
batteryState.serialNumber = serialNumber;
INFO_LOG(m_logger) << "publish batteryState serialNumber=" << serialNumber;
batteryInfo.batteryStates = {batteryState};
batteryInfo.header.equipmentNumber = 1;
batteryInfo.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
rxData(batteryInfo);
}
void NmeaHandlerRx::IIALR(const QString &package)
{
using namespace TrainingAreaBase::TetraIcd;
BatteryAlarm batteryAlarm;
QRegExp sep(QStringLiteral("(\\,|\\*)"));
QStringList pkt_data = package.split(sep);
alarm_state packageData;
INFO_LOG(m_logger) << "pkt_data.size=" << pkt_data.size();
// for ( int i = 0; i < pkt_data.size(); i++)
// {
// INFO_LOG(m_logger)<< "i=" << i << "Value=" << pkt_data[i];
// }
packageData.time = pkt_data[1];
packageData.number = pkt_data[2].toInt();
if (pkt_data[3] == QStringLiteral("A"))
packageData.condition = true;
else
packageData.condition = false;
if (pkt_data[4] == QStringLiteral("A"))
packageData.acknowledgeState = true;
else
packageData.acknowledgeState = false;
packageData.description = pkt_data[5];
qint64 timeAlarm = getDateTime(packageData.time);
INFO_LOG(m_logger) << "time=" << packageData.time
<< " timeAlarm=" << timeAlarm
<< " number=" << packageData.number
<< " condition=" << packageData.condition
<< " acknowledgeState=" << packageData.acknowledgeState
<< " description=" << packageData.description;
batteryAlarm.id = 0;
batteryAlarm.alarmTime = timeAlarm;
batteryAlarm.description = packageData.description;
batteryAlarm.acknowledge = packageData.acknowledgeState;
batteryAlarm.condition = packageData.condition;
batteryAlarm.uniqueAlarmNumber = packageData.number;
batteryAlarm.header.equipmentNumber = 1;
batteryAlarm.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
rxData(batteryAlarm);
}
void NmeaHandlerRx::GPGGA(const QString &package)
{
using namespace TrainingAreaBase::TetraIcd;
PositionReport PositionExcon;
QRegExp sep(QStringLiteral("(\\,|\\*)"));
QStringList pkt_data = package.split(sep);
gpgga_data packageData;
packageData.A_hour = pkt_data[1];
packageData.B_latitude = pkt_data[2];
packageData.C_latitude_dir = pkt_data[3].toStdString()[0];
packageData.D_longitude = pkt_data[4];
packageData.E_longitude_dir = pkt_data[5].toStdString()[0];
packageData.F_qualidade_fixa = pkt_data[6].toInt();
packageData.G_quantidade_satelites = pkt_data[7].toInt();
packageData.H_diluicao_da_precisao_horizontal = pkt_data[8].toFloat();
packageData.I_altitude = pkt_data[9].toFloat();
packageData.J_unidade_medida_altura = pkt_data[10].toStdString()[0];
packageData.K_altura_geoide_acima_elipsoide = pkt_data[11].toFloat();
packageData.L_unidade_medida_geoide = pkt_data[12].toStdString()[0];
packageData.M_idade_ultima_atualizacao_dgps = pkt_data[13].toFloat();
packageData.N_dgps_id = pkt_data[14].toInt();
QString hora;
hora = packageData.A_hour.mid(0, 6);
int inserts = 0;
for (int var = 1; var < hora.size() - inserts; ++var)
{
if (var % 2 == 0)
{
hora.insert(var + inserts, QStringLiteral(":"));
inserts++;
}
}
while (packageData.B_latitude[0] == QStringLiteral("0"))
packageData.B_latitude.remove(0, 1);
double lat = packageData.B_latitude.toDouble();
while (packageData.D_longitude[0] == QStringLiteral("0"))
packageData.D_longitude.remove(0, 1);
double lon = packageData.D_longitude.toDouble();
double latDeg = floor(lat / 100) + (lat - floor(lat / 100) * 100) / 60;
double lonDeg = floor(lon / 100) + (lon - floor(lon / 100) * 100) / 60;
if (packageData.C_latitude_dir == 'S' || packageData.C_latitude_dir == 's')
{
latDeg *= -1;
}
if (packageData.E_longitude_dir == 'W' || packageData.E_longitude_dir == 'w')
{
lonDeg *= -1;
}
DEBUG_LOG(m_logger) << "RAW Nmea Position: " << packageData.D_longitude << " | " << packageData.B_latitude;
DEBUG_LOG(m_logger) << "Lat: " << latDeg;
DEBUG_LOG(m_logger) << "Lon: " << lonDeg;
PositionExcon.geoPosition.lat = latDeg * M_PI / 180.0;
PositionExcon.geoPosition.lon = lonDeg * M_PI / 180.0;
//PositionExcon.geoPosition.isValid = true;
PositionExcon.header.equipmentNumber = 1;
PositionExcon.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
rxData(PositionExcon);
}
void NmeaHandlerRx::GPRMC(const QString &package)
{
QRegExp sep(QStringLiteral("(\\,|\\*)"));
QStringList pkt_data = package.split(sep);
gprmc_data packageData;
packageData.A_hour = (int)pkt_data[1].toFloat();
packageData.B_warning = pkt_data[2].toStdString()[0];
packageData.C_latitude = pkt_data[3].toFloat();
packageData.D_latitude_coord = pkt_data[4].toStdString()[0];
packageData.E_longitude = pkt_data[5].toFloat();
packageData.F_longitude_coord = pkt_data[6].toStdString()[0];
packageData.G_velocity = pkt_data[7].toFloat();
packageData.H_CMG = pkt_data[8].toFloat();
packageData.I_data = pkt_data[9].toInt();
packageData.J_variacao_magnetica = pkt_data[10].toFloat();
packageData.K_variacao_magnetica_coord = pkt_data[11].toStdString()[0];
INFO_LOG(m_logger) << "velocidade=" << QString::number(packageData.G_velocity * 1.852);
}
qint64 NmeaHandlerRx::getDateTime(QString receivedTimeStr)
{
int pos = receivedTimeStr.indexOf(QStringLiteral("."));
QString receivedTimeStr1 = receivedTimeStr.left(pos);
QTime currentTime = QTime::currentTime();
qint64 currentDateTime = QDateTime::currentMSecsSinceEpoch();
QTime receivedTime;
int msecsSinceStartOfDay = currentTime.msecsSinceStartOfDay();
qint64 currentDate = currentDateTime - msecsSinceStartOfDay;
QString dateFormat = QStringLiteral("hhmmss");
receivedTime = QTime::fromString(receivedTimeStr1, dateFormat);
qint64 receivedTimeMs = receivedTime.msecsSinceStartOfDay();
return currentDate + receivedTimeMs;
}
void NmeaHandlerRx::sendTestMessages()
{
using namespace TrainingAreaBase::TetraIcd;
BatteryInfo batteryInfo;
BatteryState batteryState;
batteryState.batteryPort = rand() % 2;
batteryState.batteryPercent = (0 + rand() % 5) * 20;
batteryState.current = 5;
batteryState.frequency = 3;
batteryState.generic = 1;
batteryState.serialNumber = QStringLiteral("Test");
batteryState.temperature = 38.8;
DEBUG_LOG(m_logger) << "Send BatteryInfo Message";
batteryInfo.batteryStates = {batteryState};
batteryInfo.header.equipmentNumber = 1;
batteryInfo.header.timeStamp = QDateTime::currentMSecsSinceEpoch();
rxData(batteryInfo);
}
template<typename T>
void NmeaHandlerRx::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 Nmea
+136
View File
@@ -0,0 +1,136 @@
/**
* 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"
#include <cmath>
class QTimer;
namespace Nmea
{
class NmeaHandlerRx : public QObject
{
Q_OBJECT
public:
explicit NmeaHandlerRx(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &rxHandler);
bool handleTelegram(const QString &data);
private:
struct gpgga_data //Global Positioning System Fix Data
{
QString A_hour;
QString B_latitude;
char C_latitude_dir;
QString D_longitude;
char E_longitude_dir;
int F_qualidade_fixa = -1;
int G_quantidade_satelites = -1;
float H_diluicao_da_precisao_horizontal = -1;
float I_altitude = -1;
char J_unidade_medida_altura;
float K_altura_geoide_acima_elipsoide = -1;
char L_unidade_medida_geoide;
float M_idade_ultima_atualizacao_dgps = -1;
int N_dgps_id = -1;
};
struct battery_state
{
QString serialNumber;
int battery; // 0-5 = 0 = empty, 5 = full bennetec intern
int temperature; // Celsius
int frequency; // Hertz
float generic; // x.x = variable data
long current; // mA
bool G_velocity; // 1 = ON/ CLOSED, 0 = OFF/ OPEN
long voltage; // [mV]
};
struct alarm_state
{
QString time;
int number;
bool condition;
bool acknowledgeState;
QString description;
};
struct gpgsa_data //GPS DOP and active satellites
{
char A_modo = -1;
char B_modo_dimensional = -1;
int *CN_ids_satelites;
float O_PDOP = -1;
float P_HDOP = -1;
float Q_VDOP = -1;
};
struct satelite
{
int A_sv_prn = -1;
int B_elevacao_graus = -1; //90 max
int C_azimuth = -1;
int D_snr = -1;
};
struct gpgsv_data //GPS Satellites in view
{
unsigned A_total_mensagens = -1;
unsigned B_numero_desta_mensagem = -1;
int C_satelites_visiveis = -1;
satelite DS_sats[4];
};
struct gprmc_data //Recommended minimum specific GPS/Transit data
{
int A_hour = -1;
char B_warning = -1;
float C_latitude = -1;
char D_latitude_coord = -1;
float E_longitude = -1;
char F_longitude_coord = -1;
float G_velocity = -1;
float H_CMG = -1;
int I_data = -1;
float J_variacao_magnetica = -1;
char K_variacao_magnetica_coord = -1;
};
unsigned packagesInvalid = 0;
void GPGGA(const QString &package);
void GPRMC(const QString &package);
void IIXDR(const QString &package);
void IIALR(const QString &package);
private slots:
void sendTestMessages();
private:
template<typename T>
void rxData(const T &data);
void decode(QString nmeaPackage);
bool checksum(QString package);
qint64 getDateTime(QString receivedTimeStr);
QStringList m_batteries;
protected:
const std::shared_ptr<TrainingAreaBase::RecvFromTab> m_rxHandler;
bool m_bWarnedOnce;
NGL::INGLLogger &m_logger;
};
} // namespace Nmea
@@ -0,0 +1,265 @@
/**
* Write XDR telegrams to a directory
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#include "nmea_handler_tx.h"
#include <QJsonDocument>
#include <QJsonObject>
namespace Nmea
{
NmeaHandlerTx::NmeaHandlerTx()
: QObject()
, SendToTab()
, m_udpSocket(nullptr)
, m_nmeaHost(QStringLiteral("localhost"))
, m_nmeaPort(10110)
, m_logger(getLogger("NmeaHandlerTx"))
{
resetSendCounter();
}
TrainingAreaBase::SendToTab::HandleState NmeaHandlerTx::canHandleTelegram(int equipmentNumber, int telegramId) const
{
if(equipmentNumber != 1) // 1 is ComMaster
return HandleState::No;
if (!m_udpSocket)
return HandleState::No;
using namespace TrainingAreaBase::TetraIcd;
if (telegramId == Constraints<SetDevicePowerRequest>::id())
return HandleState::YesConsume;
return HandleState::No;
}
void NmeaHandlerTx::resetSendCounter()
{
m_sendCounter = 1; // start at 1
}
void NmeaHandlerTx::onUdpSocketConnected(QUdpSocket *udpSocket, int nmeaPort, QString nmeaHost)
{
m_udpSocket = udpSocket;
m_nmeaPort = nmeaPort;
m_nmeaHost = nmeaHost;
}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data)
{
return sendToTx(&data);
}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data)
{
Q_UNUSED(data);
return false;
}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Acknowledge &data)
{
Q_UNUSED(data)
return false;
}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandBite &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Init &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::MineTriggered &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::Sanitation &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
{
Q_UNUSED(data)
return false;}
bool NmeaHandlerTx::sendToTx(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *data)
{
if(data->toJson().value(QStringLiteral("powerType")).toInt() != static_cast<int>(TrainingAreaBase::TetraIcd::PowerMethod::PowerOff))
return false;
if (!m_udpSocket)
return false;
QByteArray shutdownTelegram ("$IIXDR,S,1,,SERVICE_CONTROL_PRESHUTDOWN*79");
qDebug() << shutdownTelegram;
m_udpSocket->writeDatagram(shutdownTelegram, QHostAddress(m_nmeaHost), m_nmeaPort);
return true;
}
} // namespace NmeaTabPlugin
@@ -0,0 +1,86 @@
/**
* Write XDR telegrams to a directory
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#pragma once
#include <QObject>
#include <QUdpSocket>
#include <QWebSocket>
#include <TrainingAreaBase/send_to_tab.h>
#include "logger.h"
namespace Nmea
{
class NmeaHandlerTx final : public QObject, public TrainingAreaBase::SendToTab
{
Q_OBJECT
public:
explicit NmeaHandlerTx();
const char *name() const override { return "Tetra"; }
HandleState canHandleTelegram(int equipmentNumber, int telegramId) const override;
void resetSendCounter() override;
bool isConnected() const { return m_bConnected; }
void onUdpSocketConnected(QUdpSocket *udpSocket, int nmeaPort, QString nmeaHost);
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);
signals:
void outgoingMessage(const QByteArray &msg);
private:
QUdpSocket *m_udpSocket;
QString m_nmeaHost;
int m_nmeaPort;
int m_sendCounter = 1;
bool m_bConnected = false;
NGL::INGLLogger &m_logger;
};
}
+43
View File
@@ -0,0 +1,43 @@
/**
* 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 Nmea
{
/*!
* \brief TabNmeaPlugin::createInterface
* \author Gerlinde Rudolphus und Niklas Schmidt
* \brief
* This plugin manage the connection between ComMaster/RadioMaster backpack and Excon
* Telegrams:
* From Excon to NMEA/ComMaster
* - SetPowerDeviceRequest
* From NMEA/ ComMaster to Excon
* - PositionReport(own position of ComMaster)
* - BatteryInfo
* - BatteryAlarm
* - ServiceControl
* \param pdp
* \param recvFromTabCb
* \param sendToTabCb
* \param settings
* \return
*/
std::shared_ptr<TrainingAreaBase::Plugin::Interface> TabNmeaPlugin::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 Nmea
+30
View File
@@ -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 Nmea
{
class TabNmeaPlugin : public QObject, public TrainingAreaBase::Plugin::Plugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "special:3:tab.nmea")
Q_INTERFACES(TrainingAreaBase::Plugin::Plugin)
public:
TabNmeaPlugin() = default;
~TabNmeaPlugin() = 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 Nmea