Files
2026-08-13 18:33:10 +02:00

264 lines
7.7 KiB
C++
Executable File

/**
* 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