ESPHome 2025.5.0
Loading...
Searching...
No Matches
mqtt_backend_esp32.cpp
Go to the documentation of this file.
2
3#ifdef USE_MQTT
4#ifdef USE_ESP32
5
6#include <string>
7#include "esphome/core/log.h"
9
10namespace esphome {
11namespace mqtt {
12
13static const char *const TAG = "mqtt.idf";
14
16#if ESP_IDF_VERSION_MAJOR < 5
17 mqtt_cfg_.user_context = (void *) this;
18 mqtt_cfg_.buffer_size = MQTT_BUFFER_SIZE;
19
20 mqtt_cfg_.host = this->host_.c_str();
21 mqtt_cfg_.port = this->port_;
22 mqtt_cfg_.keepalive = this->keep_alive_;
23 mqtt_cfg_.disable_clean_session = !this->clean_session_;
24
25 if (!this->username_.empty()) {
26 mqtt_cfg_.username = this->username_.c_str();
27 if (!this->password_.empty()) {
28 mqtt_cfg_.password = this->password_.c_str();
29 }
30 }
31
32 if (!this->lwt_topic_.empty()) {
33 mqtt_cfg_.lwt_topic = this->lwt_topic_.c_str();
34 this->mqtt_cfg_.lwt_qos = this->lwt_qos_;
35 this->mqtt_cfg_.lwt_retain = this->lwt_retain_;
36
37 if (!this->lwt_message_.empty()) {
38 mqtt_cfg_.lwt_msg = this->lwt_message_.c_str();
39 mqtt_cfg_.lwt_msg_len = this->lwt_message_.size();
40 }
41 }
42
43 if (!this->client_id_.empty()) {
44 mqtt_cfg_.client_id = this->client_id_.c_str();
45 }
47 mqtt_cfg_.cert_pem = ca_certificate_.value().c_str();
48 mqtt_cfg_.skip_cert_common_name_check = skip_cert_cn_check_;
49 mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_SSL;
50
51 if (this->cl_certificate_.has_value() && this->cl_key_.has_value()) {
52 mqtt_cfg_.client_cert_pem = this->cl_certificate_.value().c_str();
53 mqtt_cfg_.client_key_pem = this->cl_key_.value().c_str();
54 }
55 } else {
56 mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_TCP;
57 }
58#else
59 mqtt_cfg_.broker.address.hostname = this->host_.c_str();
60 mqtt_cfg_.broker.address.port = this->port_;
61 mqtt_cfg_.session.keepalive = this->keep_alive_;
62 mqtt_cfg_.session.disable_clean_session = !this->clean_session_;
63
64 if (!this->username_.empty()) {
65 mqtt_cfg_.credentials.username = this->username_.c_str();
66 if (!this->password_.empty()) {
67 mqtt_cfg_.credentials.authentication.password = this->password_.c_str();
68 }
69 }
70
71 if (!this->lwt_topic_.empty()) {
72 mqtt_cfg_.session.last_will.topic = this->lwt_topic_.c_str();
73 this->mqtt_cfg_.session.last_will.qos = this->lwt_qos_;
74 this->mqtt_cfg_.session.last_will.retain = this->lwt_retain_;
75
76 if (!this->lwt_message_.empty()) {
77 mqtt_cfg_.session.last_will.msg = this->lwt_message_.c_str();
78 mqtt_cfg_.session.last_will.msg_len = this->lwt_message_.size();
79 }
80 }
81
82 if (!this->client_id_.empty()) {
83 mqtt_cfg_.credentials.client_id = this->client_id_.c_str();
84 }
86 mqtt_cfg_.broker.verification.certificate = ca_certificate_.value().c_str();
87 mqtt_cfg_.broker.verification.skip_cert_common_name_check = skip_cert_cn_check_;
88 mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_SSL;
89
90 if (this->cl_certificate_.has_value() && this->cl_key_.has_value()) {
91 mqtt_cfg_.credentials.authentication.certificate = this->cl_certificate_.value().c_str();
92 mqtt_cfg_.credentials.authentication.key = this->cl_key_.value().c_str();
93 }
94 } else {
95 mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_TCP;
96 }
97#endif
98 auto *mqtt_client = esp_mqtt_client_init(&mqtt_cfg_);
99 if (mqtt_client) {
100 handler_.reset(mqtt_client);
101 is_initalized_ = true;
102 esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, this);
103 return true;
104 } else {
105 ESP_LOGE(TAG, "Failed to initialize IDF-MQTT");
106 return false;
107 }
108}
109
111 // process new events
112 // handle only 1 message per loop iteration
113 if (!mqtt_events_.empty()) {
114 auto &event = mqtt_events_.front();
115 mqtt_event_handler_(event);
116 mqtt_events_.pop();
117 }
118}
119
121 ESP_LOGV(TAG, "Event dispatched from event loop event_id=%d", event.event_id);
122 switch (event.event_id) {
123 case MQTT_EVENT_BEFORE_CONNECT:
124 ESP_LOGV(TAG, "MQTT_EVENT_BEFORE_CONNECT");
125 break;
126
127 case MQTT_EVENT_CONNECTED:
128 ESP_LOGV(TAG, "MQTT_EVENT_CONNECTED");
129 this->is_connected_ = true;
130 this->on_connect_.call(event.session_present);
131 break;
132 case MQTT_EVENT_DISCONNECTED:
133 ESP_LOGV(TAG, "MQTT_EVENT_DISCONNECTED");
134 // TODO is there a way to get the disconnect reason?
135 this->is_connected_ = false;
137 break;
138
139 case MQTT_EVENT_SUBSCRIBED:
140 ESP_LOGV(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event.msg_id);
141 // hardcode QoS to 0. QoS is not used in this context but required to mirror the AsyncMqtt interface
142 this->on_subscribe_.call((int) event.msg_id, 0);
143 break;
144 case MQTT_EVENT_UNSUBSCRIBED:
145 ESP_LOGV(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event.msg_id);
146 this->on_unsubscribe_.call((int) event.msg_id);
147 break;
148 case MQTT_EVENT_PUBLISHED:
149 ESP_LOGV(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event.msg_id);
150 this->on_publish_.call((int) event.msg_id);
151 break;
152 case MQTT_EVENT_DATA: {
153 static std::string topic;
154 if (!event.topic.empty()) {
155 topic = event.topic;
156 }
157 ESP_LOGV(TAG, "MQTT_EVENT_DATA %s", topic.c_str());
158 this->on_message_.call(!event.topic.empty() ? topic.c_str() : nullptr, event.data.data(), event.data.size(),
159 event.current_data_offset, event.total_data_len);
160 } break;
161 case MQTT_EVENT_ERROR:
162 ESP_LOGE(TAG, "MQTT_EVENT_ERROR");
163 if (event.error_handle.error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
164 ESP_LOGE(TAG, "Last error code reported from esp-tls: 0x%x", event.error_handle.esp_tls_last_esp_err);
165 ESP_LOGE(TAG, "Last tls stack error number: 0x%x", event.error_handle.esp_tls_stack_err);
166 ESP_LOGE(TAG, "Last captured errno : %d (%s)", event.error_handle.esp_transport_sock_errno,
167 strerror(event.error_handle.esp_transport_sock_errno));
168 } else if (event.error_handle.error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
169 ESP_LOGE(TAG, "Connection refused error: 0x%x", event.error_handle.connect_return_code);
170 } else {
171 ESP_LOGE(TAG, "Unknown error type: 0x%x", event.error_handle.error_type);
172 }
173 break;
174 default:
175 ESP_LOGV(TAG, "Other event id:%d", event.event_id);
176 break;
177 }
178}
179
181void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id,
182 void *event_data) {
183 MQTTBackendESP32 *instance = static_cast<MQTTBackendESP32 *>(handler_args);
184 // queue event to decouple processing
185 if (instance) {
186 auto event = *static_cast<esp_mqtt_event_t *>(event_data);
187 instance->mqtt_events_.emplace(event);
188 }
189}
190
191} // namespace mqtt
192} // namespace esphome
193#endif // USE_ESP32
194#endif
CallbackManager< on_connect_callback_t > on_connect_
CallbackManager< on_disconnect_callback_t > on_disconnect_
CallbackManager< on_message_callback_t > on_message_
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
static - Dispatch event to instance method
optional< std::string > ca_certificate_
CallbackManager< on_subscribe_callback_t > on_subscribe_
CallbackManager< on_unsubscribe_callback_t > on_unsubscribe_
esp_mqtt_client_config_t mqtt_cfg_
CallbackManager< on_publish_user_callback_t > on_publish_
void mqtt_event_handler_(const Event &event)
optional< std::string > cl_certificate_
bool has_value() const
Definition optional.h:87
value_type const & value() const
Definition optional.h:89
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint8_t event_id
Definition tt21100.cpp:3