[core] Deprecate unsafe const char* APIs in mark_failed() and status_set_error(), add LogString* overloads (#12021)

This commit is contained in:
J. Nick Koston
2025-11-24 13:45:56 -06:00
committed by GitHub
parent 909baf5e7a
commit 97ba67f4ee
34 changed files with 157 additions and 109 deletions

View File

@@ -87,7 +87,7 @@ void AbsoluteHumidityComponent::loop() {
break;
default:
this->publish_state(NAN);
this->status_set_error("Invalid saturation vapor pressure equation selection!");
this->status_set_error(LOG_STR("Invalid saturation vapor pressure equation selection!"));
return;
}
ESP_LOGD(TAG, "Saturation vapor pressure %f kPa", es);

View File

@@ -83,7 +83,7 @@ void AHT10Component::setup() {
void AHT10Component::restart_read_() {
if (this->read_count_ == AHT10_ATTEMPTS) {
this->read_count_ = 0;
this->status_set_error("Reading timed out");
this->status_set_error(LOG_STR("Reading timed out"));
return;
}
this->read_count_++;

View File

@@ -23,7 +23,7 @@ void BH1900NUXSensor::setup() {
i2c::ErrorCode result_code =
this->write_register(SOFT_RESET_REG, &SOFT_RESET_PAYLOAD, 1); // Software Reset to check communication
if (result_code != i2c::ERROR_OK) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
}

View File

@@ -100,18 +100,18 @@ void BME280Component::setup() {
if (!this->read_byte(BME280_REGISTER_CHIPID, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != 0x60) {
this->error_code_ = WRONG_CHIP_ID;
this->mark_failed(BME280_ERROR_WRONG_CHIP_ID);
this->mark_failed(LOG_STR(BME280_ERROR_WRONG_CHIP_ID));
return;
}
// Send a soft reset.
if (!this->write_byte(BME280_REGISTER_RESET, BME280_SOFT_RESET)) {
this->mark_failed("Reset failed");
this->mark_failed(LOG_STR("Reset failed"));
return;
}
// Wait until the NVM data has finished loading.
@@ -120,12 +120,12 @@ void BME280Component::setup() {
do { // NOLINT
delay(2);
if (!this->read_byte(BME280_REGISTER_STATUS, &status)) {
this->mark_failed("Error reading status register");
this->mark_failed(LOG_STR("Error reading status register"));
return;
}
} while ((status & BME280_STATUS_IM_UPDATE) && (--retry));
if (status & BME280_STATUS_IM_UPDATE) {
this->mark_failed("Timeout loading NVM");
this->mark_failed(LOG_STR("Timeout loading NVM"));
return;
}
@@ -153,26 +153,26 @@ void BME280Component::setup() {
uint8_t humid_control_val = 0;
if (!this->read_byte(BME280_REGISTER_CONTROLHUMID, &humid_control_val)) {
this->mark_failed("Read humidity control");
this->mark_failed(LOG_STR("Read humidity control"));
return;
}
humid_control_val &= ~0b00000111;
humid_control_val |= this->humidity_oversampling_ & 0b111;
if (!this->write_byte(BME280_REGISTER_CONTROLHUMID, humid_control_val)) {
this->mark_failed("Write humidity control");
this->mark_failed(LOG_STR("Write humidity control"));
return;
}
uint8_t config_register = 0;
if (!this->read_byte(BME280_REGISTER_CONFIG, &config_register)) {
this->mark_failed("Read config");
this->mark_failed(LOG_STR("Read config"));
return;
}
config_register &= ~0b11111100;
config_register |= 0b101 << 5; // 1000 ms standby time
config_register |= (this->iir_filter_ & 0b111) << 2;
if (!this->write_byte(BME280_REGISTER_CONFIG, config_register)) {
this->mark_failed("Write config");
this->mark_failed(LOG_STR("Write config"));
return;
}
}

View File

@@ -65,23 +65,23 @@ void BMP280Component::setup() {
// https://community.st.com/t5/stm32-mcus-products/issue-with-reading-bmp280-chip-id-using-spi/td-p/691855
if (!this->bmp_read_byte(0xD0, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (!this->bmp_read_byte(0xD0, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != 0x58) {
this->error_code_ = WRONG_CHIP_ID;
this->mark_failed(BMP280_ERROR_WRONG_CHIP_ID);
this->mark_failed(LOG_STR(BMP280_ERROR_WRONG_CHIP_ID));
return;
}
// Send a soft reset.
if (!this->bmp_write_byte(BMP280_REGISTER_RESET, BMP280_SOFT_RESET)) {
this->mark_failed("Reset failed");
this->mark_failed(LOG_STR("Reset failed"));
return;
}
// Wait until the NVM data has finished loading.
@@ -90,12 +90,12 @@ void BMP280Component::setup() {
do {
delay(2);
if (!this->bmp_read_byte(BMP280_REGISTER_STATUS, &status)) {
this->mark_failed("Error reading status register");
this->mark_failed(LOG_STR("Error reading status register"));
return;
}
} while ((status & BMP280_STATUS_IM_UPDATE) && (--retry));
if (status & BMP280_STATUS_IM_UPDATE) {
this->mark_failed("Timeout loading NVM");
this->mark_failed(LOG_STR("Timeout loading NVM"));
return;
}
@@ -116,14 +116,14 @@ void BMP280Component::setup() {
uint8_t config_register = 0;
if (!this->bmp_read_byte(BMP280_REGISTER_CONFIG, &config_register)) {
this->mark_failed("Read config");
this->mark_failed(LOG_STR("Read config"));
return;
}
config_register &= ~0b11111100;
config_register |= 0b000 << 5; // 0.5 ms standby time
config_register |= (this->iir_filter_ & 0b111) << 2;
if (!this->bmp_write_byte(BMP280_REGISTER_CONFIG, config_register)) {
this->mark_failed("Write config");
this->mark_failed(LOG_STR("Write config"));
return;
}
}

View File

@@ -8,7 +8,7 @@ Camera *Camera::global_camera = nullptr;
Camera::Camera() {
if (global_camera != nullptr) {
this->status_set_error("Multiple cameras are configured, but only one is supported.");
this->status_set_error(LOG_STR("Multiple cameras are configured, but only one is supported."));
this->mark_failed();
return;
}

View File

@@ -20,13 +20,13 @@ void CST816Touchscreen::continue_setup_() {
break;
default:
ESP_LOGE(TAG, "Unknown chip ID: 0x%02X", this->chip_id_);
this->status_set_error("Unknown chip ID");
this->status_set_error(LOG_STR("Unknown chip ID"));
this->mark_failed();
return;
}
this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION);
} else if (!this->skip_probe_) {
this->status_set_error("Failed to read chip id");
this->status_set_error(LOG_STR("Failed to read chip id"));
this->mark_failed();
return;
}

View File

@@ -22,7 +22,7 @@ const char *EPaperBase::epaper_state_to_string_() {
void EPaperBase::setup() {
if (!this->init_buffer_(this->buffer_length_)) {
this->mark_failed("Failed to initialise buffer");
this->mark_failed(LOG_STR("Failed to initialise buffer"));
return;
}
this->setup_pins_();
@@ -246,7 +246,7 @@ void EPaperBase::initialise_() {
auto length = this->init_sequence_length_;
while (index != length) {
if (length - index < 2) {
this->mark_failed("Malformed init sequence");
this->mark_failed(LOG_STR("Malformed init sequence"));
return;
}
const uint8_t cmd = sequence[index++];

View File

@@ -88,7 +88,7 @@ void Esp32HostedUpdate::perform(bool force) {
hasher.add(this->firmware_data_, this->firmware_size_);
hasher.calculate();
if (!hasher.equals_bytes(this->firmware_sha256_.data())) {
this->status_set_error("SHA256 verification failed");
this->status_set_error(LOG_STR("SHA256 verification failed"));
this->publish_state();
return;
}
@@ -105,7 +105,7 @@ void Esp32HostedUpdate::perform(bool force) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to begin OTA: %s", esp_err_to_name(err));
this->state_ = prev_state;
this->status_set_error("Failed to begin OTA");
this->status_set_error(LOG_STR("Failed to begin OTA"));
this->publish_state();
return;
}
@@ -121,7 +121,7 @@ void Esp32HostedUpdate::perform(bool force) {
ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err));
esp_hosted_slave_ota_end(); // NOLINT
this->state_ = prev_state;
this->status_set_error("Failed to write OTA data");
this->status_set_error(LOG_STR("Failed to write OTA data"));
this->publish_state();
return;
}
@@ -134,7 +134,7 @@ void Esp32HostedUpdate::perform(bool force) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to end OTA: %s", esp_err_to_name(err));
this->state_ = prev_state;
this->status_set_error("Failed to end OTA");
this->status_set_error(LOG_STR("Failed to end OTA"));
this->publish_state();
return;
}
@@ -144,7 +144,7 @@ void Esp32HostedUpdate::perform(bool force) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to activate OTA: %s", esp_err_to_name(err));
this->state_ = prev_state;
this->status_set_error("Failed to activate OTA");
this->status_set_error(LOG_STR("Failed to activate OTA"));
this->publish_state();
return;
}

View File

@@ -15,7 +15,7 @@ void EspLdo::setup() {
auto err = esp_ldo_acquire_channel(&config, &this->handle_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to acquire LDO channel %d with voltage %fV", this->channel_, this->voltage_);
this->mark_failed("Failed to acquire LDO channel");
this->mark_failed(LOG_STR("Failed to acquire LDO channel"));
} else {
ESP_LOGD(TAG, "Acquired LDO channel %d with voltage %fV", this->channel_, this->voltage_);
}

View File

@@ -36,20 +36,20 @@ void GDK101Component::setup() {
uint8_t data[2];
// first, reset the sensor
if (!this->reset_sensor_(data)) {
this->status_set_error("Reset failed!");
this->status_set_error(LOG_STR("Reset failed!"));
this->mark_failed();
return;
}
// sensor should acknowledge success of the reset procedure
if (data[0] != 1) {
this->status_set_error("Reset not acknowledged!");
this->status_set_error(LOG_STR("Reset not acknowledged!"));
this->mark_failed();
return;
}
delay(10);
// read firmware version
if (!this->read_fw_version_(data)) {
this->status_set_error("Failed to read firmware version");
this->status_set_error(LOG_STR("Failed to read firmware version"));
this->mark_failed();
return;
}

View File

@@ -79,13 +79,13 @@ void GT911Touchscreen::setup_internal_() {
}
}
if (err != i2c::ERROR_OK) {
this->mark_failed("Calibration error");
this->mark_failed(LOG_STR("Calibration error"));
return;
}
}
if (err != i2c::ERROR_OK) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
this->setup_done_ = true;

View File

@@ -29,7 +29,7 @@ void HttpRequestUpdate::setup() {
this->publish_state();
} else if (state == ota::OTAState::OTA_ABORT || state == ota::OTAState::OTA_ERROR) {
this->state_ = update::UPDATE_STATE_AVAILABLE;
this->status_set_error("Failed to install firmware");
this->status_set_error(LOG_STR("Failed to install firmware"));
this->publish_state();
}
});
@@ -51,7 +51,7 @@ void HttpRequestUpdate::update_task(void *params) {
if (container == nullptr || container->status_code != HTTP_STATUS_OK) {
ESP_LOGE(TAG, "Failed to fetch manifest from %s", this_update->source_url_.c_str());
// Defer to main loop to avoid race condition on component_state_ read-modify-write
this_update->defer([this_update]() { this_update->status_set_error("Failed to fetch manifest"); });
this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to fetch manifest")); });
UPDATE_RETURN;
}
@@ -60,7 +60,8 @@ void HttpRequestUpdate::update_task(void *params) {
if (data == nullptr) {
ESP_LOGE(TAG, "Failed to allocate %zu bytes for manifest", container->content_length);
// Defer to main loop to avoid race condition on component_state_ read-modify-write
this_update->defer([this_update]() { this_update->status_set_error("Failed to allocate memory for manifest"); });
this_update->defer(
[this_update]() { this_update->status_set_error(LOG_STR("Failed to allocate memory for manifest")); });
container->end();
UPDATE_RETURN;
}
@@ -123,7 +124,7 @@ void HttpRequestUpdate::update_task(void *params) {
if (!valid) {
ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str());
// Defer to main loop to avoid race condition on component_state_ read-modify-write
this_update->defer([this_update]() { this_update->status_set_error("Failed to parse manifest JSON"); });
this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to parse manifest JSON")); });
UPDATE_RETURN;
}

View File

@@ -466,7 +466,7 @@ void LvglComponent::setup() {
buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT
}
if (buffer == nullptr) {
this->status_set_error("Memory allocation failure");
this->status_set_error(LOG_STR("Memory allocation failure"));
this->mark_failed();
return;
}
@@ -479,7 +479,7 @@ void LvglComponent::setup() {
if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) {
this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
if (this->rotate_buf_ == nullptr) {
this->status_set_error("Memory allocation failure");
this->status_set_error(LOG_STR("Memory allocation failure"));
this->mark_failed();
return;
}

View File

@@ -57,14 +57,14 @@ void MAX17043Component::setup() {
if (config_reg != MAX17043_CONFIG_POWER_UP_DEFAULT) {
ESP_LOGE(TAG, "Device does not appear to be a MAX17043");
this->status_set_error("unrecognised");
this->status_set_error(LOG_STR("unrecognised"));
this->mark_failed();
return;
}
// need to write back to config register to reset the sleep bit
if (!this->write_byte_16(MAX17043_CONFIG, MAX17043_CONFIG_POWER_UP_DEFAULT)) {
this->status_set_error("sleep reset failed");
this->status_set_error(LOG_STR("sleep reset failed"));
this->mark_failed();
return;
}

View File

@@ -12,8 +12,8 @@ static bool notify_refresh_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel
return (need_yield == pdTRUE);
}
void MIPI_DSI::smark_failed(const char *message, esp_err_t err) {
ESP_LOGE(TAG, "%s: %s", message, esp_err_to_name(err));
void MIPI_DSI::smark_failed(const LogString *message, esp_err_t err) {
ESP_LOGE(TAG, "%s: %s", LOG_STR_ARG(message), esp_err_to_name(err));
this->mark_failed(message);
}
@@ -37,7 +37,7 @@ void MIPI_DSI::setup() {
};
auto err = esp_lcd_new_dsi_bus(&bus_config, &this->bus_handle_);
if (err != ESP_OK) {
this->smark_failed("lcd_new_dsi_bus failed", err);
this->smark_failed(LOG_STR("lcd_new_dsi_bus failed"), err);
return;
}
esp_lcd_dbi_io_config_t dbi_config = {
@@ -47,7 +47,7 @@ void MIPI_DSI::setup() {
};
err = esp_lcd_new_panel_io_dbi(this->bus_handle_, &dbi_config, &this->io_handle_);
if (err != ESP_OK) {
this->smark_failed("new_panel_io_dbi failed", err);
this->smark_failed(LOG_STR("new_panel_io_dbi failed"), err);
return;
}
auto pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565;
@@ -75,7 +75,7 @@ void MIPI_DSI::setup() {
}};
err = esp_lcd_new_panel_dpi(this->bus_handle_, &dpi_config, &this->handle_);
if (err != ESP_OK) {
this->smark_failed("esp_lcd_new_panel_dpi failed", err);
this->smark_failed(LOG_STR("esp_lcd_new_panel_dpi failed"), err);
return;
}
if (this->reset_pin_ != nullptr) {
@@ -92,14 +92,14 @@ void MIPI_DSI::setup() {
auto when = millis() + 120;
err = esp_lcd_panel_init(this->handle_);
if (err != ESP_OK) {
this->smark_failed("esp_lcd_init failed", err);
this->smark_failed(LOG_STR("esp_lcd_init failed"), err);
return;
}
size_t index = 0;
auto &vec = this->init_sequence_;
while (index != vec.size()) {
if (vec.size() - index < 2) {
this->mark_failed("Malformed init sequence");
this->mark_failed(LOG_STR("Malformed init sequence"));
return;
}
uint8_t cmd = vec[index++];
@@ -110,7 +110,7 @@ void MIPI_DSI::setup() {
} else {
uint8_t num_args = x & 0x7F;
if (vec.size() - index < num_args) {
this->mark_failed("Malformed init sequence");
this->mark_failed(LOG_STR("Malformed init sequence"));
return;
}
if (cmd == SLEEP_OUT) {
@@ -125,7 +125,7 @@ void MIPI_DSI::setup() {
format_hex_pretty(ptr, num_args, '.', false).c_str());
err = esp_lcd_panel_io_tx_param(this->io_handle_, cmd, ptr, num_args);
if (err != ESP_OK) {
this->smark_failed("lcd_panel_io_tx_param failed", err);
this->smark_failed(LOG_STR("lcd_panel_io_tx_param failed"), err);
return;
}
index += num_args;
@@ -140,7 +140,7 @@ void MIPI_DSI::setup() {
err = (esp_lcd_dpi_panel_register_event_callbacks(this->handle_, &cbs, this->io_lock_));
if (err != ESP_OK) {
this->smark_failed("Failed to register callbacks", err);
this->smark_failed(LOG_STR("Failed to register callbacks"), err);
return;
}
@@ -222,7 +222,7 @@ bool MIPI_DSI::check_buffer_() {
RAMAllocator<uint8_t> allocator;
this->buffer_ = allocator.allocate(this->height_ * this->width_ * bytes_per_pixel);
if (this->buffer_ == nullptr) {
this->mark_failed("Could not allocate buffer for display!");
this->mark_failed(LOG_STR("Could not allocate buffer for display!"));
return false;
}
return true;

View File

@@ -62,7 +62,7 @@ class MIPI_DSI : public display::Display {
void set_lanes(uint8_t lanes) { this->lanes_ = lanes; }
void set_madctl(uint8_t madctl) { this->madctl_ = madctl; }
void smark_failed(const char *message, esp_err_t err);
void smark_failed(const LogString *message, esp_err_t err);
void update() override;

View File

@@ -73,7 +73,7 @@ void MipiRgbSpi::write_init_sequence_() {
auto &vec = this->init_sequence_;
while (index != vec.size()) {
if (vec.size() - index < 2) {
this->mark_failed("Malformed init sequence");
this->mark_failed(LOG_STR("Malformed init sequence"));
return;
}
uint8_t cmd = vec[index++];
@@ -84,7 +84,7 @@ void MipiRgbSpi::write_init_sequence_() {
} else {
uint8_t num_args = x & 0x7F;
if (vec.size() - index < num_args) {
this->mark_failed("Malformed init sequence");
this->mark_failed(LOG_STR("Malformed init sequence"));
return;
}
if (cmd == SLEEP_OUT) {
@@ -165,7 +165,7 @@ void MipiRgb::common_setup_() {
err = esp_lcd_panel_init(this->handle_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "lcd setup failed: %s", esp_err_to_name(err));
this->mark_failed("lcd setup failed");
this->mark_failed(LOG_STR("lcd setup failed"));
}
ESP_LOGCONFIG(TAG, "MipiRgb setup complete");
}
@@ -249,7 +249,7 @@ bool MipiRgb::check_buffer_() {
RAMAllocator<uint16_t> allocator;
this->buffer_ = allocator.allocate(this->height_ * this->width_);
if (this->buffer_ == nullptr) {
this->mark_failed("Could not allocate buffer for display!");
this->mark_failed(LOG_STR("Could not allocate buffer for display!"));
return false;
}
return true;

View File

@@ -478,7 +478,7 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
RAMAllocator<BUFFERTYPE> allocator{};
this->buffer_ = allocator.allocate(BUFFER_WIDTH * BUFFER_HEIGHT / FRACTION);
if (this->buffer_ == nullptr) {
this->mark_failed("Buffer allocation failed");
this->mark_failed(LOG_STR("Buffer allocation failed"));
}
}

View File

@@ -78,19 +78,20 @@ void SourceSpeaker::loop() {
} else {
switch (err) {
case ESP_ERR_NO_MEM:
this->status_set_error("Failed to start mixer: not enough memory");
this->status_set_error(LOG_STR("Failed to start mixer: not enough memory"));
break;
case ESP_ERR_NOT_SUPPORTED:
this->status_set_error("Failed to start mixer: unsupported bits per sample");
this->status_set_error(LOG_STR("Failed to start mixer: unsupported bits per sample"));
break;
case ESP_ERR_INVALID_ARG:
this->status_set_error("Failed to start mixer: audio stream isn't compatible with the other audio stream.");
this->status_set_error(
LOG_STR("Failed to start mixer: audio stream isn't compatible with the other audio stream."));
break;
case ESP_ERR_INVALID_STATE:
this->status_set_error("Failed to start mixer: mixer task failed to start");
this->status_set_error(LOG_STR("Failed to start mixer: mixer task failed to start"));
break;
default:
this->status_set_error("Failed to start mixer");
this->status_set_error(LOG_STR("Failed to start mixer"));
break;
}
@@ -317,7 +318,7 @@ void MixerSpeaker::loop() {
xEventGroupClearBits(this->event_group_, MixerEventGroupBits::STATE_STARTING);
}
if (event_group_bits & MixerEventGroupBits::ERR_ESP_NO_MEM) {
this->status_set_error("Failed to allocate the mixer's internal buffer");
this->status_set_error(LOG_STR("Failed to allocate the mixer's internal buffer"));
xEventGroupClearBits(this->event_group_, MixerEventGroupBits::ERR_ESP_NO_MEM);
}
if (event_group_bits & MixerEventGroupBits::STATE_RUNNING) {

View File

@@ -278,7 +278,7 @@ void NAU7802Sensor::loop() {
this->set_calibration_failure_(true);
this->state_ = CalibrationState::INACTIVE;
ESP_LOGE(TAG, "Failed to calibrate sensor");
this->status_set_error("Calibration Failed");
this->status_set_error(LOG_STR("Calibration Failed"));
return;
}

View File

@@ -195,7 +195,7 @@ static void add(std::vector<uint8_t> &vec, const char *str) {
void PacketTransport::setup() {
this->name_ = App.get_name().c_str();
if (strlen(this->name_) > 255) {
this->status_set_error("Device name exceeds 255 chars");
this->status_set_error(LOG_STR("Device name exceeds 255 chars"));
this->mark_failed();
return;
}

View File

@@ -310,7 +310,7 @@ void QMP6988Component::calculate_pressure_() {
void QMP6988Component::setup() {
if (!this->device_check_()) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}

View File

@@ -66,17 +66,17 @@ void ResamplerSpeaker::loop() {
}
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NO_MEM) {
this->status_set_error("Resampler task failed to allocate the internal buffers");
this->status_set_error(LOG_STR("Resampler task failed to allocate the internal buffers"));
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM);
this->state_ = speaker::STATE_STOPPING;
}
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED) {
this->status_set_error("Cannot resample due to an unsupported audio stream");
this->status_set_error(LOG_STR("Cannot resample due to an unsupported audio stream"));
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED);
this->state_ = speaker::STATE_STOPPING;
}
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_FAIL) {
this->status_set_error("Resampler task failed");
this->status_set_error(LOG_STR("Resampler task failed"));
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL);
this->state_ = speaker::STATE_STOPPING;
}
@@ -106,12 +106,12 @@ void ResamplerSpeaker::loop() {
} else {
switch (err) {
case ESP_ERR_INVALID_STATE:
this->status_set_error("Failed to start resampler: resampler task failed to start");
this->status_set_error(LOG_STR("Failed to start resampler: resampler task failed to start"));
break;
case ESP_ERR_NO_MEM:
this->status_set_error("Failed to start resampler: not enough memory for task stack");
this->status_set_error(LOG_STR("Failed to start resampler: not enough memory for task stack"));
default:
this->status_set_error("Failed to start resampler");
this->status_set_error(LOG_STR("Failed to start resampler"));
break;
}

View File

@@ -13,7 +13,7 @@ void SHT4XComponent::start_heater_() {
ESP_LOGD(TAG, "Heater turning on");
if (this->write(cmd, 1) != i2c::ERROR_OK) {
this->status_set_error("Failed to turn on heater");
this->status_set_error(LOG_STR("Failed to turn on heater"));
}
}

View File

@@ -21,7 +21,7 @@ static const float SENSOR_SCALE = 0.01f; // Sensor resolution in degrees Celsiu
void STTS22HComponent::setup() {
// Check if device is a STTS22H
if (!this->is_stts22h_sensor_()) {
this->mark_failed("Device is not a STTS22H sensor");
this->mark_failed(LOG_STR("Device is not a STTS22H sensor"));
return;
}
@@ -61,12 +61,12 @@ float STTS22HComponent::read_temperature_() {
bool STTS22HComponent::is_stts22h_sensor_() {
uint8_t whoami_value;
if (this->read_register(WHOAMI_REG, &whoami_value, 1) != i2c::NO_ERROR) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return false;
}
if (whoami_value != WHOAMI_STTS22H_IDENTIFICATION) {
this->mark_failed("Unexpected WHOAMI identifier. Sensor is not a STTS22H");
this->mark_failed(LOG_STR("Unexpected WHOAMI identifier. Sensor is not a STTS22H"));
return false;
}
@@ -77,7 +77,7 @@ void STTS22HComponent::initialize_sensor_() {
// Read current CTRL_REG configuration
uint8_t ctrl_value;
if (this->read_register(CTRL_REG, &ctrl_value, 1) != i2c::NO_ERROR) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -86,14 +86,14 @@ void STTS22HComponent::initialize_sensor_() {
// FREERUN bit must be cleared (see sensor documentation)
ctrl_value &= ~FREERUN_CTRL_ENABLE_FLAG; // Clear FREERUN bit
if (this->write_register(CTRL_REG, &ctrl_value, 1) != i2c::NO_ERROR) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// Enable LOW ODR mode and ADD_INC
ctrl_value |= LOW_ODR_CTRL_ENABLE_FLAG | ADD_INC_ENABLE_FLAG; // Set LOW ODR bit and ADD_INC bit
if (this->write_register(CTRL_REG, &ctrl_value, 1) != i2c::NO_ERROR) {
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
}

View File

@@ -21,7 +21,7 @@ void UDPComponent::setup() {
if (this->should_broadcast_) {
this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (this->broadcast_socket_ == nullptr) {
this->status_set_error("Could not create socket");
this->status_set_error(LOG_STR("Could not create socket"));
this->mark_failed();
return;
}
@@ -41,14 +41,14 @@ void UDPComponent::setup() {
if (this->should_listen_) {
this->listen_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (this->listen_socket_ == nullptr) {
this->status_set_error("Could not create socket");
this->status_set_error(LOG_STR("Could not create socket"));
this->mark_failed();
return;
}
auto err = this->listen_socket_->setblocking(false);
if (err < 0) {
ESP_LOGE(TAG, "Unable to set nonblocking: errno %d", errno);
this->status_set_error("Unable to set nonblocking");
this->status_set_error(LOG_STR("Unable to set nonblocking"));
this->mark_failed();
return;
}
@@ -73,7 +73,7 @@ void UDPComponent::setup() {
err = this->listen_socket_->setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(imreq));
if (err < 0) {
ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno);
this->status_set_error("Failed to set IP_ADD_MEMBERSHIP");
this->status_set_error(LOG_STR("Failed to set IP_ADD_MEMBERSHIP"));
this->mark_failed();
return;
}
@@ -82,7 +82,7 @@ void UDPComponent::setup() {
err = this->listen_socket_->bind((struct sockaddr *) &server, sizeof(server));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
this->status_set_error("Unable to bind socket");
this->status_set_error(LOG_STR("Unable to bind socket"));
this->mark_failed();
return;
}

View File

@@ -188,7 +188,7 @@ void USBClient::setup() {
auto err = usb_host_client_register(&config, &this->handle_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "client register failed: %s", esp_err_to_name(err));
this->status_set_error("Client register failed");
this->status_set_error(LOG_STR("Client register failed"));
this->mark_failed();
return;
}

View File

@@ -11,7 +11,7 @@ void USBHost::setup() {
usb_host_config_t config{};
if (usb_host_install(&config) != ESP_OK) {
this->status_set_error("usb_host_install failed");
this->status_set_error(LOG_STR("usb_host_install failed"));
this->mark_failed();
return;
}

View File

@@ -320,7 +320,7 @@ static void fix_mps(const usb_ep_desc_t *ep) {
void USBUartTypeCdcAcm::on_connected() {
auto cdc_devs = this->parse_descriptors(this->device_handle_);
if (cdc_devs.empty()) {
this->status_set_error("No CDC-ACM device found");
this->status_set_error(LOG_STR("No CDC-ACM device found"));
this->disconnect();
return;
}
@@ -341,7 +341,7 @@ void USBUartTypeCdcAcm::on_connected() {
if (err != ESP_OK) {
ESP_LOGE(TAG, "usb_host_interface_claim failed: %s, channel=%d, intf=%d", esp_err_to_name(err), channel->index_,
channel->cdc_dev_.bulk_interface_number);
this->status_set_error("usb_host_interface_claim failed");
this->status_set_error(LOG_STR("usb_host_interface_claim failed"));
this->disconnect();
return;
}

View File

@@ -206,7 +206,7 @@ void VoiceAssistant::loop() {
case State::START_MICROPHONE: {
ESP_LOGD(TAG, "Starting Microphone");
if (!this->allocate_buffers_()) {
this->status_set_error("Failed to allocate buffers");
this->status_set_error(LOG_STR("Failed to allocate buffers"));
return;
}
if (this->status_has_error()) {

View File

@@ -67,7 +67,7 @@ void WakeOnLanButton::setup() {
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (this->broadcast_socket_ == nullptr) {
this->status_set_error("Could not create socket");
this->status_set_error(LOG_STR("Could not create socket"));
this->mark_failed();
return;
}

View File

@@ -36,6 +36,9 @@ namespace {
struct ComponentErrorMessage {
const Component *component;
const char *message;
// Track if message is flash pointer (needs LOG_STR_ARG) or RAM pointer
// Remove before 2026.6.0 when deprecated const char* API is removed
bool is_flash_ptr;
};
struct ComponentPriorityOverride {
@@ -49,6 +52,25 @@ std::unique_ptr<std::vector<ComponentErrorMessage>> component_error_messages;
// Setup priority overrides - freed after setup completes
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
std::unique_ptr<std::vector<ComponentPriorityOverride>> setup_priority_overrides;
// Helper to store error messages - reduces duplication between deprecated and new API
// Remove before 2026.6.0 when deprecated const char* API is removed
void store_component_error_message(const Component *component, const char *message, bool is_flash_ptr) {
// Lazy allocate the error messages vector if needed
if (!component_error_messages) {
component_error_messages = std::make_unique<std::vector<ComponentErrorMessage>>();
}
// Check if this component already has an error message
for (auto &entry : *component_error_messages) {
if (entry.component == component) {
entry.message = message;
entry.is_flash_ptr = is_flash_ptr;
return;
}
}
// Add new error message
component_error_messages->emplace_back(ComponentErrorMessage{component, message, is_flash_ptr});
}
} // namespace
namespace setup_priority {
@@ -143,16 +165,20 @@ void Component::call_dump_config() {
if (this->is_failed()) {
// Look up error message from global vector
const char *error_msg = nullptr;
bool is_flash_ptr = false;
if (component_error_messages) {
for (const auto &entry : *component_error_messages) {
if (entry.component == this) {
error_msg = entry.message;
is_flash_ptr = entry.is_flash_ptr;
break;
}
}
}
// Log with appropriate format based on pointer type
ESP_LOGE(TAG, " %s is marked FAILED: %s", LOG_STR_ARG(this->get_component_log_str()),
error_msg ? error_msg : LOG_STR_LITERAL("unspecified"));
error_msg ? (is_flash_ptr ? LOG_STR_ARG((const LogString *) error_msg) : error_msg)
: LOG_STR_LITERAL("unspecified"));
}
}
@@ -307,6 +333,7 @@ void Component::status_set_warning(const LogString *message) {
ESP_LOGW(TAG, "%s set Warning flag: %s", LOG_STR_ARG(this->get_component_log_str()),
message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified"));
}
void Component::status_set_error() { this->status_set_error((const LogString *) nullptr); }
void Component::status_set_error(const char *message) {
if ((this->component_state_ & STATUS_LED_ERROR) != 0)
return;
@@ -315,19 +342,19 @@ void Component::status_set_error(const char *message) {
ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()),
message ? message : LOG_STR_LITERAL("unspecified"));
if (message != nullptr) {
// Lazy allocate the error messages vector if needed
if (!component_error_messages) {
component_error_messages = std::make_unique<std::vector<ComponentErrorMessage>>();
}
// Check if this component already has an error message
for (auto &entry : *component_error_messages) {
if (entry.component == this) {
entry.message = message;
return;
}
}
// Add new error message
component_error_messages->emplace_back(ComponentErrorMessage{this, message});
store_component_error_message(this, message, false);
}
}
void Component::status_set_error(const LogString *message) {
if ((this->component_state_ & STATUS_LED_ERROR) != 0)
return;
this->component_state_ |= STATUS_LED_ERROR;
App.app_state_ |= STATUS_LED_ERROR;
ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()),
message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified"));
if (message != nullptr) {
// Store the LogString pointer directly (safe because LogString is always in flash/static memory)
store_component_error_message(this, LOG_STR_ARG(message), true);
}
}
void Component::status_clear_warning() {

View File

@@ -5,6 +5,7 @@
#include <functional>
#include <string>
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/optional.h"
@@ -157,7 +158,19 @@ class Component {
*/
virtual void mark_failed();
// Remove before 2026.6.0
ESPDEPRECATED("Use mark_failed(LOG_STR(\"static string literal\")) instead. Do NOT use .c_str() from temporary "
"strings. Will stop working in 2026.6.0",
"2025.12.0")
void mark_failed(const char *message) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
this->status_set_error(message);
#pragma GCC diagnostic pop
this->mark_failed();
}
void mark_failed(const LogString *message) {
this->status_set_error(message);
this->mark_failed();
}
@@ -216,7 +229,13 @@ class Component {
void status_set_warning(const char *message = nullptr);
void status_set_warning(const LogString *message);
void status_set_error(const char *message = nullptr);
void status_set_error(); // Set error flag without message
// Remove before 2026.6.0
ESPDEPRECATED("Use status_set_error(LOG_STR(\"static string literal\")) instead. Do NOT use .c_str() from temporary "
"strings. Will stop working in 2026.6.0",
"2025.12.0")
void status_set_error(const char *message);
void status_set_error(const LogString *message);
void status_clear_warning();