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

+54
View File
@@ -0,0 +1,54 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by hjl, SLSE, 2016-06-22
#
SET(xml_FILE vom_service.xml)
# --- Executable svcVideoOverlayManagement (sVOM) -------------------------------------------------
#
SET(SRCS_exe
avs_interface.cpp
avs_interface.h
dds_handler.cpp
dds_handler.h
handler_participant_data.cpp
handler_participant_data.h
handler_infrastructure_data.cpp
handler_infrastructure_data.h
handler_overlays.cpp
handler_overlays.h
logger.cpp
logger.h
main.cpp
main_handler.cpp
main_handler.h
settings.cpp
settings.h
)
# make sure xml file is properly installed
CODEGEN_HANDLE_SVC_XML(SRCS_exe ${xml_FILE})
NGL_ADD_SVC_ICON(SRCS_exe)
NGL_ADD_EXECUTABLE(AAR SV svcVideoOverlayManagement ${SRCS_exe})
NGL_TARGET_LINK_LIBRARIES(svcVideoOverlayManagement
Qt5::Core
Qt5::Network
ddsconnector
ddsQoS
svcCoreClient
svcIsmClient
svcPpmClient
nglsettings
LtsCommandLineParser
NGLLogger
nglcoreapplication
ddscore
ngltools
)
NGL_INSTALL_TARGET(svcVideoOverlayManagement)
NGL_INSTALL(AAR SV FILES log4cxx_vom.props DESTINATION bin)
NGL_ADD_TARGET_LINK(svcVideoOverlayManagement sVOM)
+263
View File
@@ -0,0 +1,263 @@
/**
* AVS-Interface for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-24
*/
#include "avs_interface.h"
#include "settings.h"
#include <QTcpSocket>
#include <QTimer>
#include <QHostInfo>
#include <ngltools/ngltools_convert.h>
namespace VideoOverlayManagement
{
AvsInterface::AvsInterface(bool enableTryReconnect, QObject *parent)
: QObject(parent)
, m_waitTime(1)
, m_enableTryReconnect(enableTryReconnect)
, m_tryReconnect(false)
, m_avsKeepAliveTimer(new QTimer(this))
, m_keepAliveTime(Settings::getAvsKeepAliveTime())
, m_avsIfConnectionState(AvsIfConnectionState::Undefined)
, m_socket(nullptr)
, m_logger(getLogger("AVS_Interface"))
{
doConnect();
connect(m_avsKeepAliveTimer, &QTimer::timeout,
this, &AvsInterface::onAvsKeepAliveTimeout);
} // end of ctor()
//-----------------------------------------------------------------------------
AvsInterface::~AvsInterface()
{
if (m_socket)
m_socket->close();
delete m_socket;
} // end of dtor()
//-----------------------------------------------------------------------------
void AvsInterface::doConnect()
{
DEBUG_LOG(m_logger) << "doConnect TCP-Socket ";
if (m_socket)
m_socket->deleteLater();
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected,
this, &AvsInterface::onConnected);
connect(m_socket, &QTcpSocket::disconnected,
this, &AvsInterface::onDisonnected);
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
this, &AvsInterface::onError);
connect(m_socket, &QTcpSocket::readyRead,
this, &AvsInterface::onReadyRead);
if (m_tryReconnect)
{
INFO_LOG(m_logger) << "Try reconnect to host: " << m_hostName
<< " port: " << m_hostPort
<< " ip-address: " << m_ipAddressDNS;
m_socket->connectToHost(m_hostName, m_hostPort);
}
} // end of doConnect()
//-----------------------------------------------------------------------------
void AvsInterface::start(const QString &hostName, quint16 port)
{
QHostInfo hostInfo = QHostInfo::fromName(hostName);
const QList<QHostAddress> ipList = hostInfo.addresses();
if (ipList.isEmpty())
{
ERROR_LOG(m_logger) << "Non ip-address found for hostname: " << hostName;
m_ipAddressDNS.clear();
}
else
{
INFO_LOG(m_logger) << "Try connect to AVS: " << hostName
<< " port: " << port
<< " ip-address: " << ipList.at(0).toString();
m_ipAddressDNS = ipList.at(0).toString();
}
m_hostName = hostName;
m_hostPort = port;
m_socket->connectToHost(m_hostName, m_hostPort);
} // end of start()
//-----------------------------------------------------------------------------
void AvsInterface::onConnected()
{
INFO_LOG(m_logger) << "Connected to "
<< m_socket->peerAddress().toString()
<< ":" << m_socket->peerPort();
m_waitTime = 1;
m_buffer.clear();
m_avsIfConnectionState = AvsIfConnectionState::Connected;
emit avsIfConnectionState(AvsIfConnectionState::Connected);
m_avsKeepAliveTimer->start(m_keepAliveTime);
} // end of onConnected()
//-----------------------------------------------------------------------------
void AvsInterface::onDisonnected()
{
INFO_LOG(m_logger) << "Disconnected from " << m_socket->peerAddress().toString()
<< ":" << m_socket->peerPort();
m_avsKeepAliveTimer->stop();
m_avsIfConnectionState = AvsIfConnectionState::Disconnected;
emit avsIfConnectionState(AvsIfConnectionState::Disconnected);
} // end of onDisonnected()
//-----------------------------------------------------------------------------
void AvsInterface::onError(QAbstractSocket::SocketError err)
{
if (m_enableTryReconnect)
{
ERROR_LOG(m_logger) << "Socket error: " << err
<< " \"" << m_socket->errorString() << "\""
<< " Hostname: " << m_hostName
<< " Port:" << m_hostPort
<< " ip-Address:" << m_ipAddressDNS
<< " - trying to reconnect in " << m_waitTime << " seconds";
}
else
{
ERROR_LOG(m_logger) << "Socket error: " << err
<< " \"" << m_socket->errorString() << "\""
<< " Hostname: " << m_hostName
<< " Port:" << m_hostPort
<< " ip-Address:" << m_ipAddressDNS;
}
m_socket->disconnectFromHost();
m_avsKeepAliveTimer->stop();
m_avsIfConnectionState = AvsIfConnectionState::ConnectionError;
emit avsIfConnectionState(AvsIfConnectionState::ConnectionError);
// try reconnects ....
if (m_enableTryReconnect)
tryReconnect();
} // end of onError()
//-----------------------------------------------------------------------------
void AvsInterface::tryReconnect()
{
m_tryReconnect = true;
m_avsIfConnectionState = AvsIfConnectionState::TryReconnect;
emit avsIfConnectionState(AvsIfConnectionState::TryReconnect);
if (m_socket->state() != QAbstractSocket::UnconnectedState)
m_socket->waitForDisconnected();
m_waitTime += 2;
if (m_waitTime > 120)
m_waitTime = 120;
QTimer::singleShot(m_waitTime * 1000, this, &AvsInterface::doConnect);
} // end of tryReconnect()
//-----------------------------------------------------------------------------
void AvsInterface::onReadyRead()
{
while (m_socket->canReadLine())
{
const QByteArray data = m_socket->readLine().trimmed();
if (data.isEmpty())
continue;
INFO_LOG(m_logger) << "Incoming RCP_AVA: '" << data << "'";
int cmdNr = -1;
bool bOk = false;
const QVector<QByteArray> cmdList = NGL::parseFromTelnet(data);
if (cmdList.size() > 1)
cmdNr = cmdList.at(0).toInt(&bOk);
if (bOk)
{
// Fuer VOM sind nur diese 4 Command relavant
switch (cmdNr)
{
case int(AvsCmdState::Ok):
emit avsCmdState(AvsCmdState::Ok);
break;
case int(AvsCmdState::KeepAlive):
emit avsCmdState(AvsCmdState::KeepAlive);
m_avsKeepAliveTimer->start(m_keepAliveTime);
break;
case int(AvsCmdState::BadArguments):
emit avsCmdState(AvsCmdState::BadArguments);
break;
case int(AvsCmdState::CommandNotStateValid):
emit avsCmdState(AvsCmdState::CommandNotStateValid);
break;
default:
break;
}
}
} // while
} // end of onReadyRead()
//-----------------------------------------------------------------------------
void AvsInterface::onAvsKeepAliveTimeout()
{
emit avsKeepAliveTimeout();
// try reconnects ....
if (m_enableTryReconnect)
{
m_socket->disconnectFromHost();
m_avsKeepAliveTimer->stop();
if (m_socket->state() != QAbstractSocket::UnconnectedState)
m_socket->waitForDisconnected();
tryReconnect();
}
} // end of onAvsKeepAliveTimeout()
//-----------------------------------------------------------------------------
bool AvsInterface::sendCommand(const QByteArray &qba)
{
bool bOk = true;
INFO_LOG(m_logger) << "Send command: " << qba.trimmed();
if (m_socket->state() != QTcpSocket::ConnectedState)
{
ERROR_LOG(m_logger) << "sendCommand()"
<< " '" << qba.trimmed()
<< "' No socket connection established.";
return false;
}
int trxBytes = m_socket->write(qba);
if (trxBytes != qba.size())
{
bOk = false;
ERROR_LOG(m_logger) << "Insufficient number of tansfered bytes."
<< " Soll: " << trxBytes << " Ist: " << qba.size();
}
m_socket->flush();
return bOk;
} // end of sendCommand()
//-----------------------------------------------------------------------------
} // namespace VideoOverlayManagement
+124
View File
@@ -0,0 +1,124 @@
/**
* AVS-Interface for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-24
*/
#pragma once
#include <QtCore/QObject>
#include <QtNetwork/QHostAddress>
#include "logger.h"
// Forwarddeclarations
class QTcpSocket;
class QTimer;
namespace VideoOverlayManagement
{
enum class AvsIfConnectionState
{
Undefined = 0,
Connected,
Disconnected,
TryReconnect,
ConnectionError,
};
enum class AvsCmdState
{
Ok = 200,
KeepAlive = 298,
BadArguments = 402,
CommandNotStateValid = 455
};
class AvsInterface
: public QObject
{
Q_OBJECT
public:
/**
* Constructor connect to plugboard
* @param[in] enableTryReconnect if true, try reconnection
* @param[in] parent Pointer to parent qObject
*/
AvsInterface(bool enableTryReconnect, QObject *parent = nullptr);
~AvsInterface();
/**
* Connect to AVS RCP_AVA
* @param[in] hostName Hostname or Ip address to get access to AVS
* @param[in] port Ip port to get access to AVS
*/
void start(const QString &hostName, quint16 port);
AvsIfConnectionState getAvsIfState()
{
return m_avsIfConnectionState;
}
/**
* Send data to connected TcpSocket
* @param[in] qba Data to be transfered completed with "\r\n"
*/
bool sendCommand(const QByteArray &qba);
Q_SIGNALS:
/**
* Signals current AVS connection state
*/
void avsIfConnectionState(AvsIfConnectionState);
/**
* Signals current AVS command state
*/
void avsCmdState(AvsCmdState);
/**
* Signals an missing AVS keep-alive
* If the parameter 'enableTryReconnect' is set
* the connection attempting to restore automatically
*/
void avsKeepAliveTimeout();
/**
* Define the signal/slots connects uesd for TcpSocket
*/
protected Q_SLOTS:
void doConnect();
void onConnected();
void onDisonnected();
void onError(QAbstractSocket::SocketError);
void onReadyRead();
void onAvsKeepAliveTimeout();
private: // methode
void tryReconnect();
private: // attributes
QString m_hostName; ///< Hostname or Ip address to get access to AVS
QString m_ipAddressDNS; ///< DNS IP address of AVS
quint16 m_hostPort; ///< Ip port to get access to AVS
qint32 m_waitTime; ///< delay before try reconnection
bool m_enableTryReconnect; ///< if true, enables try reconnection
bool m_tryReconnect; ///< if true, try reconnection
QTimer *m_avsKeepAliveTimer; ///< AVS keep-alive timer
qint32 m_keepAliveTime; ///< AVS keep-alive time intervall in msec
AvsIfConnectionState m_avsIfConnectionState; ///< AVS Interface connection state
QTcpSocket *m_socket; ///< pointer to tcpsocket object
QByteArray m_buffer; ///< data buffer to hold incoming data form tcpsocket
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
};
} // namespace VideoOverlayManagement
+45
View File
@@ -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 VideoOverlayManagement
{
DdsHandler::DdsHandler(int domainId, int exerciseId)
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Exercise, exerciseId))
, 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 VideoOverlayManagement DDSHandler.";
if (!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
// Pacemaker
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
return true;
} // end of init()
//-----------------------------------------------------------------------------
} // Namespace VideoOverlayManagement
+45
View File
@@ -0,0 +1,45 @@
/**
* 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 VideoOverlayManagement
{
class DdsHandler final
{
public:
DdsHandler(int domainId, int exerciseId);
~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 VideoOverlayManagement
@@ -0,0 +1,162 @@
/**
* Handler for infrastructure data
* $Id$
* $HeadURL$
* $Author:
* Created by hjl, SLSE, 2016-07-22
*/
#include "handler_infrastructure_data.h"
#include "settings.h"
#include <QVector>
using namespace VideoOverlayManagement;
HandlerInfrastructureData::HandlerInfrastructureData(const std::shared_ptr<DdsHandler> &ddsHandler, QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_exerciseId(0)
, m_logger(getLogger("HandlerInfrastructureData"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerInfrastructureData::~HandlerInfrastructureData()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerInfrastructureData::init(int exerciseId)
{
m_exerciseId = exerciseId;
// DTC InfrastructureManagement
m_dtc = InfrastructureManagement::Interface::Dtc::create(m_ddsHandler->dds());
if (m_dtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create DTC InfrastructureManagement";
return false;
}
if (!m_dtc->enableMainStructureElement() ||
!m_dtc->enableMountingPointAsset() ||
!m_dtc->enableInstrumentationAsset() ||
!m_dtc->waitForHistoricalDataMainStructureElement() ||
!m_dtc->waitForHistoricalDataMountingPointAsset() ||
!m_dtc->waitForHistoricalDataInstrumentationAsset())
{
ERROR_LOG(m_logger) << "init() DTC InfrastructureManagement failed";
return false;
}
// Get 'static' data for all rooms where a camera is available
QMap<int, QVector<InfrastructureManagement::InstrumentationAsset>> assetsMap; // (roomId, QVector<Asset>)
auto predicate =
[](const InfrastructureManagement::InstrumentationAsset & a)
{
return a.mountingPointTypeId() == InfrastructureManagement::MountingPointType::IndoorCamera;
};
if (!m_dtc->getAllAssetsPerRoom(predicate, assetsMap))
{
WARNING_LOG(m_logger) << "HandlerInfrastructureData::getAllAssetsPerRoom() failed"
<< " assetsMap.size(): " << assetsMap.size();
}
for (auto i = assetsMap.cbegin(); i != assetsMap.cend(); ++i)
{
const int roomId = i.key();
for (const InfrastructureManagement::InstrumentationAsset &asset : i.value())
{
auto it = std::find(asset.availableInExercise().begin(),
asset.availableInExercise().end(), m_exerciseId);
if (it == asset.availableInExercise().end())
{
DEBUG_LOG(m_logger) << "Asset " << asset.id()
<< " is not available in current exercise - skipping";
continue;
}
// in interne m_roomId2CameraNameMap eintragen, zur Zeit nur eine Kamera pro Raum möglich
m_roomId2CameraNameMap.insert(roomId, QString::fromStdString(asset.name()));
// und fuer subscribe in m_assetId2RoomIdMap eintragen
m_assetId2RoomIdMap.insert(asset.id(), roomId);
DEBUG_LOG(m_logger) << " assetId: " << asset.id()
<< " mountingPointTypeId: " << asset.mountingPointTypeId()
<< " name: " << asset.name();
}
} // for(auto i = assetMap...
INFO_LOG(m_logger) << "m_roomId2CameraNameMap.size(): " << m_roomId2CameraNameMap.size();
for (auto i = m_roomId2CameraNameMap.begin(); i != m_roomId2CameraNameMap.end(); ++i)
{
INFO_LOG(m_logger) << "roomId: " << i.key()
<< " cameraName: " << i.value();
}
// Subsribe for AssetChanged (Daten der cameras aus den Assets ermitteln)
connect(m_dtc.get(), &InfrastructureManagement::Interface::Dtc::instrumentationAssetChanged,
this, &HandlerInfrastructureData::onAssetChanged);
// we don't need them now anymore -> unsubscribe (really?)
m_dtc->enableMainStructureElement(false);
m_dtc->enableMountingPointAsset(false);
INFO_LOG(m_logger) << "HandlerInfrastructureData::init() finished. "
<< " m_roomId2CameraNameMap.size(): " << m_roomId2CameraNameMap.size();
return true;
} // end of init()
//-----------------------------------------------------------------------------
bool HandlerInfrastructureData::isCameraAvailable(int roomId) const
{
return m_roomId2CameraNameMap.contains(roomId);
} // end of isCameraAvailable()
//-----------------------------------------------------------------------------
QString HandlerInfrastructureData::getStreamNameFromRoomId(int roomId) const
{
auto it = m_roomId2CameraNameMap.find(roomId);
const QString qs(it == m_roomId2CameraNameMap.end() ? QString() : it.value());
DEBUG_LOG(m_logger) << "streamName for roomId: " << roomId << " '" << qs << "' ";
return qs;
} // end of getStreamNameFromRoomId()
//-----------------------------------------------------------------------------
void HandlerInfrastructureData::onAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType)
{
Q_UNUSED(modType);
if (data.mountingPointTypeId() != InfrastructureManagement::MountingPointType::IndoorCamera)
return;
INFO_LOG(m_logger) << "onAssetChanged()"
<< " assetId: " << data.id()
<< " name: " << data.name();
auto it = std::find(data.availableInExercise().begin(),
data.availableInExercise().end(), m_exerciseId);
if (it == data.availableInExercise().end())
{
DEBUG_LOG(m_logger) << "Asset " << data.id()
<< " is not available in current exercise - skipping";
return;
}
// Hier muss aus der AssetId die zugehoerige roomid verwendet werden !!
m_roomId2CameraNameMap.insert(getRoomIdFromAssetId(data.id()), QString::fromStdString(data.name()));
for (auto i = m_roomId2CameraNameMap.begin(); i != m_roomId2CameraNameMap.end(); ++i)
{
DEBUG_LOG(m_logger) << "m_roomId2CameraNameMap changed... "
<< " m_roomId2CameraNameMap.size(): " << m_roomId2CameraNameMap.size()
<< " roomId: " << i.key()
<< " cameraName: " << *i;
}
} // end of onAssetChanged()
//-----------------------------------------------------------------------------
int HandlerInfrastructureData::getRoomIdFromAssetId(int assetId) const
{
return m_assetId2RoomIdMap.value(assetId, -1);
} // end of getRoomIdFromAssetId()
//-----------------------------------------------------------------------------
@@ -0,0 +1,79 @@
/**
* Handler for infrastructure data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-07-22
*/
#pragma once
#include "dds_handler.h"
#include "logger.h"
#include <InfrastructureManagement/ism_dtc.h>
#include <QtCore/QObject>
#include <QtCore/QMap>
namespace VideoOverlayManagement
{
class HandlerInfrastructureData : public QObject
{
Q_OBJECT
public:
explicit HandlerInfrastructureData(const std::shared_ptr<DdsHandler> &ddsHandler, QObject *parent = nullptr);
~HandlerInfrastructureData();
/**
* Initialize the handler to manage information from infrastructure management
*/
bool init(int exerciseId);
/**
* Check if there is a camera in the room
* @param[in] roomId Id of the room to get information about camera availability
* @returns true if camera is available, otherwise false
*/
bool isCameraAvailable(int roomId) const;
/**
* Returns the streamname of the camera for the given roomId
* @param[in] roomId Id of the room to get the streamname for this camera
* @returns returns the streamname if camera is available, otherwise string is empty
*/
QString getStreamNameFromRoomId(int roomId) const;
Q_SIGNALS:
private Q_SLOTS:
/**
* Handle the signals from 'InfrastructureManagement'
*/
void onAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType);
private: // methoden
/**
* Returns the room id for the given assetId
* @param[in] assetId Id of the asset to get the room id for
* @returns returns the room id if available, otherwise -1
*/
int getRoomIdFromAssetId(int assetId) const;
private: // attributes
std::shared_ptr<DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_dtc; ///< Pointer to DTC InfrastructureManagement interface object
QMap<int, int> m_assetId2RoomIdMap; ///< optional nur noetig bei subscribe for AssetChanged
QMap<int, QString> m_roomId2CameraNameMap; ///< Reference map roomId to camera name(roomId, cameraName) Condition: per room one camera!
int m_exerciseId;
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
};
} // namespace VideoOverlayManagement
+240
View File
@@ -0,0 +1,240 @@
/**
* Handler for Video Overlays
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-07-07
*/
#include "handler_overlays.h"
#include "handler_participant_data.h"
#include "settings.h"
#include <QByteArray>
using namespace VideoOverlayManagement;
HandlerOverlays::HandlerOverlays(AvsInterface *avsIf,
const std::shared_ptr<HandlerParticipantData> &handlerParticipantData,
const std::shared_ptr<HandlerInfrastructureData> &handlerInfrastructureData,
int exerciseId,
QObject *parent)
: QObject(parent)
, m_avsIf(avsIf)
, m_handlerParticipantData(handlerParticipantData)
, m_handlerInfrastructureData(handlerInfrastructureData)
, m_exerciseId(exerciseId)
, m_logger(getLogger("HandlerOverlays"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerOverlays::~HandlerOverlays()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerOverlays::init()
{
INFO_LOG(m_logger) << "Start VideoOverlay Handler.";
// internal Signal/Slot connection (must be done before calling initParticipantsInRoomMap() !)
connect(this, &HandlerOverlays::participantsInRoomMapChanged,
this, &HandlerOverlays::onParticipantsInRoomMapChanged);
// Get assigned participants to roomId data from Player Management ...
initParticipantsInRoomMap();
// Subscribe for external changes
connect(m_handlerParticipantData.get(), &HandlerParticipantData::participantPositionChanged,
this, &HandlerOverlays::onParticipantPositionChanged);
INFO_LOG(m_logger) << "VOM Handler initialized. ";
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerOverlays::onParticipantPositionChanged(int oldRoomId, int newRoomId, int participantId)
{
DEBUG_LOG(m_logger) << "onParticipantPositionChanged() "
<< " oldRoomId: " << oldRoomId
<< " newRoomId: " << newRoomId
<< " participantId: " << participantId
;
if (oldRoomId > 0) // is valid
removePartIdFromParticipantsInRoomMap(oldRoomId, participantId);
if (newRoomId > 0)
addPartIdToParticipantsInRoomMap(newRoomId, participantId);
} // end of onParticipantPositionChanged()
//-----------------------------------------------------------------------------
void HandlerOverlays::onParticipantsInRoomMapChanged(int roomId, const QSet<int> &participants)
{
DEBUG_LOG(m_logger) << "onParticipantsInRoomMapChanged() "
<< " roomId: " << roomId
<< " partId: " << getAllEquipmentNumbers(participants, false)
<< " eqNo: " << getAllEquipmentNumbers(participants, true)
<< " participants.size(): " << participants.size()
;
if (!m_handlerInfrastructureData->isCameraAvailable(roomId))
{
WARNING_LOG(m_logger) << "onParticipantsInRoomMapChanged() Non camera available in roomId: " << roomId << " No data will be send to AVS.";
return;
}
// SetStreamOverlayText Command String zusammenstellen
QString cmd;
QString contextName = getContextName();
QString streamName = m_handlerInfrastructureData->getStreamNameFromRoomId(roomId);
QString overlayTemplateName = getOverlayTemplateName();
if (streamName.isEmpty())
{
ERROR_LOG(m_logger) << "onParticipantsInRoomMapChanged() No streamName found for roomId: " << roomId << " No data will be send to AVS.";
return;
}
cmd.append(QLatin1String("SetStreamOverlayText "));
cmd.append(contextName);
cmd.append(QLatin1String(" "));
cmd.append(streamName);
cmd.append(QLatin1String(" "));
cmd.append(overlayTemplateName);
cmd.append(QLatin1String(" "));
cmd.append(QLatin1String("0 "));
cmd.append(QLatin1String("\""));
cmd.append(QLatin1String("Participants(EqNo) in roomId "));
cmd.append((QString::number(roomId)));
cmd.append(QLatin1String(": "));
cmd.append(getAllEquipmentNumbers(participants, true));
cmd.append(QLatin1String("\""));
QByteArray qba = cmd.toLatin1();
qba += "\r\n";
INFO_LOG(m_logger) << "onParticipantsInRoomMapChanged() sendCommand: " << qba ;
m_avsIf->sendCommand(qba);
// room entry der keine participants enthaelt loeschen
if (participants.isEmpty())
m_participantsInRoomMap.remove(roomId);
} // end of onParticipantsInRoomMapChanged()
//-----------------------------------------------------------------------------
void HandlerOverlays::initParticipantsInRoomMap()
{
// QMap<participantId, roomId>
const QMap<int, int> qm = m_handlerParticipantData->getAllAssignedParticipants();
for (auto i = qm.begin(); i != qm.end(); ++i)
onParticipantPositionChanged(0, i.value(), i.key());
} // end of initParticipantsInRoomMap()
//-----------------------------------------------------------------------------
void HandlerOverlays::addPartIdToParticipantsInRoomMap(int roomId, int participantId)
{
DEBUG_LOG(m_logger) << "addPartIdToParticipantsInRoomMap() "
<< " roomId: " << roomId
<< " participantId: " << participantId
;
QSet<int> participants;
if (m_participantsInRoomMap.contains(roomId))
{
QMap<int, QSet<int>>::const_iterator i = m_participantsInRoomMap.constFind(roomId);
participants = i.value();
}
participants.insert(participantId);
m_participantsInRoomMap.insert(roomId, participants);
///
DEBUG_LOG(m_logger) << "emit participantsInRoomMapChanged()"
<< " roomId: " << roomId
<< " partId: " << getAllEquipmentNumbers(participants, false)
<< " eqNo: " << getAllEquipmentNumbers(participants, true)
<< " participants.size(): " << participants.size()
;
emit participantsInRoomMapChanged(roomId, participants);
} // end of addPartIdToParticipantsInRoomMap()
//-----------------------------------------------------------------------------
void HandlerOverlays::removePartIdFromParticipantsInRoomMap(int roomId, int participantId)
{
DEBUG_LOG(m_logger) << "removePartIdFromParticipantsInRoomMap() "
<< " roomId: " << roomId
<< " participantId: " << participantId
;
if (m_participantsInRoomMap.contains(roomId))
{
QMap<int, QSet<int>>::const_iterator i = m_participantsInRoomMap.constFind(roomId);
QSet<int> participants = i.value();
// remove participant from the set
participants.remove(participantId);
m_participantsInRoomMap.insert(roomId, participants);
DEBUG_LOG(m_logger) << "emit participantsInRoomMapChanged()"
<< " roomId: " << roomId
<< " partId: " << getAllEquipmentNumbers(participants, false)
<< " eqNo: " << getAllEquipmentNumbers(participants, true)
<< " participants.size(): " << participants.size()
;
emit participantsInRoomMapChanged(roomId, participants);
}
} // end of removePartIdFromParticipantsInRoomMap()
//-----------------------------------------------------------------------------
QString HandlerOverlays::getContextName() const
{
QString qs(Settings::getContextName());
qs.append(QString::number(m_exerciseId));
return qs;
} // end of getContextName()
//-----------------------------------------------------------------------------
QString HandlerOverlays::getOverlayTemplateName() const
{
return Settings::getOverlayTemplateName();
} // end of getOverlayTemplateName()
//-----------------------------------------------------------------------------
QSet<int> HandlerOverlays::convertParticipantIdsToEquipmentNo(const QSet<int> &participants) const
{
QSet<int> equipmentNumbers;
for (int currentParticipantId : participants)
{
int equipmentNumber = m_handlerParticipantData->getEquipmentNumber(currentParticipantId);
equipmentNumbers.insert(equipmentNumber);
}
return equipmentNumbers;
} // end of convertParticipantIdsToEquipmentNo()
//-----------------------------------------------------------------------------
QString HandlerOverlays::getAllEquipmentNumbers(QSet<int> data, bool isParticipantIds) const
{
QString qs;
if (isParticipantIds)
data = convertParticipantIdsToEquipmentNo(data);
for (int currentDataId : qAsConst(data))
{
qs.append(QString::number(currentDataId));
qs.append(QLatin1String(", "));
}
// remove last ", "
if (!qs.isEmpty())
qs.chop(2);
return qs;
} // end of getAllEquipmentNumbers()
//-----------------------------------------------------------------------------
+123
View File
@@ -0,0 +1,123 @@
/**
* Handler for Video Overlays
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-07-07
*/
#pragma once
#include <QtCore/QObject>
#include <QSet>
#include "avs_interface.h"
#include "handler_participant_data.h"
#include "handler_infrastructure_data.h"
#include "logger.h"
namespace VideoOverlayManagement
{
// Forwarddeclarations
class AvsInterface;
class HandlerOverlays
: public QObject
{
Q_OBJECT
public:
explicit HandlerOverlays(AvsInterface *avsIf,
const std::shared_ptr<HandlerParticipantData> &handlerParticipantData,
const std::shared_ptr<HandlerInfrastructureData> &handlerInfrastructureData,
int exerciseId,
QObject *parent = nullptr);
~HandlerOverlays();
bool init();
Q_SIGNALS:
/**
* Emits when a participant position was changed to another room (internal signal/slot)
* @param[in] roomId Id of the room where the participant association to be change
* @param[in] participants List of all participants assigned to roomId
*/
void participantsInRoomMapChanged(int roomId, const QSet<int> &participants);
private Q_SLOTS:
/**
* Handle incoming position changed signals
* @param[in] oldRoomId ID of the room where the participant was at the last message.
* @param[in] newRoomId ID of the room where the participant was at this message.
* @param[in] participantId Id of the participant who is assigned to the message
*/
void onParticipantPositionChanged(int oldRoomId, int newRoomId, int participantId);
/**
* Build the video overlay string based on the given data
* @param[in] roomId Id of the room to get information about camera availability
* @param[in] participants List of all participants assigned to roomId
*/
void onParticipantsInRoomMapChanged(int roomId, const QSet<int> &participants);
private: // methodes
/**
* Initialize 'participantsInRoomMap'
*/
void initParticipantsInRoomMap();
/**
* Add participant in 'participantsInRoomMap' for the given roomId entry
* and emits onParticipantsInRoomMapChanged(...) to build the video overlay string
* @param[in] roomId Id of the room which entry will to be modified
* @param[in] participantId Id of the participant who has to be modified
*/
void addPartIdToParticipantsInRoomMap(int roomId, int participantId);
/**
* Remove participant in 'participantsInRoomMap' for the given roomId entry
* and emits onParticipantsInRoomMapChanged(...) to build the video overlay string
* @param[in] roomId Id of the room which entry will to be modified
* @param[in] participantId Id of the participant who has to be remove
*/
void removePartIdFromParticipantsInRoomMap(int roomId, int participantId);
/**
* Returns the 'context' name used for AVS output
* @returns returns the context name
*/
QString getContextName() const;
/**
* Returns the name for the overlay template used for AVS output
* @returns overlay template name
*/
QString getOverlayTemplateName() const;
/**
* Convert the given list of participants to their assigned equipment number
* @param[in] participants Set of participant ids to get the equipment number for
* @returns Converted QSet (if an participantId could not be converted the entry will be empty)
*/
QSet<int> convertParticipantIdsToEquipmentNo(const QSet<int> &participants) const;
/**
* Returns a comma separated string with equipment numbers for the given list of participantIds/equipment numbers
* @param[in] data Set of participant ids or equipment numbers to get the string for
* @param[in] isParticipantIds true means data are participantIds otherwise equipment numbers
* @returns String with equipment numbers (if an participantId could not be converted the entry will be empty)
*/
QString getAllEquipmentNumbers(QSet<int> data, bool isParticipantIds) const;
private: // attributes
AvsInterface *m_avsIf; ///< Pointer to AVS-Interface
std::shared_ptr<HandlerParticipantData> m_handlerParticipantData; ///< Pointer to participant data handler
std::shared_ptr<HandlerInfrastructureData> m_handlerInfrastructureData; ///< Pointer to infrastructure data handler
int m_exerciseId; ///< Exercise id
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
QMap<int, QSet<int>> m_participantsInRoomMap; ///< Includes all participants (player) in one room (roomId, Set<participantId>)
};
} // namespace VideoOverlayManagement
@@ -0,0 +1,130 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-07-05
*/
#include "handler_participant_data.h"
#include "settings.h"
#include <QSet>
using namespace VideoOverlayManagement;
HandlerParticipantData::HandlerParticipantData(const std::shared_ptr<DdsHandler> &ddsHandler, QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_logger(getLogger("HandlerParticipantData"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerParticipantData::~HandlerParticipantData()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerParticipantData::init()
{
// DTC ParticipantManagement
m_dtc = ParticipantManagement::Interface::Dtc::create(m_ddsHandler->dds());
if (m_dtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create DTC ParticipantManagement";
return false;
}
// only subscribe to the topics we're interested in
if (!m_dtc->enableParticipant() || !m_dtc->enableParticipantPosition())
{
ERROR_LOG(m_logger) << "init() DTC ParticipantManagement failed";
return false;
}
// Get 'static' data for all participants (playerdata)
// Subsribe for ParticipantChanged
connect(m_dtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &HandlerParticipantData::onParticipantChanged);
// Player in Referenzmap eintragen
m_dtc->participants([this](const ParticipantManagement::Participant &p) { onParticipantChanged(p, DataModification::eAdded);});
// Get last position ('dynamic' data) of all participants
// Subsribe for participantPositionChanged
connect(m_dtc.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &HandlerParticipantData::onParticipantPositionChanged);
// Position in ParticipantsPositionMap eintragen
auto cbParticipantPos = [this](const ParticipantManagement::ParticipantPosition &participantPos)
{
m_participantsPositionMap.insert(participantPos.participantId(), participantPos.roomId());
};
m_dtc->participantPositions(cbParticipantPos);
INFO_LOG(m_logger) << "HandlerParticipantData::init() finished. "
<< " m_partId2EquipNoMap.size(): " << m_partId2EquipNoMap.size()
<< " m_participantsPositionMap.size(): " << m_participantsPositionMap.size();
return true;
} // end of init()
//-----------------------------------------------------------------------------
int HandlerParticipantData::getEquipmentNumber(int participantId) const
{
return m_partId2EquipNoMap.value(participantId);
} // end of getEquipmentNumber()
//-----------------------------------------------------------------------------
QMap<int, int> HandlerParticipantData::getAllAssignedParticipants() const
{
QMap<int, int> qMap;
for (auto i = m_participantsPositionMap.begin(); i != m_participantsPositionMap.end(); ++i)
{
if (i.value() > 0)
qMap.insert(i.key(), i.value());
}
return qMap;
} // end of getAllAssignedParticipants()
//-----------------------------------------------------------------------------
void HandlerParticipantData::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
{
INFO_LOG(m_logger) << "onParticipantChanged() participantId:" << data.id();
if (modType != DataModification::eRemoved && data.equipmentNumber().is_set())
m_partId2EquipNoMap.insert(data.id(), data.equipmentNumber().get());
else
m_partId2EquipNoMap.remove(data.id());
if (m_logger.isDebugEnabled())
{
for (auto i = m_partId2EquipNoMap.begin(); i != m_partId2EquipNoMap.end(); ++i)
DEBUG_LOG(m_logger) << " partId2EquipNoMap.size(): " << m_partId2EquipNoMap.size()
<< " partId: " << i.key()
<< " eqNo: " << i.value();
}
} // end of onParticipantChanged()
//-----------------------------------------------------------------------------
void HandlerParticipantData::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
const int newRoomId = data.roomId();
// get reference to room (will be created if not exist)
int &roomId = m_participantsPositionMap[data.participantId()];
// remember old room
const int oldRoomId = roomId;
// assing new room
roomId = modType == DataModification::eRemoved ? 0 : newRoomId;
if (newRoomId != oldRoomId)
emit participantPositionChanged(oldRoomId, newRoomId, data.participantId());
INFO_LOG(m_logger) << "onParticipantPositionChanged()"
<< " oldRoomId: " << oldRoomId
<< " newRoomId: " << newRoomId
<< " participantId: " << data.participantId();
if (modType == DataModification::eRemoved)
m_participantsPositionMap.remove(data.participantId());
} // end of onParticipantPositionChanged()
//-----------------------------------------------------------------------------
@@ -0,0 +1,75 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-07-05
*/
#pragma once
#include "dds_handler.h"
#include "logger.h"
#include <ParticipantManagement/ppm_dtc.h>
#include <QtCore/QObject>
#include <QtCore/QMap>
namespace VideoOverlayManagement
{
class HandlerParticipantData : public QObject
{
Q_OBJECT
public:
explicit HandlerParticipantData(const std::shared_ptr<DdsHandler> &ddsHandler, QObject *parent = nullptr);
~HandlerParticipantData();
/**
* Initialize the handler to manage information from player management
*/
bool init();
/**
* Get equipment number for the given participant
* @param participantId participant id to get the equipment number for
* @return equipment number or 0 in case of failure
*/
int getEquipmentNumber(int participantId) const;
/**
* Get all participants which are assigned to a room
* @return QMap<participantId, roomId>
*/
QMap<int, int> getAllAssignedParticipants() const;
Q_SIGNALS:
/**
* Signal is emitted when participant position changed (Signal to HandlerOverlay)
*/
void participantPositionChanged(int oldRoomId, int newRoomId, int participantId);
private Q_SLOTS:
/**
* Handle the signals from 'ParticipantManagement'
*/
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType);
void onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType);
private: // methoden
private: // attributes
std::shared_ptr<DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_dtc; ///< Pointer to DTC ParticipantManagement interface object
QMap<int, int> m_partId2EquipNoMap; ///< Reference map participant (player) to equipment number (participantId, equipmentNo)
QMap<int, int> m_participantsPositionMap; ///< Reference map participant (player) to room id (participantId, roomId)
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
};
} // namespace VideoOverlayManagement
+84
View File
@@ -0,0 +1,84 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: VideoOverlayManagement
###########################################################
#log4j.logger.VOM=DEBUG
#log4j.logger.VOM.main=DEBUG
#log4j.logger.VOM.AVS_Interface=DEBUG
#log4j.logger.VOM.DdsHandler=DEBUG
#log4j.logger.VOM.HandlerInfrastructureData=DEBUG
#log4j.logger.VOM.HandlerOverlays=DEBUG
#log4j.logger.VOM.HandlerParticipantData=DEBUG
#log4j.logger.VOM.MainHandler=DEBUG
# File
###########################################################
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:
+36
View File
@@ -0,0 +1,36 @@
/**
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-23
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace VideoOverlayManagement
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "VOM.";
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 VideoOverlayManagement
+23
View File
@@ -0,0 +1,23 @@
/**
* Logging for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-23
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "vom_export.h"
namespace VideoOverlayManagement
{
using LOGGER_T = NGL::INGLLogger &;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace VideoOverlayManagement
+53
View File
@@ -0,0 +1,53 @@
/**
* Main for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-22
*/
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <QNetworkProxy>
#include "main_handler.h"
#include "logger.h"
#include "settings.h"
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
QNetworkProxy::setApplicationProxy(QNetworkProxy());
LtsCommandLineParser::LtsCommandLineParser options;
if (!options.init())
return -1;
app.createLogger("VOM", options.exerciseId());
if (options.exerciseId() < 0)
{
fprintf(stdout, "=> exerciseId is required (>=0)");
return -2;
}
INFO_LOG(app.baseLogger()) << "*** Start Video Overlay Management Service (VOM)";
INFO_LOG(app.baseLogger()) << "### domainId: " << options.domainId() << ", exerciseId: #" << options.exerciseId();
VideoOverlayManagement::Settings::setIniFile(options.iniFile());
int iRet = -1;
{
std::unique_ptr<VideoOverlayManagement::MainHandler> mainHandler(new VideoOverlayManagement::MainHandler);
if (!mainHandler->init(options.domainId(), options.exerciseId()))
return iRet;
STARTUP_LOG(app.baseLogger());
iRet = app.exec();
SHUTDOWN_LOG(app.baseLogger());
}
return iRet;
} // end of main()
//-----------------------------------------------------------------------------
+214
View File
@@ -0,0 +1,214 @@
/**
* MainHandler for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-23
*/
#include "main_handler.h"
#include "settings.h"
#include <QTimer>
#include <DDS/Core/pacemaker.h>
using namespace VideoOverlayManagement;
MainHandler::MainHandler(QObject *parent)
: QObject(parent)
, m_exerciseId(0)
, m_avsIf(new AvsInterface(true, this))
, m_avsConnectionState(AvsIfConnectionState::Undefined)
, m_ddsHandler(nullptr)
, m_handlerParticipantData(nullptr)
, m_handlerInfrastructureData(nullptr)
, m_handlerOverlays(nullptr)
, m_checkConnectTimer(new QTimer(this))
, m_keepAliveTriggerTimer(new QTimer(this))
, m_bAvsSocketWarnedOnce(false)
, m_logger(getLogger("MainHandler"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
MainHandler::~MainHandler()
{
m_ddsHandler.reset();
} // end of dtor()
//-----------------------------------------------------------------------------
bool MainHandler::init(int domainId, int exerciseId)
{
INFO_LOG(m_logger) << "Start VideoOverlayManagement MainHandler.";
m_exerciseId = exerciseId;
// init AVS-Interface
QString hostName = Settings::getAvsHostname();
quint16 port = Settings::getAvsAvaPort();
INFO_LOG(m_logger) << "Init AVS-Interface Hostname/Ip:" << hostName
<< " Port: " << port;
m_avsIf->start(hostName, port);
connect(m_avsIf, &AvsInterface::avsIfConnectionState,
this, &MainHandler::onAvsIfConnectionState);
connect(m_avsIf, &AvsInterface::avsCmdState,
this, &MainHandler::onAvsCmdState);
connect(m_avsIf, &AvsInterface::avsKeepAliveTimeout,
this, &MainHandler::onAvsKeepAliveTimeout);
connect(m_keepAliveTriggerTimer, &QTimer::timeout,
this, &MainHandler::onSendKeepAlive);
// initialize DDS
// for VideoOverlayManagement => exerciseId = partitionId
m_ddsHandler.reset(new DdsHandler(domainId, exerciseId));
if (!m_ddsHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation DdsHandler failed.";
if (m_ddsHandler->pacemaker())
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StartingError);
return false;
}
// initialize handlerParticipantData
m_handlerParticipantData.reset(new HandlerParticipantData(m_ddsHandler, this));
if (!m_handlerParticipantData->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerPlayerData failed.";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StartingError);
return false;
}
// initialize handlerInfraStructureData
m_handlerInfrastructureData.reset(new HandlerInfrastructureData(m_ddsHandler, this));
if (!m_handlerInfrastructureData->init(m_exerciseId))
{
ERROR_LOG(m_logger) << "Initialisation HandlerInfrastructreData failed.";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StartingError);
return false;
}
// Initialisation of OverlayHandler wait until AVS is connected
connect(m_checkConnectTimer, &QTimer::timeout,
this, &MainHandler::onTryToInitOverlayHandler);
m_checkConnectTimer->start(1000);
INFO_LOG(m_logger) << "VOM Handler initialized. (Connection to AVS may be still pending) ";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Starting);
return true;
} // end of init()
//-----------------------------------------------------------------------------
bool MainHandler::onTryToInitOverlayHandler()
{
m_avsConnectionState = m_avsIf->getAvsIfState();
if (m_avsConnectionState != AvsIfConnectionState::Connected)
{
if (!m_bAvsSocketWarnedOnce)
{
m_bAvsSocketWarnedOnce = true;
WARNING_LOG(m_logger) << "MainHandler::onTryToInitOverlayHandler()"
<< " Wait for AvsIfConnectionState::Connected... ";
}
return false;
}
m_bAvsSocketWarnedOnce = true; // reset
m_checkConnectTimer->stop();
// initialize handlerOverlays
m_handlerOverlays.reset(new HandlerOverlays(m_avsIf, m_handlerParticipantData, m_handlerInfrastructureData, m_exerciseId, this));
if (!m_handlerOverlays->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerOverlays failed.";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StoppedError);
return false;
}
INFO_LOG(m_logger) << "VOM Handler initialized. (Connection to AVS established) ";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
return true;
} // end of onTryToInitOverlayHandler()
//-----------------------------------------------------------------------------
void MainHandler::onAvsIfConnectionState(AvsIfConnectionState state)
{
switch (state)
{
case AvsIfConnectionState::Connected:
INFO_LOG(m_logger) << "AvsIfConnectionState::Connected ... start keepAliveTriggerTimer";
m_keepAliveTriggerTimer->start(Settings::getAvsKeepAliveTriggerRequestTime());
break;
case AvsIfConnectionState::Disconnected:
m_keepAliveTriggerTimer->stop();
break;
case AvsIfConnectionState::TryReconnect:
m_keepAliveTriggerTimer->stop();
break;
case AvsIfConnectionState::ConnectionError:
ERROR_LOG(m_logger) << "AvsIfConnectionState::ConnectionError !";
m_keepAliveTriggerTimer->stop();
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StoppedError);
break;
case AvsIfConnectionState::Undefined:
default:
WARNING_LOG(m_logger) << "Undefined AvsIfConnectionState !";
break;
}
} // end of onAvsIfConnectionState()
//-----------------------------------------------------------------------------
void MainHandler::onAvsCmdState(AvsCmdState state)
{
bool bOk = false;
switch (state)
{
case AvsCmdState::Ok:
INFO_LOG(m_logger) << "AvsCmdState::Ok";
bOk = true;
break;
case AvsCmdState::BadArguments:
WARNING_LOG(m_logger) << "AvsCmdState::BadArguments";
break;
case AvsCmdState::CommandNotStateValid:
WARNING_LOG(m_logger) << "AvsCmdState::CommandNotStateValid";
break;
case AvsCmdState::KeepAlive:
DEBUG_LOG(m_logger) << "AvsCmdState::KeepAlive";
break;
default:
break;
}
if (!bOk)
{
// ToDo: Fehlermeldung an ServiceManagement senden
}
} // end of onAvsCmdState()
//-----------------------------------------------------------------------------
void MainHandler::onAvsKeepAliveTimeout()
{
// ToDo: Fehlermeldung an ServiceManagement senden
WARNING_LOG(m_logger) << "AVS KeepAlive timeout !";
} // end of onAvsKeepAliveTimeout()
//-----------------------------------------------------------------------------
void MainHandler::onSendKeepAlive()
{
QString cmd(QLatin1String("KEEPALIVE"));
QByteArray qba = cmd.toLatin1();
qba += "\r\n";
m_avsIf->sendCommand(qba);
} // end of onSendKeepAlive()
//-----------------------------------------------------------------------------
+69
View File
@@ -0,0 +1,69 @@
/**
* MainHandler for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-23
*/
#pragma once
#include <QtCore/QObject>
#include "avs_interface.h"
#include "handler_participant_data.h"
#include "handler_infrastructure_data.h"
#include "handler_overlays.h"
#include "dds_handler.h"
#include "logger.h"
class QTimer;
namespace VideoOverlayManagement
{
// Forwarddeclarations
class AvsInterface;
class MainHandler
: public QObject
{
Q_OBJECT
public:
explicit MainHandler(QObject *parent = nullptr);
~MainHandler();
bool init(int domainId, int exerciseId);
private Q_SLOTS:
/**
* Handle signals for AVS Handling
*/
void onAvsIfConnectionState(AvsIfConnectionState state);
void onAvsCmdState(AvsCmdState state);
void onAvsKeepAliveTimeout();
bool onTryToInitOverlayHandler(); ///< Initialize OverlayHandler after sucessfully AVS connection
/**
* Sends a keep alive request to the server. Normally this method is
* called periodically by the KeepAliveTimer.
*/
void onSendKeepAlive();
private: // attributes
int m_exerciseId; ///< Exercise id
AvsInterface *m_avsIf; ///< Pointer to AVS-Interface
AvsIfConnectionState m_avsConnectionState; ///< AVS connection state
std::shared_ptr<DdsHandler> m_ddsHandler; ///< Pointer to DDS handler
std::shared_ptr<HandlerParticipantData> m_handlerParticipantData; ///< Pointer to participant data handler
std::shared_ptr<HandlerInfrastructureData> m_handlerInfrastructureData; ///< Pointer to infrastructure data handler
std::unique_ptr<HandlerOverlays> m_handlerOverlays; ///< Pointer to overlay handler
QTimer *m_checkConnectTimer; ///< Wait for AVS connected.
QTimer *m_keepAliveTriggerTimer; ///< Timer for triggering the keep alive request
bool m_bAvsSocketWarnedOnce;
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
};
} // namespace VideoOverlayManagement
+85
View File
@@ -0,0 +1,85 @@
/**
* Settings for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-30
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <nglsettings/nglsettings_connections.h>
#include <ngltools/ngltools_filesystem.h>
namespace VideoOverlayManagement
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//---------------------------------------------------------------------
QString Settings::getAvsHostname()
{
return NGL::Connections::hostName(NGL::Connections::eConnection::AVS_AVA);
}
//---------------------------------------------------------------------
quint16 Settings::getAvsAvaPort()
{
return NGL::Connections::port(NGL::Connections::eConnection::AVS_AVA);
}
//---------------------------------------------------------------------
quint16 Settings::getAvsKeepAliveTriggerRequestTime()
{
// Info: AVS schickt alle 20 sec '298 KEEPALIVE' aufgrund eines KEEPALIVE Requesttrigger aus MainHandler!
quint16 keepAliveTriggerRequestTime = settings()->settings()->value(QLatin1String("zwav_connection/keepAliveTriggerRequestTime"), 1000 * 20).toUInt();
return keepAliveTriggerRequestTime;
}
//---------------------------------------------------------------------
quint16 Settings::getAvsKeepAliveTime()
{
// Mit dieser Timeoutzeit wird beim Ausbleiben von '298 KEEPALIVE' der Fehlerfall dedektiert.
quint16 keepAliveTime = settings()->settings()->value(QLatin1String("zwav_connection/keepAliveTime"), 1000 * 25).toUInt();
return keepAliveTime;
}
//---------------------------------------------------------------------
QString Settings::getOverlayTemplateName()
{
return QLatin1String("bottomcenter");
}
//---------------------------------------------------------------------
QString Settings::getContextName()
{
// ToDo: Nach Umstellung von AVS den 'EXCON' Namen 'ex_' verwenden!
return QLatin1String("uebung_");
}
//---------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//---------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
} // namespace VideoOverlayManagement
+44
View File
@@ -0,0 +1,44 @@
/**
* Settings for VideoOverlayManagement
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-30
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace VideoOverlayManagement
{
namespace Settings
{
//!< Get the hostname for AVS
QString getAvsHostname();
//!< Get the port for AVS RCP_AVA
quint16 getAvsAvaPort();
//!< Get AVS keep-alive trigger request time intervall in msec
quint16 getAvsKeepAliveTriggerRequestTime();
//!< Get AVS keep-alive time intervall in msec
quint16 getAvsKeepAliveTime();
//!< Get overlay template name used for AVS textoutput
QString getOverlayTemplateName();
//!< Get context name used for AVS textoutput
QString getContextName();
//!< The real NGL::Settings - object
NGL::Settings *settings();
void setIniFile(const QString &ini);
}
} // namespace VideoOverlayManagement
+52
View File
@@ -0,0 +1,52 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-06-23
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef VOM_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define VOM_COMMON_EXPORT
# else
# if defined(MAKE_SVCVOMCOMMON_LIB)
# define VOM_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define VOM_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef VOM_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define VOM_CLIENT_EXPORT
# else
# if defined(MAKE_SVCVOMCLIENT_LIB)
# define VOM_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define VOM_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef VOM_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define VOM_SERVER_EXPORT
# else
# if defined(MAKE_SVCVOMSERVER_LIB)
# define VOM_SERVER_EXPORT Q_DECL_EXPORT
# else
# define VOM_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="VideoOverlayManagement" procNames="VideoOverlayManagement" abbreviation="VOM" exerciseDependency="Exercise" groups="ExerciseExecution,ExercisePaused,ExerciseAfterActionReview">
<rcs>
<Id Id="$Id$"/>
<HeadURL HeadURL="$HeadURL$"/>
<Author Author="$Author$"/>
</rcs>
<tables/>
<dbServiceStructs/>
<topicTypes/>
<functionTopics/>
<enumerations/>
</service>