Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion components/diag/include/diag/diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,27 @@ extern "C"
esp_mqtt_client_handle_t mqtt;
} diag_handles_t;

esp_err_t diag_start(const app_cfg_t* cfg, diag_handles_t* handles);
typedef enum
{
DIAG_EVENT_STARTING = 0,
DIAG_EVENT_HTTP_READY,
DIAG_EVENT_MQTT_STARTED,
DIAG_EVENT_WARNING,
DIAG_EVENT_ERROR,
} diag_event_type_t;

typedef struct
{
diag_event_type_t type;
esp_err_t error;
} diag_event_t;

typedef void (*diag_event_cb_t)(const diag_event_t* event, void* user_data);

esp_err_t diag_start(const app_cfg_t* cfg,
diag_handles_t* handles,
diag_event_cb_t callback,
void* user_data);
void diag_stop(diag_handles_t* handles);

#ifdef __cplusplus
Expand Down
37 changes: 35 additions & 2 deletions components/diag/src/diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,28 @@

#include <stdio.h>

#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "mdns.h"

static const char* TAG = "diag";

static void
emit_diag_event(diag_event_cb_t callback, void* user_data, diag_event_type_t type, esp_err_t error)
{
if (callback == NULL)
{
return;
}
diag_event_t event = {
.type = type,
.error = error,
};
callback(&event, user_data);
}

static esp_err_t diag_register_mdns(const app_cfg_t* cfg)
{
esp_err_t err = mdns_init();
Expand Down Expand Up @@ -49,13 +64,16 @@ static esp_err_t health_handler(httpd_req_t* req)
return httpd_resp_send(req, payload, HTTPD_RESP_USE_STRLEN);
}

