Commit 2e69d5ea authored by Micha Mueller's avatar Micha Mueller
Browse files

WIP: Refactor SensorGroup Architectur. Remove SingleSensors. Everything is now a SensorGroup

parent af8c270f
......@@ -355,7 +355,7 @@ Explanation of the values specific for the BACnet plugin:
| instance (object) | Instance of the object within the device.
| id | ID of the property to be read from the BACnet device-object. Assignment of numbers to properties is done according to the enum as defined in `bacenum.h`.
## Opa (Intel Omni-Path Archtiecture)
## Opa (Intel Omni-Path Architecture)
The Opa plugin enables dcdbpusher to query various counters from omni-path interconnects.
......
......@@ -265,18 +265,19 @@ bool Configuration::readPlugins() {
return false;
}
// returning an empty vector sensor may indicate problems with the config file
if(dynLib.configurator->getSensors().size() == 0) {
// returning an empty vector may indicate problems with the config file
if(dynLib.configurator->getSensorGroups().size() == 0) {
LOG(warning) << "Plugin \"" << dynLib.id << "\" created no sensors!";
}
//save only pointers to the sensors; copy-constructing an dynamically loaded object may lead to segfaults
//but before storing them, check if an MQTT-suffix was assigned twice
for(auto s : dynLib.configurator->getSensors()) {
bool ok = checkMqtt(s->getMqtt());
if(!ok) {
LOG(error) << "Problematic MQTT-Topics! Please check your config files";
return false;
//check if an MQTT-suffix was assigned twice
for(auto g : dynLib.configurator->getSensorGroups()) {
for(auto s : g->getSensors()) {
bool ok = checkMqtt(s->getMqtt());
if(!ok) {
LOG(error) << "Problematic MQTT-Topics! Please check your config files";
return false;
}
}
}
......
......@@ -147,9 +147,6 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
if (p.id == pathStrs[0]) {
boost::property_tree::ptree root, sensors;
for(auto s : p.configurator->getSensors()) {
sensors.put(s->getName(), "");
}
for(auto g : p.configurator->getSensorGroups()) {
boost::property_tree::ptree group;
for(auto s : g->getSensors()) {
......@@ -196,13 +193,6 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
response = "Sensor not found!";
for(auto s : p.configurator->getSensors()) {
if (s->getName() == sensor) {
response = pathStrs[0] + "::" + sensor + _httpsServer.calcAvg(s, s->getCacheSize(), time);
connection->set_status(server::connection::ok);
break;
}
}
for(auto g : p.configurator->getSensorGroups()) {
for(auto s : g->getSensors()) {
if (s->getName() == sensor) {
......@@ -241,9 +231,6 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
if (action == "start") {
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for(auto s : p.configurator->getSensors()) {
s->start();
}
for(auto g : p.configurator->getSensorGroups()) {
g->start();
}
......@@ -255,9 +242,6 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
} else if (action == "stop") {
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for(auto s : p.configurator->getSensors()) {
s->stop();
}
for(auto g : p.configurator->getSensorGroups()) {
g->stop();
}
......@@ -285,10 +269,6 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
connection->set_status(server::connection::internal_server_error);
}
for(auto s : p.configurator->getSensors()) {
s->init(_httpsServer._io);
s->start();
}
for(auto g : p.configurator->getSensorGroups()) {
g->init(_httpsServer._io);
g->start();
......
......@@ -87,11 +87,6 @@ void MQTTPusher::push() {
//for faster response
break;
}
for(auto s : p.configurator->getSensors()) {
if (s->getSizeOfReadingQueue() >= s->getMinValues()) {
sendReadings(s, reads, totalCount);
}
}
for(auto g : p.configurator->getSensorGroups()) {
for(auto s : g->getSensors()) {
if (s->getSizeOfReadingQueue() >= g->getMinValues()) {
......
......@@ -59,9 +59,6 @@ void sigintHandler(int sig) {
LOG(info) << "Stopping sensors...";
for(auto& p : _configuration->getPlugins()) {
LOG(info) << "Stop \"" << p.id << "\" plugin";
for(auto s : p.configurator->getSensors()) {
s->stop();
}
for(auto g : p.configurator->getSensorGroups()) {
g->stop();
}
......@@ -307,11 +304,6 @@ int main(int argc, char** argv) {
LOG(info) << "Init sensors...";
for(auto& p : _configuration->getPlugins()) {
LOG(info) << "Init \"" << p.id << "\" plugin";
for(auto s : p.configurator->getSensors()) {
LOG(debug) << " -" << s->getName();
s->init(io);
}
for(auto g : p.configurator->getSensorGroups()) {
LOG(debug) << " -Group: " << g->getGroupName();
g->init(io);
......@@ -322,10 +314,6 @@ int main(int argc, char** argv) {
LOG(info) << "Starting sensors...";
for(auto& p : _configuration->getPlugins()) {
LOG(info) << "Start \"" << p.id << "\" plugin";
for(auto s : p.configurator->getSensors()) {
s->start();
}
for(auto g : p.configurator->getSensorGroups()) {
g->start();
}
......
......@@ -10,7 +10,6 @@
#include <string>
#include <vector>
#include "SingleSensor.h"
#include "SensorGroupTemplate.h"
typedef struct {
......@@ -30,7 +29,6 @@ public:
virtual bool readConfig(std::string cfgPath) = 0;
virtual bool reReadConfig() = 0;
virtual void setGlobalSettings(const pluginSettings_t& pluginSettings) = 0;
virtual std::vector<SingleSensor*>& getSensors() = 0;
virtual std::vector<SensorGroupInterface*>& getSensorGroups() = 0;
protected:
......
......@@ -11,7 +11,6 @@
#include "ConfiguratorInterface.h"
#include "SensorBase.h"
#include "SingleSensor.h"
#include "SensorGroupTemplate.h"
#include <map>
......@@ -26,22 +25,23 @@
/**
* Non-virtual interface template for the configurators.
*/
template <typename SBase, typename S>
template <typename SBase, typename SGroup>
class ConfiguratorTemplate : public ConfiguratorInterface {
//the template shall only be instantiated for classes which derive from SensorBase/SingleSensor
static_assert(std::is_base_of<SingleSensor, S>::value, "S must derive from Sensor!");
//the template shall only be instantiated for classes which derive from SensorBase/SensorGroup
static_assert(std::is_base_of<SensorBase, SBase>::value, "SBase must derive from SensorBase!");
static_assert(std::is_base_of<SensorGroupTemplate, SGroup>::value, "SGroup must derive from SensorGroupTemplate!");
protected:
typedef std::map<std::string, S> sensorMap_t;
typedef std::map<std::string, SGroup> sensorGroupMap_t;
public:
ConfiguratorTemplate() : _cacheInterval(900000) {}
virtual ~ConfiguratorTemplate() {
for (auto s : _sensors) {
delete s;
for (auto g : _sensorGroups) {
delete g;
}
_templateSensorGroups.clear();
}
/**
......@@ -75,18 +75,19 @@ public:
}
}
//read template sensors
boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("sensorTemplates");
//read template groups
boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("groupTemplates");
if (tempSens) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensorVal, cfg.get_child("sensorTemplates")) {
if (STRCMP(sensorVal, "sensor")) {
LOG(debug) << "Template Sensor \"" << sensorVal.second.data() << "\"";
if (!sensorVal.second.empty()) {
S sensor(sensorVal.second.data());
if(readSingleSensor(sensor, sensorVal.second)) {
_templateSensors.insert(std::pair<std::string, S>(sensor.getName(), sensor));
BOOST_FOREACH(boost::property_tree::iptree::value_type &groupVal, cfg.get_child("groupTemplates")) {
if (STRCMP(groupVal, "group")) {
LOG(debug) << "Template Group \"" << groupVal.second.data() << "\"";
if (!groupVal.second.empty()) {
//TODO
SGroup group(groupVal.second.data());
if(readSensorGroup(group, groupVal.second)) {
_templateSensorGroups.insert(std::pair<std::string, SGroup>(group.getName(), group));
} else {
LOG(warning) << "Template sensor \"" << sensorVal.second.data() << "\" has bad values! Ignoring...";
LOG(warning) << "Template group \"" << groupVal.second.data() << "\" has bad values! Ignoring...";
}
}
}
......@@ -104,17 +105,11 @@ public:
*/
bool reReadConfig() final {
//bring everything to a halt
for (auto s : _sensors) {
s->stop();
}
for(auto g : _sensorGroups) {
g->stop();
}
//wait until everything is halted
for (auto s : _sensors) {
s->wait();
}
for(auto g : _sensorGroups) {
g->wait();
}
......@@ -123,16 +118,12 @@ public:
derivedReReadConfig();
//clean up sensors and groups
for (auto s : _sensors) {
delete s;
}
for(auto g : _sensorGroups) {
delete g;
}
_sensors.clear();
_sensorGroups.clear();
_templateSensors.clear();
_templateSensorGroups.clear();
//back to the very beginning
return readConfig(_cfgPath);
......@@ -152,15 +143,6 @@ public:
derivedSetGlobalSettings(pluginSettings);
}
/**
* Get all sensors
*
* @return Vector containing pointers to all sensors of this plugin
*/
std::vector<SingleSensor*>& getSensors() final {
return _sensors;
}
/**
* Get all sensor groups
*
......@@ -171,34 +153,19 @@ public:
}
protected:
/**
* Non-virtual interface method for class-internal use only.
* Reads and sets the values for a SingleSensor. This is only a
* convenience function and only calls readSensorBase() and
* readSensorInterface() itself.
*
* @param sensor The sensor for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
bool readSingleSensor(S& sensor, boost::property_tree::iptree& config) {
return (readSensorBase(sensor, config) & readSensorInterface(sensor, config));
}
/**
* Non-virtual interface method for class-internal use only.
* Reads and sets the common base values of a sensor (currently none),
* then calls the corresponding derived function to read plugin specific
* values.
*
* @param sensor The sensor for which to set the values
* @param sBase The sensor base for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
bool readSensorBase(SBase& sensor, boost::property_tree::iptree& config) {
return derivedReadSensorBase(sensor, config);
bool readSensorBase(SBase& sBase, boost::property_tree::iptree& config) {
return derivedReadSensorBase(sBase, config);
}
/**
......@@ -212,22 +179,28 @@ protected:
*
* @return True on success, false otherwise
*/
bool readSensorInterface(SensorInterface& sensor, boost::property_tree::iptree& config) {
//read in values inherited from SensorInterface
bool readSensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) {
sGroup.setCacheInterval(_cacheInterval);
//read in values inherited from SensorGroupInterface
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (STRCMP(val, "interval")) {
sensor.setInterval(stoull(val.second.data()));
sGroup.setInterval(stoull(val.second.data()));
} else if (STRCMP(val, "minValues")) {
sensor.setMinValues(stoull(val.second.data()));
sGroup.setMinValues(stoull(val.second.data()));
} else if (STRCMP(val, "sensor")) {
SBase* sensor = new SBase(val.second.data());
if (readSensorBase(*sensor, val.second)) {
sGroup.pushBackSensor(sensor);
} else {
LOG(warning) << "Sensor " << sGroup.getGroupName() << "::" << sensor->getName() << " could not be read! Omitting";
}
}
}
sensor.setCacheInterval(_cacheInterval);
LOG(debug) << " Interval : " << sensor.getInterval();
LOG(debug) << " minValues: " << sensor.getMinValues();
LOG(debug) << " Interval : " << sGroup.getInterval();
LOG(debug) << " minValues: " << sGroup.getMinValues();
/* return derivedReadSensorInterface(sensor, config); */
return true;
return derivedReadSensorGroup(sGroup, config);
}
/**
......@@ -258,19 +231,29 @@ protected:
* Pure virtual interface method, responsible for reading plugin-specific sensor
* base values.
*
* @param sensor The sensor for which to set the values
* @param sBase The sensor base for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
virtual bool derivedReadSensorBase(SBase& sBase, boost::property_tree::iptree& config) = 0;
/**
* Pure virtual interface method, responsible for reading plugin-specific sensor
* group values.
*
* @param sGroup The sensor group for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
virtual bool derivedReadSensorBase(SBase& sensor, boost::property_tree::iptree& config) = 0;
virtual bool derivedReadSensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) = 0;
std::string _cfgPath;
std::string _mqttPrefix;
unsigned int _cacheInterval;
std::vector<SingleSensor*> _sensors;
std::vector<SensorGroupInterface*> _sensorGroups;
sensorMap_t _templateSensors;
sensorGroupMap_t _templateSensorGroups;
};
#endif /* SRC_CONFIGURATORTEMPLATE_H_ */
......@@ -8,24 +8,100 @@
#ifndef SENSORGROUPINTERFACE_H_
#define SENSORGROUPINTERFACE_H_
#include "SensorInterface.h"
#include <atomic>
#include <memory>
#include <boost/asio.hpp>
#include "Logging.h"
#include "SensorBase.h"
class SensorGroupInterface : public SensorInterface {
class SensorGroupInterface {
public:
SensorGroupInterface(const std::string& groupName) :
_groupName(groupName) {}
_groupName(groupName),
_keepRunning(0),
_minValues(1),
_interval(1000),
_cacheInterval(900000),
_cacheSize(1),
_cacheIndex(0),
_pendingTasks(0),
_timer(nullptr) {}
SensorGroupInterface(const SensorGroupInterface& other) :
_groupName(other._groupName),
_keepRunning(other._keepRunning),
_minValues(other._minValues),
_interval(other._interval),
_cacheInterval(other._cacheInterval),
_cacheSize(other._cacheSize),
_cacheIndex(other._cacheIndex),
_timer(nullptr) {
_pendingTasks.store(other._pendingTasks.load());
}
virtual ~SensorGroupInterface() {}
SensorGroupInterface& operator=(const SensorGroupInterface& other) {
_groupName = other._groupName;
_keepRunning = other._keepRunning;
_minValues = other._minValues;
_interval = other._interval;
_cacheInterval = other._cacheInterval;
_cacheSize = other._cacheSize;
_cacheIndex = other._cacheIndex;
_pendingTasks.store(other._pendingTasks.load());
_timer = nullptr;
return *this;
}
const std::string& getGroupName() const { return _groupName; }
void setGroupName(const std::string& groupName) { _groupName = groupName; }
unsigned getMinValues() const { return _minValues; }
unsigned getInterval() const { return _interval; }
unsigned getCacheSize() const { return _cacheSize; }
void setGroupName(const std::string& groupName) { _groupName = groupName; }
void setMinValues(unsigned minValues) { _minValues = minValues; }
void setInterval(unsigned interval) { _interval = interval; }
void setCacheInterval(unsigned cacheInterval) { _cacheInterval = cacheInterval; }
/**
* Does a busy wait until all dispatched handlers are finished (_pendingTasks == 0)
*/
void wait() {
while(_pendingTasks) {
sleep(1);
}
}
//can be overwritten
virtual void init(boost::asio::io_service& io) {
_cacheSize = _cacheInterval / _interval + 1;
_timer.reset(new boost::asio::deadline_timer(io, boost::posix_time::seconds(0)));
}
//have to be overwritten
virtual void start() = 0;
virtual void stop() = 0;
virtual void pushBackSensor(SensorBase* s) = 0;
virtual std::vector<SensorBase*>& getSensors() = 0;
protected:
virtual void read() = 0;
virtual void readAsync() = 0;
std::string _groupName;
int _keepRunning;
unsigned int _minValues;
unsigned int _interval;
unsigned int _cacheInterval;
unsigned int _cacheSize;
unsigned int _cacheIndex;
std::atomic_uint _pendingTasks;
std::unique_ptr<boost::asio::deadline_timer> _timer;
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
};
#endif /* SENSORGROUPINTERFACE_H_ */
......@@ -39,7 +39,7 @@ public:
virtual std::vector<SensorBase*>& getSensors() override { return _baseSensors; }
virtual void init(boost::asio::io_service& io) {
SensorInterface::init(io);
SensorGroupInterface::init(io);
for(auto s : _sensors) {
s->initSensor(_cacheSize);
......
/*
* SensorInterface.h
*
* Created on: 09.08.2018
* Author: Micha Mueller
*/
#ifndef SRC_SENSORINTERFACE_H_
#define SRC_SENSORINTERFACE_H_
#include <atomic>
#include <memory>
#include <boost/asio.hpp>
#include "Logging.h"
class SensorInterface {
public:
SensorInterface() :
_keepRunning(0),
_minValues(1),
_interval(1000),
_cacheInterval(900000),
_cacheSize(1),
_cacheIndex(0),
_pendingTasks(0),
_timer(nullptr) {}
SensorInterface(const SensorInterface& other) :
_keepRunning(other._keepRunning),
_minValues(other._minValues),
_interval(other._interval),
_cacheInterval(other._cacheInterval),
_cacheSize(other._cacheSize),
_cacheIndex(other._cacheIndex),
_timer(nullptr) {
_pendingTasks.store(other._pendingTasks.load());
}
virtual ~SensorInterface() {}
SensorInterface& operator=(const SensorInterface& other) {
_keepRunning = other._keepRunning;
_minValues = other._minValues;
_interval = other._interval;
_cacheInterval = other._cacheInterval;
_cacheSize = other._cacheSize;
_cacheIndex = other._cacheIndex;
_pendingTasks.store(other._pendingTasks.load());
_timer = nullptr;
return *this;
}
unsigned getMinValues() const { return _minValues; }
unsigned getInterval() const { return _interval; }
unsigned getCacheSize() const { return _cacheSize; }
void setMinValues(unsigned minValues) { _minValues = minValues; }
void setInterval(unsigned interval) { _interval = interval; }
void setCacheInterval(unsigned cacheInterval) { _cacheInterval = cacheInterval; }
/**
* Does a busy wait until all dispatched handlers are finished (_pendingTasks == 0)
*/
void wait() {
while(_pendingTasks) {
sleep(1);
}
}
//can be overwritten
virtual void init(boost::asio::io_service& io) {
_cacheSize = _cacheInterval / _interval + 1;
_timer.reset(new boost::asio::deadline_timer(io, boost::posix_time::seconds(0)));
}
//have to be overwritten
virtual void start() = 0;
virtual void stop() = 0;
protected:
virtual void read() = 0;
virtual void readAsync() = 0;
int _keepRunning;
unsigned int _minValues;
unsigned int _interval;
unsigned int _cacheInterval;
unsigned int _cacheSize;
unsigned int _cacheIndex;
std::atomic_uint _pendingTasks;
std::unique_ptr<boost::asio::deadline_timer> _timer;
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
};
#endif /* SRC_SENSORINTERFACE_H_ */
/*
* SingleSensor.h
*
* Created on: 09.08.2018
* Author: Micha Mueller
*/
#ifndef SRC_SINGLESENSOR_H_
#define SRC_SINGLESENSOR_H_
#include "SensorBase.h"
#include "SensorInterface.h"
class SingleSensor : public virtual SensorBase, public SensorInterface{