/** * Handler for message data request * $Id$ * $HeadURL$ * $Author$ * Created by hjl, SLSE, 2016-10-12 */ #include "handler_configure_alarms.h" #include #include "initialization.h" #include #include #include #include #include #include namespace AlarmManagement { static AlarmConfig toDds(const Database::AlmConfig &data) { AlarmConfig almConfig; almConfig.id = data.id; almConfig.operatorId = data.operatorId; if (data.participantId.isValid()) almConfig.participantId = data.participantId.toInt(); else almConfig.participantId = 0; almConfig.eventTypeId = data.eventTypeId; almConfig.messageWindow = data.messageWindow; almConfig.global = data.global; almConfig.vulnerabilityState = data.vulnerabilityState; almConfig.setMarker = data.setMarker; return almConfig; } HandlerConfigureAlarms::HandlerConfigureAlarms(Initialization *mainHandler) : QObject() , ConfigureAlarmsRequestHandler(mainHandler->dds()->ftsAlm()) , m_mainHandler(mainHandler) , m_logger(getLogger("HandlerConfigureAlarms")) , m_windowIndex(0) { } // end of ctor() //----------------------------------------------------------------------------- HandlerConfigureAlarms::~HandlerConfigureAlarms() { } // end of dtor() //----------------------------------------------------------------------------- bool HandlerConfigureAlarms::init() { INFO_LOG(m_logger) << "Start HandlerConfigureAlarms."; auto dtcEem = m_mainHandler->dds()->dtcEem(); connect(dtcEem.get(), &ExerciseEventManagement::Interface::Dtc::eventChanged, this, &HandlerConfigureAlarms::onEventChanged); // publish data from db-table 'alm_config' auto cb = [this](const Database::AlmConfig & data) { DEBUG_LOG(m_logger) << "restore AlarmConfig from DB data: id=" << data.id << " operatorId=" << data.operatorId << " participantId=" << data.participantId.toInt() << " global=" << data.global << " eventTypeId=" << data.eventTypeId << " setMarker=" << data.setMarker << " messageWindow=" << data.messageWindow << " vulnerabilityState=" << data.vulnerabilityState; m_mainHandler->dds()->dtsAlm()->publish(toDds(data)); m_alarms.insert(data.id, data); }; if (!m_mainHandler->db()->select(cb)) { ERROR_LOG(m_logger) << "Error reading data from database 'alm_config'!"; return false; } return true; } // end init() void HandlerConfigureAlarms::removeAlarmConfig(int operatorId, int participantId, int eventTypeId) { DEBUG_LOG(m_logger) << "removeAlarmConfig m_alarms.size=" << m_alarms.size() << " operatorId=" << operatorId << " participantId=" << participantId << " eventTypeId=" << eventTypeId; // Find Key QMapIterator i(m_alarms); while (i.hasNext()) { i.next(); DEBUG_LOG(m_logger) << "key= " << i.key() << ": " << " operatorId=" << i.value().operatorId << " participantId=" << i.value().participantId.toInt() << " eventTypeId=" << i.value().eventTypeId; if ((operatorId == i.value().operatorId) && (participantId == i.value().participantId) && (eventTypeId == static_cast(ProjectDataManagement::PdmEventType::EventType_Unknown) || eventTypeId == static_cast(i.value().eventTypeId))) { const int key = i.key(); DEBUG_LOG(m_logger) << "found alarm to remove: " << key << ", eventTypeId: " << eventTypeId; m_mainHandler->db()->removeAlmConfig(key); m_mainHandler->dds()->dtsAlm()->removeAlarmConfigByKey(key); m_alarms.remove(key); // is ok, QMapIterator work on a copy } } } void HandlerConfigureAlarms::removeGlobalAlarmConfig(int operatorId) { DEBUG_LOG(m_logger) << "removeAlarmConfig m_alarms.size=" << m_alarms.size(); // Find Key QMapIterator i(m_alarms); while (i.hasNext()) { i.next(); DEBUG_LOG(m_logger) << "key= " << i.key() << " participantId=" << i.value().participantId.toInt(); if ((operatorId == i.value().operatorId) && (i.value().participantId.toInt()) == 0) { const int key = i.key(); DEBUG_LOG(m_logger) << "found alarm to remove: " << key; m_mainHandler->db()->removeAlmConfig(key); m_mainHandler->dds()->dtsAlm()->removeAlarmConfigByKey(key); m_alarms.remove(key); // is ok, QMapIterator work on a copy } } } //----------------------------------------------------------------------------- void HandlerConfigureAlarms::onConfigureAlarmsRequest(const rti::core::SampleIdentity &cookie, const ConfigureAlarmsRequest &request) { DEBUG_LOG(m_logger) << "onConfigureAlarmsRequest " << request; if (request.participantIds.size() == 0) { Core::FunctionReplyObject ret(0, tr_lts("dds", "Error adding ConfigureAlarms to database. There were no participants given.")); m_mainHandler->dds()->ftsAlm()->configureAlarmsReply(cookie, ret); return; } if (request.remove) { // remove only this one Alarm, not all types of the participant for operator // in DB, // from DDS DEBUG_LOG(m_logger) << "request.remove()"; if (request.participantIds.size() > 0 && request.alarms.size() > 0) { int participantId = request.participantIds[0]; int eventTypeId = static_cast(request.alarms[0].eventTypeId); DEBUG_LOG(m_logger) << "removeAlarmConfig(request.operatorId()=" << request.operatorId << " participantId=" << participantId << " eventTypeId=" << eventTypeId; removeAlarmConfig(request.operatorId, participantId, eventTypeId); } } else { // remove old configuration for (int participantId : request.participantIds) { DEBUG_LOG(m_logger) << "remove old configuration participantId=" << participantId; removeAlarmConfig(request.operatorId, participantId, 0); } if ( request.global) { removeGlobalAlarmConfig(request.operatorId); } for (int participantId : request.participantIds) { DEBUG_LOG(m_logger) << "participantId: " << participantId; for (const AlarmManagement::AlarmAction &action : request.alarms) { DEBUG_LOG(m_logger) << "action: " << action; AlarmManagement::AlarmConfig almConfig; almConfig.operatorId = request.operatorId; almConfig.participantId = participantId; almConfig.eventTypeId = action.eventTypeId; almConfig.messageWindow = action.messageWindow; almConfig.vulnerabilityState = action.vulnerabilityState; almConfig.setMarker = action.setMarker; almConfig.global = request.global; Database::AlmConfig newConfig; newConfig.operatorId = request.operatorId; if (participantId != 0) newConfig.participantId = participantId; newConfig.eventTypeId = action.eventTypeId; newConfig.messageWindow = action.messageWindow; newConfig.vulnerabilityState = action.vulnerabilityState; newConfig.setMarker = action.setMarker; newConfig.global = request.global; if (!m_mainHandler->db()->insert(newConfig)) { Core::FunctionReplyObject ret(0, tr_lts("dds", "Error adding ConfigureAlarms to database.")); m_mainHandler->dds()->ftsAlm()->configureAlarmsReply(cookie, ret); } DEBUG_LOG(m_logger) << "m_dbAlmConfig.insert id=" << newConfig.id; almConfig.id = newConfig.id; m_alarms.insert(newConfig.id, newConfig); m_mainHandler->dds()->dtsAlm()->publish(almConfig); } } } m_mainHandler->dds()->ftsAlm()->configureAlarmsReply(cookie, Core::FunctionReplyObject()); } // end onConfigureAlarmsRequest() //----------------------------------------------------------------------------- void HandlerConfigureAlarms::onEventChanged(const ExerciseEventManagement::Event &eventData, DataModification modType) { DEBUG_LOG(m_logger) << "onParticipantEventChanged participantId=" << eventData.participantId; if (modType == DataModification::eRemoved || modType == DataModification::eModified) return; DEBUG_LOG(m_logger) << "onParticipantEventChanged verarbeiten m_alarms.size =" << m_alarms.size(); ExerciseEventManagement::Event eventDatalocal = eventData; QVector participants; QSet sentEventToOperator; // toBool() returns false if attribute does not exist const QJsonObject eventObject = getEventProperties(eventDatalocal); const bool friendlyFireBool = eventObject.value(QStringLiteral("FriendlyFire")).toBool(); const int vulnerabilityState = eventObject.value(QStringLiteral("vulnerabilityState")).toInt(); // Schleife ueber jede Konfiguration, // pruefen, ob eventTypeId == EventTypeId // Schleife ueber jeden Participant in der Konfiguration // Vergleich Participant-ID Event mit Konfiguration Event // Wenn ja, Alarm an operatorId schicken for (const Database::AlmConfig &alarm : std::as_const(m_alarms)) { { /*DEBUG_LOG(m_logger) << " alarmConfigItem.id=" << alarm.id << " alarmConfigItem.participantId=" << alarm.participantId << " alarmConfigItem.eventTypeId=" << alarm.eventTypeId << " eventDatalocal.eventTypeId()=" << eventDatalocal.eventTypeId().underlying() << " alarm.operatorId=" << alarm.operatorId << " friendyFire =" << friendlyFireBool;*/ if ((alarm.eventTypeId == eventDatalocal.eventTypeId) || (alarm.eventTypeId == ProjectDataManagement::PdmEventType::EventType_FriendlyFire && friendlyFireBool)) { if (friendlyFireBool && eventDatalocal.eventTypeId == ProjectDataManagement::PdmEventType::EventType_FireEvent) eventDatalocal.eventTypeId = ProjectDataManagement::PdmEventType::EventType_FriendlyFire; participants.clear(); if (alarm.participantId.isValid()) participants = m_mainHandler->hdlParticipant()->getRecursiveInferiorIds(alarm.participantId.toInt()); else participants.append(0); for (int participantId : std::as_const(participants)) { bool allVulnerabilityStates = alarm.vulnerabilityState == -1; bool vulnerabilityCheck = vulnerabilityState == alarm.vulnerabilityState; bool globalAlarm = participantId == 0; DEBUG_LOG(m_logger) << " allVulnerabilityStates=" << allVulnerabilityStates << " vulnerabilityCheck=" << vulnerabilityCheck << " participantId=" << participantId << " eventDatalocal.participantId=" << eventDatalocal.participantId; if (((allVulnerabilityStates || vulnerabilityCheck) && (participantId == eventDatalocal.participantId)) || globalAlarm) { if (sentEventToOperator.contains(alarm.operatorId)) { DEBUG_LOG(m_logger) << "Event " << eventDatalocal.eventTypeId << " already handled for Operator:" << alarm.operatorId; continue; } sentEventToOperator += alarm.operatorId; if (alarm.messageWindow) { DEBUG_LOG(m_logger) << "send Window to Operator:" << alarm.operatorId; sendWindow(eventDatalocal, alarm); } if (alarm.setMarker) { DEBUG_LOG(m_logger) << "set Marker to Operator:" << alarm.operatorId; sendMarker(eventDatalocal, alarm); } } } } } } } // end onParticipantEventChanged void HandlerConfigureAlarms::sendWindow(const ExerciseEventManagement::Event &eventData, const Database::AlmConfig &config) { AlarmManagement::Notification wi; QJsonObject eventObject = getEventProperties(eventData); QJsonObject obj; wi.id = m_windowIndex; wi.operatorId = config.operatorId; wi.time = eventData.sampleTime; wi.eventId = eventData.id; if (eventData.eventTypeId == ProjectDataManagement::PdmEventType::EventType_CrossGlobalBorderline || eventData.eventTypeId == ProjectDataManagement::PdmEventType::EventType_CrossLocalBorderline) { if (eventObject.contains(QStringLiteral("Global"))) obj[QStringLiteral("Global")] = eventObject.value(QStringLiteral("Global")); } if (eventObject.contains(QStringLiteral("FriendlyFire"))) obj[QStringLiteral("FriendlyFire")] = eventObject.value(QStringLiteral("FriendlyFire")); if (eventObject.contains(QStringLiteral("AesId"))) wi.aesId = eventObject.value(QStringLiteral("AesId")).toInt(); // AesEvent from the radio: int originatorType = eventObject[QStringLiteral("OriginatorType")].toInt(); if (originatorType == static_cast(ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_AreaEffectSimulation) || originatorType == static_cast(ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_FunctionalArea)) obj[QStringLiteral("aesId")] = eventObject[QStringLiteral("OriginatorId")].toInt(); wi.equipmentNumber = eventData.equipmentNumber; wi.eventType = eventData.eventTypeId; wi.participantId = eventData.participantId; wi.position = eventData.position; const QByteArray propertiesStr = QJsonDocument(obj).toJson(QJsonDocument::Compact); wi.properties = propertiesStr.data(); m_mainHandler->dds()->dtsAlm()->publish(wi); // take data from dds-bus after 1 min const auto id = wi.id; QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_mainHandler->dds()->dtsAlm()->removeNotificationByKey(id); }); incrementWindowIndex(); // m_windowIndex++; } // end sendWindow QJsonObject HandlerConfigureAlarms::getEventProperties(const ExerciseEventManagement::Event &eventData) { return LtsUtils::JsonObject::fromJson(eventData.properties.c_str()); } void HandlerConfigureAlarms::sendMarker(const ExerciseEventManagement::Event &eventData, const Database::AlmConfig &config) { int defaultOffset = 10000; DEBUG_LOG(m_logger) << "eventProperties =" << eventData.properties; QString contentStr; contentStr = QStringLiteral("Equip No.: "); const int participantId = eventData.participantId; const int equipNo = m_mainHandler->hdlParticipant()->participantId2EquipNo(participantId); QJsonObject eventObject = getEventProperties(eventData); contentStr += QString::number(equipNo); contentStr += QStringLiteral(" "); contentStr += ProjectDataManagement::toString(eventData.eventTypeId); if (eventObject.contains(QStringLiteral("AesName"))) { contentStr += QStringLiteral(" ("); contentStr += eventObject.value(QStringLiteral("AesName")).toString(); contentStr += QStringLiteral(")"); } DEBUG_LOG(m_logger) << "contentStr=" << contentStr; const QByteArray contentArr = contentStr.toUtf8(); MarkerManagement::MarkerDescription ma; ma.content = contentArr.data(); ma.markerType = MarkerManagement::MarkerType::Situation; MarkerManagement::Marker mcr; mcr.operatorId = config.operatorId; mcr.note = ma.content; // really? mcr.timeStamp = eventData.sampleTime; mcr.timeStampOffset = defaultOffset; mcr.descriptions.push_back(ma); mcr.position = eventData.position; mcr.fileContentId = 0; // we cannot save an image here m_mainHandler->dds()->ftcMrk()->markerModifyRequest(mcr, this); } // end sendMarker void HandlerConfigureAlarms::onMarkerModifyReply(const Core::FunctionReplyObject &replyObject) { Q_UNUSED(replyObject); INFO_LOG(m_logger) << "************** onMarkerCreateReply"; } // end onMarkerCreateReply } // namespace AlarmManagement