esp_err_t diag_start(const app_cfg_t* cfg, diag_handles_t* handles)
esp_err_t
diag_start(const app_cfg_t* cfg, diag_handles_t* handles, diag_event_cb_t callback, void* user_data)
{
if (!cfg || !handles)
{
return ESP_ERR_INVALID_ARG;
}

emit_diag_event(callback, user_data, DIAG_EVENT_STARTING, ESP_OK);

httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_simple;

Expand All @@ -64,9 +82,12 @@ esp_err_t diag_start(const app_cfg_t* cfg, diag_handles_t* handles)
{
ESP_LOGE(TAG, "Failed to start diagnostics server: 0x%x", (unsigned int)err);
handles->httpd = NULL;
emit_diag_event(callback, user_data, DIAG_EVENT_ERROR, err);
return err;
}

emit_diag_event(callback, user_data, DIAG_EVENT_HTTP_READY, ESP_OK);

httpd_uri_t health_uri = {
.uri = "/health",
.method = HTTP_GET,
Expand All @@ -83,13 +104,25 @@ esp_err_t diag_start(const app_cfg_t* cfg, diag_handles_t* handles)
handles->mqtt = esp_mqtt_client_init(&mqtt_config);
if (handles->mqtt)
{
esp_mqtt_client_start(handles->mqtt);
esp_err_t mqtt_err = esp_mqtt_client_start(handles->mqtt);
if (mqtt_err != ESP_OK)
{
ESP_LOGE(TAG, "MQTT start failed: 0x%x", (unsigned int)mqtt_err);
emit_diag_event(callback, user_data, DIAG_EVENT_ERROR, mqtt_err);
return mqtt_err;
Comment on lines 83 to +112
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Clean up HTTP server when diagnostics MQTT start fails

When esp_mqtt_client_start fails, the new callback code returns the error immediately, but the HTTP diagnostics server started just above remains running and handles->httpd stays set. Callers see a failure and leave diag_running_ false, so the HTTP server and MQTT handle are never stopped, leaking resources and blocking subsequent starts because port 80 is still bound. The function should tear down any partially initialized resources before returning.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex fix comments

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Ensured diag_start destroys the MQTT client and stops the diagnostics HTTP server when esp_mqtt_client_start fails so partially initialized resources are cleaned up before returning. components/diag/src/diag.cL104-L119

Testing

  • ⚠️ idf.py set-target esp32p4 (command unavailable in container)
  • ⚠️ idf.py build (command unavailable in container)
  • ⚠️ idf.py lint (command unavailable in container)

View task →

}
emit_diag_event(callback, user_data, DIAG_EVENT_MQTT_STARTED, ESP_OK);
}
else
{
emit_diag_event(callback, user_data, DIAG_EVENT_WARNING, ESP_ERR_NO_MEM);
}

err = diag_register_mdns(cfg);
if (err != ESP_OK)
{
ESP_LOGW(TAG, "mDNS registration failed: 0x%x", (unsigned int)err);
emit_diag_event(callback, user_data, DIAG_EVENT_WARNING, err);
}

ESP_LOGI(TAG, "Diagnostics server ready");
Expand Down
23 changes: 23 additions & 0 deletions components/ota_update/include/ota_update/ota_update.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma once

#include <stdbool.h>
#include <stddef.h>

#include "esp_err.h"

Expand All @@ -14,6 +15,28 @@ extern "C"
{
#endif

typedef enum
{
OTA_UPDATE_EVENT_START = 0,
OTA_UPDATE_EVENT_PROGRESS,
OTA_UPDATE_EVENT_COMPLETED,
OTA_UPDATE_EVENT_ERROR,
} ota_update_event_type_t;

typedef struct
{
ota_update_event_type_t type;
size_t bytes_downloaded;
size_t image_size;
esp_err_t error;
} ota_update_event_t;

typedef void (*ota_update_event_cb_t)(const ota_update_event_t* event, void* user_data);

esp_err_t ota_update_perform_with_callback(const char* url,
bool reboot_on_success,
ota_update_event_cb_t callback,
void* user_data);
esp_err_t ota_update_perform(const char* url, bool reboot_on_success);

#ifdef __cplusplus
Expand Down
66 changes: 65 additions & 1 deletion components/ota_update/src/ota_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,39 @@

static const char* TAG = "ota_update";

esp_err_t ota_update_perform(const char* url, bool reboot_on_success)
static void emit_event(ota_update_event_cb_t callback,
void* user_data,
ota_update_event_type_t type,
size_t bytes_downloaded,
size_t image_size,
esp_err_t error)
{
if (callback == NULL)
{
return;
}
ota_update_event_t event = {
.type = type,
.bytes_downloaded = bytes_downloaded,
.image_size = image_size,
.error = error,
};
callback(&event, user_data);
}

esp_err_t ota_update_perform_with_callback(const char* url,
bool reboot_on_success,
ota_update_event_cb_t callback,
void* user_data)
{
if (!url)
{
emit_event(callback, user_data, OTA_UPDATE_EVENT_ERROR, 0U, 0U, ESP_ERR_INVALID_ARG);
return ESP_ERR_INVALID_ARG;
}

emit_event(callback, user_data, OTA_UPDATE_EVENT_START, 0U, 0U, ESP_OK);

esp_http_client_config_t http_config = {
.url = url,
.timeout_ms = 10000,
Expand All @@ -37,11 +63,16 @@ esp_err_t ota_update_perform(const char* url, bool reboot_on_success)
if (err != ESP_OK)
{
ESP_LOGE(TAG, "OTA begin failed: 0x%x", (unsigned int)err);
emit_event(callback, user_data, OTA_UPDATE_EVENT_ERROR, 0U, 0U, err);
return err;
}

while ((err = esp_https_ota_perform(ota_handle)) == ESP_ERR_HTTPS_OTA_IN_PROGRESS)
{
size_t image_size = esp_https_ota_get_image_size(ota_handle);
size_t bytes_downloaded = esp_https_ota_get_image_len_read(ota_handle);
emit_event(
callback, user_data, OTA_UPDATE_EVENT_PROGRESS, bytes_downloaded, image_size, ESP_OK);
vTaskDelay(pdMS_TO_TICKS(100));
}

Expand All @@ -52,19 +83,52 @@ esp_err_t ota_update_perform(const char* url, bool reboot_on_success)
else
{
ESP_LOGE(TAG, "OTA perform failed: 0x%x", (unsigned int)err);
emit_event(callback,
user_data,
OTA_UPDATE_EVENT_ERROR,
esp_https_ota_get_image_len_read(ota_handle),
esp_https_ota_get_image_size(ota_handle),
err);
}

esp_err_t finish_err = esp_https_ota_finish(ota_handle);
if (finish_err != ESP_OK)
{
ESP_LOGE(TAG, "OTA finish failed: 0x%x", (unsigned int)finish_err);
emit_event(callback,
user_data,
OTA_UPDATE_EVENT_ERROR,
esp_https_ota_get_image_len_read(ota_handle),
esp_https_ota_get_image_size(ota_handle),
finish_err);
return finish_err;
}

if (err == ESP_OK && reboot_on_success)
{
ESP_LOGI(TAG, "Rebooting after OTA update");
emit_event(callback,
user_data,
OTA_UPDATE_EVENT_COMPLETED,
esp_https_ota_get_image_len_read(ota_handle),
esp_https_ota_get_image_size(ota_handle),
ESP_OK);
esp_restart();
}
else if (err == ESP_OK)
{
emit_event(callback,
user_data,
OTA_UPDATE_EVENT_COMPLETED,
esp_https_ota_get_image_len_read(ota_handle),
esp_https_ota_get_image_size(ota_handle),
ESP_OK);
}

return err;
}

esp_err_t ota_update_perform(const char* url, bool reboot_on_success)
{
return ota_update_perform_with_callback(url, reboot_on_success, NULL, NULL);
}
Loading
Loading