/** * @RDE_HEADER@ * One connection to a bsm * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2017-01-18 */ #include "bsm_socket.h" #include "bsm_telegrams_configuration_setup.h" #include #include static const int s_aliveTimeout = 10; // 10 seconds namespace BuildingControlUnit { namespace BSM { Socket::Socket(const Bsm &cfg, QObject *parent) : QObject(parent) , m_config(cfg) , m_tcpSocket(new QTcpSocket(this)) , m_reconnectTimer(nullptr) , m_aliveTimer(new QTimer(this)) , m_logger(BuildingControlUnit::getLogger("BSM.Socket")) { m_aliveTimer->setTimerType(Qt::VeryCoarseTimer); m_aliveTimer->setSingleShot(true); m_aliveTimer->setInterval(s_aliveTimeout * 2 * 1000); connect(m_aliveTimer, &QTimer::timeout, this, &Socket::onAliveTimeout); connect(m_tcpSocket, &QTcpSocket::connected, this, &Socket::onConnected); connect(m_tcpSocket, &QTcpSocket::disconnected, this, &Socket::onDisconnected); connect(m_tcpSocket, QOverload::of(&QTcpSocket::error), this, &Socket::onError); connect(m_tcpSocket, &QTcpSocket::readyRead, this, &Socket::onReadyRead); onConnect(); } bool Socket::isConnected() const { return m_tcpSocket && (m_tcpSocket->state() == QAbstractSocket::ConnectedState); } bool Socket::sendData(const QByteArray &data) { if (!isConnected()) { WARNING_LOG(m_logger) << "BSM " << m_config.id << ": Trying to send data but not connected!"; return false; } DEBUG_LOG(m_logger) << "BSM " << m_config.id << ": sending data: 0x" << data.toHex(); m_tcpSocket->write(data); m_tcpSocket->flush(); return true; } void Socket::setVersionInformation(int verMajor, int verMinor, int verRev, const QString &manufacturer) { m_versionInfo = QStringLiteral("%1.%2-%3 (%4)").arg(verMajor).arg(verMinor).arg(verRev).arg(manufacturer); INFO_LOG(m_logger) << "BSM " << m_config.id << ": version = " << m_versionInfo; } void Socket::gotAlive() { // restart timer if (m_aliveTimer) m_aliveTimer->start(); } void Socket::onConnected() { INFO_LOG(m_logger) << "BSM " << m_config.id << " is connected to " << m_tcpSocket->peerAddress().toString() << ":" << m_tcpSocket->peerPort(); Telegrams::PanConfigurationSetup tele; tele.m_aliveMessage = s_aliveTimeout; sendData(tele.toBytestream()); m_aliveTimer->start(); emit connected(m_config.id); } void Socket::onDisconnected() { INFO_LOG(m_logger) << "BSM " << m_config.id << " is disconnected"; m_versionInfo.clear(); startReconnectTimer(); emit disconnected(m_config.id); } void Socket::onError(QAbstractSocket::SocketError error) { DEBUG_LOG(m_logger) << "BSM " << m_config.id << " can not connect to " << m_config.hostname << ":" << m_config.port << ": " << m_tcpSocket->errorString() << " (" << error << ");"; startReconnectTimer(); } void Socket::onConnect() { DEBUG_LOG(m_logger) << "BSM " << m_config.id << " trying to connect to " << m_config.hostname << ":" << m_config.port; m_tcpSocket->connectToHost(m_config.hostname, m_config.port); } void Socket::onReadyRead() { emit dataAvailable(m_config.id, m_tcpSocket->readAll()); } void Socket::onAliveTimeout() { WARNING_LOG(m_logger) << "BSM " << m_config.id << " alive timeout! Reconnecting"; //m_tcpSocket->disconnectFromHost(); } void Socket::startReconnectTimer() { if (!m_reconnectTimer) { m_reconnectTimer = new QTimer(this); m_reconnectTimer->setTimerType(Qt::VeryCoarseTimer); m_reconnectTimer->setSingleShot(true); connect(m_reconnectTimer, &QTimer::timeout, this, &Socket::onConnect); } m_reconnectTimer->start(2000); // after 2sec if (m_aliveTimer) m_aliveTimer->stop(); } } // namespace BSM } // namespace BuildingControlUnit