/** * MainHandler for TetraRadio * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-04-14 */ #include "data_manager.h" #include "settings.h" #include #include #include #include #include #include namespace WarehouseManagement { ClientMessageFactory::ClientMessageFactory(DataManager *dataManager) : LtsWebSocket::AbstractClientMessageFactory(getLogger("ClientMessageFactory")) , m_dataManager(dataManager) {} LtsWebSocket::AbstractClientMessage *ClientMessageFactory::createMessage(LtsWebSocket::ReplyHandler *client, const QString &message) { LtsWebSocket::AbstractClientMessage *result = checkAttributes(client, message); if (result) return result; if (m_type == LtsWebSocket::JsonKeys::ERROR_()) { ERROR_LOG(m_logger) << "Error in message: " << message; return nullptr; } if (m_type == WebSocketInterface::JsonKeys::EQUIPMENT_TYPES_REPLY()) result = new EquipmentTypesReply(m_dataManager, client, m_type, m_typeId, m_uuid, m_data); if (m_type == WebSocketInterface::JsonKeys::EXERCISES_REQUEST()) result = new ExercisesRequest(m_dataManager, client, m_type, m_typeId, m_uuid, m_data); if (m_type == WebSocketInterface::JsonKeys::PARTICIPANTS_REQUEST()) result = new ParticipantRequest(m_dataManager, client, m_type, m_typeId, m_uuid, m_data); if (m_type == WebSocketInterface::JsonKeys::PARTICIPANT_REGISTER_IN_EXCON_REQUEST()) result = new ParticipantRegisterInExconRequest(m_dataManager, client, m_type, m_typeId, m_uuid, m_data); if (!result) { ERROR_LOG(m_logger) << "message: " << message; Q_ASSERT(result); } return checkResult(client, message, result); } EquipmentTypesReply::EquipmentTypesReply(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data) : ClientMessage(dataManager, client, type, typeId, uuid, data) {} void EquipmentTypesReply::process() { ::EquipmentTypes eTypes = ::EquipmentTypes::fromJsonAll(m_data.toObject()); m_dataManager->handleEquipmentTypes(eTypes); // send per FTC to Ppm ex_0 } ExercisesRequest::ExercisesRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data) : ClientMessage(dataManager, client, type, typeId, uuid, data) {} void ExercisesRequest::process() { m_client->addReply(new ExerciseReply(m_dataManager->getWms2Ecc())); } ParticipantRequest::ParticipantRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data) : ClientMessage(dataManager, client, type, typeId, uuid, data) {} void ParticipantRequest::process() { const int requestedExerciseId = m_data.toObject()[::WebSocketInterface::JsonKeys::EXERCISE_ID()].toInt(); m_client->addReply(new ParticipantReply(m_dataManager->getWms2Ecc(), requestedExerciseId)); } ParticipantRegisterInExconRequest::ParticipantRegisterInExconRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data) : ClientMessage(dataManager, client, type, typeId, uuid, data) {} void ParticipantRegisterInExconRequest::process() { QJsonObject obj = m_data.toObject(); //qWarning() << "IN ParticipantRegisterInExconRequest: obj: " << obj; Registration reg = Registration::fromJson(obj); m_dataManager->registerParticipant(reg); } DataManager::DataManager(const std::shared_ptr &wms2ecc, const std::shared_ptr &ddsHandler, const std::shared_ptr &exHandler) : QObject() , m_messageFactory(nullptr) , m_clientConnection(nullptr) , m_wsReconnectTimer(new QTimer(this)) , m_wms2ecc(wms2ecc) , m_ddsHandler(ddsHandler) , m_exercisesHandler(exHandler) , m_logger(getLogger("MainHandler")) { connect(m_wsReconnectTimer, &QTimer::timeout, this, &DataManager::openWebSocket); m_messageFactory = new ClientMessageFactory(this); DEBUG_LOG(m_logger) << "WarehouseManagement/WmsServer = " << Settings::wmsServerName(); } DataManager::~DataManager() { closeWebSocket(); delete m_wsReconnectTimer; m_wsReconnectTimer = nullptr; delete m_messageFactory; } bool DataManager::init() { QTimer::singleShot(0, this, &DataManager::openWebSocket); return true; } void DataManager::openWebSocket() { closeWebSocket(); QWebSocket *wsSocket = new QWebSocket; m_clientConnection = new LtsWebSocket::ClientConnection(wsSocket, this); connect(m_clientConnection, &LtsWebSocket::ClientConnection::newTextMessage, this, &DataManager::newTextMessageFromClient); m_clientConnection->init(); connect(wsSocket, QOverload::of(&QWebSocket::error), this, &DataManager::onWebSocketError); connect(wsSocket, &QWebSocket::connected, this, &DataManager::onWebSocketConnected); connect(wsSocket, &QWebSocket::disconnected, this, &DataManager::onWebSocketDisconnected); int port = NGL::Connections::port(NGL::Connections::eConnection::ZSLV); QString url = QStringLiteral("ws://") + Settings::wmsServerName() + QStringLiteral(":") + QString::number(port); wsSocket->open(QUrl::fromEncoded(url.toLocal8Bit())); INFO_LOG(m_logger) << "Trying to listen on " << url; m_wsReconnectTimer->start(5000); } void DataManager::closeWebSocket() { if (m_clientConnection) { m_clientConnection->disconnect(this); m_clientConnection->deleteLater(); m_clientConnection = nullptr; } m_wsReconnectTimer->stop(); } void DataManager::onWebSocketError(QAbstractSocket::SocketError error) { Q_UNUSED(error) // TODO } void DataManager::onWebSocketConnected() { if (m_wsReconnectTimer) m_wsReconnectTimer->stop(); // no reconnect - we're connected now addEquipmentTypeRequest(); sendAllExercises(); sendAllParticipants(); } void DataManager::onWebSocketDisconnected() { if (m_wsReconnectTimer) m_wsReconnectTimer->start(5000); } bool DataManager::addEquipmentTypeRequest() { if (!m_clientConnection) return false; // should be 'addRequest' but does the same m_clientConnection->addReply(new EquipmentTypeRequest); return true; } bool DataManager::sendAllExercises() { if (!m_clientConnection) return false; // should be 'addRequest' but does the same m_clientConnection->addReply(new ExerciseReply(m_wms2ecc)); return true; } bool DataManager::sendAllParticipants() { if (!m_clientConnection) return false; const IWMS2ECC::exerciseMap exercises = m_wms2ecc->getExercises(); for (const IWMS2ECC::Exercise &ex : exercises) m_clientConnection->addReply(new ParticipantReply(m_wms2ecc, ex.id)); return true; } ExerciseReply::ExerciseReply(const std::shared_ptr &wms2ecc) : LtsWebSocket::ReplyMessage(WebSocketInterface::JsonKeys::EXERCISES_REPLY(), 1, QStringLiteral("zwei")) // Todo: Check whether typeId is correct { EXCON::Exercises convert; convert.setExercises(wms2ecc->getExercises()); m_jsonRepresentation.insert(LtsWebSocket::JsonKeys::DATA(), convert.toJsonAll()); } ExerciseUpdate::ExerciseUpdate(const IWMS2ECC::Exercise &data, DataModification modType) : LtsWebSocket::ReplyMessage(WebSocketInterface::JsonKeys::EXERCISE_UPDATE(), 2, QStringLiteral("zwei")) // Todo: Check whether typeId is correct { EXCON::Exercises convert; QJsonObject obj = convert.toJson(data); obj[::WebSocketInterface::JsonKeys::DATA_MODIFICATION()] = (int)modType; m_jsonRepresentation.insert(LtsWebSocket::JsonKeys::DATA(), obj); } ParticipantReply::ParticipantReply(const std::shared_ptr &wms2ecc, int exerciseId) : LtsWebSocket::ReplyMessage(WebSocketInterface::JsonKeys::PARTICIPANTS_REPLY(), 3, QStringLiteral("vier")) // Todo: Check whether typeId is correct { PlayerInfo convert; convert.setAllPlayerInfo(wms2ecc->getAllPlayers(exerciseId)); m_jsonRepresentation.insert(LtsWebSocket::JsonKeys::DATA(), convert.toJsonAll()); } ParticipantUpdate::ParticipantUpdate(const IWMS2ECC::PlayerInfo &pl, DataModification modType) : LtsWebSocket::ReplyMessage(WebSocketInterface::JsonKeys::PARTICIPANTS_UPDATE(), 4, QStringLiteral("fuenf")) // Todo: Check whether typeId is correct { QJsonObject obj = PlayerInfo::toJson(pl); obj[::WebSocketInterface::JsonKeys::DATA_MODIFICATION()] = (int) modType; m_jsonRepresentation.insert(LtsWebSocket::JsonKeys::DATA(), obj); } ParticipantRegisterInExconReply::ParticipantRegisterInExconReply(int exerciseId, qint32 participantId, ParticipantManagement::RegisterReturnValue retValue) : LtsWebSocket::ReplyMessage(WebSocketInterface::JsonKeys::PARTICIPANT_REGISTER_IN_EXCON_REPLY(), 5, QStringLiteral("zwei")) // Todo: Check whether typeId is correct { QJsonObject obj; obj[::WebSocketInterface::JsonKeys::EXERCISE_ID()] = exerciseId; obj[::WebSocketInterface::JsonKeys::PARTICIPANT_ID()] = participantId; obj[::WebSocketInterface::JsonKeys::REGISTRATION_RETURN_VALUE()] = (int) retValue.underlying(); m_jsonRepresentation.insert(LtsWebSocket::JsonKeys::DATA(), obj); } void DataManager::handleEquipmentTypes(const ::EquipmentTypes &eTypes) { const IWMS2ECC::equipTypeMap equipTypeMap = eTypes.getEquipmentTypes(); INFO_LOG(m_logger) << "equipTypeMap size: " << equipTypeMap.size(); ParticipantManagement::ModifyEquipmentTypeDataRequest request; request.deleteAll(true); auto &dataVec = request.data(); dataVec.reserve(equipTypeMap.size()); for (const IWMS2ECC::EquipmentType &et : equipTypeMap) { ParticipantManagement::EquipmentType pEt; pEt.id(et.id); pEt.name(et.name.toStdString()); pEt.minEquipNo(et.minEquipNo); pEt.maxEquipNo(et.maxEquipNo); pEt.traPlayerTypeId(et.taPlayerTypeId); pEt.deletedInWms(et.deletedInWMS); pEt.traVulnerabilityModelId(et.taVulnerabilityModelId); ParticipantManagement::WmsTypeClass wmsTypeClass = static_cast(et.specialType); pEt.wmsTypeClass(wmsTypeClass); dataVec.push_back(std::move(pEt)); } INFO_LOG(m_logger) << "dataVec size: " << dataVec.size() << ", " << request; m_ddsHandler->ppmFtc()->modifyEquipmentTypeDataRequest(request, this); } void DataManager::onModifyEquipmentTypeDataReply(const Core::FunctionReplyObject &replyObject) { if (replyObject.error()) ERROR_LOG(m_logger) << "Error while modifying equipmentType: " << replyObject.str(); else INFO_LOG(m_logger) << "onModifyEquipmentTypeDataReply ok"; } void DataManager::newTextMessageFromClient(LtsWebSocket::ClientConnection *client, const QString &message) { LtsWebSocket::AbstractClientMessage *clientMessage = nullptr; auto result = m_messageFactory->parseMessage(message); if (QJsonParseError::NoError == result.error) clientMessage = m_messageFactory->createMessage(client, message); else { WARNING_LOG(m_logger) << "Could not parse incoming message: '" << message << "', error: " << result.errorString(); clientMessage = new LtsWebSocket::InvalidMessage(client, QString(), QStringLiteral("Got message which is not JSON conform")); } if (clientMessage) clientMessage->process(); delete clientMessage; } void DataManager::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType, int exerciseId) { if (!m_clientConnection || !m_wms2ecc) return; DEBUG_LOG(m_logger) << "partyId: " << data.partyId() << "participantId: " << data.id(); IWMS2ECC::PlayerInfo pl = m_wms2ecc->convert(data, exerciseId); pl.playerId = (exerciseId* 1000000) + pl.playerId; m_clientConnection->addReply(new ParticipantUpdate(pl, modType)); } void DataManager::onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType) { if (!m_clientConnection) return; INFO_LOG(m_logger) << "IN onExerciseChanged: ExerciseUpdate: id = " << data.id(); IWMS2ECC::Exercise exeData = IWMS2ECC_Impl::convert(data); m_clientConnection->addReply(new ExerciseUpdate(exeData, modType)); } void DataManager::onRegistrationReturnValue(int exerciseId, qint32 participantId, ParticipantManagement::RegisterReturnValue retValue) { m_clientConnection->addReply(new ParticipantRegisterInExconReply(exerciseId, participantId, retValue)); } void DataManager::registerParticipant(const Registration ®) { ParticipantManagement::ParticipantAssignState state = IWMS2ECC_Impl::convert(reg.getAssignment()); INFO_LOG(m_logger) << "ParticipantAssignState: " << state; INFO_LOG(m_logger) << "Registration: participant: " << reg.getPlayerId() << ", exerciseId: " << reg.getExerciseId(); dds::core::optional equipNo; dds::core::optional identification; dds::core::optional info; if (reg.isEquipNoSet()) equipNo.set(reg.getEquipNo()); if (reg.isAliasSet()) identification.set(reg.getAlias()); if (reg.isInfoSet()) info.set(reg.getInfo()); m_exercisesHandler->registerParticipant(reg.getExerciseId(), reg.getPlayerId(), state, equipNo, identification, info); } } // namespace WarehouseManagement