/** * Send / Receive telegrams to/from Wls * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-09-26 */ #include "wls_dispatcher.h" #include "wls_handler_rx.h" #include "wls_handler_tx.h" #include #include #include #include namespace WlsTetra { WlsDispatcher::WlsDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp, const std::shared_ptr &recvFromTabCb, NGL::Settings *settings) : m_recvFromTabCb(recvFromTabCb) , m_recvFromWls(std::make_shared(recvFromTabCb, this)) , m_sendToWls(std::make_shared(pdp, this)) , m_settings(settings) , m_webSocket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this)) , m_webSocketReconnectTimer(new QTimer(this)) , m_bWarnedOnce(false) , m_logger(getLogger("WlsDispatcher")) { connect(m_webSocket, QOverload::of(&QWebSocket::error), this, &WlsDispatcher::onWebSocketError); connect(m_webSocket, &QWebSocket::connected, this, &WlsDispatcher::onWlsConnected); connect(m_webSocket, &QWebSocket::disconnected, this, &WlsDispatcher::onWlsDisconnected); connect(m_webSocket, &QWebSocket::textMessageReceived, this, &WlsDispatcher::onTextMessageReceived); connect(m_webSocketReconnectTimer, &QTimer::timeout, this, &WlsDispatcher::init); connect(m_recvFromWls.get(), &WlsHandlerRx::participantConnectionState, m_sendToWls.get(), &WlsHandlerTx::onParticipantConnectionState); } bool WlsDispatcher::init() { emit connectionState(QString::fromUtf8(name()), false); const QUrl url(webSocketUrl()); if (!m_bWarnedOnce) NOTICE_LOG(m_logger) << "Using WebSocket url: " << url.toString(); m_webSocket->open(url); return true; } std::shared_ptr WlsDispatcher::sendToTab() { return std::static_pointer_cast(m_sendToWls); } bool WlsDispatcher::canSendData() const { return m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState; } void WlsDispatcher::onWlsConnected() { QWebSocket *ws = qobject_cast(sender()); m_sendToWls->onWlsConnected(ws); m_webSocketReconnectTimer->stop(); m_bWarnedOnce = false; } void WlsDispatcher::onWlsDisconnected() { INFO_LOG(m_logger) << "Wls socket disconnected"; m_webSocketReconnectTimer->start(5000); m_sendToWls->onWlsDisconnected(); emit connectionState(QString::fromUtf8(name()), false); } void WlsDispatcher::onWlsExternalConnectionStateChanged(bool bConnected) { m_sendToWls->onWlsConnectedToExternalSystem(bConnected); emit connectionState(QString::fromUtf8(name()), bConnected); } void WlsDispatcher::onWebSocketError() { if (!m_webSocket) return; if (!m_bWarnedOnce) WARNING_LOG(m_logger) << "Error connecting to " << webSocketUrl().toString() << ": " << m_webSocket->errorString(); m_webSocket->close(); m_webSocketReconnectTimer->start(5000); m_bWarnedOnce = true; emit connectionState(QString::fromUtf8(name()), false); } void WlsDispatcher::onTextMessageReceived(const QString &message) { // convert from json to internal representation, send to TAB m_recvFromWls->handleTelegram(message.toUtf8()); } void WlsDispatcher::onParticipantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc) { INFO_LOG(m_logger) << "onParticipantLicenseChange id=" << lc.id() << " equipmentNumber=" << lc.equipmentNumber; m_recvFromWls->participantLicenseChange(lc); } QUrl WlsDispatcher::webSocketUrl() const { const quint16 port = m_settings->settings()->value(QStringLiteral("WLS/webSocketListenPort"), 12346).toInt(); const QString addr = m_settings->settings()->value(QStringLiteral("WLS/webSocketHostname"), QStringLiteral("localhost")).toString(); return QUrl(QStringLiteral("ws://%1:%2/").arg(addr).arg(port)); } } // namespace WlsTetra