Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/AudioVideoManagement/exercise_handler.cpp
T
torstenandCopilot b774f4035c Qt6 Migration: DDS-Stubs, Logger-Fixes, Export-Header Korrekturen
- NGL_ADD_LIBRARY2: 87 CMakeLists.txt konvertiert für Export-Header Generierung
- 44 Export-Header Include-Pfade korrigiert (_export.h)
- 81 DDS-Stub-Header generiert (*_dtc.h, *_fts.h, *_dts.h, *_ftc.h)
- INGLLogger: Duplikat gelöscht, m_logger Member entfernt, variadische Makros
- Q_FUNC_INFO Redefinition behoben (Qt6 definiert bereits)
- FATAL_LOG Makro hinzugefügt
- InfrastructureManagement DDS-Stubs (ism.hpp, ism_enums.hpp, ism_ftc.h)
- FilterManagement DDS-Stubs (flt_ftc.h, flt_dts.h)
- AreaEffectSimulation DDS-Stubs (aes.hpp, aes_enums.hpp)
- SymbolAppearance Klasse vollständig definiert mit content() Methode
- BuildingComponentFilter Klasse definiert mit Copy-Konstruktor
- Ftc Factory: nullptr Return (abstract class)
- AesFilter Klasse in aes.hpp hinzugefügt
- Dtc Klasse in ppm.hpp mit participantChanged Signal
- AesType Enum: alle 15 At* Werte definiert
- AesEffectState_def: EsReceived hinzugefügt
- DataModification Enum: eAdded/eModified/eRemoved
- function_reply_object.h → core_types.h Include-Pfad (72 Dateien)
- Enum-Class-Streaming Template-Operator in INGLLogger.h
- ism_mounting_point.h: QImage → QtGui/QImage, QGuiApplication/QScreen
- ism_data_plugin_interface.h: QSet Include, Include-Reihenfolge
- QRegExp → QRegularExpression in tpm_js_parser.cpp
- .underlying() Aufrufe zu direktem Enum-Vergleich korrigiert
- Include-Pfade: aes.hpp in symbol_appearance_settings_impl.h und aes_display_filter_impl.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-19 06:06:24 +02:00

310 lines
9.6 KiB
C++
Executable File

