10.12., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 141ebab3 authored by Alessio Netti's avatar Alessio Netti

Analytics: added "isOperation" metadata field

- Basic implementation that allows to publish sensors as operations
of other sensors
- Still not functional and untested
parent c95f843b
......@@ -618,33 +618,45 @@ protected:
* @return true if successful, false otherwise
*/
bool constructSensorTopics(UnitTemplate<SBase>& u, Operator& op) {
std::string name;
// Performing name construction
for(auto& s: u.getOutputs()) {
s->setName(s->getMqtt());
SensorMetadata* sm = s->getMetadata();
if(sm) {
sm->publicName = s->getMqtt();
sm->pattern = s->getMqtt();
sm->isVirtual = false;
if(sm->interval==0)
sm->interval = (unsigned long long)op.getInterval() * 1000000;
}
adjustSensor(s, op, u);
}
for(auto& subUnit: u.getSubUnits())
for(auto& s : subUnit->getOutputs()) {
s->setName(s->getMqtt());
SensorMetadata* sm = s->getMetadata();
if(sm) {
sm->publicName = s->getMqtt();
sm->pattern = s->getMqtt();
sm->isVirtual = false;
if(sm->interval==0)
sm->interval = (unsigned long long)op.getInterval() * 1000000;
}
adjustSensor(s, op, u);
}
return true;
}
/**
* @brief Adjusts a single sensor
*
*/
void adjustSensor(std::shared_ptr<SBase> s, Operator& op, UnitTemplate<SBase>& u) {
s->setName(s->getMqtt());
SensorMetadata* sm = s->getMetadata();
if(sm) {
if(sm->isOperation) {
s->clearMetadata();
if(u.getInputs().size() != 1) {
LOG(error) << _operatorName << " " << op.getName() << ": Ambiguous operation field for sensor " << s->getName();
return;
}
// Replacing the metadata to publish the sensor as an operation of its corresponding input
SensorMetadata smNew;
smNew.publicName = u.getInputs()[0]->getMqtt();
smNew.addOperation(s->getMqtt());
s->setMetadata(smNew);
} else {
sm->publicName = s->getMqtt();
sm->pattern = s->getMqtt();
sm->isVirtual = false;
if (sm->interval == 0)
sm->interval = (unsigned long long) op.getInterval() * 1000000;
}
}
}
/**
* @brief Returns true if the input string describes an input block
......
......@@ -47,6 +47,7 @@ class SensorMetadata {
public:
SensorMetadata() :
isOperation(false),
isVirtual(false),
integrable(true),
monotonic(false),
......@@ -59,6 +60,7 @@ public:
operations("") {}
SensorMetadata(const SensorMetadata& other) {
this->isOperation = other.isOperation;
this->isVirtual = other.isVirtual;
this->integrable = other.integrable;
this->monotonic = other.monotonic;
......@@ -72,6 +74,7 @@ public:
}
SensorMetadata& operator=(const SensorMetadata& other) {
this->isOperation = other.isOperation;
this->isVirtual = other.isVirtual;
this->integrable = other.integrable;
this->monotonic = other.monotonic;
......@@ -85,6 +88,19 @@ public:
return *this;
}
bool addOperation(const string& opName) {
if (publicName.length()>0 && opName.length()>publicName.length() && !opName.compare(0, publicName.length(), publicName)) {
if(operations.length()==0)
operations = opName.substr(publicName.length());
else
operations += "," + opName.substr(publicName.length());
return true;
}
else
return false;
}
/**
* @brief Parses a JSON string and stores the content in this object.
*
......@@ -112,6 +128,8 @@ public:
this->monotonic = to_bool(val.second.data());
} else if (boost::iequals(val.first, "isVirtual")) {
this->isVirtual = to_bool(val.second.data());
} else if (boost::iequals(val.first, "isOperation")) {
this->isOperation = to_bool(val.second.data());
} else if (boost::iequals(val.first, "integrable")) {
this->integrable = to_bool(val.second.data());
} else if (boost::iequals(val.first, "unit")) {
......@@ -157,6 +175,7 @@ public:
}
// Public class members
bool isOperation;
bool isVirtual;
bool integrable;
bool monotonic;
......@@ -200,6 +219,7 @@ protected:
std::ostringstream scaleStream;
scaleStream << this->scale;
config.clear();
config.push_back(boost::property_tree::ptree::value_type("isOperation", boost::property_tree::ptree(this->isOperation ? "true" : "false")));
config.push_back(boost::property_tree::ptree::value_type("isVirtual", boost::property_tree::ptree(this->isVirtual ? "true" : "false")));
config.push_back(boost::property_tree::ptree::value_type("monotonic", boost::property_tree::ptree(this->monotonic ? "true" : "false")));
config.push_back(boost::property_tree::ptree::value_type("integrable", boost::property_tree::ptree(this->integrable ? "true" : "false")));
......
......@@ -748,6 +748,7 @@ Available fields that can be published as metadata are the following:
| interval | Sampling interval in milliseconds of the sensor. |
| operations | Comma-separated lists of operations available for the sensor, whose values can be retrieved by appending their names to the sensor name. |
An additional _isOperation_ field is available for the output sensors of operators in the Wintermute framework. If these output sensors are generated starting from a single input, this field allows to publish them as _operations_ of the latter, and will be listed in the associated database entry. For this to apply, however, the MQTT topic of the output sensor must be identical to that of the input, plus a suffix that describes the operation. Enabling this option invalidates all other metadata fields.
## Writing own plugins <a name="writingOwnPlugins"></a>
First make sure you read the [plugins](#plugins) section.
......
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