added /list topic (fixes #277)
This commit is contained in:
@@ -558,12 +558,12 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string direction = topic.substr(pos+1);
|
string direction = topic.substr(pos+1);
|
||||||
bool isWrite = false;
|
|
||||||
if (direction.empty()) {
|
if (direction.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isWrite = direction == "set";
|
bool isWrite = direction == "set";
|
||||||
if (!isWrite && direction != "get") {
|
bool isList = !isWrite && direction == "list";
|
||||||
|
if (!isWrite && !isList && direction != "get") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,20 +571,30 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
|||||||
string remain = topic.substr(0, pos);
|
string remain = topic.substr(0, pos);
|
||||||
size_t last = 0;
|
size_t last = 0;
|
||||||
string circuit, name;
|
string circuit, name;
|
||||||
size_t idx;
|
bool finalField = false;
|
||||||
for (idx = 0; idx < g_topicStrs.size()+1; idx++) {
|
for (size_t idx = 0; idx < g_topicStrs.size()+1 && !finalField; idx++) {
|
||||||
string field;
|
string field;
|
||||||
string chk;
|
string chk;
|
||||||
if (idx < g_topicStrs.size()) {
|
if (idx < g_topicStrs.size()) {
|
||||||
chk = g_topicStrs[idx];
|
chk = g_topicStrs[idx];
|
||||||
pos = remain.find(chk, last);
|
pos = remain.find(chk, last);
|
||||||
if (pos == string::npos) {
|
if (pos == string::npos) {
|
||||||
|
if (!isList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (idx == 0 && remain+"/" == chk) { // check for only first prefix, e.g. "ebusd/"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = remain.size();
|
||||||
|
finalField = true;
|
||||||
|
}
|
||||||
} else if (idx-1 < g_topicFields.size()) {
|
} else if (idx-1 < g_topicFields.size()) {
|
||||||
pos = remain.size();
|
pos = remain.size();
|
||||||
} else if (last < remain.size()) {
|
} else if (last < remain.size()) {
|
||||||
|
if (!isList) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -596,8 +606,11 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (field.empty()) {
|
if (field.empty()) {
|
||||||
|
if (!isList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
string fieldName = g_topicFields[idx-1];
|
string fieldName = g_topicFields[idx-1];
|
||||||
if (fieldName == "circuit") {
|
if (fieldName == "circuit") {
|
||||||
circuit = field;
|
circuit = field;
|
||||||
@@ -610,10 +623,25 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isList) {
|
||||||
|
logOtherInfo("mqtt", "received list topic for %s %s", circuit.c_str(), name.c_str());
|
||||||
|
deque<Message*> messages;
|
||||||
|
m_messages->findAll(circuit, name, m_levels, true, true, true, true, true, true, 0, 0, false, &messages);
|
||||||
|
bool onlyWithData = !data.empty();
|
||||||
|
for (const auto message : messages) {
|
||||||
|
time_t lastup = message->getLastUpdateTime();
|
||||||
|
if (onlyWithData && lastup == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ostringstream ostream;
|
||||||
|
publishMessage(message, &ostream, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logOtherInfo("mqtt", "received topic for %s %s", circuit.c_str(), name.c_str());
|
logOtherInfo("mqtt", "received %s topic for %s %s", direction.c_str(), circuit.c_str(), name.c_str());
|
||||||
Message* message = m_messages->find(circuit, name, m_levels, isWrite);
|
Message* message = m_messages->find(circuit, name, m_levels, isWrite);
|
||||||
if (message == nullptr) {
|
if (message == nullptr) {
|
||||||
message = m_messages->find(circuit, name, m_levels, isWrite, true);
|
message = m_messages->find(circuit, name, m_levels, isWrite, true);
|
||||||
@@ -809,10 +837,15 @@ string MqttHandler::getTopic(const Message* message, const string& suffix, const
|
|||||||
return ret.str();
|
return ret.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandler::publishMessage(const Message* message, ostringstream* updates) {
|
void MqttHandler::publishMessage(const Message* message, ostringstream* updates, bool includeWithoutData) {
|
||||||
OutputFormat outputFormat = g_publishFormat;
|
OutputFormat outputFormat = g_publishFormat;
|
||||||
bool json = outputFormat & OF_JSON;
|
bool json = outputFormat & OF_JSON;
|
||||||
|
bool noData = includeWithoutData && message->getLastUpdateTime() == 0;
|
||||||
if (!m_publishByField) {
|
if (!m_publishByField) {
|
||||||
|
if (noData) {
|
||||||
|
publishEmptyTopic(getTopic(message)); // alternatively: , json ? "null" : "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
*updates << "{";
|
*updates << "{";
|
||||||
}
|
}
|
||||||
@@ -833,6 +866,10 @@ void MqttHandler::publishMessage(const Message* message, ostringstream* updates)
|
|||||||
}
|
}
|
||||||
for (size_t index = 0; index < message->getFieldCount(); index++) {
|
for (size_t index = 0; index < message->getFieldCount(); index++) {
|
||||||
string name = message->getFieldName(index);
|
string name = message->getFieldName(index);
|
||||||
|
if (noData) {
|
||||||
|
publishEmptyTopic(getTopic(message, "", name)); // alternatively: , json ? "null" : "");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
result_t result = message->decodeLastData(false, nullptr, index, outputFormat, updates);
|
result_t result = message->decodeLastData(false, nullptr, index, outputFormat, updates);
|
||||||
if (result != RESULT_OK) {
|
if (result != RESULT_OK) {
|
||||||
logOtherError("mqtt", "decode %s %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
logOtherError("mqtt", "decode %s %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||||
@@ -850,8 +887,14 @@ void MqttHandler::publishTopic(const string& topic, const string& data, bool ret
|
|||||||
const char* dataStr = data.c_str();
|
const char* dataStr = data.c_str();
|
||||||
const size_t len = strlen(dataStr);
|
const size_t len = strlen(dataStr);
|
||||||
logOtherDebug("mqtt", "publish %s %s", topicStr, dataStr);
|
logOtherDebug("mqtt", "publish %s %s", topicStr, dataStr);
|
||||||
check(mosquitto_publish(m_mosquitto, nullptr, topic.c_str(), (uint32_t)len,
|
check(mosquitto_publish(m_mosquitto, nullptr, topicStr, (uint32_t)len,
|
||||||
reinterpret_cast<const uint8_t*>(dataStr), 0, g_retain || retain), "publish");
|
reinterpret_cast<const uint8_t*>(dataStr), 0, g_retain || retain), "publish");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MqttHandler::publishEmptyTopic(const string& topic) {
|
||||||
|
const char* topicStr = topic.c_str();
|
||||||
|
logOtherDebug("mqtt", "publish empty %s", topicStr);
|
||||||
|
check(mosquitto_publish(m_mosquitto, nullptr, topicStr, 0, nullptr, 0, g_retain), "publish empty");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ebusd
|
} // namespace ebusd
|
||||||
|
|||||||
@@ -117,8 +117,9 @@ class MqttHandler : public DataSink, public DataSource, public WaitThread {
|
|||||||
* Prepare a @a Message and publish as topic.
|
* Prepare a @a Message and publish as topic.
|
||||||
* @param message the @a Message to publish.
|
* @param message the @a Message to publish.
|
||||||
* @param updates the @a ostringstream for preparation.
|
* @param updates the @a ostringstream for preparation.
|
||||||
|
* @param includeWithoutData whether to publish messages without data as well.
|
||||||
*/
|
*/
|
||||||
void publishMessage(const Message* message, ostringstream* updates);
|
void publishMessage(const Message* message, ostringstream* updates, bool includeWithoutData = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish a topic update to MQTT.
|
* Publish a topic update to MQTT.
|
||||||
@@ -128,6 +129,12 @@ class MqttHandler : public DataSink, public DataSource, public WaitThread {
|
|||||||
*/
|
*/
|
||||||
void publishTopic(const string& topic, const string& data, bool retain = false);
|
void publishTopic(const string& topic, const string& data, bool retain = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a topic update to MQTT without any data.
|
||||||
|
* @param topic the topic string.
|
||||||
|
*/
|
||||||
|
void publishEmptyTopic(const string& topic);
|
||||||
|
|
||||||
/** the @a MessageMap instance. */
|
/** the @a MessageMap instance. */
|
||||||
MessageMap* m_messages;
|
MessageMap* m_messages;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user