ESPHome  2024.11.0
mqtt_backend_esp32.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "mqtt_backend.h"
4 #ifdef USE_MQTT
5 #ifdef USE_ESP32
6 
7 #include <string>
8 #include <queue>
9 #include <mqtt_client.h>
11 #include "esphome/core/helpers.h"
12 
13 namespace esphome {
14 namespace mqtt {
15 
16 struct Event {
17  esp_mqtt_event_id_t event_id;
18  std::vector<char> data;
21  std::string topic;
22  int msg_id;
23  bool retain;
24  int qos;
25  bool dup;
27  esp_mqtt_error_codes_t error_handle;
28 
29  // Construct from esp_mqtt_event_t
30  // Any pointer values that are unsafe to keep are converted to safe copies
31  Event(const esp_mqtt_event_t &event)
32  : event_id(event.event_id),
33  data(event.data, event.data + event.data_len),
34  total_data_len(event.total_data_len),
35  current_data_offset(event.current_data_offset),
36  topic(event.topic, event.topic_len),
37  msg_id(event.msg_id),
38  retain(event.retain),
39  qos(event.qos),
40  dup(event.dup),
41  session_present(event.session_present),
42  error_handle(*event.error_handle) {}
43 };
44 
45 class MQTTBackendESP32 final : public MQTTBackend {
46  public:
47  static const size_t MQTT_BUFFER_SIZE = 4096;
48 
49  void set_keep_alive(uint16_t keep_alive) final { this->keep_alive_ = keep_alive; }
50  void set_client_id(const char *client_id) final { this->client_id_ = client_id; }
51  void set_clean_session(bool clean_session) final { this->clean_session_ = clean_session; }
52 
53  void set_credentials(const char *username, const char *password) final {
54  if (username)
55  this->username_ = username;
56  if (password)
57  this->password_ = password;
58  }
59  void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final {
60  if (topic)
61  this->lwt_topic_ = topic;
62  this->lwt_qos_ = qos;
63  if (payload)
64  this->lwt_message_ = payload;
65  this->lwt_retain_ = retain;
66  }
67  void set_server(network::IPAddress ip, uint16_t port) final {
68  this->host_ = ip.str();
69  this->port_ = port;
70  }
71  void set_server(const char *host, uint16_t port) final {
72  this->host_ = host;
73  this->port_ = port;
74  }
75  void set_on_connect(std::function<on_connect_callback_t> &&callback) final {
76  this->on_connect_.add(std::move(callback));
77  }
78  void set_on_disconnect(std::function<on_disconnect_callback_t> &&callback) final {
79  this->on_disconnect_.add(std::move(callback));
80  }
81  void set_on_subscribe(std::function<on_subscribe_callback_t> &&callback) final {
82  this->on_subscribe_.add(std::move(callback));
83  }
84  void set_on_unsubscribe(std::function<on_unsubscribe_callback_t> &&callback) final {
85  this->on_unsubscribe_.add(std::move(callback));
86  }
87  void set_on_message(std::function<on_message_callback_t> &&callback) final {
88  this->on_message_.add(std::move(callback));
89  }
90  void set_on_publish(std::function<on_publish_user_callback_t> &&callback) final {
91  this->on_publish_.add(std::move(callback));
92  }
93  bool connected() const final { return this->is_connected_; }
94 
95  void connect() final {
96  if (!is_initalized_) {
97  if (initialize_()) {
98  esp_mqtt_client_start(handler_.get());
99  }
100  }
101  }
102  void disconnect() final {
103  if (is_initalized_)
104  esp_mqtt_client_disconnect(handler_.get());
105  }
106 
107  bool subscribe(const char *topic, uint8_t qos) final {
108  return esp_mqtt_client_subscribe(handler_.get(), topic, qos) != -1;
109  }
110  bool unsubscribe(const char *topic) final { return esp_mqtt_client_unsubscribe(handler_.get(), topic) != -1; }
111 
112  bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain) final {
113 #if defined(USE_MQTT_IDF_ENQUEUE)
114  // use the non-blocking version
115  // it can delay sending a couple of seconds but won't block
116  return esp_mqtt_client_enqueue(handler_.get(), topic, payload, length, qos, retain, true) != -1;
117 #else
118  // might block for several seconds, either due to network timeout (10s)
119  // or if publishing payloads longer than internal buffer (due to message fragmentation)
120  return esp_mqtt_client_publish(handler_.get(), topic, payload, length, qos, retain) != -1;
121 #endif
122  }
123  using MQTTBackend::publish;
124 
125  void loop() final;
126 
127  void set_ca_certificate(const std::string &cert) { ca_certificate_ = cert; }
128  void set_cl_certificate(const std::string &cert) { cl_certificate_ = cert; }
129  void set_cl_key(const std::string &key) { cl_key_ = key; }
130  void set_skip_cert_cn_check(bool skip_check) { skip_cert_cn_check_ = skip_check; }
131 
132  protected:
133  bool initialize_();
134  void mqtt_event_handler_(const Event &event);
135  static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
136 
138  void operator()(esp_mqtt_client *client_handler) { esp_mqtt_client_destroy(client_handler); }
139  };
140  using ClientHandler_ = std::unique_ptr<esp_mqtt_client, MqttClientDeleter>;
142 
143  bool is_connected_{false};
144  bool is_initalized_{false};
145 
146  esp_mqtt_client_config_t mqtt_cfg_{};
147 
148  std::string host_;
149  uint16_t port_;
150  std::string username_;
151  std::string password_;
152  std::string lwt_topic_;
153  std::string lwt_message_;
154  uint8_t lwt_qos_;
156  std::string client_id_;
157  uint16_t keep_alive_;
162  bool skip_cert_cn_check_{false};
163 
164  // callbacks
171  std::queue<Event> mqtt_events_;
172 };
173 
174 } // namespace mqtt
175 } // namespace esphome
176 
177 #endif
178 #endif
void operator()(esp_mqtt_client *client_handler)
void loop()
CallbackManager< on_subscribe_callback_t > on_subscribe_
void set_on_disconnect(std::function< on_disconnect_callback_t > &&callback) final
void set_on_publish(std::function< on_publish_user_callback_t > &&callback) final
void set_server(const char *host, uint16_t port) final
Event(const esp_mqtt_event_t &event)
bool unsubscribe(const char *topic) final
void set_server(network::IPAddress ip, uint16_t port) final
optional< std::string > ca_certificate_
void set_on_subscribe(std::function< on_subscribe_callback_t > &&callback) final
void set_client_id(const char *client_id) final
CallbackManager< on_unsubscribe_callback_t > on_unsubscribe_
void set_cl_key(const std::string &key)
void set_ca_certificate(const std::string &cert)
std::unique_ptr< esp_mqtt_client, MqttClientDeleter > ClientHandler_
void set_credentials(const char *username, const char *password) final
void set_keep_alive(uint16_t keep_alive) final
esp_mqtt_error_codes_t error_handle
void set_clean_session(bool clean_session) final
std::vector< char > data
void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final
void set_on_unsubscribe(std::function< on_unsubscribe_callback_t > &&callback) final
void set_skip_cert_cn_check(bool skip_check)
bool subscribe(const char *topic, uint8_t qos) final
CallbackManager< on_connect_callback_t > on_connect_
void set_on_message(std::function< on_message_callback_t > &&callback) final
esp_mqtt_event_id_t event_id
bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain) final
CallbackManager< on_message_callback_t > on_message_
CallbackManager< on_publish_user_callback_t > on_publish_
uint16_t length
Definition: tt21100.cpp:12
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void set_cl_certificate(const std::string &cert)
uint8_t event_id
Definition: tt21100.cpp:15
CallbackManager< on_disconnect_callback_t > on_disconnect_
optional< std::string > cl_certificate_
optional< std::string > cl_key_
void set_on_connect(std::function< on_connect_callback_t > &&callback) final
virtual bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain)=0