Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(xml_FILE dgps_service.xml)
|
||||
|
||||
SET(if_SRCS
|
||||
tcpsocket.cpp
|
||||
tcpsocket.h
|
||||
tetra_if.cpp
|
||||
tetra_if.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV Tetra_Interface ${if_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(Tetra_Interface
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
CoPrtCnv
|
||||
NGLLogger
|
||||
)
|
||||
|
||||
SET(dgps_SRCS
|
||||
main.cpp
|
||||
dds_handler.cpp
|
||||
dds_handler.h
|
||||
dgps_config.cpp
|
||||
dgps_config.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
mainthread.cpp
|
||||
mainthread.h
|
||||
tetra_if_impl.cpp
|
||||
tetra_if_impl.h
|
||||
trimble_if.cpp
|
||||
trimble_if.h
|
||||
log4cxx_dgps.props
|
||||
${xml_FILE}
|
||||
)
|
||||
# make sure xml file is properly installed
|
||||
CODEGEN_HANDLE_SVC_XML(dgps_SRCS ${xml_FILE})
|
||||
|
||||
NGL_ADD_SVC_ICON(dgps_SRCS)
|
||||
NGL_ADD_EXECUTABLE(AAR SV svcDifferentialGPS ${dgps_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(svcDifferentialGPS
|
||||
ddsconnector
|
||||
svcCoreClient
|
||||
Tetra_Interface
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
CoPrtCnv
|
||||
LtsCommandLineParser
|
||||
NGLLogger
|
||||
nglcoreapplication
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcDifferentialGPS)
|
||||
NGL_INSTALL(AAR SV FILES log4cxx_dgps.props DESTINATION bin)
|
||||
NGL_INSTALL(AAR SV FILES dgps.ini DESTINATION bin RENAME dgps.ini.distrib)
|
||||
|
||||
#
|
||||
# Tetra_dgps_simulator
|
||||
#
|
||||
NGL_ADD_EXECUTABLE(AAR SV Tetra_dgps_simulator Simulator/main_sim.cpp Simulator/main_sim.h)
|
||||
NGL_TARGET_LINK_LIBRARIES(Tetra_dgps_simulator
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
)
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QStringList>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include "main_sim.h"
|
||||
|
||||
//
|
||||
// PayloadSender
|
||||
//
|
||||
PayloadSender::PayloadSender(int numByte, int ctrFail, QTcpSocket *s, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_socket(s)
|
||||
, m_timer(new QTimer(this))
|
||||
, m_char('1')
|
||||
, m_numByte(numByte)
|
||||
, m_ctrFail(ctrFail)
|
||||
{
|
||||
m_timer->setInterval(10 * 1000); // 10s
|
||||
m_timer->setSingleShot(false);
|
||||
m_timer->start();
|
||||
connect(m_timer, &QTimer::timeout,
|
||||
this, &PayloadSender::onTimeout);
|
||||
}
|
||||
|
||||
PayloadSender::~PayloadSender()
|
||||
{
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
m_socket->disconnectFromHost();
|
||||
m_socket->waitForDisconnected(2000);
|
||||
}
|
||||
delete m_socket;
|
||||
delete m_timer;
|
||||
}
|
||||
|
||||
void PayloadSender::onTimeout()
|
||||
{
|
||||
static int ctrFail = 0;
|
||||
|
||||
ctrFail++;
|
||||
bool failure = ((ctrFail >= m_ctrFail) && (ctrFail <= (m_ctrFail + 2)));
|
||||
|
||||
if (!failure)
|
||||
{
|
||||
qDebug() << "Sending data to socket " << m_socket << " content: 256 * 0x" << QString::number(m_char, 16);
|
||||
QByteArray ba(m_numByte, m_char++);
|
||||
m_socket->write(ba);
|
||||
}
|
||||
else
|
||||
qDebug() << " +++ Failure: Sending data ";
|
||||
}
|
||||
|
||||
//
|
||||
// TcpTestServer
|
||||
//
|
||||
TcpTestServer::TcpTestServer(int numByte, int ctrFail, QObject *parent)
|
||||
: QTcpServer(parent)
|
||||
, m_numByte(numByte)
|
||||
, m_ctrFail(ctrFail)
|
||||
{
|
||||
connect(this, &TcpTestServer::newConnection,
|
||||
this, &TcpTestServer::onNewIncomingConnection);
|
||||
}
|
||||
|
||||
TcpTestServer::~TcpTestServer()
|
||||
{
|
||||
qDeleteAll(m_openConnections);
|
||||
}
|
||||
|
||||
void TcpTestServer::onNewIncomingConnection()
|
||||
{
|
||||
QTcpSocket *newSocket = nextPendingConnection();
|
||||
if (!newSocket)
|
||||
return;
|
||||
PayloadSender *ps = new PayloadSender(m_numByte, m_ctrFail, newSocket, this);
|
||||
|
||||
connect(newSocket, &QTcpSocket::disconnected,
|
||||
ps, &PayloadSender::deleteLater);
|
||||
|
||||
qDebug() << "Created new payload sender" << ps << "for socket " << newSocket;
|
||||
m_openConnections += ps;
|
||||
|
||||
connect(ps, &PayloadSender::destroyed,
|
||||
this, &TcpTestServer::onPayloadSenderDestroyed);
|
||||
}
|
||||
|
||||
void TcpTestServer::onPayloadSenderDestroyed(QObject *obj)
|
||||
{
|
||||
qDebug() << "Payload sender " << obj << "destroyed";
|
||||
m_openConnections -= obj;
|
||||
}
|
||||
|
||||
//
|
||||
// main
|
||||
//
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
unsigned short port = 1234;
|
||||
int numByte = 40;
|
||||
int ctrFail = -10;
|
||||
if (app.arguments().size() > 1) port = app.arguments().at(1).toInt();
|
||||
if (app.arguments().size() > 2) numByte = app.arguments().at(2).toInt();
|
||||
if (app.arguments().size() > 3) ctrFail = app.arguments().at(3).toInt();
|
||||
|
||||
|
||||
TcpTestServer *srv = new TcpTestServer(numByte, ctrFail);
|
||||
if (!srv->listen(QHostAddress::Any, port))
|
||||
return 1;
|
||||
|
||||
int ret = app.exec();
|
||||
|
||||
delete srv;
|
||||
|
||||
return ret;
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTcpServer>
|
||||
|
||||
class QTimer;
|
||||
class PayloadSender : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PayloadSender(int numByte, int ctrFail, QTcpSocket *s, QObject *parent = nullptr);
|
||||
~PayloadSender();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onTimeout();
|
||||
private:
|
||||
QTcpSocket *m_socket;
|
||||
QTimer *m_timer;
|
||||
char m_char;
|
||||
int m_numByte;
|
||||
int m_ctrFail;
|
||||
};
|
||||
|
||||
class TcpTestServer : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TcpTestServer(int numByte, int ctrFail, QObject *parent = nullptr);
|
||||
~TcpTestServer();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onNewIncomingConnection();
|
||||
void onPayloadSenderDestroyed(QObject *obj);
|
||||
private:
|
||||
QSet<QObject *> m_openConnections;
|
||||
int m_numByte;
|
||||
int m_ctrFail;
|
||||
};
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* DdsHandler for VideoOverlayManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-07-06
|
||||
*/
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
|
||||
DdsHandler::DdsHandler(int domainId)
|
||||
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Global))
|
||||
, m_logger(getLogger("DdsHandler"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool DdsHandler::init(const QStringList &qosFileList)
|
||||
{
|
||||
INFO_LOG(m_logger) << "--- Start DifferentialGPS DDSHandler.";
|
||||
|
||||
if (!m_ddsConnector->init(qosFileList))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
|
||||
return false;
|
||||
}
|
||||
|
||||
// default initialize Publisher only
|
||||
m_ddsConnector->initPublisher();
|
||||
|
||||
// Pacemaker
|
||||
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
} // Namespace DifferentialGPS
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* DdsHandler for VideoOverlayManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-07-06
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class Pacemaker;
|
||||
}
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class DdsHandler final
|
||||
{
|
||||
public:
|
||||
explicit DdsHandler(int domainId);
|
||||
~DdsHandler() = default;
|
||||
|
||||
bool init(const QStringList &qosFileList = QStringList());
|
||||
|
||||
std::shared_ptr<Core::Pacemaker> pacemaker() const
|
||||
{
|
||||
return m_pacemaker;
|
||||
}
|
||||
std::shared_ptr<DDSConnector::DdsConnector> dds() const
|
||||
{
|
||||
return m_ddsConnector;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
std::shared_ptr<Core::Pacemaker> m_pacemaker;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
[Trimble]
|
||||
RxCycle_ms=10000
|
||||
|
||||
[Trimble0]
|
||||
IP= fuer TESTS!!! Benutzung von: localHost 192.168.133.81
|
||||
Port=1234
|
||||
|
||||
[Trimble1]
|
||||
IP= fuer TESTS!!! Benutzung von: localHost 192.168.133.81
|
||||
Port=1235
|
||||
|
||||
[Tetra]
|
||||
FeedbackTimeout_ms = 100
|
||||
|
||||
[Tetra0]
|
||||
IP=192.168.133.81
|
||||
Port=52010
|
||||
ISSI=9989
|
||||
ISSIBroadcast=5014
|
||||
|
||||
[Tetra1]
|
||||
IP=192.168.133.81
|
||||
Port=52011
|
||||
ISSI=9989
|
||||
ISSIBroadcast=5014
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QCoreApplication>
|
||||
#include "dgps_config.h"
|
||||
|
||||
using namespace DifferentialGPS;
|
||||
|
||||
DgpsConfig::DgpsConfig()
|
||||
{
|
||||
}
|
||||
|
||||
DgpsConfig &DgpsConfig::instance()
|
||||
{
|
||||
static DgpsConfig instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DgpsConfig::readIniData(QString iniFileName)
|
||||
{
|
||||
QFileInfo fi(iniFileName);
|
||||
if (!fi.isAbsolute())
|
||||
iniFileName = QCoreApplication::applicationDirPath() + QLatin1Char('/') + iniFileName;
|
||||
|
||||
// Reading of configuration data from "dgps.ini" file
|
||||
QSettings iniData(iniFileName, QSettings::IniFormat);
|
||||
|
||||
m_trimbleConfig.rxCycle_ms = iniData.value(QLatin1String("Trimble/RxCycle_ms"), 0).toInt();
|
||||
|
||||
m_trimbleConfig.ip[0] = iniData.value(QLatin1String("Trimble0/IP"), QString()).toString();
|
||||
m_trimbleConfig.port[0] = iniData.value(QLatin1String("Trimble0/Port"), 11).toInt();
|
||||
|
||||
m_trimbleConfig.ip[1] = iniData.value(QLatin1String("Trimble1/IP")).toString();
|
||||
m_trimbleConfig.port[1] = iniData.value(QLatin1String("Trimble1/Port"), 11).toInt();
|
||||
|
||||
m_tetraConfig.feedbackTimeout_ms = iniData.value(QLatin1String("Tetra/FeedbackTimeout_ms"), 0).toInt();
|
||||
|
||||
m_tetraConfig.ip[0] = iniData.value(QLatin1String("Tetra0/IP"), QString()).toString();
|
||||
m_tetraConfig.port[0] = iniData.value(QLatin1String("Tetra0/Port"), 0).toInt();
|
||||
m_tetraConfig.issi[0] = iniData.value(QLatin1String("Tetra0/ISSI"), 11).toInt();
|
||||
m_tetraConfig.broadcastIssi[0] = iniData.value(QLatin1String("Tetra0/ISSIBroadcast"), 5000).toInt();
|
||||
|
||||
m_tetraConfig.ip[1] = iniData.value(QLatin1String("Tetra1/IP"), QString()).toString();
|
||||
m_tetraConfig.port[1] = iniData.value(QLatin1String("Tetra1/Port"), 0).toInt();
|
||||
m_tetraConfig.issi[1] = iniData.value(QLatin1String("Tetra1/ISSI"), 11).toInt();
|
||||
m_tetraConfig.broadcastIssi[1] = iniData.value(QLatin1String("Tetra1/ISSIBroadcast"), 5000).toInt();
|
||||
}
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class DgpsConfig
|
||||
{
|
||||
private:
|
||||
DgpsConfig();
|
||||
|
||||
public:
|
||||
DgpsConfig(DgpsConfig &) = delete;
|
||||
|
||||
static DgpsConfig &instance();
|
||||
|
||||
void readIniData(QString iniFileName = QLatin1String("dgps.ini"));
|
||||
|
||||
|
||||
struct TrimbleConfig_t
|
||||
{
|
||||
int rxCycle_ms = 0;
|
||||
QString ip[2];
|
||||
quint16 port[2] = {};
|
||||
};
|
||||
|
||||
const TrimbleConfig_t &getTrimbleConfig() const { return m_trimbleConfig; }
|
||||
|
||||
|
||||
struct TetraConfig_t
|
||||
{
|
||||
int feedbackTimeout_ms = 0;
|
||||
QString ip[2];
|
||||
quint16 port[2] = {};
|
||||
int issi[2] = {};
|
||||
int broadcastIssi[2] = {};
|
||||
};
|
||||
|
||||
const TetraConfig_t &getTetraConfig() const { return m_tetraConfig; }
|
||||
|
||||
|
||||
private:
|
||||
TrimbleConfig_t m_trimbleConfig;
|
||||
TetraConfig_t m_tetraConfig;
|
||||
|
||||
};
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<service namespace="DifferentialGPS" procNames="DifferentialGPS" abbreviation="DGPS" exerciseDependency="Global" groups="Core">
|
||||
<rcs>
|
||||
<Id Id="$Id$"/>
|
||||
<HeadURL HeadURL="$HeadURL$"/>
|
||||
<Author Author="$Author$"/>
|
||||
</rcs>
|
||||
<tables/>
|
||||
<dbServiceStructs/>
|
||||
<topicTypes/>
|
||||
<functionTopics/>
|
||||
<enumerations/>
|
||||
</service>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=WARN, file
|
||||
|
||||
#log4j.logger.DGPS=DEBUG
|
||||
#log4j.logger.DGPS.Main=DEBUG
|
||||
#log4j.logger.DGPS.TetraIF=DEBUG
|
||||
#log4j.logger.DGPS.TrimbleIF=ERROR
|
||||
|
||||
###########################################################
|
||||
log4j.appender.file=Lts::RollingFileAppender
|
||||
log4j.appender.file.MaxFileSize=1MB
|
||||
log4j.appender.file.MaxBackupIndex=9
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Console
|
||||
###########################################################
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Syslog
|
||||
###########################################################
|
||||
log4j.appender.syslog=org.apache.log4j.SyslogAppender
|
||||
log4j.appender.syslog.Threshold=ERROR
|
||||
log4j.appender.syslog.SysLogHost=localhost
|
||||
log4j.appender.syslog.Facility=LOCAL7
|
||||
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
|
||||
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
|
||||
|
||||
|
||||
###########################################################
|
||||
###########################################################
|
||||
###########################################################
|
||||
# 1) Available Levels in LOG4CXX Version 0.10.0:
|
||||
# TRACE,
|
||||
# DEBUG,
|
||||
# INFO,
|
||||
# WARN,
|
||||
# ERROR
|
||||
# FATAL
|
||||
#
|
||||
# d = date/time
|
||||
# p = priority (Level)
|
||||
# c = category/channel
|
||||
# m = message
|
||||
# F = file
|
||||
# L = line
|
||||
# n = platform dependent line separator character or characters.
|
||||
# ....
|
||||
#
|
||||
# Examples for console:
|
||||
# a)
|
||||
# %d %p %c #%m# (%.50F:%L)%n
|
||||
# date/time
|
||||
# priority
|
||||
# category/channel
|
||||
# #message#
|
||||
# (Maximal 50Character des Filename von rechts:Line)
|
||||
# line separator
|
||||
#
|
||||
# b)
|
||||
# %d (%.15F:%L) %-5p %c |#| %m%n
|
||||
# date/time
|
||||
# (Maximal 15Character des Filename von rechts:Line)
|
||||
# priority, Right pad with spaces if the priority name is less than 5 characters long.
|
||||
# category/channel
|
||||
# message
|
||||
# line separator
|
||||
#
|
||||
# Examples for files:
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "DGPS.";
|
||||
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 DifferentialGPS
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for Buildings
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
using LOGGER_T = NGL::INGLLogger &;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <nglapplication/nglcoreapplication.h>
|
||||
#include <LtsCommandLineParser/LtsCommandLineParser.h>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#include "logger.h"
|
||||
#include "mainthread.h"
|
||||
#include "dgps_config.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
NGLCoreApplication app(argc, argv);
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy());
|
||||
|
||||
int iRet = -1;
|
||||
LtsCommandLineParser::LtsCommandLineParser options;
|
||||
if (!options.init())
|
||||
return iRet;
|
||||
app.createLogger("DGPS", options.exerciseId());
|
||||
|
||||
// Reading of configuration data from "dgps.ini" file
|
||||
QString iniFileName(options.iniFile());
|
||||
if (iniFileName.isEmpty())
|
||||
DifferentialGPS::DgpsConfig::instance().readIniData();
|
||||
else
|
||||
DifferentialGPS::DgpsConfig::instance().readIniData(iniFileName);
|
||||
|
||||
{
|
||||
std::unique_ptr<DifferentialGPS::MainThread> mainThread(new DifferentialGPS::MainThread);
|
||||
if (mainThread->init(options.domainId()))
|
||||
{
|
||||
STARTUP_LOG(app.baseLogger());
|
||||
iRet = app.exec();
|
||||
SHUTDOWN_LOG(app.baseLogger());
|
||||
}
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "mainthread.h"
|
||||
|
||||
#include "tetra_if_impl.h"
|
||||
#include "trimble_if.h"
|
||||
|
||||
#include <QMutexLocker>
|
||||
#include <QTimer>
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
MainThread::MainThread(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(nullptr)
|
||||
, m_dgpsTimer(new QTimer(this))
|
||||
, m_tetraIfNum(0)
|
||||
, m_trimbleIfNum(0)
|
||||
, m_logger(getLogger("MainThread"))
|
||||
, m_broadcastTime(QTime::currentTime())
|
||||
, m_broadcastCycle_ms(10000)
|
||||
{
|
||||
m_tetraIF[0] = new TetraImpl;
|
||||
m_tetraIF[1] = new TetraImpl;
|
||||
|
||||
m_trimbleIF[0] = new TrimbleIF;
|
||||
m_trimbleIF[1] = new TrimbleIF;
|
||||
|
||||
connect(this, &MainThread::newDataAvailable,
|
||||
m_tetraIF[m_tetraIfNum], &TetraImpl::onNewDataAvailable,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
}
|
||||
|
||||
MainThread::~MainThread()
|
||||
{
|
||||
m_ddsHandler = nullptr;
|
||||
|
||||
m_tetraIF[0]->quit();
|
||||
m_tetraIF[1]->quit();
|
||||
m_trimbleIF[0]->quit();
|
||||
m_trimbleIF[1]->quit();
|
||||
|
||||
m_tetraIF[0]->wait();
|
||||
m_tetraIF[1]->wait();
|
||||
m_trimbleIF[0]->wait();
|
||||
m_trimbleIF[1]->wait();
|
||||
|
||||
delete m_tetraIF[0];
|
||||
delete m_tetraIF[1];
|
||||
delete m_trimbleIF[0];
|
||||
delete m_trimbleIF[1];
|
||||
}
|
||||
|
||||
|
||||
bool MainThread::init(int domainId)
|
||||
{
|
||||
m_ddsHandler.reset(new DdsHandler(domainId));
|
||||
if (!m_ddsHandler->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation DdsHandler failed.";
|
||||
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StartingError);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_trimbleIF[0]->startThread(0, this);
|
||||
m_trimbleIF[1]->startThread(1, this);
|
||||
|
||||
m_tetraIF[m_tetraIfNum]->startThread(m_tetraIfNum, this);
|
||||
|
||||
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainThread::addNewData(const QByteArray &ba, int trimbleIfNum)
|
||||
{
|
||||
const int cycle_ms = m_broadcastCycle_ms + (m_broadcastCycle_ms / 5); // Zykluszeit + 20%
|
||||
QTime currentTime = QTime::currentTime();
|
||||
|
||||
bool overtake = (trimbleIfNum == m_trimbleIfNum);
|
||||
if (!overtake)
|
||||
{
|
||||
if (m_broadcastTime.msecsTo(currentTime) > cycle_ms)
|
||||
{
|
||||
overtake = true;
|
||||
m_trimbleIfNum = trimbleIfNum; // Lese ab jetzt bevorzugt von diesem IF
|
||||
}
|
||||
}
|
||||
|
||||
if (overtake)
|
||||
{
|
||||
QMutexLocker l(&m_mutex);
|
||||
m_dgpsData = ba;
|
||||
if (m_tetraIF[m_tetraIfNum]->isRunning())
|
||||
emit newDataAvailable();
|
||||
else
|
||||
{
|
||||
disconnect(this, &MainThread::newDataAvailable,
|
||||
m_tetraIF[m_tetraIfNum], &TetraImpl::onNewDataAvailable);
|
||||
m_tetraIfNum = (m_tetraIfNum + 1) % 2;
|
||||
connect(this, &MainThread::newDataAvailable,
|
||||
m_tetraIF[m_tetraIfNum], &TetraImpl::onNewDataAvailable,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
m_tetraIF[m_tetraIfNum]->startThread(m_tetraIfNum, this);
|
||||
}
|
||||
|
||||
m_broadcastTime = currentTime; // Die Broadcast-Zeit merken
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MainThread::getNewData(QByteArray &ba)
|
||||
{
|
||||
QMutexLocker l(&m_mutex);
|
||||
if (!m_dgpsData.size())
|
||||
return false;
|
||||
ba = m_dgpsData;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include "logger.h"
|
||||
#include "dds_handler.h"
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class TetraImpl;
|
||||
class TrimbleIF;
|
||||
|
||||
class MainThread final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainThread(QObject *parent = nullptr);
|
||||
~MainThread();
|
||||
|
||||
bool init(int domainId);
|
||||
|
||||
void addNewData(const QByteArray &ba, int trimbleIfNum);
|
||||
bool getNewData(QByteArray &ba);
|
||||
|
||||
Q_SIGNALS:
|
||||
void newDataAvailable();
|
||||
protected:
|
||||
std::shared_ptr<DdsHandler> m_ddsHandler;
|
||||
QByteArray m_dgpsData;
|
||||
QTimer *m_dgpsTimer;
|
||||
QMutex m_mutex;
|
||||
|
||||
TetraImpl *m_tetraIF[2];
|
||||
int m_tetraIfNum; // Nummer des Tetra IF-es, an das Daten gesendet werden.
|
||||
|
||||
TrimbleIF *m_trimbleIF[2];
|
||||
int m_trimbleIfNum; // Nummer des Trimble IF-es, von dem Daten erwartet werden.
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
QTime m_broadcastTime;
|
||||
int m_broadcastCycle_ms;
|
||||
};
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#include "tcpsocket.h"
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QTimer>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
TcpSocket::TcpSocket(const char *logName)
|
||||
: QThread()
|
||||
, m_socket(nullptr)
|
||||
, m_logger(getLogger(logName))
|
||||
, m_waitTime(1)
|
||||
, m_reconnectTimer(nullptr)
|
||||
{
|
||||
qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
|
||||
moveToThread(this);
|
||||
}
|
||||
|
||||
TcpSocket::~TcpSocket()
|
||||
{
|
||||
cleanupObject(); // just to be sure
|
||||
}
|
||||
|
||||
void TcpSocket::startThreadInternal(const QString &hostName, quint16 port)
|
||||
{
|
||||
m_hostName = hostName;
|
||||
m_hostPort = port;
|
||||
start();
|
||||
}
|
||||
|
||||
void TcpSocket::run()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Starting thread";
|
||||
m_reconnectTimer = new QTimer(this);
|
||||
doConnect();
|
||||
exec();
|
||||
cleanupObject();
|
||||
}
|
||||
|
||||
void TcpSocket::doConnect()
|
||||
{
|
||||
if (m_socket)
|
||||
m_socket->deleteLater();;
|
||||
m_socket = new QTcpSocket(this);
|
||||
connect(m_socket, &QTcpSocket::connected,
|
||||
this, &TcpSocket::onConnected);
|
||||
connect(m_socket, &QTcpSocket::disconnected,
|
||||
this, &TcpSocket::onDisconnected);
|
||||
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
|
||||
this, &TcpSocket::onError);
|
||||
connect(m_socket, &QTcpSocket::readyRead,
|
||||
this, &TcpSocket::onReadyRead);
|
||||
|
||||
INFO_LOG(m_logger) << "Connecting to tcp server at "
|
||||
<< m_hostName << ":" << m_hostPort;
|
||||
m_socket->connectToHost(m_hostName, m_hostPort);
|
||||
}
|
||||
|
||||
void TcpSocket::onConnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Connected to "
|
||||
<< m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
m_waitTime = 1;
|
||||
}
|
||||
|
||||
void TcpSocket::onDisconnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Disconnected from " << m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
}
|
||||
|
||||
void TcpSocket::onError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Socket error: " << err
|
||||
<< " " << m_socket->errorString()
|
||||
<< ":" << m_socket->peerPort()
|
||||
<< " - trying to reconnect in " << m_waitTime << " seconds";
|
||||
m_socket->disconnectFromHost();
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
|
||||
m_waitTime += 2;
|
||||
|
||||
if (!m_reconnectTimer->isActive())
|
||||
m_reconnectTimer->start(m_waitTime * 1000);
|
||||
|
||||
if (m_waitTime > 120)
|
||||
m_waitTime = 120;
|
||||
}
|
||||
|
||||
void TcpSocket::cleanupObject()
|
||||
{
|
||||
if (m_reconnectTimer)
|
||||
{
|
||||
m_reconnectTimer->disconnect(this);
|
||||
delete m_reconnectTimer;
|
||||
m_reconnectTimer = nullptr;
|
||||
}
|
||||
if (m_socket)
|
||||
{
|
||||
m_socket->disconnect(this);
|
||||
m_socket->close();
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
delete m_socket;
|
||||
m_socket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtNetwork/QAbstractSocket>
|
||||
#include <QtCore/QThread>
|
||||
#include "logger.h"
|
||||
|
||||
class QTcpSocket;
|
||||
class QTimer;
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class TcpSocket : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TcpSocket(const char *logName);
|
||||
~TcpSocket();
|
||||
|
||||
protected:
|
||||
void startThreadInternal(const QString &hostName, quint16 port);
|
||||
|
||||
void run() override;
|
||||
|
||||
void doConnect();
|
||||
|
||||
void cleanupObject();
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void onConnected();
|
||||
virtual void onDisconnected();
|
||||
virtual void onError(QAbstractSocket::SocketError);
|
||||
virtual void onReadyRead() = 0;
|
||||
protected:
|
||||
QString m_hostName;
|
||||
quint16 m_hostPort;
|
||||
QTcpSocket *m_socket;
|
||||
NGL::INGLLogger &m_logger;
|
||||
private:
|
||||
qint32 m_waitTime;
|
||||
QTimer *m_reconnectTimer;
|
||||
};
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+248
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#include "tetra_if.h"
|
||||
#include "dgps_config.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkInterface>
|
||||
#include <QTimer>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
void TetraIF::startThreadInternal(int threadIndex)
|
||||
{
|
||||
const DgpsConfig::TetraConfig_t &cfg = DgpsConfig::instance().getTetraConfig();
|
||||
|
||||
m_srcIssi = cfg.issi[threadIndex];
|
||||
m_broadcastIssi = cfg.broadcastIssi[threadIndex];
|
||||
m_feedbackTimeout_ms = cfg.feedbackTimeout_ms;
|
||||
TcpSocket::startThreadInternal(cfg.ip[threadIndex], cfg.port[threadIndex]);
|
||||
}
|
||||
|
||||
|
||||
void TetraIF::run()
|
||||
{
|
||||
m_feedbackTimeout = new QTimer(this);
|
||||
m_feedbackTimeout->setSingleShot(true);
|
||||
connect(m_feedbackTimeout, &QTimer::timeout,
|
||||
this, &TetraIF::onFeedbackTimeout);
|
||||
|
||||
TcpSocket::run();
|
||||
|
||||
m_feedbackTimeout->disconnect(this);
|
||||
delete m_feedbackTimeout;
|
||||
m_feedbackTimeout = nullptr;
|
||||
}
|
||||
|
||||
void TetraIF::onNewDataAvailable()
|
||||
{
|
||||
if (m_socket->state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Can not send new data to Tetra - not yet connected ("
|
||||
<< m_socket->state() << ")";
|
||||
return;
|
||||
}
|
||||
if (!m_bTetraOk)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Can not send new data to Tetra - not yet logged in";
|
||||
return;
|
||||
}
|
||||
if (onNewDataAvailableInternal())
|
||||
{
|
||||
// feedback expected; start feedback timeout timer
|
||||
m_feedbackTimeout->start(m_feedbackTimeout_ms);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TetraIF::onFeedbackTimeout()
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Tetra feedback timeout"
|
||||
<< m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
|
||||
m_socket->disconnectFromHost();
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
|
||||
exit(3);
|
||||
}
|
||||
|
||||
bool TetraIF::checkTetraConnecting()
|
||||
{
|
||||
return m_bTetraOk;
|
||||
}
|
||||
|
||||
void TetraIF::doInitialLogin()
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(m_srcIssi);
|
||||
m_socket->write(tele.data());
|
||||
m_socket->flush();
|
||||
}
|
||||
|
||||
void TetraIF::onConnected()
|
||||
{
|
||||
TcpSocket::onConnected();
|
||||
|
||||
m_counter = 1;
|
||||
doInitialLogin();
|
||||
}
|
||||
|
||||
void TetraIF::onDisconnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Disconnected from " << m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
|
||||
exit(3); // stop the thread
|
||||
}
|
||||
|
||||
void TetraIF::onReadyRead()
|
||||
{
|
||||
do
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Reading " << m_socket->bytesAvailable()
|
||||
<< " from " << m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
|
||||
// read the 4-byte frame-header for find out the length of whole telegram
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram::PrtCnvRadioGwHeader header;
|
||||
if (m_socket->bytesAvailable() < (int)sizeof(header))
|
||||
return;
|
||||
|
||||
m_socket->peek((char *)&header, sizeof(header));
|
||||
if (N_CoPrtCnv::CoPrtCnvRadioTelegram::MAGIC_NUMBER != header.m_MagicNumber)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Incorrect magic number (0x"
|
||||
<< (int)header.m_MagicNumber
|
||||
<< " - aborting";
|
||||
exit(2);
|
||||
}
|
||||
if (!N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(header.m_Length))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Radio-Telegram length to big: "
|
||||
<< header.m_Length
|
||||
<< ", but I proceed with this telegram.";
|
||||
}
|
||||
|
||||
quint16 dataSize = header.m_Length + sizeof(header);
|
||||
if (m_socket->bytesAvailable() < dataSize)
|
||||
{
|
||||
INFO_LOG(m_logger) << "not enough bytes available";
|
||||
return;
|
||||
}
|
||||
uint8_t *data = new uint8_t[dataSize];
|
||||
m_socket->read((char *)data, dataSize);
|
||||
|
||||
handleReceivedTelegram(data, dataSize);
|
||||
|
||||
}
|
||||
while (m_socket->bytesAvailable());
|
||||
}
|
||||
|
||||
void TetraIF::onError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Socket error: " << err
|
||||
<< " " << m_socket->errorString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
m_socket->disconnectFromHost();
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
|
||||
exit(3);
|
||||
}
|
||||
|
||||
void TetraIF::handleReceivedTelegram(uint8_t *a_data, quint16 a_dataSize)
|
||||
{
|
||||
if (a_dataSize < 4)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "To few bytes for handle receieved telegramm ("
|
||||
<< a_dataSize << ")";
|
||||
return;
|
||||
}
|
||||
switch (a_data[4])
|
||||
{
|
||||
// response to register indication
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq:
|
||||
INFO_LOG(m_logger) << "Got data from Tetra ...";
|
||||
if (m_feedbackTimeout->isActive())
|
||||
m_feedbackTimeout->stop();
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp:
|
||||
if (a_dataSize < 5)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "To few bytes for handle register response telegramm ("
|
||||
<< a_dataSize << ")";
|
||||
return;
|
||||
}
|
||||
handleRegisterRsp(a_data[5]); // registration status
|
||||
break;
|
||||
default:
|
||||
INFO_LOG(m_logger) << "Radio-Telegram with PDU-Type="
|
||||
<< (int)a_data[4]
|
||||
<< " ignored";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TetraIF::handleRegisterRsp(const uint8_t a_registrationStatus)
|
||||
{
|
||||
std::stringstream logText;
|
||||
switch (a_registrationStatus)
|
||||
{
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_IssiSuccessfulRegistered:
|
||||
INFO_LOG(m_logger) << "Valid register response from Tetra";
|
||||
m_bTetraOk = true;
|
||||
onAddGroupMonitoring();
|
||||
onNewDataAvailable();
|
||||
return;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DuplicateISSI:
|
||||
logText << "TETRA: Register-Response: Status=Duplicate ISSI";
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_InvalidISSI:
|
||||
logText << "TETRA: Register-Response: Status=Invalid ISSI";
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_InvalidIpAddress:
|
||||
logText << "TETRA: Register-Response: Status=Invalid IP address => Configure TETRA for accepting our IP-address (";
|
||||
{
|
||||
const QList<QHostAddress> ipList = QNetworkInterface::allAddresses();
|
||||
QList<QHostAddress>::const_iterator iter = ipList.begin();
|
||||
while (iter != ipList.end())
|
||||
{
|
||||
logText << (*iter).toString().toStdString() << ", ";
|
||||
++iter;
|
||||
}
|
||||
logText << ")...";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logText << "Unknown registration status: " << (int)a_registrationStatus;
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR_LOG(m_logger) << logText.str();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void TetraIF::onAddGroupMonitoring()
|
||||
{
|
||||
std::set<uint32_t> groupsToMonitor;
|
||||
groupsToMonitor.insert(m_broadcastIssi);
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(m_srcIssi, groupsToMonitor);
|
||||
tele.setZaehler(m_counter++);
|
||||
|
||||
m_socket->write(tele.data());
|
||||
m_socket->flush();
|
||||
|
||||
NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, tele.data());
|
||||
|
||||
}
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include "tcpsocket.h"
|
||||
|
||||
class QTcpSocket;
|
||||
class QTimer;
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class TetraIF : public TcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using TcpSocket::TcpSocket;
|
||||
|
||||
void run() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void onNewDataAvailable();
|
||||
void onFeedbackTimeout();
|
||||
bool checkTetraConnecting();
|
||||
|
||||
protected:
|
||||
virtual void startThreadInternal(int threadIndex);
|
||||
virtual bool onNewDataAvailableInternal() = 0;
|
||||
|
||||
|
||||
private:
|
||||
void doConnect();
|
||||
void doInitialLogin();
|
||||
void handleReceivedTelegram(uint8_t *a_data, quint16 a_dataSize);
|
||||
void handleRegisterRsp(const uint8_t a_registrationStatus);
|
||||
void onAddGroupMonitoring();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onConnected() override;
|
||||
void onDisconnected() override;
|
||||
void onReadyRead() override;
|
||||
void onError(QAbstractSocket::SocketError) override;
|
||||
|
||||
protected:
|
||||
int m_srcIssi = 0;
|
||||
int m_broadcastIssi = 0;
|
||||
bool m_bTetraOk = true;
|
||||
quint8 m_counter = 1;
|
||||
QTimer *m_feedbackTimeout = nullptr; // timer for feedback timeout
|
||||
int m_feedbackTimeout_ms = 0; // feedback timeout in ms
|
||||
};
|
||||
} // DifferentialGPS
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "tetra_if_impl.h"
|
||||
|
||||
#include "mainthread.h"
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
#include <time.h>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
TetraImpl::TetraImpl()
|
||||
: TetraIF("TetraIF")
|
||||
, m_main(nullptr)
|
||||
{}
|
||||
|
||||
TetraImpl::~TetraImpl()
|
||||
{}
|
||||
|
||||
void TetraImpl::startThread(int threadIndex, MainThread *main)
|
||||
{
|
||||
m_main = main;
|
||||
startThreadInternal(threadIndex);
|
||||
}
|
||||
|
||||
bool TetraImpl::onNewDataAvailableInternal()
|
||||
{
|
||||
QByteArray payload;
|
||||
if (!m_main->getNewData(payload))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "No data to send";
|
||||
return false;
|
||||
}
|
||||
|
||||
// GEF_BESTAETIGUNG -> Dummy, gets overridden by setPayloadDataComplete()
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, payload.size(), m_broadcastIssi);
|
||||
tele.setPayloadDataComplete(payload);
|
||||
tele.setSrcISSI(m_srcIssi);
|
||||
tele.setDestISSI(m_broadcastIssi);
|
||||
tele.setZaehler(m_counter++);
|
||||
m_socket->write(tele.data());
|
||||
m_socket->flush();
|
||||
|
||||
/*
|
||||
uint8_t* p = tele.getData();
|
||||
QString outText("Data: \n ");
|
||||
for (int i=0; i<tele.getSize(); ++i)
|
||||
{
|
||||
outText.append(QString::number(p[i], 16).rightJustified(2,QChar('0')));
|
||||
outText.append(" ");
|
||||
if(i%8 == 7 )
|
||||
outText.append("\n");
|
||||
}
|
||||
DEBUG_LOG(m_logger) << outText;
|
||||
*/
|
||||
|
||||
DEBUG_LOG(m_logger) << "Sent " << tele.getSize() << " to Tetra";
|
||||
return true;
|
||||
}
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tetra_if.h"
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class MainThread;
|
||||
|
||||
class TetraImpl final : public TetraIF
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TetraImpl();
|
||||
~TetraImpl();
|
||||
void startThread(int threadIndex, MainThread *main);
|
||||
|
||||
protected:
|
||||
bool onNewDataAvailableInternal() override;
|
||||
protected:
|
||||
MainThread *m_main;
|
||||
};
|
||||
} //namespace DifferentialGPS
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#include "trimble_if.h"
|
||||
|
||||
#include "mainthread.h"
|
||||
#include "dgps_config.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
TrimbleIF::TrimbleIF()
|
||||
: TcpSocket("TrimbleIF")
|
||||
, m_main(nullptr)
|
||||
, m_rxCycle_ms(10000)
|
||||
, m_socketTimeout(nullptr)
|
||||
, m_socketReconnect(nullptr)
|
||||
, m_threadIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
TrimbleIF::~TrimbleIF()
|
||||
{
|
||||
}
|
||||
|
||||
void TrimbleIF::startThread(int threadIndex, MainThread *main)
|
||||
{
|
||||
const DgpsConfig::TrimbleConfig_t &cfg = DgpsConfig::instance().getTrimbleConfig();
|
||||
m_threadIndex = threadIndex;
|
||||
m_main = main;
|
||||
startThreadInternal(cfg.ip[threadIndex], cfg.port[threadIndex]);
|
||||
}
|
||||
|
||||
void TrimbleIF::run()
|
||||
{
|
||||
m_socketTimeout = new QTimer;
|
||||
connect(m_socketTimeout, &QTimer::timeout, this, &TrimbleIF::onTimeout);
|
||||
m_socketReconnect = new QTimer;
|
||||
m_socketReconnect->setInterval(60 * 1000);
|
||||
connect(m_socketReconnect, &QTimer::timeout, this, &TrimbleIF::doConnect);
|
||||
|
||||
TcpSocket::run();
|
||||
|
||||
delete m_socketTimeout;
|
||||
delete m_socketReconnect;
|
||||
}
|
||||
|
||||
void TrimbleIF::onError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
m_socketTimeout->stop(); // Timer anhalten
|
||||
|
||||
TcpSocket::onError(err); // Generelle Fehlerbehandlung
|
||||
}
|
||||
|
||||
|
||||
void TrimbleIF::onReadyRead()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Reading " << m_socket->bytesAvailable()
|
||||
<< " bytes from " << m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
m_buf = m_socket->readAll();
|
||||
|
||||
m_main->addNewData(m_buf, m_threadIndex);
|
||||
|
||||
const DgpsConfig::TrimbleConfig_t &cfg = DgpsConfig::instance().getTrimbleConfig();
|
||||
m_socketTimeout->start(3 * cfg.rxCycle_ms); // starte/ restarte timeout-Ueberwachung (3-fache Zykluszeit)
|
||||
}
|
||||
|
||||
|
||||
void TrimbleIF::onTimeout()
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Socket timeout "
|
||||
<< m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort()
|
||||
<< " - trying to reconnect in " << m_socketReconnect->interval() / 1000 << " seconds";
|
||||
|
||||
m_socketTimeout->stop(); // Timer anhalten
|
||||
|
||||
m_socket->disconnectFromHost();
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
|
||||
m_socketReconnect->start();
|
||||
}
|
||||
} // namespace DifferentialGPS
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
#include "mainthread.h"
|
||||
#include "tcpsocket.h"
|
||||
|
||||
class QTcpSocket;
|
||||
class QTimer;
|
||||
class MainThread;
|
||||
|
||||
namespace DifferentialGPS
|
||||
{
|
||||
class TrimbleIF final : public TcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrimbleIF();
|
||||
~TrimbleIF();
|
||||
|
||||
void startThread(int threadIndex, MainThread *main);
|
||||
|
||||
void run() override;
|
||||
|
||||
protected:
|
||||
void dumpDataText(const QByteArray &ba);
|
||||
void dumpDataBinary(const QByteArray &ba);
|
||||
protected Q_SLOTS:
|
||||
void onError(QAbstractSocket::SocketError) override;
|
||||
void onReadyRead() override;
|
||||
void onTimeout();
|
||||
|
||||
protected:
|
||||
MainThread *m_main;
|
||||
QByteArray m_buf;
|
||||
int m_rxCycle_ms; // Zyklus in ms in dem Daten empfangen werden sollten
|
||||
QTimer *m_socketTimeout; // Timer zur Ueberwachung des receive-Daten-Zyklus
|
||||
QTimer *m_socketReconnect; // Timer zum Reconnect-Versuch nachdem m_socketTimeout zugeschlagen hat
|
||||
int m_threadIndex; // Index des Thread [0..1]
|
||||
|
||||
};
|
||||
} // namespace DifferentialGPS
|
||||
Reference in new issue
Block a user