/** * Handler for message data request * $Id$ * $HeadURL$ * $Author$ * Created by hjl, SLSE, 2016-10-12 */ #include "handler_operator_message.h" namespace Messaging { HandlerOperatorMessage::HandlerOperatorMessage(const std::shared_ptr &ddsHandler, const std::shared_ptr &db, const std::shared_ptr &exercisesHandler, QObject *parent) : QObject(parent) , CreateOperatorMessageRequestHandler(ddsHandler->fts()) , ModifyOperatorMessageRequestHandler(ddsHandler->fts()) , m_ddsHandler(ddsHandler) , m_db(db) , m_exercisesHandler(exercisesHandler) , m_logger(getLogger("HandlerOperatorMessage")) { } // end of ctor() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool HandlerOperatorMessage::init() { INFO_LOG(m_logger) << "Start HandlerOperatorMessage."; // read data from db-table 'msg_message_data' // add to internal buffer auto cbMsgData = [this] (const Database::MsgMessageData &data) { if (data.isDeleted) return; m_dbOperatorMessageData.insert(data.id, data); m_ddsHandler->dts()->publish(toDdsData(data)); }; if (!m_db->select(cbMsgData)) // TODO (CE): nicht alle selektieren, nur die, die nicht gelöscht sind { ERROR_LOG(m_logger) << "Error reading data from database 'msg_message_data'!"; return false; } // Signal von tabDtc verbinden ( void equipmentMessageChanged(const TrainingAreaBase::EquipmentMessage &data, DataModification modType)) // enableEquipmentMessage zum abbonieren der EquipmentMessages // Alle derzeit vorhandenen Messages auslesen (equipmentMessages()) und verarbeiten connect(m_exercisesHandler.get(), &ExercisesHandler::messageFromTrainingArea, this, &HandlerOperatorMessage::onMesssageFromTrainingArea); //OperatorManagement::Interface::Dtc m_opmDtc = OperatorManagement::Interface::Dtc::create(m_ddsHandler->ddsConnector()); // Operator Management to get Username from operator connect(m_opmDtc.get(), &OperatorManagement::Interface::Dtc::userChanged, this, &HandlerOperatorMessage::onOperatorChanged); m_opmDtc->enableUser(); return true; } // end of init() //----------------------------------------------------------------------------- void HandlerOperatorMessage::onCreateOperatorMessageRequest(const rti::core::SampleIdentity &cookie, const CreateOperatorMessageRequest &request) { DEBUG_LOG(m_logger) << "onCreateOperatorMessageRequest" << request; auto ret = createOperatorMessageRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_ddsHandler->fts()->createOperatorMessageReply(cookie, ret); } Core::FunctionReplyObject HandlerOperatorMessage::createOperatorMessageRequest(const CreateOperatorMessageRequest &request) { // 1. In DB eintragen // 2. publishen // 3. in interne Verwaltung eintragen // 4. mit ok antworten Database::MsgMessageData newMsg; newMsg.timeStamp = m_ddsHandler->currentPartitionTime(); newMsg.senderId = request.senderId(); INFO_LOG(m_logger) << "newMsg.senderId=" << newMsg.senderId; newMsg.subject = QString::fromStdString(request.subject()); newMsg.message = QString::fromStdString(request.message()); newMsg.senderType = request.senderType(); INFO_LOG(m_logger) << "newMsg.senderType.underlying()=" << newMsg.senderType.underlying(); newMsg.senderText = toAddressStr(newMsg.senderType, newMsg.senderId, request.exerciseId()); newMsg.recipientType = request.recipientType(); newMsg.exerciseId = request.exerciseId(); QString recipientText; for (int32_t i : request.recipientIds()) { recipientText.append(toAddressStr(newMsg.recipientType, i, newMsg.exerciseId)); recipientText.append(QString::fromStdString(" ")); } newMsg.isRead = false; newMsg.isDeleted = false; INFO_LOG(m_logger) << "newMsg.senderType=" << newMsg.senderType << " newMsg.receiverType=" << newMsg.recipientType; // Insert message for sender newMsg.recipientId = 0; newMsg.recipientText = recipientText; // Only Operator messages Core::FunctionReplyObject ret(newMsg.id); if (newMsg.senderType == Messaging::AddressType_def::type::Operator) ret = insertInDbAndPublish(newMsg); const int correspondingOutboxMsgId = ret.id(); if (!ret.error() ) { INFO_LOG(m_logger) << "insert message for each receiver"; // Insert message for each receiver //newMsg.senderId = 0; WHY? //if (correspondingOutboxMsgId > 0) // messages received from TETRA dont have a corresponding outbox id newMsg.correspondingOutboxMessageId = correspondingOutboxMsgId; // can be also 0 - from TETRA for (const auto recipientId : request.recipientIds()) { newMsg.recipientId = recipientId; newMsg.recipientText = toAddressStr(newMsg.recipientType, newMsg.recipientId, newMsg.exerciseId); INFO_LOG(m_logger) << "recipientId: " << newMsg.recipientId; ret = insertInDbAndPublish(newMsg); if (ret.error()) break; } } if (ret.error()) WARNING_LOG(m_logger) << ret(); return ret; } // end of onCreateOperatorMessageRequest() //----------------------------------------------------------------------------- void HandlerOperatorMessage::onModifyOperatorMessageRequest(const rti::core::SampleIdentity &cookie, const ModifyOperatorMessageRequest &request) { // 1. schauen ob es diese Message überhaupt gibt // 2. aktualisieren in DB // 3. interne Verwaltung aktualisieren // 4. neu publishen bzw. von dds löschen // 5. mit ok antworten auto it = m_dbOperatorMessageData.find(request.id()); if (it == m_dbOperatorMessageData.end()) { const auto ret = Core::FunctionReplyObject(0, tr_lts("dds", "Could not find message with id %1")).arg(request.id()); m_ddsHandler->fts()->modifyOperatorMessageReply(cookie, ret); return; } Database::MsgMessageData data = it.value(); data.isDeleted = request.isDeleted(); data.isSend = request.isSend(); data.isRead = request.isRead(); const auto ret = modifyDbAndPublish(data); m_ddsHandler->fts()->modifyOperatorMessageReply(cookie, ret); } // end of onModifyOperatorMessageRequest() //----------------------------------------------------------------------------- OperatorMessage HandlerOperatorMessage::toDdsData(const Database::MsgMessageData &dbData) { OperatorMessage ddsData; ddsData.id(dbData.id); ddsData.senderId(dbData.senderId); ddsData.recipientId(dbData.recipientId); ddsData.exerciseId(dbData.exerciseId); ddsData.subject(dbData.subject.toStdString()); ddsData.message(dbData.message.toStdString()); ddsData.recipientText(dbData.recipientText.toStdString()); ddsData.senderText(dbData.senderText.toStdString()); ddsData.isRead(dbData.isRead); ddsData.isSend(dbData.isSend); ddsData.isDeleted(dbData.isDeleted); ddsData.senderType(dbData.senderType); ddsData.recipientType(dbData.recipientType); ddsData.correspondingOutboxMessageId(dbData.correspondingOutboxMessageId); // can also be 0 ddsData.timeStamp(dbData.timeStamp); return ddsData; } // end of toDdsData() //----------------------------------------------------------------------------- // Insert in db and publish Core::FunctionReplyObject HandlerOperatorMessage::insertInDbAndPublish(Database::MsgMessageData newMsg) { // Length Check: if (newMsg.recipientType == Messaging::AddressType_def::type::ObserverController) { newMsg.subject = newMsg.subject.left(m_maxSubjectLength); newMsg.message = newMsg.message.left(m_maxOcContentLength); } if (newMsg.recipientType == Messaging::AddressType_def::type::Participant) { newMsg.subject = newMsg.subject.left(m_maxSubjectLength); newMsg.message.clear(); } DEBUG_LOG(m_logger) << "newMsg.senderId = " << newMsg.senderId; if (!m_db->insert(newMsg)) return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding message to database")); m_dbOperatorMessageData.insert(newMsg.id, newMsg); if ((newMsg.recipientType == Messaging::AddressType_def::type::ObserverController) || (newMsg.recipientType == Messaging::AddressType_def::type::Participant)) { int32_t equipmentNumber = m_exercisesHandler->findEquipmentNumber(newMsg.recipientId, newMsg.exerciseId); int32_t participantId = newMsg.recipientId; INFO_LOG(m_logger) << "equipmentNumber: " << equipmentNumber << ", participantId: " << participantId << ", exerciseId: " << newMsg.exerciseId; // Length Check: const auto subject = newMsg.subject.toStdString(); const auto message = newMsg.message.toStdString(); INFO_LOG(m_logger) << "Message to OC: subject =" << subject << " Message =" << message; // only send to Tetra: if (newMsg.recipientId > 0) { int senderId = m_dbOperatorMessageData[newMsg.correspondingOutboxMessageId].senderId; AddressType senderType = m_dbOperatorMessageData[newMsg.correspondingOutboxMessageId].senderType; INFO_LOG(m_logger) << "SendEquipmentMessageRequest id =" << newMsg.id; INFO_LOG(m_logger) << " equipmentNumber=" << equipmentNumber << " participantId=" << participantId << " newMsg.id=" << newMsg.id << " newMsg.senderId=" << senderId << " newMsg.adressType=" << senderType << " subject=" << subject << " message=" << message; static int s_requestId = 1; if (newMsg.recipientType == Messaging::AddressType_def::type::ObserverController) { INFO_LOG(m_logger) << "Send to OC senderId=" << newMsg.senderId << " sendertype: " << newMsg.senderType << " subject " << subject; m_exercisesHandler->sendOcEquipmentMessage({s_requestId++, {equipmentNumber}, //newMsg.id, newMsg.senderId, newMsg.senderType, subject, message }); } else { m_exercisesHandler->sendEquipmentMessage({s_requestId++, {equipmentNumber}, newMsg.id, senderId, subject, message }); } } //m_ddsHandler->tabFtc()->sendEquipmentMessageRequest(...); //onsendEquipmentMessageReply implementieren und dort gelesen = true; } m_ddsHandler->dts()->publish(toDdsData(newMsg)); INFO_LOG(m_logger) << "insertInDbAndPublish id=" << newMsg.id; if (newMsg.recipientType == Messaging::AddressType_def::type::ObserverController && newMsg.recipientId > 0) { INFO_LOG(m_logger) << "O/C-Message in Member-Variable kopieren: id = " << newMsg.id; } return Core::FunctionReplyObject(newMsg.id); } // end of insertInDbAndPublish() // Modify db and publish Core::FunctionReplyObject HandlerOperatorMessage::modifyDbAndPublish(const Database::MsgMessageData &modMsg) { INFO_LOG(m_logger) << "modifyDbAndPublish" << " id=" << modMsg.id << " isDeleted=" << modMsg.isDeleted << " modMsg.isRead=" << modMsg.isRead << " modMsg.isSend=" << modMsg.isSend << " modMsg.sender=" << modMsg.senderId << " modMsg.receiver=" << modMsg.recipientId; if (!m_db->update(modMsg)) return Core::FunctionReplyObject(modMsg.id, tr_lts("dds", "Error updating message with id %1 to database")).arg(modMsg.id); m_dbOperatorMessageData[modMsg.id] = modMsg; if (modMsg.isDeleted) { INFO_LOG(m_logger) << "Remove LTS_OperatorMessage from DDS id=" << modMsg.id; m_ddsHandler->dts()->removeOperatorMessageByKey(modMsg.id); } else m_ddsHandler->dts()->publish(toDdsData(modMsg)); return Core::FunctionReplyObject(modMsg.id); } // end of modifyDbAndPublish() // Receive from Tetra void HandlerOperatorMessage::onMesssageFromTrainingArea(const TrainingAreaBase::EquipmentMessage &data) { INFO_LOG(m_logger) << "************ onMesssageFromTrainingArea ********************"; onEquipmentMessageChanged(data, DataModification::eAdded); } // Receive from Tetra void HandlerOperatorMessage::onEquipmentMessageChanged(const TrainingAreaBase::EquipmentMessage &data, const DataModification modType) { if (modType == DataModification::eRemoved) return; CreateOperatorMessageRequest request; DEBUG_LOG(m_logger) << "onEquipmentMessageChanged: " << data; request.senderType() = Messaging::AddressType_def::type::Participant; request.senderId(data.sender()); DEBUG_LOG(m_logger) << "request.senderId = " << request.senderId(); request.recipientType(Messaging::AddressType_def::type::Operator); request.recipientIds().push_back(data.receiver()); request.subject() = data.subject(); request.message() = data.text(); createOperatorMessageRequest(request); // Todo Fragen, ob die Meldung vom DDS geloescht werden soll. } // end of onEquipmentMessageChanged void HandlerOperatorMessage::onOperatorChanged(const OperatorManagement::User &data) { DEBUG_LOG(m_logger) << "************** onOperatorChanged "; m_operatorMap.insert(data.id(), data.name()); } // end of onOperatorChanged QString HandlerOperatorMessage::toAddressStr(const AddressType addressType, const qint32 addressId, int exerciseId) { QString result; switch (addressType.underlying()) { case AddressType::Operator: // nicht per Request sondern hier aus OPM holen result = QString::fromStdString(m_operatorMap.value(addressId, "Unknown Operator")); break; case AddressType::ObserverController: { int equipNumber = m_exercisesHandler->findEquipmentNumber(addressId, exerciseId); if (equipNumber > 0) result += QStringLiteral(" - ") + QString::number(equipNumber); break; } case AddressType::Participant: result = QLatin1String("Participant:") + QString::number(addressId); break; default: result = QString::fromStdString("No valid addressType:"); QString numberStr ; numberStr.setNum(addressType.underlying()); result.append(numberStr); } return result; } // end of toAddressStr } // namespace Messaging