/** * @RDE_HEADER@ * The ClientMessage class is an abstract base class for concrete ClientMessage objects * $Id$ * $HeadURL$ * $Author$ * Created by Hannes Fritsche, SLSE, 2017-09-07 */ #include "client_message.h" #include "reply_message.h" #include "exercise_manager.h" #include "WebSocketInterface/Messages/message_transmitter.h" #include "WebSocketInterface/Messages/reply_message.h" #include "WebSocketInterface/json_keys.h" #include #include #include /* *python testing: import websocket import json import time ws = websocket.create_connection("ws://127.0.0.1:2081") d = { 'type' : 'getEssentials', 'uuid': 'blub' } ws.send(json.dumps(d)) d = { 'type' : 'getConfigCNR', 'uuid': 'blub' } ws.send(json.dumps(d)) d = { 'type' : 'getPositionsCNR', 'uuid': 'blub', 'data': {'repeat': 10}} ws.send(json.dumps(d)) while True: ws.recv() */ namespace CombatNetRadio { namespace WebSocketInterface { using namespace JsonKeys; namespace Messages { // ####### ClientMessage begin ####### ClientMessage *ClientMessage::create(const QString &message, NGL::INGLLogger &logger) { ClientMessage *result = nullptr; QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error); if (error.error != QJsonParseError::NoError) { ERROR_LOG(logger) << "Got message which is not JSON conform: " << message; return new InvalidMessage(QString(), QStringLiteral("Got message which is not JSON conform")); } QJsonObject obj = doc.object(); QJsonObject dataPart = obj.value(DATA()).toObject(); QString type = obj.value(TYPE()).toString(); QString uuid = obj.value(UUID_()).toString(); if (type.isEmpty()) { ERROR_LOG(logger) << "Got message without type: " << message; result = new InvalidMessage(uuid, QStringLiteral("Message has no type")); } else if (type == ERROR_() && dataPart.contains(ERROR_MESSAGE()) && dataPart.contains(ERROR_CLASS()) && dataPart.contains(UUID_())) { ERROR_LOG(logger) << "Got error message: " << QJsonDocument(dataPart).toJson(); return nullptr; } else if (uuid.isEmpty()) { ERROR_LOG(logger) << "Got message without uuid: " << message; result = new InvalidMessage(QString(), QStringLiteral("Got message without uuid")); } else if (type == GET_ESSENTIALS()) result = new GetEssentialsMessage(type, uuid, dataPart); else if (type == GET_CONFIG_CNR()) result = new GetConfigCnrMessage(type, uuid, dataPart); else if (type == GET_POSITIONS_CNR()) result = new GetPositionsCnrMessage(type, uuid, dataPart); else if (type == ALIVE_REQUEST()) result = new AliveRequest(type, uuid, dataPart); else if (type == OK()) result = new OkMessageC(type, uuid, dataPart); else if (type == CONFIG_CNR()) result = new ConfigCnrMessageC(type, uuid, dataPart); if (result == nullptr) { ERROR_LOG(logger) << "Got message with invalid type: " << message; result = new InvalidMessage(uuid, QStringLiteral("Invalid type")); } if (!result->hasValidData()) { ERROR_LOG(logger) << "Got message with invalid data part: " << message; delete result; result = new InvalidMessage(uuid, QStringLiteral("Has invalid data part")); } return result; } ClientMessage::ClientMessage(const QString &type, const QString &uuid, const QJsonObject &data) : m_type(type) , m_uuid(uuid) , m_data(data) { } // ####### ClientMessage end ####### // ####### InvalidMessage begin ####### void InvalidMessage::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { Q_UNUSED(exerciseManager); ErrorMessage::ErrorData errorData; errorData.errorClass = 1; // ?????????? errorData.errorMessage = m_errorText; errorData.uuid = m_uuid; transmitter->addMessage(ErrorMessage(errorData)); } bool InvalidMessage::hasValidData() const { // always true because there is no data part return true; } // ####### InvalidMessage end ####### // ####### GetEssentialsMessage begin ####### void GetEssentialsMessage::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { using namespace Messages; transmitter->addMessage(exerciseManager->trainingAreaData(m_uuid)); for (const ReplyMessage ¤tMessage : exerciseManager->radioStations(m_uuid)) transmitter->addMessage(currentMessage); QString requester = m_data.value(REQUESTER()).toString(); bool isActiveClient = m_data.value(ISACTIVECLIENT()).toBool(); transmitter->addMessage(exerciseManager->configCnr(m_uuid)); exerciseManager->onConfigCnrSent((qint64) transmitter, m_uuid, requester, isActiveClient); } // ####### GetEssentialsMessage end ####### // ####### GetConfigCnrMessage begin ####### void GetConfigCnrMessage::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { QString requester = m_data.value(REQUESTER()).toString(); bool isActiveClient = m_data.value(ISACTIVECLIENT()).toBool(); transmitter->addMessage(exerciseManager->configCnr(m_uuid)); exerciseManager->onConfigCnrSent((qint64) transmitter, m_uuid, requester, isActiveClient); } // ####### GetConfigCnrMessage end ####### void OkMessageC::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { exerciseManager->onConfigCnrReceived((qint64) transmitter, m_uuid); } // ####### GetPositionsCnrMessage begin ####### void GetPositionsCnrMessage::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { transmitter->addMessage(exerciseManager->positionsCnr(m_uuid)); int updateInterval = m_data.value(REPEAT()).toInt(); if (updateInterval > 0) exerciseManager->setPositionsUpdateInterval(std::chrono::seconds(updateInterval)); else exerciseManager->stopPositionsUpdate(); } bool GetPositionsCnrMessage::hasValidData() const { return m_data.contains(REPEAT()); } // ####### GetPositionsCnrMessage end ####### // ####### GetPositionsCnrMessage begin ####### void AliveRequest::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { Q_UNUSED(exerciseManager); transmitter->addMessage(AliveResponse(m_uuid)); } void ConfigCnrMessageC::process(ExerciseManager *exerciseManager, MessageTransmitter *transmitter) { exerciseManager->onConfigCnrProcessed((qint64) transmitter, m_uuid, m_data); } // ####### GetPositionsCnrMessage end ####### } // namespace Messages } // namespace WebSocketInterface } // namespace CombatNetRadio