Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Write all incoming / outgoing telegrams to a directory (xdr encoded)
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(XDR_QtHandler)
|
||||
|
||||
SET(SRCS
|
||||
directory_cleaner.cpp
|
||||
directory_cleaner.h
|
||||
directory_dispatcher.cpp
|
||||
directory_dispatcher.h
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
../TetraJson/convert_from_json.cpp
|
||||
../TetraJson/convert_from_json.h
|
||||
convert_to_json_file.cpp
|
||||
convert_to_json_file.h
|
||||
)
|
||||
NGL_ADD_LIBRARY(SV tabPluginDebugJsonDir MODULE ${SRCS})
|
||||
NGL_INSTALL_TARGET(tabPluginDebugJsonDir)
|
||||
NGL_TARGET_LINK_LIBRARIES(tabPluginDebugJsonDir
|
||||
tabPluginInterface
|
||||
tabTelegrams
|
||||
NGLLogger
|
||||
nglsettings
|
||||
Qt5::Core
|
||||
Qt5::WebSockets
|
||||
tabPluginInterface
|
||||
xdr_qthandler_dir
|
||||
)
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
SET(xdr_dh_SRCS
|
||||
XDR_DirHandler.cpp
|
||||
XDR_DirHandler_ifc.cpp
|
||||
)
|
||||
SET(xdr_dh_HDRS
|
||||
XDR_DirHandler.h
|
||||
XDR_DirHandler_ifc.h
|
||||
)
|
||||
IF(WIN32)
|
||||
LIST(APPEND xdr_dh_SRCS
|
||||
XDR_DirHandler_win.cpp
|
||||
)
|
||||
LIST(APPEND xdr_dh_HDRS
|
||||
XDR_DirHandler_win.h
|
||||
)
|
||||
ELSE(WIN32)
|
||||
LIST(APPEND xdr_dh_SRCS
|
||||
XDR_DirHandler_linux.cpp
|
||||
)
|
||||
LIST(APPEND xdr_dh_HDRS
|
||||
XDR_DirHandler_linux.h
|
||||
)
|
||||
ENDIF(WIN32)
|
||||
NGL_ADD_LIBRARY(AAR SV xdr_qthandler_dir SHARED ${xdr_dh_SRCS} ${xdr_dh_HDRS})
|
||||
NGL_TARGET_LINK_LIBRARIES(xdr_qthandler_dir
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
NGL_INSTALL_TARGET(xdr_qthandler_dir)
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Scan directory for new XDR files
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "XDR_DirHandler.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "XDR_DirHandler_win.h"
|
||||
#else
|
||||
#include "XDR_DirHandler_linux.h"
|
||||
#endif
|
||||
|
||||
XDR_DirHandler::XDR_DirHandler(const QString &dirToWatch, bool startWatching, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_workerThread(new QThread)
|
||||
, m_workerObject(nullptr)
|
||||
, m_startWatching(startWatching)
|
||||
, m_dirToWatch(dirToWatch)
|
||||
{
|
||||
#ifdef WIN32
|
||||
m_workerObject = new XDR_DirHandlerWin(dirToWatch);
|
||||
#else
|
||||
m_workerObject = new XDR_DirHandlerLinux(dirToWatch);
|
||||
#endif
|
||||
m_workerThread->start();
|
||||
m_workerObject->moveToThread(m_workerThread);
|
||||
connect(m_workerObject, &XDR_DirHandlerIfc::newTelegramArrived,
|
||||
this, &XDR_DirHandler::newTelegramArrived);
|
||||
connect(m_workerThread, &QThread::finished,
|
||||
m_workerObject, &XDR_DirHandlerIfc::deleteLater);
|
||||
if (startWatching)
|
||||
QTimer::singleShot(0, m_workerObject, &XDR_DirHandlerIfc::startWatching);
|
||||
}
|
||||
|
||||
XDR_DirHandler::~XDR_DirHandler()
|
||||
{
|
||||
m_workerThread->requestInterruption();
|
||||
m_workerThread->quit();
|
||||
if (!m_workerThread->wait(10000))
|
||||
m_workerThread->terminate();
|
||||
delete m_workerThread;
|
||||
}
|
||||
|
||||
void XDR_DirHandler::startWatching()
|
||||
{
|
||||
if (!m_startWatching)
|
||||
{
|
||||
QTimer::singleShot(0, m_workerObject, &XDR_DirHandlerIfc::startWatching);
|
||||
m_startWatching = true;
|
||||
}
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Scan directory for new XDR files
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#ifndef XDR_QTHANDLER_DIR_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define XDR_QTHANDLER_DIR_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_XDR_QTHANDLER_DIR_LIB
|
||||
# define XDR_QTHANDLER_DIR_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define XDR_QTHANDLER_DIR_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
class XDR_DirHandlerIfc;
|
||||
class XDR_QTHANDLER_DIR_EXPORT XDR_DirHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XDR_DirHandler(const QString &dirToWatch, bool startWatching = true, QObject *parent = nullptr);
|
||||
~XDR_DirHandler();
|
||||
|
||||
void startWatching();
|
||||
QString dirToWatch() const { return m_dirToWatch; }
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void newTelegramArrived(const QString &fullPath) = 0;
|
||||
private:
|
||||
QThread *m_workerThread;
|
||||
XDR_DirHandlerIfc *m_workerObject;
|
||||
bool m_startWatching;
|
||||
QString m_dirToWatch;
|
||||
};
|
||||
|
||||
class XDR_QTHANDLER_DIR_EXPORT XDR_DirHandler_emit : public XDR_DirHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XDR_DirHandler_emit(const QString &dirToWatch, QObject *parent = nullptr)
|
||||
: XDR_DirHandler(dirToWatch, true, parent)
|
||||
{}
|
||||
~XDR_DirHandler_emit()
|
||||
{}
|
||||
protected:
|
||||
virtual void newTelegramArrived(const QString &fullPath)
|
||||
{
|
||||
emit newTelegram(fullPath);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void newTelegram(const QString &fullPath);
|
||||
};
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - internal interfacefor OS abstraction
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "XDR_DirHandler_ifc.h"
|
||||
|
||||
XDR_DirHandlerIfc::XDR_DirHandlerIfc(const QString &dirToWatch, QObject *parent)
|
||||
: QObject(parent)
|
||||
, mDirToWatchBA(dirToWatch.toLocal8Bit())
|
||||
, mDirToWatch(dirToWatch)
|
||||
{
|
||||
if (!mDirToWatch.endsWith(QLatin1Char('/')))
|
||||
mDirToWatch += QLatin1Char('/');
|
||||
if (!mDirToWatchBA.endsWith('/'))
|
||||
mDirToWatchBA += '/';
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - internal interfacefor OS abstraction
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
class XDR_DirHandlerIfc : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XDR_DirHandlerIfc(const QString &dirToWatch, QObject *parent = nullptr);
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void startWatching() = 0;
|
||||
Q_SIGNALS:
|
||||
void newTelegramArrived(const QString &fullPath);
|
||||
protected:
|
||||
QByteArray mDirToWatchBA;
|
||||
QString mDirToWatch;
|
||||
};
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - windows specific implementation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "XDR_DirHandler_linux.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QVarLengthArray>
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void XDR_DirHandlerLinux::startWatching()
|
||||
{
|
||||
onScanDirectory();
|
||||
startEPoll();
|
||||
}
|
||||
|
||||
void XDR_DirHandlerLinux::onScanDirectory()
|
||||
{
|
||||
QByteArray nameBA;
|
||||
nameBA.reserve(128);
|
||||
|
||||
QVarLengthArray<char, 512> tmpFilename;
|
||||
const int tmpFilenameOffset = mDirToWatchBA.size();
|
||||
tmpFilename.clear();
|
||||
tmpFilename.append(mDirToWatchBA.data(), mDirToWatchBA.size());
|
||||
|
||||
// Verzeichnis oeffnen
|
||||
DIR *dirp = opendir(mDirToWatchBA.constData());
|
||||
|
||||
if(!dirp)
|
||||
return;
|
||||
|
||||
// Schleife ueber alle Files
|
||||
dirent* entry;
|
||||
while ((entry = readdir(dirp)) != nullptr) {
|
||||
const char *name = entry->d_name;
|
||||
// skip directories
|
||||
size_t len = strlen(name);
|
||||
// skip "."
|
||||
if( len == 1 && name[0] == '.' )
|
||||
continue;
|
||||
// skip ".."
|
||||
if( len == 2 && name[0] == '.' && name[1] == '.' )
|
||||
continue;
|
||||
|
||||
if(len > 4) {
|
||||
size_t pos = len - 4;
|
||||
if( name[pos] == '.' &&
|
||||
tolower(name[pos+1]) == 't' &&
|
||||
tolower(name[pos+2]) == 'm' &&
|
||||
tolower(name[pos+3]) == 'p')
|
||||
continue;
|
||||
}
|
||||
|
||||
// ist es ein Verzeichnis?
|
||||
struct stat st;
|
||||
tmpFilename.resize(tmpFilenameOffset);
|
||||
tmpFilename.append(name, len);
|
||||
tmpFilename.append('\0');
|
||||
int res = stat(tmpFilename.constData(), &st);
|
||||
if (res || S_ISDIR(st.st_mode) ) {
|
||||
// Unterverzeichnis
|
||||
continue;
|
||||
}
|
||||
|
||||
// einfuegen
|
||||
nameBA.clear();
|
||||
nameBA.append(name, len);
|
||||
m_newFilesMap.insert(nameBA, 1);
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
// map is sorted by key, we don't care about value
|
||||
QMap<QByteArray, int>::ConstIterator it = m_newFilesMap.constBegin();
|
||||
QMap<QByteArray, int>::ConstIterator end = m_newFilesMap.constEnd();
|
||||
for( ; it != end; ++it)
|
||||
{
|
||||
emit newTelegramArrived(mDirToWatch + QString::fromLocal8Bit(it.key()));
|
||||
}
|
||||
QTimer::singleShot(5000, this, &XDR_DirHandlerLinux::clearNewFilesMap);
|
||||
}
|
||||
|
||||
void XDR_DirHandlerLinux::clearNewFilesMap()
|
||||
{
|
||||
m_newFilesMap.clear();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// fuer debug-Zwecke
|
||||
static void /* Display information from inotify_event structure */
|
||||
displayInotifyEvent(const inotify_event *i)
|
||||
{
|
||||
printf(" wd =%2d; ", i->wd);
|
||||
if (i->cookie > 0)
|
||||
printf("cookie =%4d; ", i->cookie);
|
||||
|
||||
printf("mask = ");
|
||||
if (i->mask & IN_ACCESS) printf("IN_ACCESS ");
|
||||
if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");
|
||||
if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
|
||||
if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");
|
||||
if (i->mask & IN_CREATE) printf("IN_CREATE ");
|
||||
if (i->mask & IN_DELETE) printf("IN_DELETE ");
|
||||
if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");
|
||||
if (i->mask & IN_IGNORED) printf("IN_IGNORED ");
|
||||
if (i->mask & IN_ISDIR) printf("IN_ISDIR ");
|
||||
if (i->mask & IN_MODIFY) printf("IN_MODIFY ");
|
||||
if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");
|
||||
if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");
|
||||
if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");
|
||||
if (i->mask & IN_OPEN) printf("IN_OPEN ");
|
||||
if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");
|
||||
if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");
|
||||
printf("\n");
|
||||
|
||||
if (i->len > 0)
|
||||
printf(" name = %s\n", i->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
void XDR_DirHandlerLinux::startEPoll()
|
||||
{
|
||||
int inotifyFd = inotify_init();
|
||||
if (inotifyFd != -1) {
|
||||
// Entweder wenn foo.tmp nach foo verschoben wird oder
|
||||
// wenn eine Datei geschlossen wird (inklusive Schreibvorgang vorher)
|
||||
// d.h. wir würden das umbenennen von foo.tmp nach foo gar nicht mehr benoetigen
|
||||
int wd = inotify_add_watch(inotifyFd, mDirToWatchBA.constData(), IN_MOVED_TO|IN_CLOSE_WRITE);
|
||||
if (wd != -1) {
|
||||
Q_FOREVER {
|
||||
if (QThread::currentThread()->isInterruptionRequested())
|
||||
break;
|
||||
struct pollfd fds[1];
|
||||
memset(fds, 0, sizeof(fds));
|
||||
fds[0].fd = inotifyFd;
|
||||
fds[0].events = POLLIN | POLLPRI;
|
||||
constexpr int timeout_msecs = 5;
|
||||
int ret = poll(fds, 1, timeout_msecs);
|
||||
if (ret > 0) {
|
||||
static const int BUF_LEN = (10 * (sizeof(struct inotify_event) + NAME_MAX + 1));
|
||||
char buf[BUF_LEN] __attribute__ ((aligned(8)));
|
||||
int numRead = read(inotifyFd, buf, BUF_LEN);
|
||||
if(numRead <= 0)
|
||||
break;
|
||||
|
||||
for (const char *p = buf; p < buf + numRead; ) {
|
||||
const inotify_event *event = reinterpret_cast<const inotify_event *>(p);
|
||||
//displayInotifyEvent(event);
|
||||
handleInotifyEvents(event);
|
||||
|
||||
p += sizeof(struct inotify_event) + event->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(wd);
|
||||
}
|
||||
close(inotifyFd);
|
||||
}
|
||||
}
|
||||
|
||||
void XDR_DirHandlerLinux::handleInotifyEvents(const inotify_event *entry)
|
||||
{
|
||||
// wir gehen davon aus, dass wir nur IN_CLOSE_WRITE und IN_MOVED_TO
|
||||
// bekommen so wie wir es auch aboniert haben.
|
||||
|
||||
// skip directories
|
||||
if((entry->mask & IN_ISDIR) == IN_ISDIR)
|
||||
return;
|
||||
|
||||
const char *name = entry->name;
|
||||
const size_t len = strlen(name); // entry->len contains the length including \0 and padding bytes!
|
||||
if (len > 4) {
|
||||
size_t pos = len - 4;
|
||||
if( name[pos] == '.' &&
|
||||
tolower(name[pos+1]) == 't' &&
|
||||
tolower(name[pos+2]) == 'm' &&
|
||||
tolower(name[pos+3]) == 'p') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_newFilesMap.isEmpty()) {
|
||||
if (m_newFilesMap.contains(QByteArray::fromRawData(name, len)))
|
||||
return;
|
||||
}
|
||||
|
||||
emit newTelegramArrived(mDirToWatch + QString::fromLocal8Bit(name));
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - windows specific implementation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "XDR_DirHandler_ifc.h"
|
||||
#include <QMap>
|
||||
|
||||
struct inotify_event;
|
||||
|
||||
class XDR_DirHandlerLinux final : public XDR_DirHandlerIfc
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using XDR_DirHandlerIfc::XDR_DirHandlerIfc;
|
||||
private Q_SLOTS:
|
||||
void onScanDirectory();
|
||||
void startWatching();
|
||||
void startEPoll();
|
||||
void clearNewFilesMap();
|
||||
private:
|
||||
void handleInotifyEvents(const inotify_event *entry);
|
||||
private:
|
||||
QMap<QByteArray, int> m_newFilesMap; // fuer initiales lesen
|
||||
};
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - windows specific implementation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "XDR_DirHandler_win.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVarLengthArray>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
void XDR_DirHandlerWin::startWatching()
|
||||
{
|
||||
onScanDirectory();
|
||||
}
|
||||
|
||||
void XDR_DirHandlerWin::onScanDirectory()
|
||||
{
|
||||
QString lastFilename = mLastFilename;
|
||||
QMap<QString, int> newFilesMap;
|
||||
|
||||
// Verzeichnis oeffnen
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE dirp = FindFirstFile(reinterpret_cast<LPCWSTR>(mDirToWatch.utf16()), &findData);
|
||||
|
||||
while(dirp != INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
// Schleife ueber alle Files
|
||||
do {
|
||||
// skip directories
|
||||
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (FindNextFile(dirp, &findData) == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
const TCHAR *name = findData.cFileName;
|
||||
const size_t len = wcslen(name);
|
||||
if(len > 4) {
|
||||
size_t pos = len - 4;
|
||||
if( name[pos] == '.' &&
|
||||
_totlower(name[pos+1]) == 't' &&
|
||||
_totlower(name[pos+2]) == 'm' &&
|
||||
_totlower(name[pos+3]) == 'p')
|
||||
continue;
|
||||
}
|
||||
|
||||
// hatten wir schon ?
|
||||
const QString nameStr = QString::fromUtf16(reinterpret_cast<const ushort*>(name), len);
|
||||
if ( mLastFilename.size() && nameStr <= mLastFilename )
|
||||
continue;
|
||||
if (nameStr > lastFilename)
|
||||
lastFilename = nameStr;
|
||||
|
||||
// einfuegen
|
||||
newFilesMap.insert(nameStr, 1);
|
||||
} while (FindNextFile(dirp, &findData) != 0);
|
||||
FindClose(dirp);
|
||||
mLastFilename = lastFilename;
|
||||
|
||||
// map is sorted by key, we don't care about value
|
||||
QMap<QString, int>::ConstIterator it = newFilesMap.constBegin();
|
||||
QMap<QString, int>::ConstIterator end = newFilesMap.constEnd();
|
||||
for( ; it != end; ++it)
|
||||
emit newTelegramArrived(mDirToWatch + it.key());
|
||||
|
||||
// Alle 200 msec lesen
|
||||
QTimer::singleShot(200, this, &XDR_DirHandlerWin::onScanDirectory);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Scan directory for new XDR files - windows specific implementation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "XDR_DirHandler_ifc.h"
|
||||
|
||||
class XDR_DirHandlerWin : public XDR_DirHandlerIfc
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using XDR_DirHandlerIfc::XDR_DirHandlerIfc;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onScanDirectory();
|
||||
void startWatching();
|
||||
private:
|
||||
QString mLastFilename;
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Export definitions
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef XDR_QTHANDLER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define XDR_QTHANDLER_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_XDR_QTHANDLER_LIB)
|
||||
# define XDR_QTHANDLER_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define XDR_QTHANDLER_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* Write XDR telegrams to a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "convert_to_json_file.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QFile>
|
||||
#include <QDateTime>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace TetraRadio
|
||||
{
|
||||
ConvertToJsonFile::ConvertToJsonFile(const QString &txDir)
|
||||
: SendToTab()
|
||||
, m_bRetvalOnError(false)
|
||||
, m_txDir(txDir + QLatin1Char('/'))
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("TAB.Plugin.ConvertToJsonFile"))
|
||||
{
|
||||
resetSendCounter();
|
||||
}
|
||||
|
||||
TrainingAreaBase::SendToTab::HandleState ConvertToJsonFile::canHandleTelegram(int equipmentNumber, int telegramId) const
|
||||
{
|
||||
Q_UNUSED(equipmentNumber)
|
||||
Q_UNUSED(telegramId)
|
||||
return HandleState::Debug;
|
||||
}
|
||||
|
||||
void ConvertToJsonFile::resetSendCounter()
|
||||
{}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::Acknowledge &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DemandBite &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::Init &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::SetVulnerabilityModel &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DemandEquipmentConfigurationReport &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::LanguageSelection &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::EquipmentMessage &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::EquipmentMessageOC &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateSingleExplosion &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateAreaExplosion &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateMineArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::MineAreaSingleMineState &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateNContamination &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateCContamination &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DeactivateEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ModifyAreaEffectSimulationName &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::PauseEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ResumeEffectSimulation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::MineTriggered &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DusMineReactivation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateFunctionalArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CreateDusSingleMine &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExerciseEnvironmentData &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExerciseStateData &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ParticipantSwVersionsRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::OpaquePayloadDataOut &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::TechnicalArea &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CesHitInformation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ParticipantMode &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DemandParticipantMode &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::DemandParticipantConfiguration &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::Sanitation &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::SelectiveReammunition &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::SetDevicePowerRequest &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::OcCommand &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::UAVChangeState &data)
|
||||
{
|
||||
return sendToTx(&data);
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExFireReadiness &data)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExFiredReport &data)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConvertToJsonFile::txData(const TrainingAreaBase::TetraIcd::ExConfirmationReport &data)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ConvertToJsonFile::sendToTx(const T *data)
|
||||
{
|
||||
const QString fileName = m_txDir + QString::number(QDateTime::currentMSecsSinceEpoch());
|
||||
QFile f(fileName);
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
return m_bRetvalOnError;
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("data")] = data->toJson();
|
||||
obj[QStringLiteral("type")] = TrainingAreaBase::TetraIcd::Constraints<T>::type();
|
||||
obj[QStringLiteral("typeId")] = data->id();
|
||||
const QByteArray ba = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
f.write(ba);
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Write XDR telegrams to a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-04-14
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include <TrainingAreaBase/send_to_tab.h>
|
||||
|
||||
namespace TetraRadio
|
||||
{
|
||||
class ConvertToJsonFile : public TrainingAreaBase::SendToTab
|
||||
{
|
||||
public:
|
||||
explicit ConvertToJsonFile(const QString &txDir);
|
||||
|
||||
const char *name() const override { return "ConvertToJsonFile"; }
|
||||
HandleState canHandleTelegram(int equipmentNumber, int telegramId) const override;
|
||||
void resetSendCounter() override;
|
||||
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::OcCommand &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::UAVChangeState &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::ExFireReadiness &data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::ExFiredReport&data) override;
|
||||
bool txData(const TrainingAreaBase::TetraIcd::ExConfirmationReport &data) override;
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
bool sendToTx(const T *data);
|
||||
protected:
|
||||
bool m_bRetvalOnError;
|
||||
QString m_txDir;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Helper class to remove outdated telegram files in a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "directory_cleaner.h"
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <TrainingAreaBase/training_area_telegrams.h>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <ctime>
|
||||
|
||||
namespace TetraRadio
|
||||
{
|
||||
|
||||
//
|
||||
// DirectoryCleaner
|
||||
//
|
||||
DirectoryCleaner::DirectoryCleaner(const QString &directory, unsigned int maxAgeSec, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_cleanerThread(new QThread(this))
|
||||
, m_worker(new DirectoryCleanerWorker(directory, maxAgeSec))
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("TAB.Plugin.DirectoryCleaner"))
|
||||
{
|
||||
QDir().mkpath(directory);
|
||||
doInitialCleanup(directory);
|
||||
m_worker->moveToThread(m_cleanerThread);
|
||||
m_cleanerThread->start();
|
||||
QTimer::singleShot(0, m_worker, &DirectoryCleanerWorker::onTimeout);
|
||||
}
|
||||
|
||||
DirectoryCleaner::~DirectoryCleaner()
|
||||
{
|
||||
m_cleanerThread->quit();
|
||||
m_cleanerThread->wait();
|
||||
delete m_worker;
|
||||
}
|
||||
|
||||
void DirectoryCleaner::doInitialCleanup(const QString &directory)
|
||||
{
|
||||
QDir d(directory);
|
||||
if (!d.exists())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Directory " << directory
|
||||
<< " does not exist - can not cleanup directory";
|
||||
return;
|
||||
}
|
||||
QDirIterator it(d.absolutePath(), QDir::Files | QDir::NoDotAndDotDot);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
QFile f(it.filePath());
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
continue;
|
||||
const QByteArray ba = f.readAll();
|
||||
const QJsonObject obj = QJsonDocument::fromJson(ba).object();
|
||||
const int teleId = obj[QStringLiteral("typeId")].toInt();
|
||||
if (teleShouldBeRemoved(teleId))
|
||||
QFile::remove(it.filePath());
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryCleaner::teleShouldBeRemoved(int teleId)
|
||||
{
|
||||
switch (teleId)
|
||||
{
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_EINZELGESCHOSS:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_FLAECHENDECKENDES_FEUER:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_FLAECHENDECKENDES_FEUER_STOP:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_MINENSPERRE:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_STATUS_MINENSPERRE:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_AENDERUNG_BEZEICHNER:
|
||||
case TrainingAreaBase::TetraIcd::REAKTIVIERUNG_DUS_MINE:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_A_KAMPFMITTEL:
|
||||
case TrainingAreaBase::TetraIcd::WIRKFELD_C_KAMPFMITTEL:
|
||||
case TrainingAreaBase::TetraIcd::DEAKTIVIERUNG_WIRKFELD:
|
||||
case TrainingAreaBase::TetraIcd::DEAKTIVIERUNG_EINZELMINE:
|
||||
case TrainingAreaBase::TetraIcd::FUNKTIONSRAUM:
|
||||
case TrainingAreaBase::TetraIcd::DEAKTIVIEREN_FUNKTIONSRAUM:
|
||||
case TrainingAreaBase::TetraIcd::BETRIEBSZUSTANDSMELDUNG:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DirectoryCleanerWorker
|
||||
//
|
||||
DirectoryCleanerWorker::DirectoryCleanerWorker(const QString &directory, unsigned int maxAgeSec)
|
||||
: m_directory(directory)
|
||||
, m_maxAgeSec(maxAgeSec)
|
||||
, m_bWarnedOnce(false)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("TRA.Plugin.DirectoryCleaner"))
|
||||
{}
|
||||
|
||||
void DirectoryCleanerWorker::onTimeout()
|
||||
{
|
||||
doCleanup();
|
||||
// search every 5sec
|
||||
QTimer::singleShot(5000, Qt::VeryCoarseTimer, this, &DirectoryCleanerWorker::onTimeout);
|
||||
}
|
||||
|
||||
void DirectoryCleanerWorker::doCleanup()
|
||||
{
|
||||
QDir d(m_directory);
|
||||
if (!d.exists())
|
||||
{
|
||||
if (!m_bWarnedOnce)
|
||||
WARNING_LOG(m_logger) << "Directory " << m_directory
|
||||
<< " does not exist - can not cleanup directory";
|
||||
m_bWarnedOnce = true;
|
||||
return;
|
||||
}
|
||||
m_bWarnedOnce = false;
|
||||
const qint64 tRemoveTimeMSec = (time(nullptr) - m_maxAgeSec) * 1000;
|
||||
QDirIterator it(d.absolutePath(), QDir::Files | QDir::NoDotAndDotDot);
|
||||
while (it.hasNext())
|
||||
{
|
||||
const QString filepath(it.next());
|
||||
const QString filename(it.fileName());
|
||||
bool bOk = false;
|
||||
qint64 timestampUSec = filename.toLongLong(&bOk);
|
||||
TRACE_LOG(m_logger) << "File: " << filename
|
||||
<< " timestamp: " << timestampUSec
|
||||
<< " remove time: " << tRemoveTimeMSec * 1000;
|
||||
if (!bOk)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Found file with name '" << filepath
|
||||
<< " which is not a valid xdr filename"
|
||||
<< " - removing this file when mtime older than "
|
||||
<< m_maxAgeSec << "seconds";
|
||||
qint64 modTime = it.fileInfo().lastModified().toMSecsSinceEpoch();
|
||||
if (modTime < tRemoveTimeMSec)
|
||||
QFile::remove(filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
const qint64 timestampMSec = timestampUSec / 1000; // usec -> msec
|
||||
if (timestampMSec < tRemoveTimeMSec)
|
||||
{
|
||||
if (!QFile::remove(filepath))
|
||||
WARNING_LOG(m_logger) << "Could not remove " << filepath;
|
||||
else
|
||||
TRACE_LOG(m_logger) << "Removed " << filepath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Helper class to remove outdated telegram files in a directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
class QThread;
|
||||
class XDR_Wrapper_it;
|
||||
namespace TetraRadio
|
||||
{
|
||||
class DirectoryCleanerWorker;
|
||||
class DirectoryCleaner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DirectoryCleaner(const QString &directory, unsigned int maxAgeSec, QObject *parent = nullptr);
|
||||
~DirectoryCleaner();
|
||||
private:
|
||||
// remove xdr telegrams which are regenerated on startup (e.g. AES telegrams)
|
||||
// and therefore must not be reread on startup
|
||||
void doInitialCleanup(const QString &directory);
|
||||
bool teleShouldBeRemoved(int teleId);
|
||||
QThread *m_cleanerThread;
|
||||
DirectoryCleanerWorker *m_worker;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
class DirectoryCleanerWorker: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DirectoryCleanerWorker(const QString &directory, unsigned int maxAgeSec);
|
||||
~DirectoryCleanerWorker() = default;
|
||||
public Q_SLOTS:
|
||||
void onTimeout();
|
||||
private:
|
||||
void doCleanup();
|
||||
private:
|
||||
QString m_directory;
|
||||
qint64 m_maxAgeSec;
|
||||
bool m_bWarnedOnce;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from TX/RX directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "directory_dispatcher.h"
|
||||
#include "convert_to_json_file.h"
|
||||
#include "directory_cleaner.h"
|
||||
#include <XDR_QtHandler/XDR_DirHandler.h>
|
||||
#include <QDir>
|
||||
|
||||
namespace TetraRadio
|
||||
{
|
||||
//
|
||||
// DirectoryDispatcher
|
||||
//
|
||||
DirectoryDispatcher::DirectoryDispatcher(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
const QString &txDir,
|
||||
const QString &rxDir)
|
||||
: TrainingAreaBase::Plugin::Interface()
|
||||
, ConvertFromJson(recvFromTabCb, "TAB.Plugin.DirectoryDispatcher")
|
||||
, m_xdrDirHandler(new XDR_DirHandler_emit(rxDir, this))
|
||||
, m_txCleaner(new DirectoryCleaner(txDir, 10 * 60, this))
|
||||
, m_txDir(txDir)
|
||||
, m_rxDir(rxDir)
|
||||
{
|
||||
QFileInfo fi(m_txDir);
|
||||
if (!fi.exists() || !fi.isDir())
|
||||
{
|
||||
QDir d;
|
||||
if (!d.mkpath(m_txDir))
|
||||
ERROR_LOG(m_logger) << "Can not create directory " << m_txDir;
|
||||
}
|
||||
fi = QFileInfo(m_rxDir);
|
||||
if (!fi.exists() || !fi.isDir())
|
||||
{
|
||||
QDir d;
|
||||
if (!d.mkpath(m_rxDir))
|
||||
ERROR_LOG(m_logger) << "Can not create directory " << m_rxDir;
|
||||
}
|
||||
|
||||
NOTICE_LOG(m_logger) << "Using RX dir: " << m_rxDir;
|
||||
NOTICE_LOG(m_logger) << "Using TX dir: " << m_txDir;
|
||||
connect(m_xdrDirHandler, &XDR_DirHandler_emit::newTelegram,
|
||||
this, &DirectoryDispatcher::newTelegramArrived);
|
||||
}
|
||||
|
||||
DirectoryDispatcher::~DirectoryDispatcher()
|
||||
{
|
||||
delete m_xdrDirHandler;
|
||||
}
|
||||
|
||||
|
||||
bool DirectoryDispatcher::init()
|
||||
{
|
||||
m_tx = std::make_shared<ConvertToJsonFile>(m_txDir);
|
||||
m_xdrDirHandler->startWatching();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> DirectoryDispatcher::sendToTab()
|
||||
{
|
||||
return m_tx;
|
||||
}
|
||||
|
||||
void DirectoryDispatcher::newTelegramArrived(const QString &fullPath)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got new telegram: "
|
||||
<< fullPath;
|
||||
QFile f(fullPath);
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
const QByteArray tele = f.readAll();
|
||||
f.close();
|
||||
int recvCounterUnused;
|
||||
handleTelegram(tele, recvCounterUnused);
|
||||
}
|
||||
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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>
|
||||
#include <DDS/Core/function_reply_object.h>
|
||||
#include "../TetraJson/convert_from_json.h"
|
||||
#include "convert_to_json_file.h"
|
||||
|
||||
class XDR_DirHandler_emit;
|
||||
namespace TetraRadio
|
||||
{
|
||||
|
||||
class DirectoryCleaner;
|
||||
class DirectoryDispatcher final : public TrainingAreaBase::Plugin::Interface,
|
||||
protected ConvertFromJson
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DirectoryDispatcher(const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
const QString &txDir,
|
||||
const QString &rxDir);
|
||||
~DirectoryDispatcher();
|
||||
|
||||
bool init() override;
|
||||
std::shared_ptr<TrainingAreaBase::SendToTab> sendToTab() override;
|
||||
bool isDebugInterface() const override { return true; }
|
||||
bool canSendData() const override { return true; }
|
||||
void exerciseChanged() override { return; }
|
||||
const char *name() const override { return tr_lts("dds", "Debug Directory XDR Dispatcher"); }
|
||||
|
||||
void handleAcknowledge(qint64, int) override {}
|
||||
void handleTetraConnectionChanged(bool) override {}
|
||||
|
||||
private Q_SLOTS:
|
||||
void newTelegramArrived(const QString &fullPath);
|
||||
private:
|
||||
std::shared_ptr<ConvertToJsonFile> m_tx;
|
||||
std::shared_ptr<TrainingAreaBase::RecvFromTab> m_rx;
|
||||
|
||||
XDR_DirHandler_emit *m_xdrDirHandler;
|
||||
DirectoryCleaner *m_txCleaner;
|
||||
QString m_txDir;
|
||||
QString m_rxDir;
|
||||
};
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Send / Receive telegrams to/from TX/RX directory
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "directory_dispatcher.h"
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
|
||||
namespace TetraRadio
|
||||
{
|
||||
|
||||
//
|
||||
// DebugJsonDirPlugin
|
||||
//
|
||||
std::shared_ptr<TrainingAreaBase::Plugin::Interface> DebugJsonDirPlugin::createInterface(TrainingAreaBase::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb,
|
||||
const std::shared_ptr<TrainingAreaBase::TxMixin> &,
|
||||
const std::shared_ptr<TrainingAreaBase::DdsHandler> &,
|
||||
NGL::Settings *settings)
|
||||
{
|
||||
const QString dir = QStringLiteral("/ex_%1_json/").arg(pdp->exerciseId());
|
||||
return std::make_shared<DirectoryDispatcher>(recvFromTabCb,
|
||||
settings->zsks_txPath() + dir,
|
||||
settings->zsks_rxPath() + dir);
|
||||
}
|
||||
} // namespace TetraRadio
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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 TetraRadio
|
||||
{
|
||||
class DebugJsonDirPlugin : public QObject, public TrainingAreaBase::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:tab.jsondir")
|
||||
Q_INTERFACES(TrainingAreaBase::Plugin::Plugin)
|
||||
public:
|
||||
DebugJsonDirPlugin() = default;
|
||||
~DebugJsonDirPlugin() = 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,
|
||||
const std::shared_ptr<TrainingAreaBase::DdsHandler> &ddsHandler,
|
||||
NGL::Settings *settings) override;
|
||||
};
|
||||
|
||||
} // namespace TetraRadio
|
||||
Reference in new issue
Block a user