From 89c3340ef6f6c24b5fe4f6e90ef4549e36aeb1d9 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Fri, 3 Oct 2025 23:06:16 +1000 Subject: [PATCH 1/7] [mpr121] remove delay (#10963) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/mpr121/mpr121.cpp | 75 ++++++++++++++-------------- esphome/components/mpr121/mpr121.h | 2 +- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/esphome/components/mpr121/mpr121.cpp b/esphome/components/mpr121/mpr121.cpp index 074bc79ea2..60d8235b03 100644 --- a/esphome/components/mpr121/mpr121.cpp +++ b/esphome/components/mpr121/mpr121.cpp @@ -13,45 +13,46 @@ static const char *const TAG = "mpr121"; void MPR121Component::setup() { // soft reset device this->write_byte(MPR121_SOFTRESET, 0x63); - delay(100); // NOLINT - if (!this->write_byte(MPR121_ECR, 0x0)) { - this->error_code_ = COMMUNICATION_FAILED; - this->mark_failed(); - return; - } + this->set_timeout(100, [this]() { + if (!this->write_byte(MPR121_ECR, 0x0)) { + this->error_code_ = COMMUNICATION_FAILED; + this->mark_failed(); + return; + } + // set touch sensitivity for all 12 channels + for (auto *channel : this->channels_) { + channel->setup(); + } + this->write_byte(MPR121_MHDR, 0x01); + this->write_byte(MPR121_NHDR, 0x01); + this->write_byte(MPR121_NCLR, 0x0E); + this->write_byte(MPR121_FDLR, 0x00); - // set touch sensitivity for all 12 channels - for (auto *channel : this->channels_) { - channel->setup(); - } - this->write_byte(MPR121_MHDR, 0x01); - this->write_byte(MPR121_NHDR, 0x01); - this->write_byte(MPR121_NCLR, 0x0E); - this->write_byte(MPR121_FDLR, 0x00); + this->write_byte(MPR121_MHDF, 0x01); + this->write_byte(MPR121_NHDF, 0x05); + this->write_byte(MPR121_NCLF, 0x01); + this->write_byte(MPR121_FDLF, 0x00); - this->write_byte(MPR121_MHDF, 0x01); - this->write_byte(MPR121_NHDF, 0x05); - this->write_byte(MPR121_NCLF, 0x01); - this->write_byte(MPR121_FDLF, 0x00); + this->write_byte(MPR121_NHDT, 0x00); + this->write_byte(MPR121_NCLT, 0x00); + this->write_byte(MPR121_FDLT, 0x00); - this->write_byte(MPR121_NHDT, 0x00); - this->write_byte(MPR121_NCLT, 0x00); - this->write_byte(MPR121_FDLT, 0x00); + this->write_byte(MPR121_DEBOUNCE, 0); + // default, 16uA charge current + this->write_byte(MPR121_CONFIG1, 0x10); + // 0.5uS encoding, 1ms period + this->write_byte(MPR121_CONFIG2, 0x20); - this->write_byte(MPR121_DEBOUNCE, 0); - // default, 16uA charge current - this->write_byte(MPR121_CONFIG1, 0x10); - // 0.5uS encoding, 1ms period - this->write_byte(MPR121_CONFIG2, 0x20); + // Write the Electrode Configuration Register + // * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits. + // * The 2 bits below is "Proximity Enable" and are left at 0. + // * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled + // as a range, starting at 0 up to the highest channel index used. + this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1)); - // Write the Electrode Configuration Register - // * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits. - // * The 2 bits below is "Proximity Enable" and are left at 0. - // * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled - // as a range, starting at 0 up to the highest channel index used. - this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1)); - - this->flush_gpio_(); + this->flush_gpio_(); + this->setup_complete_ = true; + }); } void MPR121Component::set_touch_debounce(uint8_t debounce) { @@ -73,15 +74,15 @@ void MPR121Component::dump_config() { case COMMUNICATION_FAILED: ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); break; - case WRONG_CHIP_STATE: - ESP_LOGE(TAG, "MPR121 has wrong default value for CONFIG2?"); - break; case NONE: default: break; } } void MPR121Component::loop() { + if (!this->setup_complete_) + return; + uint16_t val = 0; this->read_byte_16(MPR121_TOUCHSTATUS_L, &val); diff --git a/esphome/components/mpr121/mpr121.h b/esphome/components/mpr121/mpr121.h index eb2e2edc57..8f942f3e98 100644 --- a/esphome/components/mpr121/mpr121.h +++ b/esphome/components/mpr121/mpr121.h @@ -80,6 +80,7 @@ class MPR121Component : public Component, public i2c::I2CDevice { void pin_mode(uint8_t ionum, gpio::Flags flags); protected: + bool setup_complete_{false}; std::vector channels_{}; uint8_t debounce_{0}; uint8_t touch_threshold_{}; @@ -88,7 +89,6 @@ class MPR121Component : public Component, public i2c::I2CDevice { enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, - WRONG_CHIP_STATE, } error_code_{NONE}; bool flush_gpio_(); From 2b389bb8f2a3d02ede8b7cafa32cdf9351145382 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Fri, 3 Oct 2025 23:40:43 +1000 Subject: [PATCH 2/7] [sps30] remove delay (#10964) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/sps30/sps30.cpp | 30 +++++++++++++++++------------- esphome/components/sps30/sps30.h | 3 +++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/esphome/components/sps30/sps30.cpp b/esphome/components/sps30/sps30.cpp index b99bf416d6..dc14e3a610 100644 --- a/esphome/components/sps30/sps30.cpp +++ b/esphome/components/sps30/sps30.cpp @@ -45,24 +45,26 @@ void SPS30Component::setup() { } ESP_LOGV(TAG, " Serial number: %s", this->serial_number_); - bool result; if (this->fan_interval_.has_value()) { // override default value - result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value()); + this->result_ = + this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value()); } else { - result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS); - } - if (result) { - delay(20); - uint16_t secs[2]; - if (this->read_data(secs, 2)) { - this->fan_interval_ = secs[0] << 16 | secs[1]; - } + this->result_ = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS); } - this->status_clear_warning(); - this->skipped_data_read_cycles_ = 0; - this->start_continuous_measurement_(); + this->set_timeout(20, [this]() { + if (this->result_) { + uint16_t secs[2]; + if (this->read_data(secs, 2)) { + this->fan_interval_ = secs[0] << 16 | secs[1]; + } + } + this->status_clear_warning(); + this->skipped_data_read_cycles_ = 0; + this->start_continuous_measurement_(); + this->setup_complete_ = true; + }); }); } @@ -111,6 +113,8 @@ void SPS30Component::dump_config() { } void SPS30Component::update() { + if (!this->setup_complete_) + return; /// Check if warning flag active (sensor reconnected?) if (this->status_has_warning()) { ESP_LOGD(TAG, "Reconnecting"); diff --git a/esphome/components/sps30/sps30.h b/esphome/components/sps30/sps30.h index 461a770ab6..cab5a075a0 100644 --- a/esphome/components/sps30/sps30.h +++ b/esphome/components/sps30/sps30.h @@ -30,9 +30,12 @@ class SPS30Component : public PollingComponent, public sensirion_common::Sensiri bool start_fan_cleaning(); protected: + bool result_{false}; + bool setup_complete_{false}; uint16_t raw_firmware_version_; char serial_number_[17] = {0}; /// Terminating NULL character uint8_t skipped_data_read_cycles_ = 0; + bool start_continuous_measurement_(); enum ErrorCode : uint8_t { From 14a23101f2ddf9e3473451d9779fe0b712d592a0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:35:55 -0400 Subject: [PATCH 3/7] [core] Fix MQTT import (#10982) --- esphome/__main__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 38edcb070f..b0f541f521 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -14,9 +14,11 @@ from typing import Protocol import argcomplete +# Note: Do not import modules from esphome.components here, as this would +# cause them to be loaded before external components are processed, resulting +# in the built-in version being used instead of the external component one. from esphome import const, writer, yaml_util import esphome.codegen as cg -from esphome.components.mqtt import CONF_DISCOVER_IP from esphome.config import iter_component_configs, read_config, strip_default_ids from esphome.const import ( ALLOWED_NAME_CHARS, @@ -240,6 +242,8 @@ def has_ota() -> bool: def has_mqtt_ip_lookup() -> bool: """Check if MQTT is available and IP lookup is supported.""" + from esphome.components.mqtt import CONF_DISCOVER_IP + if CONF_MQTT not in CORE.config: return False # Default Enabled From ca0e738799f62e8fc2170fb6dd2ba03e5f117355 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 3 Oct 2025 10:50:21 -0500 Subject: [PATCH 4/7] [logger] Fix line number wrapping bug for files with >999 lines (#10979) --- esphome/components/logger/logger.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 7d4c14df0b..f0e0ed9a27 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -355,9 +355,18 @@ class Logger : public Component { buffer[pos++] = '['; copy_string(buffer, pos, tag); buffer[pos++] = ':'; - buffer[pos++] = '0' + (line / 100) % 10; - buffer[pos++] = '0' + (line / 10) % 10; - buffer[pos++] = '0' + line % 10; + // Format line number without modulo operations (passed by value, safe to mutate) + if (line > 999) [[unlikely]] { + int thousands = line / 1000; + buffer[pos++] = '0' + thousands; + line -= thousands * 1000; + } + int hundreds = line / 100; + int remainder = line - hundreds * 100; + int tens = remainder / 10; + buffer[pos++] = '0' + hundreds; + buffer[pos++] = '0' + tens; + buffer[pos++] = '0' + (remainder - tens * 10); buffer[pos++] = ']'; #if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) From 6f8e82aeb682533d3a602dad1c05d3fe91e57860 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:27:29 -0500 Subject: [PATCH 5/7] Bump actions/stale from 10.0.0 to 10.1.0 (#11001) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f57f0987ec..63a8ade37f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 + uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0 with: debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch remove-stale-when-updated: true From 2596b6096fcac0ace8ed4462da423a88806aa627 Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Fri, 3 Oct 2025 13:28:38 -0600 Subject: [PATCH 6/7] Fix log level selector when selecting levels above INFO (#10368) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../logger/select/logger_level_select.cpp | 13 ++++++------- .../components/logger/select/logger_level_select.h | 7 +++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/esphome/components/logger/select/logger_level_select.cpp b/esphome/components/logger/select/logger_level_select.cpp index d9c950ce3c..6d60a3ae47 100644 --- a/esphome/components/logger/select/logger_level_select.cpp +++ b/esphome/components/logger/select/logger_level_select.cpp @@ -3,11 +3,10 @@ namespace esphome::logger { void LoggerLevelSelect::publish_state(int level) { - auto value = this->at(level); - if (!value) { + const auto &option = this->at(level_to_index(level)); + if (!option) return; - } - Select::publish_state(value.value()); + Select::publish_state(option.value()); } void LoggerLevelSelect::setup() { @@ -16,10 +15,10 @@ void LoggerLevelSelect::setup() { } void LoggerLevelSelect::control(const std::string &value) { - auto level = this->index_of(value); - if (!level) + const auto index = this->index_of(value); + if (!index) return; - this->parent_->set_log_level(level.value()); + this->parent_->set_log_level(index_to_level(index.value())); } } // namespace esphome::logger diff --git a/esphome/components/logger/select/logger_level_select.h b/esphome/components/logger/select/logger_level_select.h index f31a6f6cdb..0631eca45d 100644 --- a/esphome/components/logger/select/logger_level_select.h +++ b/esphome/components/logger/select/logger_level_select.h @@ -3,11 +3,18 @@ #include "esphome/components/select/select.h" #include "esphome/core/component.h" #include "esphome/components/logger/logger.h" + namespace esphome::logger { class LoggerLevelSelect : public Component, public select::Select, public Parented { public: void publish_state(int level); void setup() override; void control(const std::string &value) override; + + protected: + // Convert log level to option index (skip CONFIG at level 4) + static uint8_t level_to_index(uint8_t level) { return (level > ESPHOME_LOG_LEVEL_CONFIG) ? level - 1 : level; } + // Convert option index to log level (skip CONFIG at level 4) + static uint8_t index_to_level(uint8_t index) { return (index >= ESPHOME_LOG_LEVEL_CONFIG) ? index + 1 : index; } }; } // namespace esphome::logger From d43b844e06b0a01f6ef0c550d7c95108fd09cbdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:28:58 -0500 Subject: [PATCH 7/7] Bump ruff from 0.13.2 to 0.13.3 (#11000) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 818f360860..3c1b888cfd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.13.2 + rev: v0.13.3 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 59ea77fd2d..f2be6f3a24 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==3.3.8 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.13.2 # also change in .pre-commit-config.yaml when updating +ruff==0.13.3 # also change in .pre-commit-config.yaml when updating pyupgrade==3.20.0 # also change in .pre-commit-config.yaml when updating pre-commit