Commit 787db53b authored by Alessio Netti's avatar Alessio Netti

MQTT Topics and Names checks

- Name uniqueness checks have been extended to sensor names and sensor
groups (managed by two separate sets)
parent 06155b53
......@@ -109,7 +109,7 @@ bool AnalyticsManager::load(const string& path, const string& globalFile, const
if(dynLib.configurator->getAnalyzers().size() == 0) {
LOG(warning) << "Plugin \"" << dynLib.id << "\" created no analyzers!";
} else if(!checkTopics(dynLib)) {
LOG(error) << "Problematic MQTT-Topics, please check your config files!";
LOG(error) << "Problematic MQTT topics or sensor names, please check your config files!";
return false;
}
//save dl-struct
......@@ -172,11 +172,13 @@ bool AnalyticsManager::reload(boost::asio::io_service& io, const string& plugin)
void AnalyticsManager::removeTopics(an_dl_t p) {
MQTTChecker& mqttCheck = MQTTChecker::getInstance();
for(const auto& a : p.configurator->getAnalyzers()) {
mqttCheck.removeName(a->getName());
mqttCheck.removeGroup(a->getName());
if (a->getStreaming())
for (const auto &u : a->getUnits())
for (const auto &o: u->getBaseOutputs())
for (const auto &o: u->getBaseOutputs()) {
mqttCheck.removeTopic(o->getMqtt());
mqttCheck.removeName(o->getName());
}
}
}
......@@ -184,12 +186,12 @@ bool AnalyticsManager::checkTopics(an_dl_t p) {
MQTTChecker& mqttCheck = MQTTChecker::getInstance();
bool validTopics=true;
for(const auto& a : p.configurator->getAnalyzers()) {
if (!mqttCheck.checkName(a->getName()))
if (!mqttCheck.checkGroup(a->getName()))
validTopics = false;
if (a->getStreaming())
for (const auto &u : a->getUnits())
for (const auto &o: u->getBaseOutputs())
if (!mqttCheck.checkTopic(o->getMqtt()))
if (!mqttCheck.checkTopic(o->getMqtt()) || !mqttCheck.checkName(o->getName()))
validTopics = false;
}
return validTopics;
......
......@@ -78,30 +78,60 @@ public:
return true;
}
/**
* @brief Removes a name from the internal set of sensor names
*
* This method should be used to remove obsolete sensor names, e.g. when reloading plugins.
* This is useful only in the case that MQTT topics differ from the actual sensor names.
*
* @param name The name (string) to be removed
*/
//TODO: get rid of these two methods once MQTT topics and sensor names are unified
void removeName(const std::string& name) {
_names.erase(name);
}
/**
* @brief Performs a check on a certain name
*
* The check is passed if the name for the group, analyzer or entity is not used already.
*
* @param name An arbitrary name (string) to check
* @return True if the name is valid, False otherwise
*/
bool checkName(const std::string& name) {
auto returnIt = _names.insert(name);
if (!returnIt.second) {
LOG(error) << "Name \"" << name << "\" used twice!";
return false;
}
return true;
}
/**
* @brief Removes a name from the internal set of entities
*
* This method should be used to remove obsolete sensor groups, entities or analyzers once they
* are destroyed, e.g. on plugin reload actions.
*
* @param topic The name (string) to be removed
* @param name The name (string) to be removed
*/
void removeName(const std::string& name) {
void removeGroup(const std::string& name) {
_groups.erase(name);
}
/**
* @brief Performs a check on a certain name
* @brief Performs a check on a certain group name
*
* The check is passed if the name for the group, analyzer or entity is not used already.
*
* @param topic An arbitrary name (string) to check
* @param name An arbitrary name (string) to check
* @return True if the name is valid, False otherwise
*/
bool checkName(const std::string& name) {
bool checkGroup(const std::string& name) {
auto returnIt = _groups.insert(name);
if (!returnIt.second) {
LOG(error) << "Name \"" << name << "\" used twice!";
LOG(error) << "Group name \"" << name << "\" used twice!";
return false;
}
return true;
......@@ -128,6 +158,8 @@ private:
std::set<std::string> _topics;
// Set used to keep track of groups, analyzers and other entities
std::set<std::string> _groups;
// Set used to keep track of sensor names (if different from the respective topics)
std::set<std::string> _names;
// Logger object to notify MQTT check outcome
logger_t lg;
......
......@@ -297,13 +297,16 @@ bool Configuration::readPlugins() {
//check if an MQTT-suffix was assigned twice
bool validTopics=true;
for(const auto& g : dynLib.configurator->getSensorGroups())
for(const auto& s : g->getSensors())
if(!mqttCheck.checkTopic(s->getMqtt()))
validTopics=false;
for(const auto& g : dynLib.configurator->getSensorGroups()) {
if (!mqttCheck.checkGroup(g->getGroupName()))
validTopics = false;
for (const auto &s : g->getSensors())
if (!mqttCheck.checkTopic(s->getMqtt()) || !mqttCheck.checkName(s->getName()))
validTopics = false;
}
if(!validTopics) {
LOG(error) << "Problematic MQTT-Topics, please check your config files!";
LOG(error) << "Problematic MQTT topics or sensor names, please check your config files!";
return false;
}
......
......@@ -369,7 +369,7 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
if (p.configurator->reReadConfig()) {
// Perform checks on MQTT topics
if(!_httpsServer.checkTopics(p)) {
response = "Plugin " + pathStrs[0] + ": problematic MQTT-Topics, please check your config files!";
response = "Plugin " + pathStrs[0] + ": problematic MQTT topics or sensor names, please check your config files!";
connection->set_status(server::connection::internal_server_error);
_httpsServer.removeTopics(p);
p.configurator->clearConfig();
......@@ -460,18 +460,25 @@ bool HttpsServer::check_authkey(const std::string& authkey, permission requiredP
void HttpsServer::removeTopics(dl_t p) {
MQTTChecker& mqttCheck = MQTTChecker::getInstance();
for(const auto& g : p.configurator->getSensorGroups())
for(const auto& s : g->getSensors())
mqttCheck.removeTopic(s->getMqtt());
for(const auto& g : p.configurator->getSensorGroups()) {
mqttCheck.removeGroup(g->getGroupName());
for (const auto &s : g->getSensors()) {
mqttCheck.removeTopic(s->getMqtt());
mqttCheck.removeName(s->getName());
}
}
}
bool HttpsServer::checkTopics(dl_t p) {
MQTTChecker& mqttCheck = MQTTChecker::getInstance();
bool validTopics=true;
for(const auto& g : p.configurator->getSensorGroups())
for(const auto& s : g->getSensors())
if(!mqttCheck.checkTopic(s->getMqtt()))
for(const auto& g : p.configurator->getSensorGroups()) {
if (!mqttCheck.checkGroup(g->getGroupName()))
validTopics = false;
for (const auto &s : g->getSensors())
if (!mqttCheck.checkTopic(s->getMqtt()) || !mqttCheck.checkName(s->getName()))
validTopics = false;
}
return validTopics;
}
......
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