Skip to content

Commit d979e1b

Browse files
committed
fix(mqtt_cxx): Fix to construct in two steps
to avoid issues with receiving initial (on-connect) event before construction Closes #631
1 parent 9f9c6c1 commit d979e1b

File tree

5 files changed

+53
-4
lines changed

5 files changed

+53
-4
lines changed

components/esp_mqtt_cxx/esp_mqtt_cxx.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -163,7 +163,20 @@ Client::Client(esp_mqtt_client_config_t const &config) : handler(esp_mqtt_clien
163163
throw MQTTException(ESP_FAIL);
164164
};
165165
CHECK_THROW_SPECIFIC(esp_mqtt_client_register_event(handler.get(), MQTT_EVENT_ANY, mqtt_event_handler, this), mqtt::MQTTException);
166+
}
167+
168+
void Client::start()
169+
{
170+
if (started) {
171+
return;
172+
}
166173
CHECK_THROW_SPECIFIC(esp_mqtt_client_start(handler.get()), mqtt::MQTTException);
174+
started = true;
175+
}
176+
177+
bool Client::is_started() const noexcept
178+
{
179+
return started;
167180
}
168181

169182
void Client::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) noexcept
@@ -247,6 +260,18 @@ void Client::on_data(esp_mqtt_event_handle_t const event)
247260
{
248261
}
249262

263+
void Client::dispatch_event_for_test(int32_t event_id, esp_mqtt_event_t *event)
264+
{
265+
if (event == nullptr) {
266+
throw MQTTException(ESP_ERR_INVALID_ARG);
267+
}
268+
event->event_id = static_cast<esp_mqtt_event_id_t>(event_id);
269+
auto err = esp_mqtt_dispatch_custom_event(handler.get(), event);
270+
if (err != ESP_OK) {
271+
throw MQTTException(err);
272+
}
273+
}
274+
250275
std::optional<MessageID> Client::subscribe(std::string const &topic, QoS qos)
251276
{
252277
auto res = esp_mqtt_client_subscribe(handler.get(), topic.c_str(),

components/esp_mqtt_cxx/examples/ssl/main/mqtt_ssl_example.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ extern "C" void app_main(void)
8383
idf::mqtt::Configuration config{};
8484

8585
MyClient client{broker, credentials, config};
86+
client.start();
8687
while (true) {
8788
constexpr TickType_t xDelay = 500 / portTICK_PERIOD_MS;
88-
vTaskDelay( xDelay );
89+
vTaskDelay(xDelay);
8990
}
9091
}

components/esp_mqtt_cxx/examples/tcp/main/mqtt_tcp_example.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ extern "C" void app_main(void)
7878
mqtt::Configuration config{};
7979

8080
MyClient client{broker, credentials, config};
81+
client.start();
8182

8283
while (true) {
8384
constexpr TickType_t xDelay = 500 / portTICK_PERIOD_MS;

components/esp_mqtt_cxx/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ dependencies:
88
espressif/esp-idf-cxx: "^1.0.0-beta"
99
# Required IDF version
1010
idf:
11-
version: ">=5.0"
11+
version: ">=5.0,<6.0"
1212
espressif/mqtt:
1313
rules:
1414
- if: idf_version >=6.0

components/esp_mqtt_cxx/include/esp_mqtt.hpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -165,6 +165,19 @@ class Client {
165165
*/
166166
Client(const esp_mqtt_client_config_t &config);
167167

168+
/**
169+
* @brief Start the underlying esp-mqtt client
170+
*
171+
* Must be called after the derived class has finished constructing to avoid
172+
* events being dispatched to partially constructed objects.
173+
*/
174+
void start();
175+
176+
/**
177+
* @brief Check whether start() has been called
178+
*/
179+
[[nodiscard]] bool is_started() const noexcept;
180+
168181
/**
169182
* @brief Subscribe to topic
170183
*
@@ -216,6 +229,14 @@ class Client {
216229

217230
virtual ~Client() = default;
218231

232+
/**
233+
* @brief Test helper to dispatch events without a broker connection
234+
*
235+
* Intended for unit tests; forwards directly to the internal event handler.
236+
*/
237+
void dispatch_event_for_test(int32_t event_id, esp_mqtt_event_t *event);
238+
239+
219240
protected:
220241
/**
221242
* @brief Helper type to be used as custom deleter for std::unique_ptr.
@@ -292,5 +313,6 @@ class Client {
292313
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id,
293314
void *event_data) noexcept;
294315
void init(const esp_mqtt_client_config_t &config);
316+
bool started{false};
295317
};
296318
} // namespace idf::mqtt

0 commit comments

Comments
 (0)