Commit d7e398c1 authored by Micha Mueller's avatar Micha Mueller
Browse files

WIP2: Simplify writing plugin configurators

parent 5272e779
......@@ -22,11 +22,28 @@
#define STRCMP(node,str) boost::iequals(node.first,str)
//TODO how to set mqttsuffix? (_mqttprefix + (mqttpart) + suffix)
#define LOOP_HEADER BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) { \
if (false) {}
#define S_BASE_ATTRIBUTES bool sensorBase(S_BASE& obj, boost::property_tree::iptree& config) override { \
LOOP_HEADER
#define S_GROUP_ATTRIBUTES bool sensorGroup(S_GROUP& obj, boost::property_tree::iptree& config) override { \
LOOP_HEADER
#define S_ENTITY_ATTRIBUTES bool sensorEntity(S_ENTITY& obj, boost::property_tree::iptree& config) override { \
LOOP_HEADER
#define ADD(name,setter) else if (boost::iequals(val.first, name)) { obj.setter(val.second.data()); }
#define END_ATTRIBUTES } return true; \
}
/*
#define CONFIG boost::property_tree::iptree& config
#define ATTRIBUTES BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) { \
if (false) {}
#define ADD(name,setter) else if (boost::iequals(val.first, name)) { sBase.setter(val.second.data()); }
#define END } return true;
*/
/**
* Non-virtual interface template for the configurators.
......@@ -72,23 +89,40 @@ public:
boost::property_tree::read_info(cfgPath, cfg);
//read global variables (if present overwrite those from global.conf)
boost::optional<boost::property_tree::iptree&> 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("/");
readGlobal(cfg);
//read template stuff
boost::optional<boost::property_tree::iptree&> templates = cfg.get_child_optional("templates");
if (templates) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &tempVal, cfg.get_child("templates")) {
if (boost::iequals(tempVal.first, _entityName)) {
//TODO
} else if (boost::iequals(tempVal.first, _groupName)) {
LOG(debug) << "Template Group \"" << tempVal.second.data() << "\"";
if (!tempVal.second.empty()) {
SGroup group(tempVal.second.data());
if (readSensorGroup(group, tempVal.second)) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &sBaseVal, tempVal.second) {
if (boost::iequals(sBaseVal.first, _baseName)) {
SBase* sensor = new SBase(sBaseVal.second.data());
if (readSensorBase(*sensor, sBaseVal.second)) {
group.pushBackSensor(sensor);
} else {
LOG(warning) << "Template sensor \"" << group.getName() << "::" << sBaseVal.second.data() << "\" has bad values! Ignoring...";
}
}
}
_templateSensorGroups.insert(std::pair<std::string, SGroup>(group.getName(), group));
} else {
LOG(warning) << "Template group \"" << tempVal.second.data() << "\" has bad values! Ignoring...";
}
}
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;
}
} //else if (boost::iequals(tempVal.first, _baseName)) {//TODO allow for template sensors? even useful?}
}
}
//TODO read actual entitys/groups/bases. How to handle defaults?
//read template groups
boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("groupTemplates");
if (tempSens) {
......@@ -197,6 +231,7 @@ protected:
sGroup.setCacheInterval(_cacheInterval);
//read in values inherited from SensorGroupInterface
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
//TODO handle default value here?
if (STRCMP(val, "interval")) {
sGroup.setInterval(stoull(val.second.data()));
} else if (STRCMP(val, "minValues")) {
......@@ -221,6 +256,26 @@ protected:
return sensorEntity(sEntity, config);
}
bool readGlobal(boost::property_tree::iptree& config) {
boost::optional<boost::property_tree::iptree&> globalVals = config.get_child_optional("global");
if (globalVals) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, config.get_child("global")) {
if (boost::iequals(global.first, "mqttprefix")) {
_mqttPrefix = global.second.data();
if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
_mqttPrefix.append("/");
}
LOG(debug) << " Using own MQTT-Prefix " << _mqttPrefix;
} else if (boost::iequals(global.first, "cacheInterval")) {
_cacheInterval = stoul(global.second.data());
LOG(debug) << " Using own caching interval " << _cacheInterval << " [s]";
_cacheInterval *= 1000;
}
}
}
return global(config);
}
/**
* Pure virtual interface method, responsible for reading the plugin-specific
* configuration part.
......@@ -269,9 +324,11 @@ protected:
virtual bool sensorEntity(SEntity& sEntity, boost::property_tree::iptree& config) = 0;
virtual bool global(boost::property_tree::iptree& config) = 0;
std::string _entityName;
std::string _groupName;
std::string _sensorName;
std::string _baseName;
std::string _cfgPath;
std::string _mqttPrefix;
......
......@@ -11,20 +11,6 @@
using namespace std;
SysfsConfigurator::SysfsConfigurator() {
_entityName = "host";
_groupName = "group";
_sensorName = "sensor";
}
SysfsConfigurator::~SysfsConfigurator() {}
bool SysfsConfigurator::Entity(Entity& entity, config) {
Add_Attribute("att", setter);
Add_Attribute("att2", setter2);
Group()
}
bool SysfsConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
//read one sensor at a time
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, cfg.get_child("sensors")) {
......@@ -56,58 +42,3 @@ bool SysfsConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
}
return true;
}
bool SysfsConfigurator::sensorBase(SysfsSensorBase& sBase, CONFIG) {
ATTRIBUTES
ADD("mqttsuffix", setMqtt)
ADD("path", setPath)
ADD("filter", setFilter)
END
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (STRCMP(val, "mqttsuffix")) {
sBase.setMqtt(_mqttPrefix + val.second.data());
} else if (STRCMP(val, ("path"))) {
sBase.setPath(val.second.data());
} else if (STRCMP(val, "filter")) {
sBase.setFilter(true);
string input = val.second.data();
//check if input has sed format of "s/.../.../" for substitution
regex checkSubstitute("s([^\\\\]{1})([\\S|\\s]*)\\1([\\S|\\s]*)\\1");
smatch matchResults;
if(regex_match(input, matchResults, checkSubstitute)) {
//input has substitute format
LOG(debug) << " Init Regex with: " << matchResults[2].str();
LOG(debug) << " Substitution: " << matchResults[3].str();
sBase.setRegex(regex(matchResults[2].str(), regex_constants::extended));
sBase.setSubstitution(matchResults[3].str());
} else {
//input is only a regex
LOG(debug) << " Init Regex with " << input;
sBase.setRegex(regex(input, regex_constants::extended));
sBase.setSubstitution("&");
}
}
}
LOG(debug) << " MQTT : " << sBase.getMqtt();
LOG(debug) << " Path : " << sBase.getPath();
if (sBase.hasFilter()) {
//regex cannot be converted back to string
LOG(debug) << " Using regular expression to filter data";
}
return true;
}
bool SysfsConfigurator::sensorGroup(SysfsSensorGroup& sGroup, boost::property_tree::iptree& config) {
return true;
}
bool SysfsConfiguratorsensorEntity(void& sEntity, boost::property_tree::iptree& config) {
return false;
}
......@@ -14,18 +14,38 @@
class SysfsConfigurator : public ConfiguratorTemplate<SysfsSensorBase, SysfsSensorGroup, void> {
#define S_BASE SysfsSensorBase
#define S_GROUP SysfsSensorGroup
#define S_ENTITY void
public:
SysfsConfigurator();
virtual ~SysfsConfigurator();
SysfsConfigurator() {
_entityName = "host";
_groupName = "group";
_sensorName = "sensor";
}
virtual ~SysfsConfigurator() {}
protected:
/* Overwritten from ConfiguratorTemplate */
bool derivedReadConfig(boost::property_tree::iptree& cfg) override;
void derivedReReadConfig() override { /* nothing to overwrite */ }
void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) override { /* nothing to overwrite */ }
bool sensorBase(SysfsSensorBase& sBase, boost::property_tree::iptree& config) override;
bool sensorGroup(SysfsSensorGroup& sGroup, boost::property_tree::iptree& config) override;
bool sensorEntity(void& sEntity, boost::property_tree::iptree& config) override;
bool global(boost::property_tree::iptree& config) override { /* No plugin specific global settings */ return true; }
S_BASE_ATTRIBUTES
ADD("mqttsuffix", setMqtt)
ADD("path", setPath)
ADD("filter", setFilter)
END_ATTRIBUTES
S_GROUP_ATTRIBUTES
END_ATTRIBUTES
S_ENTITY_ATTRIBUTES
END_ATTRIBUTES
};
extern "C" ConfiguratorInterface* create() {
......
......@@ -34,6 +34,23 @@ public:
void setPath(const std::string& path) { _path = path; }
void setFile(FILE* file) { _file = file; }
void setFilter(bool filter) { _filter = filter; }
void setFilter(const std::string& filter) {
setFilter(true);
//check if input has sed format of "s/.../.../" for substitution
std::regex checkSubstitute("s([^\\\\]{1})([\\S|\\s]*)\\1([\\S|\\s]*)\\1");
std::smatch matchResults;
if(regex_match(filter, matchResults, checkSubstitute)) {
//input has substitute format
setRegex(regex(matchResults[2].str(), std::regex_constants::extended));
setSubstitution(matchResults[3].str());
} else {
//input is only a regex
setRegex(regex(filter, std::regex_constants::extended));
setSubstitution("&");
}
}
void setRegex(std::regex regx) { _regx = regx; }
void setSubstitution(const std::string& substitution) { _substitution = substitution; }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment