Files
T
berrux-dev 82356f23e5 Migrates InfrastructureManagement to generated rtiddsgen API
Converts accessor calls to plain member access across ism service.
2026-09-21 02:45:09 +02:00

1223 lines
44 KiB
C++
Executable File

/**
* @RDE_HEADER@
* The DataManager class takes strucure element data from the HandlerStructureElement,
* offers an interface to get and set structure data
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-09-12
*/
#include "data_manager.h"
#include "Common/LtsCoordTrans/lts_coord_trans.h"
#include "main_handler.h"
#include "handler_main_schedule.h"
#include "object_main_schedule.h"
#include "handler_mounting_point_asset.h"
#include "object_mounting_point_asset.h"
#include "handler_instrumentation_asset.h"
#include "object_instrumentation_asset.h"
#include "handler_main_structure_element.h"
#include "object_main_structure_element.h"
#include "object_structure_element.h"
#include <InfrastructureManagement/ism_translation.h>
#include <AssetManagement/asm_dtc.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <LtsCoordTrans/lts_coord_trans.h>
using namespace InfrastructureManagement;
using namespace InfrastructureManagement::WebSocketInterface;
namespace
{
/**
* Determine the floor number.
* Currently the floor number is not part of the model. At least it is not stored in the DB.
* But the floor number is encoded in the floor name, e.g. "floor_-1",
* so we simply try to extract it from there.
*/
int determineFloorNumber(ObjectStructureElement *floor)
{
static const QString FLOOR_PATTERN = QStringLiteral("floor_");
Q_ASSERT(floor);
Q_ASSERT(floor->getStructureElementTypeId() == StructureElementType::Floor);
QString name = QString::fromStdString(floor->getData().name).toLower();
if (!name.startsWith(FLOOR_PATTERN))
return 0;
bool ok = false;
int floorNumber = name.midRef(FLOOR_PATTERN.size()).toInt(&ok);
if (!ok)
return 0;
return floorNumber;
}
} // anonymous namespace
//---------------------------------------------------------------------------------------------------------
DataManager::DataManager(MainHandler *mainHandler)
: LtsWebSocket::DataManagerBaseDl<DatabaseInterface>(mainHandler->db(), getLogger(QStringLiteral("DataManager")))
, m_mainHandler(mainHandler)
{}
//---------------------------------------------------------------------------------------------------------
bool DataManager::init()
{
std::shared_ptr<DDSConnector::DdsConnector> ddsConnector = m_mainHandler->dds()->ddsConnector();
m_asmDtc = AssetManagement::Interface::Dtc::create(ddsConnector);
return m_asmDtc->enableTrainingArea();
}
//---------------------------------------------------------------------------------------------------------
DataManager::EinruestEssentials DataManager::getEssentials(const QString &uuid) const
{
using namespace Messages;
EinruestEssentials result;
// training areas and areas
const QMap<qint32, AssetManagement::TrainingArea> trainingAreaMap = m_asmDtc->trainingAreas();
QVector<ReplyMessage::LonLatPoint> path;
path.reserve(4);
result.trainingAreas.reserve(trainingAreaMap.size());
result.areas.reserve(trainingAreaMap.size());
using namespace LtsCoordTrans;
for (const AssetManagement::TrainingArea &currentArea : trainingAreaMap)
{
TrainingAreaMessage::TrainingAreaData trainingAreaData;
AreaMessage::AreaData areaData;
ReplyMessage::LonLatPoint point;
path.clear();
// bottom left
UtmCoordinate bl(UtmCoordinate::fromGeographic({currentArea.bottomLeft.lon, currentArea.bottomLeft.lat}));
point.lon = currentArea.bottomLeft.lon;
point.lat = currentArea.bottomLeft.lat;
trainingAreaData.path.append(point);
areaData.path.append(point);
// upper left
UtmCoordinate ul(UtmCoordinate::fromGeographic(bl.geographic(0, currentArea.height)));
point.lon = ul.geographic().x();
point.lat = ul.geographic().y();
trainingAreaData.path.append(point);
areaData.path.append(point);
// upper right
UtmCoordinate ur(UtmCoordinate::fromGeographic(bl.geographic(currentArea.width, currentArea.height)));
point.lon = ur.geographic().x();
point.lat = ur.geographic().y();
trainingAreaData.path.append(point);
areaData.path.append(point);
// lower right
UtmCoordinate lr(UtmCoordinate::fromGeographic(bl.geographic(currentArea.width, 0)));
point.lon = lr.geographic().x();
point.lat = lr.geographic().y();
trainingAreaData.path.append(point);
areaData.path.append(point);
trainingAreaData.designation = QString::fromStdString(currentArea.name);
trainingAreaData.id = currentArea.id;
areaData.id = currentArea.id;
areaData.trainingAreaId = currentArea.id;
areaData.designation = QString::fromStdString(currentArea.name);
result.trainingAreas.append(TrainingAreaMessage(trainingAreaData, uuid));
result.areas.append(AreaMessage(areaData, uuid));
}
const auto structureElementsMap = m_mainHandler->getHandlerMainStructureElement()->getStructureElementMap();
const auto mainStructureElementMap = m_mainHandler->getHandlerMainStructureElement()->getMainStructureElementsMap();
for (auto it = structureElementsMap.begin(); it != structureElementsMap.end(); ++it)
{
ObjectStructureElement *currentElement = it.value();
switch (currentElement->getStructureElementTypeId())
{
case StructureElementType::TrainingArea:
case StructureElementType::City:
case StructureElementType::Section:
case StructureElementType::ApproachingPoint:
case StructureElementType::RadioStation:
continue;
case StructureElementType::MeteoDataUnit:
case StructureElementType::Bridge:
case StructureElementType::Announcement:
case StructureElementType::Building:
{
ObjectMessage::ObjectMessageData objectData;
ReplyMessage::LonLatPoint refPoint;
refPoint.lat = currentElement->getGeoPosition().lat;
refPoint.lon = currentElement->getGeoPosition().lon;
objectData.z = currentElement->getGeoPosition().z;
objectData.refPoint = refPoint;
objectData.pathRelative = pathForStructureId(currentElement->getId());
objectData.path = relativeToGeographic(objectData.refPoint, objectData.pathRelative);
objectData.designation = (currentElement->getData().displayName.size() > 0) ?
QString::fromStdString(currentElement->getData().displayName) :
QString::fromStdString(currentElement->getData().name);
objectData.id = currentElement->getId();
objectData.areaId = 6; // TODO: HACK - calculate from position
objectData.mseId = currentElement->getMainStructureElementId();
const ObjectMainStructureElement *mse = mainStructureElementMap.value(currentElement->getMainStructureElementId());
if (mse)
{
QJsonObject description = QJsonDocument::fromJson(mse->getDescription().toUtf8()).object();
objectData.street = description.value(QStringLiteral("street")).toString();
objectData.number = description.value(QStringLiteral("number")).toString();
objectData.rotationDegree = mse->getData().angle;
}
result.objects.append(ObjectMessage(objectData, uuid));
break;
}
case StructureElementType::Floor:
{
LevelMessage::LevelData levelData;
levelData.id = currentElement->getId();
levelData.objectid = currentElement->getPath().at(0);
levelData.designation = (currentElement->getData().displayName.size() > 0) ?
QString::fromStdString(currentElement->getData().displayName) :
QString::fromStdString(currentElement->getData().name);
levelData.number = determineFloorNumber(currentElement);
levelData.path = pathForStructureId(currentElement->getId());
levelData.zPos = currentElement->getRelativePosition().offsetZ;
result.levels.append(LevelMessage(levelData, uuid));
break;
}
case StructureElementType::Room:
{
RoomMessage::RoomData roomData;
roomData.id = currentElement->getId();
roomData.designation = (currentElement->getData().displayName.size() > 0) ?
QString::fromStdString(currentElement->getData().displayName) :
QString::fromStdString(currentElement->getData().name);
roomData.path = pathForStructureId(currentElement->getId());
roomData.levelId = currentElement->getPath().at(1);
result.rooms.append(RoomMessage(roomData, uuid));
break;
}
case StructureElementType::MountingPoint:
{
MountingPointMessage::MountingPointData mountingPointData;
mountingPointData.id = currentElement->getId();
mountingPointData.designation = (currentElement->getData().displayName.size() > 0) ?
QString::fromStdString(currentElement->getData().displayName) :
QString::fromStdString(currentElement->getData().name);
mountingPointData.tag = QString::fromStdString(currentElement->getData().barcode);
mountingPointData.objectId = currentElement->getPath().at(0);
mountingPointData.levelId = currentElement->getPath().size() > 2 ? currentElement->getPath().at(1) : -1;
mountingPointData.roomId = currentElement->getPath().size() > 2 ? currentElement->getPath().at(2) : -1;
mountingPointData.position3d.x = currentElement->getRelativePosition().offsetX;
mountingPointData.position3d.y = currentElement->getRelativePosition().offsetY;
mountingPointData.position3d.z = currentElement->getRelativePosition().offsetZ;
mountingPointData.supportedAssetTypIds.append(currentElement->getData().mountingPointTypeId);
mountingPointData.assetId = getMountedAssetId(currentElement->getId());
result.mountingPoints.append(MountingPointMessage(mountingPointData, uuid));
break;
}
}
}
// No BuildingNetworkSwitch and no AnnouncementUnit (see GUEZE-1548/1459)
AssetTypeMessage::AssetTypeData assetTypeData;
for (int i = MountingPointType::Unknown; i <= static_cast<int>(MountingPointType::EffectGenerationControlUnit); ++i)
{
if (i == static_cast<int>(MountingPointType::AnnouncementUnit))
continue;
assetTypeData.id = i;
assetTypeData.designation = toString(static_cast<MountingPointType>(i));
if (assetTypeData.designation.endsWith(QLatin1Char(')')))
continue;
assetTypeData.deviceClass = 1; // device class is just a dumy value here ...
result.assetTypes.append(AssetTypeMessage(assetTypeData, uuid));
}
return result;
}
//---------------------------------------------------------------------------------------------------------
QVector<Messages::PlannedMountingMessage> DataManager::getPlannedMounting(const QString &uuid) const
{
using namespace Messages;
const auto schedulesMap = m_mainHandler->getHandlerMainSchedule()->getMainScheduleMap();
QVector<PlannedMountingMessage> result;
result.reserve(schedulesMap.size());
PlannedMountingMessage::PlannedMountingData mountingData;
for (const ObjectMainSchedule *sched : schedulesMap)
{
const MainSchedule &data = sched->getData();
if (data.statusId == ScheduleStatus::Inactive)
continue;
mountingData.areaId = areaIdForScheduleId(data.id);
mountingData.plannedMountingId = data.id;
mountingData.designation = QString::fromStdString(data.name);
mountingData.mounting = entriesForScheduleId(data.id);
result.append(PlannedMountingMessage(mountingData, uuid));
}
return result;
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::getObjectMounting(int plannedMountingId, int objectId, const QString &uuid) const
{
// objectId = structureElementId
using namespace Messages;
ObjectMainSchedule *objMps = m_mainHandler->getHandlerMainSchedule()->getMainSchedule(plannedMountingId);
// check if plannedMountingId exists
if (!objMps)
{
LtsWebSocket::ErrorMessage::ErrorData errorData;
errorData.errorClass = 1;
errorData.errorMessage = QObject::tr("Planned mounting schedule id is invalid", "DataManager");
errorData.uuid = uuid;
WARNING_LOG(m_logger) << errorData.errorMessage << " - " << plannedMountingId;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(errorData);
return reply;
}
// check if objectId is valid
ObjectStructureElement *buildingEle = m_mainHandler->getHandlerMainStructureElement()->getStructureElement(objectId);
if (buildingEle == nullptr ||
buildingEle->getStructureElementTypeId() != StructureElementType::Building)
{
LtsWebSocket::ErrorMessage::ErrorData errorData;
errorData.errorClass = 1;
errorData.errorMessage = QObject::tr("Building id is invalid", "DataManager");
errorData.uuid = uuid;
WARNING_LOG(m_logger) << errorData.errorMessage << " - " << (buildingEle ? buildingEle->getStructureElementTypeId() : -1)
<< ", " << plannedMountingId << ", " << objectId;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(errorData);
return reply;
}
// check if building with ID objectId has a plan
if (!isPlannedObject(objectId))
{
LtsWebSocket::ErrorMessage::ErrorData errorData;
errorData.errorClass = 1;
errorData.errorMessage = QObject::tr("There is no planned data available for building with id %1", "DataManager").
arg(objectId);
errorData.uuid = uuid;
WARNING_LOG(m_logger) << errorData.errorMessage << " - " << plannedMountingId << ", " << objectId;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(errorData);
return reply;
}
ObjectMountingMessage::ObjectMountingData objectMountingData;
objectMountingData.objectId = objectId;
objectMountingData.plannedMountingId = plannedMountingId;
objectMountingData.planned = entriesForBuildingInSchedule(plannedMountingId, buildingEle->getMainStructureElementId());
return new ObjectMountingMessage(objectMountingData, uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mountTag(const QString &mountingPointTag,
const QString &assetTag,
const QString &messageType,
const QString &uuid) const
{
using namespace Messages;
QString okMessage;
std::shared_ptr<HandlerMountingPointAsset> mountingPointAssetHandler = m_mainHandler->getHandlerMountingPointAsset();
int32_t mountingPointId = -1;
int32_t assetId = -1;
// check if mountingPointTag exists
if (!mountingPointTag.isEmpty())
{
mountingPointId = mountingPointIdFromBarcode(mountingPointTag);
if (mountingPointId == -1)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Got invalid mounting point tag '%1'", "DataManager").
arg(mountingPointTag);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
}
// check if assetTag exists
if (!assetTag.isEmpty())
{
assetId = assetIdFromBarcode(assetTag);
if (assetId == -1)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Got invalid instrumentation asset tag '%1'", "DataManager").
arg(assetTag);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
}
if(assetId > 0)
{
ObjectInstrumentationAsset *asset = m_mainHandler->getHandlerInstrumentationAsset()->getAssetFromId(assetId);
if(asset->getData().assetStateId == InstrumentationAssetState::Defect)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Got defect instrumentation asset with id '%1'", "DataManager").
arg(assetId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
}
if (mountingPointId == -1 &&
assetId >= 0) // unmount mounting point
{
if (!mountingPointAssetHandler->unmountAsset(assetId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting instrumentation asset with id %1", "DataManager").
arg(assetId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
okMessage = QObject::tr("Successfully unmounted instrumentation asset with id %1", "DataManager").
arg(assetId);
}
else if (assetId == -1 &&
mountingPointId >= 0) // unmount asset
{
if (!mountingPointAssetHandler->unmountMountingPoint(mountingPointId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting mounting point with id %1", "DataManager").
arg(mountingPointId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
okMessage = QObject::tr("Successfully unmounted mounting point with id %1", "DataManager").
arg(mountingPointId);
}
else if (assetId >= 0 &&
mountingPointId >= 0)
{
if (!mountingPointAssetHandler->mount(assetId, mountingPointId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error mounting instrumentation asset with id %1 on mounting point with id %2", "DataManager").
arg(assetId).
arg(mountingPointId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
}
else if (assetId == -1 &&
mountingPointId == -1)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Got 'mountTag' message with empty tags", "DataManager");;
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
OkMessage::OkData data;
if (okMessage.isEmpty())
okMessage = QObject::tr("Successfully mounted instrumentation asset with id %1 on mounting point with id %2", "DataManager").
arg(assetId).
arg(mountingPointId);
data.messageType = messageType;
data.uuid = uuid;
data.info = okMessage;
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mount(int32_t mountingPointId, int32_t assetId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
if (!m_mainHandler->getHandlerMountingPointAsset()->mount(assetId, mountingPointId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error mounting instrumentation asset with id %1 on mounting point with id %2", "DataManager").
arg(assetId).
arg(mountingPointId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
OkMessage::OkData data;
data.messageType = messageType;
data.uuid = uuid;
data.info = QObject::tr("Successfully mounted instrumentation asset with id %1 on mounting point with id %2", "DataManager").
arg(assetId).
arg(mountingPointId);
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::unmountAsset(int32_t assetId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
if (!m_mainHandler->getHandlerMountingPointAsset()->unmountAsset(assetId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting instrumentation asset with id %1", "DataManager").
arg(assetId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
LtsWebSocket::ReplyMessage *reply = new LtsWebSocket::ErrorMessage(data);
return reply;
}
OkMessage::OkData data;
data.messageType = messageType;
data.uuid = uuid;
data.info = QObject::tr("Successfully unmounted instrumentation asset with id %1", "DataManager").
arg(assetId);
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::unmountMountingPoint(int32_t mountingPointId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
if (!m_mainHandler->getHandlerMountingPointAsset()->unmountMountingPoint(mountingPointId))
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting mounting point with id %1", "DataManager").
arg(mountingPointId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
OkMessage::OkData data;
data.messageType = messageType;
data.uuid = uuid;
data.info = QObject::tr("Successfully unmounted mounting point with id %1").
arg(mountingPointId);
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::unmountObject(int32_t objectId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
ObjectStructureElement *buildingSe = m_mainHandler->getHandlerMainStructureElement()->getStructureElement(objectId);
ObjectMainStructureElement *building = nullptr;
if (buildingSe)
building = buildingSe->getMainStructureElement();
if (building == nullptr)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting building - building id %1 is invalid", "DataManager").
arg(objectId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
QStringList errorIds;
std::shared_ptr<HandlerMountingPointAsset> mountingPointAssetHandler = m_mainHandler->getHandlerMountingPointAsset();
const auto seElements = building->getStructureElements();
for (ObjectStructureElement *currentElement : seElements)
{
if (currentElement->getStructureElementTypeId() != StructureElementType::MountingPoint)
continue;
int32_t assetId = mountingPointAssetHandler->getMountedAssetId(currentElement->getId());
if (assetId <= 0)
continue;
if (!mountingPointAssetHandler->unmountMountingPoint(currentElement->getId()))
errorIds.append(QString::number(currentElement->getId()));
}
if (!errorIds.isEmpty())
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting the following mounting point(s): %1", "DataManager").
arg(errorIds.join(QLatin1String(", ")));
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
OkMessage::OkData data;
data.info = QObject::tr("Successfully unmounted building with id %1", "DataManager").
arg(objectId);
data.messageType = messageType;
data.uuid = uuid;
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::unmountArea(int32_t areaId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
std::shared_ptr<HandlerMainStructureElement> structEleHandler = m_mainHandler->getHandlerMainStructureElement();
std::shared_ptr<HandlerMountingPointAsset> mountingPointAssetHandler = m_mainHandler->getHandlerMountingPointAsset();
const auto structEleMap = structEleHandler->getStructureElementMap();
QStringList errorIds;
bool isValidAreaId = false;
for (const auto &seElem : structEleMap)
{
if (seElem->getStructureElementTypeId() == StructureElementType::MountingPoint)
{
if (!seElem->getData().path.size())
continue;
int32_t buildingId = seElem->getData().path[0];
if (structEleMap.value(buildingId)->getParentId() == areaId)
{
isValidAreaId = true;
if (!mountingPointAssetHandler->unmountMountingPoint(seElem->getId()))
errorIds.append(QString::number(seElem->getId()));
}
}
}
if (!isValidAreaId)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting training area with id %1. Id is invalid", "DataManager").
arg(areaId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
if (!errorIds.isEmpty())
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Error unmounting the following mounting point(s): %1", "DataManager").
arg(errorIds.join(QLatin1String(", ")));
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
OkMessage::OkData data;
data.info = QObject::tr("Successfully unmounted training area with id %1").
arg(areaId);
data.messageType = messageType;
data.uuid = uuid;
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::objectMountingReady(int32_t plannedMountingId, int32_t objectId, const QString &messageType, const QString &uuid) const
{
using namespace Messages;
std::shared_ptr<HandlerMainStructureElement> structEleHandler = m_mainHandler->getHandlerMainStructureElement();
const auto structEleMap = structEleHandler->getStructureElementMap();
const auto mountingPointPlans = m_mainHandler->getHandlerMainSchedule()->getMountingPointPlans(plannedMountingId);
bool isValidObjectId = false;
QStringList missingMountingPoints;
missingMountingPoints.reserve(mountingPointPlans.size());
for (const auto &mpp : mountingPointPlans)
{
int32_t structEleId = mpp.structureElementId;
int32_t buildingId = -1;
if (structEleMap.value(structEleId)->getData().path.size())
buildingId = structEleMap.value(structEleId)->getData().path[0];
if (buildingId == objectId)
{
isValidObjectId = true;
if (!isMounted(structEleId))
missingMountingPoints.append(QString::number(structEleId));
}
}
if (!isValidObjectId)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Building with id %1 is invalid", "DataManager")
.arg(objectId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
if (!missingMountingPoints.isEmpty())
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("The following mounting points are not ready: %1", "DataManager")
.arg(missingMountingPoints.join(QStringLiteral(", ")));
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
OkMessage::OkData data;
data.info = QObject::tr("Building with id %1 is ready", "DataManager")
.arg(objectId);
data.messageType = messageType;
data.uuid = uuid;
return new OkMessage(data);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::getAssetState(int32_t assetId, const QString &assetTag, const QString &uuid) const
{
using namespace Messages;
QString errorString;
ObjectInstrumentationAsset *asset = nullptr;
std::shared_ptr<HandlerInstrumentationAsset> assetHandler = m_mainHandler->getHandlerInstrumentationAsset();
if (assetId == 0 && assetTag.isEmpty())
errorString = QObject::tr("Not possible to get instrumentation asset state for empty id and tag", "DataManager");
else if (assetId == 0)
asset = assetHandler->getAssetFromBarcode(assetTag);
else if (assetTag.isEmpty())
asset = assetHandler->getAssetFromId(assetId);
else
asset = assetHandler->getAssetFromBarcodeAndId(assetTag, assetId);
if (asset == nullptr)
errorString = QObject::tr("Either instrumentation asset id %1 or instrumentation asset tag %2 is invalid").
arg(assetId).
arg(assetTag);
if (!errorString.isEmpty())
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = errorString;
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
return new AssetStateMessage(assetData(asset), uuid);
}
LtsWebSocket::ReplyMessage *DataManager::getAssets(const QSet<int> &assetTypeIds, const QString &uuid) const
{
using namespace Messages;
for (const int value : assetTypeIds)
DEBUG_LOG(m_logger) << "getAssets assetTypeId =" << value;
const auto m = m_mainHandler->getHandlerInstrumentationAsset()->getObjectInstrumentationAssetMap();
QVector<AssetData> assets;
for (const ObjectInstrumentationAsset *asset : m)
{
if (assetTypeIds.contains(asset->getData().mountingPointTypeId))
assets += assetData(asset);
}
return new AssetsMessage(assets, uuid);
}
LtsWebSocket::ReplyMessage *DataManager::getBuildingState(int32_t buildingId, const QString &uuid) const
{
using namespace Messages;
std::shared_ptr<HandlerMainStructureElement> structEleHandler = m_mainHandler->getHandlerMainStructureElement();
std::shared_ptr<HandlerMountingPointAsset> mountingPointAssetHandler = m_mainHandler->getHandlerMountingPointAsset();
ObjectMainStructureElement *mse = nullptr;
if (buildingId > 0)
{
const auto ose = structEleHandler->getStructureElement(buildingId);
mse = ose ? structEleHandler->getMainStructureElement(ose->getMainStructureElementId()) : nullptr;
}
if (!mse)
{
LtsWebSocket::ErrorMessage::ErrorData data;
data.errorClass = 1;
data.errorMessage = QObject::tr("Building id %1 is invalid", "DataManager").arg(buildingId);
data.uuid = uuid;
WARNING_LOG(m_logger) << data.errorMessage;
return new LtsWebSocket::ErrorMessage(data);
}
AssetStateObjectMessage::AssetStateObjectData data;
AssetStateObjectMessage::AssetStatesEntry entry;
data.objectId = buildingId;
data.time = QDateTime::currentDateTime().toString(QStringLiteral("dd:MM:yy hh:mm"));
for (const StructureElement &currentElement : mse->getElements())
{
if (currentElement.structureElementTypeId == InfrastructureManagement::StructureElementType::MountingPoint)
{
int32_t assetId = mountingPointAssetHandler->getMountedAssetId(currentElement.id);
if (assetId)
{
const AssetData assetDat = assetData(assetId);
entry.assetId = assetId;
entry.assetTypeId = assetDat.assetTypeId;
entry.hostname = assetDat.hostname;
entry.mountingPointId = assetDat.mountingPointId;
entry.state = assetDat.state;
data.assetStates.append(entry);
}
}
}
return new AssetStateObjectMessage(data, uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::assetBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmAsset, Messages::AssetBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mainStructureElementBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmMainStructureElement, Messages::MainStructureElementBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::structureElementBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmStructureElement, Messages::StructureElementBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::structureElementFootprintBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmStructureElementFootprint, Messages::StructureElementFootprintBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mountingPointAssetBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmMountingPointAsset, Messages::MountingPointAssetBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mountingPointScheduleBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmMountingPointSchedule, Messages::MountingPointScheduleBaseData>(uuid);
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::mountingPointPlanBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::IsmMountingPointPlan, Messages::MountingPointPlanBaseData>(uuid);
}
QVector<Messages::ReplyMessage::LonLatPoint> DataManager::relativeToGeographic(const Messages::ReplyMessage::LonLatPoint &pos,
const QVector<Messages::ReplyMessage::XYPoint> &relPoints)
{
QVector<Messages::ReplyMessage::LonLatPoint> ret;
ret.reserve(relPoints.size());
const LtsCoordTrans::UtmCoordinate base(LtsCoordTrans::UtmCoordinate::fromGeographic(pos.lon, pos.lat));
for (const auto &relPoint : relPoints)
{
const auto absPoint = base.geographic(relPoint.x, relPoint.y);
Messages::ReplyMessage::LonLatPoint p;
p.lon = absPoint.x();
p.lat = absPoint.y();
ret.push_back(std::move(p));
}
return ret;
}
// -------------------------------------------------------------------------------------------------------
QVector<Messages::ReplyMessage::XYPoint> DataManager::pathForStructureId(int32_t structureElementId) const
{
using namespace Messages;
QVector<ReplyMessage::XYPoint> result;
// we currently only have paths for MainStructureElements (== Buildings)
// -> search all buildings for structureElementId
ObjectMainStructureElement *mse = nullptr;
const auto objMap = m_mainHandler->getHandlerMainStructureElement()->getMainStructureElementsMap();
for (ObjectMainStructureElement *obj : objMap)
{
if (obj->getStructureElementId() == structureElementId)
{
mse = obj;
break;
}
}
if (!mse)
return result;
const MainFootprint &footprint = mse->getFootprint();
ReplyMessage::XYPoint newPoint;
result.reserve(footprint.elements.size());
const double angleDegree = mse->getData().angle;
for (const FootprintElement &fpElem : footprint.elements)
{
const QPointF offset = rotatePoint(fpElem.relPosition.offsetX, fpElem.relPosition.offsetY, angleDegree);
newPoint.x = offset.x();
newPoint.y = offset.y();
result.append(newPoint);
}
return result;
}
//---------------------------------------------------------------------------------------------------------
QVector<Messages::PlannedMountingMessage::MountingEntry> DataManager::entriesForScheduleId(int32_t scheduleId) const
{
using namespace Messages;
QVector<PlannedMountingMessage::MountingEntry> result;
PlannedMountingMessage::MountingEntry entry;
QSet<int> involvedBuildingIds;
std::shared_ptr<HandlerMainStructureElement> structEleHandler = m_mainHandler->getHandlerMainStructureElement();
for (const MountingPointPlan &currentPlan : m_mainHandler->getHandlerMainSchedule()->getMountingPointPlans(scheduleId))
{
const auto path = structEleHandler->getStructureElement(currentPlan.structureElementId)->getPath();
int32_t buildingId = -1;
if (path.size())
buildingId = path[0];
if (involvedBuildingIds.contains(buildingId))
continue;
involvedBuildingIds.insert(buildingId);
entry.id = buildingId;
entry.state = stateForBuilding(buildingId);
result.append(entry);
}
return result;
}
//---------------------------------------------------------------------------------------------------------
int32_t DataManager::areaIdForScheduleId(int32_t scheduleId) const
{
const auto mountingPointPlans = m_mainHandler->getHandlerMainSchedule()->getMountingPointPlans(scheduleId);
std::shared_ptr<HandlerMainStructureElement> structureElementHandler = m_mainHandler->getHandlerMainStructureElement();
for (const auto &data : mountingPointPlans)
{
int32_t buildingId = structureElementHandler->getStructureElement(data.structureElementId)->getPath()[0];
return structureElementHandler->getStructureElement(buildingId)->getParentId();
}
return -1;
}
//---------------------------------------------------------------------------------------------------------
int32_t DataManager::stateForBuilding(int32_t buildingId) const
{
bool isFullyMounted = true;
bool isPartlyMounted = false;
ObjectMainStructureElement *objMse = m_mainHandler->getHandlerMainStructureElement()->getMainStructureElement(buildingId);
if (!objMse)
return -1;
const auto seElements = objMse->getStructureElements();
for (ObjectStructureElement *currentElement : seElements)
{
if (currentElement->getStructureElementTypeId() == StructureElementType::MountingPoint)
{
bool isMountingPointMounted = isMounted(currentElement->getId());
isFullyMounted &= isMountingPointMounted;
isPartlyMounted |= isMountingPointMounted;
}
}
if (isFullyMounted)
return 1;
if (isPartlyMounted)
return 0;
return -1;
}
//---------------------------------------------------------------------------------------------------------
bool DataManager::isMounted(int32_t mountingPointId) const
{
return getMountedAssetId(mountingPointId) != -1;
}
//---------------------------------------------------------------------------------------------------------
bool DataManager::isPlannedObject(int32_t objectId) const
{
std::shared_ptr<HandlerMainStructureElement> structEleHandler = m_mainHandler->getHandlerMainStructureElement();
for (const int mainScheduleId : m_mainHandler->getHandlerMainSchedule()->getMainScheduleMap().keys())
{
for (const auto &mpp : m_mainHandler->getHandlerMainSchedule()->getMountingPointPlans(mainScheduleId))
{
const auto path = structEleHandler->getStructureElement(mpp.structureElementId)->getPath();
if (!path.size())
continue;
if (path[0] == objectId)
return true;
}
}
return false;
}
//---------------------------------------------------------------------------------------------------------
QVector<Messages::ObjectMountingMessage::PlannedEntry> DataManager::entriesForBuildingInSchedule(int32_t scheduleId, int32_t buildingId) const
{
using namespace Messages;
QVector<ObjectMountingMessage::PlannedEntry> result;
ObjectMountingMessage::PlannedEntry entry;
ObjectMainStructureElement *objMse = m_mainHandler->getHandlerMainStructureElement()->getMainStructureElement(buildingId);
if (!objMse)
return result;
const auto seElements = objMse->getStructureElements();
for (ObjectStructureElement *currentElement : seElements)
{
if (currentElement->getStructureElementTypeId() == StructureElementType::MountingPoint)
{
MountingPointState mountingPointState = getMountingPointState(currentElement->getId(), scheduleId);
if (mountingPointState != MountingPointState::Idle)
{
entry.id = currentElement->getId();
entry.assetId = getMountedAssetId(currentElement->getId());
entry.planningState = mountingPointState == MountingPointState::Empty ? 0 : 1;
result.append(entry);
}
}
}
return result;
}
//---------------------------------------------------------------------------------------------------------
int32_t DataManager::getMountedAssetId(int32_t mountingPointId) const
{
const auto mountingPointAssetMap = m_mainHandler->getHandlerMountingPointAsset()->getMountingPointAssetMap();
for (const auto &p : mountingPointAssetMap)
{
if (p->getStructureElementId() == mountingPointId)
return p->getAssetId();
}
return -1;
}
//---------------------------------------------------------------------------------------------------------
int32_t DataManager::mountingPointIdFromBarcode(const QString &barcode) const
{
const auto structEleMap = m_mainHandler->getHandlerMainStructureElement()->getStructureElementMap();
const auto barcodeStd(barcode.toStdString());
for (const auto &p : structEleMap)
{
if (p->getStructureElementTypeId() == StructureElementType::MountingPoint &&
p->getData().barcode == barcodeStd)
return p->getId();
}
return -1;
}
//---------------------------------------------------------------------------------------------------------
int32_t DataManager::assetIdFromBarcode(const QString &barcode) const
{
const auto assetMap = m_mainHandler->getHandlerInstrumentationAsset()->getObjectInstrumentationAssetMap();
const auto barcodeStd(barcode.toStdString());
for (const auto &p : assetMap)
{
if (p->getData().barcode == barcodeStd)
return p->getId();
}
return -1;
}
//---------------------------------------------------------------------------------------------------------
Messages::AssetData DataManager::assetData(int32_t assetId) const
{
return assetData(m_mainHandler->getHandlerInstrumentationAsset()->getAssetFromId(assetId));
}
//---------------------------------------------------------------------------------------------------------
Messages::AssetData DataManager::assetData(const ObjectInstrumentationAsset *asset) const
{
Messages::AssetData result;
if (asset == nullptr)
return result;
result.mountingPointId = -1;
const auto mountingPointAssetMap = m_mainHandler->getHandlerMountingPointAsset()->getMountingPointAssetMap();
for (const auto &p : mountingPointAssetMap)
{
if (p->getAssetId() == asset->getId())
{
result.mountingPointId = p->getStructureElementId();
break;
}
}
result.id = asset->getId();
result.assetTypeId = asset->getData().mountingPointTypeId;
result.assetTag = QString::fromStdString(asset->getData().barcode);
result.designation = QString::fromStdString(asset->getData().name);
result.hostname = QString::fromStdString(asset->getData().hostname);
result.state = toString(asset->getData().assetStateId);
result.time = QDateTime::fromMSecsSinceEpoch(asset->getData().lastUpdated).toString(QStringLiteral("dd:MM:yy hh:mm"));
if (asset->getData().assetStateId == InstrumentationAssetState::Defect)
result.errorDescription = QObject::tr("Instrumentation asset not working properly");
return result;
}
//---------------------------------------------------------------------------------------------------------
MountingPointState DataManager::getMountingPointState(int32_t mountingPointId, int32_t scheduleId) const
{
for (const auto &data : m_mainHandler->getHandlerMainSchedule()->getMountingPointPlans(scheduleId))
{
if (data.structureElementId == mountingPointId)
return data.mountingPointState;
}
return MountingPointState::Idle;
}