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

+41
View File
@@ -0,0 +1,41 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# CMakeLists.txt fuer topicdiscover
#
SET(topicdiscover_SRCS
topic_discoverer.cpp
topic_discoverer.h
)
NGL_ADD_LIBRARY(AAR SV WS NO_TRANSLATION topicdiscover SHARED ${topicdiscover_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(topicdiscover
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(topicdiscover
PRIVATE
ddsQoS
NGLLogger
RTI::nddsc
RTI::nddscore
PUBLIC
Qt5::Core
RTI::nddscpp2
ddsQoS
)
NGL_INSTALL_TARGET(topicdiscover)
##################
NGL_ADD_EXECUTABLE(topicdiscoverexe AAR SV WS main.cpp)
NGL_TARGET_LINK_LIBRARIES(topicdiscoverexe
LtsCommandLineParser
nglcoreapplication
topicdiscover
)
+78
View File
@@ -0,0 +1,78 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# TopicDiscoverer
###########################################################
log4j.logger.TopicDiscoverer=INFO
log4j.logger.TopicDiscoverer.BuiltinSubscriberListener=INFO
log4j.logger.TopicDiscoverer.BuiltinParticipantListener=INFO
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_topicDiscoverer.log
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:
+69
View File
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* DDS View -> The "LogView" for DDS
* $Id$
* $HeadURL$
* $Author$
*/
/*!
*
* \page OCLaptop O/C Laptop
*
* This part of the TDS software is needed to assist the O/C in the field. It is
* designed to provide a subset of the workstation software to help the O/C to
* evaluate the situation in the field. It has also the possibility to do short
* after action reviews (prepared with the workstation software) and to do evaluations
* for later usage in the workstation i.e. for the after action review. The TakeHomePackage-Viewer
* is also a part of this software component.
*
*/
#include <QtGui/QDesktopServices>
#include <QtCore/QSettings>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <NGLLogger/INGLLogger.h>
#include <nglsettings/nglsettings_settings.h>
#include <nglapplication/nglcoreapplication.h>
#include "topic_discoverer.h"
int main( int argc, char *argv[] )
{
NGLCoreApplication app ( argc, argv );
QCoreApplication::setApplicationName(QLatin1String("Topic Discoverer"));
QCoreApplication::setOrganizationName(QLatin1String("RME"));
app.createLogger("TopicDiscover", "log4cxx_topicdiscover.props");
NGL::INGLLogger &logger = app.baseLogger();
LtsCommandLineParser::LtsCommandLineParser options;
options.addOption( { QStringList() << QLatin1String("lang") << QLatin1String("language")
, QLatin1String("language / region code (e.g. de_DE or en_US)")
, QLatin1String("de_DE|en_US")
, QLatin1String("en_US") } );
if(!options.init())
{
options.showHelp();
return -1;
}
QString langCodeArg = options.isSet(QLatin1String("lang")) ? options.value(QLatin1String("lang")) : QLatin1String("en_US");
Q_UNUSED(langCodeArg);
STARTUP_LOG(logger);
TopicDiscoverer td(0);
td.init(DDS::QosProfile::ConnectionType::ShmUdp, QUrl());
int retval = app.exec();
SHUTDOWN_LOG(logger);
return retval;
}
+194
View File
@@ -0,0 +1,194 @@
#include "topic_discoverer.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QCoreApplication>
#include <DDS/QosProfile/DDS_DefaultQos.h>
BuiltinAnyListener::BuiltinAnyListener(QObject *parent)
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("TopicDiscoverer.BuiltinAnyListener"))
{
Q_UNUSED(parent)
}
dds::core::xtypes::StructType BuiltinAnyListener::structType(const std::string &typeName)
{
QReadLocker l(&m_safeTypeLock);
return m_structTypes.value(typeName, dds::core::xtypes::StructType("NULL"));
}
// This gets called when a participant has been discovered
template <typename S>
void BuiltinAnyListener::on_data_available(dds::sub::DataReader<S> &reader)
{
// We only process newly seen participants
dds::sub::LoanedSamples<S> samples
= reader.select().state(dds::sub::status::DataState::new_instance()).take();
for (typename dds::sub::LoanedSamples<S>::iterator sampleIt = samples.begin();
sampleIt != samples.end();
++sampleIt)
{
if (!sampleIt->info().valid())
continue;
const std::string &topicName = sampleIt->data().topic_name();
const std::string &typeName = sampleIt->data().type_name();
if (QString::fromStdString(typeName).contains(QLatin1String("rti::"), Qt::CaseInsensitive))
continue;
dds::core::optional<dds::core::xtypes::DynamicType> dynamicType = sampleIt->data()->type();
if (!dynamicType.is_set() || dynamicType.get().kind() != dds::core::xtypes::TypeKind::STRUCTURE_TYPE)
continue;
const dds::core::xtypes::StructType &structType = static_cast<dds::core::xtypes::StructType&>(dynamicType.get());
DEBUG_LOG(m_logger) << "Built-in Reader: found subscriber: "
<< " topicName: " << topicName
<< " topicType: " << typeName
;
{
QWriteLocker l(&m_safeTypeLock);
m_structTypes.insert(typeName, structType);
}
emit topicDescription(topicName, typeName);
}
}
/***********************************************************************************************/
BuiltinPublicationListener::BuiltinPublicationListener(QObject *parent)
: BuiltinAnyListener(parent)
{
}
void BuiltinPublicationListener::on_data_available(dds::sub::DataReader<dds::topic::PublicationBuiltinTopicData> &reader)
{
BuiltinAnyListener::on_data_available(reader);
}
/***********************************************************************************************/
BuiltinSubscriberListener::BuiltinSubscriberListener(QObject *parent)
: BuiltinAnyListener(parent)
{
}
void BuiltinSubscriberListener::on_data_available(dds::sub::DataReader<dds::topic::SubscriptionBuiltinTopicData> &reader)
{
BuiltinAnyListener::on_data_available(reader);
}
/***********************************************************************************************/
TopicDiscoverer::TopicDiscoverer(int domainId, QObject *parent)
: QObject(parent)
, m_domainId(domainId)
, m_domainParticipant(nullptr)
, m_publisherListener(nullptr)
, m_subscriberListener(nullptr)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("TopicDiscoverer"))
{
qRegisterMetaType<std::string>("std::string");
}
void TopicDiscoverer::init(DDS::QosProfile::ConnectionType ct, const QUrl &tcpDiscoveryUrl)
{
// make sure to get the same qos as a normal dp/publisher/subscriber
DDS::QosProfile::setDefault();
// By default, the participant is enabled upon construction.
// At that time our listeners for the builtin topics have not
// been installed, so we disable the participant until we
// set up the listeners.
dds::domain::qos::DomainParticipantFactoryQos factoryQos =
dds::domain::DomainParticipant::participant_factory_qos();
factoryQos << dds::core::policy::EntityFactory::ManuallyEnable();
dds::domain::DomainParticipant::participant_factory_qos(factoryQos);
// Create a DomainParticipant with given Qos.
m_domainParticipant = dds::domain::DomainParticipant(m_domainId, DDS::QosProfile::domainParticipantDefault(ct, tcpDiscoveryUrl));
dds::domain::qos::DomainParticipantQos dpQos = m_domainParticipant.qos();
rti::core::policy::EntityName entityName;
entityName.name(QString(qAppName() +
QStringLiteral(" - DP ") +
QString::number(m_domainId)
).toStdString());
dpQos << entityName;
m_domainParticipant.qos(dpQos);
// Installing listeners for the builtin topics requires several steps
// First get the builtin subscriber.
dds::sub::Subscriber builtin_subscriber = dds::sub::builtin_subscriber(m_domainParticipant);
// Get builtin subscriber's datareader for publishers.
std::vector< dds::sub::DataReader<dds::topic::PublicationBuiltinTopicData> > publication_reader;
dds::sub::find< dds::sub::DataReader<dds::topic::PublicationBuiltinTopicData> >
(
builtin_subscriber,
dds::topic::publication_topic_name(),
std::back_inserter(publication_reader)
);
BuiltinPublicationListener *bipl = new BuiltinPublicationListener(this);
// Install our listener using ListenerBinder.
m_publisherListener = rti::core::bind_and_manage_listener(publication_reader[0],
bipl,
dds::core::status::StatusMask::data_available()
);
connect(bipl, &BuiltinPublicationListener::topicDescription,
this, &TopicDiscoverer::onTopicDescription);
/*------------------------------*/
// Get builtin subscriber's datareader for subscribers.
std::vector< dds::sub::DataReader<dds::topic::SubscriptionBuiltinTopicData> > subscription_reader;
dds::sub::find< dds::sub::DataReader<dds::topic::SubscriptionBuiltinTopicData> >
(
builtin_subscriber,
dds::topic::subscription_topic_name(),
std::back_inserter(subscription_reader)
);
BuiltinSubscriberListener *bisl = new BuiltinSubscriberListener(this);
// Install our listener using ListenerBinder.
m_subscriberListener = rti::core::bind_and_manage_listener(subscription_reader[0],
bisl,
dds::core::status::StatusMask::data_available()
);
connect(bisl, &BuiltinSubscriberListener::topicDescription,
this, &TopicDiscoverer::onTopicDescription);
/*------------------------------*/
// Done! All the listeners are installed, so we can enable the
// participant now.
m_domainParticipant.enable();
}
void TopicDiscoverer::onTopicDescription(const std::string &topicName,
const std::string &typeName)
{
INFO_LOG(m_logger) << "Built-in Reader: found Topic: "
<< " topicName: " << topicName
<< " typeName: " << typeName
;
BuiltinAnyListener* bal = qobject_cast<BuiltinAnyListener*>(sender());
if (!bal)
return;
dds::core::xtypes::StructType type = bal->structType(typeName);
if (type.name() != "NULL")
emit topicDescription(topicName, typeName, type);
}
+106
View File
@@ -0,0 +1,106 @@
#pragma once
#include <dds/dds.hpp>
#include <QtCore/QObject>
#include <QtCore/QMap>
#include <QtCore/QReadWriteLock>
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <rti/core/ListenerBinder.hpp>
#ifndef TOPICDISCOVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define TOPICDISCOVER_EXPORT
# else
# if defined(MAKE_TOPICDISCOVER_LIB)
# define TOPICDISCOVER_EXPORT Q_DECL_EXPORT
# else
# define TOPICDISCOVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
namespace NGL {
class INGLLogger;
}
class BuiltinAnyListener
: public QObject
{
Q_OBJECT
public:
dds::core::xtypes::StructType structType(const std::string &typeName);
protected:
template <typename S>
void on_data_available(dds::sub::DataReader<S>& reader);
explicit BuiltinAnyListener(QObject *parent = nullptr);
virtual ~BuiltinAnyListener() = default;
signals:
void topicDescription(const std::string &topicName,
const std::string &typeName);
protected:
QMap<std::string, dds::core::xtypes::StructType> m_structTypes;
QReadWriteLock m_safeTypeLock;
NGL::INGLLogger &m_logger;
};
class BuiltinPublicationListener
: public BuiltinAnyListener
, public dds::sub::NoOpDataReaderListener<dds::topic::PublicationBuiltinTopicData>
{
Q_OBJECT
public:
explicit BuiltinPublicationListener(QObject *parent = nullptr);
virtual ~BuiltinPublicationListener() = default;
void on_data_available(dds::sub::DataReader<dds::topic::PublicationBuiltinTopicData> &reader) override final;
};
class BuiltinSubscriberListener
: public BuiltinAnyListener
, public dds::sub::NoOpDataReaderListener<dds::topic::SubscriptionBuiltinTopicData>
{
Q_OBJECT
public:
explicit BuiltinSubscriberListener(QObject *parent = nullptr);
virtual ~BuiltinSubscriberListener() = default;
void on_data_available(dds::sub::DataReader<dds::topic::SubscriptionBuiltinTopicData> &reader) override final;
};
class TOPICDISCOVER_EXPORT TopicDiscoverer
: public QObject
{
Q_OBJECT
public:
explicit TopicDiscoverer(int domainId, QObject *parent = nullptr);
virtual ~TopicDiscoverer() = default;
void init(DDS::QosProfile::ConnectionType ct, const QUrl &tcpDiscoveryUrl);
const dds::domain::DomainParticipant &getDomainParticipant() const { return m_domainParticipant; }
signals:
void topicDescription(const std::string &topicName,
const std::string &typeName,
const dds::core::xtypes::StructType &type);
private slots:
void onTopicDescription(const std::string &topicName,
const std::string &typeName);
private:
int m_domainId;
dds::domain::DomainParticipant m_domainParticipant;
rti::core::ListenerBinder< dds::sub::DataReader<dds::topic::PublicationBuiltinTopicData> > m_publisherListener;
rti::core::ListenerBinder< dds::sub::DataReader<dds::topic::SubscriptionBuiltinTopicData> > m_subscriberListener;
NGL::INGLLogger &m_logger;
};