diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index ced7e3fec9..dcc3ce71cf 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -22,7 +22,6 @@ from esphome.core import CORE, CoroPriority, TimePeriod, coroutine_with_priority import esphome.final_validate as fv DEPENDENCIES = ["esp32"] -AUTO_LOAD = ["socket"] CODEOWNERS = ["@jesserockz", "@Rapsssito", "@bdraco"] DOMAIN = "esp32_ble" diff --git a/esphome/components/gcja5/gcja5.cpp b/esphome/components/gcja5/gcja5.cpp index a7342bc828..f7f7f8d02c 100644 --- a/esphome/components/gcja5/gcja5.cpp +++ b/esphome/components/gcja5/gcja5.cpp @@ -95,11 +95,13 @@ void GCJA5Component::parse_data_() { if (!this->first_status_log_) { this->first_status_log_ = true; - ESP_LOGI(TAG, "GCJA5 Status"); - ESP_LOGI(TAG, "Overall Status : %i", (status >> 6) & 0x03); - ESP_LOGI(TAG, "PD Status : %i", (status >> 4) & 0x03); - ESP_LOGI(TAG, "LD Status : %i", (status >> 2) & 0x03); - ESP_LOGI(TAG, "Fan Status : %i", (status >> 0) & 0x03); + ESP_LOGI(TAG, + "GCJA5 Status\n" + "Overall Status : %i\n" + "PD Status : %i\n" + "LD Status : %i\n" + "Fan Status : %i", + (status >> 6) & 0x03, (status >> 4) & 0x03, (status >> 2) & 0x03, (status >> 0) & 0x03); } } diff --git a/esphome/components/gl_r01_i2c/gl_r01_i2c.cpp b/esphome/components/gl_r01_i2c/gl_r01_i2c.cpp index e2a64b6877..38328c4b03 100644 --- a/esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +++ b/esphome/components/gl_r01_i2c/gl_r01_i2c.cpp @@ -27,8 +27,10 @@ void GLR01I2CComponent::setup() { } void GLR01I2CComponent::dump_config() { - ESP_LOGCONFIG(TAG, "GL-R01 I2C:"); - ESP_LOGCONFIG(TAG, " Firmware Version: 0x%04X", this->version_); + ESP_LOGCONFIG(TAG, + "GL-R01 I2C:\n" + " Firmware Version: 0x%04X", + this->version_); LOG_I2C_DEVICE(this); LOG_SENSOR(" ", "Distance", this); } diff --git a/esphome/components/hc8/hc8.cpp b/esphome/components/hc8/hc8.cpp index 5b649c2735..4d0f77df1b 100644 --- a/esphome/components/hc8/hc8.cpp +++ b/esphome/components/hc8/hc8.cpp @@ -89,11 +89,12 @@ void HC8Component::calibrate(uint16_t baseline) { float HC8Component::get_setup_priority() const { return setup_priority::DATA; } void HC8Component::dump_config() { - ESP_LOGCONFIG(TAG, "HC8:"); + ESP_LOGCONFIG(TAG, + "HC8:\n" + " Warmup time: %" PRIu32 " s", + this->warmup_seconds_); LOG_SENSOR(" ", "CO2", this->co2_sensor_); this->check_uart_settings(9600); - - ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", this->warmup_seconds_); } } // namespace esphome::hc8 diff --git a/esphome/components/hlw8012/hlw8012.cpp b/esphome/components/hlw8012/hlw8012.cpp index 70a05e4f72..f037ee9d8b 100644 --- a/esphome/components/hlw8012/hlw8012.cpp +++ b/esphome/components/hlw8012/hlw8012.cpp @@ -33,15 +33,15 @@ void HLW8012Component::setup() { } } void HLW8012Component::dump_config() { - ESP_LOGCONFIG(TAG, "HLW8012:"); - LOG_PIN(" SEL Pin: ", this->sel_pin_); - LOG_PIN(" CF Pin: ", this->cf_pin_); - LOG_PIN(" CF1 Pin: ", this->cf1_pin_); ESP_LOGCONFIG(TAG, + "HLW8012:\n" " Change measurement mode every %" PRIu32 "\n" " Current resistor: %.1f mΩ\n" " Voltage Divider: %.1f", this->change_mode_every_, this->current_resistor_ * 1000.0f, this->voltage_divider_); + LOG_PIN(" SEL Pin: ", this->sel_pin_); + LOG_PIN(" CF Pin: ", this->cf_pin_); + LOG_PIN(" CF1 Pin: ", this->cf1_pin_); LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "Voltage", this->voltage_sensor_); LOG_SENSOR(" ", "Current", this->current_sensor_); diff --git a/esphome/components/honeywellabp/honeywellabp.cpp b/esphome/components/honeywellabp/honeywellabp.cpp index 4c00f034aa..c204325dfc 100644 --- a/esphome/components/honeywellabp/honeywellabp.cpp +++ b/esphome/components/honeywellabp/honeywellabp.cpp @@ -35,8 +35,10 @@ uint8_t HONEYWELLABPSensor::readsensor_() { pressure_count_ = ((uint16_t) (buf_[0]) << 8 & 0x3F00) | ((uint16_t) (buf_[1]) & 0xFF); // 11 - bit temperature is all of byte 2 (lowest 8 bits) and the first three bits of byte 3 temperature_count_ = (((uint16_t) (buf_[2]) << 3) & 0x7F8) | (((uint16_t) (buf_[3]) >> 5) & 0x7); - ESP_LOGV(TAG, "Sensor pressure_count_ %d", pressure_count_); - ESP_LOGV(TAG, "Sensor temperature_count_ %d", temperature_count_); + ESP_LOGV(TAG, + "Sensor pressure_count_ %d\n" + "Sensor temperature_count_ %d", + pressure_count_, temperature_count_); } return status_; } diff --git a/esphome/components/ina260/ina260.cpp b/esphome/components/ina260/ina260.cpp index 9dd922cec2..4d6acf400c 100644 --- a/esphome/components/ina260/ina260.cpp +++ b/esphome/components/ina260/ina260.cpp @@ -61,13 +61,13 @@ void INA260Component::setup() { } void INA260Component::dump_config() { - ESP_LOGCONFIG(TAG, "INA260:"); + ESP_LOGCONFIG(TAG, + "INA260:\n" + " Manufacture ID: 0x%x\n" + " Device ID: 0x%x", + this->manufacture_id_, this->device_id_); LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); - - ESP_LOGCONFIG(TAG, " Manufacture ID: 0x%x", this->manufacture_id_); - ESP_LOGCONFIG(TAG, " Device ID: 0x%x", this->device_id_); - LOG_SENSOR(" ", "Bus Voltage", this->bus_voltage_sensor_); LOG_SENSOR(" ", "Current", this->current_sensor_); LOG_SENSOR(" ", "Power", this->power_sensor_); diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index 4ab02703e8..7185d21810 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -364,8 +364,10 @@ bool INA2XX::configure_shunt_() { ESP_LOGW(TAG, "Shunt value too high"); } this->shunt_cal_ &= 0x7FFF; - ESP_LOGV(TAG, "Given Rshunt=%f Ohm and Max_current=%.3f", this->shunt_resistance_ohm_, this->max_current_a_); - ESP_LOGV(TAG, "New CURRENT_LSB=%f, SHUNT_CAL=%u", this->current_lsb_, this->shunt_cal_); + ESP_LOGV(TAG, + "Given Rshunt=%f Ohm and Max_current=%.3f\n" + "New CURRENT_LSB=%f, SHUNT_CAL=%u", + this->shunt_resistance_ohm_, this->max_current_a_, this->current_lsb_, this->shunt_cal_); return this->write_unsigned_16_(RegisterMap::REG_SHUNT_CAL, this->shunt_cal_); } diff --git a/esphome/components/lc709203f/lc709203f.cpp b/esphome/components/lc709203f/lc709203f.cpp index 7e6ac878f8..ad9d6b3098 100644 --- a/esphome/components/lc709203f/lc709203f.cpp +++ b/esphome/components/lc709203f/lc709203f.cpp @@ -146,19 +146,14 @@ void Lc709203f::update() { } void Lc709203f::dump_config() { - ESP_LOGCONFIG(TAG, "LC709203F:"); - LOG_I2C_DEVICE(this); - - LOG_UPDATE_INTERVAL(this); ESP_LOGCONFIG(TAG, + "LC709203F:\n" " Pack Size: %d mAH\n" - " Pack APA: 0x%02X", - this->pack_size_, this->apa_); - - // This is only true if the pack_voltage_ is either 0x0000 or 0x0001. The config validator - // should have already verified this. - ESP_LOGCONFIG(TAG, " Pack Rated Voltage: 3.%sV", this->pack_voltage_ == 0x0000 ? "8" : "7"); - + " Pack APA: 0x%02X\n" + " Pack Rated Voltage: 3.%sV", + this->pack_size_, this->apa_, this->pack_voltage_ == 0x0000 ? "8" : "7"); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "Voltage", this->voltage_sensor_); LOG_SENSOR(" ", "Battery Remaining", this->battery_remaining_sensor_); diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index aaa4794586..a203dde115 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -130,8 +130,10 @@ void LEDCOutput::setup() { } int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); - ESP_LOGV(TAG, "Configured frequency %f with a bit depth of %u bits", this->frequency_, this->bit_depth_); - ESP_LOGV(TAG, "Angle of %.1f° results in hpoint %u", this->phase_angle_, hpoint); + ESP_LOGV(TAG, + "Configured frequency %f with a bit depth of %u bits\n" + "Angle of %.1f° results in hpoint %u", + this->frequency_, this->bit_depth_, this->phase_angle_, hpoint); ledc_channel_config_t chan_conf{}; chan_conf.gpio_num = this->pin_->get_pin(); @@ -147,25 +149,30 @@ void LEDCOutput::setup() { } void LEDCOutput::dump_config() { - ESP_LOGCONFIG(TAG, "Output:"); - LOG_PIN(" Pin ", this->pin_); ESP_LOGCONFIG(TAG, + "Output:\n" " Channel: %u\n" " PWM Frequency: %.1f Hz\n" " Phase angle: %.1f°\n" " Bit depth: %u", this->channel_, this->frequency_, this->phase_angle_, this->bit_depth_); - ESP_LOGV(TAG, " Max frequency for bit depth: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_)); - ESP_LOGV(TAG, " Min frequency for bit depth: %f", - ledc_min_frequency_for_bit_depth(this->bit_depth_, (this->frequency_ < 100))); - ESP_LOGV(TAG, " Max frequency for bit depth-1: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_ - 1)); - ESP_LOGV(TAG, " Min frequency for bit depth-1: %f", - ledc_min_frequency_for_bit_depth(this->bit_depth_ - 1, (this->frequency_ < 100))); - ESP_LOGV(TAG, " Max frequency for bit depth+1: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_ + 1)); - ESP_LOGV(TAG, " Min frequency for bit depth+1: %f", - ledc_min_frequency_for_bit_depth(this->bit_depth_ + 1, (this->frequency_ < 100))); - ESP_LOGV(TAG, " Max res bits: %d", MAX_RES_BITS); - ESP_LOGV(TAG, " Clock frequency: %f", CLOCK_FREQUENCY); + LOG_PIN(" Pin ", this->pin_); + ESP_LOGV(TAG, + " Max frequency for bit depth: %f\n" + " Min frequency for bit depth: %f\n" + " Max frequency for bit depth-1: %f\n" + " Min frequency for bit depth-1: %f\n" + " Max frequency for bit depth+1: %f\n" + " Min frequency for bit depth+1: %f\n" + " Max res bits: %d\n" + " Clock frequency: %f", + ledc_max_frequency_for_bit_depth(this->bit_depth_), + ledc_min_frequency_for_bit_depth(this->bit_depth_, (this->frequency_ < 100)), + ledc_max_frequency_for_bit_depth(this->bit_depth_ - 1), + ledc_min_frequency_for_bit_depth(this->bit_depth_ - 1, (this->frequency_ < 100)), + ledc_max_frequency_for_bit_depth(this->bit_depth_ + 1), + ledc_min_frequency_for_bit_depth(this->bit_depth_ + 1, (this->frequency_ < 100)), MAX_RES_BITS, + CLOCK_FREQUENCY); } void LEDCOutput::update_frequency(float frequency) { diff --git a/esphome/components/libretiny_pwm/libretiny_pwm.cpp b/esphome/components/libretiny_pwm/libretiny_pwm.cpp index 92e4097c0e..4e4a16d761 100644 --- a/esphome/components/libretiny_pwm/libretiny_pwm.cpp +++ b/esphome/components/libretiny_pwm/libretiny_pwm.cpp @@ -31,9 +31,11 @@ void LibreTinyPWM::setup() { } void LibreTinyPWM::dump_config() { - ESP_LOGCONFIG(TAG, "PWM Output:"); + ESP_LOGCONFIG(TAG, + "PWM Output:\n" + " Frequency: %.1f Hz", + this->frequency_); LOG_PIN(" Pin ", this->pin_); - ESP_LOGCONFIG(TAG, " Frequency: %.1f Hz", this->frequency_); } void LibreTinyPWM::update_frequency(float frequency) { diff --git a/esphome/components/m5stack_8angle/m5stack_8angle.cpp b/esphome/components/m5stack_8angle/m5stack_8angle.cpp index c542b4459e..5a9a5e8c9d 100644 --- a/esphome/components/m5stack_8angle/m5stack_8angle.cpp +++ b/esphome/components/m5stack_8angle/m5stack_8angle.cpp @@ -26,9 +26,11 @@ void M5Stack8AngleComponent::setup() { } void M5Stack8AngleComponent::dump_config() { - ESP_LOGCONFIG(TAG, "M5STACK_8ANGLE:"); + ESP_LOGCONFIG(TAG, + "M5STACK_8ANGLE:\n" + " Firmware version: %d", + this->fw_version_); LOG_I2C_DEVICE(this); - ESP_LOGCONFIG(TAG, " Firmware version: %d ", this->fw_version_); } float M5Stack8AngleComponent::read_knob_pos(uint8_t channel, AnalogBits bits) { diff --git a/esphome/components/mcp3204/mcp3204.cpp b/esphome/components/mcp3204/mcp3204.cpp index f0dd171a14..abefcad0eb 100644 --- a/esphome/components/mcp3204/mcp3204.cpp +++ b/esphome/components/mcp3204/mcp3204.cpp @@ -11,9 +11,11 @@ float MCP3204::get_setup_priority() const { return setup_priority::HARDWARE; } void MCP3204::setup() { this->spi_setup(); } void MCP3204::dump_config() { - ESP_LOGCONFIG(TAG, "MCP3204:"); + ESP_LOGCONFIG(TAG, + "MCP3204:\n" + " Reference Voltage: %.2fV", + this->reference_voltage_); LOG_PIN(" CS Pin:", this->cs_); - ESP_LOGCONFIG(TAG, " Reference Voltage: %.2fV", this->reference_voltage_); } float MCP3204::read_data(uint8_t pin, bool differential) { diff --git a/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp b/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp index 4c4abef4a7..e673537be1 100644 --- a/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp +++ b/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp @@ -11,8 +11,10 @@ float MCP3204Sensor::get_setup_priority() const { return setup_priority::DATA; } void MCP3204Sensor::dump_config() { LOG_SENSOR("", "MCP3204 Sensor", this); - ESP_LOGCONFIG(TAG, " Pin: %u", this->pin_); - ESP_LOGCONFIG(TAG, " Differential Mode: %s", YESNO(this->differential_mode_)); + ESP_LOGCONFIG(TAG, + " Pin: %u\n" + " Differential Mode: %s", + this->pin_, YESNO(this->differential_mode_)); LOG_UPDATE_INTERVAL(this); } float MCP3204Sensor::sample() { return this->parent_->read_data(this->pin_, this->differential_mode_); } diff --git a/esphome/components/mcp9600/mcp9600.cpp b/esphome/components/mcp9600/mcp9600.cpp index e1a88988c4..ff411bef7a 100644 --- a/esphome/components/mcp9600/mcp9600.cpp +++ b/esphome/components/mcp9600/mcp9600.cpp @@ -63,12 +63,12 @@ void MCP9600Component::setup() { } void MCP9600Component::dump_config() { - ESP_LOGCONFIG(TAG, "MCP9600:"); + ESP_LOGCONFIG(TAG, + "MCP9600:\n" + " Device ID: 0x%x", + this->device_id_); LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); - - ESP_LOGCONFIG(TAG, " Device ID: 0x%x", this->device_id_); - LOG_SENSOR(" ", "Hot Junction Temperature", this->hot_junction_sensor_); LOG_SENSOR(" ", "Cold Junction Temperature", this->cold_junction_sensor_); diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 457dff4075..5e9387b843 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -196,12 +196,12 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { } void Modbus::dump_config() { - ESP_LOGCONFIG(TAG, "Modbus:"); - LOG_PIN(" Flow Control Pin: ", this->flow_control_pin_); ESP_LOGCONFIG(TAG, + "Modbus:\n" " Send Wait Time: %d ms\n" " CRC Disabled: %s", this->send_wait_time_, YESNO(this->disable_crc_)); + LOG_PIN(" Flow Control Pin: ", this->flow_control_pin_); } float Modbus::get_setup_priority() const { // After UART bus diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.cpp b/esphome/components/mopeka_std_check/mopeka_std_check.cpp index 986a9a9fdc..231d09b909 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.cpp +++ b/esphome/components/mopeka_std_check/mopeka_std_check.cpp @@ -17,10 +17,12 @@ static const uint16_t MANUFACTURER_ID = 0x000D; static constexpr size_t MOPEKA_MAX_LOG_BYTES = 32; void MopekaStdCheck::dump_config() { - ESP_LOGCONFIG(TAG, "Mopeka Std Check"); - ESP_LOGCONFIG(TAG, " Propane Butane mix: %.0f%%", this->propane_butane_mix_ * 100); - ESP_LOGCONFIG(TAG, " Tank distance empty: %" PRIi32 "mm", this->empty_mm_); - ESP_LOGCONFIG(TAG, " Tank distance full: %" PRIi32 "mm", this->full_mm_); + ESP_LOGCONFIG(TAG, + "Mopeka Std Check\n" + " Propane Butane mix: %.0f%%\n" + " Tank distance empty: %" PRIi32 "mm\n" + " Tank distance full: %" PRIi32 "mm", + this->propane_butane_mix_ * 100, this->empty_mm_, this->full_mm_); LOG_SENSOR(" ", "Level", this->level_); LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Battery Level", this->battery_level_); diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index e3105f4860..3838d6df26 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -166,10 +166,12 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) { case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "MQTT_EVENT_ERROR"); if (event.error_handle.error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - ESP_LOGE(TAG, "Last error code reported from esp-tls: 0x%x", event.error_handle.esp_tls_last_esp_err); - ESP_LOGE(TAG, "Last tls stack error number: 0x%x", event.error_handle.esp_tls_stack_err); - ESP_LOGE(TAG, "Last captured errno : %d (%s)", event.error_handle.esp_transport_sock_errno, - strerror(event.error_handle.esp_transport_sock_errno)); + ESP_LOGE(TAG, + "Last error code reported from esp-tls: 0x%x\n" + "Last tls stack error number: 0x%x\n" + "Last captured errno : %d (%s)", + event.error_handle.esp_tls_last_esp_err, event.error_handle.esp_tls_stack_err, + event.error_handle.esp_transport_sock_errno, strerror(event.error_handle.esp_transport_sock_errno)); } else if (event.error_handle.error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { ESP_LOGE(TAG, "Connection refused error: 0x%x", event.error_handle.connect_return_code); } else { diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index c650c99f62..d26548acfc 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -154,15 +154,17 @@ void MQTTClientComponent::on_log(uint8_t level, const char *tag, const char *mes void MQTTClientComponent::dump_config() { char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + // clang-format off ESP_LOGCONFIG(TAG, "MQTT:\n" " Server Address: %s:%u (%s)\n" " Username: " LOG_SECRET("'%s'") "\n" - " Client ID: " LOG_SECRET("'%s'") "\n" - " Clean Session: %s", + " Client ID: " LOG_SECRET("'%s'") "\n" + " Clean Session: %s", this->credentials_.address.c_str(), this->credentials_.port, this->ip_.str_to(ip_buf), this->credentials_.username.c_str(), this->credentials_.client_id.c_str(), YESNO(this->credentials_.clean_session)); + // clang-format on if (this->is_discovery_ip_enabled()) { ESP_LOGCONFIG(TAG, " Discovery IP enabled"); } diff --git a/esphome/components/my9231/my9231.cpp b/esphome/components/my9231/my9231.cpp index fba7ac2bf3..5b77a49e72 100644 --- a/esphome/components/my9231/my9231.cpp +++ b/esphome/components/my9231/my9231.cpp @@ -58,14 +58,14 @@ void MY9231OutputComponent::setup() { } } void MY9231OutputComponent::dump_config() { - ESP_LOGCONFIG(TAG, "MY9231:"); - LOG_PIN(" DI Pin: ", this->pin_di_); - LOG_PIN(" DCKI Pin: ", this->pin_dcki_); ESP_LOGCONFIG(TAG, + "MY9231:\n" " Total number of channels: %u\n" " Number of chips: %u\n" " Bit depth: %u", this->num_channels_, this->num_chips_, this->bit_depth_); + LOG_PIN(" DI Pin: ", this->pin_di_); + LOG_PIN(" DCKI Pin: ", this->pin_dcki_); } void MY9231OutputComponent::loop() { if (!this->update_) diff --git a/esphome/components/opentherm/hub.cpp b/esphome/components/opentherm/hub.cpp index b23792fc7a..7a0cdc7f80 100644 --- a/esphome/components/opentherm/hub.cpp +++ b/esphome/components/opentherm/hub.cpp @@ -395,10 +395,8 @@ void OpenthermHub::dump_config() { this->write_initial_messages_(initial_messages); this->write_repeating_messages_(repeating_messages); - ESP_LOGCONFIG(TAG, "OpenTherm:"); - LOG_PIN(" In: ", this->in_pin_); - LOG_PIN(" Out: ", this->out_pin_); ESP_LOGCONFIG(TAG, + "OpenTherm:\n" " Sync mode: %s\n" " Sensors: %s\n" " Binary sensors: %s\n" @@ -409,6 +407,8 @@ void OpenthermHub::dump_config() { YESNO(this->sync_mode_), SHOW(OPENTHERM_SENSOR_LIST(ID, )), SHOW(OPENTHERM_BINARY_SENSOR_LIST(ID, )), SHOW(OPENTHERM_SWITCH_LIST(ID, )), SHOW(OPENTHERM_INPUT_SENSOR_LIST(ID, )), SHOW(OPENTHERM_OUTPUT_LIST(ID, )), SHOW(OPENTHERM_NUMBER_LIST(ID, ))); + LOG_PIN(" In: ", this->in_pin_); + LOG_PIN(" Out: ", this->out_pin_); ESP_LOGCONFIG(TAG, " Initial requests:"); for (auto type : initial_messages) { ESP_LOGCONFIG(TAG, " - %d (%s)", type, this->opentherm_->message_id_to_str(type)); diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 1f18e51496..a9aff3cce4 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -126,9 +126,12 @@ void OpenThreadComponent::ot_main() { ESP_LOGE(TAG, "Failed to set OpenThread linkmode."); } link_mode_config = otThreadGetLinkMode(esp_openthread_get_instance()); - ESP_LOGD(TAG, "Link Mode Device Type: %s", link_mode_config.mDeviceType ? "true" : "false"); - ESP_LOGD(TAG, "Link Mode Network Data: %s", link_mode_config.mNetworkData ? "true" : "false"); - ESP_LOGD(TAG, "Link Mode RX On When Idle: %s", link_mode_config.mRxOnWhenIdle ? "true" : "false"); + ESP_LOGD(TAG, + "Link Mode Device Type: %s\n" + "Link Mode Network Data: %s\n" + "Link Mode RX On When Idle: %s", + link_mode_config.mDeviceType ? "true" : "false", link_mode_config.mNetworkData ? "true" : "false", + link_mode_config.mRxOnWhenIdle ? "true" : "false"); // Run the main loop #if CONFIG_OPENTHREAD_CLI @@ -144,8 +147,8 @@ void OpenThreadComponent::ot_main() { // Make sure the length is 0 so we fallback to the configuration dataset.mLength = 0; } else { - ESP_LOGI(TAG, "Found OpenThread-managed dataset, ignoring esphome configuration"); - ESP_LOGI(TAG, "(set force_dataset: true to override)"); + ESP_LOGI(TAG, "Found OpenThread-managed dataset, ignoring esphome configuration\n" + "(set force_dataset: true to override)"); } #endif diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index 49e074a6ee..e364da78f8 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -47,6 +47,8 @@ def require_wake_loop_threadsafe() -> None: This enables the shared UDP loopback socket mechanism (~208 bytes RAM). The socket is shared across all components that use this feature. + This call is a no-op if networking is not enabled in the configuration. + IMPORTANT: This is for background thread context only, NOT ISR context. Socket operations are not safe to call from ISR handlers. @@ -56,8 +58,11 @@ def require_wake_loop_threadsafe() -> None: async def to_code(config): socket.require_wake_loop_threadsafe() """ + # Only set up once (idempotent - multiple components can call this) - if not CORE.data.get(KEY_WAKE_LOOP_THREADSAFE_REQUIRED, False): + if CORE.has_networking and not CORE.data.get( + KEY_WAKE_LOOP_THREADSAFE_REQUIRED, False + ): CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True cg.add_define("USE_WAKE_LOOP_THREADSAFE") # Consume 1 socket for the shared wake notification socket diff --git a/esphome/components/sun/sun.cpp b/esphome/components/sun/sun.cpp index df7030461b..e8fc4e44d1 100644 --- a/esphome/components/sun/sun.cpp +++ b/esphome/components/sun/sun.cpp @@ -172,21 +172,25 @@ struct SunAtTime { void debug() const { // debug output like in example 25.a, p. 165 - ESP_LOGV(TAG, "jde: %f", jde); - ESP_LOGV(TAG, "T: %f", t); - ESP_LOGV(TAG, "L_0: %f", mean_longitude()); - ESP_LOGV(TAG, "M: %f", mean_anomaly()); - ESP_LOGV(TAG, "e: %f", eccentricity()); - ESP_LOGV(TAG, "C: %f", equation_of_center()); - ESP_LOGV(TAG, "Odot: %f", true_longitude()); - ESP_LOGV(TAG, "Omega: %f", omega()); - ESP_LOGV(TAG, "lambda: %f", apparent_longitude()); - ESP_LOGV(TAG, "epsilon_0: %f", mean_obliquity()); - ESP_LOGV(TAG, "epsilon: %f", true_obliquity()); - ESP_LOGV(TAG, "v: %f", true_anomaly()); auto eq = equatorial_coordinate(); - ESP_LOGV(TAG, "right_ascension: %f", eq.right_ascension); - ESP_LOGV(TAG, "declination: %f", eq.declination); + ESP_LOGV(TAG, + "jde: %f\n" + "T: %f\n" + "L_0: %f\n" + "M: %f\n" + "e: %f\n" + "C: %f\n" + "Odot: %f\n" + "Omega: %f\n" + "lambda: %f\n" + "epsilon_0: %f\n" + "epsilon: %f\n" + "v: %f\n" + "right_ascension: %f\n" + "declination: %f", + jde, t, mean_longitude(), mean_anomaly(), eccentricity(), equation_of_center(), true_longitude(), omega(), + apparent_longitude(), mean_obliquity(), true_obliquity(), true_anomaly(), eq.right_ascension, + eq.declination); } }; diff --git a/esphome/components/sx1509/output/sx1509_float_output.cpp b/esphome/components/sx1509/output/sx1509_float_output.cpp index 1d2541bb46..4a24d78478 100644 --- a/esphome/components/sx1509/output/sx1509_float_output.cpp +++ b/esphome/components/sx1509/output/sx1509_float_output.cpp @@ -22,8 +22,10 @@ void SX1509FloatOutputChannel::setup() { } void SX1509FloatOutputChannel::dump_config() { - ESP_LOGCONFIG(TAG, "SX1509 PWM:"); - ESP_LOGCONFIG(TAG, " sx1509 pin: %d", this->pin_); + ESP_LOGCONFIG(TAG, + "SX1509 PWM:\n" + " sx1509 pin: %d", + this->pin_); LOG_FLOAT_OUTPUT(this); } diff --git a/esphome/components/tlc5947/tlc5947.cpp b/esphome/components/tlc5947/tlc5947.cpp index 6d4e099f7a..0a278bbaf6 100644 --- a/esphome/components/tlc5947/tlc5947.cpp +++ b/esphome/components/tlc5947/tlc5947.cpp @@ -21,12 +21,14 @@ void TLC5947::setup() { this->pwm_amounts_.resize(this->num_chips_ * N_CHANNELS_PER_CHIP, 0); } void TLC5947::dump_config() { - ESP_LOGCONFIG(TAG, "TLC5947:"); + ESP_LOGCONFIG(TAG, + "TLC5947:\n" + " Number of chips: %u", + this->num_chips_); LOG_PIN(" Data Pin: ", this->data_pin_); LOG_PIN(" Clock Pin: ", this->clock_pin_); LOG_PIN(" LAT Pin: ", this->lat_pin_); LOG_PIN(" OE Pin: ", this->outenable_pin_); - ESP_LOGCONFIG(TAG, " Number of chips: %u", this->num_chips_); } void TLC5947::loop() { diff --git a/esphome/components/tmp1075/tmp1075.cpp b/esphome/components/tmp1075/tmp1075.cpp index 1d9b384c66..9eb1e86c75 100644 --- a/esphome/components/tmp1075/tmp1075.cpp +++ b/esphome/components/tmp1075/tmp1075.cpp @@ -73,12 +73,15 @@ void TMP1075Sensor::set_fault_count(const int faults) { } void TMP1075Sensor::log_config_() { - ESP_LOGV(TAG, " oneshot : %d", config_.fields.oneshot); - ESP_LOGV(TAG, " rate : %d", config_.fields.rate); - ESP_LOGV(TAG, " faults : %d", config_.fields.faults); - ESP_LOGV(TAG, " polarity : %d", config_.fields.polarity); - ESP_LOGV(TAG, " alert_mode: %d", config_.fields.alert_mode); - ESP_LOGV(TAG, " shutdown : %d", config_.fields.shutdown); + ESP_LOGV(TAG, + " oneshot : %d\n" + " rate : %d\n" + " faults : %d\n" + " polarity : %d\n" + " alert_mode: %d\n" + " shutdown : %d", + config_.fields.oneshot, config_.fields.rate, config_.fields.faults, config_.fields.polarity, + config_.fields.alert_mode, config_.fields.shutdown); } void TMP1075Sensor::write_config() { diff --git a/esphome/components/tuya/binary_sensor/tuya_binary_sensor.cpp b/esphome/components/tuya/binary_sensor/tuya_binary_sensor.cpp index edfbb2ac60..a63e9c8318 100644 --- a/esphome/components/tuya/binary_sensor/tuya_binary_sensor.cpp +++ b/esphome/components/tuya/binary_sensor/tuya_binary_sensor.cpp @@ -14,8 +14,10 @@ void TuyaBinarySensor::setup() { } void TuyaBinarySensor::dump_config() { - ESP_LOGCONFIG(TAG, "Tuya Binary Sensor:"); - ESP_LOGCONFIG(TAG, " Binary Sensor has datapoint ID %u", this->sensor_id_); + ESP_LOGCONFIG(TAG, + "Tuya Binary Sensor:\n" + " Binary Sensor has datapoint ID %u", + this->sensor_id_); } } // namespace tuya diff --git a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp index fbe511811f..c71bf176a4 100644 --- a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp +++ b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp @@ -33,8 +33,10 @@ void TuyaTextSensor::setup() { } void TuyaTextSensor::dump_config() { - ESP_LOGCONFIG(TAG, "Tuya Text Sensor:"); - ESP_LOGCONFIG(TAG, " Text Sensor has datapoint ID %u", this->sensor_id_); + ESP_LOGCONFIG(TAG, + "Tuya Text Sensor:\n" + " Text Sensor has datapoint ID %u", + this->sensor_id_); } } // namespace tuya diff --git a/esphome/components/ufire_ec/ufire_ec.cpp b/esphome/components/ufire_ec/ufire_ec.cpp index 0a57ecc67b..3868dc92b7 100644 --- a/esphome/components/ufire_ec/ufire_ec.cpp +++ b/esphome/components/ufire_ec/ufire_ec.cpp @@ -102,16 +102,16 @@ void UFireECComponent::write_data_(uint8_t reg, float data) { } void UFireECComponent::dump_config() { - ESP_LOGCONFIG(TAG, "uFire-EC"); + ESP_LOGCONFIG(TAG, + "uFire-EC:\n" + " Temperature Compensation: %f\n" + " Temperature Coefficient: %f", + this->temperature_compensation_, this->temperature_coefficient_); LOG_I2C_DEVICE(this) LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "EC Sensor", this->ec_sensor_); LOG_SENSOR(" ", "Temperature Sensor", this->temperature_sensor_); LOG_SENSOR(" ", "Temperature Sensor external", this->temperature_sensor_external_); - ESP_LOGCONFIG(TAG, - " Temperature Compensation: %f\n" - " Temperature Coefficient: %f", - this->temperature_compensation_, this->temperature_coefficient_); } } // namespace ufire_ec diff --git a/esphome/components/uln2003/uln2003.cpp b/esphome/components/uln2003/uln2003.cpp index 991fe53487..11e1c3d4c0 100644 --- a/esphome/components/uln2003/uln2003.cpp +++ b/esphome/components/uln2003/uln2003.cpp @@ -34,12 +34,14 @@ void ULN2003::loop() { this->write_step_(this->current_uln_pos_); } void ULN2003::dump_config() { - ESP_LOGCONFIG(TAG, "ULN2003:"); + ESP_LOGCONFIG(TAG, + "ULN2003:\n" + " Sleep when done: %s", + YESNO(this->sleep_when_done_)); LOG_PIN(" Pin A: ", this->pin_a_); LOG_PIN(" Pin B: ", this->pin_b_); LOG_PIN(" Pin C: ", this->pin_c_); LOG_PIN(" Pin D: ", this->pin_d_); - ESP_LOGCONFIG(TAG, " Sleep when done: %s", YESNO(this->sleep_when_done_)); const char *step_mode_s; switch (this->step_mode_) { case ULN2003_STEP_MODE_FULL_STEP: diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 664f49d137..09da6e3b73 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -39,37 +39,46 @@ static void print_ep_desc(const usb_ep_desc_t *ep_desc) { break; } - ESP_LOGV(TAG, "\t\t*** Endpoint descriptor ***"); - ESP_LOGV(TAG, "\t\tbLength %d", ep_desc->bLength); - ESP_LOGV(TAG, "\t\tbDescriptorType %d", ep_desc->bDescriptorType); - ESP_LOGV(TAG, "\t\tbEndpointAddress 0x%x\tEP %d %s", ep_desc->bEndpointAddress, USB_EP_DESC_GET_EP_NUM(ep_desc), - USB_EP_DESC_GET_EP_DIR(ep_desc) ? "IN" : "OUT"); - ESP_LOGV(TAG, "\t\tbmAttributes 0x%x\t%s", ep_desc->bmAttributes, ep_type_str); - ESP_LOGV(TAG, "\t\twMaxPacketSize %d", ep_desc->wMaxPacketSize); - ESP_LOGV(TAG, "\t\tbInterval %d", ep_desc->bInterval); + ESP_LOGV(TAG, + "\t\t*** Endpoint descriptor ***\n" + "\t\tbLength %d\n" + "\t\tbDescriptorType %d\n" + "\t\tbEndpointAddress 0x%x\tEP %d %s\n" + "\t\tbmAttributes 0x%x\t%s\n" + "\t\twMaxPacketSize %d\n" + "\t\tbInterval %d", + ep_desc->bLength, ep_desc->bDescriptorType, ep_desc->bEndpointAddress, USB_EP_DESC_GET_EP_NUM(ep_desc), + USB_EP_DESC_GET_EP_DIR(ep_desc) ? "IN" : "OUT", ep_desc->bmAttributes, ep_type_str, ep_desc->wMaxPacketSize, + ep_desc->bInterval); } static void usbh_print_intf_desc(const usb_intf_desc_t *intf_desc) { - ESP_LOGV(TAG, "\t*** Interface descriptor ***"); - ESP_LOGV(TAG, "\tbLength %d", intf_desc->bLength); - ESP_LOGV(TAG, "\tbDescriptorType %d", intf_desc->bDescriptorType); - ESP_LOGV(TAG, "\tbInterfaceNumber %d", intf_desc->bInterfaceNumber); - ESP_LOGV(TAG, "\tbAlternateSetting %d", intf_desc->bAlternateSetting); - ESP_LOGV(TAG, "\tbNumEndpoints %d", intf_desc->bNumEndpoints); - ESP_LOGV(TAG, "\tbInterfaceClass 0x%x", intf_desc->bInterfaceProtocol); - ESP_LOGV(TAG, "\tiInterface %d", intf_desc->iInterface); + ESP_LOGV(TAG, + "\t*** Interface descriptor ***\n" + "\tbLength %d\n" + "\tbDescriptorType %d\n" + "\tbInterfaceNumber %d\n" + "\tbAlternateSetting %d\n" + "\tbNumEndpoints %d\n" + "\tbInterfaceClass 0x%x\n" + "\tiInterface %d", + intf_desc->bLength, intf_desc->bDescriptorType, intf_desc->bInterfaceNumber, intf_desc->bAlternateSetting, + intf_desc->bNumEndpoints, intf_desc->bInterfaceProtocol, intf_desc->iInterface); } static void usbh_print_cfg_desc(const usb_config_desc_t *cfg_desc) { - ESP_LOGV(TAG, "*** Configuration descriptor ***"); - ESP_LOGV(TAG, "bLength %d", cfg_desc->bLength); - ESP_LOGV(TAG, "bDescriptorType %d", cfg_desc->bDescriptorType); - ESP_LOGV(TAG, "wTotalLength %d", cfg_desc->wTotalLength); - ESP_LOGV(TAG, "bNumInterfaces %d", cfg_desc->bNumInterfaces); - ESP_LOGV(TAG, "bConfigurationValue %d", cfg_desc->bConfigurationValue); - ESP_LOGV(TAG, "iConfiguration %d", cfg_desc->iConfiguration); - ESP_LOGV(TAG, "bmAttributes 0x%x", cfg_desc->bmAttributes); - ESP_LOGV(TAG, "bMaxPower %dmA", cfg_desc->bMaxPower * 2); + ESP_LOGV(TAG, + "*** Configuration descriptor ***\n" + "bLength %d\n" + "bDescriptorType %d\n" + "wTotalLength %d\n" + "bNumInterfaces %d\n" + "bConfigurationValue %d\n" + "iConfiguration %d\n" + "bmAttributes 0x%x\n" + "bMaxPower %dmA", + cfg_desc->bLength, cfg_desc->bDescriptorType, cfg_desc->wTotalLength, cfg_desc->bNumInterfaces, + cfg_desc->bConfigurationValue, cfg_desc->iConfiguration, cfg_desc->bmAttributes, cfg_desc->bMaxPower * 2); } static void usb_client_print_device_descriptor(const usb_device_desc_t *devc_desc) { @@ -77,21 +86,27 @@ static void usb_client_print_device_descriptor(const usb_device_desc_t *devc_des return; } - ESP_LOGV(TAG, "*** Device descriptor ***"); - ESP_LOGV(TAG, "bLength %d", devc_desc->bLength); - ESP_LOGV(TAG, "bDescriptorType %d", devc_desc->bDescriptorType); - ESP_LOGV(TAG, "bcdUSB %d.%d0", ((devc_desc->bcdUSB >> 8) & 0xF), ((devc_desc->bcdUSB >> 4) & 0xF)); - ESP_LOGV(TAG, "bDeviceClass 0x%x", devc_desc->bDeviceClass); - ESP_LOGV(TAG, "bDeviceSubClass 0x%x", devc_desc->bDeviceSubClass); - ESP_LOGV(TAG, "bDeviceProtocol 0x%x", devc_desc->bDeviceProtocol); - ESP_LOGV(TAG, "bMaxPacketSize0 %d", devc_desc->bMaxPacketSize0); - ESP_LOGV(TAG, "idVendor 0x%x", devc_desc->idVendor); - ESP_LOGV(TAG, "idProduct 0x%x", devc_desc->idProduct); - ESP_LOGV(TAG, "bcdDevice %d.%d0", ((devc_desc->bcdDevice >> 8) & 0xF), ((devc_desc->bcdDevice >> 4) & 0xF)); - ESP_LOGV(TAG, "iManufacturer %d", devc_desc->iManufacturer); - ESP_LOGV(TAG, "iProduct %d", devc_desc->iProduct); - ESP_LOGV(TAG, "iSerialNumber %d", devc_desc->iSerialNumber); - ESP_LOGV(TAG, "bNumConfigurations %d", devc_desc->bNumConfigurations); + ESP_LOGV(TAG, + "*** Device descriptor ***\n" + "bLength %d\n" + "bDescriptorType %d\n" + "bcdUSB %d.%d0\n" + "bDeviceClass 0x%x\n" + "bDeviceSubClass 0x%x\n" + "bDeviceProtocol 0x%x\n" + "bMaxPacketSize0 %d\n" + "idVendor 0x%x\n" + "idProduct 0x%x\n" + "bcdDevice %d.%d0\n" + "iManufacturer %d\n" + "iProduct %d\n" + "iSerialNumber %d\n" + "bNumConfigurations %d", + devc_desc->bLength, devc_desc->bDescriptorType, ((devc_desc->bcdUSB >> 8) & 0xF), + ((devc_desc->bcdUSB >> 4) & 0xF), devc_desc->bDeviceClass, devc_desc->bDeviceSubClass, + devc_desc->bDeviceProtocol, devc_desc->bMaxPacketSize0, devc_desc->idVendor, devc_desc->idProduct, + ((devc_desc->bcdDevice >> 8) & 0xF), ((devc_desc->bcdDevice >> 4) & 0xF), devc_desc->iManufacturer, + devc_desc->iProduct, devc_desc->iSerialNumber, devc_desc->bNumConfigurations); } static void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc, diff --git a/esphome/components/usb_uart/cp210x.cpp b/esphome/components/usb_uart/cp210x.cpp index be024d1ba2..483286560a 100644 --- a/esphome/components/usb_uart/cp210x.cpp +++ b/esphome/components/usb_uart/cp210x.cpp @@ -58,8 +58,10 @@ std::vector USBUartTypeCP210X::parse_descriptors(usb_device_handle_t dev ESP_LOGE(TAG, "get_active_config_descriptor failed"); return {}; } - ESP_LOGD(TAG, "bDeviceClass: %u, bDeviceSubClass: %u", device_desc->bDeviceClass, device_desc->bDeviceSubClass); - ESP_LOGD(TAG, "bNumInterfaces: %u", config_desc->bNumInterfaces); + ESP_LOGD(TAG, + "bDeviceClass: %u, bDeviceSubClass: %u\n" + "bNumInterfaces: %u", + device_desc->bDeviceClass, device_desc->bDeviceSubClass, config_desc->bNumInterfaces); if (device_desc->bDeviceClass != 0) { ESP_LOGE(TAG, "bDeviceClass != 0"); return {}; diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.cpp b/esphome/components/vl53l0x/vl53l0x_sensor.cpp index d2548a5bbd..e833657fc4 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.cpp +++ b/esphome/components/vl53l0x/vl53l0x_sensor.cpp @@ -27,8 +27,10 @@ void VL53L0XSensor::dump_config() { if (this->enable_pin_ != nullptr) { LOG_PIN(" Enable Pin: ", this->enable_pin_); } - ESP_LOGCONFIG(TAG, " Timeout: %u%s", this->timeout_us_, this->timeout_us_ > 0 ? "us" : " (no timeout)"); - ESP_LOGCONFIG(TAG, " Timing Budget %uus ", this->measurement_timing_budget_us_); + ESP_LOGCONFIG(TAG, + " Timeout: %u%s\n" + " Timing Budget %uus ", + this->timeout_us_, this->timeout_us_ > 0 ? "us" : " (no timeout)", this->measurement_timing_budget_us_); } void VL53L0XSensor::setup() { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 6063647acc..261147368c 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -430,9 +430,12 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr } if (this->api_client_ != nullptr) { - ESP_LOGE(TAG, "Multiple API Clients attempting to connect to Voice Assistant"); - ESP_LOGE(TAG, "Current client: %s (%s)", this->api_client_->get_name(), this->api_client_->get_peername()); - ESP_LOGE(TAG, "New client: %s (%s)", client->get_name(), client->get_peername()); + ESP_LOGE(TAG, + "Multiple API Clients attempting to connect to Voice Assistant\n" + "Current client: %s (%s)\n" + "New client: %s (%s)", + this->api_client_->get_name(), this->api_client_->get_peername(), client->get_name(), + client->get_peername()); return; } @@ -864,9 +867,11 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse .is_active = msg.is_active, }; this->timers_[timer.id] = timer; - ESP_LOGD(TAG, "Timer Event"); - ESP_LOGD(TAG, " Type: %" PRId32, msg.event_type); - ESP_LOGD(TAG, " %s", timer.to_string().c_str()); + ESP_LOGD(TAG, + "Timer Event\n" + " Type: %" PRId32 "\n" + " %s", + msg.event_type, timer.to_string().c_str()); switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_TIMER_STARTED: diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 9ab050395d..4db9438206 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -1825,8 +1825,10 @@ void WaveshareEPaper2P9InV2R2::write_lut_(const uint8_t *lut, const uint8_t size void WaveshareEPaper2P9InV2R2::dump_config() { LOG_DISPLAY("", "Waveshare E-Paper", this); - ESP_LOGCONFIG(TAG, " Model: 2.9inV2R2"); - ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); + ESP_LOGCONFIG(TAG, + " Model: 2.9inV2R2\n" + " Full Update Every: %" PRIu32, + this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); @@ -2528,8 +2530,10 @@ int GDEY042T81::get_height_internal() { return 300; } uint32_t GDEY042T81::idle_timeout_() { return 5000; } void GDEY042T81::dump_config() { LOG_DISPLAY("", "GoodDisplay E-Paper", this); - ESP_LOGCONFIG(TAG, " Model: 4.2in B/W GDEY042T81"); - ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); + ESP_LOGCONFIG(TAG, + " Model: 4.2in B/W GDEY042T81\n" + " Full Update Every: %" PRIu32, + this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); @@ -3159,8 +3163,10 @@ int GDEY0583T81::get_height_internal() { return 480; } uint32_t GDEY0583T81::idle_timeout_() { return 5000; } void GDEY0583T81::dump_config() { LOG_DISPLAY("", "GoodDisplay E-Paper", this); - ESP_LOGCONFIG(TAG, " Model: 5.83in B/W GDEY0583T81"); - ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); + ESP_LOGCONFIG(TAG, + " Model: 5.83in B/W GDEY0583T81\n" + " Full Update Every: %" PRIu32, + this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); @@ -4340,8 +4346,10 @@ int WaveshareEPaper7P5InV2P::get_height_internal() { return 480; } uint32_t WaveshareEPaper7P5InV2P::idle_timeout_() { return 10000; } void WaveshareEPaper7P5InV2P::dump_config() { LOG_DISPLAY("", "Waveshare E-Paper", this); - ESP_LOGCONFIG(TAG, " Model: 7.50inv2p"); - ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); + ESP_LOGCONFIG(TAG, + " Model: 7.50inv2p\n" + " Full Update Every: %" PRIu32, + this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 5bf1f444e8..1906b672b8 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -245,6 +245,10 @@ enum WifiMinAuthMode : uint8_t { struct IDFWiFiEvent; #endif +#ifdef USE_LIBRETINY +struct LTWiFiEvent; +#endif + /** Listener interface for WiFi IP state changes. * * Components can implement this interface to receive IP address updates @@ -583,6 +587,7 @@ class WiFiComponent : public Component { #ifdef USE_LIBRETINY void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info); + void wifi_process_event_(LTWiFiEvent *event); void wifi_scan_done_callback_(); #endif diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 9bbd319f33..e9ccb86871 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -3,12 +3,16 @@ #ifdef USE_WIFI #ifdef USE_LIBRETINY +#include #include #include #include "lwip/ip_addr.h" #include "lwip/err.h" #include "lwip/dns.h" +#include +#include + #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -19,7 +23,68 @@ namespace esphome::wifi { static const char *const TAG = "wifi_lt"; -static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +// Thread-safe event handling for LibreTiny WiFi +// +// LibreTiny's WiFi.onEvent() callback runs in the WiFi driver's thread context, +// not the main ESPHome loop. Without synchronization, modifying shared state +// (like connection status flags) from the callback causes race conditions: +// - The main loop may never see state changes (values cached in registers) +// - State changes may be visible in inconsistent order +// - LibreTiny targets (BK7231, RTL8720) lack atomic instructions (no LDREX/STREX) +// +// Solution: Queue events in the callback and process them in the main loop. +// This is the same approach used by ESP32 IDF's wifi_process_event_(). +// All state modifications happen in the main loop context, eliminating races. + +static constexpr size_t EVENT_QUEUE_SIZE = 16; // Max pending WiFi events before overflow +static QueueHandle_t s_event_queue = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static volatile uint32_t s_event_queue_overflow_count = + 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// Event structure for queued WiFi events - contains a copy of event data +// to avoid lifetime issues with the original event data from the callback +struct LTWiFiEvent { + arduino_event_id_t event_id; + union { + struct { + uint8_t ssid[33]; + uint8_t ssid_len; + uint8_t bssid[6]; + uint8_t channel; + uint8_t authmode; + } sta_connected; + struct { + uint8_t ssid[33]; + uint8_t ssid_len; + uint8_t bssid[6]; + uint8_t reason; + } sta_disconnected; + struct { + uint8_t old_mode; + uint8_t new_mode; + } sta_authmode_change; + struct { + uint32_t status; + uint8_t number; + uint8_t scan_id; + } scan_done; + struct { + uint8_t mac[6]; + int rssi; + } ap_probe_req; + } data; +}; + +// Connection state machine - only modified from main loop after queue processing +enum class LTWiFiSTAState : uint8_t { + IDLE, // Not connecting + CONNECTING, // Connection in progress + CONNECTED, // Successfully connected with IP + ERROR_NOT_FOUND, // AP not found (probe failed) + ERROR_FAILED, // Connection failed (auth, timeout, etc.) +}; + +static LTWiFiSTAState s_sta_state = LTWiFiSTAState::IDLE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) bool WiFiComponent::wifi_mode_(optional sta, optional ap) { uint8_t current_mode = WiFi.getMode(); @@ -136,7 +201,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { this->wifi_apply_hostname_(); - s_sta_connecting = true; + // Reset state machine before connecting + s_sta_state = LTWiFiSTAState::CONNECTING; WiFiStatus status = WiFi.begin(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), ap.get_channel(), // 0 = auto @@ -271,16 +337,101 @@ const char *get_disconnect_reason_str(uint8_t reason) { using esphome_wifi_event_id_t = arduino_event_id_t; using esphome_wifi_event_info_t = arduino_event_info_t; +// Event callback - runs in WiFi driver thread context +// Only queues events for processing in main loop, no logging or state changes here void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_wifi_event_info_t info) { + if (s_event_queue == nullptr) { + return; + } + + // Allocate on heap and fill directly to avoid extra memcpy + auto *to_send = new LTWiFiEvent{}; // NOLINT(cppcoreguidelines-owning-memory) + to_send->event_id = event; + + // Copy event-specific data switch (event) { + case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: { + auto &it = info.wifi_sta_connected; + to_send->data.sta_connected.ssid_len = it.ssid_len; + memcpy(to_send->data.sta_connected.ssid, it.ssid, + std::min(static_cast(it.ssid_len), sizeof(to_send->data.sta_connected.ssid) - 1)); + memcpy(to_send->data.sta_connected.bssid, it.bssid, 6); + to_send->data.sta_connected.channel = it.channel; + to_send->data.sta_connected.authmode = it.authmode; + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: { + auto &it = info.wifi_sta_disconnected; + to_send->data.sta_disconnected.ssid_len = it.ssid_len; + memcpy(to_send->data.sta_disconnected.ssid, it.ssid, + std::min(static_cast(it.ssid_len), sizeof(to_send->data.sta_disconnected.ssid) - 1)); + memcpy(to_send->data.sta_disconnected.bssid, it.bssid, 6); + to_send->data.sta_disconnected.reason = it.reason; + break; + } + case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: { + auto &it = info.wifi_sta_authmode_change; + to_send->data.sta_authmode_change.old_mode = it.old_mode; + to_send->data.sta_authmode_change.new_mode = it.new_mode; + break; + } + case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: { + auto &it = info.wifi_scan_done; + to_send->data.scan_done.status = it.status; + to_send->data.scan_done.number = it.number; + to_send->data.scan_done.scan_id = it.scan_id; + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: { + auto &it = info.wifi_ap_probereqrecved; + memcpy(to_send->data.ap_probe_req.mac, it.mac, 6); + to_send->data.ap_probe_req.rssi = it.rssi; + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: { + auto &it = info.wifi_sta_connected; + memcpy(to_send->data.sta_connected.bssid, it.bssid, 6); + break; + } + case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: { + auto &it = info.wifi_sta_disconnected; + memcpy(to_send->data.sta_disconnected.bssid, it.bssid, 6); + break; + } + case ESPHOME_EVENT_ID_WIFI_READY: + case ESPHOME_EVENT_ID_WIFI_STA_START: + case ESPHOME_EVENT_ID_WIFI_STA_STOP: + case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP: + case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: + case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: + case ESPHOME_EVENT_ID_WIFI_AP_START: + case ESPHOME_EVENT_ID_WIFI_AP_STOP: + case ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED: + // No additional data needed + break; + default: + // Unknown event, don't queue + delete to_send; // NOLINT(cppcoreguidelines-owning-memory) + return; + } + + // Queue event (don't block if queue is full) + if (xQueueSend(s_event_queue, &to_send, 0) != pdPASS) { + delete to_send; // NOLINT(cppcoreguidelines-owning-memory) + s_event_queue_overflow_count++; + } +} + +// Process a single event from the queue - runs in main loop context +void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { + switch (event->event_id) { case ESPHOME_EVENT_ID_WIFI_READY: { ESP_LOGV(TAG, "Ready"); break; } case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: { - auto it = info.wifi_scan_done; - ESP_LOGV(TAG, "Scan done: status=%u number=%u scan_id=%u", it.status, it.number, it.scan_id); - + auto &it = event->data.scan_done; + ESP_LOGV(TAG, "Scan done: status=%" PRIu32 " number=%u scan_id=%u", it.status, it.number, it.scan_id); this->wifi_scan_done_callback_(); break; } @@ -291,14 +442,18 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } case ESPHOME_EVENT_ID_WIFI_STA_STOP: { ESP_LOGV(TAG, "STA stop"); - s_sta_connecting = false; + s_sta_state = LTWiFiSTAState::IDLE; break; } case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: { - auto it = info.wifi_sta_connected; + auto &it = event->data.sta_connected; + char bssid_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(it.bssid, bssid_buf); ESP_LOGV(TAG, "Connected ssid='%.*s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", it.ssid_len, - (const char *) it.ssid, format_mac_address_pretty(it.bssid).c_str(), it.channel, - get_auth_mode_str(it.authmode)); + (const char *) it.ssid, bssid_buf, it.channel, get_auth_mode_str(it.authmode)); + // Note: We don't set CONNECTED state here yet - wait for GOT_IP + // This matches ESP32 IDF behavior where s_sta_connected is set but + // wifi_sta_connect_status_() also checks got_ipv4_address_ #ifdef USE_WIFI_LISTENERS for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); @@ -306,6 +461,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #ifdef USE_WIFI_MANUAL_IP if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { + s_sta_state = LTWiFiSTAState::CONNECTED; for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } @@ -315,19 +471,18 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: { - auto it = info.wifi_sta_disconnected; + auto &it = event->data.sta_disconnected; // LibreTiny can send spurious disconnect events with empty ssid/bssid during connection. // These are typically "Association Leave" events that don't indicate actual failures: // [W][wifi_lt]: Disconnected ssid='' bssid=00:00:00:00:00:00 reason='Association Leave' // [W][wifi_lt]: Disconnected ssid='' bssid=00:00:00:00:00:00 reason='Association Leave' // [V][wifi_lt]: Connected ssid='WIFI' bssid=... channel=3, authmode=WPA2 PSK - // Without this check, the spurious events set s_sta_connecting=false, causing - // wifi_sta_connect_status_() to return IDLE. The main loop then sees - // "Unknown connection status 0" (wifi_component.cpp check_connecting_finished) - // and calls retry_connect(), aborting a connection that may succeed moments later. - // Real connection failures will have ssid/bssid populated, or we'll hit the connection timeout. - if (it.ssid_len == 0 && s_sta_connecting) { + // Without this check, the spurious events would transition state to ERROR_FAILED, + // causing wifi_sta_connect_status_() to return an error. The main loop would then + // call retry_connect(), aborting a connection that may succeed moments later. + // Only ignore benign reasons - real failures like NO_AP_FOUND should still be processed. + if (it.ssid_len == 0 && s_sta_state == LTWiFiSTAState::CONNECTING && it.reason != WIFI_REASON_NO_AP_FOUND) { ESP_LOGV(TAG, "Ignoring disconnect event with empty ssid while connecting (reason=%s)", get_disconnect_reason_str(it.reason)); break; @@ -336,11 +491,13 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ if (it.reason == WIFI_REASON_NO_AP_FOUND) { ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len, (const char *) it.ssid); + s_sta_state = LTWiFiSTAState::ERROR_NOT_FOUND; } else { - char bssid_s[18]; + char bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; format_mac_addr_upper(it.bssid, bssid_s); ESP_LOGW(TAG, "Disconnected ssid='%.*s' bssid=" LOG_SECRET("%s") " reason='%s'", it.ssid_len, (const char *) it.ssid, bssid_s, get_disconnect_reason_str(it.reason)); + s_sta_state = LTWiFiSTAState::ERROR_FAILED; } uint8_t reason = it.reason; @@ -351,7 +508,6 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ this->error_from_callback_ = true; } - s_sta_connecting = false; #ifdef USE_WIFI_LISTENERS static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : this->connect_state_listeners_) { @@ -361,24 +517,22 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: { - auto it = info.wifi_sta_authmode_change; + auto &it = event->data.sta_authmode_change; ESP_LOGV(TAG, "Authmode Change old=%s new=%s", get_auth_mode_str(it.old_mode), get_auth_mode_str(it.new_mode)); // Mitigate CVE-2020-12638 // https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors if (it.old_mode != WIFI_AUTH_OPEN && it.new_mode == WIFI_AUTH_OPEN) { ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting"); - // we can't call retry_connect() from this context, so disconnect immediately - // and notify main thread with error_from_callback_ WiFi.disconnect(); this->error_from_callback_ = true; + s_sta_state = LTWiFiSTAState::ERROR_FAILED; } break; } case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP: { - // auto it = info.got_ip.ip_info; ESP_LOGV(TAG, "static_ip=%s gateway=%s", format_ip4_addr(WiFi.localIP()).c_str(), format_ip4_addr(WiFi.gatewayIP()).c_str()); - s_sta_connecting = false; + s_sta_state = LTWiFiSTAState::CONNECTED; #ifdef USE_WIFI_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); @@ -387,7 +541,6 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { - // auto it = info.got_ip.ip_info; ESP_LOGV(TAG, "Got IPv6"); #ifdef USE_WIFI_LISTENERS for (auto *listener : this->ip_state_listeners_) { @@ -398,6 +551,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: { ESP_LOGV(TAG, "Lost IP"); + // Don't change state to IDLE - let the disconnect event handle that break; } case ESPHOME_EVENT_ID_WIFI_AP_START: { @@ -409,15 +563,21 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: { - auto it = info.wifi_sta_connected; - auto &mac = it.bssid; - ESP_LOGV(TAG, "AP client connected MAC=%s", format_mac_address_pretty(mac).c_str()); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + auto &it = event->data.sta_connected; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(it.bssid, mac_buf); + ESP_LOGV(TAG, "AP client connected MAC=%s", mac_buf); +#endif break; } case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: { - auto it = info.wifi_sta_disconnected; - auto &mac = it.bssid; - ESP_LOGV(TAG, "AP client disconnected MAC=%s", format_mac_address_pretty(mac).c_str()); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + auto &it = event->data.sta_disconnected; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(it.bssid, mac_buf); + ESP_LOGV(TAG, "AP client disconnected MAC=%s", mac_buf); +#endif break; } case ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED: { @@ -425,8 +585,12 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ break; } case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: { - auto it = info.wifi_ap_probereqrecved; - ESP_LOGVV(TAG, "AP receive Probe Request MAC=%s RSSI=%d", format_mac_address_pretty(it.mac).c_str(), it.rssi); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + auto &it = event->data.ap_probe_req; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(it.mac, mac_buf); + ESP_LOGVV(TAG, "AP receive Probe Request MAC=%s RSSI=%d", mac_buf, it.rssi); +#endif break; } default: @@ -434,23 +598,35 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } } void WiFiComponent::wifi_pre_setup_() { + // Create event queue for thread-safe event handling + // Events are pushed from WiFi callback thread and processed in main loop + s_event_queue = xQueueCreate(EVENT_QUEUE_SIZE, sizeof(LTWiFiEvent *)); + if (s_event_queue == nullptr) { + ESP_LOGE(TAG, "Failed to create event queue"); + return; + } + auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); WiFi.onEvent(f); // Make sure WiFi is in clean state before anything starts this->wifi_mode_(false, false); } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { - auto status = WiFi.status(); - if (status == WL_CONNECTED) { - return WiFiSTAConnectStatus::CONNECTED; - } else if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) { - return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; - } else if (status == WL_NO_SSID_AVAIL) { - return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; - } else if (s_sta_connecting) { - return WiFiSTAConnectStatus::CONNECTING; + // Use state machine instead of querying WiFi.status() directly + // State is updated in main loop from queued events, ensuring thread safety + switch (s_sta_state) { + case LTWiFiSTAState::CONNECTED: + return WiFiSTAConnectStatus::CONNECTED; + case LTWiFiSTAState::ERROR_NOT_FOUND: + return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; + case LTWiFiSTAState::ERROR_FAILED: + return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; + case LTWiFiSTAState::CONNECTING: + return WiFiSTAConnectStatus::CONNECTING; + case LTWiFiSTAState::IDLE: + default: + return WiFiSTAConnectStatus::IDLE; } - return WiFiSTAConnectStatus::IDLE; } bool WiFiComponent::wifi_scan_start_(bool passive) { // enable STA @@ -534,9 +710,9 @@ network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {WiFi.softAPIP()}; #endif // USE_WIFI_AP bool WiFiComponent::wifi_disconnect_() { - // Clear connecting flag first so disconnect events aren't ignored + // Reset state first so disconnect events aren't ignored // and wifi_sta_connect_status_() returns IDLE instead of CONNECTING - s_sta_connecting = false; + s_sta_state = LTWiFiSTAState::IDLE; return WiFi.disconnect(); } @@ -563,7 +739,29 @@ int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); } network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; } network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; } -void WiFiComponent::wifi_loop_() {} +void WiFiComponent::wifi_loop_() { + // Process all pending events from the queue + if (s_event_queue == nullptr) { + return; + } + + // Check for dropped events due to queue overflow + if (s_event_queue_overflow_count > 0) { + ESP_LOGW(TAG, "Event queue overflow, %" PRIu32 " events dropped", s_event_queue_overflow_count); + s_event_queue_overflow_count = 0; + } + + while (true) { + LTWiFiEvent *event; + if (xQueueReceive(s_event_queue, &event, 0) != pdTRUE) { + // No more events + break; + } + + wifi_process_event_(event); + delete event; // NOLINT(cppcoreguidelines-owning-memory) + } +} } // namespace esphome::wifi #endif // USE_LIBRETINY diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index 2de6f0d2e3..7810a40ae1 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -131,15 +131,21 @@ void Wireguard::update() { } void Wireguard::dump_config() { - ESP_LOGCONFIG(TAG, "WireGuard:"); - ESP_LOGCONFIG(TAG, " Address: %s", this->address_.c_str()); - ESP_LOGCONFIG(TAG, " Netmask: %s", this->netmask_.c_str()); - ESP_LOGCONFIG(TAG, " Private Key: " LOG_SECRET("%s"), mask_key(this->private_key_).c_str()); - ESP_LOGCONFIG(TAG, " Peer Endpoint: " LOG_SECRET("%s"), this->peer_endpoint_.c_str()); - ESP_LOGCONFIG(TAG, " Peer Port: " LOG_SECRET("%d"), this->peer_port_); - ESP_LOGCONFIG(TAG, " Peer Public Key: " LOG_SECRET("%s"), this->peer_public_key_.c_str()); - ESP_LOGCONFIG(TAG, " Peer Pre-shared Key: " LOG_SECRET("%s"), - (!this->preshared_key_.empty() ? mask_key(this->preshared_key_).c_str() : "NOT IN USE")); + // clang-format off + ESP_LOGCONFIG( + TAG, + "WireGuard:\n" + " Address: %s\n" + " Netmask: %s\n" + " Private Key: " LOG_SECRET("%s") "\n" + " Peer Endpoint: " LOG_SECRET("%s") "\n" + " Peer Port: " LOG_SECRET("%d") "\n" + " Peer Public Key: " LOG_SECRET("%s") "\n" + " Peer Pre-shared Key: " LOG_SECRET("%s"), + this->address_.c_str(), this->netmask_.c_str(), mask_key(this->private_key_).c_str(), + this->peer_endpoint_.c_str(), this->peer_port_, this->peer_public_key_.c_str(), + (!this->preshared_key_.empty() ? mask_key(this->preshared_key_).c_str() : "NOT IN USE")); + // clang-format on ESP_LOGCONFIG(TAG, " Peer Allowed IPs:"); for (auto &allowed_ip : this->allowed_ips_) { ESP_LOGCONFIG(TAG, " - %s/%s", std::get<0>(allowed_ip).c_str(), std::get<1>(allowed_ip).c_str()); diff --git a/esphome/components/wl_134/wl_134.cpp b/esphome/components/wl_134/wl_134.cpp index 403f8bd1b3..20a145d183 100644 --- a/esphome/components/wl_134/wl_134.cpp +++ b/esphome/components/wl_134/wl_134.cpp @@ -68,12 +68,15 @@ Wl134Component::Rfid134Error Wl134Component::read_packet_() { reading.reserved1 = this->hex_lsb_ascii_to_uint64_(&(packet[RFID134_PACKET_RESERVED1]), RFID134_PACKET_CHECKSUM - RFID134_PACKET_RESERVED1); - ESP_LOGV(TAG, "Tag id: %012lld", reading.id); - ESP_LOGV(TAG, "Country: %03d", reading.country); - ESP_LOGV(TAG, "isData: %s", reading.isData ? "true" : "false"); - ESP_LOGV(TAG, "isAnimal: %s", reading.isAnimal ? "true" : "false"); - ESP_LOGV(TAG, "Reserved0: %d", reading.reserved0); - ESP_LOGV(TAG, "Reserved1: %" PRId32, reading.reserved1); + ESP_LOGV(TAG, + "Tag id: %012lld\n" + "Country: %03d\n" + "isData: %s\n" + "isAnimal: %s\n" + "Reserved0: %d\n" + "Reserved1: %" PRId32, + reading.id, reading.country, reading.isData ? "true" : "false", reading.isAnimal ? "true" : "false", + reading.reserved0, reading.reserved1); char buf[20]; sprintf(buf, "%03d%012lld", reading.country, reading.id); diff --git a/esphome/components/x9c/x9c.cpp b/esphome/components/x9c/x9c.cpp index 5cd4fba8c0..8f66c46015 100644 --- a/esphome/components/x9c/x9c.cpp +++ b/esphome/components/x9c/x9c.cpp @@ -62,14 +62,14 @@ void X9cOutput::write_state(float state) { } void X9cOutput::dump_config() { - ESP_LOGCONFIG(TAG, "X9C Potentiometer Output:"); - LOG_PIN(" Chip Select Pin: ", this->cs_pin_); - LOG_PIN(" Increment Pin: ", this->inc_pin_); - LOG_PIN(" Up/Down Pin: ", this->ud_pin_); ESP_LOGCONFIG(TAG, + "X9C Potentiometer Output:\n" " Initial Value: %f\n" " Step Delay: %d", this->initial_value_, this->step_delay_); + LOG_PIN(" Chip Select Pin: ", this->cs_pin_); + LOG_PIN(" Increment Pin: ", this->inc_pin_); + LOG_PIN(" Up/Down Pin: ", this->ud_pin_); LOG_FLOAT_OUTPUT(this); } diff --git a/esphome/components/xgzp68xx/xgzp68xx.cpp b/esphome/components/xgzp68xx/xgzp68xx.cpp index 2b0824de0a..b5b786c105 100644 --- a/esphome/components/xgzp68xx/xgzp68xx.cpp +++ b/esphome/components/xgzp68xx/xgzp68xx.cpp @@ -72,8 +72,10 @@ void XGZP68XXComponent::update() { temperature_raw = encode_uint16(data[3], data[4]); // Convert the pressure data to hPa - ESP_LOGV(TAG, "Got raw pressure=%" PRIu32 ", raw temperature=%u", pressure_raw, temperature_raw); - ESP_LOGV(TAG, "K value is %u", this->k_value_); + ESP_LOGV(TAG, + "Got raw pressure=%" PRIu32 ", raw temperature=%u\n" + "K value is %u", + pressure_raw, temperature_raw, this->k_value_); // Sign extend the pressure float pressure_in_pa = (float) (((int32_t) pressure_raw << 8) >> 8); diff --git a/esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp b/esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp index d3fec6cc9e..31e426f0cc 100644 --- a/esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +++ b/esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp @@ -13,8 +13,10 @@ static constexpr size_t XMWSDJ04MMC_BINDKEY_SIZE = 16; void XiaomiXMWSDJ04MMC::dump_config() { char bindkey_hex[format_hex_pretty_size(XMWSDJ04MMC_BINDKEY_SIZE)]; - ESP_LOGCONFIG(TAG, "Xiaomi XMWSDJ04MMC"); - ESP_LOGCONFIG(TAG, " Bindkey: %s", format_hex_pretty_to(bindkey_hex, this->bindkey_, XMWSDJ04MMC_BINDKEY_SIZE, '.')); + ESP_LOGCONFIG(TAG, + "Xiaomi XMWSDJ04MMC\n" + " Bindkey: %s", + format_hex_pretty_to(bindkey_hex, this->bindkey_, XMWSDJ04MMC_BINDKEY_SIZE, '.')); LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Humidity", this->humidity_); LOG_SENSOR(" ", "Battery Level", this->battery_level_); diff --git a/esphome/components/xpt2046/touchscreen/xpt2046.cpp b/esphome/components/xpt2046/touchscreen/xpt2046.cpp index fa99e3afa7..84d3daf823 100644 --- a/esphome/components/xpt2046/touchscreen/xpt2046.cpp +++ b/esphome/components/xpt2046/touchscreen/xpt2046.cpp @@ -59,10 +59,8 @@ void XPT2046Component::update_touches() { } void XPT2046Component::dump_config() { - ESP_LOGCONFIG(TAG, "XPT2046:"); - - LOG_PIN(" IRQ Pin: ", this->irq_pin_); ESP_LOGCONFIG(TAG, + "XPT2046:\n" " X min: %d\n" " X max: %d\n" " Y min: %d\n" @@ -73,7 +71,7 @@ void XPT2046Component::dump_config() { " threshold: %d", this->x_raw_min_, this->x_raw_max_, this->y_raw_min_, this->y_raw_max_, YESNO(this->swap_x_y_), YESNO(this->invert_x_), YESNO(this->invert_y_), this->threshold_); - + LOG_PIN(" IRQ Pin: ", this->irq_pin_); LOG_UPDATE_INTERVAL(this); } diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 3baec93186..70593d8153 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -721,6 +721,25 @@ class EsphomeCore: def config_filename(self) -> str: return self.config_path.name + def has_at_least_one_component(self, *components: str) -> bool: + """ + Are any of the given components configured? + :param components: component names + :return: true if so + """ + if self.config is None: + raise ValueError("Config has not been loaded yet") + + return any(component in self.config for component in components) + + @property + def has_networking(self) -> bool: + """ + Is a network component configured? + :return: true if so + """ + return self.has_at_least_one_component("wifi", "ethernet", "openthread") + def relative_config_path(self, *path: str | Path) -> Path: path_ = Path(*path).expanduser() return self.config_dir / path_ diff --git a/tests/components/socket/test_wake_loop_threadsafe.py b/tests/components/socket/test_wake_loop_threadsafe.py index 45e5ea2211..b4bc95176d 100644 --- a/tests/components/socket/test_wake_loop_threadsafe.py +++ b/tests/components/socket/test_wake_loop_threadsafe.py @@ -4,6 +4,7 @@ from esphome.core import CORE def test_require_wake_loop_threadsafe__first_call() -> None: """Test that first call sets up define and consumes socket.""" + CORE.config = {"wifi": True} socket.require_wake_loop_threadsafe() # Verify CORE.data was updated @@ -17,6 +18,7 @@ def test_require_wake_loop_threadsafe__idempotent() -> None: """Test that subsequent calls are idempotent.""" # Set up initial state as if already called CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True + CORE.config = {"ethernet": True} # Call again - should not raise or fail socket.require_wake_loop_threadsafe() @@ -31,6 +33,7 @@ def test_require_wake_loop_threadsafe__idempotent() -> None: def test_require_wake_loop_threadsafe__multiple_calls() -> None: """Test that multiple calls only set up once.""" # Call three times + CORE.config = {"openthread": True} socket.require_wake_loop_threadsafe() socket.require_wake_loop_threadsafe() socket.require_wake_loop_threadsafe() @@ -40,3 +43,35 @@ def test_require_wake_loop_threadsafe__multiple_calls() -> None: # Verify the define was added (only once, but we can just check it exists) assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) + + +def test_require_wake_loop_threadsafe__no_networking() -> None: + """Test that wake loop is NOT configured when no networking is configured.""" + # Set up config without any networking components + CORE.config = {"esphome": {"name": "test"}, "logger": {}} + + # Call require_wake_loop_threadsafe + socket.require_wake_loop_threadsafe() + + # Verify CORE.data flag was NOT set (since has_networking returns False) + assert socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED not in CORE.data + + # Verify the define was NOT added + assert not any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) + + +def test_require_wake_loop_threadsafe__no_networking_does_not_consume_socket() -> None: + """Test that no socket is consumed when no networking is configured.""" + # Set up config without any networking components + CORE.config = {"logger": {}} + + # Track initial socket consumer state + initial_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS, {}) + + # Call require_wake_loop_threadsafe + socket.require_wake_loop_threadsafe() + + # Verify no socket was consumed + consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS, {}) + assert "socket.wake_loop_threadsafe" not in consumers + assert consumers == initial_consumers diff --git a/tests/unit_tests/test_core.py b/tests/unit_tests/test_core.py index e52cb24831..1fc8dab358 100644 --- a/tests/unit_tests/test_core.py +++ b/tests/unit_tests/test_core.py @@ -718,3 +718,65 @@ class TestEsphomeCore: # Even though "web_server" is in loaded_integrations due to the platform, # web_port must return None because the full web_server component is not configured assert target.web_port is None + + def test_has_at_least_one_component__none_configured(self, target): + """Test has_at_least_one_component returns False when none of the components are configured.""" + target.config = {const.CONF_ESPHOME: {"name": "test"}, "logger": {}} + + assert target.has_at_least_one_component("wifi", "ethernet") is False + + def test_has_at_least_one_component__one_configured(self, target): + """Test has_at_least_one_component returns True when one component is configured.""" + target.config = {const.CONF_WIFI: {}, "logger": {}} + + assert target.has_at_least_one_component("wifi", "ethernet") is True + + def test_has_at_least_one_component__multiple_configured(self, target): + """Test has_at_least_one_component returns True when multiple components are configured.""" + target.config = { + const.CONF_WIFI: {}, + const.CONF_ETHERNET: {}, + "logger": {}, + } + + assert ( + target.has_at_least_one_component("wifi", "ethernet", "bluetooth") is True + ) + + def test_has_at_least_one_component__single_component(self, target): + """Test has_at_least_one_component works with a single component.""" + target.config = {const.CONF_MQTT: {}} + + assert target.has_at_least_one_component("mqtt") is True + assert target.has_at_least_one_component("wifi") is False + + def test_has_at_least_one_component__config_not_loaded(self, target): + """Test has_at_least_one_component raises ValueError when config is not loaded.""" + target.config = None + + with pytest.raises(ValueError, match="Config has not been loaded yet"): + target.has_at_least_one_component("wifi") + + def test_has_networking__with_wifi(self, target): + """Test has_networking returns True when wifi is configured.""" + target.config = {const.CONF_WIFI: {}} + + assert target.has_networking is True + + def test_has_networking__with_ethernet(self, target): + """Test has_networking returns True when ethernet is configured.""" + target.config = {const.CONF_ETHERNET: {}} + + assert target.has_networking is True + + def test_has_networking__with_openthread(self, target): + """Test has_networking returns True when openthread is configured.""" + target.config = {const.CONF_OPENTHREAD: {}} + + assert target.has_networking is True + + def test_has_networking__without_networking(self, target): + """Test has_networking returns False when no networking component is configured.""" + target.config = {const.CONF_ESPHOME: {"name": "test"}, "logger": {}} + + assert target.has_networking is False