mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
fix publish, added subscriptions to show mqtt. Subscribe to cmd during initialization
This commit is contained in:
48
src/mqtt.cpp
48
src/mqtt.cpp
@@ -93,6 +93,11 @@ void Mqtt::subscribe(const uint8_t device_id, const std::string & topic, mqtt_fu
|
|||||||
queue_subscribe_message(topic); // add subscription to queue
|
queue_subscribe_message(topic); // add subscription to queue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subscribe to an MQTT topic, and store the associated callback function. For generic functions not tied to a specific device
|
||||||
|
void Mqtt::subscribe(const std::string & topic, mqtt_function_p cb) {
|
||||||
|
subscribe(0, topic, cb); // no device_id needed, if generic to EMS-ESP
|
||||||
|
}
|
||||||
|
|
||||||
// resubscribe to all MQTT topics again
|
// resubscribe to all MQTT topics again
|
||||||
void Mqtt::resubscribe() {
|
void Mqtt::resubscribe() {
|
||||||
if (mqtt_functions_.empty()) {
|
if (mqtt_functions_.empty()) {
|
||||||
@@ -104,11 +109,6 @@ void Mqtt::resubscribe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// subscribe to an MQTT topic, and store the associated callback function. For generic functions not tied to a specific device
|
|
||||||
void Mqtt::subscribe(const std::string & topic, mqtt_function_p cb) {
|
|
||||||
subscribe(0, topic, cb); // no device_id needed, if generic to EMS-ESP
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main MQTT loop
|
// Main MQTT loop
|
||||||
// Checks for connection, establishes a connection if not
|
// Checks for connection, establishes a connection if not
|
||||||
// sends out top item on publish queue
|
// sends out top item on publish queue
|
||||||
@@ -138,6 +138,13 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(F("MQTT publish fails: %lu"), mqtt_publish_fails_);
|
shell.printfln(F("MQTT publish fails: %lu"), mqtt_publish_fails_);
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
|
// show subscriptions
|
||||||
|
shell.printfln(F("MQTT subscriptions:"));
|
||||||
|
for (const auto & mqtt_function : mqtt_functions_) {
|
||||||
|
shell.printfln(F(" %s"), mqtt_function.topic_.c_str());
|
||||||
|
}
|
||||||
|
shell.println();
|
||||||
|
|
||||||
// show queues
|
// show queues
|
||||||
if (mqtt_messages_.empty()) {
|
if (mqtt_messages_.empty()) {
|
||||||
shell.printfln(F("MQTT queue is empty"));
|
shell.printfln(F("MQTT queue is empty"));
|
||||||
@@ -283,13 +290,16 @@ void Mqtt::start(AsyncMqttClient * mqttClient) {
|
|||||||
mqtt_qos_ = mqttSettings.mqtt_qos;
|
mqtt_qos_ = mqttSettings.mqtt_qos;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
mqttClient_->onConnect([this](bool sessionPresent) { on_connect(); });
|
mqttClient_->onConnect([this](bool sessionPresent) { on_connect(); });
|
||||||
mqttClient_->setWill(make_topic(will_topic_, "status"), 1, true, "offline"); // with qos 1, retain true
|
mqttClient_->setWill(make_topic(will_topic_, "status"), 1, true, "offline"); // with qos 1, retain true
|
||||||
mqttClient_->onMessage([this](char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
mqttClient_->onMessage([this](char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||||
on_message(topic, payload, len);
|
on_message(topic, payload, len);
|
||||||
mqttClient_->onPublish([this](uint16_t packetId) { on_publish(packetId); });
|
mqttClient_->onPublish([this](uint16_t packetId) { on_publish(packetId); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// add the system MQTT subscriptions
|
||||||
|
Mqtt::subscribe("cmd", System::mqtt_commands);
|
||||||
|
// Mqtt::subscribe("cmd", std::bind(&System::mqtt_commands, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::set_publish_time(uint16_t publish_time) {
|
void Mqtt::set_publish_time(uint16_t publish_time) {
|
||||||
@@ -327,7 +337,11 @@ void Mqtt::queue_publish_message(const std::string & topic, const std::string &
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message = std::make_shared<MqttMessage>(Operation::PUBLISH, topic, payload, retain);
|
// prefix the hostname to the topic
|
||||||
|
char full_topic[MQTT_TOPIC_MAX_SIZE];
|
||||||
|
make_topic(full_topic, topic);
|
||||||
|
|
||||||
|
auto message = std::make_shared<MqttMessage>(Operation::PUBLISH, full_topic, payload, retain);
|
||||||
|
|
||||||
// if the queue is full, make room but removing the last one
|
// if the queue is full, make room but removing the last one
|
||||||
if (mqtt_messages_.size() >= maximum_mqtt_messages_) {
|
if (mqtt_messages_.size() >= maximum_mqtt_messages_) {
|
||||||
@@ -396,17 +410,12 @@ void Mqtt::process_queue() {
|
|||||||
auto mqtt_message = mqtt_messages_.front();
|
auto mqtt_message = mqtt_messages_.front();
|
||||||
auto message = mqtt_message.content_;
|
auto message = mqtt_message.content_;
|
||||||
|
|
||||||
// append the hostname to the topic, unless we're doing native HA which has a different format
|
|
||||||
// if the topic starts with "homeassistant" we leave it untouched, otherwise append host
|
|
||||||
char full_topic[MQTT_TOPIC_MAX_SIZE];
|
|
||||||
make_topic(full_topic, message->topic);
|
|
||||||
|
|
||||||
// if we're subscribing...
|
// if we're subscribing...
|
||||||
if (message->operation == Operation::SUBSCRIBE) {
|
if (message->operation == Operation::SUBSCRIBE) {
|
||||||
LOG_DEBUG(F("Subscribing to topic: %s"), full_topic);
|
LOG_DEBUG(F("Subscribing to topic: %s"), message->topic.c_str());
|
||||||
uint16_t packet_id = mqttClient_->subscribe(full_topic, mqtt_qos_);
|
uint16_t packet_id = mqttClient_->subscribe(message->topic.c_str(), mqtt_qos_);
|
||||||
if (!packet_id) {
|
if (!packet_id) {
|
||||||
LOG_DEBUG(F("Error subscribing to %s, error %d"), full_topic, packet_id);
|
LOG_DEBUG(F("Error subscribing to %s, error %d"), message->topic.c_str(), packet_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
mqtt_messages_.pop_front(); // remove the message from the queue
|
mqtt_messages_.pop_front(); // remove the message from the queue
|
||||||
@@ -421,19 +430,20 @@ void Mqtt::process_queue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// else try and publish it
|
// else try and publish it
|
||||||
uint16_t packet_id = mqttClient_->publish(full_topic, mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
|
uint16_t packet_id =
|
||||||
LOG_DEBUG(F("Publishing topic %s (#%02d, attempt #%d, pid %d)"), full_topic, mqtt_message.id_, mqtt_message.retry_count_ + 1, packet_id);
|
mqttClient_->publish(message->topic.c_str(), mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
|
||||||
|
LOG_DEBUG(F("Publishing topic %s (#%02d, attempt #%d, pid %d)"), message->topic.c_str(), mqtt_message.id_, mqtt_message.retry_count_ + 1, packet_id);
|
||||||
|
|
||||||
if (packet_id == 0) {
|
if (packet_id == 0) {
|
||||||
// it failed. if we retried n times, give up. remove from queue
|
// it failed. if we retried n times, give up. remove from queue
|
||||||
if (mqtt_message.retry_count_ == (MQTT_PUBLISH_MAX_RETRY - 1)) {
|
if (mqtt_message.retry_count_ == (MQTT_PUBLISH_MAX_RETRY - 1)) {
|
||||||
LOG_ERROR(F("Failed to publish to %s after %d attempts"), full_topic, mqtt_message.retry_count_ + 1);
|
LOG_ERROR(F("Failed to publish to %s after %d attempts"), message->topic.c_str(), mqtt_message.retry_count_ + 1);
|
||||||
mqtt_publish_fails_++; // increment failure counter
|
mqtt_publish_fails_++; // increment failure counter
|
||||||
mqtt_messages_.pop_front(); // delete
|
mqtt_messages_.pop_front(); // delete
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
mqtt_messages_.front().retry_count_++;
|
mqtt_messages_.front().retry_count_++;
|
||||||
LOG_DEBUG(F("Failed to publish to %s. Trying again, #%d"), full_topic, mqtt_message.retry_count_ + 1);
|
LOG_DEBUG(F("Failed to publish to %s. Trying again, #%d"), message->topic.c_str(), mqtt_message.retry_count_ + 1);
|
||||||
return; // leave on queue for next time so it gets republished
|
return; // leave on queue for next time so it gets republished
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user