/** * Handler for all exercise objects * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, SLSE, 2015-09-03 */ #include "handler_effect_show.h" #include "handler_effect_show_vehicle_status.h" #include "handler_tab_data.h" #include "handler_mdm_data.h" #include "object_effect_show_vehicle_status.h" #include "esm_db.h" #include "initialization.h" #include namespace EffectShowManagement { //============================================================================= HandlerEffectShowVehicleStatus::HandlerEffectShowVehicleStatus(Initialization *mainHandler, QObject *parent) : QObject(parent) , m_mainHandler(mainHandler) , m_logger(getLogger("HandlerEffectShowVehicleStatus")) { m_timerVehicleStatus.setSingleShot(true); } //============================================================================= HandlerEffectShowVehicleStatus::~HandlerEffectShowVehicleStatus() { qDeleteAll(m_effectShowVehicleStatusObjMap); } //============================================================================= bool HandlerEffectShowVehicleStatus::init() { DEBUG_LOG(m_logger) << "Begin HandlerEffectShowVehicleStatus"; // create EffectShowVehicleStatuss objects auto cbEsvs = [this] (const Database::EsmEffectShowVehicleStatus &data) { ObjectEffectShowVehicleStatus *ifs(new ObjectEffectShowVehicleStatus(m_mainHandler)); ifs->set(data); DEBUG_LOG(m_logger) << "HandlerEffectShowVehicleStatus::init getParticipantId :" << ifs->getParticipantId(); m_effectShowVehicleStatusObjMap.insert(ifs->getParticipantId(), ifs); }; if (!m_mainHandler->db()->select(cbEsvs)) { ERROR_LOG(m_logger) << "Error reading data from database!"; return false; } // check status from data base after statusRequestInterval QTimer::singleShot(HandlerEffectShowVehicleStatus::delayAfterStart, this, &HandlerEffectShowVehicleStatus::onStatusRequest); // provision of timer for timeout vehicle status connect(&m_timerVehicleStatus, &QTimer::timeout, this, &HandlerEffectShowVehicleStatus::onTimeoutVehicleStatus); m_timerVehicleStatus.setSingleShot(true); if (m_effectShowVehicleStatusObjMap.size() != 0) onTimeoutVehicleStatus(); DEBUG_LOG(m_logger) << "m_effectShowVehicleStatusObjMap.size() = " << m_effectShowVehicleStatusObjMap.size(); return true; } //============================================================================= int HandlerEffectShowVehicleStatus::getNumOfEffectShowActors() const { int res = 0; auto it = m_effectShowVehicleStatusObjMap.begin(); while (it != m_effectShowVehicleStatusObjMap.end()) { if (it.value()->getOperational()) res++; } return res; } //============================================================================= int HandlerEffectShowVehicleStatus::getIdOfEffectShowActor(int seq) { int num = 0; auto it = m_effectShowVehicleStatusObjMap.begin(); while (it != m_effectShowVehicleStatusObjMap.end()) { if (it.value()->getOperational()) { if (seq == num) return it.value()->getIdOfEffectShowActor(); num++; } } return -1; // illegal seq-number } //============================================================================= bool HandlerEffectShowVehicleStatus::isOperational(int id) const { for (auto it = m_effectShowVehicleStatusObjMap.begin(); it != m_effectShowVehicleStatusObjMap.end(); ++it) { if (it.value()->getIdOfEffectShowActor() == id) return it.value()->getOperational(); } return false; } //============================================================================= void HandlerEffectShowVehicleStatus::vehicleStatusReceived(const ConvertFromTab::VehicleStatus_t &vehicleStatus) { DEBUG_LOG(m_logger) << "vehicleStatusReceived: " << vehicleStatus.equipmentNumber << ' ' << vehicleStatus.timestamp << ' ' << m_mainHandler->dds()->currentPartitionTime(); HandlerPpmData::Participant_t actor = m_mainHandler->handlerPpmData()->getIdAndNameOfEffectShowActor(vehicleStatus.equipmentNumber); if (actor.id == -1) return; ObjectEffectShowVehicleStatus *ifs = m_effectShowVehicleStatusObjMap.value(actor.id); if (ifs == nullptr) { // create new object ifs = new ObjectEffectShowVehicleStatus(m_mainHandler); ifs->set(vehicleStatus); ifs->set(actor); ifs->createObject(); // write into db and publish data m_effectShowVehicleStatusObjMap.insert(ifs->getParticipantId(), ifs); // insert object into map } else { // update object ifs->set(vehicleStatus); ifs->set(actor); ifs->updateObject(); // update db and publish data } onTimeoutVehicleStatus(); } //============================================================================= void HandlerEffectShowVehicleStatus::effectShowActorChanged(const HandlerPpmData::Participant_t &data, DataModification modType) { DEBUG_LOG(m_logger) << "onEffectShowActorChanged: " << data.equipmentNumber; auto it = m_effectShowVehicleStatusObjMap.find(data.id); if (it == m_effectShowVehicleStatusObjMap.end()) return; // participant not allocated to any order if (modType == DataModification::eRemoved) { it.value()->removeObject(); // remove vehicle status object } else { it.value()->set(data); it.value()->updateObject(); // update and publish Object } } //============================================================================= void HandlerEffectShowVehicleStatus::onStatusRequest() { qint64 currentTime = m_mainHandler->dds()->currentPartitionTime(); if (currentTime == 0) { QTimer::singleShot(HandlerEffectShowVehicleStatus::statusRequestInterval, this, &HandlerEffectShowVehicleStatus::onStatusRequest); return; // wait for the clock } if (m_statusRequest.size() == 0) { // check timestamp after init() one time for (auto it = m_effectShowVehicleStatusObjMap.begin(); it != m_effectShowVehicleStatusObjMap.end(); ++it) { if ((currentTime - it.value()->getTimestamp()) > HandlerEffectShowVehicleStatus::statusTimeout) { it.value()->setOperational(false); // reset operational status m_statusRequest.append(it.value()->getParticipantId()); // order status request } } } if (m_statusRequest.size() != 0) { // sent status request int equipmentNumber = m_statusRequest[m_statusRequest.size() - 1]; HandlerPpmData::Participant_t actor = m_mainHandler->handlerPpmData()->getIdAndNameOfEffectShowActor(equipmentNumber); auto it = m_effectShowVehicleStatusObjMap.find(actor.id); if (it != m_effectShowVehicleStatusObjMap.end()) { DEBUG_LOG(m_logger) << "Status Request equipment number: " << equipmentNumber << ' ' << it.value()->getIdOfEffectShowActor(); m_mainHandler->handlerTabData()->effectShowVehicleStatusRequest(equipmentNumber, it.value()->getIdOfEffectShowActor()); } // remove request order m_statusRequest.removeLast(); } // activate timer, if further vehicle status requests to be done if (m_statusRequest.size() != 0) QTimer::singleShot(HandlerEffectShowVehicleStatus::statusRequestInterval, this, &HandlerEffectShowVehicleStatus::onStatusRequest); } //============================================================================= void HandlerEffectShowVehicleStatus::onTimeoutVehicleStatus() { if (m_timerVehicleStatus.isActive()) return; // timeout already active qint64 currentTime = m_mainHandler->dds()->currentPartitionTime(); if (currentTime == 0) { m_timerVehicleStatus.start(HandlerEffectShowVehicleStatus::delayAfterStart); return; // wait for partition time } bool activateTimer = false; qint64 maxAge = 0; // determine the next vehicle status for timeout observation for (auto it = m_effectShowVehicleStatusObjMap.begin(); it != m_effectShowVehicleStatusObjMap.end(); ++it) { if (it.value()->getOperational()) { qint64 age = currentTime - it.value()->getTimestamp(); DEBUG_LOG(m_logger) << currentTime << ' ' << it.value()->getTimestamp(); if ((age + 1000) >= HandlerEffectShowVehicleStatus::statusTimeout) { it.value()->setOperational(false); // reset operational status } else { activateTimer = true; if (age > maxAge) maxAge = age; } } } // activate timer for timeout observation, if needed if (activateTimer) m_timerVehicleStatus.start(HandlerEffectShowVehicleStatus::statusTimeout - maxAge); DEBUG_LOG(m_logger) << "onTimeoutVehicleStatus(): " << activateTimer << ' ' << maxAge; } } // Namespace EffectShowManagement