Browse Source

relay: fixup sub topic generator for older gcc

Also fix a logic bug where the vector element is not actually initialized
dev
Maxim Prokhorov 3 years ago
parent
commit
6f4a8387ef
1 changed files with 78 additions and 26 deletions
  1. +78
    -26
      code/espurna/relay.cpp

+ 78
- 26
code/espurna/relay.cpp View File

@ -1423,23 +1423,83 @@ const char* relayPayload(PayloadStatus status) {
#if MQTT_SUPPORT #if MQTT_SUPPORT
namespace {
// TODO: it *will* handle the duplicates, but we waste memory storing them
// TODO: mqttSubscribe(...) also happens multiple times
//
// this is not really an intended use-case though, but it is techically possible...
struct RelayCustomTopicBase {
RelayCustomTopicBase() = delete;
RelayCustomTopicBase(const RelayCustomTopicBase&) = delete;
RelayCustomTopicBase(RelayCustomTopicBase&& other) noexcept :
_value(std::move(other._value)),
_mode(other._mode)
{}
template <typename T>
RelayCustomTopicBase(T&& value, RelayMqttTopicMode mode) :
_value(std::forward<T>(value)),
_mode(mode)
{}
RelayCustomTopicBase& operator=(const char* const value) {
_value = value;
return *this;
}
RelayCustomTopicBase& operator=(const String& value) {
_value = value;
return *this;
}
RelayCustomTopicBase& operator=(String&& value) noexcept {
_value = std::move(value);
return *this;
}
RelayCustomTopicBase& operator=(RelayMqttTopicMode mode) noexcept {
_mode = mode;
return *this;
}
String&& get() && {
return std::move(_value);
}
const String& value() const {
return _value;
}
RelayMqttTopicMode mode() const {
return _mode;
}
private:
String _value;
RelayMqttTopicMode _mode;
};
struct RelayCustomTopic { struct RelayCustomTopic {
RelayCustomTopic() = delete; RelayCustomTopic() = delete;
RelayCustomTopic(const RelayCustomTopic&) = delete; RelayCustomTopic(const RelayCustomTopic&) = delete;
RelayCustomTopic(RelayCustomTopic&&) = delete; RelayCustomTopic(RelayCustomTopic&&) = delete;
template <typename T>
RelayCustomTopic(unsigned char id, T&& topic, RelayMqttTopicMode mode) :
RelayCustomTopic(size_t id, RelayCustomTopicBase&& base) :
_id(id), _id(id),
_topic(std::forward<T>(topic)),
_topic(std::move(base).get()),
_parts(_topic), _parts(_topic),
_mode(mode)
_mode(base.mode())
{} {}
unsigned char id() const { unsigned char id() const {
return _id; return _id;
} }
const char* const c_str() const {
return _topic.c_str();
}
const String& topic() const { const String& topic() const {
return _topic; return _topic;
} }
@ -1470,28 +1530,15 @@ private:
std::forward_list<RelayCustomTopic> _relay_custom_topics; std::forward_list<RelayCustomTopic> _relay_custom_topics;
// TODO: it *will* handle the duplicates, but we waste memory storing them
// TODO: mqttSubscribe(...) also happens multiple times
//
// this is not really an intended use-case though, but it is techically possible...
void _relayMqttSubscribeCustomTopics() { void _relayMqttSubscribeCustomTopics() {
const size_t relays { relayCount() }; const size_t relays { relayCount() };
if (!relays) { if (!relays) {
return; return;
} }
struct CustomTopic {
String value;
RelayMqttTopicMode mode;
};
std::vector<CustomTopic> topics;
topics.reserve(relays);
for (unsigned char id = 0; id < relays; ++id) {
topics[id].value = _relayMqttTopicSub(id);
topics[id].mode = _relayMqttTopicMode(id);
static std::vector<RelayCustomTopicBase> topics;
for (size_t id = 0; id < relays; ++id) {
topics.emplace_back(_relayMqttTopicSub(id), _relayMqttTopicMode(id));
} }
settings::kv_store.foreach([&](settings::kvs_type::KeyValueResult&& kv) { settings::kv_store.foreach([&](settings::kvs_type::KeyValueResult&& kv) {
@ -1512,26 +1559,29 @@ void _relayMqttSubscribeCustomTopics() {
if (key.startsWith(SubPrefix)) { if (key.startsWith(SubPrefix)) {
if (_relayTryParseId(key.c_str() + strlen(SubPrefix), id)) { if (_relayTryParseId(key.c_str() + strlen(SubPrefix), id)) {
topics[id].value = std::move(kv.value.read());
topics[id] = std::move(kv.value.read());
} }
} else if (key.startsWith(ModePrefix)) { } else if (key.startsWith(ModePrefix)) {
using namespace settings::internal; using namespace settings::internal;
if (_relayTryParseId(key.c_str() + strlen(ModePrefix), id)) { if (_relayTryParseId(key.c_str() + strlen(ModePrefix), id)) {
topics[id].mode = convert<RelayMqttTopicMode>(kv.value.read());
topics[id] = convert<RelayMqttTopicMode>(kv.value.read());
} }
} }
}); });
_relay_custom_topics.clear(); _relay_custom_topics.clear();
for (unsigned char id = 0; id < relays; ++id) { for (unsigned char id = 0; id < relays; ++id) {
auto& topic = topics[id];
if (!topic.value.length()) {
RelayCustomTopicBase& topic = topics[id];
auto& value = topic.value();
if (!value.length()) {
continue; continue;
} }
mqttSubscribeRaw(topic.value.c_str());
_relay_custom_topics.emplace_front(id, std::move(topic.value), topic.mode);
mqttSubscribeRaw(value.c_str());
_relay_custom_topics.emplace_front(id, std::move(topic));
} }
topics.clear();
} }
void _relayMqttPublishCustomTopic(unsigned char id) { void _relayMqttPublishCustomTopic(unsigned char id) {
@ -1550,6 +1600,8 @@ void _relayMqttPublishCustomTopic(unsigned char id) {
mqttSendRaw(topic.c_str(), relayPayload(status)); mqttSendRaw(topic.c_str(), relayPayload(status));
} }
} // namespace
void _relayMqttReport(unsigned char id) { void _relayMqttReport(unsigned char id) {
if (id < _relays.size()) { if (id < _relays.size()) {
if (_relays[id].report) { if (_relays[id].report) {


Loading…
Cancel
Save