Commit 03527a09 authored by Alessio Netti's avatar Alessio Netti
Browse files

DA: improved template support

- Now template sensors can be defined in data analytics plugins, and
can be used both for input and output
- The list of input "prototype" sensors of a template analyzer is now
propagated to derived analyzers
- The list of output "prototype" sensors of a template is ignored and
not inherited, because it would interfere with the Unit system
parent 8b4b1738
......@@ -85,7 +85,11 @@ public:
virtual ~AnalyzerConfiguratorTemplate() {
for (auto ta : _templateAnalyzers)
delete ta.second;
for (auto ts : _templateSensors)
delete ts.second;
_templateAnalyzers.clear();
_templateSensors.clear();
_templateProtoInputs.clear();
_analyzerInterfaces.clear();
_analyzers.clear();
}
......@@ -154,18 +158,22 @@ public:
if (!val.second.empty()) {
Analyzer* an = new Analyzer(val.second.data());
an->setTemplate(true);
if (readAnalyzer(*an, val.second)) {
auto ret = _templateAnalyzers.insert(std::pair<std::string, Analyzer*>(val.second.data(), an));
if(!ret.second) {
LOG(warning) << "Template " << _analyzerName << " " << val.second.data() << " already exists! Omitting...";
delete an;
}
} else {
if (!readAnalyzer(*an, val.second)) {
LOG(warning) << "Template " << _analyzerName << " \"" << val.second.data() << "\" has bad values! Ignoring...";
delete an;
}
}
// Here we read and instantiate analyzers
// Sensor templates are read
} else if (boost::iequals(val.first, "template_" + _baseName)) {
LOG(debug) << "Template " << _baseName << " \"" << val.second.data() << "\"";
if (!val.second.empty()) {
SBase* base = new SBase(val.second.data());
if (!readSensorBase(*base, val.second, true)) {
LOG(warning) << "Template " << _baseName << " \"" << val.second.data() << "\" has bad values! Ignoring...";
delete base;
}
}
// Here we read and instantiate analyzers
} else if (boost::iequals(val.first, _analyzerName)) {
LOG(debug) << _analyzerName << " \"" << val.second.data() << "\"";
if (!val.second.empty()) {
......@@ -211,14 +219,18 @@ public:
for(auto a : _analyzers)
a->wait();
// First of all, delete all template analyzers
// First of all, delete all template analyzers and sensors
for (auto ta : _templateAnalyzers)
delete ta.second;
for (auto ts : _templateSensors)
delete ts.second;
// Clear all analyzers
_analyzerInterfaces.clear();
_analyzers.clear();
_templateAnalyzers.clear();
_templateSensors.clear();
_templateProtoInputs.clear();
}
/**
......@@ -294,7 +306,7 @@ protected:
* @param ll Severity level to log with
*/
virtual void printConfiguratorConfig(LOG_LEVEL ll) {
LOG_VAR(ll) << " No other plugin-specific general parameters defined";
LOG_VAR(ll) << " No other plugin-specific general parameters defined";
}
/**
......@@ -331,9 +343,12 @@ protected:
an = *(it->second);
an.setName(config.data());
an.setTemplate(false);
// Analyzers instantiated from templates DO NOT share the same units and sensors. This would lead to
// too much naming ambiguity and is generally just not needed
// Analyzers instantiated from templates DO NOT share the same units and output sensors.
// This would lead to too much naming ambiguity and is generally just not needed
an.clearUnits();
// The input sensors defined in the template are on the other hand preserved; this is meant as a
// workaround to shorten certain configurations
protoInputs = _templateProtoInputs[def.get().data()];
} else {
LOG(warning) << "Template " << _analyzerName << "\"" << def.get().data() << "\" not found! Using standard values.";
}
......@@ -362,7 +377,7 @@ protected:
if (boost::iequals(valInner.first, _baseName)) {
LOG(debug) << " I/O " << _baseName << " " << valInner.second.data();
SBase sensor = SBase(valInner.second.data());
if (readSensorBase(sensor, valInner.second)) {
if (readSensorBase(sensor, valInner.second, false)) {
shared_ptr<SBase> sensorPtr = make_shared<SBase>(sensor);
val.first==INPUT_BLOCK ? protoInputs.push_back(sensorPtr) : protoOutputs.push_back(sensorPtr);
} else {
......@@ -424,6 +439,14 @@ protected:
}
}
delete units;
} else {
// If the analyzer is a template, we add it to the related map
auto ret = _templateAnalyzers.insert(std::pair<std::string, Analyzer*>(an.getName(), &an));
if(!ret.second) {
LOG(warning) << "Template " << _analyzerName << " " << an.getName() << " already exists! Omitting...";
return false;
}
_templateProtoInputs.insert(std::pair<std::string, std::vector<shared_ptr<SBase>>>(an.getName(), protoInputs));
}
return true;
}
......@@ -439,10 +462,23 @@ protected:
* @param config A boost property (sub-)tree containing the sensor values
* @return True if successful, false otherwise
*/
//TODO: add template functionality (if useful at all here)
bool readSensorBase(SBase& sBase, CFG_VAL config) {
bool readSensorBase(SBase& sBase, CFG_VAL config, bool isTemplate=false) {
sBase.setCacheInterval(_cacheInterval);
if (!isTemplate) {
// Copying parameters from the template (if defined)
boost::optional<boost::property_tree::iptree&> def = config.get_child_optional("default");
if(def) {
LOG(debug) << " Using \"" << def.get().data() << "\" as default.";
auto it = _templateSensors.find(def.get().data());
if(it != _templateSensors.end()) {
sBase = *(it->second);
sBase.setName(config.data());
} else {
LOG(warning) << "Template " << _baseName << "\" " << def.get().data() << "\" not found! Using standard values.";
}
}
}
// Reading other sensor parameters
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (boost::iequals(val.first, "mqttsuffix")) {
sBase.setMqtt(val.second.data());
......@@ -451,12 +487,21 @@ protected:
} else if (boost::iequals(val.first, "delta")) {
sBase.setDelta(to_bool(val.second.data()));
} else if (boost::iequals(val.first, "sink")) {
sBase.setSinkPath( val.second.data() );
sBase.setSinkPath(val.second.data());
} else if (boost::iequals(val.first, "subSampling")) {
sBase.setSubsampling( std::stoul(val.second.data()) );
sBase.setSubsampling(std::stoul(val.second.data()));
}
}
sensorBase(sBase, config);
if(isTemplate) {
auto ret = _templateSensors.insert(std::pair<std::string, SBase*>(sBase.getName(), &sBase));
if(!ret.second) {
LOG(warning) << "Template " << _baseName << " " << sBase.getName() << " already exists! Omitting...";
return false;
}
}
return true;
}
......@@ -554,6 +599,10 @@ protected:
std::vector<A_Ptr> _analyzers;
// Map of the template analyzers that were defined in the config file - used for easy retrieval and instantiation
std::map<std::string, Analyzer*> _templateAnalyzers;
// Map of the template sensors that were defined
std::map<std::string, SBase*> _templateSensors;
// Map of the protoinputs belonging to template analyzers
std::map<std::string, std::vector<shared_ptr<SBase>>> _templateProtoInputs;
};
#endif //PROJECT_ANALYZERCONFIGURATORTEMPLATE_H
Supports Markdown
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