Initial commit
This commit is contained in:
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 ¤tStructEle : 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 ¤tStructEle : 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
|
||||
Reference in new issue
Block a user