Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+172
@@ -0,0 +1,172 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
INCLUDE(MacroRTIDDSGen)
|
||||
INCLUDE(MacroCodeGenIdl)
|
||||
|
||||
SET(xml_FILE mdm_service.xml)
|
||||
|
||||
#
|
||||
# --- Library svcMdmCommon --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_common
|
||||
mdm_export.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
# Generate mdm_enums.idl / mdm.idl
|
||||
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
|
||||
# Generate mdm_db_impl.cpp/.h, mdm_db.h
|
||||
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
|
||||
|
||||
# Generate *.cpp/*.hpp from idl
|
||||
RTIDDSGEN(SRCS_common mdm_enums.idl)
|
||||
RTIDDSGEN(SRCS_common mdm.idl)
|
||||
|
||||
# Generate mdm_dt[s,c]_types.h, mdm_ft[s,c]_types.h
|
||||
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
|
||||
# generate mdm_[d|f]tc.h
|
||||
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV WS HLA svcMdmCommon SHARED ${SRCS_common})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcMdmCommon
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(svcMdmCommon
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
ddscore
|
||||
NGLLogger
|
||||
ngldb
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcMdmCommon)
|
||||
|
||||
#
|
||||
# --- Library svcMdmClient --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_client
|
||||
mdm_export.h
|
||||
)
|
||||
# generate mdm_[d|f]tc_impl.[cpp|h]
|
||||
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV WS svcMdmClient SHARED ${SRCS_client})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcMdmClient
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(svcMdmClient
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
ddsconnector
|
||||
PUBLIC
|
||||
svcMdmCommon
|
||||
ddsftc
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcMdmClient)
|
||||
|
||||
#
|
||||
# --- Library svcMdmServer --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_server
|
||||
mdm_export.h
|
||||
)
|
||||
# generate mdm_[d|f]ts.h, mdm_[d|f]ts_impl.[cpp|h]
|
||||
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV svcMdmServer SHARED ${SRCS_server})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcMdmServer
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(svcMdmServer
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
ddsconnector
|
||||
ddsfts
|
||||
PUBLIC
|
||||
svcMdmCommon
|
||||
ngldb
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcMdmServer)
|
||||
|
||||
#
|
||||
# --- Topic Type Plugin --------------------------------------------------------------
|
||||
#
|
||||
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
|
||||
|
||||
#
|
||||
# --- Executable svcMeteoDataManagement (sMDM) -------------------------------------------------
|
||||
#
|
||||
SET(HDRS_exe
|
||||
main_handler.h
|
||||
settings.h
|
||||
dds_handler.h
|
||||
handler_infrastructure_data.h
|
||||
handler_meteo_data_units.h
|
||||
handler_meteo_data_unit.h
|
||||
handler_static_meteo_data.h
|
||||
tcpweatherstation.h
|
||||
tcpsocket.h
|
||||
tcpwind.h
|
||||
tcpclimate.h
|
||||
)
|
||||
|
||||
SET(SRCS_exe
|
||||
main.cpp
|
||||
main_handler.cpp
|
||||
settings.cpp
|
||||
dds_handler.cpp
|
||||
handler_infrastructure_data.cpp
|
||||
handler_meteo_data_units.cpp
|
||||
handler_meteo_data_unit.cpp
|
||||
handler_static_meteo_data.cpp
|
||||
tcpweatherstation.cpp
|
||||
tcpsocket.cpp
|
||||
tcpwind.cpp
|
||||
tcpclimate.cpp
|
||||
log4cxx_mdm.props
|
||||
${xml_FILE}
|
||||
)
|
||||
|
||||
# Generate mdm.sql, mdm.xml
|
||||
CODEGEN_SQL(SRCS_exe ${xml_FILE})
|
||||
|
||||
NGL_ADD_SVC_ICON(SRCS_exe)
|
||||
NGL_ADD_EXECUTABLE(AAR SV svcMeteoDataManagement ${SRCS_exe} ${HDRS_exe})
|
||||
NGL_TARGET_LINK_LIBRARIES(svcMeteoDataManagement
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
ddsconnector
|
||||
svcMdmCommon
|
||||
svcMdmServer
|
||||
svcCoreClient
|
||||
svcIsmClient
|
||||
nglsettings
|
||||
ProjectConfig
|
||||
LtsCommandLineParser
|
||||
NGLLogger
|
||||
nglcoreapplication
|
||||
ngltools
|
||||
|
||||
svcGnaServer
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcMeteoDataManagement)
|
||||
NGL_INSTALL(AAR SV FILES log4cxx_mdm.props DESTINATION bin)
|
||||
NGL_ADD_TARGET_LINK(svcMeteoDataManagement sMDM)
|
||||
|
||||
# Uncomment if necessary
|
||||
#ADD_SUBDIRECTORY(UnitTests)
|
||||
#ADD_SUBDIRECTORY(ModuleTests)
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Dds Handler for MDM
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-21
|
||||
*/
|
||||
|
||||
#include "dds_handler.h"
|
||||
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
DdsHandler::DdsHandler(int domainId)
|
||||
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::AllExercises))
|
||||
, m_logger(getLogger("DdsHandler"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DdsHandler::~DdsHandler()
|
||||
{
|
||||
m_ddsFts = nullptr;
|
||||
m_ddsDts = nullptr;
|
||||
m_pacemaker = nullptr;
|
||||
m_dtcCore = nullptr;
|
||||
m_ddsConnector = nullptr;
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool DdsHandler::init(const QStringList &qosFileList)
|
||||
{
|
||||
INFO_LOG(m_logger) << "--- Start MeteoDataManagement DDSHandler.";
|
||||
|
||||
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);
|
||||
|
||||
// DTC Core (to get partitionTime)
|
||||
m_dtcCore = Core::Interface::Dtc::create(m_ddsConnector);
|
||||
m_dtcCore->enablePartitionTime();
|
||||
|
||||
// DTS
|
||||
m_ddsDts = MeteoDataManagement::Interface::Dts::create(m_ddsConnector);
|
||||
bool bRet = m_ddsDts->enableAll();
|
||||
INFO_LOG(m_logger) << "Dts initialised";
|
||||
|
||||
// FTS
|
||||
m_ddsFts = MeteoDataManagement::Interface::Fts::create(m_ddsConnector);
|
||||
bRet &= m_ddsFts->enableAll();
|
||||
INFO_LOG(m_logger) << "Fts initialised";
|
||||
|
||||
|
||||
return bRet;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
qint64 DdsHandler::currentPartitionTime() const
|
||||
{
|
||||
return m_dtcCore->partitionTime().timeStamp();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // Namespace MeteoDataManagement
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Dds Handler for MDM
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-06-06
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <MeteoDataManagement/mdm_dts.h>
|
||||
#include <MeteoDataManagement/mdm_fts.h>
|
||||
|
||||
#include <DDS/Core/core_dtc.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class Pacemaker;
|
||||
}
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
class DdsHandler
|
||||
{
|
||||
public:
|
||||
explicit DdsHandler(int domainId);
|
||||
~DdsHandler();
|
||||
|
||||
bool init(const QStringList &qosFileList = QStringList());
|
||||
|
||||
std::shared_ptr<DDSConnector::DdsConnector> dds() const { return m_ddsConnector; }
|
||||
std::shared_ptr<Core::Pacemaker> pacemaker() const { return m_pacemaker; }
|
||||
std::shared_ptr<MeteoDataManagement::Interface::Dts> dts() const { return m_ddsDts; }
|
||||
std::shared_ptr<MeteoDataManagement::Interface::Fts> fts() const { return m_ddsFts; }
|
||||
|
||||
qint64 currentPartitionTime() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
std::shared_ptr<Core::Interface::Dtc> m_dtcCore;
|
||||
std::shared_ptr<Core::Pacemaker> m_pacemaker;
|
||||
std::shared_ptr<MeteoDataManagement::Interface::Dts> m_ddsDts;
|
||||
std::shared_ptr<MeteoDataManagement::Interface::Fts> m_ddsFts;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Handler for infrastructure data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author:
|
||||
* Created by hjl, SLSE, 2016-09-21
|
||||
*/
|
||||
|
||||
#include "handler_infrastructure_data.h"
|
||||
|
||||
#include <DDS/DTC/generic_dtc.h>
|
||||
#include <DDS/DTC/generic_dtc_impl.h>
|
||||
#include <DDS/Generic/generic_data_reader.h>
|
||||
|
||||
using namespace MeteoDataManagement;
|
||||
|
||||
HandlerInfrastructureData::HandlerInfrastructureData(const std::shared_ptr<DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<HandlerMeteoDataUnits> &handlerMeteoDataUnits,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerMeteoDataUnits(handlerMeteoDataUnits)
|
||||
, m_logger(getLogger("HandlerInfrastructureData"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerInfrastructureData::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "start init() DTC InfrastructureManagement ";
|
||||
|
||||
// DTC InfrastructureManagement
|
||||
m_dtc = InfrastructureManagement::Interface::Dtc::create(m_ddsHandler->dds());
|
||||
if (m_dtc == nullptr)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not create DTC InfrastructureManagement";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_dtc->enableMountingPointAsset() ||
|
||||
!m_dtc->enableMainStructureElement())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "init() DTC InfrastructureManagement failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// InstrumentationAsset mit ContentFilter
|
||||
const dds::topic::Filter filter("mountingPointTypeId = 'MeteoDataUnit'");
|
||||
m_dtcInstrumentationAssetCF.reset(m_ddsHandler->dds()->createDTC<DTC::InstrumentationAssetCFImpl>(filter));
|
||||
if (!m_dtcInstrumentationAssetCF)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "init() DTC InfrastructureManagement failed";
|
||||
return false;
|
||||
}
|
||||
m_dtcInstrumentationAssetCF->setSubscriberCallback([this](const InfrastructureManagement::InstrumentationAsset &data, DataModification modType)
|
||||
{
|
||||
onAssetChanged(data, modType);
|
||||
});
|
||||
using DATA = InfrastructureManagement::InstrumentationAsset;
|
||||
using LOANED_DATA = rti::sub::LoanedSample<DATA>;
|
||||
for (const LOANED_DATA &sample : m_dtcInstrumentationAssetCF->readAlive())
|
||||
onAssetChanged(sample.data(), DataModification::eAdded);
|
||||
}
|
||||
|
||||
// Subsribe for MountingPointChanged (um ueber StructureElementId die Position der meteo data units zu ermitteln)
|
||||
connect(m_dtc.get(), &InfrastructureManagement::Interface::Dtc::mountingPointAssetChanged,
|
||||
this, &HandlerInfrastructureData::onMountingPointAssetChanged);
|
||||
// Subsribe for MainStructureElementChanged (Postion der Gebäude)
|
||||
connect(m_dtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &HandlerInfrastructureData::onMainStructureElementChanged);
|
||||
|
||||
m_dtc->mountingPointAssets([this](const InfrastructureManagement::MountingPointAsset &mpa) { onMountingPointAssetChanged(mpa); });
|
||||
m_dtc->mainStructureElements([this](const InfrastructureManagement::MainStructureElement &mse) { onMainStructureElementChanged(mse); });
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerInfrastructureData::onAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType)
|
||||
{
|
||||
// nur die MountingPointType::MeteoDataUnit bearbeiten...
|
||||
if (data.mountingPointTypeId() != InfrastructureManagement::MountingPointType::MeteoDataUnit)
|
||||
return;
|
||||
|
||||
INFO_LOG(m_logger) << "onAssetChanged()"
|
||||
<< " assetId: " << data.id()
|
||||
<< " mountingPointTypeId: " << data.mountingPointTypeId()
|
||||
<< " name: " << data.name();
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
m_handlerMeteoDataUnits->addMeteoDataUnit(data);
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
m_handlerMeteoDataUnits->removeMeteoDataUnit(data);
|
||||
break;
|
||||
}
|
||||
} // end of onAssetChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerInfrastructureData::onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, DataModification modType)
|
||||
{
|
||||
// zugehoerige StructureElementId ablegen
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
m_mountingPointAssetsMap.insert(data.assetId(), data.structureElementId());
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
m_mountingPointAssetsMap.remove(data.assetId());
|
||||
break;
|
||||
}
|
||||
} // end of onMountingPointAssetChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerInfrastructureData::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
m_mainStructureElements.insert(data.id(), data);
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
m_mainStructureElements.remove(data.id());
|
||||
break;
|
||||
}
|
||||
} // end of onMountingPointAssetChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Core::GeoPosition HandlerInfrastructureData::getStructureElementPosition(int assetId) const
|
||||
{
|
||||
const int seId = m_mountingPointAssetsMap.value(assetId);
|
||||
if (seId <= 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find mountingPointAsset for asset id " << assetId;
|
||||
return Core::GeoPosition();
|
||||
}
|
||||
// Go through all MainStructureElements and search structureElementId
|
||||
for (const InfrastructureManagement::MainStructureElement &mse : m_mainStructureElements)
|
||||
{
|
||||
for (const InfrastructureManagement::StructureElement &se : mse.elements())
|
||||
{
|
||||
if (se.id() == seId)
|
||||
return mse.geoPosition();
|
||||
}
|
||||
}
|
||||
return Core::GeoPosition();
|
||||
} // end of getStructureElementPosition()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Handler for infrastructure data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-21
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include "handler_meteo_data_units.h"
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <InfrastructureManagement/ism_dtc_types.h>
|
||||
#include <DDS/DTC/generic_dtc_impl.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
class HandlerInfrastructureData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerInfrastructureData(const std::shared_ptr<DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<HandlerMeteoDataUnits> &handlerMeteoDataUnits,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from infrastructure management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
/**
|
||||
* Returns the Position of the StructureElement for the given assetId (if available).
|
||||
*/
|
||||
Core::GeoPosition getStructureElementPosition(int assetId) const;
|
||||
|
||||
/**
|
||||
* Returns the shared pointer to ISM DTC Interface.
|
||||
*/
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> dtc() const
|
||||
{
|
||||
return m_dtc;
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle the signals from 'InfrastructureManagement'
|
||||
*/
|
||||
void onAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType = DataModification::eAdded);
|
||||
void onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, DataModification modType = DataModification::eAdded);
|
||||
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType = DataModification::eAdded);
|
||||
|
||||
private: // attributes
|
||||
std::shared_ptr<DdsHandler> m_ddsHandler; ///< Pointer to MDM DDS handler
|
||||
std::shared_ptr<HandlerMeteoDataUnits> m_handlerMeteoDataUnits; ///< Pointer to meteo data units handler
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_dtc; ///< Pointer to DTC InfrastructureManagement interface object
|
||||
std::unique_ptr<DTC::InstrumentationAssetCF> m_dtcInstrumentationAssetCF;
|
||||
|
||||
|
||||
QHash<int, int> m_mountingPointAssetsMap; ///< Hold all available structure element ids for meteo data units (key == assetId)
|
||||
QHash<int, InfrastructureManagement::MainStructureElement> m_mainStructureElements;
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Handler for one meteo data unit
|
||||
* Manages the connection to a MDU and sends data via DDS as soon as they have been changed
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-27
|
||||
*/
|
||||
|
||||
#include "handler_meteo_data_unit.h"
|
||||
#include "handler_meteo_data_units.h"
|
||||
#include "handler_infrastructure_data.h"
|
||||
#include "tcpweatherstation.h"
|
||||
#include "main_handler.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
using namespace MeteoDataManagement;
|
||||
|
||||
HandlerMeteoDataUnit::HandlerMeteoDataUnit(MainHandler *mainHandler,
|
||||
const InfrastructureManagement::InstrumentationAsset &asset,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_asset(asset)
|
||||
, m_tcpWS(nullptr)
|
||||
, m_logger(getLogger("HandlerMeteoDataUnit"))
|
||||
{
|
||||
init();
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerMeteoDataUnit::~HandlerMeteoDataUnit()
|
||||
{
|
||||
delete m_tcpWS;
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerMeteoDataUnit::init()
|
||||
{
|
||||
delete m_tcpWS;
|
||||
QJsonParseError jError;
|
||||
QJsonDocument doc(QJsonDocument::fromJson(m_asset.properties().c_str(), &jError));
|
||||
if (jError.error != QJsonParseError::NoError ||
|
||||
!doc.isObject())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Can not initialize meteo data unit - properties are not parsable: "
|
||||
<< jError.errorString() << " - '" << m_asset.properties() << "'";
|
||||
return false;
|
||||
}
|
||||
QJsonObject obj(doc.object());
|
||||
quint16 climatePort = obj[QStringLiteral("climatePort")].toInt();
|
||||
quint16 windPort = obj[QStringLiteral("windPort")].toInt();
|
||||
if (climatePort == 0 || windPort == 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Can not parse climate and/or wind port from properties: '" <<
|
||||
m_asset.properties() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_tcpWS = new TcpWeatherStation(m_asset.id(),
|
||||
QString::fromStdString(m_asset.hostname()),
|
||||
climatePort,
|
||||
windPort);
|
||||
|
||||
// init local MeteoData Values for compare
|
||||
m_newMeteoData.id(m_asset.id());
|
||||
m_newMeteoData.weatherStationId(m_asset.id());
|
||||
m_newMeteoData.note(m_asset.name());
|
||||
m_newMeteoData.isStaticMeteoData(false);
|
||||
|
||||
// Position der MDU eintragen (GeoPosition2D)
|
||||
if (m_mainHandler->ism())
|
||||
{
|
||||
const Core::GeoPosition geoPos = m_mainHandler->ism()->getStructureElementPosition(m_asset.id());
|
||||
//GeoPos->GeoPos2D
|
||||
m_newMeteoData.pos(Core::GeoPosition2D(geoPos.lon(), geoPos.lat()));
|
||||
}
|
||||
|
||||
|
||||
m_newMeteoData.pressure(800.0);
|
||||
m_newMeteoData.humidity(0.0);
|
||||
m_newMeteoData.temperature(0.0);
|
||||
m_newMeteoData.windSpeed(0.0);
|
||||
m_newMeteoData.windDirection(0.0);
|
||||
|
||||
m_lastMeteoData = m_newMeteoData;
|
||||
|
||||
connect(m_tcpWS, &TcpWeatherStation::sigWeatherDataChanged,
|
||||
this, &HandlerMeteoDataUnit::onMeteoDataChanged);
|
||||
|
||||
return true;
|
||||
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerMeteoDataUnit::onMeteoDataChanged(int id,
|
||||
float pressure, float temperature, float humidity,
|
||||
float direction, float speed, bool climateOk, bool windOk)
|
||||
{
|
||||
m_newMeteoData.id(id);
|
||||
m_newMeteoData.pressure(pressure); // in hPa
|
||||
m_newMeteoData.temperature(temperature); // in Grad Celsius
|
||||
m_newMeteoData.humidity(humidity); // % rel. Feuchte
|
||||
m_newMeteoData.windDirection(direction); // Grad, Nordbezogen mathem. negativ
|
||||
m_newMeteoData.windSpeed(speed); // in m/s
|
||||
m_newMeteoData.climateOk(climateOk);
|
||||
m_newMeteoData.windOk(windOk);
|
||||
|
||||
// Position der MDU eintragen (falls sie noch nicht beim init() ermittelt werden konnte)
|
||||
if (m_lastMeteoData.pos() == Core::GeoPosition2D())
|
||||
{
|
||||
if (m_mainHandler->ism())
|
||||
{
|
||||
const Core::GeoPosition geoPos = m_mainHandler->ism()->getStructureElementPosition(m_asset.id());
|
||||
m_newMeteoData.pos(Core::GeoPosition2D(geoPos.lon(), geoPos.lat()));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_lastMeteoData == m_newMeteoData)
|
||||
return;
|
||||
|
||||
// publish newMeteoData
|
||||
onPublishData();
|
||||
|
||||
// safe for next compare
|
||||
m_lastMeteoData = m_newMeteoData;
|
||||
|
||||
} // end of onMeteoDataChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerMeteoDataUnit::onPublishData()
|
||||
{
|
||||
MeteoDataManagement::MeteoData ddsData;
|
||||
|
||||
ddsData = m_newMeteoData;
|
||||
ddsData.timeStamp(m_mainHandler->dds()->currentPartitionTime());
|
||||
|
||||
INFO_LOG(m_logger) << "Publish dynamic MeteoData to dds: " << ddsData;
|
||||
|
||||
if (!m_mainHandler->dds()->dts()->publish(ddsData))
|
||||
ERROR_LOG(m_logger) << "Error publishing MdmMeteoData to dds";
|
||||
} // end of onPublishData()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Handler for one meteo data unit
|
||||
* Manages the connection to a MDU and sends data via DDS as soon as they have been changed
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-27
|
||||
*/
|
||||
|
||||
#include "InfrastructureManagement/ism_dtc.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <MeteoDataManagement/mdm.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
class MainHandler;
|
||||
class TcpWeatherStation;
|
||||
class HandlerMeteoDataUnits;
|
||||
|
||||
class HandlerMeteoDataUnit : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerMeteoDataUnit(MainHandler *mainHandler,
|
||||
const InfrastructureManagement::InstrumentationAsset &asset,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerMeteoDataUnit();
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Signaled from weatherstartion class if data were changed
|
||||
* @param[in] id weatherstation id (== assetId for meteoDataUnit)
|
||||
* @param[in] pressure pressure in hPa
|
||||
* @param[in] temperature temperature in °C
|
||||
* @param[in] humidity humidity in % relative humidity
|
||||
* @param[in] direction wind FROM direction in degree (north=0°, east=90°, south= 180°, west=270°)
|
||||
* @param[in] speed speed in m/s
|
||||
*/
|
||||
void onMeteoDataChanged(int id,
|
||||
float pressure, float temperature, float humidity,
|
||||
float direction, float speed, bool climateOk, bool windOk);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onPublishData();
|
||||
|
||||
|
||||
private:
|
||||
MainHandler *m_mainHandler; ///< Pointer to MDM DDS handler
|
||||
InfrastructureManagement::InstrumentationAsset m_asset; ///< meteo unit data asset
|
||||
|
||||
TcpWeatherStation *m_tcpWS; ///< Pointer to tcp based meteo data unit
|
||||
MeteoDataManagement::MeteoData m_lastMeteoData; ///< last received meteo data
|
||||
MeteoDataManagement::MeteoData m_newMeteoData; ///< new received meteo data
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Handler for all meteo data units
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-27
|
||||
*/
|
||||
|
||||
|
||||
#include "handler_meteo_data_units.h"
|
||||
#include "handler_meteo_data_unit.h"
|
||||
#include "handler_infrastructure_data.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
HandlerMeteoDataUnits::HandlerMeteoDataUnits(MainHandler *mainHandler)
|
||||
: m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerMeteoDataUnits"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerMeteoDataUnits::~HandlerMeteoDataUnits()
|
||||
{
|
||||
qDeleteAll(m_handlerMeteoDataUnitsMap);
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerMeteoDataUnits::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerMeteoDataUnits::init().... Initialisation of MDU's will be started from ISM directly. ";
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerMeteoDataUnits::addMeteoDataUnit(const InfrastructureManagement::InstrumentationAsset &asset)
|
||||
{
|
||||
INFO_LOG(m_logger) << "addMeteoDataUnit: " << asset;
|
||||
removeMeteoDataUnit(asset); // just to be sure
|
||||
|
||||
HandlerMeteoDataUnit *hMDU = new HandlerMeteoDataUnit(m_mainHandler, asset);
|
||||
m_handlerMeteoDataUnitsMap.insert(asset.id(), hMDU);
|
||||
|
||||
return false;
|
||||
} // end of addMeteoDataUnit()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerMeteoDataUnits::removeMeteoDataUnit(const InfrastructureManagement::InstrumentationAsset &asset)
|
||||
{
|
||||
INFO_LOG(m_logger) << "removeMeteoDataUnit: " << asset;
|
||||
auto it = m_handlerMeteoDataUnitsMap.find(asset.id());
|
||||
if (it == m_handlerMeteoDataUnitsMap.end())
|
||||
return false;
|
||||
|
||||
delete it.value();
|
||||
|
||||
m_handlerMeteoDataUnitsMap.erase(it);
|
||||
|
||||
return true;
|
||||
} // end of removeMeteoDataUnit()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // Namespace MeteoDataManagement
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Handler for all meteo data units
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-27
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
#include "handler_meteo_data_unit.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
class HandlerMeteoDataUnits
|
||||
{
|
||||
public:
|
||||
explicit HandlerMeteoDataUnits(MainHandler *mainHandler);
|
||||
|
||||
~HandlerMeteoDataUnits();
|
||||
|
||||
bool init();
|
||||
|
||||
bool addMeteoDataUnit(const InfrastructureManagement::InstrumentationAsset &asset);
|
||||
bool removeMeteoDataUnit(const InfrastructureManagement::InstrumentationAsset &asset);
|
||||
|
||||
private:
|
||||
QMap <int, HandlerMeteoDataUnit *> m_handlerMeteoDataUnitsMap; ///< Hold all meteo data unit handler
|
||||
MainHandler *m_mainHandler; ///< Pointer to DDS handler
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Handler for static meteo data request
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-10-12
|
||||
*/
|
||||
|
||||
#include "handler_static_meteo_data.h"
|
||||
|
||||
using namespace MeteoDataManagement;
|
||||
|
||||
HandlerStaticMeteoData::HandlerStaticMeteoData(const std::shared_ptr<DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<DatabaseInterface> &db)
|
||||
: StaticMeteoDataModifyRequestHandler(ddsHandler->fts())
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_db(db)
|
||||
, m_logger(getLogger("HandlerStaticMeteoData"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerStaticMeteoData::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Start HandlerStaticMeteoData.";
|
||||
|
||||
// read data from db-table 'mdm_static_meteo_data'
|
||||
QVector<Database::MdmStaticMeteoData> dataVec;
|
||||
if (!m_db->select(dataVec))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database 'mdm_static_meteo_data'!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dataVec.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "DB table 'mdm_static_meteo_data' is empty! Try to create default entry.";
|
||||
|
||||
if (!insertDefaultStaticMeteoDataEntry())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Insert DB table 'mdm_static_meteo_data' failed! No static meteo data may be handled!";
|
||||
return false; // Damit werden alle moeglicherweise erreichbaren MDU's nicht bearbeitet,
|
||||
// da die Initialisierung des Service im 'SCM' mit Error beendet wird.
|
||||
}
|
||||
|
||||
m_db->select(dataVec);
|
||||
m_dbStaticMeteoData = dataVec.at(0);
|
||||
|
||||
m_dbStaticMeteoData.timeStamp = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
INFO_LOG(m_logger) << "Insert into DB table 'mdm_static_meteo_data' successfully. id: "
|
||||
<< m_dbStaticMeteoData.id;
|
||||
|
||||
onPublishData();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dataVec.size() > 1)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Invalid number of table entries for 'mdm_static_meteo_data' size:"
|
||||
<< dataVec.size()
|
||||
<< " The first entry will be used only!";
|
||||
}
|
||||
m_dbStaticMeteoData = dataVec.at(0);
|
||||
onPublishData();
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerStaticMeteoData::onStaticMeteoDataModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const StaticMeteoDataModifyRequest &request)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onStaticMeteoDataModifyRequest: " << request;
|
||||
|
||||
Core::FunctionReplyObject rep(request.id());
|
||||
|
||||
if (!updateStaticMeteoDatainDB(request))
|
||||
{
|
||||
rep = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Update database failed"));
|
||||
m_ddsHandler->fts()->staticMeteoDataModifyReply(cookie, rep);
|
||||
return;
|
||||
}
|
||||
|
||||
// publish static meteo data
|
||||
onPublishData();
|
||||
|
||||
// set reply object on non error and return to acknowledge the FTC-Request
|
||||
m_ddsHandler->fts()->staticMeteoDataModifyReply(cookie, rep);
|
||||
} // end of onStaticMeteoDataModifyRequest()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerStaticMeteoData::updateStaticMeteoDatainDB(const StaticMeteoDataModifyRequest &request)
|
||||
{
|
||||
if (request.id() != m_dbStaticMeteoData.id)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Invalid id for db-table 'mdm_static_meteo_data'"
|
||||
<< m_dbStaticMeteoData.id
|
||||
<< " correct id: " << m_dbStaticMeteoData.id;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_db->update(ddsInputDataToDbData(request)))
|
||||
return false;
|
||||
|
||||
// safe new data (used in onPublishData()
|
||||
m_dbStaticMeteoData = ddsInputDataToDbData(request);
|
||||
return true;
|
||||
} // end of updateStaticMeteoDatainDB()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerStaticMeteoData::onPublishData()
|
||||
{
|
||||
// convert db-Data to dds output data
|
||||
MeteoDataManagement::MeteoData ddsData = toDdsData(m_dbStaticMeteoData);
|
||||
|
||||
const auto note(tr_lts("dds", "static data"));
|
||||
|
||||
ddsData.isStaticMeteoData(true);
|
||||
ddsData.note(note);
|
||||
ddsData.weatherStationId(ddsData.id()); // MDUid == dbId
|
||||
|
||||
INFO_LOG(m_logger) << "Publish static MeteoData to dds: " << ddsData;
|
||||
|
||||
if (!m_ddsHandler->dts()->publish(ddsData))
|
||||
ERROR_LOG(m_logger) << "Error publishing static MdmMeteoData to dds";
|
||||
|
||||
} // end of onPublishData()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerStaticMeteoData::insertDefaultStaticMeteoDataEntry()
|
||||
{
|
||||
Database::MdmStaticMeteoData dbData;
|
||||
|
||||
// Info: currentPartitionTime() liefert beim Start hier noch 0!
|
||||
dbData.timeStamp = m_ddsHandler->currentPartitionTime();
|
||||
dbData.windDirection = 90.0;
|
||||
dbData.windSpeed = 0.0;
|
||||
dbData.temperature = 18.5;
|
||||
dbData.pressure = 1010.3;
|
||||
dbData.humidity = 45.8;
|
||||
|
||||
if (!m_db->insert(dbData))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "insertDefaultStaticMeteoDataEntry for db-table 'mdm_static_meteo_data' failed!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // end of insertDefaultStaticMeteoDataEntry()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Database::MdmStaticMeteoData HandlerStaticMeteoData::ddsInputDataToDbData(const StaticMeteoDataModifyRequest &ddsData)
|
||||
{
|
||||
Database::MdmStaticMeteoData dbData;
|
||||
|
||||
dbData.id = ddsData.id();
|
||||
dbData.timeStamp = ddsData.timeStamp();
|
||||
dbData.windDirection = ddsData.windDirection();
|
||||
dbData.windSpeed = ddsData.windSpeed();
|
||||
dbData.temperature = ddsData.temperature();
|
||||
dbData.pressure = ddsData.pressure();
|
||||
dbData.humidity = ddsData.humidity();
|
||||
|
||||
return dbData;
|
||||
} // end of toDbData()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MeteoData HandlerStaticMeteoData::toDdsData(const Database::MdmStaticMeteoData &dbData)
|
||||
{
|
||||
MeteoData ddsData;
|
||||
|
||||
ddsData.id(dbData.id);
|
||||
ddsData.timeStamp(dbData.timeStamp);
|
||||
ddsData.windDirection(dbData.windDirection);
|
||||
ddsData.windSpeed(dbData.windSpeed);
|
||||
ddsData.temperature(dbData.temperature);
|
||||
ddsData.pressure(dbData.pressure);
|
||||
ddsData.humidity(dbData.humidity);
|
||||
|
||||
return ddsData;
|
||||
} // end of toDdsData()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Handler for static meteo data request
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-10-12
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include <mdm_fts.h>
|
||||
#include <MeteoDataManagement/mdm_db.h>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
class HandlerStaticMeteoData final : protected Interface::Fts::StaticMeteoDataModifyRequestHandler
|
||||
{
|
||||
public:
|
||||
explicit HandlerStaticMeteoData(const std::shared_ptr<DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<DatabaseInterface> &db);
|
||||
|
||||
bool init();
|
||||
|
||||
private: // methods
|
||||
void onStaticMeteoDataModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const StaticMeteoDataModifyRequest &request) override final;
|
||||
|
||||
bool updateStaticMeteoDatainDB(const StaticMeteoDataModifyRequest &request);
|
||||
|
||||
void onPublishData();
|
||||
|
||||
bool insertDefaultStaticMeteoDataEntry();
|
||||
|
||||
|
||||
// convert methodes
|
||||
static MeteoData toDdsData(const Database::MdmStaticMeteoData &dbData); // db -> dds
|
||||
// for modify request
|
||||
static Database::MdmStaticMeteoData ddsInputDataToDbData(const StaticMeteoDataModifyRequest &ddsData); // dds -> db
|
||||
|
||||
|
||||
private: // attributes
|
||||
std::shared_ptr<DdsHandler> m_ddsHandler;
|
||||
std::shared_ptr<DatabaseInterface> m_db;
|
||||
Database::MdmStaticMeteoData m_dbStaticMeteoData;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=WARN, file
|
||||
|
||||
#log4j.logger.DDS=DEBUG
|
||||
|
||||
# Service: MeteoDataManagement
|
||||
###########################################################
|
||||
|
||||
#MDM
|
||||
#log4j.logger.MDM=INFO
|
||||
#log4j.logger.MDM.main=INFO
|
||||
#log4j.logger.MDM.MainHandler=INFO
|
||||
#log4j.logger.MDM.DdsHandler=INFO
|
||||
#log4j.logger.MDM.DbHandler=INFO
|
||||
#log4j.logger.MDM.HandlerInfrastructureData=INFO
|
||||
#log4j.logger.MDM.HandlerMeteoDataUnits=INFO
|
||||
#log4j.logger.MDM.HandlerMeteoDataUnit=INFO
|
||||
#log4j.logger.MDM.HandlerStaticMeteoData=INFO
|
||||
#log4j.logger.MDM.TcpWeatherStation=INFO
|
||||
#log4j.logger.MDM.TcpClimate=WARN
|
||||
#log4j.logger.MDM.TcpWind=WARN
|
||||
|
||||
#GNA
|
||||
#log4j.logger.GNA=INFO
|
||||
#log4j.logger.GNA.Initialization=INFO
|
||||
#log4j.logger.GNA.DdsHandler=INFO
|
||||
#log4j.logger.GNA.Participant2Dds=INFO
|
||||
#log4j.logger.GNA.ParticipantPositionPublisher=INFO
|
||||
#log4j.logger.GNA.HandlerNasatAircraft=INFO
|
||||
#log4j.logger.GNA.HandlerNasatAircraftParticipant=INFO
|
||||
#log4j.logger.GNA.NasatAircraftParticipantEx=INFO
|
||||
#log4j.logger.GNA.HandlerNasatImpact=INFO
|
||||
#log4j.logger.GNA.HandlerNasatNineLiner=INFO
|
||||
#log4j.logger.GNA.WebSocketHandler=INFO
|
||||
#log4j.logger.GNA.TcpSocketHandler=INFO
|
||||
|
||||
|
||||
# File
|
||||
###########################################################
|
||||
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
|
||||
log4j.appender.file.layout.ConversionPattern=%d %-5p [%t] %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:
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "MDM.";
|
||||
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 MeteoDataManagement
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for MeteoDataManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include "mdm_export.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
using LOGGER_T = NGL::INGLLogger&;
|
||||
|
||||
MDM_COMMON_EXPORT LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace MeteoDataManagement
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Main for Meteo Data Management
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-06-06
|
||||
*/
|
||||
|
||||
#include <nglapplication/nglcoreapplication.h>
|
||||
#include <LtsCommandLineParser/LtsCommandLineParser.h>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
#include "settings.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
NGLCoreApplication app(argc, argv);
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy());
|
||||
|
||||
LtsCommandLineParser::LtsCommandLineParser options;
|
||||
if (!options.init())
|
||||
return -1;
|
||||
app.createLogger("MDM", options.exerciseId());
|
||||
|
||||
MeteoDataManagement::Settings::setIniFile(options.iniFile());
|
||||
|
||||
INFO_LOG(app.baseLogger()) << "*** Start Meteo Data Management Service (MDM)";
|
||||
INFO_LOG(app.baseLogger()) << "### domainId: " << options.domainId();
|
||||
|
||||
int iRet = -1;
|
||||
{
|
||||
std::unique_ptr<MeteoDataManagement::MainHandler> mainHandler(new MeteoDataManagement::MainHandler);
|
||||
if (!mainHandler->init(options.domainId()))
|
||||
return iRet;
|
||||
|
||||
STARTUP_LOG(app.baseLogger());
|
||||
|
||||
iRet = app.exec();
|
||||
|
||||
SHUTDOWN_LOG(app.baseLogger());
|
||||
}
|
||||
|
||||
return iRet;
|
||||
} // end of main()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* MainHandler for MeteoDataManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-21
|
||||
*/
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
#include <ngldb/db_service_handler.h>
|
||||
#include <GuezNasat/initialization.h>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
MainHandler::MainHandler()
|
||||
: m_ddsHandler(nullptr)
|
||||
, m_dbHandler(nullptr)
|
||||
, m_handlerMeteoDataUnits(nullptr)
|
||||
, m_handlerInfrastructureData(nullptr)
|
||||
, m_handlerStaticMeteoData(nullptr)
|
||||
, m_gnaService(nullptr)
|
||||
, m_logger(getLogger("MainHandler"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MainHandler::~MainHandler()
|
||||
{
|
||||
delete m_gnaService;
|
||||
m_handlerMeteoDataUnits = nullptr;
|
||||
m_handlerInfrastructureData = nullptr;
|
||||
m_handlerStaticMeteoData = nullptr;
|
||||
m_ddsHandler = nullptr;
|
||||
m_dbHandler = nullptr;
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool MainHandler::init(int domainId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Start MeteoDataManagement MainHandler.";
|
||||
const QString errStr = initInternal(domainId);
|
||||
if (!errStr.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << errStr;
|
||||
if (m_ddsHandler && m_ddsHandler->pacemaker())
|
||||
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::StartingError, errStr);
|
||||
return false;
|
||||
}
|
||||
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
|
||||
INFO_LOG(m_logger) << "MeteoDataManagement MainHandler initialized.";
|
||||
return true;
|
||||
}
|
||||
|
||||
QString MainHandler::initInternal(int domainId)
|
||||
{
|
||||
// initialize DDS
|
||||
m_ddsHandler = std::make_shared<DdsHandler>(domainId);
|
||||
if (!m_ddsHandler->init())
|
||||
return QStringLiteral("Initialisation DdsHandler failed.");
|
||||
|
||||
// initialize database
|
||||
m_dbHandler = std::make_shared<DbHandler>();
|
||||
|
||||
if (!m_dbHandler->init(0, Settings::settings()))
|
||||
return QStringLiteral("Initialisation DbHandler failed.");
|
||||
|
||||
// create HandlerMeteoDataUnits
|
||||
INFO_LOG(m_logger) << "create HandlerMeteoDataUnits.";
|
||||
m_handlerMeteoDataUnits = std::make_shared<HandlerMeteoDataUnits>(this);
|
||||
if (!m_handlerMeteoDataUnits->init())
|
||||
return QStringLiteral("create HandlerMeteoDataUnits failed.");
|
||||
|
||||
// initialize handlerInfraStructureData
|
||||
m_handlerInfrastructureData = std::make_shared<HandlerInfrastructureData>(m_ddsHandler, m_handlerMeteoDataUnits);
|
||||
if (!m_handlerInfrastructureData->init())
|
||||
return QStringLiteral("Initialisation HandlerInfrastructureData failed.");
|
||||
// Info: Initialisierung der einzelnen Wetterstationen erfolgt direkt aus ISM.
|
||||
|
||||
// initialize HandlerStaticMeteoData
|
||||
m_handlerStaticMeteoData = std::make_shared<HandlerStaticMeteoData>(m_ddsHandler, db());
|
||||
if (!m_handlerStaticMeteoData->init())
|
||||
return QStringLiteral("Initialisation HandlerStaticMeteoData failed.");
|
||||
|
||||
m_gnaService = new GuezNasat::Initialization;
|
||||
if (!m_gnaService->initialize(m_ddsHandler->dds(), m_dbHandler->db()->database()) ||
|
||||
!m_gnaService->loadFromDatabase())
|
||||
return QStringLiteral("Can not initialize GNA service.");
|
||||
|
||||
return QString();
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::shared_ptr<DatabaseInterface> MainHandler::db() const
|
||||
{
|
||||
return m_dbHandler->db();
|
||||
}
|
||||
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* MainHandler for MeteoDataManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-21
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "handler_infrastructure_data.h"
|
||||
#include "handler_meteo_data_units.h"
|
||||
#include "handler_static_meteo_data.h"
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include "mdm_db.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace GuezNasat
|
||||
{
|
||||
class Initialization;
|
||||
}
|
||||
|
||||
namespace NGLDB
|
||||
{
|
||||
template <typename DB> class DbServiceHandler;
|
||||
}
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
|
||||
class MainHandler
|
||||
{
|
||||
public:
|
||||
explicit MainHandler();
|
||||
~MainHandler();
|
||||
|
||||
bool init(int domainId);
|
||||
|
||||
std::shared_ptr<DdsHandler> dds() const { return m_ddsHandler; }
|
||||
std::shared_ptr<DatabaseInterface> db() const;
|
||||
std::shared_ptr<HandlerInfrastructureData> ism() const { return m_handlerInfrastructureData; }
|
||||
private:
|
||||
QString initInternal(int domainId);
|
||||
private: // attributes
|
||||
std::shared_ptr<DdsHandler> m_ddsHandler; ///< Pointer to DDS handler
|
||||
std::shared_ptr<DbHandler> m_dbHandler; ///< Pointer to DB handler
|
||||
std::shared_ptr<HandlerMeteoDataUnits> m_handlerMeteoDataUnits; ///< Pointer to meteo data units handler
|
||||
std::shared_ptr<HandlerInfrastructureData> m_handlerInfrastructureData; ///< Pointer to infrastructure data handler
|
||||
std::shared_ptr<HandlerStaticMeteoData> m_handlerStaticMeteoData; ///< Pointer to static meteo data handler
|
||||
GuezNasat::Initialization *m_gnaService;
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
+52
@@ -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 MDM_COMMON_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define MDM_COMMON_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCMDMCOMMON_LIB)
|
||||
# define MDM_COMMON_EXPORT Q_DECL_EXPORT
|
||||
# ifndef WIN32
|
||||
# ifdef NDDSUSERDllExport
|
||||
# undef NDDSUSERDllExport
|
||||
# endif
|
||||
# define NDDSUSERDllExport Q_DECL_EXPORT
|
||||
# endif
|
||||
# else
|
||||
# define MDM_COMMON_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MDM_CLIENT_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define MDM_CLIENT_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCMDMCLIENT_LIB)
|
||||
# define MDM_CLIENT_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define MDM_CLIENT_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MDM_SERVER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define MDM_SERVER_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCMDMSERVER_LIB)
|
||||
# define MDM_SERVER_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define MDM_SERVER_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<service namespace="MeteoDataManagement" abbreviation="MDM" procNames="MeteoDataManagement" exerciseDependency="Global" groups="Core">
|
||||
<rcs>
|
||||
<Id Id="$Id$"/>
|
||||
<HeadURL HeadURL="$HeadURL$"/>
|
||||
<Author Author="$Author$"/>
|
||||
</rcs>
|
||||
<operatorRights offset="22">
|
||||
<guiPlugin name="StaticWeather" offset="2">
|
||||
<operatorRightGroup name="Meteo Data Management - Static Weather Data" description="Edit static weather">
|
||||
<operatorRight right="MeteoDataStaticWeatherEdit" value="1" description="Edit Meteorological Data"/>
|
||||
<operatorRight right="MeteoDataStaticWeatherShow" value="2" description="Show Meteorological Data"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
<guiPlugin name="WeatherStations" offset="1">
|
||||
<operatorRightGroup name="Meteo Data Management - Weather Stations" description="Show Weather Stations">
|
||||
<operatorRight right="MeteoDataWeatherStationsShow" value="2" description="Show Meteorological Data"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
</operatorRights>
|
||||
<tables>
|
||||
<table name="mdm_static_meteo_data">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="time_stamp" datatype="bigint"/>
|
||||
<column name="wind_direction" datatype="real" default="90.0"/>
|
||||
<column name="wind_speed" datatype="real" default="0.0"/>
|
||||
<column name="temperature" datatype="real" default="18.5"/>
|
||||
<column name="pressure" datatype="real" default="1010.5"/>
|
||||
<column name="humidity" datatype="real" default="45.6"/>
|
||||
<constraint name="UQ_mdm_static_meteo_data_id" type="unique">
|
||||
<column name="id"/>
|
||||
</constraint>
|
||||
</table>
|
||||
</tables>
|
||||
<views/>
|
||||
<dbServiceStructs>
|
||||
<serviceStruct name="MdmStaticMeteoData" table="mdm_static_meteo_data"/>
|
||||
<table name="mdm_static_meteo_data"/>
|
||||
</dbServiceStructs>
|
||||
<topicTypes>
|
||||
<topicType name="MeteoData" isDataObject="1" autosubscribe="1" routeToClient="1" routeToServer="0" routeInReplay="0">
|
||||
<column name="id" idlType="long" isKey="1"/>
|
||||
<column name="pos" idlType="Core::GeoPosition2D"/>
|
||||
<column name="weatherStationId" idlType="long" comment="Correspond to the assetId assigned from ISM"/>
|
||||
<column name="note" idlType="string"/>
|
||||
<column name="isStaticMeteoData" idlType="boolean"/>
|
||||
<column name="timeStamp" idlType="long long"/>
|
||||
<column name="windDirection" idlType="double" comment="wind direction in degree, clockwise, North = 0. Statement means the wind comes from direction."/>
|
||||
<column name="windSpeed" idlType="double" comment="wind speed in m/s"/>
|
||||
<column name="temperature" idlType="double" comment="in degree Celsius"/>
|
||||
<column name="pressure" idlType="double" comment="air pressure in hPa"/>
|
||||
<column name="humidity " idlType="double" comment="air humidity in percent"/>
|
||||
<column name="windOk" idlType="boolean"/>
|
||||
<column name="climateOk" idlType="boolean"/>
|
||||
</topicType>
|
||||
<topicType name="StaticMeteoDataModifyRequest">
|
||||
<column name="id" idlType="long"/>
|
||||
<column name="timeStamp" idlType="long long"/>
|
||||
<column name="windDirection" idlType="double"/>
|
||||
<column name="windSpeed" idlType="double"/>
|
||||
<column name="temperature" idlType="double"/>
|
||||
<column name="pressure" idlType="double"/>
|
||||
<column name="humidity" idlType="double"/>
|
||||
</topicType>
|
||||
</topicTypes>
|
||||
<functionTopics>
|
||||
<functionTopic name="StaticMeteoDataModify" requestTopicType="StaticMeteoDataModifyRequest" replyTopicType="Core::FunctionReply" requestTopicName="StaticMeteoDataModifyRequest" replyTopicName="StaticMeteoDataModifyReply" routeInReplay="0"/>
|
||||
</functionTopics>
|
||||
<enumerations>
|
||||
<enumeration name="DummyEnum">
|
||||
<attribute key="val1" value="1"/>
|
||||
<attribute key="val2" value="2"/>
|
||||
</enumeration>
|
||||
</enumerations>
|
||||
</service>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Settings for MeteoDataManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
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)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
quint16 Settings::getRequstIntervalClimateSensor()
|
||||
{
|
||||
// quint16 requestIntervalClimateSensor = settings()->settings()->value("ZSKSWS/requestIntervalClimateSensor", 1000*5).toUInt();
|
||||
quint16 requestIntervalClimateSensor = 5000;
|
||||
return requestIntervalClimateSensor;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
quint16 Settings::getRequstTimeoutClimateSensor()
|
||||
{
|
||||
// quint16 requestTimeoutWindSensor = settings()->settings()->value("ZSKSWS/requestTimeoutClimateSensor", 1000*1).toUInt();
|
||||
quint16 requestTimeoutWindSensor = 1000;
|
||||
return requestTimeoutWindSensor;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
quint16 Settings::getRequstIntervalWindSensor()
|
||||
{
|
||||
// quint16 requestIntervalWindSensor = settings()->settings()->value("ZSKSWS/requestIntervalWindSensor", 1000*5).toUInt();
|
||||
quint16 requestIntervalWindSensor = 5000;
|
||||
return requestIntervalWindSensor;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
quint16 Settings::getRequstTimeoutWindSensor()
|
||||
{
|
||||
// quint16 requestTimeoutWindSensor = settings()->settings()->value("ZSKSWS/requestTimeoutWindSensor", 1000*1).toUInt();
|
||||
quint16 requestTimeoutWindSensor = 1000;
|
||||
return requestTimeoutWindSensor;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NGL::Settings *Settings::settings()
|
||||
{
|
||||
return s();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void Settings::setIniFile(const QString &ini)
|
||||
{
|
||||
NGLSettingsClass::setIniFile(ini);
|
||||
}
|
||||
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Settings for MeteoDataManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
//!< Get request interval for climate sensor in msec
|
||||
quint16 getRequstIntervalClimateSensor();
|
||||
|
||||
//!< Get request interval for wind sensor in msec
|
||||
quint16 getRequstIntervalWindSensor();
|
||||
|
||||
//!< Get request timeout for wind sensor in msec
|
||||
quint16 getRequstTimeoutWindSensor();
|
||||
|
||||
//!< Get request timeout for climate sensor in msec
|
||||
quint16 getRequstTimeoutClimateSensor();
|
||||
|
||||
|
||||
//!< The real NGL::Settings - object
|
||||
NGL::Settings *settings();
|
||||
void setIniFile(const QString &ini);
|
||||
}
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* Handle one climate sensor
|
||||
* Requests for climate sensor data in an given interval.
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#include "tcpclimate.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
TcpClimate::TcpClimate(QObject *parent)
|
||||
: TcpSocket("TcpClimate", parent)
|
||||
, m_requestTimer(new QTimer(this))
|
||||
, m_requestTimeoutTimer(new QTimer(this))
|
||||
, m_pressure(0.0)
|
||||
, m_temperature(0.0)
|
||||
, m_humidity(0.0)
|
||||
, m_dataChanged(false)
|
||||
{
|
||||
// m_logger geerbt aus TcpSocket
|
||||
DEBUG_LOG(m_logger) << "CTOR TcpClimate... hat TcpSocket fuer connects initialisiert";
|
||||
|
||||
connect(m_requestTimer, &QTimer::timeout, this, &TcpClimate::onSensorDataRequest);
|
||||
connect(m_requestTimeoutTimer, &QTimer::timeout, this, &TcpClimate::onRequestTimeout);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpClimate::start(const QString &converterIp, quint16 climatePort)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "TcpClimate::start() ... call function TcpSocket::start()";
|
||||
|
||||
TcpSocket::start(converterIp, climatePort); // connect...
|
||||
m_requestTimer->start(Settings::getRequstIntervalClimateSensor());
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpClimate::init()
|
||||
{
|
||||
// pure virtual function aus TcpSocket
|
||||
|
||||
// PTU-300 Einstellungen: StopMode, 4800,7,E,1
|
||||
// Hier sind dann keine weiteren Einstellungen erforderlich.
|
||||
// Nach PowerOn ist die PTU betriebsbereit.
|
||||
|
||||
// PTU Stop-Mode setzen damit das Geraet ueberhaupt commands annnimmt.
|
||||
// if(! sendCommand("S\r"))
|
||||
// return;
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpClimate::dataAvailable(const QByteArray &line)
|
||||
{
|
||||
// pure virtual function aus TcpSocket
|
||||
|
||||
// Nur lines mit Wetterdaten behandeln
|
||||
if (line.contains("P="))
|
||||
{
|
||||
m_requestTimeoutTimer->stop();
|
||||
bool ok = extractDataFromLine(line);
|
||||
if (!ok)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Read error climate sensor data."
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
}
|
||||
|
||||
if (m_dataChanged)
|
||||
{
|
||||
m_dataChanged = false;
|
||||
|
||||
INFO_LOG(m_logger) << "climateDataChanged()"
|
||||
<< " pressure: " << m_pressure
|
||||
<< " temperature: " << m_temperature
|
||||
<< " humidity: " << m_humidity;
|
||||
|
||||
emit sigClimateDataChanged(m_pressure, m_temperature, m_humidity, ok);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Other climate sensor data available. line: " << line;
|
||||
// ggf. andere Meldungen behandeln
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpClimate::onSensorDataRequest()
|
||||
{
|
||||
if (m_requestTimeoutTimer->isActive())
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "onSensorDataRequest() ... " ;
|
||||
|
||||
if (!sendCommand("SEND\r\n"))
|
||||
return;
|
||||
|
||||
m_requestTimeoutTimer->start(Settings::getRequstTimeoutClimateSensor());
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpClimate::onRequestTimeout()
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Timeout for climate sensor data request."
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
|
||||
emit sigClimateDataChanged(0, 0, 0, false);
|
||||
m_requestTimeoutTimer->stop();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
bool TcpClimate::extractDataFromLine(const QByteArray &line)
|
||||
{
|
||||
bool bOk = true;
|
||||
float retValue;
|
||||
|
||||
if (extractValueFromLine(line, "P=", "hPa", retValue))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "pressure: " << retValue ;
|
||||
if (!qFuzzyCompare(retValue, m_pressure))
|
||||
{
|
||||
m_pressure = retValue;
|
||||
m_dataChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Value for pressure not available!"
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
bOk = false;
|
||||
}
|
||||
|
||||
if (extractValueFromLine(line, "T=", "'C", retValue))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "temperature: " << retValue ;
|
||||
if (!qFuzzyCompare(retValue, m_temperature))
|
||||
{
|
||||
m_temperature = retValue;
|
||||
m_dataChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Value for temperature not available!"
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
bOk = false;
|
||||
}
|
||||
|
||||
if (extractValueFromLine(line, "RH=", "%RH", retValue))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "humidity: " << retValue ;
|
||||
if (!qFuzzyCompare(retValue, m_humidity))
|
||||
{
|
||||
m_humidity = retValue;
|
||||
m_dataChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Value for humidity not available!"
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
bOk = false;
|
||||
}
|
||||
|
||||
return bOk;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
bool TcpClimate::extractValueFromLine(const QByteArray &line, const QByteArray &startKey, const QByteArray &endKey, float &retValue)
|
||||
{
|
||||
bool bOk = true;
|
||||
if (line.contains(startKey) && line.contains(endKey))
|
||||
{
|
||||
int idx = line.indexOf(startKey);
|
||||
int idx2 = line.indexOf(endKey);
|
||||
|
||||
QByteArray value;
|
||||
for (int i = idx + startKey.length(); i < idx2; i++)
|
||||
{
|
||||
if (line.at(i) != ' ')
|
||||
value.append(line.at(i));
|
||||
}
|
||||
retValue = value.toFloat(&bOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
bOk = false;
|
||||
WARNING_LOG(m_logger) << "One or both keywords not found in line: "
|
||||
<< line << "keywords: " << startKey << " / " << endKey;
|
||||
}
|
||||
return bOk;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Handle one climate sensor
|
||||
* Requests for climate sensor data in an given interval.
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "tcpsocket.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
class TcpClimate final : public TcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TcpClimate(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Connect to converter and starts reading sensor data
|
||||
* @param[in] converterIp IP address of the RS232-LAN Converter
|
||||
* @param[in] climatePort Port number of climate sensor on the RS232-LAN Converter
|
||||
*/
|
||||
void start(const QString &converterIp, quint16 climatePort);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emits signal if data were changed
|
||||
*/
|
||||
void sigClimateDataChanged(float pressure, float temperature, float humidity, bool climateOk);
|
||||
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Requests for new sensor data
|
||||
*/
|
||||
void onSensorDataRequest();
|
||||
|
||||
/**
|
||||
* Timeout for new sensor data request
|
||||
*/
|
||||
void onRequestTimeout();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pure virtual function from TcpSocket to initialize the especially sensor device
|
||||
*/
|
||||
void init() override;
|
||||
/**
|
||||
* pure virtual function from TcpSocket to to handle the especially sensor device data
|
||||
*/
|
||||
void dataAvailable(const QByteArray &line) override;
|
||||
|
||||
/**
|
||||
* Extract sensor data from given data line
|
||||
* @param[in] line data line to be extacted
|
||||
* @return False if an error occurded, otherwise true;
|
||||
*/
|
||||
bool extractDataFromLine(const QByteArray &line);
|
||||
|
||||
/**
|
||||
* Extract especially value from given data line
|
||||
* @param[in] line data line to be extracted
|
||||
* @param[in] startKey extraction starts after startkey
|
||||
* @param[in] endKey extraction stops before endkey
|
||||
* @param[in/out] retValue reference to return value
|
||||
* @return False if an error occurded, otherwise true;
|
||||
*/
|
||||
bool extractValueFromLine(const QByteArray &line, const QByteArray &startKey, const QByteArray &endKey, float &retValue);
|
||||
|
||||
|
||||
|
||||
QTimer *m_requestTimer; ///< Request Interval in msec
|
||||
QTimer *m_requestTimeoutTimer; ///< Request Timeout in mse
|
||||
float m_pressure; ///< pressure in hPa
|
||||
float m_temperature; ///< temperature in Grad C
|
||||
float m_humidity; ///< humidity in %
|
||||
bool m_dataChanged; ///< if true, sensor data were changed
|
||||
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* TcpSocket handling for MeteoDataUnit
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#include "tcpsocket.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QHostInfo>
|
||||
//#include <sys/socket.h> // used for keepalive
|
||||
//#include <netinet/tcp.h> // used for keepalive
|
||||
//#include <netinet/in.h> // used for keepalive
|
||||
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
TcpSocket::TcpSocket(const char *logName, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_waitTime(1)
|
||||
, m_socket(nullptr)
|
||||
, m_tryReconnect(false)
|
||||
, m_bSocketErrorWarnedOnce(false)
|
||||
, m_logger(getLogger(logName))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "CTOR TCP-Socket... " ;
|
||||
|
||||
doConnect();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
TcpSocket::~TcpSocket()
|
||||
{
|
||||
if (m_socket)
|
||||
m_socket->close();
|
||||
delete m_socket;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpSocket::doConnect()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "doConnect TCP-Socket " ;
|
||||
|
||||
if (m_socket)
|
||||
m_socket->deleteLater();
|
||||
|
||||
m_socket = new QTcpSocket(this);
|
||||
connect(m_socket, &QTcpSocket::connected,
|
||||
this, &TcpSocket::onConnected);
|
||||
connect(m_socket, &QTcpSocket::disconnected,
|
||||
this, &TcpSocket::onDisonnected);
|
||||
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
|
||||
this, &TcpSocket::onError);
|
||||
connect(m_socket, &QTcpSocket::readyRead,
|
||||
this, &TcpSocket::onReadyRead);
|
||||
|
||||
if (m_tryReconnect)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Try reconnect to host " << m_hostName
|
||||
<< ":" << m_hostPort;
|
||||
m_socket->connectToHost(m_hostName, m_hostPort);
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpSocket::start(const QString &hostName, quint16 port)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Try connect to host: " << hostName
|
||||
<< ": " << port;
|
||||
|
||||
m_hostName = hostName;
|
||||
m_hostPort = port;
|
||||
|
||||
m_socket->connectToHost(m_hostName, port);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpSocket::onConnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Connected to "
|
||||
<< m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
m_bSocketErrorWarnedOnce = false;
|
||||
m_waitTime = 1;
|
||||
|
||||
// Bei einer TCP Verbindung ergibt sich ein Problem bei der Pruefung ob die Verbindung noch besteht.
|
||||
// Das sollte mit Hilfe des 'TCP keepalive Mechanismus' behoben werden.
|
||||
// Infos dazu u.A. unter http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#intro
|
||||
// Leider fuehrte keine der Varianten zum Erfolg.
|
||||
// Der Abbruch wurde unabhaengig der Parameter in allen Faellen immer nach ziemlich genau 15:40Min dedektiert.
|
||||
// Das Setzen der Systemvariablen war ebenfalls ohne Auswirkung.
|
||||
// Da diese Programmteile unter Windows eh so nicht zu uebersetzen sind, ist der Codeteil hier in Kommentar gesetzt.
|
||||
|
||||
// INFO_LOG(m_logger) << "----Set TCP_KEEPIDLE parameter ";
|
||||
|
||||
// const int keepAliveOption = 1; // on
|
||||
// if (setsockopt(m_socket->socketDescriptor(), SOL_SOCKET, SO_KEEPALIVE, &keepAliveOption, sizeof(keepAliveOption)) != 0)
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Error setting SO_KEEPALIVE: " << errno;
|
||||
// }
|
||||
|
||||
// const int idleTimeout = 5; // sec
|
||||
// if (setsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPIDLE, &idleTimeout, sizeof(idleTimeout)) != 0)
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Error setting TCP_KEEPIDLE: " << errno;
|
||||
// }
|
||||
|
||||
// const int keepIntervalCnt = 10; // sec
|
||||
// if (setsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPINTVL, &keepIntervalCnt, sizeof(keepIntervalCnt)) != 0)
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Error setting TCP_KEEPINTVL: " << errno;
|
||||
// }
|
||||
|
||||
// const int idlePaketCnt = 2; // 2 probes -> detection shoud be comes after 5s + 2 * 10s => 25 sec
|
||||
// if (setsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPCNT, &idlePaketCnt, sizeof(idlePaketCnt)) != 0)
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Error setting TCP_KEEPCNT: " << errno;
|
||||
// }
|
||||
|
||||
// //----- Testausgaben
|
||||
// int getOption = 0;
|
||||
// socklen_t optlen = sizeof(getOption);
|
||||
// getsockopt(m_socket->socketDescriptor(), SOL_SOCKET, SO_KEEPALIVE, &getOption, &optlen);
|
||||
// ERROR_LOG(m_logger) << "...SO_KEEPALIVE set to: " << getOption;
|
||||
|
||||
// getsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPIDLE, &getOption, &optlen);
|
||||
// ERROR_LOG(m_logger) << "...TCP_KEEPIDLE set to: " << getOption;
|
||||
|
||||
// getsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPINTVL, &getOption, &optlen);
|
||||
// ERROR_LOG(m_logger) << "...TCP_KEEPINTVL set to: " << getOption;
|
||||
|
||||
// getsockopt(m_socket->socketDescriptor(), SOL_TCP, TCP_KEEPCNT, &getOption, &optlen);
|
||||
// ERROR_LOG(m_logger) << "...TCP_KEEPCNT set to: " << getOption;
|
||||
|
||||
init(); // pure virtual function
|
||||
// Auspraegung mit spezieller Sensorinitialisierung durchfuehren
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpSocket::onDisonnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Disconnected from " << m_socket->peerAddress().toString()
|
||||
<< ":" << m_socket->peerPort();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpSocket::onError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Socket error: " << err
|
||||
<< " \"" << m_socket->errorString() << "\""
|
||||
<< " Hostname: " << m_hostName
|
||||
<< " Serial Port:" << m_hostPort
|
||||
<< " - trying to reconnect in " << m_waitTime << " seconds";
|
||||
m_socket->disconnectFromHost();
|
||||
|
||||
// try reconnects ....
|
||||
m_tryReconnect = true;
|
||||
if (m_socket->state() != QAbstractSocket::UnconnectedState)
|
||||
m_socket->waitForDisconnected();
|
||||
|
||||
m_waitTime += 2;
|
||||
|
||||
if (m_waitTime > 120)
|
||||
m_waitTime = 120;
|
||||
|
||||
QTimer::singleShot(m_waitTime * 1000, this, &TcpSocket::doConnect);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
void TcpSocket::onReadyRead()
|
||||
{
|
||||
// zeilenweises Einlesen der Sensordaten
|
||||
while (m_socket->canReadLine())
|
||||
{
|
||||
const QByteArray line = m_socket->readLine();
|
||||
DEBUG_LOG(m_logger) << "Read line from sensor: " << line;
|
||||
|
||||
dataAvailable(line); // pure virtual function
|
||||
// Auspraegung mit spezieller Sensordatenauswertung durchfuehren
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
bool TcpSocket::sendCommand(const QByteArray &qba)
|
||||
{
|
||||
bool bOk = true;
|
||||
|
||||
INFO_LOG(m_logger) << "Send command: " << qba;
|
||||
|
||||
if (m_socket->state() != QTcpSocket::ConnectedState)
|
||||
{
|
||||
if (m_bSocketErrorWarnedOnce)
|
||||
{
|
||||
m_bSocketErrorWarnedOnce = true;
|
||||
WARNING_LOG(m_logger) << "Error on sendCommand(). No socket connection estabilished."
|
||||
<< " Hostname: " << m_hostName;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int trxBytes = m_socket->write(qba);
|
||||
|
||||
if (trxBytes != qba.size())
|
||||
{
|
||||
bOk = false;
|
||||
ERROR_LOG(m_logger) << "Insufficient number of tansfered bytes."
|
||||
<< " Soll: " << trxBytes << " Ist: " << qba.size();
|
||||
}
|
||||
m_socket->flush();
|
||||
return bOk;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* TcpSocket handling for MeteoDataUnit
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include "logger.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
|
||||
class TcpSocket : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TcpSocket(const char *logName, QObject *parent = nullptr);
|
||||
~TcpSocket();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Connect to converter
|
||||
* @param[in] hostName Hostname or Ip address of the RS232-LAN Converter
|
||||
* @param[in] windPort Port number of especially sensor on the RS232-LAN Converter
|
||||
*/
|
||||
void start(const QString &hostName, quint16 port);
|
||||
|
||||
/**
|
||||
* Define the signal/slots connects uesd for TcpSocket
|
||||
*/
|
||||
protected Q_SLOTS:
|
||||
void doConnect();
|
||||
void onConnected();
|
||||
void onDisonnected();
|
||||
void onError(QAbstractSocket::SocketError);
|
||||
void onReadyRead();
|
||||
|
||||
/**
|
||||
* Send data to connected TcpSocket
|
||||
* @param[in] qba Data tob transfered
|
||||
*/
|
||||
bool sendCommand(const QByteArray &qba);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pure virtual function to initialize the especially sensor device
|
||||
*/
|
||||
virtual void init() = 0;
|
||||
|
||||
/**
|
||||
* Pure virtual function to handle the especially sensor device data
|
||||
* @param[in] qba Data tob transfered
|
||||
*/
|
||||
virtual void dataAvailable(const QByteArray &line) = 0;
|
||||
|
||||
QString m_hostName; ///< Hostname or Ip address to get access to the RS232-LAN Converter
|
||||
quint16 m_hostPort; ///< Access port number of sensor on the RS232-LAN Converter
|
||||
qint32 m_waitTime; ///< delay time before try reconnection
|
||||
QTcpSocket *m_socket; ///< pointer to tcpsocket object
|
||||
bool m_tryReconnect; ///< if true, try reconnection
|
||||
bool m_bSocketErrorWarnedOnce;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Handle one weatherstation consist of one wind- and climate sensor
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#include "tcpweatherstation.h"
|
||||
#include "tcpclimate.h"
|
||||
#include "tcpwind.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
TcpWeatherStation::TcpWeatherStation(int id,
|
||||
const QString &converterIp,
|
||||
quint16 climatePort,
|
||||
quint16 windPort,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_id(id)
|
||||
, m_converterIp(converterIp)
|
||||
, m_climatePort(climatePort)
|
||||
, m_windPort(windPort)
|
||||
, m_tcpClimate(nullptr)
|
||||
, m_tcpWind(nullptr)
|
||||
, m_pressure(800.0)
|
||||
, m_temperature(0.0)
|
||||
, m_humidity(0.0)
|
||||
, m_direction(0.0)
|
||||
, m_speed(0.0)
|
||||
, m_climateOk(false)
|
||||
, m_windOk(false)
|
||||
, m_logger(getLogger("TcpWeatherStation"))
|
||||
{
|
||||
INFO_LOG(m_logger) << "Start TcpWeatherStation ip/(hostname): " << m_converterIp
|
||||
<< " climatePort: " << m_climatePort
|
||||
<< " windPort: " << m_windPort;
|
||||
|
||||
if (m_climatePort)
|
||||
{
|
||||
m_tcpClimate = new TcpClimate(this);
|
||||
|
||||
INFO_LOG(m_logger) << "m_tcpClimate->start(" << m_converterIp << ", "
|
||||
<< QString::number(m_climatePort) << ")";
|
||||
m_tcpClimate->start(m_converterIp, m_climatePort);
|
||||
|
||||
connect(m_tcpClimate, &TcpClimate::sigClimateDataChanged,
|
||||
this, &TcpWeatherStation::onClimateDataChanged);
|
||||
}
|
||||
|
||||
if (m_windPort)
|
||||
{
|
||||
m_tcpWind = new TcpWind(this);
|
||||
|
||||
INFO_LOG(m_logger) << "m_tcpWind->start(" << m_converterIp << ", "
|
||||
<< QString::number(m_windPort) << ")";
|
||||
|
||||
m_tcpWind->start(m_converterIp, m_windPort);
|
||||
|
||||
connect(m_tcpWind, &TcpWind::sigWindDataChanged,
|
||||
this, &TcpWeatherStation::onWindDataChanged);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWeatherStation::onClimateDataChanged(float pressure, float temperature, float humidity, bool climateOk)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onClimateDataChanged()"
|
||||
<< " MDU AssetId: " << m_id
|
||||
<< " pressure: " << pressure
|
||||
<< " temperature: " << temperature
|
||||
<< " humidity: " << humidity
|
||||
<< " climateOk: " << climateOk;
|
||||
|
||||
m_pressure = pressure;
|
||||
m_temperature = temperature;
|
||||
m_humidity = humidity;
|
||||
m_climateOk = climateOk;
|
||||
|
||||
emit sigWeatherDataChanged(m_id, m_pressure, m_temperature, m_humidity, m_direction, m_speed, m_climateOk, m_windOk);
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWeatherStation::onWindDataChanged(float direction, float speed, bool windOk)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onWindDataChanged()"
|
||||
<< " MDU AssetId: " << m_id
|
||||
<< " direction: " << direction
|
||||
<< " speed: " << speed
|
||||
<< " climateOk: " << m_climateOk;
|
||||
|
||||
m_direction = direction;
|
||||
m_speed = speed;
|
||||
m_windOk = windOk;
|
||||
|
||||
emit sigWeatherDataChanged(m_id, m_pressure, m_temperature, m_humidity, m_direction, m_speed, m_climateOk, m_windOk);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Handle one weatherstation consist of one wind- and climate sensor
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include "logger.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
class TcpClimate;
|
||||
class TcpWind;
|
||||
|
||||
|
||||
class TcpWeatherStation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Class constructor
|
||||
* @param[in] id weatherstatiopn id
|
||||
* @param[in] converterIp IP address of the RS232-LAN Converter
|
||||
* @param[in] climatePort Port number of climate sensor on the RS232-LAN Converter
|
||||
* @param[in] windPort Port number of wind sensor on the RS232-LAN Converter
|
||||
* A port number of 0 indicates this sensor is not available
|
||||
*/
|
||||
TcpWeatherStation(int id,
|
||||
const QString &converterIp,
|
||||
quint16 climatePort,
|
||||
quint16 windPort,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* Emits signal if data were changed
|
||||
* @param[in] id weatherstation id
|
||||
* @param[in] pressure pressure in hPa
|
||||
* @param[in] temperature temperature in °C
|
||||
* @param[in] humidity humidity in % relative humidity
|
||||
* @param[in] direction wind FROM direction in degree (north=0°, east=90°, south= 180°, west=270°)
|
||||
* @param[in] speed speed in m/s
|
||||
*/
|
||||
void sigWeatherDataChanged(int id,
|
||||
float pressure, float temperature, float humidity,
|
||||
float direction, float speed, bool climateOk, bool weatherOk);
|
||||
|
||||
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Signaled from tcpclimate class if data were changed
|
||||
* @param[in] pressure pressure in hPa
|
||||
* @param[in] temperature temperature in °C
|
||||
* @param[in] humidity humidity in % relative humidity
|
||||
*/
|
||||
void onClimateDataChanged(float pressure, float temperature, float humidity, bool climateOk);
|
||||
|
||||
/**
|
||||
* Signaled from tcpwind class if data were changed
|
||||
* @param[in] direction wind FROM direction in degree (north=0°, east=90°, south= 180°, west=270°)
|
||||
* @param[in] speed speed in m/s
|
||||
*/
|
||||
void onWindDataChanged(float direction, float speed, bool windOk);
|
||||
|
||||
|
||||
protected:
|
||||
int m_id; ///< weatherstation id
|
||||
QString m_converterIp; ///< IP address of the RS232-LAN Converter
|
||||
quint16 m_climatePort; ///< Access port number of climate sensor on the RS232-LAN Converter
|
||||
quint16 m_windPort; ///< Access port number of wind sensor on the RS232-LAN Converter
|
||||
|
||||
TcpClimate *m_tcpClimate; ///< pointer to climate sensor object
|
||||
TcpWind *m_tcpWind; ///< pointer to wind sensor object
|
||||
|
||||
float m_pressure; ///< last pressure value from climate sensor
|
||||
float m_temperature; ///< last temperature value from climate sensor
|
||||
float m_humidity; ///< last humidity value from climate sensor
|
||||
float m_direction; ///< last direction value from wind sensor
|
||||
float m_speed; ///< last speed value from wind sensor
|
||||
bool m_climateOk; ///< last statecheck climate
|
||||
bool m_windOk; ///< last statecheck weather
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
Executable
+175
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Handle one wind sensor
|
||||
* Requests for wind sensor data in an given interval.
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
#include "tcpwind.h"
|
||||
#include "settings.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
|
||||
TcpWind::TcpWind(QObject *parent)
|
||||
: TcpSocket("TcpWind", parent)
|
||||
, m_requestTimer(new QTimer(this))
|
||||
, m_requestTimeoutTimer(new QTimer(this))
|
||||
, m_direction(0)
|
||||
, m_speed(0)
|
||||
, m_dataChanged(false)
|
||||
{
|
||||
// m_logger geerbt aus TcpSocket
|
||||
INFO_LOG(m_logger) << "CTOR TcpWind... hat TcpSocket fuer connects initialisiert";
|
||||
|
||||
connect(m_requestTimer, &QTimer::timeout, this, &TcpWind::onSensorDataRequest);
|
||||
connect(m_requestTimeoutTimer, &QTimer::timeout, this, &TcpWind::onRequestTimeout);
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWind::start(const QString &converterIp, quint16 windPort)
|
||||
{
|
||||
INFO_LOG(m_logger) << "startTcpWind() ... call function TcpSocket::start()";
|
||||
|
||||
TcpSocket::start(converterIp, windPort); // connect...
|
||||
m_requestTimer->start(Settings::getRequstIntervalWindSensor());
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWind::init()
|
||||
{
|
||||
// pure virtual function aus TcpSocket
|
||||
|
||||
// WS-425 Einstellungen: NEMA-Extended, PollMode, 9600,8,N,1
|
||||
// Hier sind dann keine weiteren Einstellungen erforderlich.
|
||||
// Nach PowerOn ist der WS betriebsbereit.
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWind::dataAvailable(const QByteArray &line)
|
||||
{
|
||||
// pure virtual function aus TcpSocket
|
||||
|
||||
// Nur lines mit Wetterdaten behandeln
|
||||
if (line.contains("PAMWV"))
|
||||
{
|
||||
m_requestTimeoutTimer->stop();
|
||||
|
||||
bool windOk = extractDataFromLine(line);
|
||||
|
||||
if (m_dataChanged)
|
||||
{
|
||||
m_dataChanged = false;
|
||||
emit sigWindDataChanged(m_direction, m_speed, windOk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Other wind sensor data available line: " << line ;
|
||||
// ggf. andere Meldungen behandeln
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWind::onSensorDataRequest()
|
||||
{
|
||||
if (m_requestTimeoutTimer->isActive())
|
||||
return;
|
||||
|
||||
INFO_LOG(m_logger) << "onSensorDataRequest() ...";
|
||||
|
||||
if (!sendCommand("$WIPAQ,*72\r\n"))
|
||||
return;
|
||||
|
||||
m_requestTimeoutTimer->start(Settings::getRequstTimeoutWindSensor());
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void TcpWind::onRequestTimeout()
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Timeout for wind sensor data request."
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort;
|
||||
|
||||
emit sigWindDataChanged(0, 0, false);
|
||||
m_requestTimeoutTimer->stop();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
bool TcpWind::extractDataFromLine(const QByteArray &line)
|
||||
{
|
||||
bool bOk = true;
|
||||
DEBUG_LOG(m_logger) << "extractDataFromLine line: " << line;
|
||||
|
||||
QList<QByteArray> list = line.split(',');
|
||||
|
||||
if (list.size() != 6)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Invalid number of data in line: " << line << " cnt: " << list.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
// NMEA-Extended line data format:
|
||||
// [0] $PAWMV fixed Remark: 'A' discribes the sensor-id
|
||||
// [1] float direction in degree, or empty
|
||||
// [2] char R = relativ, T = true
|
||||
// [3] float speed, or empty
|
||||
// [4] char M = m/s, K = Km/h, N = Knoten
|
||||
// [5] String "<State> * <checksum>"
|
||||
// State: A = Data valid, V = Data invalid
|
||||
// * fixed
|
||||
// checksum 8bit XOR, excluding $ and *)
|
||||
|
||||
if (list.at(5).contains('V'))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid data from windsensor. "
|
||||
<< " RS232-LAN Converter: " << m_hostName
|
||||
<< " Port: " << m_hostPort
|
||||
<< " Line: " << line;
|
||||
return false;
|
||||
}
|
||||
|
||||
float value;
|
||||
if (list.at(1).size() > 0)
|
||||
{
|
||||
value = list.at(1).toFloat(&bOk);
|
||||
if (bOk && !qFuzzyCompare(value, m_direction))
|
||||
{
|
||||
m_direction = value;
|
||||
m_dataChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (list.at(3).size() > 0)
|
||||
{
|
||||
value = list.at(3).toFloat(&bOk);
|
||||
if (bOk && !qFuzzyCompare(value, m_speed))
|
||||
{
|
||||
m_speed = value;
|
||||
m_dataChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (list.at(4).contains('K'))
|
||||
{
|
||||
// km/h -> m/s
|
||||
m_speed = m_speed * 0.2778f;
|
||||
}
|
||||
|
||||
if (list.at(4).contains('N'))
|
||||
{
|
||||
// Kn -> m/s
|
||||
m_speed = m_speed * 0.5144f;
|
||||
}
|
||||
|
||||
return bOk;
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
} // namespace MeteoDataManagement
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Handle one wind sensor
|
||||
* Requests for wind sensor data in an given interval.
|
||||
* All data will be send by signal/slot connection in case of data change.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-09-22
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "tcpsocket.h"
|
||||
|
||||
namespace MeteoDataManagement
|
||||
{
|
||||
class TcpWind final : public TcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TcpWind(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Connect to converter and starts reading sensor data
|
||||
* @param[in] converterIp IP address of the RS232-LAN Converter
|
||||
* @param[in] windPort Port number of wind sensor on the RS232-LAN Converter
|
||||
*/
|
||||
void start(const QString &converterIp, quint16 windPort);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emits signal if data were changed
|
||||
*/
|
||||
void sigWindDataChanged(float direction, float speed, bool windOk);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Requests of new sensor data
|
||||
*/
|
||||
void onSensorDataRequest();
|
||||
|
||||
/**
|
||||
* Timeout for new sensor data request
|
||||
*/
|
||||
void onRequestTimeout();
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pure virtual function from TcpSocket to initialize the especially sensor device
|
||||
*/
|
||||
void init() override;
|
||||
/**
|
||||
* pure virtual function from TcpSocket to handle the especially sensor device data
|
||||
*/
|
||||
void dataAvailable(const QByteArray &line) override;
|
||||
|
||||
/**
|
||||
* Extract sensor data from given data line
|
||||
* @param[in] line data line to be extacted
|
||||
* @return False if an error occurded, otherwise true;
|
||||
*/
|
||||
bool extractDataFromLine(const QByteArray &line);
|
||||
|
||||
QTimer *m_requestTimer; ///< Request Interval in msec
|
||||
QTimer *m_requestTimeoutTimer; ///< Request Timeout in msec
|
||||
float m_direction; ///< wind FROM direction in degree (north=0°, east=90°, south= 180°, west=270°)
|
||||
float m_speed; ///< wind speed in m/s
|
||||
char m_speedUnit; ///< M = m/s, K = Km/h, N = Knoten
|
||||
bool m_dataChanged; ///< if true, sensor data were changed
|
||||
};
|
||||
} // namespace MeteoDataManagement
|
||||
Reference in new issue
Block a user