/** * AVS-Interface for VideoOverlayManagement * $Id$ * $HeadURL$ * $Author$ * Created by hjl, SLSE, 2016-06-24 */ #include "avs_interface.h" #include "settings.h" #include #include #include #include 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::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 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 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