Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Proxies/Buildings/ism_handler.cpp
T
2026-10-03 09:20:13 +02:00

568 lines
21 KiB
C++
Executable File

#include "ism_handler.h"
#include <utility>
#include "main_handler.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtCore/QTimer>
#include <QtCore/QJsonDocument>
#include <QJsonParseError>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <LtsUtils/LtsUtilsCore/dds_vector.h>
#include <QtWebSockets/QWebSocket>
#include <web_socket_telegrams.h>
namespace Buildings
{
IsmHandler::IsmHandler(MainHandler *mainHandler) : m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger())
, m_mainHandler(mainHandler)
, m_dtcIsm(nullptr)
, m_ftcIsm(nullptr)
, m_changeTimeoutTimer(new QTimer(this))
, m_changeTimeoutTimerInit(new QTimer(this)) {
connect(m_changeTimeoutTimer, &QTimer::timeout,
this, &IsmHandler::onBuildingsChanged);
m_changeTimeoutTimer->setInterval(3 * 1000);
m_changeTimeoutTimer->setSingleShot(true);
connect(m_changeTimeoutTimerInit, &QTimer::timeout,
this, &IsmHandler::onBuildingsChangedInit);
m_changeTimeoutTimerInit->setInterval(3 * 1000);
m_changeTimeoutTimerInit->setSingleShot(true);
}
IsmHandler::~IsmHandler()
{}
bool IsmHandler::init()
{
if (m_dtcIsm)
return true;
m_dtcIsm = InfrastructureManagement::Interface::Dtc::create(m_mainHandler->ddsHandler()->ddsConnector());
connect(m_dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::instrumentationAssetChanged,
this, &IsmHandler::onInstrumentationAssetChanged);
connect(m_dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mountingPointAssetChanged,
this, &IsmHandler::onMountingPointAssetChanged);
connect(m_dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &IsmHandler::onMainStructureElementChanged);
connect(m_dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::bridgeChangeStatusChanged,
this, &IsmHandler::onBridgeStatusChanged);
if (!m_dtcIsm->enableInstrumentationAsset() ||
!m_dtcIsm->enableMainStructureElement() ||
!m_dtcIsm->enableMountingPointAsset() ||
!m_dtcIsm->enableBridgeChangeStatus())
{
ERROR_LOG(m_logger) << "Can not read data from ISM";
return false;
}
m_ftcIsm = InfrastructureManagement::Interface::Ftc::create(m_mainHandler->ddsHandler()->ddsConnector());
if (!m_ftcIsm->enableStructureElementUpdateEffectOverride())
{
ERROR_LOG(m_logger) << "Can not read data from ISM";
return false;
}
m_changeTimeoutTimerInit->start();
return true;
}
bool IsmHandler::isElementAssignedToExercise(const int mseId, int exerciseId)
{
InfrastructureManagement::MainStructureElement mse = m_dtcIsm->mainStructureElement(mseId);
return m_dtcIsm->isElementAssignedToExercise(mse, exerciseId);
}
void IsmHandler::onInstrumentationAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType)
{
if (data.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingSensorModule ||
data.mountingPointTypeId == InfrastructureManagement::MountingPointType::EffectGenerationControlUnit)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_instAssets.insert(data.id, data);
break;
case DataModification::eRemoved:
m_instAssets.remove(data.id);
break;
}
m_changeTimeoutTimer->start();
return;
}
if (data.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingControlUnit)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
const int exerciseId = data.availableInExercise.size() == 0 ? 0 : data.availableInExercise.at(0);
DEBUG_LOG(m_logger) << "setting asset " << data.id << " available in exercise " << exerciseId;
m_assetMainStructureElementInExercise.insert(data.id, exerciseId);
break;
}
case DataModification::eRemoved:
{
const int exerciseId = data.availableInExercise.size() == 0 ? 0 : data.availableInExercise.at(0);
DEBUG_LOG(m_logger) << "removing asset " << data.id << " from exercise " << exerciseId;
m_assetMainStructureElementInExercise.remove(data.id);
break;
}
}
m_changeTimeoutTimer->start();
}
}
void IsmHandler::onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
DEBUG_LOG(m_logger) << "mounting asset " << data.assetId << " on structure element id " << data.structureElementId;
m_structureElementId2AssetId.insert(data.structureElementId, data.assetId);
break;
case DataModification::eRemoved:
DEBUG_LOG(m_logger) << "unmounting asset " << m_structureElementId2AssetId.value(data.structureElementId) << " from structure element " << data.structureElementId;
m_structureElementId2AssetId.remove(data.structureElementId);
break;
}
m_changeTimeoutTimer->start();
}
void IsmHandler::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
{
DEBUG_LOG(m_logger) << Q_FUNC_INFO;
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
if (!isElementAssignedToExercise (data.id,m_mainHandler->exerciseId() ) )
{
m_mainStructureElements.remove(data.id);
DEBUG_LOG(m_logger) << "Building not in exercise id=" << data.id;
return;
}
DEBUG_LOG(m_logger) << "Building=" << data.name
<< " properties=" << data.properties;
QJsonParseError parserError;
QByteArray content = QByteArray::fromStdString(data.properties);
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return;
}
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson();
const QJsonObject objProperties(doc.object());
if ( objProperties.contains(QStringLiteral("start_building_process")))
{
DEBUG_LOG(m_logger) << "properties contains start_building_process";
bool startBuildingProcess = objProperties.value(QStringLiteral("start_building_process")).toBool();
if (!startBuildingProcess)
{
DEBUG_LOG(m_logger) << "Building=" << data.name
<< " start_building_process = false ";
return;
}
}
DEBUG_LOG(m_logger) << "##### onMainStructureElementChanged - ID = " << data.id;
checkOverride( m_mainStructureElements[data.id], data);
m_mainStructureElements[data.id] = data;
break;
}
case DataModification::eRemoved:
m_mainStructureElements.remove(data.id);
break;
}
m_changeTimeoutTimer->start();
}
void IsmHandler::onBridgeStatusChanged(const InfrastructureManagement::BridgeChangeStatus &data, DataModification modType)
{
static int s_id = 1;
DEBUG_LOG(m_logger) << Q_FUNC_INFO << "s_id=" << s_id;
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
DEBUG_LOG(m_logger) << "##### onBridgeStatusChanged - buildingId = " << data.buildingId;
BridgeStatus bs;
bs.id = s_id++;
bs.buildingId = data.buildingId;
bs.sampleTime = data.sampleTime;
bs.status = static_cast<int>(m_dtcIsm->getBridgeStatus(data.buildingId));
m_mainHandler->ddsHandler()->dts()->publish(bs);
break;
}
case DataModification::eRemoved:
break;
}
m_changeTimeoutTimer->start();
}
void IsmHandler::getEgcuToRoom(const InfrastructureManagement::MainStructureElement &mse, QVector<EgcuInfo> &eis)
{
INFO_LOG(m_logger) << "properties=" << mse.properties;
QJsonParseError parserError;
QByteArray content = QByteArray::fromStdString(mse.properties);
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return;
}
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson();
const QJsonObject objEgcus(doc.object());
const QJsonArray arrEgcus(objEgcus.value(QStringLiteral("egcusToRooms")).toArray());
for (int i = 0; i < arrEgcus.size(); ++i)
{
const QJsonObject objRooms(arrEgcus.at(i).toObject());
const int mountpointEgcuId = objRooms[QStringLiteral("mountpointEgcu")].toInt();
INFO_LOG(m_logger) << "mountpointEgcu=" << mountpointEgcuId;
INFO_LOG(m_logger) << "i=" <<i;
const QJsonArray arrRooms(objRooms.value(QStringLiteral("rooms")).toArray());
INFO_LOG(m_logger) << "bi.egcus.size()=" << eis.size();
for (EgcuInfo &egcuInfo : eis)
{
DEBUG_LOG(m_logger) << "bi.egcus.at(k).mountPointId=" << egcuInfo.mountPointId
<< " mountpointEgcu=" << mountpointEgcuId;
if (egcuInfo.mountPointId == mountpointEgcuId)
{
DEBUG_LOG(m_logger) << "mountpointEgcu=" << mountpointEgcuId;
egcuInfo.roomIds.clear();
egcuInfo.roomIds.reserve(arrRooms.size());
for (const auto &room : arrRooms)
egcuInfo.roomIds += room.toInt();
break;
}
}
}
}
void IsmHandler::onBuildingsChangedInit()
{
buildingsChanged(false);
}
void IsmHandler::onBuildingsChanged()
{
buildingsChanged(true);
}
void IsmHandler::buildingsChanged(bool init)
{
QSet<int> availableBuildingIds;
QMap<int, BuildingInfo> newBuildingConfiguration;
availableBuildingIds.reserve(m_mainStructureElements.size());
INFO_LOG(m_logger) << "Updating building config m_mainStructureElements.size=" << m_mainStructureElements.size();
for (const InfrastructureManagement::MainStructureElement &mse : std::as_const(m_mainStructureElements))
{
DEBUG_LOG(m_logger) << "Checking building " << mse.id << " - " << mse.name;
BuildingInfo bi;
bi.mseId = mse.id;
bi.modelId = mse.modelId;
bi.externalWlsId = mse.externalWlsId;
bi.name = QString::fromStdString(mse.name);
bi.absPosition = mse.geoPosition;
bi.angle = mse.angle;
bi.structureElementId = mse.structureElementId;
for (const InfrastructureManagement::StructureElement &se : mse.elements)
{
if (se.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingSensorModule)
handleBuildingSensorModule(se, bi);
else if (se.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingControlUnit)
handleBuildingControlUnit(se, bi);
else if (se.mountingPointTypeId == InfrastructureManagement::MountingPointType::EffectGenerationControlUnit)
handleEffectGenerationControlUnit(se, bi);
else if (se.structureElementTypeId == InfrastructureManagement::StructureElementType::Room)
{
bi.subId2RoomId.insert(se.mountingPointId, se.id);
bi.roomId2SubId.insert(se.id, se.mountingPointId);
bi.roomName2RoomId.insert(QString::fromStdString(se.name), se.mountingPointId);
INFO_LOG(m_logger) << " Room: mountingPointId: " << se.mountingPointId
<< ", roomId: " << se.id
<< ", Name: " << se.name;
m_roomId2RoomName.insert(se.id, QString::fromStdString(se.name));
}
}
if (m_mainHandler->exerciseId() != bi.currentExerciseId)
{
DEBUG_LOG(m_logger) << "Exercise id of building does not match current exercise: " << bi.currentExerciseId
<< " != " << m_mainHandler->exerciseId()
<< " buildingId=" << bi.mseId
<< " buildingName" << bi.name;
continue;
}
INFO_LOG(m_logger) << "Adding building configuration for " << mse.id << " - " << mse.name;
availableBuildingIds += mse.id;
getEgcuToRoom(mse, bi.egcus);
newBuildingConfiguration.insert(bi.mseId, bi);
}
for (auto it = m_currentBuildingConfiguration.begin(); it != m_currentBuildingConfiguration.end(); ++it)
{
const int buildingId = it.key();
if (!availableBuildingIds.contains(buildingId))
{
INFO_LOG(m_logger) << "Building " << buildingId << " no longer exists in this exercise - removing";
emit buildingRemoved(buildingId);
continue;
}
const BuildingInfo &biOld = it.value();
const BuildingInfo &biNew = newBuildingConfiguration.value(buildingId);
if (biOld == biNew)
{
INFO_LOG(m_logger) << "Building " << buildingId << " did not change - nothing to do";
}
else
{
INFO_LOG(m_logger) << "setHistoryState Building " << buildingId << " changed -> updating configuration"
<< " biNew mseId=" << biNew.mseId
<< " init=" << init;
bool initBuildingChanged = true;
emit buildingChanged(biNew, initBuildingChanged);
}
}
for (auto it = newBuildingConfiguration.begin(); it != newBuildingConfiguration.end(); ++it)
{
if (m_currentBuildingConfiguration.contains(it.key()))
continue;
INFO_LOG(m_logger) << "setHistoryState New building added key= " << it.key()
<< " init=" << init;
emit buildingChanged(it.value(), init);
}
m_currentBuildingConfiguration = newBuildingConfiguration;
}
void IsmHandler::handleBuildingSensorModule(const InfrastructureManagement::StructureElement &se, BuildingInfo &bi) const
{
auto itMpa = m_structureElementId2AssetId.find(se.id);
if (itMpa == m_structureElementId2AssetId.end())
return;
const int assetId = itMpa.value();
const auto itAsset = m_instAssets.find(assetId);
if (itAsset == m_instAssets.end())
return;
const InfrastructureManagement::InstrumentationAsset &ia = itAsset.value();
BsmInfo bsi;
bsi.assetId = assetId;
bsi.bsmId = se.mountingPointId;
bsi.hostname = QString::fromStdString(ia.hostname);
bsi.port = getBsmPortFromJSon(ia.properties);
bsi.relPosition = se.relPosition;
bsi.orientation = se.orientation;
DEBUG_LOG(m_logger) << "adding bsm sensor module to building " << bi.mseId << ": " << bsi.assetId << ", " << bsi.bsmId << ", " << bsi.hostname;
bi.bsms.insert(bsi.assetId, bsi);
}
void IsmHandler::handleBuildingControlUnit(const InfrastructureManagement::StructureElement &se, BuildingInfo &bi) const
{
bi.currentExerciseId = 0;
auto itMpa = m_structureElementId2AssetId.find(se.id);
if (itMpa == m_structureElementId2AssetId.end())
{
INFO_LOG(m_logger) << "structure element id " << se.id << " not (yet)found"
<< " bi.mseId=" << bi.mseId
<< " bi.assetId=" << bi.assetId
<< " bi.egcus.size=" << bi.egcus.size()
<< " bi.roomName2RoomId.size()=" << bi.roomName2RoomId.size();
return;
}
const int assetId = itMpa.value();
const auto itAsset = m_assetMainStructureElementInExercise.find(assetId);
if (itAsset == m_assetMainStructureElementInExercise.end())
{
ERROR_LOG(m_logger) << "asset id " << assetId << " not found";
Q_ASSERT(false);
return;
}
bi.currentExerciseId = itAsset.value();
bi.assetId = itAsset.key();
DEBUG_LOG(m_logger) << "adding bsm control unit (virtual) to building " << bi.mseId << ": " << bi.assetId << ", " << bi.currentExerciseId;
}
void IsmHandler::handleEffectGenerationControlUnit(const InfrastructureManagement::StructureElement &se, BuildingInfo &bi) const
{
DEBUG_LOG(m_logger) << "BuildingId=" << bi.mseId
<< " se.id=" << se.id;
auto itMpa = m_structureElementId2AssetId.find(se.id);
if (itMpa == m_structureElementId2AssetId.end())
{
INFO_LOG(m_logger) << "Return m_structureElementId2AssetId.size()=" << m_structureElementId2AssetId.size();
return;
}
const int assetId = itMpa.value();
const auto itAsset = m_instAssets.find(assetId);
if (itAsset == m_instAssets.end())
{
INFO_LOG(m_logger) << "Return m_instAssets.size()=" << m_instAssets.size();
return;
}
const InfrastructureManagement::InstrumentationAsset &ia = itAsset.value();
EgcuInfo egcu;
egcu.buildingName = bi.name;
egcu.mountPointName = QString::fromStdString(se.name);
egcu.mountPointId = se.mountingPointId;
egcu.hostname = QString::fromStdString(ia.hostname);
egcu.assetId = assetId;
DEBUG_LOG(m_logger) << "Egcu.hostname=" << egcu.hostname;
INFO_LOG(m_logger) << "properties=" << ia.properties;
bi.egcus.push_back(egcu);
DEBUG_LOG(m_logger) << "adding egcu to building " << bi.mseId << ": " << egcu.hostname
<< " name=" << egcu.buildingName
<< " mountPointName=" << egcu.mountPointName
<< " mountPointId=" << egcu.mountPointId
<< " rooms.size=" << egcu.roomIds.size();
}
unsigned short IsmHandler::getBsmPortFromJSon(const std::string &s)
{
constexpr int s_defBsmPort = 12000;
QJsonParseError jError;
QJsonDocument doc(QJsonDocument::fromJson(s.c_str(), &jError));
if (jError.error != QJsonParseError::NoError ||
!doc.isObject())
{
return s_defBsmPort;
}
QJsonObject obj(doc.object());
int ret = obj[QStringLiteral("port")].toInt();
return ret ? ret : s_defBsmPort;
}
InfrastructureManagement::MainStructureElement IsmHandler::mainStructureElement(int id) const
{
return m_mainStructureElements.value(id);
}
void IsmHandler::checkOverride(const InfrastructureManagement::MainStructureElement &mseOld,
const InfrastructureManagement::MainStructureElement &mseNew)
{
DEBUG_LOG(m_logger) << Q_FUNC_INFO;
DEBUG_LOG(m_logger) << "mseOld.elements.size()=" << mseOld.elements.size()
<< " mseNew.elements.size()=" << mseNew.elements.size();
for (const InfrastructureManagement::StructureElement &se : mseNew.elements)
{
DEBUG_LOG(m_logger) << "se=" << se.id
<< " name=" << se.name
<< " displayName=" << se.displayName
<< " properties=" << se.properties;
for (const InfrastructureManagement::StructureElement &seOld : mseOld.elements)
{
DEBUG_LOG(m_logger) << "seOld.id=" << seOld.id
<< " se.id=" << se.id;
if ( seOld.id == se.id)
{
DEBUG_LOG(m_logger) << "Properties =" << se.properties
<< " se.id=" << se.id
<< " se.name=" << se.name
<< " mountingPointId=" << se.mountingPointId;
DEBUG_LOG(m_logger) << "se.properties=" << se.properties
<< " seOld.properties=" << seOld.properties;
if (se.properties != seOld.properties )
{
DEBUG_LOG(m_logger) << "HandleOverrides"
"<< m_currentBuildingConfiguration.size=" << m_currentBuildingConfiguration.size();
if ( se.structureElementTypeId == InfrastructureManagement::StructureElementType::Building)
{
DEBUG_LOG(m_logger) << "BSM-Flash, no EGCU";
QByteArray properties = QByteArray::fromStdString(se.properties);
emit setEffectStates(mseNew.id, 0, properties );
continue;
}
for (auto it = m_currentBuildingConfiguration.begin(); it != m_currentBuildingConfiguration.end(); ++it)
{
BuildingInfo &bi = it.value();
DEBUG_LOG(m_logger) << "key=" << it.key()
<< " id=" << bi.mseId
<< " assetId=" << bi.assetId
<< " egcus.size=" << bi.egcus.size();
for (const auto &egcu : std::as_const(bi.egcus))
{
DEBUG_LOG(m_logger) << "AssetId=" << egcu.assetId
<< " assetName=" << egcu.assetName
<< " hostname=" << egcu.hostname
<< " egcu.mountPointId=" << egcu.mountPointId
<< " se.mountingPointId=" << se.mountingPointId;
if (egcu.mountPointId == se.mountingPointId)
{
QByteArray properties = QByteArray::fromStdString(se.properties);
DEBUG_LOG(m_logger) << "Send Json SetEffectStates to BuildingProcess"
<< " buildingId="
<< " assetId="<< egcu.assetId
<< " properties =" << properties;
emit setEffectStates(mseNew.id, egcu.assetId, properties );
}
}
}
}
}
else
{
TRACE_LOG(m_logger) << "No changes do not HandleOverrides";
}
}
if (mseOld.elements.size() == 0)
{
QByteArray properties = QByteArray::fromStdString(se.properties);
QByteArray overrides("Overrides");
if (properties.contains(overrides))
{
int assetId;
bool foundAssetId = m_dtcIsm->getAssetIdFromMountingPoint(se.id, se.mountingPointId, assetId);
DEBUG_LOG(m_logger) << "Send Overrides to BuildingProcess (EGCU)"
<< " foundAssetId=" << foundAssetId
<< " structureElementId=" << mseNew.id
<< " se.id=" << se.id
<< " mountingPointId=" << se.mountingPointId
<< " assetId=" << assetId;
emit setEffectStates(mseNew.id, assetId, properties );
}
}
}
}
}