Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,446 @@
/**
* @RDE_HEADER@
* Data Plugin for InfrastructureManagement
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-08-24
*/
#include "ism_foreign_data_plugin.h"
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <InfrastructureManagement/logger.h>
#include <LtsUtilsCore/json_object.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSet>
#include <QtConcurrent>
#include <QMutexLocker>
// #ifdef LTS_DEBUG
# define BENCHMARK
// #endif // LTS_DEBUG
#ifdef BENCHMARK
# define BENCHMARK_SETUP_AND_START() QElapsedTimer elapsedTimer; elapsedTimer.start();
# define BENCHMARK_RUN
#else
# define BENCHMARK_SETUP_AND_START()
#endif
namespace InfrastructureManagement
{
ForeignInterfaceImpl::ForeignInterfaceImpl(const std::shared_ptr<Interface::Dtc> &dtc, int exerciseId)
: m_dtc(dtc)
, m_scheduleId(-1)
, m_exerciseId(exerciseId)
, m_logger(getLogger("ForeignDataInterface"))
{
// init() ; lazy-initialisation : moved to enableIsmForeignInterface.
}
ForeignInterfaceImpl::~ForeignInterfaceImpl()
{
}
void ForeignInterfaceImpl::enableIsmForeignInterface() const
{
BENCHMARK_SETUP_AND_START();
if (!m_mountingPoints.isEmpty())
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, ismDataDtc, m_exerciseId = " << m_exerciseId
<< " already initialized -> return";
return;
}
// cast const away:
ForeignInterfaceImpl *NON_CONST_THIS = const_cast<ForeignInterfaceImpl*>(this);
NON_CONST_THIS->init();
#ifdef BENCHMARK_RUN
NOTICE_LOG(m_logger) << LOGFUNCTION << " ISM::StructureElementCache / ForeignInterfaceImpl::init took " << elapsedTimer.elapsed() << " [ms]"
<< " - m_exerciseId = " << m_exerciseId
<< " - m_mountingPoints.size()=" << m_mountingPoints.size()
<< ", (m_mountingPointAssetMap.size()=" << m_mountingPointAssetMap.size() << ")";
#endif // BENCHMARK_RUN
}
bool ForeignInterfaceImpl::mountingPoints(const std::function<void (const MountingPoint &)> &cb)
{
BENCHMARK_SETUP_AND_START();
enableIsmForeignInterface();
for (auto it = m_mountingPoints.constBegin(); it != m_mountingPoints.constEnd(); ++it)
cb(it.value());
#ifdef BENCHMARK_RUN
NOTICE_LOG(m_logger) << LOGFUNCTION
<< " - m_exerciseId = " << m_exerciseId
<< " - m_mountingPoints.size()=" << m_mountingPoints.size()
<< " took " << elapsedTimer.elapsed() << " [ms]";
#else
NOTICE_LOG(m_logger) << LOGFUNCTION
<< " - m_exerciseId = " << m_exerciseId
<< " - m_mountingPoints.size()=" << m_mountingPoints.size();
#endif // BENCHMARK_RUN
return true;
}
bool ForeignInterfaceImpl::mountingPoints(const std::function<bool (const MountingPoint &)> &cb)
{
enableIsmForeignInterface();
for (auto it = m_mountingPoints.constBegin(); it != m_mountingPoints.constEnd(); ++it)
if (cb(it.value()))
return true;
return false;
}
QHash<int32_t, MountingPoint> ForeignInterfaceImpl::mountingPoints() const
{
enableIsmForeignInterface();
return m_mountingPoints;
}
MountingPoint ForeignInterfaceImpl::mountingPoint(int32_t mountingPointId) const
{
enableIsmForeignInterface();
return m_mountingPoints.value(mountingPointId);
}
MainSchedule ForeignInterfaceImpl::mainSchedule(int32_t scheduleId)
{
enableIsmForeignInterface();
return m_dtc->mainSchedule(scheduleId);
}
void ForeignInterfaceImpl::setScheduleId(int32_t scheduleId)
{
DEBUG_LOG(m_logger) << "setScheduleId to: " << scheduleId
<< " (was " << m_scheduleId << ")";
enableIsmForeignInterface();
m_scheduleId = scheduleId;
onMainScheduleChanged(m_dtc->mainSchedule(scheduleId), DataModification::eModified);
emit scheduleIdChanged(m_scheduleId);
}
int32_t ForeignInterfaceImpl::scheduleId() const
{
return m_scheduleId;
}
QSet<int> ForeignInterfaceImpl::buildingsInCurrentExercise()
{
enableIsmForeignInterface();
return m_bldgsInExcersise;
}
const QSet<int>& ForeignInterfaceImpl::buildingsInCurrentExercise() const
{
enableIsmForeignInterface();
return m_bldgsInExcersise;
}
bool ForeignInterfaceImpl::isBuildingsInCurrentExercise(int buildingId) const
{
enableIsmForeignInterface();
return m_bldgsInExcersise.contains(buildingId);
}
void ForeignInterfaceImpl::onMainStructureElementChanged(const MainStructureElement &data, DataModification modType)
{
const int mseId = data.id();
switch (modType)
{
case DataModification::eRemoved:
{
QMutexLocker locker(&m_mutex);
const auto &structureElements = data.elements();
for (const StructureElement &currentStructEle : structureElements)
{
if (currentStructEle.structureElementTypeId() != StructureElementType::MountingPoint)
continue;
m_mountingPoints.remove(currentStructEle.id());
}
break;
}
case DataModification::eAdded:
case DataModification::eModified:
{
QVector<int> exeIds;
// read only once properties - available_in_exercise from MSE, only if exerciseId is relevant
if (m_exerciseId > 0)
{
QJsonParseError parserError;
const QByteArray &content = QByteArray::fromStdString(data.properties());
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
WARNING_LOG(m_logger) << "Invalid properties for MSE " << data.id() << ", " << data.name();
else
{
const QJsonArray exercises(QJsonObject(doc.object()).value(QStringLiteral("available_in_exercise")).toArray());
exeIds.reserve(exercises.size());
for (const auto &exercise : exercises)
exeIds += exercise.toInt();
}
}
// update m_bldgsInExcersise
{
bool realChange = false;
{
QMutexLocker locker(&m_mutex);
if (exeIds.contains(m_exerciseId) ||
(m_exerciseId == 0) // global -> processAll
)
{
if (!m_bldgsInExcersise.contains(mseId))
{
m_bldgsInExcersise.insert(mseId);
realChange = true;
}
} else {
if (m_bldgsInExcersise.contains(mseId))
{
m_bldgsInExcersise.remove(mseId);
realChange = true;
}
}
} // scope for mutex
// Maybe an MSE/building is added/removed?
if (realChange)
{
// ensure map object will be created
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_bldgsInExcersise updated."
<< " (mseId=" << mseId << " name=" << data.name();
emit buildingsInCurrentExerciseChanged();
}
}
// N. Thoden, 11.01.2022:
// reduce amount of data by filtering m_exerciseId / available_in_exercise
// (may otherwise took up to ~10 seconds!!)
// m_exerciseId <= 0 -> process all
if (m_exerciseId == 0 || (m_exerciseId > 0 && exeIds.contains(m_exerciseId)))
{
const auto &structureElements = data.elements();
for (const StructureElement &currentStructEle : structureElements)
{
if (currentStructEle.structureElementTypeId() != StructureElementType::MountingPoint)
continue;
StructureElement seFloor;
const std::vector<int32_t> &curPath = currentStructEle.path();
if (curPath.size() == 4)
{
// GUEZE-3258: Performance-Untersuchung der OpApp : getStructureElementById is expensive
// 500 bldgs, ~25000 structure element -> init() can took 2500ms (CTCAP28)
if (!m_dtc->getStructureElementById(curPath[1], seFloor)) // getStructureElementById is expensive if many buildings/structure elements
WARNING_LOG(m_logger) << " getStructureElementById failed for " << curPath[1];
}
const int floorId = QString::fromStdString(seFloor.name()).split(QStringLiteral("_")).value(1, QStringLiteral("-10")).toInt();
{
QMutexLocker locker(&m_mutex);
// GUEZE-3258: Performance-Untersuchung der OpApp
const auto it = m_mountingPoints.find(currentStructEle.id());
if (it != m_mountingPoints.end())
{
MountingPoint &mountingPointRef = *it;
if (mountingPointRef.data() == currentStructEle)
continue;
mountingPointRef.updateData(currentStructEle, floorId);
emit mountingPointChanged(mountingPointRef, DataModification::eModified);
} else {
DEBUG_LOG(m_logger) << "New Mounting point with id " << currentStructEle.id()
<< " and type " << currentStructEle.mountingPointTypeId()
<< " (type " << currentStructEle.mountingPointTypeId().underlying() << ")"
<< " subid: " << currentStructEle.mountingPointId() << this;
MountingPoint newMountingPoint(currentStructEle, floorId);
const int assetId = m_mountingPointAssetMap.value(newMountingPoint.id(), -1);
newMountingPoint.setAssociatedAssetId(assetId);
// newMountingPoint->setHasAssociatedAssetDefect(); // TODO
m_mountingPoints.insert(newMountingPoint.id(), newMountingPoint);
emit mountingPointChanged(newMountingPoint, DataModification::eAdded);
} // if (it != m_mountingPoints.end())
}
}
}
break;
}
} // switch
}
void ForeignInterfaceImpl::onMountingPointAssetChanged(const MountingPointAsset &data, DataModification modType)
{
const int32_t structureElementId = data.structureElementId();
DEBUG_LOG(m_logger) << "onMountingPointAssetChanged se id: " << structureElementId << ", assetId: " << data.assetId();
// [GUEZE-3494] Ressourcenverwaltung ist fehlerhaft laut Kunden
// QHash:
// value() -> return const T
// operator[] -> return T &
// // MountingPoint mp = m_mountingPoints.value(structureElementId);
MountingPoint &mpRef = m_mountingPoints[structureElementId]; // default constructed value may okay
if (modType == DataModification::eRemoved)
{
m_mountingPointAssetMap.remove(structureElementId);
if (mpRef.id() > 0)
{
mpRef.setAssociatedAssetId(-1);
mpRef.setHasAssociatedAssetDefect(false);
}
}
else
{
m_mountingPointAssetMap.insert(structureElementId, data.assetId());
if (mpRef.id() > 0)
{
mpRef.setAssociatedAssetId(data.assetId());
mpRef.setHasAssociatedAssetDefect(m_dtc->instrumentationAsset(data.assetId()).assetStateId() == InstrumentationAssetState::Defect);
}
}
if (mpRef.id() > 0)
emit mountingPointChanged(mpRef, DataModification::eModified);
}
void ForeignInterfaceImpl::onMainScheduleChanged(const MainSchedule &data, DataModification modType)
{
if (m_scheduleId != data.id())
return;
Q_UNUSED(modType);
QHash<int, MountingPointPlan> mppMap;
for (const auto &elem : data.elements())
mppMap[elem.structureElementId()] = elem;
for (MountingPoint &mp : m_mountingPoints)
{
const MountingPointPlan &mpp = mppMap[mp.id()];
const MountingPointState &mps = mpp.mountingPointState();
// If there is no MPP for this Schedule
if(mpp.structureElementId() != mp.id())
{
// Do nothing if idle
if (mp.aimState() == MountingPointState_def::Idle)
continue;
mp.setAimState(MountingPointState::Idle);
emit mountingPointChanged(mp, DataModification::eModified);
continue;
}
// If AimState did not change, continue
if (mp.aimState() == mps)
continue;
mp.setAimState(mps);
emit mountingPointChanged(mp, DataModification::eModified);
}
}
void ForeignInterfaceImpl::init()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, ismDataDtc, m_exerciseId = " << m_exerciseId
<< " - m_mountingPoints.size()=" << m_mountingPoints.size()
<< ", (m_mountingPointAssetMap.size()=" << m_mountingPointAssetMap.size() << ")";
m_dtc->waitForHistoricalDataMainStructureElement(1000); // enable is implicit
m_dtc->waitForHistoricalDataMainSchedule(1000); // enable is implicit
m_dtc->waitForHistoricalDataMountingPointAsset(1000); // enable is implicit
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged,
this, &ForeignInterfaceImpl::onMainStructureElementChanged, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged,
this, &ForeignInterfaceImpl::onMainScheduleChanged, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::mountingPointAssetChanged,
this, &ForeignInterfaceImpl::onMountingPointAssetChanged, Qt::UniqueConnection);
// // #define PROCESS_MSE_SEQUENTIELL
#ifdef PROCESS_MSE_SEQUENTIELL
m_dtc->mainStructureElements([this](const MainStructureElement &data)
{
onMainStructureElementChanged(data, DataModification::eAdded);
});
#else
// 25.10.2022, Norbert Thoden:
// ForeignInterfaceImpl::init() benoetigt ca. 5sec at CTCAP15
// Durch Parallelisierung reduziert es sich auf knapp 2sec. :-)
// via std::bind:
// using namespace std::placeholders;
// std::function<void(const MainStructureElement &data)> functor =
// std::bind(&ForeignInterfaceImpl::onMseChangedForInitializing, this, _1);
// QtConcurrent::blockingMap(mseMap, functor);
// Es geht aber auch einfacher per lambda :-)
const QMap<qint32, InfrastructureManagement::MainStructureElement> &mseMap =
m_dtc->mainStructureElements();
m_mountingPoints.reserve(mseMap.size());
// blockingMap -> functor will be applied to every item:
QtConcurrent::blockingMap(mseMap, [this](const MainStructureElement &data) {
onMainStructureElementChanged(data, DataModification::eAdded);
});
#endif // PROCESS_MSE_SEQUENTIELL
m_dtc->mountingPointAssets([this](const MountingPointAsset &data)
{
onMountingPointAssetChanged(data, DataModification::eAdded);
});
m_dtc->mainSchedules([this](const MainSchedule &data)
{
onMainScheduleChanged(data, DataModification::eAdded);
});
int firstBldg = -1;
if (!m_bldgsInExcersise.isEmpty())
firstBldg = *m_bldgsInExcersise.begin();
DEBUG_LOG(m_logger) << LOGFUNCTION << ", exerciseId = " << m_exerciseId << ", bldgs in excersise = " << m_bldgsInExcersise.size()
<< ", firstBldg: " << firstBldg;
DEBUG_LOG(m_logger) << LOGFUNCTION << "XXXXX" << m_bldgsInExcersise.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, ismDataDtc, m_exerciseId = " << m_exerciseId
<< " - m_mountingPoints.size()=" << m_mountingPoints.size()
<< ", (m_mountingPointAssetMap.size()=" << m_mountingPointAssetMap.size() << ")";
}
} // namespace InfrastructureManagement