From 7337dd9e52b50e627c8f14599ba90d6fd26b69ab Mon Sep 17 00:00:00 2001 From: John Date: Sat, 12 Feb 2022 09:11:03 +0100 Subject: [PATCH] add option to auto-adjust poll prio of matched messages from integration --- contrib/etc/ebusd/mqtt-hassio.cfg | 8 ++++--- contrib/etc/ebusd/mqtt-integration.cfg | 4 +++- src/ebusd/mqtthandler.cpp | 31 +++++++++++++++++++------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/contrib/etc/ebusd/mqtt-hassio.cfg b/contrib/etc/ebusd/mqtt-hassio.cfg index 078dd070..437941ab 100644 --- a/contrib/etc/ebusd/mqtt-hassio.cfg +++ b/contrib/etc/ebusd/mqtt-hassio.cfg @@ -92,9 +92,11 @@ # - "$" matches the end of the input, e.g. "al$" matches "hal" but not "all". # - "*" matches a single arbitrary length wildcard part in the middle, e.g. "^a*l$" matches "all" but not "always". -# include only messages having data sent at least once (only checked for passive or read messages, not for active write). -# HA integration: filtering only seen messages to avoid unnecessary "pollution" -filter-seen = 1 +# include only messages having data sent at least once (only checked for passive or read messages, not for active write) +# when set to 1. If set to >1, then all messages passing the other filter criteria (including active read messages) will +# automatically be set to have a poll priority of at most this value, so these are automatically being polled. +# HA integration: filtering only seen messages to avoid unnecessary "pollution" and auto-poll all matched messages +filter-seen = 2 # include only messages having a priority less than or equal to the specified value. #filter-priority = # include only messages having the specified circuit (partial match, alternatives and wildcard supported). diff --git a/contrib/etc/ebusd/mqtt-integration.cfg b/contrib/etc/ebusd/mqtt-integration.cfg index 44f11dac..96c8fb0f 100644 --- a/contrib/etc/ebusd/mqtt-integration.cfg +++ b/contrib/etc/ebusd/mqtt-integration.cfg @@ -86,7 +86,9 @@ # - "$" matches the end of the input, e.g. "al$" matches "hal" but not "all". # - "*" matches a single arbitrary length wildcard part in the middle, e.g. "^a*l$" matches "all" but not "always". -# include only messages having data sent at least once (only checked for passive or read messages, not for active write). +# include only messages having data sent at least once (only checked for passive or read messages, not for active write) +# when set to 1. If set to >1, then all messages passing the other filter criteria (including active read messages) will +# automatically be set to have a poll priority of at most this value, so these are automatically being polled. filter-seen = 1 # include only messages having a priority less than or equal to the specified value. #filter-priority = diff --git a/src/ebusd/mqtthandler.cpp b/src/ebusd/mqtthandler.cpp index 3a9d1505..1889088e 100755 --- a/src/ebusd/mqtthandler.cpp +++ b/src/ebusd/mqtthandler.cpp @@ -651,7 +651,6 @@ ssize_t MqttReplacer::matchTopic(const string& topic, string* circuit, string* n } string value; if (idx+1 < count) { - // TODO require topic fields to be separated by non-empty string? e.g. %circuit%name is not parseable here size_t pos = topic.find(m_parts[idx+1].first, last); if (pos == string::npos) { // next part not found @@ -1324,7 +1323,7 @@ void MqttHandler::run() { string uptimeTopic = m_globalTopic.get("", "uptime"); ostringstream updates; unsigned int filterPriority = 0; - bool filterSeen = false; + unsigned int filterSeen = 0; string filterCircuit, filterName, filterLevel, filterField, filterDirection; vector typeSwitchNames; if (m_hasDefinitionTopic) { @@ -1333,7 +1332,10 @@ void MqttHandler::run() { if (result != RESULT_OK) { filterPriority = 0; } - filterSeen = parseBool(m_replacers["filter-seen"]); + filterSeen = parseInt(m_replacers["filter-seen"].c_str(), 10, 0, 9, &result); + if (result != RESULT_OK) { + filterSeen = 0; + } filterCircuit = m_replacers["filter-circuit"]; FileReader::tolower(&filterCircuit); filterName = m_replacers["filter-name"]; @@ -1395,12 +1397,22 @@ void MqttHandler::run() { deque messages; m_messages->findAll("", "", m_levels, false, true, true, true, true, true, 0, 0, false, &messages); for (const auto& message : messages) { - if (filterSeen) { + bool checkPollAdjust = false; + if (filterSeen > 0) { if (message->getLastUpdateTime()==0) { - if (message->isPassive() || !message->isWrite()) { - // only wait for data on passive or read messages + if (message->isPassive()) { + // only wait for data on passive messages continue; // no data ever } + if (!message->isWrite()) { + // only wait for data on read messages or set their poll prio + if (filterSeen > 1 && (!message->getPollPriority() || message->getPollPriority() > filterSeen)) { + // check for poll prio adjustment after all other filters + checkPollAdjust = true; + } else { + continue; // no poll adjustment + } + } } if (message->getDataHandlerState()==1) { // already seen in the past, check for poll prio update @@ -1412,8 +1424,7 @@ void MqttHandler::run() { } else if (message->getCreateTime() <= m_definitionsSince) { // only newer defined continue; } - if ((filterPriority>0 && (message->getPollPriority()==0 || message->getPollPriority()>filterPriority)) - || !FileReader::matches(message->getCircuit(), filterCircuit, true, true) + if (!FileReader::matches(message->getCircuit(), filterCircuit, true, true) || !FileReader::matches(message->getName(), filterName, true, true) || !FileReader::matches(message->getLevel(), filterLevel, true, true)) { continue; @@ -1422,6 +1433,10 @@ void MqttHandler::run() { if (!FileReader::matches(direction, filterDirection, true, true)) { continue; } + if ((checkPollAdjust && !message->setPollPriority(filterSeen)) + || (filterPriority>0 && (message->getPollPriority()==0 || message->getPollPriority()>filterPriority))) { + continue; + } MqttReplacers msgValues = m_replacers; // need a copy here as the contents are manipulated msgValues.set("circuit", message->getCircuit());