/**
* Exercises Handler - Handle all information which is needed for AVS to create the proper AV-Streams for a specific context
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-10-20
*/
#include "exercise_handler.h"
#include "exercises_handler.h"
#include "dds_handler.h"
#include "main_handler.h"
#include <LtsUtilsCore/json_object.h>
#include <chrono>
using LtsUtils::JsonObject;
namespace
{
QString avRootName() { return QStringLiteral("ECRS"); }
QString avRecordReplayDefintion() { return QStringLiteral("mode=1;rootfilepath=/data/AVS"); }
QString avController() { return QStringLiteral("EXCAVS01"); }
bool isActive(ExerciseManagement::ExerciseState state)
{
return (state == ExerciseManagement::ExerciseState::Started ||
state == ExerciseManagement::ExerciseState::Paused);
}
} // anonymous namespace
namespace AudioVideoManagement
{
ExerciseHandler::ExerciseHandler(MainHandler *mainHandler, int exerciseId)
: QObject()
, m_exContext(exerciseId)
, m_curExerciseState(ExerciseManagement::ExerciseState::Unknown)
, m_curAVOperatingMode(AVControl::OperatingMode::Unknown)
, m_mainHandler(mainHandler)
, m_updateTimer(new QTimer(this))
, m_lastSeenTimer(new QTimer(this))
, m_bWarnedOnce(false)
{
m_updateTimer->setSingleShot(true);
connect(m_updateTimer, &QTimer::timeout, this, &ExerciseHandler::onUpdateTimerTimeout);
m_lastSeenTimer->setSingleShot(false);
m_lastSeenTimer->setInterval(std::chrono::milliseconds(std::chrono::minutes(10)).count());
connect(m_lastSeenTimer, &QTimer::timeout, this, &ExerciseHandler::onLastSeenTimerTimeout);
m_lastSeenTimer->start();
connect(avControl(), &AVControl::operatingModeChanged, this, &ExerciseHandler::onOperatingModeChanged);
connect(avControl(), &AVControl::successfullyLoggedIn, this, &ExerciseHandler::onAvSuccessfullyLoggedIn);
connect(fmControl(), &FMControl::fileDeletionCompleted, this, &ExerciseHandler::onContextFilesDeleted);
}
/**
* Called whenever the exercise state changed unless the new state is Terminated.
* We make sure that for this exercise the Record- and PlaybackSession-entries
* exist in avm.device_config.
*/
void ExerciseHandler::checkForRecordPlaybackSession()
{
if (m_recordSession.id <= 0) // new
{
m_recordSession.context = m_exContext.toString();
m_recordSession.controller = avController();
m_recordSession.definition = avRecordReplayDefintion();
m_recordSession.name = avRootName();
m_recordSession.type = avTypeRecordSession();
if (!db()->insert(m_recordSession))
{
ERROR_LOG() << m_exContext << " Error adding AvmDeviceConfig - aborting";
return;
}
emit avDbReloadNeeded();
}
if (m_replaySession.id <= 0)
{
m_replaySession.context = m_exContext.toString();
m_replaySession.controller = avController();
m_replaySession.definition = avRecordReplayDefintion();
m_replaySession.name = avRootName();
m_replaySession.type = avTypePlaybackSession();
if (!db()->insert(m_replaySession))
{
ERROR_LOG() << m_exContext << " Error adding AvmDeviceConfig - aborting";
return;
}
emit avDbReloadNeeded();
}
}
void ExerciseHandler::setNewExerciseState(ExerciseManagement::ExerciseState newState)
{
Q_ASSERT(newState != ExerciseManagement::ExerciseState::Unknown);
INFO_LOG() << m_exContext << ": state change: " << m_curExerciseState << " -> " << newState;
if (m_curExerciseState == newState)
return;
Q_ASSERT(m_curExerciseState != ExerciseManagement::ExerciseState::Terminated); // No transition from Terminated to some other state allowed.
if (newState != ExerciseManagement::ExerciseState::Terminated)
checkForRecordPlaybackSession();
else
{
// We are about to terminate the session. OperatingMode will be switched to Cleanup.
// Once the AVS has removed all relevant files it will signal onContextFilesDelete().
// Then, Record- and PlaybackSession will be removed and the deletion of this is triggered.
}
bool currentIsActive = isActive(m_curExerciseState);
bool newIsActive = isActive(newState);
if (newIsActive != currentIsActive)
{
if (newIsActive)
{
DEBUG_LOG() << m_exContext << " activated";
emit contextActivated();
}
else
{
DEBUG_LOG() << m_exContext << " deactivated";
emit contextDeactivated();
}
}
m_curExerciseState = newState;
m_updateTimer->start(0);
}
void ExerciseHandler::setLastSeen(const Database::AvmExerciseLastSeen &lastSeen)
{
Q_ASSERT(lastSeen.id > 0);
m_lastSeen = lastSeen;
}
void ExerciseHandler::addDeviceConfig(const Database::AvmDeviceConfig &config)
{
if (config.type == avTypeRecordSession())
m_recordSession = config;
else if (config.type == avTypePlaybackSession())
m_replaySession = config;
else
Q_ASSERT(false);
}
bool ExerciseHandler::isTerminating() const
{
return m_curExerciseState == ExerciseManagement::ExerciseState::Terminated;
}
void ExerciseHandler::onUpdateTimerTimeout()
{
// check current state and make sure AVS has the same state
const AVControl::OperatingMode desiredOperatingMode = avModeFromExerciseState(m_curExerciseState);
if (m_curAVOperatingMode == desiredOperatingMode)
return;
DEBUG_LOG() << "Context: " << m_exContext << " Try switching to " << desiredOperatingMode;
if (!avControl()->setOperatingModeForContext(m_exContext, desiredOperatingMode))
{
if (!m_bWarnedOnce)
{
DEBUG_LOG() << "Context: " << m_exContext
<< " - could not change operating mode, maybe not yet connected to AVS - trying again in 5 seconds";
m_bWarnedOnce = true;
}
m_updateTimer->start(5000); // retry in 5sec
}
else
m_bWarnedOnce = false;
}
void ExerciseHandler::onLastSeenTimerTimeout()
{
if (isTerminating())
return;
// we check if the exercise is still available on dds
// if this is not the case, we first switch to AVControl::OperatingMode::Cleanup
// and remove all device_config entries except the record/replay session
// when the cleanup is finished (signal from A/V) we remove also the last two sessions and delete our self
auto ex = exmDtc()->exercise(m_exContext.id());
if (ex.id() == m_exContext.id())
{
// found -> update last seen timestamp
m_lastSeen.context = m_exContext.toString();
m_lastSeen.lastSeen = QDateTime::currentDateTimeUtc();
if (m_lastSeen.id > 0)
db()->update(m_lastSeen);
else
db()->insert(m_lastSeen);
return;
}
// not found, check for last seen information
if (m_lastSeen.id == 0 ||
m_lastSeen.lastSeen.isNull() ||
m_lastSeen.lastSeen.addDays(1) < QDateTime::currentDateTimeUtc())
{
INFO_LOG() << "Exercise with id " << m_exContext.id()
<< " not seen since more than 1 day -> removing";
// not seen at all or not since more than 1 day -> remove
setNewExerciseState(ExerciseManagement::ExerciseState::Terminated);
// now wait for finished signal from AVS ...
}
}
void ExerciseHandler::onOperatingModeChanged(const ExerciseContext &context,
AVControl::Component comp,
AVControl::OperatingMode om)
{
if (context != m_exContext)
return;
const AVControl::OperatingMode desiredOperatingMode = avModeFromExerciseState(m_curExerciseState);
if (desiredOperatingMode != om)
{
DEBUG_LOG() << "Context: " << context << " Got " << om
<< " for " << comp << " but expected " << desiredOperatingMode;
m_updateTimer->start(100);
}
else
{
DEBUG_LOG() << "Context: " << context << " Got " << om
<< " for " << comp << " which is the expected value";
m_updateTimer->stop();
}
m_curAVOperatingMode = om;
}
void ExerciseHandler::onContextFilesDeleted(const ExerciseContext &context)
{
if (context != m_exContext)
return;
if (!isTerminating())
return;
// all files were deleted, so we are ready with cleaning up - the only thing which is left now
// is to remove the record/replay session from db and delete ourself
if (m_recordSession.id > 0)
db()->removeAvmDeviceConfig(m_recordSession.id);
if (m_replaySession.id > 0)
db()->removeAvmDeviceConfig(m_replaySession.id);
m_recordSession = Database::AvmDeviceConfig();
m_replaySession = Database::AvmDeviceConfig();
if (m_lastSeen.id > 0)
db()->removeAvmExerciseLastSeen(m_lastSeen.id);
emit removeMeImFinished(m_exContext.id());
}
AVControl::OperatingMode ExerciseHandler::avModeFromExerciseState(ExerciseManagement::ExerciseState state)
{
switch (state.underlying())
{
case ExerciseManagement::ExerciseState::Unknown:
case ExerciseManagement::ExerciseState::Created:
return AVControl::OperatingMode::Initialization;
case ExerciseManagement::ExerciseState::Started:
return AVControl::OperatingMode::Recording;
case ExerciseManagement::ExerciseState::Paused:
return AVControl::OperatingMode::Pause;
case ExerciseManagement::ExerciseState::Stopped:
return AVControl::OperatingMode::SaveData;
case ExerciseManagement::ExerciseState::Terminated:
return AVControl::OperatingMode::Cleanup;
}
return AVControl::OperatingMode::Unknown;
}
AVControl *ExerciseHandler::avControl() const
{
return m_mainHandler->avControl();
}
FMControl *ExerciseHandler::fmControl() const
{
return m_mainHandler->fmControl();
}
DatabaseInterface *ExerciseHandler::db() const
{
return m_mainHandler->db();
}
ExerciseManagement::Interface::Dtc *ExerciseHandler::exmDtc() const
{
return m_mainHandler->ddsHandler()->exmDtc();
}
void ExerciseHandler::onAvSuccessfullyLoggedIn()
{
m_updateTimer->start();
m_curAVOperatingMode = AVControl::OperatingMode::Unknown;
}
} // namespace AudioVideoManagement