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

+192
View File
@@ -0,0 +1,192 @@
#
# $Id$
# $HeadURL$
# $Author$
#
INCLUDE(MacroRTIDDSGen)
INCLUDE(MacroCodeGenIdl)
SET(xml_FILE whg_service.xml)
#
# --- Library svcWhgCommon --------------------------------------------------------------------------------
#
SET(SRCS_common
whg_export.h
logger.cpp
logger.h
)
# Generate whg_enums.idl / whg.idl
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
# Generate whg_db_impl.cpp/.h, whg_db.h
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
# Generate *.cpp/*.hpp from idl
RTIDDSGEN(SRCS_common whg_enums.idl)
RTIDDSGEN(SRCS_common whg.idl)
# Generate whg_dt[s,c]_types.h, whg_ft[s,c]_types.h
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
# Generate whg_[d|f]tc.h
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV WS svcWhgCommon SHARED ${SRCS_common})
NGL_TARGET_INCLUDE_DIRECTORIES(svcWhgCommon
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcWhgCommon
PRIVATE
RTI::nddscpp2
PUBLIC
Qt5::Core
ddscore
NGLLogger
ngldb
)
NGL_INSTALL_TARGET(svcWhgCommon)
#
# --- Library svcWhgClient --------------------------------------------------------------------------------
#
SET(SRCS_client
whg_export.h
)
# generate whg_[d|f]tc.h, whg_[d|f]tc_impl.[cpp|h]
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV WS svcWhgClient SHARED ${SRCS_client})
NGL_TARGET_INCLUDE_DIRECTORIES(svcWhgClient
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcWhgClient
PRIVATE
RTI::nddscpp2
ddsconnector
PUBLIC
svcWhgCommon
ddsftc
)
NGL_INSTALL_TARGET(svcWhgClient)
#
# --- Library svcWhgServer --------------------------------------------------------------------------------
#
SET(SRCS_server
whg_export.h
)
# generate whg_[d|f]ts.h, whg_[d|f]ts_impl.[cpp|h]
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV svcWhgServer SHARED ${SRCS_server})
NGL_TARGET_INCLUDE_DIRECTORIES(svcWhgServer
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcWhgServer
PRIVATE
RTI::nddscpp2
ddsconnector
ddsfts
PUBLIC
svcWhgCommon
ngldb
)
NGL_INSTALL_TARGET(svcWhgServer)
#
# --- Topic Type Plugin --------------------------------------------------------------
#
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
#
# --- Executable svcWarehouseGuez (sWHG) -------------------------------------------------
#
SET(SRCS_exe
main.cpp
main_handler.cpp
main_handler.h
dds_handler.cpp
dds_handler.h
handler_equipment_type_wh.cpp
handler_equipment_type_wh.h
handler_injury_model.cpp
handler_injury_model.h
handler_types.cpp
handler_types.h
object_equipment_type_wh.cpp
object_equipment_type_wh.h
object_injury_model.cpp
object_injury_model.h
settings.cpp
settings.h
WsBaseDataInterface/data_manager.cpp
WsBaseDataInterface/data_manager.h
WsBaseDataInterface/Messages/client_message.cpp
WsBaseDataInterface/Messages/client_message.h
WsBaseDataInterface/Messages/reply_message.cpp
WsBaseDataInterface/Messages/reply_message.h
WsBaseDataInterface/ws_base_data_interface_handler.cpp
WsBaseDataInterface/ws_base_data_interface_handler.h
WsBiteInterface/Connection/client_connection.cpp
WsBiteInterface/Connection/client_connection.h
WsBiteInterface/Connection/connection_handler.cpp
WsBiteInterface/Connection/connection_handler.h
WsBiteInterface/json_keys.h
WsBiteInterface/bite_data_manager.cpp
WsBiteInterface/bite_data_manager.h
WsBiteInterface/Messages/ws_client_message.cpp
WsBiteInterface/Messages/ws_client_message.h
WsBiteInterface/Messages/message_handler.cpp
WsBiteInterface/Messages/message_handler.h
WsBiteInterface/Messages/message_transmitter.h
WsBiteInterface/Messages/ws_reply_message.cpp
WsBiteInterface/Messages/ws_reply_message.h
WsBiteInterface/ws_bite_interface_handler.cpp
WsBiteInterface/ws_bite_interface_handler.h
${xml_FILE}
)
# Generate whg.sql, whg.xml
CODEGEN_SQL(SRCS_exe ${xml_FILE})
NGL_ADD_SVC_ICON(SRCS_exe)
NGL_ADD_EXECUTABLE(AAR SV svcWarehouseGuez ${SRCS_exe})
NGL_TARGET_LINK_LIBRARIES(svcWarehouseGuez
Qt5::Core
Qt5::Network
svcCoreClient
svcWhgCommon
svcWhgServer
ddsconnector
nglsettings
ProjectConfig
LtsCommandLineParser
LtsWebSocketServer
NGLLogger
nglcoreapplication
ngltools
codegen_base
wms_json_ds
svcPpmClient
svcTabClient
)
NGL_INSTALL_TARGET(svcWarehouseGuez)
NGL_INSTALL(AAR SV FILES log4cxx_whg.props DESTINATION bin)
NGL_ADD_TARGET_LINK(svcWarehouseGuez sWHG)
# Uncomment if necessary
#ADD_SUBDIRECTORY(UnitTests)
ADD_SUBDIRECTORY(ModuleTests)
+35
View File
@@ -0,0 +1,35 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS_MRK_TEST
whg_tests.cpp
)
SET(HDRS_MRK_TEST
whg_tests.h
)
IF(BUILD_TESTING)
IF(TARGET svcWhgClient)
# Testing FunctionTopic Functionality (FTC)
ADD_EXECUTABLE(whgTests ${SRCS_MRK_TEST} ${HDRS_MRK_TEST})
TARGET_LINK_LIBRARIES(whgTests
Qt5::Core
Qt5::Test
RTI::nddscpp2
svcWhgClient
LtsCommandLineParser
ddsconnector
nglcoreapplication
nglsettings
LtsWebSocketClient
)
IF(NOT BUILD_RPM)
NGL_INSTALL(AAR SV TARGETS whgTests DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES ../log4cxx_whg.props DESTINATION bin/test)
ENDIF()
ENDIF()
ENDIF()
+705
View File
@@ -0,0 +1,705 @@
/**
* whg Function Topic test executable
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-04-18
*/
#include "whg_tests.h"
#include <nglapplication/nglcoreapplication.h>
#include <nglsettings/nglsettings_connections.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <QTimer>
#include <QDateTime>
#include <QString>
#include <QVector>
#include <QJsonObject>
#include <QJsonDocument>
#include <QtNetwork/QHostAddress>
#include <WarehouseGuez/whg_ftc.h>
#include <WarehouseGuez/whg_dtc.h>
#include <WarehouseGuez/WsBiteInterface/json_keys.h>
using namespace WarehouseGuez;
using namespace WsBiteInterface;
//-----------------------------------------------------------------------------
WhgTests::WhgTests(QObject *parent)
: QObject(parent)
, m_testId(0)
, m_equipmentTypeWhId(-1)
, m_injuryModelWhId(0)
, m_equipNo(0)
, m_boxId(0)
, m_eTestStep(eUnknown)
, m_bTestsSuccessful(true)
, m_logger(getLogger("Test"))
{
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
} // end of ctor()
//-----------------------------------------------------------------------------
WhgTests::~WhgTests()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool WhgTests::init(int domainId, int testId, int eqtTypeWhId, int injuryModelWhId, int equipNo, int boxId)
{
INFO_LOG(m_logger) << "WhgTests::init() "
<< " domainId:" << domainId
<< " testId: " << testId
<< " equipmentTypeWhId: " << eqtTypeWhId
<< " equipNo: " << equipNo
<< " boxId: " << boxId;
;
m_testId = testId;
m_equipmentTypeWhId = eqtTypeWhId;
m_injuryModelWhId = injuryModelWhId;
m_equipNo = equipNo;
m_boxId = boxId;
// initialize DDS
m_ddsConnector.reset(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Global, 0));
if (!m_ddsConnector->init())
return false;
m_ddsConnector->initPublisherSubscriber();
// Access to FTC
DEBUG_LOG(m_logger) << "create ftc";
m_ftc = WarehouseGuez::Interface::Ftc::create(m_ddsConnector);
DEBUG_LOG(m_logger) << "init ftc";
bool bRet = m_ftc->enableAll();
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
// Access to DTC
DEBUG_LOG(m_logger) << "create dtc";
m_dtc = WarehouseGuez::Interface::Dtc::create(m_ddsConnector);
DEBUG_LOG(m_logger) << "init dtc";
bRet = m_dtc->enableAll();
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
connect(&m_wsClient, &QWebSocket::connected, this, &WhgTests::onConnected);
connect(&m_wsClient, &QWebSocket::textMessageReceived, this, &WhgTests::onTextMessageReceived);
int port = NGL::Connections::port(NGL::Connections::eConnection::LVS);
ERROR_LOG(m_logger) << "Port:_ " << port;
//QUrl url(QStringLiteral("ws://%1:%2").arg(QStringLiteral("localhost"), QString::number(9094)));
QUrl url(QStringLiteral("ws://%1:%2").arg(QStringLiteral("localhost"), QString::number(port)));
m_wsClient.open(url);
return bRet;
} // end of init()
void WhgTests::onConnected()
{
ERROR_LOG(m_logger) << "wsClient connected";
startTest();
}
void WhgTests::onTextMessageReceived(const QString &msg)
{
INFO_LOG(m_logger) << "new text message: " << msg;
//QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//-----------------------------------------------------------------------------
void WhgTests::startTest()
{
INFO_LOG(m_logger) << "startTest()"
<< " testId:" << m_testId
<< " eqtTypeWhId:" << m_equipmentTypeWhId
;
connect(m_dtc.get(), &Interface::Dtc::equipmentTypeWhChanged,
this, &WhgTests::onReceiveEqtTypeChanged);
if (m_testId <= 1)
QTimer::singleShot(0, this, &WhgTests::tryCreate);
else if (m_testId == 2)
QTimer::singleShot(0, this, &WhgTests::tryModify);
else if (m_testId == 3)
QTimer::singleShot(0, this, &WhgTests::tryRemove);
else if (m_testId == 4)
QTimer::singleShot(0, this, &WhgTests::tryCreateInjuryModel);
else if (m_testId == 5)
QTimer::singleShot(0, this, &WhgTests::tryModifyInjuryModel);
else if (m_testId == 6)
QTimer::singleShot(0, this, &WhgTests::tryRemoveInjuryModel);
else if (m_testId == 10)
QTimer::singleShot(0, this, &WhgTests::tryGetAllEquipmentTypesWh);
else if (m_testId == 11)
QTimer::singleShot(0, this, &WhgTests::tryGetEquipmentTypeWh);
else if (m_testId == 12)
QTimer::singleShot(0, this, &WhgTests::tryGetBiteData);
else
{
ERROR_LOG(m_logger) << "Unknown test id " << m_testId;
failExit();
}
//QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of startTest()
//-----------------------------------------------------------------------------
void WhgTests::tryCreate()
{
m_eTestStep = eCreate;
EquipmentTypeWh data;
getEqtTypeWhCreateRequestData(data);
INFO_LOG(m_logger) << "trying to send create EquipmentTypeWh Request";
if (!m_ftc->modifyEquipmentTypeWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
} // end of tryCreate()
//-----------------------------------------------------------------------------
void WhgTests::tryModify()
{
m_eTestStep = eModify;
EquipmentTypeWh data;
getEqtTypeWhModifyRequestData(data);
INFO_LOG(m_logger) << "trying to send ModifyEquipementTypeWhRequest for eqtTypeWhId:" << data.id();
if (!m_ftc->modifyEquipmentTypeWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting modify data for eqtTypeWhId:" << data.id();
failExit();
}
} // end of tryModify()
//-----------------------------------------------------------------------------
void WhgTests::tryRemove()
{
m_eTestStep = eRemove;
RemoveEquipmentTypeWhRequest data;
data.id(m_equipmentTypeWhId);
INFO_LOG(m_logger) << "trying to send remove request for eqtTypeWhId:" << data.id();
if (!m_ftc->removeEquipmentTypeWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting remove data for eqtTypeWhId:" << data.id();
failExit();
}
} // end of tryRemove()
//-----------------------------------------------------------------------------
void WhgTests::tryGetAllEquipmentTypesWh()
{
m_eTestStep = eGetAllEquipmentTypesWh;
DEBUG_LOG(m_logger) << "trying to get all eqtTypesWh";
m_dtc->waitForHistoricalDataEquipmentTypeWh();
const QMap<qint32, WarehouseGuez::EquipmentTypeWh> map = m_dtc->equipmentTypeWhs();
if (map.isEmpty())
{
ERROR_LOG(m_logger) << "Error requesting all eqtTypesWh data";
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
return;
}
INFO_LOG(m_logger) << "Amout of existing eqtTypesWh:" << map.size();
m_equipmentTypeWhId = map.firstKey();
for (auto it = map.begin(); it != map.end(); ++it)
{
INFO_LOG(m_logger) << "whg(" << it.key() << ") :"
<< " name:" << it.value().name()
<< " minEquipNo:" << it.value().minEquipNo()
<< " maxEquipNo:" << it.value().maxEquipNo()
<< " vbAgdus:" << it.value().vbAgdusId();
}
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of tryGetAllEquipmentTypesWh()
//-----------------------------------------------------------------------------
void WhgTests::tryGetEquipmentTypeWh()
{
DEBUG_LOG(m_logger) << "trying to get eqtTypeWh with id:" << m_equipmentTypeWhId;
if (m_testId > 1)
m_eTestStep = eGetEquipmentTypeWh;
if (m_equipmentTypeWhId < 0)
{
ERROR_LOG(m_logger) << "invalid eqtTypeWhId - test aborted.";
failExit();
}
m_dtc->waitForHistoricalDataEquipmentTypeWh();
WarehouseGuez::EquipmentTypeWh data = m_dtc->equipmentTypeWh(m_equipmentTypeWhId);
if (data.id() < 0)
{
ERROR_LOG(m_logger) << "Error receiving data for equipmentTypeId " << m_equipmentTypeWhId << " returnVal:" << data.id();
failExit();
}
else
{
INFO_LOG(m_logger) << "whg(" << data.id() << ") :"
<< " name:" << data.name()
<< " minEquipNo:" << data.minEquipNo()
<< " maxEquipNo:" << data.maxEquipNo()
<< " vbAgdus:" << data.vbAgdusId();
}
if (m_testId == 0)
{
if (m_eTestStep == eCreate)
{
if (! onCompareCreatedData(data))
{
ERROR_LOG(m_logger) << "Compare created data failed!";
failExit();
}
else
{
QTimer::singleShot(0, this, &WhgTests::tryModify);
return;
}
}
else if (m_eTestStep == eModify)
{
if (! onCompareModifiedData(data))
{
ERROR_LOG(m_logger) << "Compare modified data failed!";
failExit();
}
else
{
QTimer::singleShot(0, this, &WhgTests::tryRemove);
return;
}
}
}
else
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of tryGetEquipmentTypeWh()
//-----------------------------------------------------------------------------
void WhgTests::onModifyEquipmentTypeWhReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got onModifyEquipmentTypeWhReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
m_equipmentTypeWhId = replyObject.id();
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
return;
}
else
INFO_LOG(m_logger) << "Requesting create data ok. Got new id:" << replyObject.id() << " ... ok.";
if (m_testId == 0)
// QTimer::singleShot(0, this, &WhgTests::tryModify()));
QTimer::singleShot(0, this, &WhgTests::tryGetEquipmentTypeWh);
else
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of onModifyEquipmentTypeWhReply()
//-----------------------------------------------------------------------------
void WhgTests::onRemoveEquipmentTypeWhReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got removeReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Error requesting remove data for eqtTypeWhId:" << replyObject.id();
failExit();
return;
}
else
DEBUG_LOG(m_logger) << "Requesting remove data for eqtTypeWhId:" << replyObject.id() << " ... ok.";
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of onRemoveEquipmentTypeWhReply()
//-----------------------------------------------------------------------------
void WhgTests::onModifyInjuryModelAgdusWhReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got onModifyInjuryModelAgdusWhReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
m_injuryModelWhId = replyObject.id();
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
return;
}
else
DEBUG_LOG(m_logger) << "Requesting create data ok. Got new id:" << replyObject.id() << " ... ok.";
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of onModifyInjuryModelAgdusWhReply()
//-----------------------------------------------------------------------------
void WhgTests::onRemoveInjuryModelAgdusWhReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got removeReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Error requesting remove data for injuryModelWhId:" << replyObject.id();
failExit();
return;
}
else
DEBUG_LOG(m_logger) << "Requesting remove data for injuryModelWhId:" << replyObject.id() << " ... ok.";
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} // end of onRemoveInjuryModelAgdusWhReply()
//-----------------------------------------------------------------------------
void WhgTests::onReceiveEqtTypeChanged(const EquipmentTypeWh &data, DataModification modType)
{
INFO_LOG(m_logger) << "onReceiveEqtTypeChanged() eqtTypeWhId:" << data.id()
<< " modificationType: = " << (int)modType<< " received";
switch (modType)
{
case DataModification::eAdded:
INFO_LOG(m_logger) << "*** EquipmentTypeWh added received. eqtTypeWhId:" << data.id();
break;
case DataModification::eModified:
INFO_LOG(m_logger) << "*** EquipmentTypeWh modified received. eqtTypeWhId:" << data.id();
break;
case DataModification::eRemoved:
INFO_LOG(m_logger) << "*** EquipmentTypeWh removed received. eqtTypeWhId:" << data.id();
break;
default:
INFO_LOG(m_logger) << "DataModification::" << modType << " not implemented";
}
} // end of onReceiveEqtTypeChanged()
//-----------------------------------------------------------------------------
void WhgTests::getEqtTypeWhCreateRequestData(EquipmentTypeWh &data)
{
data.id(); // -1 for add, 0 is a valid id // 0 should be valid though?!?
data.name("TestEqtTypeCreate");
data.minEquipNo(1000);
data.maxEquipNo(3000);
data.vbAgdusId(1);
data.configurationAgdusHV(ConfigurationAgdusHV_def::AgdusHWNoHelmetNoWest);
} // end of getEqtTypeWhCreateRequestData()
//-----------------------------------------------------------------------------
void WhgTests::getEqtTypeWhModifyRequestData(EquipmentTypeWh &data)
{
data.id(m_equipmentTypeWhId);
data.name("TestEqtTypeModify");
data.maxEquipNo(3100);
data.minEquipNo(1100);
data.vbAgdusId(2);
data.configurationAgdusHV(ConfigurationAgdusHV_def::AgdusHWWithHelmetWithVest);
} // end of getEqtTypeWhModifyRequestData()
//-----------------------------------------------------------------------------
void WhgTests::getInjuryModelWhCreateRequestData(InjuryModelAgdusWh &data)
{
data.name("TestInjuryModelCreate");
data.version("1.0");
data.description("This is the description");
data.id(0);
} // end of getInjuryModelWhCreateRequestData()
//-----------------------------------------------------------------------------
void WhgTests::getInjuryModelWhModifyRequestData(InjuryModelAgdusWh &data)
{
data.id(m_injuryModelWhId);
data.name("TestInjuryModelWhModify");
data.version("2.0");
data.description("Description Modify");
} // end of getInjuryModelWhModifyRequestData()
//-----------------------------------------------------------------------------
bool WhgTests::onCompareCreatedData(EquipmentTypeWh &data)
{
DEBUG_LOG(m_logger) << "start onCompareCreatedData() for id :" << data.id();
// Vergleicht die zurueckgelesen Datan mit den statischen create Daten
EquipmentTypeWh createData;
getEqtTypeWhCreateRequestData(createData);
if (createData.name() != data.name())
return false;
if (createData.minEquipNo() != data.minEquipNo())
return false;
if (createData.maxEquipNo() != data.maxEquipNo())
return false;
if (createData.vbAgdusId() != data.vbAgdusId())
return false;
DEBUG_LOG(m_logger) << "successfull finished onCompareCreatedData() for id :" << data.id();
return true;
} // end of onCompareCreatedData()
bool WhgTests::onCompareCreatedData(InjuryModelAgdusWh &data)
{
DEBUG_LOG(m_logger) << "start onCompareCreatedData() for id :" << data.id();
// Vergleicht die zurueckgelesen Datan mit den statischen create Daten
InjuryModelAgdusWh createData;
getInjuryModelWhCreateRequestData(createData);
if (createData.name() != data.name())
return false;
if (createData.version() != data.version())
return false;
if (createData.description() != data.description())
return false;
DEBUG_LOG(m_logger) << "successfull finished onCompareCreatedData() for id :" << data.id();
return true;
} // end of onCompareCreatedData()
//-----------------------------------------------------------------------------
bool WhgTests::onCompareModifiedData(EquipmentTypeWh &data)
{
DEBUG_LOG(m_logger) << "start onCompareModifiedData() for id :" << data.id();
EquipmentTypeWh modifyData;
getEqtTypeWhModifyRequestData(modifyData);
if (modifyData.id() != data.id())
return false;
if (modifyData.name() != data.name())
return false;
if (modifyData.minEquipNo() != data.minEquipNo())
return false;
if (modifyData.maxEquipNo() != data.maxEquipNo())
return false;
if (modifyData.vbAgdusId() != data.vbAgdusId())
return false;
DEBUG_LOG(m_logger) << "successfully finished onCompareModifiedData() for id :" << data.id();
return true;
} // end of onCompareModifiedData()
//-----------------------------------------------------------------------------
bool WhgTests::onCompareModifiedData(InjuryModelAgdusWh &data)
{
DEBUG_LOG(m_logger) << "start onCompareModifiedData() for id :" << data.id();
InjuryModelAgdusWh modifyData;
getInjuryModelWhModifyRequestData(modifyData);
if (modifyData.id() != data.id())
return false;
if (modifyData.name() != data.name())
return false;
if (modifyData.version() != data.version())
return false;
if (modifyData.description() != data.description())
return false;
DEBUG_LOG(m_logger) << "successfull finished onCompareModifiedData() for id :" << data.id();
return true;
} // end of onCompareModifiedData()
//-----------------------------------------------------------------------------
void WhgTests::tryCreateInjuryModel()
{
m_eTestStep = eCreateInjuryModel;
InjuryModelAgdusWh data;
getInjuryModelWhCreateRequestData(data);
INFO_LOG(m_logger) << "trying to send modifyInjuryModelAgdusWhRequest with id = 0 (create)";
if (!m_ftc->modifyInjuryModelAgdusWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
} // end of tryCreateInjuryModel()
//-----------------------------------------------------------------------------
void WhgTests::tryModifyInjuryModel()
{
m_eTestStep = eModifyInjuryModel;
InjuryModelAgdusWh data;
getInjuryModelWhModifyRequestData(data);
ERROR_LOG(m_logger) << "trying to send modifyInjuryModelAgdusWhRequest for injuryModelWhId:" << data.id();
if (!m_ftc->modifyInjuryModelAgdusWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting modify data for injuryModelWhId:" << data.id();
failExit();
}
} // end of tryModifyInjuryModel()
//-----------------------------------------------------------------------------
void WhgTests::tryRemoveInjuryModel()
{
m_eTestStep = eRemoveInjuryModel;
Core::RemoveElementRequest data;
data.id(m_injuryModelWhId);
INFO_LOG(m_logger) << "trying to send remove request for injuryModelWhId:" << data.id();
if (!m_ftc->removeInjuryModelAgdusWhRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting remove data for injuryModelWhId:" << data.id();
failExit();
}
} // end of tryRemoveInjuryModel()
void WhgTests::tryGetBiteData()
{
QJsonObject data;
data.insert(JsonKeys::EQUIP_NO(), m_equipNo);
data.insert(JsonKeys::BOX(), m_boxId);
QJsonObject obj;
obj.insert(JsonKeys::UUID_(), QStringLiteral("7737"));
obj.insert(JsonKeys::TYPE(), QStringLiteral("getBiteData"));
obj.insert(JsonKeys::DATA(), data);
m_wsClient.sendTextMessage(QString::fromUtf8(QJsonDocument(obj).toJson()));
}
//-----------------------------------------------------------------------------
void WhgTests::failExit()
{
m_bTestsSuccessful = false;
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//-----------------------------------------------------------------------------
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser()
{
addOption({ QStringList() << QLatin1String("t") << QLatin1String("testId")
, QLatin1String("TestId.")
, QLatin1String("Default: 0 (all FTC/DTC tests), 1 create, 2 modify, 3 remove, 10 getAllEqtTypesWh, 11 getEqtTypeWh")
, QLatin1String("0")
});
addOption({ QStringList() << QLatin1String("w") << QLatin1String("eqtTypeWhId")
, QLatin1String("EquipmentTypeWhId.")
, QLatin1String("Used for tests 2, 3 & 11 only to select the eqtTypeWh")
, QLatin1String("0")
});
addOption({ QStringList() << QLatin1String("i") << QLatin1String("injuryModelWhId")
, QLatin1String("InjuryModelWhId.")
, QLatin1String("Used for tests 5 and 6 & only to select the injuryModelWh")
, QLatin1String("0")
});
addOption({ QStringList() << QLatin1String("e") << QLatin1String("equipNo")
, QLatin1String("EquipNo")
, QLatin1String("Used for test 12")
, QLatin1String("0")
});
addOption({ QStringList() << QLatin1String("b") << QLatin1String("boxId")
, QLatin1String("BoxId")
, QLatin1String("Used for test 12")
, QLatin1String("0")
});
}
int testId() const { return isSet(QLatin1String("t")) ? value(QLatin1String("t")).toInt() : -1; }
int eqtTypeWhId() const { return isSet(QLatin1String("w")) ? value(QLatin1String("w")).toInt() : -1; }
int injuryModelWhId() const { return isSet(QLatin1String("i")) ? value(QLatin1String("i")).toInt() : -1; }
int equipNo() const { return isSet(QLatin1String("e")) ? value(QLatin1String("e")).toInt() : -1; }
int boxId() const { return isSet(QLatin1String("b")) ? value(QLatin1String("b")).toInt() : -1; }
};
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
app.createLogger("WHG", 0);
int iRet = -1;
CmdLineParser options;
if (!options.init())
return iRet;
std::unique_ptr<WarehouseGuez::WhgTests> WhgTests(new WarehouseGuez::WhgTests);
if (!WhgTests->init(options.domainId(), options.testId(), options.eqtTypeWhId(), options.injuryModelWhId(), options.equipNo(), options.boxId()))
return iRet;
// QTimer::singleShot(2000, WhgTests.get(), &WarehouseGuez::WhgTests::startTest);
STARTUP_LOG(app.baseLogger());
app.exec();
iRet = WhgTests->testsSuccessful() ? 0 : 1;
fprintf(stderr, "%d\n", iRet);
DEBUG_LOG(app.baseLogger()) << "** TEST result = " << iRet;
SHUTDOWN_LOG(app.baseLogger());
return iRet;
}
//-----------------------------------------------------------------------------
+123
View File
@@ -0,0 +1,123 @@
/**
* @RDE_HEADER@
*
* EXM Function Topic test executable
*
* ModuleTests for create/modify/remove marker
* ---------------------------------------------------
* Client FTC is implemented
*
* => (!) Preconditon:
* - Service svcMarkerManagent running
*
* -------------------------------------------------
*
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2016-04-18
*/
#pragma once
#include <WarehouseGuez/whg_ftc.h>
#include <WarehouseGuez/whg_ftc_types.h>
#include <WarehouseGuez/whg_dtc.h>
#include <WarehouseGuez/whg_dtc_types.h>
#include <WarehouseGuez/logger.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <QtWebSockets/QWebSocket>
namespace WarehouseGuez
{
class WhgTests : public QObject
, protected WarehouseGuez::Interface::Ftc::ModifyEquipmentTypeWhReplyHandler
, protected WarehouseGuez::Interface::Ftc::RemoveEquipmentTypeWhReplyHandler
, protected WarehouseGuez::Interface::Ftc::ModifyInjuryModelAgdusWhReplyHandler
, protected WarehouseGuez::Interface::Ftc::RemoveInjuryModelAgdusWhReplyHandler
{
Q_OBJECT
public:
explicit WhgTests(QObject *parent = nullptr);
~WhgTests();
bool init(int domainId, int testId, int eqtTypeWhId, int injuryModelWhId, int equipNo, int boxId);
bool testsSuccessful() const { return m_bTestsSuccessful; }
public Q_SLOTS:
void startTest();
protected Q_SLOTS:
// used to check FTC
void tryCreate();
void tryModify();
void tryRemove();
void tryCreateInjuryModel();
void tryModifyInjuryModel();
void tryRemoveInjuryModel();
// used to check DTC
void tryGetAllEquipmentTypesWh();
void tryGetEquipmentTypeWh();
void tryGetBiteData();
void onReceiveEqtTypeChanged(const WarehouseGuez::EquipmentTypeWh &data, DataModification modType);
protected:
// Callbackfunctions for FTC
void onModifyEquipmentTypeWhReply(const Core::FunctionReplyObject &replyObject) override final;
void onRemoveEquipmentTypeWhReply(const Core::FunctionReplyObject &replyObject) override final;
void onModifyInjuryModelAgdusWhReply(const Core::FunctionReplyObject &replyObject) override final;
void onRemoveInjuryModelAgdusWhReply(const Core::FunctionReplyObject &replyObject) override final;
private Q_SLOTS:
bool onCompareCreatedData(EquipmentTypeWh &data);
bool onCompareModifiedData(EquipmentTypeWh &data);
bool onCompareCreatedData(InjuryModelAgdusWh &data);
bool onCompareModifiedData(InjuryModelAgdusWh &data);
void onConnected();
void onTextMessageReceived(const QString &msg);
private:
void getEqtTypeWhCreateRequestData(EquipmentTypeWh &data);
void getEqtTypeWhModifyRequestData(EquipmentTypeWh &data);
void getInjuryModelWhCreateRequestData(InjuryModelAgdusWh &data);
void getInjuryModelWhModifyRequestData(InjuryModelAgdusWh &data);
void failExit();
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<WarehouseGuez::Interface::Ftc> m_ftc;
std::shared_ptr<WarehouseGuez::Interface::Dtc> m_dtc;
QWebSocket m_wsClient;
int m_testId;
int m_equipmentTypeWhId;
int m_injuryModelWhId;
int m_equipNo;
int m_boxId;
enum TestStep
{
eUnknown,
eCreate,
eModify,
eRemove,
eGetAllEquipmentTypesWh,
eGetEquipmentTypeWh,
eCreateInjuryModel,
eModifyInjuryModel,
eRemoveInjuryModel
} m_eTestStep;
bool m_bTestsSuccessful;
NGL::INGLLogger &m_logger;
};
} // namespace WarehouseGuez
@@ -0,0 +1,192 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "client_message.h"
#include "WsBaseDataInterface/Messages/reply_message.h"
#include "WsBaseDataInterface/data_manager.h"
#include <WMS_Interface/json_keys.h>
#include <LtsWebSocket/json_keys.h>
#include <WMS_Interface/wms_ecc_exercises.h>
#include <WMS_Interface/wms_ecc_playerInfo.h>
#include <WMS_Interface/wms_ecc_registration.h>
#include <LtsUtilsCore/data_modification_enum.h>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QUuid>
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
namespace Messages
{
// ####### ClientMessageFactory begin #######
ClientMessageFactory::ClientMessageFactory(DataManager *dataManager)
: LtsWebSocket::AbstractClientMessageFactory(getLogger("BiteClientMessageFactory"))
, m_dataManager(dataManager)
{}
LtsWebSocket::AbstractClientMessage *ClientMessageFactory::createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message)
{
LtsWebSocket::AbstractClientMessage *result = checkAttributes(client, message);
if (result)
return result;
if (m_type == LtsWebSocket::JsonKeys::ERROR_())
{
ERROR_LOG(m_logger) << "Error in message: " << message;
return nullptr;
}
if (m_type == ::WebSocketInterface::JsonKeys::EQUIPMENT_TYPES_REQUEST())
result = new EquipmentTypesRequest(m_dataManager, client, m_type, m_typeId, m_uuid);
if (m_type == ::WebSocketInterface::JsonKeys::EXERCISE_UPDATE())
result = new ExerciseUpdate(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
if (m_type == ::WebSocketInterface::JsonKeys::EXERCISES_REPLY())
result = new ExercisesReply(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
if (m_type == ::WebSocketInterface::JsonKeys::PARTICIPANTS_UPDATE())
result = new ParticipantsUpdate(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
if (m_type == ::WebSocketInterface::JsonKeys::PARTICIPANTS_REPLY())
result = new ParticipantsReply(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
if (m_type == ::WebSocketInterface::JsonKeys::PARTICIPANT_REGISTER_IN_EXCON_REPLY())
result = new ParticipantRegisterInExconReply(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
return checkResult(client, message, result);
}
// ####### ClientMessageFactory end #######
// ####### ClientMessage begin #######
ClientMessage::ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: LtsWebSocket::AbstractClientMessage(client, type, typeId, uuid, data)
, m_dataManager(dataManager)
{}
// ####### ClientMessage end #######
// ####### EquipmentTypesRequest begin #######
EquipmentTypesRequest::EquipmentTypesRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid)
: ClientMessage (dataManager,client, type, typeId, uuid, QJsonValue())
{}
void EquipmentTypesRequest::process()
{
m_client->addReply(m_dataManager->equipmentTypes(m_uuid));
}
bool EquipmentTypesRequest::hasValidData() const
{
return true;
}
// ####### EquipmentTypesRequest end #######
// ####### ExercisesReply begin #######
ExercisesReply::ExercisesReply(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage (dataManager,client, type, typeId, uuid, data)
{}
void ExercisesReply::process()
{
EXCON::Exercises ex = EXCON::Exercises::fromJsonAll(m_data.toObject());
m_dataManager->newExerciseInformationsFromEXCON(ex);
}
bool ExercisesReply::hasValidData() const
{
return true;
}
// ####### ExercisesReply end #######
// ####### ExercisesReply begin #######
ExerciseUpdate::ExerciseUpdate(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage (dataManager,client, type, typeId, uuid, data)
{}
void ExerciseUpdate::process()
{
const QJsonObject obj = m_data.toObject();
DataModification modType = (DataModification) obj[::WebSocketInterface::JsonKeys::DATA_MODIFICATION()].toInt();
IWMS2ECC::Exercise exeData = EXCON::Exercises::fromJson(obj);
m_dataManager->exerciseChanged(exeData, modType);
}
bool ExerciseUpdate::hasValidData() const
{
return true;
}
// ####### ExerciseUpdate end #######
// ####### ParticipantsReply begin #######
ParticipantsReply::ParticipantsReply(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage (dataManager,client, type, typeId, uuid, data)
{}
void ParticipantsReply::process()
{
PlayerInfo pl = PlayerInfo::fromJsonAll(m_data.toObject());
m_dataManager->participantsFromEXCON(pl);
}
bool ParticipantsReply::hasValidData() const
{
return true;
}
// ####### ParticipantsReply end #######
// ####### ParticipantsUpdate begin #######
ParticipantsUpdate::ParticipantsUpdate(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage (dataManager,client, type, typeId, uuid, data)
{}
void ParticipantsUpdate::process()
{
const QJsonObject obj = m_data.toObject();
int modType = obj[::WebSocketInterface::JsonKeys::DATA_MODIFICATION()].toInt();
IWMS2ECC::PlayerInfo pl = PlayerInfo::fromJson(obj);
m_dataManager->participantFromEXCON(pl, modType);
}
bool ParticipantsUpdate::hasValidData() const
{
return true;
}
// ####### ParticipantsUpdate end #######
// ####### ParticipantRegisterInExconReply begin #######
ParticipantRegisterInExconReply::ParticipantRegisterInExconReply(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage (dataManager,client, type, typeId, uuid, data)
{}
void ParticipantRegisterInExconReply::process()
{
const QJsonObject obj = m_data.toObject();
int exerciseId = obj[::WebSocketInterface::JsonKeys::EXERCISE_ID()].toInt();
qint32 participantId = obj[::WebSocketInterface::JsonKeys::PARTICIPANT_ID()].toInt();
int returnValue = obj[::WebSocketInterface::JsonKeys::REGISTRATION_RETURN_VALUE()].toInt();
//qWarning() << "exerciseId: " << exerciseId << ", participantId: " << participantId << ", retValue: " << returnValue;
m_dataManager->registerReply(exerciseId, participantId, returnValue);
}
bool ParticipantRegisterInExconReply::hasValidData() const
{
return true;
}
// ####### ParticipantRegisterInExconReply end #######
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,130 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QJsonObject>
#include <LtsWebSocket/client_message_factory.h>
#include <LtsWebSocket/client_message.h>
#include "logger.h"
#include <WMS_Interface/json_keys.h>
// incoming messages
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
class DataManager;
namespace Messages
{
/**
* @brief The ClientMessageFactory class creates ClientMessages which will then be processed
*/
class ClientMessageFactory final : public LtsWebSocket::AbstractClientMessageFactory
{
public:
explicit ClientMessageFactory(DataManager* dataManager);
/**
* @brief create Only way to create a ClientMessage object
* @param message Text message which will be converted to a ClientMessage object
* @return A ClientMessage object, which represents a concrete ClientMessage
*/
LtsWebSocket::AbstractClientMessage *createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message);
private:
DataManager *m_dataManager;
}; // class ClientMessageFactory
/**
* @brief The ClientMessage class is an abstract base class for concrete ClientMessage objects
*/
class ClientMessage : public LtsWebSocket::AbstractClientMessage
{
protected: // method
explicit ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
protected: // attributes
DataManager *m_dataManager;
}; // class ClientMessage
// ################## Message Implementations ##################
class EquipmentTypesRequest : public ClientMessage
{
public:
explicit EquipmentTypesRequest (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid);
void process();
bool hasValidData() const;
}; // class EquipmentTypesRequest
// Client -> Server - answer to ExercisesRequest or information from Client that a specific exercise changed
// -> then there is only one exercise in the message
class ExercisesReply : public ClientMessage
{
public:
explicit ExercisesReply (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class ExercisesReply
class ExerciseUpdate : public ClientMessage
{
public:
explicit ExerciseUpdate (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class ExerciseUpdate
class ParticipantsReply : public ClientMessage
{
public:
explicit ParticipantsReply (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class ParticipantsReply
class ParticipantsUpdate : public ClientMessage
{
public:
explicit ParticipantsUpdate (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class ParticipantsUpdate
class ParticipantRegisterInExconReply : public ClientMessage
{
public:
explicit ParticipantRegisterInExconReply (DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class ParticipantRegisterInExconReply
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,55 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "reply_message.h"
#include <LtsWebSocket/json_keys.h>
#include <WMS_Interface/json_keys.h>
#include <QtCore/QUuid>
#include <QtCore/QJsonDocument>
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
namespace Messages
{
using namespace LtsWebSocket::JsonKeys;
ExerciseRequest::ExerciseRequest()
: LtsWebSocket::ReplyMessage(::WebSocketInterface::JsonKeys::EXERCISES_REQUEST(), 1, QStringLiteral("drei")) // Todo: Check whether typeId is correct
{}
ParticipantsRequest::ParticipantsRequest(int exerciseId)
: LtsWebSocket::ReplyMessage(::WebSocketInterface::JsonKeys::PARTICIPANTS_REQUEST(), 2, QStringLiteral("drei")) // Todo: Check whether typeId is correct
{
m_jsonRepresentation[::WebSocketInterface::JsonKeys::EXERCISE_ID()] = exerciseId;
}
// ####### EquipmentTypesMessage begin #######
EquipmentTypesMessage::EquipmentTypesMessage(const QJsonObject &data, const QString &uuid)
: ReplyMessage (::WebSocketInterface::JsonKeys::EQUIPMENT_TYPES_REPLY(), 3, uuid) // Todo: Check whether typeId is correct
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### EquipmentTypesMessage end #######
// ####### ParticipantRegisterInExconRequest begin #######
ParticipantRegisterInExconRequest::ParticipantRegisterInExconRequest(const QJsonObject &data, const QString &uuid)
: ReplyMessage (::WebSocketInterface::JsonKeys::PARTICIPANT_REGISTER_IN_EXCON_REQUEST(), 4, uuid) // Todo: Check whether typeId is correct
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### ParticipantRegisterInExconRequest end #######
} // namespace Messages
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <LtsWebSocket/client_message_factory.h>
#include <DDS/Core/core.hpp>
#include <QString>
#include <QMap>
#include <QtCore/QVector>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
// outgoing messages
// ReplyMessage -> MessageToSend
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
namespace Messages
{
// WHG -> WMS - requesting data for all exercises
class ExerciseRequest : public LtsWebSocket::ReplyMessage
{
public:
ExerciseRequest();
};
class ParticipantsRequest : public LtsWebSocket::ReplyMessage
{
public:
explicit ParticipantsRequest(int exerciseId);
};
/**
* @brief The EquipmentTypesMessage class represents the equipment types from the svcWarehouseGuez
*/
class EquipmentTypesMessage final : public LtsWebSocket::ReplyMessage
{
public:
explicit EquipmentTypesMessage (const QJsonObject &data, const QString &uuid);
}; // class EquipmentTypesMessage
// ReplyMessage -> message to send
class ParticipantRegisterInExconRequest : public LtsWebSocket::ReplyMessage
{
public:
explicit ParticipantRegisterInExconRequest(const QJsonObject &data, const QString &uuid);
void process();
bool hasValidData() const;
}; // class ParticipantRegisterRequest
} // namespace Messages
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,559 @@
/**
* @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 Philipp Dassow, SLST, 2017-12-05
*/
#include "WsBaseDataInterface/data_manager.h"
#include <WMS_Interface/IWMS2ECC.h>
#include <WMS_Interface/wms_ecc_equipmenttypes.h>
#include <WMS_Interface/wms_ecc_registration.h>
#include <ngltools/ngltools_filesystem.h>
#include <ngldb/nsqlquery.h>
#include <CodeGen/SqlGenerator.h>
#include "main_handler.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QMap>
#include <QSqlRecord>
#include <QTimer>
#include <QVector>
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
static constexpr int s_exerciseOffset = 1000000;
static inline QString tlnTable(int exerciseId)
{
return QStringLiteral("tln_") + QString::number(exerciseId);
}
static inline QString tlnZuordnungTable(int exerciseId)
{
return QStringLiteral("tln_zuordnung_") + QString::number(exerciseId);
}
static inline QString triggerName(int exerciseId)
{
if (exerciseId <= 0)
return QStringLiteral("whg_notifyInsertParticipantAssignment");
return QStringLiteral("whg_notifyInsertParticipantAssignment_") + QString::number(exerciseId);
}
//---------------------------------------------------------------------------------------------------------
DataManager::DataManager(MainHandler *mainHandler)
: m_mainHandler(mainHandler)
, m_webSocketServer(nullptr)
, m_logger(getLogger(QStringLiteral("DataManager")))
{
}
//---------------------------------------------------------------------------------------------------------
bool DataManager::init()
{
reconnectSignals();
return true;
}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::equipmentTypes(const QString &uuid) const
{
using namespace Messages;
IWMS2ECC::equipTypeMap etMap;
auto cbEqTypeWh = [&etMap](const WarehouseGuez::Database::EquipmentTypeWh &data)
{
IWMS2ECC::EquipmentType et;
et.id = data.id;
et.name = data.name;
et.minEquipNo = data.ausstgNrMin;
et.maxEquipNo = data.ausstgNrMax;
et.specialType = 0; // not used in GUEZ
et.taVulnerabilityModelId = data.vbAgdus;
etMap.insert(et.id, et);
};
m_mainHandler->db()->select(cbEqTypeWh);
EquipmentTypes eTypes;
eTypes.setEquipmentTypes(etMap);
QJsonObject obj = eTypes.toJsonAll();
INFO_LOG(m_logger) << "equipTypeMap.size: " << etMap.size() << ", " << QJsonDocument(obj).toJson();
return new EquipmentTypesMessage(obj, uuid);
}
void DataManager::newExerciseInformationsFromEXCON(const EXCON::Exercises &ex)
{
const IWMS2ECC::exerciseMap exMap = ex.getExercises();
DEBUG_LOG(m_logger) << "Exercises map.size: " << exMap.size();
QVector<Database::Exercise> dataVec;
m_mainHandler->db()->select(dataVec);
for (const IWMS2ECC::Exercise &exercise : exMap)
{
WarehouseGuez::Database::Exercise ex;
ex.id = exercise.id;
ex.name = exercise.name;
ex.beginn = QDateTime::fromMSecsSinceEpoch(exercise.start);
ex.aktUebung = exercise.actExercise;
ex.tln = tlnTable(exercise.id);
ex.tlnZuordnung = tlnZuordnungTable(exercise.id);
bool ok;
if (findExercise(exercise.id, dataVec))
ok = m_mainHandler->db()->update(ex);
else
ok = m_mainHandler->db()->insert(ex);
if (!ok)
{
ERROR_LOG(m_logger) << "Error while insert/update in exercise";
break;
}
}
}
bool DataManager::findExercise(int exerciseId, const QVector<Database::Exercise> &dataVec)
{
for (const Database::Exercise &exercise : dataVec)
{
if (exercise.id == exerciseId)
return true;
}
return false;
}
static inline QString fixupString(const QString &in)
{
// Warehouse in GUEZ loves SQL-Injection
QString ret;
ret.reserve(in.size());
for (const QChar &c : in)
{
if (c == QLatin1Char('\"') ||
c == QLatin1Char('\'') ||
c.unicode() == 0x60 || // GRAVE ACCENT - `
c.unicode() == 0xb4 || // ACUTE ACCENT - ´
c == QLatin1Char(';'))
continue;
ret += c;
}
return ret;
}
static inline void bindPlayer(NSqlQuery &q, const IWMS2ECC::PlayerInfo &pl)
{
q.bindValue(QStringLiteral(":id"), pl.playerId);
q.bindValue(QStringLiteral(":hierarchie"), fixupString(pl.hierarchy));
q.bindValue(QStringLiteral(":typ_id"), pl.typeId);
q.bindValue(QStringLiteral(":ausstg_typ_id"), pl.equipTypeId);
q.bindValue(QStringLiteral(":ausstg_nr"), pl.equipNo);
q.bindValue(QStringLiteral(":zuordnung"), pl.assignState);
q.bindValue(QStringLiteral(":y_nr"), fixupString(pl.alias));
q.bindValue(QStringLiteral(":info"), fixupString(pl.info));
q.bindValue(QStringLiteral(":loeschkennung"), pl.isDeleted ? 1 : 0); // bool -> smallint :(
q.bindValue(QStringLiteral(":zeit"), NSqlQuery::qDateTimeToQVariant(QDateTime::currentDateTime()));
}
void DataManager::participantsFromEXCON(const PlayerInfo &pl)
{
const QMap<int,IWMS2ECC::PlayerInfo> plMap = pl.getAllPlayerInfo();
if (plMap.isEmpty())
{
DEBUG_LOG(m_logger) << "No valid exercise -> no participants";
return;
}
// first get exerciseId
int exerciseId = plMap.firstKey() / s_exerciseOffset;
DEBUG_LOG(m_logger) << "ExerciseId: " << exerciseId;
DEBUG_LOG(m_logger) << "plMap.size(): " << plMap.size();
// table is created at exercise creation
QString tlnOut = tlnTable(exerciseId);
NSqlQuery q(m_mainHandler->db()->database());
// If entries exist delete them
QString stmt = QStringLiteral("DELETE FROM ") + tlnOut;
DEBUG_LOG(m_logger) << "Executing delete statement: " << stmt;
q.exec(stmt);
stmt = QStringLiteral("INSERT INTO ") + tlnOut + QStringLiteral("( id, hierarchie, typ_id, ausstg_typ_id, ausstg_nr, zuordnung, y_nr, info, loeschkennung, zeit ) VALUES (" )
+ QStringLiteral(":id, :hierarchie, :typ_id, :ausstg_typ_id, :ausstg_nr, :zuordnung, :y_nr, :info, :loeschkennung, :zeit )");
DEBUG_LOG(m_logger) << "Preparing insert statement: " << stmt;
q.prepare(stmt);
for (const IWMS2ECC::PlayerInfo &pl : plMap)
{
bindPlayer(q, pl);
DEBUG_LOG(m_logger) << "Executing insert statement for participant: " << pl.playerId;
if (!q.exec())
ERROR_LOG(m_logger) << "Error inserting data for participantId: " << pl.playerId;
}
}
bool DataManager::participantFromEXCON(const IWMS2ECC::PlayerInfo &pl, int modType)
{
DEBUG_LOG(m_logger) << "IN participantFromEXCON: modType: " << modType << ", participantId: " << pl.playerId;
DataModification modificationType = static_cast<DataModification>(modType);
int exerciseId = pl.playerId / s_exerciseOffset;
QString tlnOut = tlnTable(exerciseId);
NSqlQuery q(m_mainHandler->db()->database());
DEBUG_LOG(m_logger) << "Executing delete statement: " << QStringLiteral("DELETE FROM %1 WHERE id = %2").arg(tlnOut).arg(pl.playerId);
q.exec(QStringLiteral("DELETE FROM %1 WHERE id = %2").arg(tlnOut).arg(pl.playerId));
switch(modificationType)
{
case DataModification::eModified:
case DataModification::eAdded:
{
QString stmt = QStringLiteral("INSERT INTO ") + tlnOut +
QStringLiteral("( id, hierarchie, typ_id, ausstg_typ_id, ausstg_nr, zuordnung, y_nr, info, loeschkennung, zeit ) VALUES (" ) +
QStringLiteral(":id, :hierarchie, :typ_id, :ausstg_typ_id, :ausstg_nr, :zuordnung, :y_nr, :info, :loeschkennung, :zeit )");
if (!q.prepare(stmt))
{
ERROR_LOG(m_logger) << "Error while preparing insert stmt: " << stmt;
return false;
}
bindPlayer(q, pl);
DEBUG_LOG(m_logger) << "Executing insert statement: " << stmt;
if (!q.exec())
{
ERROR_LOG(m_logger) << "Error inserting data for participantId: " << pl.playerId;
return false;
}
break;
}
case DataModification::eRemoved:
break;
} // end switch
return true;
}
bool DataManager::exerciseChanged(const IWMS2ECC::Exercise &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "IN exerciseChanged: id = " << data.id << ", actExercise: " << data.actExercise;
Database::Exercise exData;
exData.id = data.id;
exData.name = data.name;
exData.beginn = QDateTime::fromMSecsSinceEpoch(data.start);
exData.tln = tlnTable(data.id);
exData.tlnZuordnung = tlnZuordnungTable(data.id);
exData.aktUebung = data.actExercise;
switch(modType)
{
case DataModification::eAdded:
{
Database::Exercise tmp;
if (m_mainHandler->db()->selectExercise(exData.id, tmp))
{
if (!m_mainHandler->db()->update(exData))
{
ERROR_LOG(m_logger) << "Error while updating exerciseData for exercise: " << data.id;
return false;
}
}
else
{
if (!m_mainHandler->db()->insert(exData))
{
ERROR_LOG(m_logger) << "Error while inserting exerciseData for exercise: " << data.id;
return false;
}
createTableTlnOut(exData.id);
createTableTlnZuordnung(exData.id);
}
return true;
}
case DataModification::eModified:
{
if (!m_mainHandler->db()->update(exData))
{
ERROR_LOG(m_logger) << "Error while updating exerciseData for exercise: " << data.id;
return false;
}
return true;
}
case DataModification::eRemoved:
{
if (!m_mainHandler->db()->removeExercise(data.id))
{
ERROR_LOG(m_logger) << "Error while removing exerciseData for exercise: " << data.id;
return false;
}
return true;
}
}
ERROR_LOG(m_logger) << "DataModification Type: " << modType << " not handled in switch";
return false;
}
void DataManager::createTableTlnOut(int exerciseId)
{
ERROR_LOG(m_logger) << "createTableTlnOut";
// xmlPath
const QString xmlPath = NGL::directory(NGL::FileType::ConfigFile, QLatin1String("xml"));
QString xmlFile = xmlPath + QStringLiteral("/whg.xml");
CodeGen::SqlGenerator sqlGen(xmlFile);
QString tlnOut = tlnTable(exerciseId);
ERROR_LOG(m_logger) << "tlnOut: " << tlnOut;
sqlGen.createStatementsForTable(QStringLiteral("tln"), tlnOut);
const CodeGen::SqlGenerator::SqlStatements stmts = sqlGen.getStatements(CodeGen::Global);
QSqlRecord record = m_mainHandler->db()->database().record(tlnOut);
NSqlQuery q(m_mainHandler->db()->database());
for (const QString &stmt : stmts.createTables)
{
ERROR_LOG(m_logger) << "stmt: " << stmt;
if (record.isEmpty())
{
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error executing stmt: " << stmt;
}
}
}
void DataManager::createTableTlnZuordnung(int exerciseId)
{
ERROR_LOG(m_logger) << "in createTableTlnZuordnung";
// xmlPath
const QString xmlPath = NGL::directory(NGL::FileType::ConfigFile, QLatin1String("xml"));
QString xmlFile = xmlPath + QStringLiteral("/whg.xml");
CodeGen::SqlGenerator sqlGen(xmlFile);
const QString tlnZuordnung = tlnZuordnungTable(exerciseId);
ERROR_LOG(m_logger) << "tlnZuordnung: " << tlnZuordnung;
sqlGen.createStatementsForTable(QStringLiteral("tln_zuordnung"), tlnZuordnung);
const CodeGen::SqlGenerator::SqlStatements stmts = sqlGen.getStatements(CodeGen::Global);
QSqlRecord record = m_mainHandler->db()->database().record(tlnZuordnung);
NSqlQuery q(m_mainHandler->db()->database());
for (const QString &stmt : stmts.createTables)
{
DEBUG_LOG(m_logger) << "stmt: " << stmt;
if (record.isEmpty())
{
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error executing stmt: " << stmt;
}
}
for (const QString &stmt : stmts.createSequences)
{
DEBUG_LOG(m_logger) << "stmt: " << stmt;
if (record.isEmpty())
{
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error executing stmt: " << stmt;
}
}
createTriggerForExercise(q, exerciseId);
}
void DataManager::createTriggerForExercise(NSqlQuery &q, int exerciseId)
{
QString stmt;
const QString triggerNameExercise(triggerName(exerciseId));
const QString tlnZuordnungTableExercise(tlnZuordnungTable(exerciseId));
// drop possible old trigger
stmt = QLatin1String("DROP TRIGGER IF EXISTS ") + triggerNameExercise +
QLatin1String(" ON ") + tlnZuordnungTableExercise;
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error dropping possible old trigger: " << stmt;
// Create trigger
stmt = QLatin1String("CREATE OR REPLACE FUNCTION public.") + triggerNameExercise +
QLatin1String("() RETURNS TRIGGER AS $$ "
" BEGIN "
" PERFORM pg_notify('") + triggerNameExercise + QLatin1String("', CAST(NEW.id AS text));"
" RETURN NEW;"
"END;"
"$$ LANGUAGE plpgsql;");
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error while creating function in statement: " << stmt;
stmt = QLatin1String("CREATE TRIGGER ") + triggerNameExercise +
QLatin1String(" AFTER INSERT ON ") + tlnZuordnungTableExercise +
QLatin1String(" FOR EACH ROW EXECUTE PROCEDURE public.") + triggerNameExercise + QLatin1String("();");
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error while creating trigger in statement: " << stmt;
QSqlDriver *driver = m_mainHandler->db()->database().driver();
// create subscription
connect(driver, QOverload<const QString &, QSqlDriver::NotificationSource, const QVariant &>::of(&QSqlDriver::notification),
this, &DataManager::onNotification, Qt::UniqueConnection);
if (!driver->subscribeToNotification(triggerNameExercise))
WARNING_LOG(m_logger) << "Error subscribing to DB notification " << triggerNameExercise;
else
DEBUG_LOG(m_logger) << "Sucessfully subscribed to DB notification " << triggerNameExercise;
}
void DataManager::onInsertParticipantAssignment(int participantId, int exerciseId)
{
INFO_LOG(m_logger) << "Reading ParticipantAssignment from database!";
NSqlQuery q(m_mainHandler->db()->database());
QString stmt = QLatin1String("SELECT id, ausstg_nr, zuordnung, y_nr, info FROM ") + m_mainHandler->db()->schemaName() +
QLatin1Char('.') + tlnZuordnungTable(exerciseId) +
QLatin1String(" WHERE gesendet = false");
if (participantId > 0)
stmt += QLatin1String(" AND id = ") + QString::number(participantId);
stmt += QLatin1String(" ORDER BY zeit");
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Error selecting data for participantId: " << participantId << ", exerciseId: " << exerciseId;
return;
}
// we may get back more than one row, esp. in case participantId == 0
while (q.next())
{
// use the 'correct' participant id in case participantId == 0 was given (happens during startup)
participantId = q.value(0).toInt() - (exerciseId * s_exerciseOffset);
DEBUG_LOG(m_logger) << "participantId: " << participantId;
Registration reg;
reg.setPlayerId(participantId);
reg.setAssignment(IWMS2ECC::int2PlayerAssignState(q.value(2).toInt()));
if (!q.value(1).isNull())
reg.setEquipNo(q.value(1).toInt());
if (!q.value(3).isNull())
reg.setAlias(q.value(3).toString());
if (!q.value(4).isNull())
reg.setInfo(q.value(4).toString());
reg.setExerciseId(exerciseId);
reg.setOk(true);
Messages::ParticipantRegisterInExconRequest *msg = new Messages::ParticipantRegisterInExconRequest(reg.toJson(),
QLatin1String("blub"));
INFO_LOG(m_logger) << "registration: " << msg->toJsonString();
m_webSocketServer->sendToAllClients(msg);
}
}
void DataManager::onNotification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload)
{
Q_UNUSED(source);
// search coresponding signal
INFO_LOG(m_logger) << "IN onNotification name: " << name;
const QString triggerNameEx0 = triggerName(0);
if (name.contains(triggerNameEx0))
{
QStringRef name_(&name);
name_ = name_.mid(triggerNameEx0.size() + 1);
int exerciseId = name_.toInt();
int participantId = payload.toInt();
INFO_LOG(m_logger) << "exerciseId: " << exerciseId << ", participantId: " << participantId;
onInsertParticipantAssignment(participantId, exerciseId);
}
}
void DataManager::reconnectSignals()
{
NSqlQuery q(m_mainHandler->db()->database());
QVector<Database::Exercise> vecExercises;
m_mainHandler->db()->select(vecExercises);
for (const auto &exercise : qAsConst(vecExercises))
{
createTriggerForExercise(q, exercise.id);
const QString tn = triggerName(exercise.id);
QTimer::singleShot(5000, this, [this, tn]() { onNotification(tn, QSqlDriver::UnknownSource, QLatin1String("0")); });
}
}
void DataManager::registerReply(int exerciseId, qint32 participantId, int returnValue)
{
DEBUG_LOG(m_logger) << "registerReply for exercise id = " << exerciseId << ", participant id = " << participantId << ", return value = " << returnValue;
NSqlQuery q(m_mainHandler->db()->database());
qint32 newParticipantId = participantId + (exerciseId * s_exerciseOffset);
QString stmt = QLatin1String("UPDATE ") + m_mainHandler->db()->schemaName() +
QLatin1Char('.') + tlnZuordnungTable(exerciseId) +
QLatin1String(" SET gesendet = true, error_code = ") + QString::number(returnValue) +
QLatin1String(" WHERE id = ") + QString::number(newParticipantId) +
QLatin1String(" AND gesendet = false");
DEBUG_LOG(m_logger) << "registerReply: stmt = " << stmt;
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Cannot update reply entry for participant: " << participantId
<< " in exercise: " << exerciseId << ", returnValue: " << returnValue;
}
else
{
INFO_LOG(m_logger) << "Update successful for participant " << participantId << " in exercise: " << exerciseId;
}
if (returnValue != 0)
{
QString stmt1 = QLatin1String("UPDATE ") + m_mainHandler->db()->schemaName() +
QLatin1String(".") + tlnTable(exerciseId) +
QLatin1String(" SET ausstg_nr = -1, zeit = ") + QString::number(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()) +
QLatin1String(" WHERE id = ") + QString::number(newParticipantId);
DEBUG_LOG(m_logger) << "registerReply: stmt1 = " << stmt1;
if (!q.exec(stmt1))
{
ERROR_LOG(m_logger) << "Cannot update austtg_nr for participant: " << participantId
<< " in exercise: " << exerciseId << ", returnValue: " << returnValue;
}
else
{
INFO_LOG(m_logger) << "Update ausstg_nr successful for participant " << participantId << " in exercise: " << exerciseId;
}
}
}
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,80 @@
/**
* @RDE_HEADER@
* The DataManager class is a convenience class for managing structure data
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include "WsBaseDataInterface/Messages/reply_message.h"
#include "logger.h"
#include "ws_base_data_interface_handler.h"
#include <WarehouseGuez/whg_db.h>
#include <WMS_Interface/wms_ecc_exercises.h>
#include <WMS_Interface/wms_ecc_playerInfo.h>
#include <LtsUtilsCore/data_modification_enum.h>
#include <QObject>
#include <QSqlDriver>
class NSqlQuery;
namespace WarehouseGuez
{
class MainHandler;
class GroupHandler;
namespace WsBaseDataInterface
{
/**
* @brief The DataManager class is a convenience class for managing structure data
*/
class DataManager final : public QObject
{
Q_OBJECT
public:
/**
* @brief DataManager Constructor
* @param mainHandler Source for needed handlers
*/
explicit DataManager(MainHandler *mainHandler);
/**
* @brief init Initialises a DataManager object
* @return True on sucess, otherwise false
*/
bool init();
void setWebSocketServer( LtsWebSocket::LtsWebSocketServer *webSocketServer) { m_webSocketServer = webSocketServer;}
void reconnectSignals();
LtsWebSocket::ReplyMessage *equipmentTypes(const QString &uuid) const;
void newExerciseInformationsFromEXCON(const EXCON::Exercises &ex);
void participantsFromEXCON(const PlayerInfo &pl);
bool participantFromEXCON(const IWMS2ECC::PlayerInfo &pl, int modType);
bool exerciseChanged(const IWMS2ECC::Exercise &data, DataModification modType);
void registerReply(int exerciseId, qint32 participantId, int returnValue);
private:
static bool findExercise(int exerciseId, const QVector<Database::Exercise> &dataVec);
void createTableTlnOut(int exerciseId);
void createTableTlnZuordnung(int exerciseId);
void createTriggerForExercise(NSqlQuery &q, int exerciseId);
private slots:
void onInsertParticipantAssignment(int participantId, int exerciseId);
void onNotification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload);
private: // attributes
MainHandler *m_mainHandler;
LtsWebSocket::LtsWebSocketServer *m_webSocketServer;
LOGGER_T m_logger;
}; // class DataManager
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,98 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "ws_base_data_interface_handler.h"
#include "main_handler.h"
#include "data_manager.h"
#include "WsBaseDataInterface/Messages/client_message.h"
#include <nglsettings/nglsettings_connections.h>
namespace WarehouseGuez
{
namespace WsBaseDataInterface
{
WsBaseDataInterfaceHandler::WsBaseDataInterfaceHandler(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, m_webSocketServer(nullptr)
, m_messageFactory(nullptr)
, m_dataManager(nullptr)
, m_mainHandler(mainHandler)
, m_logger(getLogger("WsBaseDataInterfaceHandler"))
{
}
WsBaseDataInterfaceHandler::~WsBaseDataInterfaceHandler()
{
cleanup();
}
bool WsBaseDataInterfaceHandler::init()
{
cleanup();
DEBUG_LOG(m_logger) << "... ok";
DEBUG_LOG(m_logger) << "Initialising DataManager";
m_dataManager = new DataManager(m_mainHandler);
if (!m_dataManager->init())
{
ERROR_LOG(m_logger) << "Failed to initialise DataManager";
return false;
}
DEBUG_LOG(m_logger) << "... ok";
m_messageFactory = new Messages::ClientMessageFactory(m_dataManager);
m_webSocketServer = new LtsWebSocket::LtsWebSocketServer(m_messageFactory, this);
DEBUG_LOG(m_logger) << "Initialising LtsWebSocketServer";
int port = NGL::Connections::port(NGL::Connections::eConnection::ZSLV);
ERROR_LOG(m_logger) << "Port: " << port;
if (!m_webSocketServer->init(QStringLiteral("localhost"), port))
{
ERROR_LOG(m_logger) << "Failed to initialise LtsWebSocketServer";
return false;
}
DEBUG_LOG(m_logger) << "... ok";
DEBUG_LOG(m_logger) << "Connection signals and slots";
m_dataManager->setWebSocketServer(m_webSocketServer);
return true;
}
void WsBaseDataInterfaceHandler::cleanup()
{
delete m_webSocketServer;
delete m_messageFactory;
delete m_dataManager;
}
void WsBaseDataInterfaceHandler::requestExercisesFromExcon()
{
m_webSocketServer->sendToAllClients(new Messages::ExerciseRequest);
}
void WsBaseDataInterfaceHandler::requestParticipantsFromExcon(int exerciseId)
{
m_webSocketServer->sendToAllClients(new Messages::ParticipantsRequest(exerciseId));
}
void WsBaseDataInterfaceHandler::sendEquipmentTypes()
{
m_webSocketServer->sendToAllClients(m_dataManager->equipmentTypes(QStringLiteral("spontaneous")));
}
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,75 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QObject>
#include <LtsWebSocket/lts_web_socket_server.h>
#include "logger.h"
namespace WarehouseGuez
{
class MainHandler;
namespace WsBaseDataInterface
{
namespace Messages
{
class ClientMessageFactory;
}
class DataManager;
/**
* @brief The WsBaseDataInterfaceHandler class is the main class for the WsBaseDataInterface
*/
class WsBaseDataInterfaceHandler final : public QObject
{
public:
/**
* @brief WsBaseDataInterfaceHandler Constructor
* @param mainHandler MainHandler to get the HandlerStructureElement from
*/
explicit WsBaseDataInterfaceHandler(MainHandler *mainHandler, QObject *parent = nullptr);
/**
* @brief ~WsBaseDataInterfaceHandler Destructor
*/
~WsBaseDataInterfaceHandler();
/**
* @brief init Initialises all needed classes for the WsBaseDataInterface
* @return True on success, otherwise false
*/
bool init();
/**
* @brief webSocketPort returns the listen port
* @return listen port
*/
unsigned short webSocketPort() { return m_webSocketServer->webSocketPort(); }
void requestExercisesFromExcon();
void requestParticipantsFromExcon(int exerciseId);
void sendEquipmentTypes();
private:
void cleanup();
private:
LtsWebSocket::LtsWebSocketServer *m_webSocketServer;
Messages::ClientMessageFactory *m_messageFactory;
DataManager *m_dataManager;
MainHandler *m_mainHandler;
LOGGER_T m_logger;
}; // class WsBaseDataInterfaceHandle
} // namespace WsBaseDataInterface
} // namespace WarehouseGuez
@@ -0,0 +1,94 @@
/**
* @RDE_HEADER@
* The ClientConnection class represents a connection to a single client.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "client_connection.h"
#include "WsBiteInterface/Messages/ws_reply_message.h"
#include <QtWebSockets/QWebSocket>
#include <QtCore/QTimer>
using namespace WarehouseGuez::WsBiteInterface::Connection;
ClientConnection::ClientConnection(QWebSocket *socket, QObject *parent)
: QObject(parent)
, m_socket(socket)
, m_ip(socket->peerAddress())
, m_logger(getLogger(QLatin1String("ClientConnection")))
{}
ClientConnection::~ClientConnection()
{
if (m_socket)
{
m_socket->disconnect(this);
m_socket->close();
}
delete m_socket;
}
bool ClientConnection::init()
{
if (m_socket == nullptr)
{
ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket";
return false;
}
connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket);
connect(m_socket, &QWebSocket::connected, this, &ClientConnection::sendMessagesFromQueue);
connect(m_socket, &QWebSocket::disconnected, this, &ClientConnection::onSocketDisconnect);
return true;
}
QHostAddress ClientConnection::ip() const
{
return m_ip;
}
void ClientConnection::addMessage(const WarehouseGuez::WsBiteInterface::Messages::ReplyMessage &message)
{
if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
{
m_messageQueue.enqueue(message);
DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size();
return;
}
const QString msg(message.toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
}
void ClientConnection::onNewTextMessageFromSocket(const QString &message)
{
DEBUG_LOG(m_logger) << "Recv msg: " << message;
emit newTextMessage(this, message);
}
void ClientConnection::sendMessagesFromQueue()
{
if (m_socket->state() != QAbstractSocket::ConnectedState)
return;
while (!m_messageQueue.isEmpty())
{
Messages::ReplyMessage message = m_messageQueue.dequeue();
const QString msg(message.toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size();
}
}
void ClientConnection::onSocketDisconnect()
{
DEBUG_LOG(m_logger) << "Client with ip "
<< m_ip.toString()
<< " disconnected";
emit disconnected(this);
}
@@ -0,0 +1,60 @@
/**
* @RDE_HEADER@
* The ClientConnection class represents a connection to a single client.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QQueue>
#include <QtNetwork/QHostAddress>
#include "WsBiteInterface/Messages/message_transmitter.h"
#include "logger.h"
class QWebSocket;
class QTimer;
namespace WarehouseGuez
{
namespace WsBiteInterface
{
namespace Connection
{
class ClientConnection
: public QObject
, public Messages::MessageTransmitter
{
Q_OBJECT
public:
explicit ClientConnection(QWebSocket *socket, QObject *parent = nullptr);
~ClientConnection();
bool init();
QHostAddress ip() const;
void addMessage(const Messages::ReplyMessage &message) override final;
Q_SIGNALS:
void newTextMessage(MessageTransmitter *transmitter, const QString &message);
void disconnected(ClientConnection *conn);
private Q_SLOTS:
void onNewTextMessageFromSocket(const QString &message);
void sendMessagesFromQueue();
void onSocketDisconnect();
private: // methods
void sendMessages();
private: // attributes
QWebSocket *m_socket;
QQueue<Messages::ReplyMessage> m_messageQueue;
QHostAddress m_ip;
LOGGER_T m_logger;
}; // class ClientConnection
} // namespace Connection
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,113 @@
/**
* @RDE_HEADER@
* The ConnectionHandler class functions as a WebSocket server and manages incoming client connections.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "connection_handler.h"
#include "client_connection.h"
#include "WsBiteInterface/Messages/message_transmitter.h"
#include <nglsettings/nglsettings_connections.h>
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>
using namespace WarehouseGuez::WsBiteInterface::Connection;
ConnectionHandler::ConnectionHandler()
: m_server(nullptr)
, m_logger(getLogger("ConnectionHandler"))
{
}
ConnectionHandler::~ConnectionHandler()
{
for (auto s : qAsConst(m_connections))
s->disconnect(this);
qDeleteAll(m_connections);
}
bool ConnectionHandler::init()
{
if (m_server != nullptr)
{
m_server->disconnect();
delete m_server;
}
// TODO: get a server name from config ?
// TODO: get the SslMode from config ?
m_server = new QWebSocketServer(QStringLiteral("RDE-EXC"), QWebSocketServer::NonSecureMode, this);
connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection);
connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError);
// TODO: read port from config?
int port = NGL::Connections::port(NGL::Connections::eConnection::LVS);
DEBUG_LOG(m_logger) << "Trying to listen to port " << port;
if (!m_server->listen(QHostAddress::Any, port))
{
ERROR_LOG(m_logger) << "Not possible to listen to port " << port;
return false;
}
DEBUG_LOG(m_logger) << "... ok - port: " << port;
return true;
}
void ConnectionHandler::onNewMessage(WarehouseGuez::WsBiteInterface::Messages::MessageTransmitter *transmitter, const QString &message)
{
emit newTextMessageFromClient(transmitter, message);
}
void ConnectionHandler::onServerError(QWebSocketProtocol::CloseCode closeCode)
{
ERROR_LOG(m_logger) << "Got server error with close code " << closeCode;
}
void ConnectionHandler::onNewConnection()
{
while (m_server->hasPendingConnections())
{
QWebSocket *socket = m_server->nextPendingConnection();
ClientConnection *newConnection = new ClientConnection(socket, this);
if (!newConnection->init())
{
ERROR_LOG(m_logger) << "Failed to initialise new client";
delete newConnection;
newConnection = nullptr;
continue;
}
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::onNewMessage);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::onDisconnected);
m_connections.append(newConnection);
DEBUG_LOG(m_logger) << "New client with ip " << newConnection->ip().toString() << " connected";
}
}
void ConnectionHandler::onDisconnected(ClientConnection *conn)
{
bool removeCount = m_connections.removeOne(conn);
Q_ASSERT(removeCount == 1);
conn->deleteLater(); // use deleteLater() as the signal is emitted from with ClientConnection
if (m_connections.empty())
emit lastConnectionClosed();
emit clientDisconnected(conn);
}
/*
void ConnectionHandler::onPositions(const ::WsBiteInterface::Messages::ReplyMessage &positionsCnr)
{
for (ClientConnection *currentConnection : qAsConst(m_connections))
currentConnection->addMessage(positionsCnr);
}
*/
@@ -0,0 +1,60 @@
/**
* @RDE_HEADER@
* The ConnectionHandler class functions as a WebSocket server and manages incoming client connections.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtNetwork/QHostAddress>
#include <QtWebSockets/qwebsocketprotocol.h>
#include "../Messages/ws_reply_message.h"
#include "logger.h"
class QWebSocketServer;
namespace WarehouseGuez
{
namespace WsBiteInterface
{
namespace Messages
{
class MessageTransmitter;
}
namespace Connection
{
class ClientConnection;
class ConnectionHandler
: public QObject
{
Q_OBJECT
public:
explicit ConnectionHandler();
~ConnectionHandler();
bool init();
Q_SIGNALS:
void newTextMessageFromClient(Messages::MessageTransmitter *transmitter, const QString &message);
void lastConnectionClosed();
void clientDisconnected(Messages::MessageTransmitter *transmitter);
private Q_SLOTS:
void onNewMessage(Messages::MessageTransmitter *transmitter, const QString &message);
void onServerError(QWebSocketProtocol::CloseCode closeCode);
void onNewConnection();
void onDisconnected(ClientConnection *conn);
private: // attributes
QWebSocketServer *m_server;
QVector<ClientConnection *> m_connections;
LOGGER_T m_logger;
};
} // namespace Connection
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,42 @@
/**
* @RDE_HEADER@
* The MessageHandler class processes messages from the client an creates appropriate replys
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "message_handler.h"
#include "message_transmitter.h"
#include "ws_client_message.h"
#include <memory>
namespace WarehouseGuez
{
namespace WsBiteInterface
{
namespace Messages
{
MessageHandler::MessageHandler(DataManager *dataManager)
: m_dataManager(dataManager)
, m_logger(getLogger("MessageHandler"))
{
Q_ASSERT(dataManager);
}
void MessageHandler::onNewTextMessage(MessageTransmitter *transmitter, const QString &message)
{
Q_ASSERT(transmitter);
std::unique_ptr<ClientMessage> clientMessage(ClientMessage::create(message, m_logger));
if (!clientMessage)
return;
clientMessage->process(m_dataManager, transmitter);
}
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,43 @@
/**
* @RDE_HEADER@
* The MessageHandler class processes messages from the client an creates appropriate replys
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QObject>
#include "logger.h"
namespace WarehouseGuez
{
namespace WsBiteInterface
{
class DataManager;
namespace Messages
{
class MessageTransmitter;
class MessageHandler
: public QObject
{
Q_OBJECT
public:
explicit MessageHandler(DataManager *dataManager);
public Q_SLOTS:
void onNewTextMessage(MessageTransmitter *transmitter, const QString &message);
private:
DataManager *m_dataManager;
LOGGER_T m_logger;
};
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,26 @@
/**
* @RDE_HEADER@
* The MessageTransmitter Interface offers an extremely lightweight API for a class to just write textmessages to
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include "ws_reply_message.h"
namespace WarehouseGuez
{
namespace WsBiteInterface
{
namespace Messages
{
class MessageTransmitter
{
public:
virtual void addMessage(const ReplyMessage &message) = 0;
};
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,161 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id: client_message.cpp 58958 2023-02-13 11:26:20Z fritsche_h $
* $HeadURL: svn://slssvn/TDS/branches/product/stable/guez2/Lts/Services/WarehouseGuez/WsBiteInterface/Messages/client_message.cpp $
* $Author: fritsche_h $
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "ws_client_message.h"
#include "ws_reply_message.h"
#include "WsBiteInterface/bite_data_manager.h"
#include "WsBiteInterface/Messages/message_transmitter.h"
#include "WsBiteInterface/json_keys.h"
#include <QtCore/QJsonDocument>
#include <QtCore/QUuid>
#include <chrono>
/*
*python testing:
import websocket
import json
import time
ws = websocket.create_connection("ws://127.0.0.1:2081")
d = { 'type' : 'getEssentials', 'uuid': 'blub' }
ws.send(json.dumps(d))
d = { 'type' : 'getConfigCNR', 'uuid': 'blub' }
ws.send(json.dumps(d))
d = { 'type' : 'getPositionsCNR', 'uuid': 'blub', 'data': {'repeat': 10}}
ws.send(json.dumps(d))
while True:
ws.recv()
*/
namespace WarehouseGuez
{
namespace WsBiteInterface
{
using namespace JsonKeys;
namespace Messages
{
// ####### ClientMessage begin #######
ClientMessage *ClientMessage::create(const QString &message, NGL::INGLLogger &logger)
{
ClientMessage *result = nullptr;
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error);
if (error.error != QJsonParseError::NoError)
{
ERROR_LOG(logger) << "Got message which is not JSON conform: " << message;
return new InvalidMessage(QString(), QStringLiteral("Got message which is not JSON conform"));
}
QJsonObject obj = doc.object();
QJsonObject dataPart = obj.value(DATA()).toObject();
QString type = obj.value(TYPE()).toString();
QString uuid = obj.value(UUID_()).toString();
if (type.isEmpty())
{
ERROR_LOG(logger) << "Got message without type: " << message;
result = new InvalidMessage(uuid, QStringLiteral("Message has no type"));
}
else if (type == ERROR_() && dataPart.contains(ERROR_MESSAGE()) && dataPart.contains(ERROR_CLASS()) && dataPart.contains(UUID_()))
{
ERROR_LOG(logger) << "Got error message: " << QJsonDocument(dataPart).toJson();
return nullptr;
}
else if (uuid.isEmpty())
{
ERROR_LOG(logger) << "Got message without uuid: " << message;
result = new InvalidMessage(QString(), QStringLiteral("Got message without uuid"));
}
else if (type == GET_BITE_DATA())
result = new GetBiteDataMessage(type, uuid, dataPart);
if (result == nullptr)
{
ERROR_LOG(logger) << "Got message with invalid type: " << message;
result = new InvalidMessage(uuid, QStringLiteral("Invalid type"));
}
if (!result->hasValidData())
{
ERROR_LOG(logger) << "Got message with invalid data part: " << message;
delete result;
result = new InvalidMessage(uuid, QStringLiteral("Has invalid data part"));
}
return result;
}
ClientMessage::ClientMessage(const QString &type, const QString &uuid, const QJsonObject &data)
: m_type(type)
, m_uuid(uuid)
, m_data(data)
{
}
// ####### ClientMessage end #######
InvalidMessage::InvalidMessage(const QString &uuid, const QString &errorText)
: ClientMessage(QString(), uuid)
, m_errorText(errorText)
{}
// ####### InvalidMessage begin #######
void InvalidMessage::process(DataManager *dataManager, MessageTransmitter *transmitter)
{
Q_UNUSED(dataManager);
ErrorMessage::ErrorData errorData;
errorData.errorClass = 1; // ??????????
errorData.errorMessage = m_errorText;
errorData.uuid = m_uuid;
transmitter->addMessage(ErrorMessage(errorData));
}
bool InvalidMessage::hasValidData() const
{
// always true because there is no data part
return true;
}
// ####### InvalidMessage end #######
// ####### GetBiteDataMessage begin #######
void GetBiteDataMessage::process(DataManager *dataManager, MessageTransmitter *transmitter)
{
using namespace Messages;
int equipNo = m_data.value(EQUIP_NO()).toInt();
int boxId = m_data.value(BOX()).toInt();
dataManager->setEquipNoBoxId(equipNo, boxId, transmitter, m_uuid);
OkMessage::OkData okMsg;
okMsg.messageType = GET_BITE_DATA();
okMsg.uuid = m_uuid;
okMsg.info = QStringLiteral("Received");
OkMessage msg(okMsg);
transmitter->addMessage(msg);
}
// ####### GetBiteDataMessage end #######
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,71 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id: client_message.h 58958 2023-02-13 11:26:20Z fritsche_h $
* $HeadURL: svn://slssvn/TDS/branches/product/stable/guez2/Lts/Services/WarehouseGuez/WsBiteInterface/Messages/client_message.h $
* $Author: fritsche_h $
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QJsonObject>
#include "logger.h"
namespace WarehouseGuez
{
namespace WsBiteInterface
{
class DataManager;
namespace Messages
{
class MessageTransmitter;
class ClientMessage
{
public:
static ClientMessage *create(const QString &message, NGL::INGLLogger &logger);
virtual void process(DataManager *dataManager, MessageTransmitter *transmitter) = 0;
virtual bool hasValidData() const = 0;
virtual ~ClientMessage() = default;
ClientMessage(const QString &type, const QString &uuid, const QJsonObject &data = QJsonObject());
protected: // attributes
const QString m_type;
const QString m_uuid;
const QJsonObject m_data;
}; // class ClientMessage
class GetBiteDataMessage final : public ClientMessage
{
public:
void process(DataManager *dataManager, MessageTransmitter *transmitter) override;
bool hasValidData() const override { return true; }
using ClientMessage::ClientMessage;
}; // class GetBiteDataMessage
class InvalidMessage final : public ClientMessage
{
friend class ClientMessage;
explicit InvalidMessage(const QString &uuid, const QString &errorText);
public:
void process(DataManager *dataManager, MessageTransmitter *transmitter) override;
bool hasValidData() const override;
using ClientMessage::ClientMessage;
private: // attributes
QString m_errorText;
}; // class InvalidMessage
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,79 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id: reply_message.cpp 58543 2022-12-05 13:40:10Z rathje $
* $HeadURL: svn://slssvn/TDS/branches/product/stable/guez2/Lts/Services/WarehouseGuez/WsBiteInterface/Messages/reply_message.cpp $
* $Author: rathje $
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "ws_reply_message.h"
#include "WsBiteInterface/json_keys.h"
#include <QtCore/QUuid>
#include <QtCore/QJsonDocument>
#include <QtGlobal>
namespace WarehouseGuez
{
namespace WsBiteInterface
{
using namespace JsonKeys;
namespace Messages
{
// ####### ReplyMessage begin #######
QString ReplyMessage::toJsonString() const
{
return QString::fromUtf8(QJsonDocument(m_jsonRepresentation).toJson(QJsonDocument::Compact));
}
ReplyMessage::ReplyMessage(const QString &type, const QString &uuid)
{
m_jsonRepresentation.insert(TYPE(), type);
Q_ASSERT(!uuid.isEmpty());
m_jsonRepresentation.insert(UUID_(), uuid);
}
// ####### ReplyMessage end #######
// ####### OkMessage begin #######
OkMessage::OkMessage(const OkMessage::OkData &data)
: ReplyMessage(OK(), data.uuid)
{
m_jsonRepresentation.insert(DATA(),
QJsonObject({
{MESSAGE_TYPE(), data.messageType},
{INFO(), data.info}
}));
}
// ####### OkMessage end #######
// ####### ErrorMessage begin #######
ErrorMessage::ErrorMessage(const ErrorMessage::ErrorData &data)
: ReplyMessage(ERROR_(), data.uuid)
{
m_jsonRepresentation.insert(DATA(),
QJsonObject({
{ERROR_CLASS(), data.errorClass},
{ERROR_MESSAGE(), data.errorMessage}
}));
}
// ####### ErrorMessage end #######
// ####### BiteDataMessage begin #######
BiteDataMessage::BiteDataMessage(const QJsonObject &data, const QString &uuid)
: ReplyMessage(BITE_DATA(), uuid)
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### BiteDataMessage end #######
} // namespace Messages
} // namespace WsBiteInterface
} // namespace CombatNetRadio
@@ -0,0 +1,103 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id: reply_message.h 58543 2022-12-05 13:40:10Z rathje $
* $HeadURL: svn://slssvn/TDS/branches/product/stable/guez2/Lts/Services/WarehouseGuez/WsBiteInterface/Messages/reply_message.h $
* $Author: rathje $
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QVector>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <QtCore/QString>
namespace WarehouseGuez
{
namespace WsBiteInterface
{
namespace Messages
{
class ReplyMessage
{
public:
ReplyMessage() = default; //!< QVector requires this; don't use directly
virtual ~ReplyMessage() = default;
virtual QString toJsonString() const;
protected:
template<typename T>
static QJsonArray vecToPath(const QVector<T> &data)
{
QJsonArray result;
for (const T &p : data)
result.append(p.toJson());
return result;
}
protected: // methods
explicit ReplyMessage(const QString &type, const QString &uuid);
protected: // attributes
QJsonObject m_jsonRepresentation;
}; // class Reply Message
class ErrorMessage final
: public ReplyMessage
{
public:
struct ErrorData
{
int errorClass = 0;
QString uuid;
QString errorMessage;
ErrorData() = default;
explicit ErrorData(int errorClass_, const QString &uuid_, const QString &errorMessage_)
: errorClass(errorClass_)
, uuid(uuid_)
, errorMessage(errorMessage_)
{}
};
explicit ErrorMessage(const ErrorData &data);
explicit ErrorMessage(int errorClass, const QString &uuid, const QString &errorMessage)
: ErrorMessage(ErrorData(errorClass, uuid, errorMessage))
{}
}; // class ErrorMessage
class OkMessage final
: public ReplyMessage
{
public:
struct OkData
{
QString uuid;
QString messageType;
QString info;
};
explicit OkMessage(const OkData &data);
}; // class OkMessage
class BiteDataMessage final
: public ReplyMessage
{
public:
explicit BiteDataMessage(const QJsonObject &data, const QString &uuid);
}; // BiteDataMessage
} // namespace Messages
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,294 @@
/**
* @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 Fritsche, SLSE, 2017-09-07
*/
#include "bite_data_manager.h"
#include "dds_handler.h"
#include "WsBiteInterface/Messages/message_transmitter.h"
#include <WarehouseGuez/WsBiteInterface/json_keys.h>
#include <LtsUtilsCore/outdated_position.h>
#include <nglsettings/nglsettings_connections.h>
#include <QMap>
#include <QUuid>
#include <QJsonDocument>
namespace WarehouseGuez
{
namespace WsBiteInterface
{
using namespace JsonKeys;
DataManager::DataManager(std::shared_ptr<DdsHandler> ddsHandler)
: m_scmWebSocket(new QWebSocket)
, m_ddsHandler(ddsHandler)
, m_timer(new QTimer(this))
, m_logger(getLogger(QLatin1String("DataManager")))
{
QUrl scmUrl(QStringLiteral("ws://%1:%2").arg(NGL::Connections::hostName(NGL::Connections::eConnection::SCM_WEBSOCKET)).arg(NGL::Connections::port(NGL::Connections::eConnection::SCM_WEBSOCKET)));
connect(m_scmWebSocket, &QWebSocket::connected, this, &DataManager::onConnected);
connect(m_scmWebSocket, &QWebSocket::disconnected, this, &DataManager::closed);
m_scmWebSocket->open(scmUrl);
// DTC TrainingAreaBase
m_tabDtc = TrainingAreaBase::Interface::Dtc::create(m_ddsHandler->dds());
if (m_tabDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create DTC TrainingAreaBase";
return;
}
#if 0
connectToTabWebSocket(8080, 42);
#endif
}
DataManager::~DataManager()
{
for ( TabData data : m_tabWebSocketMap.values())
delete data.websocket;
delete m_scmWebSocket;
}
void DataManager::onConnected()
{
DEBUG_LOG(m_logger) << "SCM websocket port connected";
connect(m_scmWebSocket, &QWebSocket::textMessageReceived, this, &DataManager::onTextMessageFromScm);
connect(m_timer, &QTimer::timeout, this, &DataManager::onTimerTimeout);
m_timer->setInterval(60000);
m_timer->start();
onTimerTimeout();
}
void DataManager::onTimerTimeout()
{
m_scmWebSocket->sendTextMessage(QStringLiteral("{\"type\":\"servicePortsInformationRequest\", \"uuid\": \"7777\"}"));
}
void DataManager::onTextMessageFromScm(const QString &message)
{
DEBUG_LOG(m_logger) << "onTextMessageFromScm from scm: " << message;
const QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8());
const QJsonArray exercises = doc.object().value(DATA()).toArray();
for (const QJsonValue &valEx : exercises)
{
const QJsonObject &exercise = valEx.toObject();
const int exerciseId = exercise.value(EXERCISE_ID()).toInt();
DEBUG_LOG(m_logger) << "textMessageFromScm from scm - exerciseId " << exerciseId;
const QJsonArray services = exercise.value(SERVICES()).toArray();
for (const QJsonValue &valSvc : services)
{
const QJsonObject &service = valSvc.toObject();
const QString svcName = service.value(NAME_ABBREVATION()).toString().toUpper();
DEBUG_LOG(m_logger) << "textMessageFromScm from scm - svcName " << svcName;
if (svcName != QStringLiteral("TAB"))
continue;
DEBUG_LOG(m_logger) << "service TAB ";
const QJsonArray ports = service.value(PORTS()).toArray();
for (const QJsonValue &valPort : ports)
{
const QJsonObject &port = valPort.toObject();
int typeId = port.value(TYPE_ID()).toInt();
if (typeId == Core::PortType::WebSocketServer)
{
int tabPort = port.value(NUMBER()).toInt();
DEBUG_LOG(m_logger) << "connect to TAB - port: " << tabPort;
connectToTabWebSocket(tabPort, exerciseId);
}
}
}
}
}
void DataManager::onConnectedTab()
{
DEBUG_LOG(m_logger) << "TAB connected";
}
void DataManager::connectToTabWebSocket(int port, int exerciseId)
{
if (m_tabWebSocketMap.contains(exerciseId))
{
TabData tabData = m_tabWebSocketMap.value(exerciseId);
// Websocket connection already exists?
if (tabData.port == port)
{
INFO_LOG(m_logger) << "Connection to port " << port << " already exists.";
return;
}
else
{
tabData.websocket->close();
delete tabData.websocket;
m_tabWebSocketMap.remove(exerciseId);
}
}
INFO_LOG(m_logger) << "New connection: exercise: " << exerciseId << ", port: " << port;
const QUrl url(QStringLiteral("ws://%1:%2").arg(NGL::Connections::hostName(NGL::Connections::eConnection::SCM_WEBSOCKET)).arg(port));
QWebSocket *webSocketTab = new QWebSocket;
connect(webSocketTab, &QWebSocket::connected, this, &DataManager::onConnectedTab);
connect(webSocketTab, &QWebSocket::disconnected, this, &DataManager::closedTab);
connect(webSocketTab, &QWebSocket::textMessageReceived, this, &DataManager::onTextMessageFromTab);
DEBUG_LOG(m_logger) << "Trying to connect to TAB at " << url.toString();
webSocketTab->open(url);
TabData data;
data.exerciseId = exerciseId;
data.port = port;
data.websocket = webSocketTab;
m_tabWebSocketMap.insert(exerciseId, data);
}
void DataManager::onClientDisconnect(Messages::MessageTransmitter *transmitter)
{
for (EquipData &ed : m_equipDataMap)
{
if (ed.transmitter == transmitter)
{
DEBUG_LOG(m_logger) << "removed dead transmitter";
ed.transmitter = nullptr;
}
}
}
void DataManager::onTextMessageFromTab(const QString &message)
{
INFO_LOG(m_logger) << "onTextMessageFromTab : " << message;
const QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8());
if (doc.object().value(TYPE()) != BITE_DATA() && doc.object().value(TYPE()) != POSITION_DATA())
return;
INFO_LOG(m_logger) << "TYPE: " << doc.object().value(TYPE()).toString();
QJsonObject data = doc.object().value(DATA()).toObject();
data.insert(LAST_UPDATE(), QDateTime::currentSecsSinceEpoch());
int equipNo = data.value(EQUIP_NO()).toInt();
INFO_LOG(m_logger) << "equipNo: " << equipNo;
if (equipNo <= 0)
return;
if (doc.object().value(TYPE()) == BITE_DATA())
m_equipDataMap[equipNo].biteMessage = data;
if (doc.object().value(TYPE()) == POSITION_DATA())
{
m_equipDataMap[equipNo].lastPositionUpdate = data.value(LAST_POSITION_UPDATE()).toDouble();
INFO_LOG(m_logger) << "lastPosUpdate: " << m_equipDataMap[equipNo].lastPositionUpdate;
}
if (m_equipDataMap[equipNo].boxId >= 0)
{
Messages::MessageTransmitter* transmitter = m_equipDataMap[equipNo].transmitter;
if (transmitter == nullptr)
{
ERROR_LOG(m_logger) << "transmitter for eqId " << equipNo << " no longer available";
return;
}
int &boxId = m_equipDataMap[equipNo].boxId;
QJsonObject &biteData = m_equipDataMap[equipNo].biteMessage;
biteData.insert(BOX(), boxId);
biteData.insert(LAST_POSITION_UPDATE(), m_equipDataMap[equipNo].lastPositionUpdate);
transmitter->addMessage(Messages::BiteDataMessage(biteData, m_equipDataMap[equipNo].uuid));
INFO_LOG(m_logger) << "Send Message with boxId: " << boxId << ", equipNo: " << equipNo;
if (boxId == 0)
boxId = -1; // only single request
}
}
void DataManager::setEquipNoBoxId(int equipNo, int boxId, Messages::MessageTransmitter *transmitter, const QString &uuid)
{
INFO_LOG(m_logger) << "equipNo: " << equipNo << ", boxId = " << boxId;
// erase abonnement, no further biteData telegrams
if (equipNo == 0)
{
for ( int key : m_equipDataMap.keys())
{
if (m_equipDataMap[key].boxId == boxId)
{
m_equipDataMap.remove(key);
break;
}
}
return;
}
auto &equipData = m_equipDataMap[equipNo];
// create new equipData if equipNo is not present yet
equipData.equipNo = equipNo;
equipData.boxId = boxId;
equipData.transmitter = transmitter;
equipData.uuid = uuid;
// find biteMessage and send biteData telegram if not older than 1h
if (!equipData.biteMessage.isEmpty())
{
QJsonObject &data = equipData.biteMessage;
qint64 lastUpdate = data.value(LAST_UPDATE()).toDouble();
if ( lastUpdate + 3600 > QDateTime::currentSecsSinceEpoch())
{
data.insert(BOX(), boxId);
data.insert(LAST_POSITION_UPDATE(), equipData.lastPositionUpdate);
transmitter->addMessage(Messages::BiteDataMessage(data, equipData.uuid));
INFO_LOG(m_logger) << "Send Message with boxId: " << boxId << ", equipNo: " << equipNo;
}
}
else
{
QJsonObject data;
data.insert(EQUIP_NO(), equipNo);
data.insert(BOX(), boxId);
data.insert(LAST_UPDATE(), 0);
data.insert(LAST_POSITION_UPDATE(), 0);
data.insert(IS_LICENSED(), false);
equipData.biteMessage = data;
transmitter->addMessage(Messages::BiteDataMessage(data, equipData.uuid));
INFO_LOG(m_logger) << "Send Message with boxId: " << boxId << ", equipNo: " << equipNo << ", lastUpdate 0";
// send bite request
QJsonObject biteData;
biteData.insert(DATA(), data);
biteData.insert(TYPE(), SEND_BITE_REQUEST());
biteData.insert(UUID_(), QUuid::createUuid().toString());
QString message = QString::fromStdString(QJsonDocument(biteData).toJson(QJsonDocument::Compact).toStdString());
INFO_LOG(m_logger) << "message: " << message;
for (TabData dataTab : m_tabWebSocketMap)
dataTab.websocket->sendTextMessage(message);
}
}
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,99 @@
/**
* @RDE_HEADER@
* The DataManager class is a convenience class for managing structure data
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <memory>
#include <QHash>
#include <QSet>
#include <QTimer>
#include <WarehouseGuez/WsBiteInterface/Messages/ws_reply_message.h>
#include "logger.h"
#include <TrainingAreaBase/tab.hpp>
#include <TrainingAreaBase/tab_dtc.h>
#include <ParticipantManagement/ppm.hpp>
#include <QtWebSockets/QWebSocket>
class QTimer;
namespace WarehouseGuez
{
namespace Interface
{
class Dtc;
}
class DdsHandler;
namespace WsBiteInterface
{
namespace Messages
{
class MessageTransmitter;
}
class DataManager final : public QObject
{
Q_OBJECT
public:
explicit DataManager(std::shared_ptr<DdsHandler> ddsHandler);
~DataManager();
void setEquipNoBoxId( int equipNo, int boxId, Messages::MessageTransmitter* transmitter, const QString &uuid);
Q_SIGNALS:
void closed();
void closedTab();
public slots:
void onClientDisconnect(Messages::MessageTransmitter *transmitter);
private Q_SLOTS:
void onConnected();
void onConnectedTab();
void onTimerTimeout();
void onTextMessageFromScm(const QString &message);
void onTextMessageFromTab(const QString &message);
private: // methods
void connectToTabWebSocket(int port, int exerciseId);
private: // attributes
struct EquipData
{
int equipNo{0};
int boxId{-1} ;
Messages::MessageTransmitter* transmitter{nullptr};
QString uuid;
QJsonObject biteMessage;
qint64 lastPositionUpdate{0};
};
struct TabData
{
int exerciseId{0};
int port{0};
QWebSocket* websocket;
};
QWebSocket *m_scmWebSocket;
QMap<int,TabData> m_tabWebSocketMap;
QMap<int,EquipData > m_equipDataMap; // Key: equipNo, Value: <equipData>
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<TrainingAreaBase::Interface::Dtc> m_tabDtc; ///< Pointer to DTC Training Area Base interface object
QTimer *m_timer = nullptr;
LOGGER_T m_logger;
}; // class DataManager
} // namespace WsBiteInterface
} // namespace WarehouseGuez
+79
View File
@@ -0,0 +1,79 @@
/**
* @RDE_HEADER@
* Header file which holds all occuring JSON keys
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QString>
namespace WarehouseGuez
{
namespace WsBiteInterface
{
/**
* @brief Namespace which holds all occuring JSON keys as const QString objects
*/
namespace JsonKeys
{
// root keys
inline QString DATA() { return QLatin1String("data"); }
inline QString UUID_() { return QStringLiteral("uuid"); } // Windows: typedef GUID UUUID; ...
inline QString TYPE() { return QStringLiteral("type"); }
// types for TAB client
inline QString SEND_BITE_REQUEST() { return QStringLiteral("sendBiteRequest"); }
// types for client --> server messages
inline QString GET_BITE_DATA() { return QStringLiteral("getBiteData"); }
// types for server --> client messages
inline QString BITE_DATA() { return QStringLiteral("biteData"); }
inline QString POSITION_DATA() { return QStringLiteral("positionData"); }
inline QString OK() { return QStringLiteral("ok");}
inline QString ERROR_() { return QLatin1String("error"); }
// data keys
inline QString EQUIP_NO() { return QLatin1String("equipNo"); }
inline QString BOX() { return QLatin1String("box"); }
inline QString LAST_UPDATE() { return QLatin1String("lastUpdate"); }
inline QString BITE_ERRORS() { return QLatin1String("biteErrors"); }
inline QString ERROR_TEXT() { return QLatin1String("errorText"); }
inline QString LANG() { return QLatin1String("lang"); }
inline QString _TEXT() { return QLatin1String("text"); }
inline QString DEVICE_ID() { return QLatin1String("deviceId"); }
inline QString SUBDEVICE() { return QLatin1String("subdevice"); }
inline QString UNIQUE_ID() { return QLatin1String("uniqueId"); }
inline QString ERROR_NO() { return QLatin1String("errorNo"); }
inline QString CONFIGURATION_ERRORS() { return QLatin1String("configurationErrors"); }
inline QString COMPONENT_NAME() { return QLatin1String("componentName"); }
inline QString LAST_POSITION_UPDATE() { return QLatin1String("lastPositionUpdate"); }
inline QString IS_LICENSED() { return QLatin1String("isLicensed"); }
inline QString POS_LAT() { return QLatin1String("posX"); }
inline QString POS_LON() { return QLatin1String("posY"); }
inline QString POS_Z() { return QLatin1String("posZ"); }
inline QString INFO() { return QLatin1String("info"); }
inline QString ERROR_CLASS() { return QLatin1String("errorClass"); }
inline QString ERROR_MESSAGE() { return QLatin1String("errorMessage"); }
inline QString MESSAGE_TYPE() { return QLatin1String("msgType"); }
inline QString EXERCISE_ID() { return QLatin1String("exerciseId"); }
inline QString SERVICES() { return QLatin1String("services"); }
inline QString NAME() { return QLatin1String("name"); }
inline QString NAME_ABBREVATION() { return QLatin1String("nameAbbrevation"); }
inline QString PORTS() { return QLatin1String("ports"); }
inline QString TYPE_ID() { return QLatin1String("typeId"); }
inline QString NUMBER() { return QLatin1String("number"); }
} // namespace JsonKeys
} // namespace WsBiteInterface
} // namespace WarehouseGuez
@@ -0,0 +1,60 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "ws_bite_interface_handler.h"
#include "Connection/connection_handler.h"
#include "Messages/message_handler.h"
#include "Messages/message_transmitter.h"
#include "dds_handler.h"
#include "bite_data_manager.h"
namespace WarehouseGuez
{
namespace WsBiteInterface
{
WsBiteInterfaceHandler::WsBiteInterfaceHandler(DataManager *dataManager)
: m_dataManager(dataManager)
, m_connectionHandler(nullptr)
, m_messageHandler(nullptr)
, m_logger(getLogger("WsBiteInterfaceHandler"))
{
Q_ASSERT(dataManager);
}
WsBiteInterfaceHandler::~WsBiteInterfaceHandler()
{
delete m_connectionHandler;
delete m_messageHandler;
}
bool WsBiteInterfaceHandler::init()
{
Q_ASSERT(!m_connectionHandler);
m_connectionHandler = new Connection::ConnectionHandler;
if (!m_connectionHandler->init())
{
ERROR_LOG(m_logger) << "Failed to initialise ConnectionHandler";
return false;
}
m_messageHandler = new Messages::MessageHandler(m_dataManager);
QObject::connect(m_connectionHandler, &Connection::ConnectionHandler::clientDisconnected, m_dataManager, &DataManager::onClientDisconnect);
//QObject::connect(m_connectionHandler, &Connection::ConnectionHandler::lastConnectionClosed, m_dataManager, &ExerciseManager::stopPositionsUpdate);
QObject::connect(m_connectionHandler, &Connection::ConnectionHandler::newTextMessageFromClient, m_messageHandler, &Messages::MessageHandler::onNewTextMessage);
return true;
}
} // namespace WsBiteInterface
} // namespace CombatNetRadio
@@ -0,0 +1,46 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QObject>
#include "logger.h"
namespace WarehouseGuez
{
namespace WsBiteInterface
{
class DataManager;
namespace Messages
{
class MessageHandler;
}
namespace Connection
{
class ConnectionHandler;
}
class WsBiteInterfaceHandler final
{
public:
explicit WsBiteInterfaceHandler(DataManager *dataManager);
~WsBiteInterfaceHandler();
bool init();
private:
DataManager *m_dataManager;
Connection::ConnectionHandler *m_connectionHandler;
Messages::MessageHandler *m_messageHandler;
LOGGER_T m_logger;
}; // class WsBiteInterfaceHandle
} // namespace WsBiteInterface
} // namespace WarehouseGuez
+48
View File
@@ -0,0 +1,48 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#include "dds_handler.h"
namespace WarehouseGuez
{
DdsHandler::DdsHandler(int domainId)
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Global))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if(!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
// Pacemaker
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
m_ddsDts = WarehouseGuez::Interface::Dts::create(m_ddsConnector);
m_ddsFts = WarehouseGuez::Interface::Fts::create(m_ddsConnector);
bool bRet = m_ddsDts->enableAll();
INFO_LOG(m_logger) << "Dts initialised";
bRet &= m_ddsFts->enableAll();
INFO_LOG(m_logger) << "Fts initialised";
return bRet;
}
} // Namespace PDM
+56
View File
@@ -0,0 +1,56 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/Core/topic_lock_master.h>
#include <DDS/Core/pacemaker.h>
#include <WarehouseGuez/whg_dts.h>
#include <WarehouseGuez/whg_fts.h>
#include "logger.h"
namespace WarehouseGuez
{
class DdsHandler final
{
public:
explicit DdsHandler(int domainId);
~DdsHandler() = default;
bool init(const QStringList &qosFileList = QStringList());
std::shared_ptr<Core::Pacemaker> pacemaker() const
{
return m_pacemaker;
}
std::shared_ptr<Core::TopicLockMaster> topicLockMaster() const { return m_topicLockMaster; }
std::shared_ptr<WarehouseGuez::Interface::Dts> dts() const
{
return m_ddsDts;
}
std::shared_ptr<WarehouseGuez::Interface::Fts> fts() const
{
return m_ddsFts;
}
std::shared_ptr<DDSConnector::DdsConnector> dds() const { return m_ddsConnector; }
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<Core::Pacemaker> m_pacemaker;
std::shared_ptr<Core::TopicLockMaster> m_topicLockMaster;
std::shared_ptr<WarehouseGuez::Interface::Dts> m_ddsDts;
std::shared_ptr<WarehouseGuez::Interface::Fts> m_ddsFts;
NGL::INGLLogger &m_logger;
};
} // namespace WarehouseGuez
+174
View File
@@ -0,0 +1,174 @@
/**
* Handler for all exercise objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#include "handler_equipment_type_wh.h"
#include "object_equipment_type_wh.h"
#include "main_handler.h"
namespace WarehouseGuez
{
HandlerEquipmentTypeWh::HandlerEquipmentTypeWh(MainHandler *mainHandler)
: Interface::Fts::ModifyEquipmentTypeWhRequestHandler(mainHandler->dds()->fts())
, Interface::Fts::RemoveEquipmentTypeWhRequestHandler(mainHandler->dds()->fts())
, m_mainHandler(mainHandler)
, m_logger(getLogger("HandlerEquipmentTypeWh"))
{}
HandlerEquipmentTypeWh::~HandlerEquipmentTypeWh()
{
qDeleteAll(m_equipmenttypewhObjMap);
}
bool HandlerEquipmentTypeWh::init()
{
bool bRet = true;
// create languageHmi objects
auto cb = [this, &bRet](const Database::EquipmentTypeWh &data)
{
ObjectEquipmentTypeWh *ifs(new ObjectEquipmentTypeWh(m_mainHandler));
Core::FunctionReplyObject ret = ifs->createObject(data);
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
bRet = false;
return;
}
m_equipmenttypewhObjMap.insert(ifs->getId(), ifs);
};
if (!m_mainHandler->db()->select(cb) || !bRet)
{
ERROR_LOG(m_logger) << "Error reading data from database!";
return true;
}
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_equipmenttypewhObjMap.size();
return true;
}
void convert(Database::EquipmentTypeWh &data, const EquipmentTypeWh &request)
{
data.id = request.id();
data.name = QString::fromStdString(request.name());
data.canAbeSprache = request.configurationAbeLanguage().underlying();
data.agdusHelmWeste = request.configurationAgdusHV().underlying();
data.canAbeSprAusg = request.configurationAudioResponse();
data.canWirkdarstPyro = request.configurationCedPyrotechnic();
data.anzeigeAdag = request.configurationDisplayAdag().underlying();
data.adagUntergruppe = request.configurationDisplayAdagSubUnit().underlying();
data.canMhgrEnergie = request.configurationMhgrEnergieSave();
data.canMhgrBetrArt = request.configurationMhgrOperatingMode().underlying();
data.canSsFirSan = request.configurationSsFirSan();
data.canSsFirFunkt = request.configurationSsFirFunction().underlying();
data.canSsMvFunkt = request.configurationSsMineFitFunction().underlying();
data.canSsStdFunkt = request.configurationSsStandardFunction().underlying();
data.canStartupZeit = request.configurationStartupTime();
data.ausstgGrp = request.equipGroup();
data.ausstgNrMax = request.maxEquipNo();
data.ausstgNrMin = request.minEquipNo();
data.vbAgdus = request.vbAgdusId();
data.vbEinsatzmittel = request.vbAirSupport();
data.vbSteilfeuer = request.vbFireArea();
data.vbMinenIed = request.vbMineIed();
data.vbAcWaffen = request.vbNc();
data.canDevices = request.canDevices();
data.posUpdate = request.posUpdate().underlying();
}
void HandlerEquipmentTypeWh::onModifyEquipmentTypeWhRequest(const rti::core::SampleIdentity &cookie, const EquipmentTypeWh &request)
{
DEBUG_LOG(m_logger) << "onModifyEquipmentTypeWhRequest() id:" << request.id();
ObjectEquipmentTypeWh *ifs = nullptr;
Core::FunctionReplyObject ret;
if (request.id() <= 0) // add with -1
{
Database::EquipmentTypeWh data;
convert(data, request);
data.id = 0 - request.id();
DEBUG_LOG(m_logger) << "Request.id = " << request.id() << ", data.id = " << data.id;
ifs = new ObjectEquipmentTypeWh(m_mainHandler);
ret = ifs->createObject(data, true);
if (ret.error())
{
delete ifs;
ifs = nullptr;
ERROR_LOG(m_logger) << ret();
}
else
m_equipmenttypewhObjMap.insert(ifs->getId(), ifs);
}
else // modify
{
ifs = m_equipmenttypewhObjMap.value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "EquipmentTypeWh with id %1 not found")).arg(request.id());
m_mainHandler->dds()->fts()->modifyEquipmentTypeWhReply(cookie, ret);
return;
}
Database::EquipmentTypeWh data = ifs->getData();
convert(data, request);
ret = ifs->updateObject(data);
}
if (ret.error() || !ifs)
ERROR_LOG(m_logger) << ret();
else
sendToEXCON();
m_mainHandler->dds()->fts()->modifyEquipmentTypeWhReply(cookie, ret);
return;
}
//-----------------------------------------------------------------------------
void HandlerEquipmentTypeWh::onRemoveEquipmentTypeWhRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request)
{
DEBUG_LOG(m_logger) << "onRemoveEquipmentTypeWhRequest() id:" << request.id();
Core::FunctionReplyObject ret;
ObjectEquipmentTypeWh *ifs = m_equipmenttypewhObjMap.value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "EquipmentTypeWh with id %1 not found")).arg(request.id());
m_mainHandler->dds()->fts()->removeEquipmentTypeWhReply(cookie, ret);
return;
}
ret = ifs->removeObject();
if (ret.error())
ERROR_LOG(m_logger) << ret();
else
{
// delete ObjectEquipmentTypeWH
delete ifs;
m_equipmenttypewhObjMap.remove(request.id());
}
sendToEXCON();
m_mainHandler->dds()->fts()->removeEquipmentTypeWhReply(cookie, ret);
}
void HandlerEquipmentTypeWh::sendToEXCON()
{
m_mainHandler->wsBaseDataHandler()->sendEquipmentTypes();
}
} // Namespace WarehouseGuez
+39
View File
@@ -0,0 +1,39 @@
/**
* Handler for all Language HMI objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#pragma once
#include <QHash>
#include "logger.h"
#include "main_handler.h"
#include <WarehouseGuez/whg_db.h>
namespace WarehouseGuez
{
class ObjectEquipmentTypeWh;
class HandlerEquipmentTypeWh final
: protected Interface::Fts::ModifyEquipmentTypeWhRequestHandler
, protected Interface::Fts::RemoveEquipmentTypeWhRequestHandler
{
public:
explicit HandlerEquipmentTypeWh(MainHandler *mainHandler);
~HandlerEquipmentTypeWh();
bool init();
private:
void onModifyEquipmentTypeWhRequest(const rti::core::SampleIdentity &cookie, const EquipmentTypeWh &request) override final;
void onRemoveEquipmentTypeWhRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request) override final;
void sendToEXCON();
private:
QHash<int, ObjectEquipmentTypeWh*> m_equipmenttypewhObjMap;
MainHandler *m_mainHandler;
NGL::INGLLogger &m_logger;
};
}
+134
View File
@@ -0,0 +1,134 @@
/**
* Handler for all exercise objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#include "handler_injury_model.h"
#include "object_injury_model.h"
#include "whg_db.h"
namespace WarehouseGuez
{
HandlerInjuryModel::HandlerInjuryModel(MainHandler *mainHandler)
: Interface::Fts::ModifyInjuryModelAgdusWhRequestHandler(mainHandler->dds()->fts())
, Interface::Fts::RemoveInjuryModelAgdusWhRequestHandler(mainHandler->dds()->fts())
, m_mainHandler(mainHandler)
, m_logger(getLogger("HandlerInjuryModel"))
{}
HandlerInjuryModel::~HandlerInjuryModel()
{
qDeleteAll(m_injurymodelObjMap);
}
bool HandlerInjuryModel::init()
{
bool bRet = true;
// create InjuryModelAgdusWh objects
auto cb = [this, &bRet](const Database::InjuryModelAgdusWh &data)
{
ObjectInjuryModel *ifs(new ObjectInjuryModel(m_mainHandler));
Core::FunctionReplyObject ret = ifs->createObject(data);
if(ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
bRet = false;
return;
}
m_injurymodelObjMap.insert(ifs->getId(), ifs);
};
if (!m_mainHandler->db()->select(cb) || !bRet)
{
ERROR_LOG(m_logger) << "Error reading data from database!";
return true;
}
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_injurymodelObjMap.size();
return true;
}
void HandlerInjuryModel::onModifyInjuryModelAgdusWhRequest(const rti::core::SampleIdentity &cookie, const InjuryModelAgdusWh &request)
{
DEBUG_LOG(m_logger) << "onModifyInjuryModelAgdusWhRequest() id:" << request.id();
Core::FunctionReplyObject ret;
if (request.id() <= 0)
{
Database::InjuryModelAgdusWh data;
data.id = request.id();
data.name = QString::fromStdString(request.name());
data.version = QString::fromStdString(request.version());
data.beschreibung = QString::fromStdString(request.description());
ObjectInjuryModel *ifs(new ObjectInjuryModel(m_mainHandler));
ret = ifs->createObject(data);
if (ret.error())
{
delete ifs;
ifs = nullptr;
ERROR_LOG(m_logger) << ret();
}
else
m_injurymodelObjMap.insert(ifs->getId(), ifs);
}
else
{
ObjectInjuryModel *ifs = m_injurymodelObjMap.value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "InjuryModel with id %1 not found")).arg(request.id());
m_mainHandler->dds()->fts()->modifyInjuryModelAgdusWhReply(cookie, ret);
return;
}
Database::InjuryModelAgdusWh data = ifs->getData();
data.name = QString::fromStdString(request.name());
data.version = QString::fromStdString(request.version());
data.beschreibung = QString::fromStdString(request.description());
ret = ifs->updateObject(data);
}
if (ret.error())
ERROR_LOG(m_logger) << ret();
m_mainHandler->dds()->fts()->modifyInjuryModelAgdusWhReply(cookie, ret);
}
void HandlerInjuryModel::onRemoveInjuryModelAgdusWhRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request)
{
DEBUG_LOG(m_logger) << "onRemoveInjuryModelAgdusWhRequest() id:" << request.id();
Core::FunctionReplyObject ret;
ObjectInjuryModel *ifs = m_injurymodelObjMap.value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "InjuryModel with id %1 not found")).arg(request.id());
m_mainHandler->dds()->fts()->removeInjuryModelAgdusWhReply(cookie, ret);
return;
}
ret = ifs->removeObject();
if (ret.error())
ERROR_LOG(m_logger) << ret();
else
{
// delete ObjectInjuryModel
delete ifs;
m_injurymodelObjMap.remove(request.id());
}
m_mainHandler->dds()->fts()->removeInjuryModelAgdusWhReply(cookie, ret);
}
} // Namespace WarehouseGuez
+38
View File
@@ -0,0 +1,38 @@
/**
* Handler for all Language HMI objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#pragma once
#include <QHash>
#include "main_handler.h"
#include "logger.h"
namespace WarehouseGuez
{
class ObjectInjuryModel;
class HandlerInjuryModel final
: protected Interface::Fts::ModifyInjuryModelAgdusWhRequestHandler
, protected Interface::Fts::RemoveInjuryModelAgdusWhRequestHandler
{
public:
explicit HandlerInjuryModel(MainHandler *mainHandler);
~HandlerInjuryModel();
bool init();
private:
void onModifyInjuryModelAgdusWhRequest(const rti::core::SampleIdentity &cookie, const InjuryModelAgdusWh &request);
void onRemoveInjuryModelAgdusWhRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request);
private:
QHash<int, ObjectInjuryModel*> m_injurymodelObjMap;
MainHandler* m_mainHandler;
NGL::INGLLogger &m_logger;
};
}
+73
View File
@@ -0,0 +1,73 @@
/**
* Handler for all exercise objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#include "handler_types.h"
#include "main_handler.h"
#include <WarehouseGuez/whg_db_impl.h>
namespace WarehouseGuez
{
HandlerTypes::HandlerTypes(MainHandler *mainHandler)
: m_mainHandler(mainHandler)
, m_logger(getLogger("HandlerTypes"))
{}
bool HandlerTypes::init()
{
m_ppmDtc = ParticipantManagement::Interface::Dtc::create(m_mainHandler->dds()->dds());
if (m_ppmDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create PPM DTC";
return false;
}
if (!m_mainHandler->db()->truncateType())
{
ERROR_LOG(m_logger) << "Error reading types from db";
return false;
}
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::typeChanged,
this, &HandlerTypes::onTypeChanged);
m_ppmDtc->enableType();
return true;
}
static inline Database::Type convert(const ParticipantManagement::Type &data)
{
Database::Type dbType;
dbType.id = data.id();
dbType.name = QString::fromStdString(data.name());
dbType.ausstgTypId = data.equipmentTypeId() == 0 ? QVariant() : data.equipmentTypeId();
return dbType;
}
void HandlerTypes::onTypeChanged(const ParticipantManagement::Type &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onTypeChanged: " << data << ", " << modType;
switch(modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
m_mainHandler->db()->removeType(data.id());
auto dbData = convert(data);
m_mainHandler->db()->insert(dbData);
break;
}
case DataModification::eRemoved:
m_mainHandler->db()->removeType(data.id());
break;
}
}
} // Namespace WarehouseGuez
+36
View File
@@ -0,0 +1,36 @@
/**
* Handler for all Language HMI objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-03
*/
#pragma once
#include <QHash>
#include <ParticipantManagement/ppm_dtc.h>
#include "main_handler.h"
#include "logger.h"
namespace WarehouseGuez
{
class HandlerTypes : public QObject
{
Q_OBJECT
public:
explicit HandlerTypes(MainHandler *mainHandler);
bool init();
private Q_SLOTS:
void onTypeChanged(const ParticipantManagement::Type &data, DataModification modType);
private:
MainHandler* m_mainHandler;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc; ///< Pointer to DTC ParticipantManagement interface object
NGL::INGLLogger &m_logger;
};
}
+80
View File
@@ -0,0 +1,80 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: WarehouseGuez
###########################################################
#log4j.logger.WHG=DEBUG
#log4j.logger.WHG.main=DEBUG
#log4j.logger.WHG.DdsHandler=DEBUG
#log4j.logger.WHG.MainHandler=DEBUG
#
# Lts::RollingFileAppender
log4j.appender.file=Lts::RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace WarehouseGuez
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "WHG.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace WarehouseGuez
+23
View File
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Logging for WarehouseGuez
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "whg_export.h"
namespace WarehouseGuez
{
using LOGGER_T = NGL::INGLLogger &;
WHG_COMMON_EXPORT LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace WarehouseGuez
+42
View File
@@ -0,0 +1,42 @@
/**
* @RDE_HEADER@
* main for WarehouseGuez
* $Id$
* $HeadURL$
* $Author$
*/
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include "main_handler.h"
#include "logger.h"
#include "settings.h"
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
LtsCommandLineParser::LtsCommandLineParser options;
if (!options.init())
return -1;
app.createLogger("WHG");
WarehouseGuez::Settings::setIniFile(options.iniFile());
int iRet = -3;
{
std::unique_ptr<WarehouseGuez::MainHandler> mainHandler(new WarehouseGuez::MainHandler);
if (!mainHandler->init(options.domainId()))
return iRet;
STARTUP_LOG(app.baseLogger());
iRet = app.exec();
SHUTDOWN_LOG(app.baseLogger());
}
return iRet;
}
+107
View File
@@ -0,0 +1,107 @@
/**
* MainHandler for AssetManagement
* $Id$
* $HeadURL$
* $Author$
*/
#include "main_handler.h"
#include "settings.h"
#include "handler_equipment_type_wh.h"
#include "handler_injury_model.h"
#include "handler_types.h"
#include "WsBiteInterface/bite_data_manager.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <ngldb/db_service_handler.h>
#include <nglsettings/nglsettings_connections.h>
namespace WarehouseGuez
{
MainHandler::MainHandler()
: m_logger(getLogger("MainHandler"))
{}
MainHandler::~MainHandler()
{
m_wsBaseDataHandler = nullptr;
m_handlerEquipTypeWh = nullptr;
m_handlerInjuryModel = nullptr;
m_handlerTypes = nullptr;
m_ddsHandler = nullptr;
m_dbHandler = nullptr;
}
bool MainHandler::init(int domainId)
{
// initialize database
m_dbHandler = std::make_shared<DbHandler>();
if (!m_dbHandler->init(0, Settings::settings()))
{
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation dbHandler succesful.";
// initialize DDS
m_ddsHandler = std::make_shared<DdsHandler>(domainId);
if (!m_ddsHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation ddsHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation ddsHandler succesful.";
DEBUG_LOG(m_logger) << "WarehouseManagement FTC initialized";
m_handlerEquipTypeWh = std::make_shared<HandlerEquipmentTypeWh>(this);
if (!m_handlerEquipTypeWh->init())
{
ERROR_LOG(m_logger) << "Initalisation HandlerEquipmentTYpeWH failed";
return false;
}
m_handlerInjuryModel = std::make_shared<HandlerInjuryModel>(this);
if (!m_handlerInjuryModel->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerInjuryModel failed";
return false;
}
m_handlerTypes = std::make_shared<HandlerTypes>(this);
if (!m_handlerTypes->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerTypes failed";
return false;
}
// WebSocketServer
m_wsBaseDataHandler = std::make_shared<WsBaseDataInterface::WsBaseDataInterfaceHandler>(this);
if (!m_wsBaseDataHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation WsBaseDataInterfaceHandler failed.";
return false;
}
m_wsBiteInterfaceHandler = std::make_shared<WsBiteInterface::WsBiteInterfaceHandler>(new WsBiteInterface::DataManager(m_ddsHandler));
if (!m_wsBiteInterfaceHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation WsBiteInterfaceHandler failed.";
return false;
}
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
m_ddsHandler->pacemaker()->addPort(m_wsBaseDataHandler->webSocketPort(), Core::PortType::WebSocketServer);
return true;
}
std::shared_ptr<DatabaseInterface> MainHandler::db() const
{
return m_dbHandler->db();
}
} // namespace WarehouseGuez
+59
View File
@@ -0,0 +1,59 @@
/**
* MainHandler for AereaEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <memory>
#include "dds_handler.h"
#include "whg_db.h"
#include "WsBaseDataInterface/ws_base_data_interface_handler.h"
#include "WsBiteInterface/ws_bite_interface_handler.h"
#include "logger.h"
namespace NGLDB
{
template <typename DB> class DbServiceHandler;
}
namespace WarehouseGuez
{
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
class HandlerEquipmentTypeWh;
class HandlerInjuryModel;
class HandlerTypes;
namespace WsBiteInterface
{
class DataManager;
}
class MainHandler final
{
public:
MainHandler();
~MainHandler();
bool init(int domainId);
std::shared_ptr<DdsHandler> dds() const { return m_ddsHandler; }
std::shared_ptr<DatabaseInterface> db() const;
std::shared_ptr<WsBaseDataInterface::WsBaseDataInterfaceHandler> wsBaseDataHandler() { return m_wsBaseDataHandler; }
private:
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<DbHandler> m_dbHandler;
std::shared_ptr<HandlerEquipmentTypeWh> m_handlerEquipTypeWh;
std::shared_ptr<HandlerInjuryModel> m_handlerInjuryModel;
std::shared_ptr<HandlerTypes> m_handlerTypes;
std::shared_ptr<WsBaseDataInterface::WsBaseDataInterfaceHandler> m_wsBaseDataHandler;
std::shared_ptr<WsBiteInterface::WsBiteInterfaceHandler> m_wsBiteInterfaceHandler;
std::shared_ptr<WsBiteInterface::DataManager> m_wsBiteDataManager;
NGL::INGLLogger &m_logger;
};
} // namespace WarehouseGuez
+102
View File
@@ -0,0 +1,102 @@
/**
* Handler for the HMI language
* $Id$
* $HeadURL$
* $Author$
*/
#include "object_equipment_type_wh.h"
namespace WarehouseGuez
{
ObjectEquipmentTypeWh::ObjectEquipmentTypeWh(MainHandler *mainHandler)
: m_mainHandler(mainHandler)
, m_logger(getLogger("ObjectEquipmentTypeWh"))
{
}
ObjectEquipmentTypeWh::~ObjectEquipmentTypeWh()
{
}
Core::FunctionReplyObject ObjectEquipmentTypeWh::createObject(const Database::EquipmentTypeWh &data, bool forceInsert)
{
m_data = data;
if (forceInsert)
{
if (!m_mainHandler->db()->insert(m_data))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting EquipmentTypeWh-data into database"));
DEBUG_LOG(m_logger) << "New EquipmentTypeId: " << m_data.id;
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id);
}
Core::FunctionReplyObject ObjectEquipmentTypeWh::updateObject(const Database::EquipmentTypeWh &data)
{
if (!m_mainHandler->db()->update(data))
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating EquipmentTypeWh-data into database"));
m_data = data;
DEBUG_LOG(m_logger) << "Data changed for EquipmentTypeWhId: " << m_data.id;
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id);
}
Core::FunctionReplyObject ObjectEquipmentTypeWh::removeObject()
{
if (!m_mainHandler->db()->removeEquipmentTypeWh(m_data.id))
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "EquipmentTypeWh with id %1 can not be removed")).arg(m_data.id);
m_mainHandler->dds()->dts()->removeEquipmentTypeWhByKey(m_data.id);
return Core::FunctionReplyObject(m_data.id);
}
void ObjectEquipmentTypeWh::onPublishData()
{
WarehouseGuez::EquipmentTypeWh ddsData;
ddsData.id(m_data.id);
ddsData.configurationAbeLanguage(static_cast<WarehouseGuez::ConfigurationAbeLanguage_def::type>(m_data.canAbeSprache));
ddsData.configurationAgdusHV(static_cast<WarehouseGuez::ConfigurationAgdusHV_def::type>(m_data.agdusHelmWeste));
ddsData.configurationAudioResponse(m_data.canAbeSprAusg);
ddsData.configurationCedPyrotechnic(m_data.canWirkdarstPyro);
ddsData.configurationDisplayAdag(static_cast<WarehouseGuez::ConfigurationDisplayAdag_def::type>(m_data.anzeigeAdag));
ddsData.configurationDisplayAdagSubUnit(static_cast<WarehouseGuez::ConfigurationDisplayAdagSubUnit_def::type>(m_data.adagUntergruppe));
ddsData.configurationMhgrEnergieSave(m_data.canMhgrEnergie);
ddsData.configurationMhgrOperatingMode(static_cast<WarehouseGuez::ConfigurationMhgrSensor_def::type>(m_data.canMhgrBetrArt));
ddsData.configurationSsFirSan(m_data.canSsFirSan);
ddsData.configurationSsFirFunction(static_cast<WarehouseGuez::ConfigurationSpecialSensorFir_def::type>(m_data.canSsFirFunkt));
ddsData.configurationSsMineFitFunction(static_cast<WarehouseGuez::ConfigurationSpecialSensorMineFit_def::type>(m_data.canSsMvFunkt));
ddsData.configurationSsStandardFunction(static_cast<WarehouseGuez::ConfigurationSpecialSensorStd_def::type>(m_data.canSsStdFunkt));
ddsData.configurationStartupTime(m_data.canStartupZeit);
ddsData.equipGroup(m_data.ausstgGrp);
ddsData.maxEquipNo(m_data.ausstgNrMax);
ddsData.minEquipNo(m_data.ausstgNrMin);
ddsData.name(m_data.name.toStdString());
ddsData.posUpdate(static_cast<WarehouseGuez::ConfigurationPositionUpdate_def::type>(m_data.posUpdate));
ddsData.vbAgdusId(m_data.vbAgdus);
ddsData.vbAirSupport(m_data.vbEinsatzmittel);
ddsData.vbFireArea(m_data.vbSteilfeuer);
ddsData.vbMineIed(m_data.vbMinenIed);
ddsData.vbNc(m_data.vbAcWaffen);
ddsData.canDevices(m_data.canDevices);
INFO_LOG(m_logger) << "Publish WhgEquipmentTypeWh-data to dds (" << m_data.id << ") ...";
if (!m_mainHandler->dds()->dts()->publish(ddsData))
{
ERROR_LOG(m_logger) << "Error publishing WhgEquipmentTypeWh-data to dds";
}
}
} // Namespace WarehouseGuez
+37
View File
@@ -0,0 +1,37 @@
/**
* Exercise object
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "logger.h"
#include "main_handler.h"
#include <DDS/Core/function_reply_object.h>
namespace WarehouseGuez
{
class ObjectEquipmentTypeWh final
{
public:
explicit ObjectEquipmentTypeWh(MainHandler *mainHandler);
~ObjectEquipmentTypeWh();
Core::FunctionReplyObject createObject(const Database::EquipmentTypeWh &data, bool forceInsert = false);
Core::FunctionReplyObject updateObject(const Database::EquipmentTypeWh &data);
Core::FunctionReplyObject removeObject();
int getId() const { return m_data.id; }
Database::EquipmentTypeWh getData() const { return m_data; }
protected:
void onPublishData();
private:
MainHandler *m_mainHandler;
Database::EquipmentTypeWh m_data;
NGL::INGLLogger &m_logger;
};
}
+78
View File
@@ -0,0 +1,78 @@
/**
* Handler for the HMI language
* $Id$
* $HeadURL$
* $Author$
*/
#include "object_injury_model.h"
namespace WarehouseGuez
{
ObjectInjuryModel::ObjectInjuryModel(MainHandler *mainHandler)
: m_mainHandler(mainHandler)
, m_logger(getLogger("ObjectInjuryModel"))
{
}
Core::FunctionReplyObject ObjectInjuryModel::createObject(const Database::InjuryModelAgdusWh &data)
{
m_data = data;
if (m_data.id <= 0)
{
m_data.id = 0 - m_data.id;
if (!m_mainHandler->db()->insert(m_data))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting InjuryModel-data into database"));
}
DEBUG_LOG(m_logger) << "New InjuryModel: " << m_data.id;
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id);
}
Core::FunctionReplyObject ObjectInjuryModel::updateObject(const Database::InjuryModelAgdusWh &data)
{
if (!m_mainHandler->db()->update(data))
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating InjuryModel-data into database"));
m_data = data;
DEBUG_LOG(m_logger) << "Data changed for InjuryModelId: " << m_data.id;
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id);
}
Core::FunctionReplyObject ObjectInjuryModel::removeObject()
{
if (!m_mainHandler->db()->removeInjuryModelAgdusWh(m_data.id))
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "InjuryModelId with id %1 can not be removed")).arg(m_data.id);
m_mainHandler->dds()->dts()->removeInjuryModelAgdusWhByKey(m_data.id);
return Core::FunctionReplyObject(m_data.id);
}
void ObjectInjuryModel::onPublishData()
{
WarehouseGuez::InjuryModelAgdusWh ddsData;
ddsData.id(m_data.id);
ddsData.name(m_data.name.toStdString());
ddsData.description(m_data.beschreibung.toStdString());
ddsData.version(m_data.version.toStdString());
INFO_LOG(m_logger) << "Publish InjuryModelAgdusWh-data to dds (" << m_data.id << ") ...";
if (!m_mainHandler->dds()->dts()->publish(ddsData))
{
ERROR_LOG(m_logger) << "Error publishing WhgInjuryModel-data to dds";
}
}
} // Namespace WarehouseGuez
+37
View File
@@ -0,0 +1,37 @@
/**
* Exercise object
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "logger.h"
#include "main_handler.h"
#include <DDS/Core/function_reply_object.h>
namespace WarehouseGuez
{
class ObjectInjuryModel final
{
public:
explicit ObjectInjuryModel(MainHandler *mainHandler);
~ObjectInjuryModel() = default;
Core::FunctionReplyObject createObject(const Database::InjuryModelAgdusWh &data);
Core::FunctionReplyObject updateObject(const Database::InjuryModelAgdusWh &data);
Core::FunctionReplyObject removeObject();
int getId() const { return m_data.id; }
Database::InjuryModelAgdusWh getData() const { return m_data; }
protected:
void onPublishData();
private:
MainHandler *m_mainHandler;
Database::InjuryModelAgdusWh m_data;
NGL::INGLLogger &m_logger;
};
}
+42
View File
@@ -0,0 +1,42 @@
/**
* Settings for WarehouseGuez
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
namespace WarehouseGuez
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
} // namespace WarehouseGuez
+24
View File
@@ -0,0 +1,24 @@
/**
* Settings for WarehouseGuez
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace WarehouseGuez
{
namespace Settings
{
NGL::Settings *settings();
void setIniFile(const QString &ini);
}
} // namespace WarehouseGuez
+52
View File
@@ -0,0 +1,52 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-08-04
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef WHG_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define WHG_COMMON_EXPORT
# else
# if defined(MAKE_SVCWHGCOMMON_LIB)
# define WHG_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define WHG_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef WHG_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define WHG_CLIENT_EXPORT
# else
# if defined(MAKE_SVCWHGCLIENT_LIB)
# define WHG_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define WHG_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef WHG_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define WHG_SERVER_EXPORT
# else
# if defined(MAKE_SVCWHGSERVER_LIB)
# define WHG_SERVER_EXPORT Q_DECL_EXPORT
# else
# define WHG_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+348
View File
@@ -0,0 +1,348 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="WarehouseGuez" abbreviation="WHG" procNames="WarehouseGuez" exerciseDependency="Global" groups="Core">
<rcs>
<Id Id="$Id: ea_export_script.txt 41311 2018-04-23 09:43:45Z ehrlicher $"/>
<HeadURL HeadURL="$HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Common/CodeGen/ea_export_script.txt $"/>
<Author Author="$Author: ehrlicher $"/>
</rcs>
<tables>
<table name="ausstg_konfig">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="configuration" datatype="bytea"/>
<column name="serial_no_board" datatype="text" comment="Serial No of the Backplane (...2D=RegTNE, ...01=AgdusHw2)"/>
<column name="serial_no_sfm" datatype="text" comment="Serial No of the SFM (...2F)"/>
<column name="serial_no_ply_unit" datatype="integer" comment="Printed Serial number (xxxxx)"/>
<column name="equip_no" datatype="integer"/>
<column name="effmodel" datatype="bytea"/>
<column name="time_stamp" datatype="timestamp"/>
<column name="issi" datatype="integer"/>
<column name="equipmenttype_id" datatype="integer"/>
<constraint name="UQ_ausstg_konfig_serial_no_board" type="unique">
<column name="serial_no_board"/>
</constraint>
</table>
<table name="ausstg_protokoll">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="serial_no" datatype="text"/>
<column name="tsr_name" datatype="text"/>
<column name="data" datatype="text"/>
<column name="time_stamp" datatype="timestamp"/>
</table>
<table name="ausstg_typen">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
<column name="ausstg_grp" datatype="integer"/>
<column name="ausstg_nr_min" datatype="integer"/>
<column name="ausstg_nr_max" datatype="integer"/>
<column name="pos_update" datatype="integer"/>
<column name="anzeige_adag" datatype="integer"/>
<column name="adag_untergruppe" datatype="integer"/>
<column name="agdus_helm_weste" datatype="integer"/>
<column name="vb_agdus" datatype="integer"/>
<column name="vb_minen_ied" datatype="integer"/>
<column name="vb_steilfeuer" datatype="integer"/>
<column name="vb_einsatzmittel" datatype="integer"/>
<column name="vb_ac_waffen" datatype="integer"/>
<column name="can_abe_sprache" datatype="integer"/>
<column name="can_abe_spr_ausg" datatype="integer"/>
<column name="can_mhgr_betr_art" datatype="integer"/>
<column name="can_mhgr_energie" datatype="integer"/>
<column name="can_wirkdarst_pyro" datatype="integer"/>
<column name="can_ss_fir_san" datatype="boolean" default="false"/>
<column name="can_ss_fir_funkt" datatype="integer"/>
<column name="can_ss_mv_funkt" datatype="integer"/>
<column name="can_ss_std_funkt" datatype="integer"/>
<column name="can_startup_zeit" datatype="integer"/>
<column name="can_devices" datatype="integer"/>
<column name="agdus_hw2_helm" datatype="integer"/>
<column name="agdus_hw2_weste" datatype="integer"/>
<column name="agdus_hw2_schutzniveau" datatype="integer"/>
<constraint name="UQ_ausstg_typen_id" type="unique">
<column name="id"/>
</constraint>
</table>
<table name="can_device">
<column name="id" datatype="integer" isPrimaryKey="1"/>
<column name="name" datatype="text"/>
<column name="bitmask" datatype="integer"/>
<constraint name="UQ_can_device_bitmask" type="unique">
<column name="bitmask"/>
</constraint>
</table>
<table name="software">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
<column name="version" datatype="text"/>
<column name="description" datatype="text"/>
<column name="software_type_id" datatype="integer" isForeignKey="1"/>
<column name="filename" datatype="text"/>
<column name="data" datatype="bytea"/>
<column name="checksum" datatype="text"/>
<foreignKey name="FK_software_software_type">
<source table="software" column="software_type_id"/>
<destination table="software_type" column="id"/>
</foreignKey>
</table>
<table name="software_type">
<column name="id" datatype="integer" isPrimaryKey="1"/>
<column name="name" datatype="text"/>
<column name="filetype" datatype="text"/>
</table>
<table name="tln">
<column name="id" datatype="bigint" isPrimaryKey="1"/>
<column name="hierarchie" datatype="text"/>
<column name="typ_id" datatype="integer"/>
<column name="ausstg_typ_id" datatype="integer"/>
<column name="ausstg_nr" datatype="integer"/>
<column name="zuordnung" datatype="smallint"/>
<column name="y_nr" datatype="text"/>
<column name="info" datatype="text"/>
<column name="loeschkennung" datatype="smallint"/>
<column name="zeit" datatype="timestamp"/>
</table>
<table name="tln_zuordnung">
<column name="id" datatype="integer"/>
<column name="zeit" datatype="timestamp"/>
<column name="ausstg_nr" datatype="integer"/>
<column name="zuordnung" datatype="integer"/>
<column name="y_nr" datatype="text"/>
<column name="info" datatype="text"/>
<column name="ausstg_typ_id" datatype="integer"/>
<column name="zaehler" datatype="bigint" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="gesendet" datatype="boolean" default="false"/>
<column name="error_code" datatype="integer"/>
</table>
<table name="tne_sn_zuordnung" comment="Table to assign a Serial Number (printed, xxxxx, for Sticker) to a certain Serial Number of the SFM (...2F). The Serial Number of the Backplane (...01 =AgdusHw2, ...2D = RegTNE, etc.) is not part of this relation. The ISSI that shall be provided for the Player Unit identified by the serial_no_sfm is also part of this relation">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="serial_no_sfm" datatype="text" comment="Serial No of SFM (...2F)"/>
<column name="serial_no_ply_unit" datatype="integer" comment="Serial No of Player Unit (Sticker, nnnnn)"/>
<column name="playerunit_type" datatype="text"/>
<column name="issi" datatype="integer"/>
<column name="info" datatype="text"/>
</table>
<table name="typen">
<column name="id" datatype="integer" isPrimaryKey="1"/>
<column name="name" datatype="text"/>
<column name="ausstg_typ_id" datatype="integer" isOptional="1" isForeignKey="1"/>
<foreignKey name="FK_typen_ausstg_typen">
<source table="typen" column="ausstg_typ_id"/>
<destination table="ausstg_typen" column="id"/>
</foreignKey>
</table>
<table name="uebersetzungen">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="tabelle" datatype="text"/>
<column name="spalte" datatype="text"/>
<column name="fremd_id" datatype="integer"/>
<column name="sprache" datatype="text"/>
<column name="text" datatype="text"/>
</table>
<table name="uebungen">
<column name="id" datatype="integer" isPrimaryKey="1"/>
<column name="name" datatype="text"/>
<column name="beginn" datatype="timestamp"/>
<column name="akt_uebung" datatype="integer"/>
<column name="tln" datatype="text"/>
<column name="tln_zuordnung" datatype="text"/>
</table>
<table name="vb_agdus">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
<column name="version" datatype="text"/>
<column name="beschreibung" datatype="text"/>
<constraint name="UQ_vb_agdus_id" type="unique">
<column name="id"/>
</constraint>
</table>
<table name="version">
<column name="version" datatype="integer" isPrimaryKey="1"/>
<column name="date" datatype="text"/>
<column name="product" datatype="text"/>
<column name="change" datatype="text"/>
</table>
</tables>
<views/>
<dbServiceStructs>
<serviceStruct name="CanDevice" table="can_device"/>
<serviceStruct name="EquipmentConfiguration" table="ausstg_konfig"/>
<serviceStruct name="EquipmentProtocol" table="ausstg_protokoll"/>
<serviceStruct name="EquipmentTypeWh" table="ausstg_typen"/>
<serviceStruct name="Exercise" table="uebungen"/>
<serviceStruct name="InjuryModelAgdusWh" table="vb_agdus"/>
<serviceStruct name="Participant" table="tln"/>
<serviceStruct name="ParticipantAssignment" table="tln_zuordnung">
<notification name="notifyInsertParticipantAssignment" returns="void" notificationTypes="AfterInsert">
<parameter pos="1" name="id" type="qint64"/>
</notification>
</serviceStruct>
<serviceStruct name="SerialNumberMapping" table="tne_sn_zuordnung"/>
<serviceStruct name="Software" table="software"/>
<serviceStruct name="SoftwareType" table="software_type"/>
<serviceStruct name="Translations" table="uebersetzungen"/>
<serviceStruct name="Type" table="typen"/>
<serviceStruct name="Version" table="version"/>
<table name="can_device"/>
<table name="ausstg_konfig"/>
<table name="ausstg_protokoll"/>
<table name="ausstg_typen"/>
<table name="uebungen"/>
<table name="vb_agdus"/>
<table name="tln"/>
<table name="tln_zuordnung"/>
<table name="tne_sn_zuordnung"/>
<table name="software"/>
<table name="software_type"/>
<table name="uebersetzungen"/>
<table name="typen"/>
<table name="version"/>
</dbServiceStructs>
<topicTypes>
<topicType name="EquipmentTypeWh" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="0">
<column name="id" idlType="long" isKey="1"/>
<column name="name" idlType="string"/>
<column name="equipGroup" idlType="long"/>
<column name="minEquipNo" idlType="long"/>
<column name="maxEquipNo" idlType="long"/>
<column name="posUpdate" idlType="ConfigurationPositionUpdate"/>
<column name="configurationDisplayAdag" idlType="ConfigurationDisplayAdag"/>
<column name="configurationDisplayAdagSubUnit" idlType="ConfigurationDisplayAdagSubUnit"/>
<column name="configurationAgdusHV" idlType="ConfigurationAgdusHV"/>
<column name="vbAgdusId" idlType="long"/>
<column name="vbMineIed" idlType="long"/>
<column name="vbFireArea" idlType="long"/>
<column name="vbAirSupport" idlType="long"/>
<column name="vbNc" idlType="long"/>
<column name="configurationAbeLanguage" idlType="ConfigurationAbeLanguage"/>
<column name="configurationAudioResponse" idlType="boolean"/>
<column name="configurationMhgrOperatingMode" idlType="ConfigurationMhgrSensor"/>
<column name="configurationMhgrEnergieSave" idlType="boolean"/>
<column name="configurationCedPyrotechnic" idlType="boolean"/>
<column name="configurationSsFirSan" idlType="boolean"/>
<column name="configurationSsFirFunction" idlType="ConfigurationSpecialSensorFir"/>
<column name="configurationSsMineFitFunction" idlType="ConfigurationSpecialSensorMineFit"/>
<column name="configurationSsStandardFunction" idlType="ConfigurationSpecialSensorStd"/>
<column name="configurationStartupTime" idlType="long"/>
<column name="canDevices" idlType="long"/>
</topicType>
<topicType name="InjuryModelAgdusWh" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="0">
<column name="id" idlType="long" isKey="1"/>
<column name="name" idlType="string"/>
<column name="version" idlType="string"/>
<column name="description" idlType="string"/>
</topicType>
</topicTypes>
<functionTopics>
<functionTopic name="ModifyEquipmentTypeWh" requestTopicType="EquipmentTypeWh" replyTopicType="Core::FunctionReply" requestTopicName="ModifyEquipmentTypeWhRequest" replyTopicName="ModifyEquipmentTypeWhReply" routeInReplay="0"/>
<functionTopic name="ModifyInjuryModelAgdusWh" requestTopicType="InjuryModelAgdusWh" replyTopicType="Core::FunctionReply" requestTopicName="ModifyInjuryModelAgdusWhRequest" replyTopicName="ModifyInjuryModelAgdusWhReply" routeInReplay="0"/>
<functionTopic name="RemoveEquipmentTypeWh" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="RemoveEquipmentTypeWhRequest" replyTopicName="RemoveEquipmentTypeWhReply" routeInReplay="0"/>
<functionTopic name="RemoveInjuryModelAgdusWh" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="RemoveInjuryModelAgdusWhRequest" replyTopicName="RemoveInjuryModelAgdusWhReply" routeInReplay="0"/>
</functionTopics>
<enumerations>
<enumeration name="CanDevices">
<attribute key="IED_KONT_EINH" value="8"/>
<attribute key="IED_SENSOR" value="16"/>
<attribute key="DMF" value="32"/>
<attribute key="SRT" value="64"/>
<attribute key="WIRKDARST" value="128"/>
<attribute key="ABC_STROEM" value="256"/>
<attribute key="ABC_UEBERDR" value="512"/>
<attribute key="MHGR" value="1024"/>
<attribute key="SS_STD" value="2048"/>
<attribute key="SS_MV" value="4096"/>
<attribute key="SS_FIR" value="8192"/>
<attribute key="ABE" value="16384"/>
<attribute key="AGDUS" value="32768"/>
</enumeration>
<enumeration name="ConfigurationAbeLanguage">
<attribute key="AbeLanguageGerman" value="0"/>
<attribute key="AbeLanguageEnglish" value="1"/>
<attribute key="AbeLanguageFrench" value="2"/>
</enumeration>
<enumeration name="ConfigurationAgdusHV">
<attribute key="AgdusHWNoHelmetNoWest" value="1"/>
<attribute key="AgdusHWWithHelmetNoVest" value="2"/>
<attribute key="AgdusHWWithHelmetWithVest" value="3"/>
</enumeration>
<enumeration name="ConfigurationDisplayAdag">
<attribute key="DisplayAdagNoDisplay" value="0"/>
<attribute key="DisplayAdagAbe" value="1"/>
<attribute key="DisplayAdagAgdusPassiveAbe" value="3"/>
<attribute key="DisplayAdagAgdusHW" value="4"/>
<attribute key="DisplayAdagAgdusBt46" value="6"/>
</enumeration>
<enumeration name="ConfigurationDisplayAdagSubUnit">
<attribute key="DASNoDisplayAll" value="0"/>
<attribute key="DASAbeAll" value="1000"/>
<attribute key="DASAgdusPassiveAbeDefault" value="3000"/>
<attribute key="DASAgdusPassiveAbeUnarmouredWheeledVehicle" value="3002"/>
<attribute key="DASAgdusPassiveAbeCraneVehicle" value="3003"/>
<attribute key="DASAgdusPassiveAbeExcavatorVehicle" value="3004"/>
<attribute key="DASAgdusPassiveAbeNbcDetectionFuchs" value="3005"/>
<attribute key="DASAgdusPassiveAbeArmouredWheeledVehicle" value="3006"/>
<attribute key="DASAgdusPassiveAbeM113BasedVehicles" value="3007"/>
<attribute key="DASAgdusPAssiveAbeMiwSkorpion" value="3008"/>
<attribute key="DASAgdusPassiveAbePiPzDachs" value="3009"/>
<attribute key="DASAgdusPassiveAbeMiRPzKeiler" value="3010"/>
<attribute key="DASAgdusPassiveAbeBPzBueffel" value="3011"/>
<attribute key="DASAgdusPassiveAbePrLPzBiber" value="3012"/>
<attribute key="DASAgdusPassiveAbePZh2000" value="3013"/>
<attribute key="DASAgdusPassiveAbeMinethrowerMiv" value="3014"/>
<attribute key="DASAgdusPassiveAbeWieselAff" value="3015"/>
<attribute key="DASAgdusPassiveAbeFlarakwatrgozelot" value="3016"/>
<attribute key="DASAgdusHWAll" value="4000"/>
<attribute key="DASAgdusBt46Default" value="6000"/>
<attribute key="DASAgdusBt46KPzLeopard" value="6002"/>
<attribute key="DASAgdusBt46SPzMarder" value="6003"/>
<attribute key="DASAgdusBt46LLPzWieselMk" value="6004"/>
<attribute key="DASAgdusBt46LLPzWieselTow" value="6005"/>
<attribute key="DASAgdusBt46SpehwgFennek" value="6006"/>
<attribute key="DASAgdusBt46GtkBoxer" value="6007"/>
<attribute key="DASAgdusBt46GefKl_1_4" value="6008"/>
<attribute key="DASAgdusBt46GTFKl_1_4" value="6009"/>
<attribute key="DASAgdusBt46TPzFuchs" value="6010"/>
</enumeration>
<enumeration name="ConfigurationMhgrSensor">
<attribute key="MhgrSensorOperatingOnTrainingEquipment" value="0"/>
<attribute key="MhgrSensorOperatingOnOtherVehicle" value="2"/>
<attribute key="MhgrSensorOperatingOnSrVehicle" value="3"/>
</enumeration>
<enumeration name="ConfigurationPositionUpdate">
<attribute key="PositionUpdateVehicle" value="0"/>
<attribute key="PositionUpdatePerson" value="1"/>
<attribute key="PositionUpdateAirUnit" value="2"/>
</enumeration>
<enumeration name="ConfigurationSpecialSensorFir">
<attribute key="SpecialSensorFirNoConfiguration" value="0"/>
<attribute key="SpecialSensorFirFir" value="1"/>
<attribute key="SpecialSensorFirFirSpzMarder" value="2"/>
</enumeration>
<enumeration name="ConfigurationSpecialSensorMineFit">
<attribute key="SpecialSensorMineFitNoConfiguration" value="0"/>
<attribute key="SpecialSensorMineMv" value="6"/>
<attribute key="SpecialSensorMineWmv" value="8"/>
</enumeration>
<enumeration name="ConfigurationSpecialSensorStd">
<attribute key="SpecialSensorStdNoConfiguration" value="0"/>
<attribute key="SpecialSensorStdZabc" value="3"/>
<attribute key="SpecialSensorStdCsf" value="4"/>
<attribute key="SpecialSensorStdPzBr" value="5"/>
<attribute key="SpecialSensorStdMrf" value="7"/>
</enumeration>
</enumerations>
</service>
+43
View File
@@ -0,0 +1,43 @@
<!--msg: <input type="text" id="x" /> <button onclick="sendx()">send</button> -->
<button onclick="connect()">connect</button> <button onclick="socket.close()">close</button> <br />
<div id="log">...</div>
<script>
let data = `{"data": {"equipNo": 123, "box": 1}, "type": "getBiteData", "uuid": "123"}`;
let socket;
let seq = 0;
function connect()
{
console.log("connecting...");
socket = new WebSocket("ws://127.0.0.1:9094");
socket.addEventListener('open', () =>
{
console.log("connected");
send();
});
socket.addEventListener('message', (event) =>
{
console.log("recv", event.data);
document.getElementById("log").innerText = (seq++) + ": " + event.data;
});
socket.addEventListener('close', (event) =>
{
console.log("closed", JSON.stringify(event));
alert("connection was closed");
});
}
connect();
function send()
{
socket.send(data);
console.log("registering...");
}
</script>
+9
View File
@@ -0,0 +1,9 @@
How to use? (Schnelle Ich-Habe-Keine-Kostentraeger-Fuer-Gute-Doku Edition)
"Was kann das?" Die .ts-Datei faked einen Tab Server (Websocket Server), der periodisch - per Timer - Bite-Daten sendet. Die HTML Datei faked einen Client, der sich fuer Bite-Daten beim svcWarehouseGuez registriert.
"Wozu?" Um zu testen, ob der svcWarehouseGuez bei Verbindungs-Abbruechen abstuerzt ;)
- in 'Lts/Services/WarehouseGuez/WsBiteInterface/bite_data_manager.cpp': #if 0 => #if 1
- './svcWarehouseGuez'
- './ws-tab-test.ts' => Fehlermeldung? Header der .ts-Datei lesen!
- 'firefox ws-tab-test.html'
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env -S deno run -A --watch
// get deno here: https://github.com/denoland/deno/releases and extract to /usr/local/bin ;)
async function handle(conn: Deno.Conn)
{
const httpConn = Deno.serveHttp(conn);
for await (const requestEvent of httpConn)
{
await requestEvent.respondWith(handleReq(requestEvent.request));
}
}
function handleReq(req: Request): Response
{
const upgrade = req.headers.get("upgrade") || "";
if (upgrade.toLowerCase() != "websocket")
{
return new Response("request isn't trying to upgrade to websocket.");
}
const { socket, response } = Deno.upgradeWebSocket(req);
socket.onopen = () =>
{
console.log("socket opened");
let interval = setInterval(() =>
{
console.log("sending bite data..");
try
{
socket.send('{"type": "biteData", "data": {"equipNo": 123}}');
}
catch(e)
{
clearInterval(interval);
console.log("cleared");
}
}
, 1000);
}
socket.onmessage = (e) =>
{
console.log("socket message:", e.data);
socket.send(new Date().toString());
};
socket.onerror = (e) => console.log("socket errored:");//, e);
socket.onclose = () => console.log("socket closed");
return response;
}
const server = Deno.listen({ port: 8080 });
for await (const conn of server)
{
handle(conn);
}