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