/* * Configurator.h * * Created on: 13.01.2018 * Author: Micha Mueller */ #ifndef SRC_CONFIGURATORTEMPLATE_H_ #define SRC_CONFIGURATORTEMPLATE_H_ #include "ConfiguratorInterface.h" #include #include #include #include #include #define STRCMP(node,str) boost::iequals(node.first,str) /** * Non-virtual interface template for the configurators. */ template class ConfiguratorTemplate : public ConfiguratorInterface { //the template shall only be instantiated for classes which implement the sensor interface static_assert(std::is_base_of::value, "S must derive from Sensor!"); protected: typedef std::map sensorMap_t; public: ConfiguratorTemplate() : _cacheInterval(900000) {} virtual ~ConfiguratorTemplate() { for (auto s : _sensors) { delete s; } } /** * Read in the given configuration * * @param cfgPath Path to the config-file * * @return True on success, false otherwise */ bool readConfig(std::string cfgPath) final { _cfgPath = cfgPath; boost::property_tree::iptree cfg; boost::property_tree::read_info(cfgPath, cfg); //read global variables (if present overwrite those from global.conf) boost::optional globalVals = cfg.get_child_optional("global"); if (globalVals) { BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) { if (STRCMP(global, "mqttprefix")) { _mqttPrefix = global.second.data(); if (_mqttPrefix[_mqttPrefix.length()-1] != '/') { _mqttPrefix.append("/"); } LOG(debug) << " Using own MQTT-Prefix " << _mqttPrefix; } else if (STRCMP(global, "cacheInterval")) { _cacheInterval = stoul(global.second.data()); LOG(debug) << " Using own caching interval " << _cacheInterval << " [s]"; _cacheInterval *= 1000; } } } //read template sensors boost::optional tempSens = cfg.get_child_optional("sensorTemplates"); 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(readSensor(sensor, sensorVal.second)) { _templateSensors.insert(std::pair(sensor.getName(), sensor)); } else { LOG(warning) << "Template sensor \"" << sensorVal.second.data() << "\" has bad values! Ignoring..."; } } } } } //read in plugin specific stuff (including actual sensors) return derivedReadConfig(cfg); } /** * Clear internal storage and read in the configuration again. * * @return True on success, false otherwise */ bool reReadConfig() final { //bring everything to a halt for (auto s : _sensors) { s->stopPolling(); } for(auto g : _sensorGroups) { g->stopPolling(); } //wait until everything is halted for (auto s : _sensors) { s->wait(); } for(auto g : _sensorGroups) { g->wait(); } //clean up plugin specific stuff derivedReReadConfig(); //clean up sensors and groups for (auto s : _sensors) { delete s; } for(auto g : _sensorGroups) { delete g; } _sensors.clear(); _sensorGroups.clear(); _templateSensors.clear(); //back to the very beginning return readConfig(_cfgPath); } /** * Sets internal variables with the ones provided by pluginSettings. * This method should be called once after constructing a configurator * to provide him with the global default values. * * @param pluginSettings Struct with global default settings for the plugins. */ void setGlobalSettings(const pluginSettings_t& pluginSettings) final { _mqttPrefix = pluginSettings.mqttPrefix; _cacheInterval = pluginSettings.cacheInterval; derivedSetGlobalSettings(pluginSettings); } /** * Get all sensors * * @return Vector containing pointers to all sensors of this plugin */ std::vector& getSensors() final { return _sensors; } /** * Get all sensor groups * * @return Vector containing pointers to all sensor groups of this plugin */ std::vector& getSensorGroups() { return _sensorGroups; } protected: /** * Non-virtual interface method for class-internal use only. * Reads and sets the common base values of a sensor, then calls * the corresponding derived function. * * @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 readSensor(S& sensor, boost::property_tree::iptree& config) { //read in base values BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) { if (STRCMP(val, "interval")) { sensor.setInterval(stoull(val.second.data())); } else if (STRCMP(val, "minValues")) { sensor.setMinValues(stoull(val.second.data())); } } sensor.setCacheInterval(_cacheInterval); LOG(debug) << " Interval : " << sensor.getInterval(); LOG(debug) << " minValues: " << sensor.getMinValues(); return derivedReadSensor(sensor, config); } /** * Pure virtual interface method, responsible for reading the plugin-specific * configuration part. * * @param cfg The (root) boost property tree from the plugins configuration file * * @return True on success, false otherwise */ virtual bool derivedReadConfig(boost::property_tree::iptree& cfg) = 0; /** * Pure virtual interface method, responsible for the plugin specific part if * re-reading the config. */ virtual void derivedReReadConfig() = 0; /** * Pure virtual interface method, responsible for setting global values specifically * for its plugin. * * @param pluginSettings The struct with global default plugin settings */ virtual void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) = 0; /** * Pure virtual interface method, responsible for reading plugin-specific sensor * values. * * @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 */ virtual bool derivedReadSensor(S& sensor, boost::property_tree::iptree& config) = 0; std::string _cfgPath; std::string _mqttPrefix; unsigned int _cacheInterval; std::vector _sensors; std::vector _sensorGroups; sensorMap_t _templateSensors; }; #endif /* SRC_CONFIGURATORTEMPLATE_H_ */