/** * Websocket interface to participant positions * $Id$ * $HeadURL$ * $Author$ * Created by Justus Hertel, SLSE, 2020-07-08 */ #include "web_socket_handler.h" #include "building_process.h" #include #include #include #include //#include namespace Buildings { WebSocketHandler::WebSocketHandler(const std::shared_ptr &buildingControlHandler, QObject *parent) : QObject(parent) , m_buildingControlHandler(buildingControlHandler) , m_webSocketServer(new QWebSocketServer(QStringLiteral("BuildingsSocket"), QWebSocketServer::NonSecureMode, this)) , m_logger(getLogger(QStringLiteral("WebSocketHandler"))) {} WebSocketHandler::~WebSocketHandler() { for (const auto& ws : qAsConst(m_webSockets)) { ws->disconnect(this); } m_webSockets.clear(); } bool WebSocketHandler::init(quint16 listenPort) { DEBUG_LOG(m_logger) << "init"; if (!m_webSocketServer->listen(QHostAddress::Any, listenPort)) { WARNING_LOG(m_logger) << "Can not listen on port " << listenPort << " - aborting"; return false; } connect(m_webSocketServer, &QWebSocketServer::newConnection, this, &WebSocketHandler::onNewConnection); INFO_LOG(m_logger) << "Listening on port " << m_webSocketServer->serverPort(); return true; } bool WebSocketHandler::init(const QPair &portRange) { for (quint16 currentPort = portRange.first; currentPort != portRange.second; ++currentPort) { if (init(currentPort)) return true; } return init(); } bool WebSocketHandler::sendTelegramInternal() const { DEBUG_LOG(m_logger) << "sendTelegramInternal"; QJsonObject obj; obj[QStringLiteral("participantId")] = 1; obj[QStringLiteral("equipmentNumber")] = 2; obj[QStringLiteral("lat")] = 3.0; obj[QStringLiteral("lon")] = 4.0; obj[QStringLiteral("height")] = 5.0; const QString jsonStr = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); bool ret = false; for (const auto &wsw : qAsConst(m_webSockets)) { if (wsw->sendTextMessage(jsonStr)) ret = true; } return ret; } bool WebSocketHandler::sendbuildingInfos() const { DEBUG_LOG(m_logger) << "sendbuildingInfos"; QJsonObject obj; QJsonArray arr; QMapIterator i(m_buildingControlHandler->getBuildings()); while (i.hasNext()) { i.next(); BuildingProcess* buildingProcess = i.value(); BuildingInfo buildingInfo = buildingProcess->buildingInfo(); quint16 port = buildingProcess->getWebsocketPort(); DEBUG_LOG(m_logger) << "key=" << i.key() << " port= " << port << " buildingInfo.name=" << buildingInfo.name; QJsonObject objIter; objIter[QStringLiteral("building_name")] = buildingInfo.name; objIter[QStringLiteral("port")] = port; arr.push_back(objIter); } obj[QStringLiteral("type")] = QStringLiteral("Buildings"); obj[QStringLiteral("data")] = arr; const QString jsonStr = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); bool ret = false; for (const auto &wsw : qAsConst(m_webSockets)) { if (wsw->sendTextMessage(jsonStr)) ret = true; } return ret; } void WebSocketHandler::onNewMessage(const QString &message) { DEBUG_LOG(m_logger) << "onNewMessage='" << message << "'"; DEBUG_LOG(m_logger) << "m_buildingControlHandler->m_buildings.size()=" << m_buildingControlHandler->getBuildings().size(); if (message.indexOf(QStringLiteral("buildingRequest")) > 0) { sendbuildingInfos(); } if (message.indexOf(QStringLiteral("triggerFlashlight")) > 0) { DEBUG_LOG(m_logger) << "triggerFlashlight" ; triggerFlashlight(message); } } QJsonObject WebSocketHandler::ObjectFromString(const QString& in) { QJsonObject obj; QJsonDocument doc = QJsonDocument::fromJson(in.toUtf8()); // check validity of the document if(!doc.isNull()) { if(doc.isObject()) { obj = doc.object(); } else { WARNING_LOG(m_logger) << "Document is not an object"; } } else { WARNING_LOG(m_logger) << "Invalid JSON...\n" << in ; } return obj; } void WebSocketHandler::triggerFlashlight(const QString &message) { DEBUG_LOG(m_logger) << "triggerFlashlight message=" << message; QJsonObject obj = ObjectFromString(message); QJsonObject dataObj = obj.value(QStringLiteral("data")).toObject(); int structureElementId = dataObj.value(QStringLiteral("structureElementId")).toInt(); QString hostnameBsm = dataObj.value(QStringLiteral("hostnameBsm")).toString(); DEBUG_LOG(m_logger) << "hostnameBsm=" << hostnameBsm << " structureElementId=" << structureElementId; } void WebSocketHandler::onNewConnection() { DEBUG_LOG(m_logger) << "onNewConnection"; QWebSocket *ws = m_webSocketServer->nextPendingConnection(); if (!ws) return; connect(ws, &QWebSocket::disconnected, this, &WebSocketHandler::onWebSocketDisconnected); connect(ws, &QWebSocket::textMessageReceived, this, &WebSocketHandler::onNewMessage); m_webSockets += ws; INFO_LOG(m_logger) << "New websocket connected"; } void WebSocketHandler::onWebSocketDisconnected() { DEBUG_LOG(m_logger) << "onWebSocketDisconnected"; QWebSocket *ws = qobject_cast(sender()); if (!ws) return; m_webSockets.removeAll(ws); ws->deleteLater(); INFO_LOG(m_logger) << "A websocket disconnected"; } bool WebSocketHandler::sendPosition() { if (!isConnected() || m_webSockets.isEmpty()) return false; return sendTelegramInternal(); } }