From 46b6dcdfbf63b660be98e4c6c8448e59b1fae153 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:56:08 -0500 Subject: [PATCH 01/23] [logger] Fix bug causing global log level to be overwritten (#8248) --- esphome/components/logger/__init__.py | 4 ++-- esphome/components/logger/logger.cpp | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index a89bf95c77..113f306327 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -247,8 +247,8 @@ async def to_code(config): ) cg.add(log.pre_setup()) - for tag, level in config[CONF_LOGS].items(): - cg.add(log.set_log_level(tag, LOG_LEVELS[level])) + for tag, log_level in config[CONF_LOGS].items(): + cg.add(log.set_log_level(tag, LOG_LEVELS[log_level])) cg.add_define("USE_LOGGER") this_severity = LOG_LEVEL_SEVERITY.index(level) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 79fc4cf499..57f0ba9f9a 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -102,9 +102,6 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr #endif int HOT Logger::level_for(const char *tag) { - // Uses std::vector<> for low memory footprint, though the vector - // could be sorted to minimize lookup times. This feature isn't used that - // much anyway so it doesn't matter too much. if (this->log_levels_.count(tag) != 0) return this->log_levels_[tag]; return this->current_level_; From 788c41e6f4365f4b3dd6b7fd28d245ac3007dbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20M=C3=A1rai?= Date: Fri, 14 Feb 2025 01:15:01 +0100 Subject: [PATCH 02/23] Add support for the DAC on the S2 (#8030) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32_dac/esp32_dac.cpp | 23 +++++++++++++++------- esphome/components/esp32_dac/esp32_dac.h | 8 ++++++++ esphome/components/esp32_dac/output.py | 20 +++++++++++++++---- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/esphome/components/esp32_dac/esp32_dac.cpp b/esphome/components/esp32_dac/esp32_dac.cpp index 7f37e2ce47..6f1577b8b1 100644 --- a/esphome/components/esp32_dac/esp32_dac.cpp +++ b/esphome/components/esp32_dac/esp32_dac.cpp @@ -7,13 +7,16 @@ #ifdef USE_ARDUINO #include #endif -#ifdef USE_ESP_IDF -#include -#endif namespace esphome { namespace esp32_dac { +#ifdef USE_ESP32_VARIANT_ESP32S2 +static constexpr uint8_t DAC0_PIN = 17; +#else +static constexpr uint8_t DAC0_PIN = 25; +#endif + static const char *const TAG = "esp32_dac"; void ESP32DAC::setup() { @@ -22,8 +25,15 @@ void ESP32DAC::setup() { this->turn_off(); #ifdef USE_ESP_IDF - auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2; - dac_output_enable(channel); + const dac_channel_t channel = this->pin_->get_pin() == DAC0_PIN ? DAC_CHAN_0 : DAC_CHAN_1; + const dac_oneshot_config_t oneshot_cfg{channel}; + dac_oneshot_new_channel(&oneshot_cfg, &this->dac_handle_); +#endif +} + +void ESP32DAC::on_safe_shutdown() { +#ifdef USE_ESP_IDF + dac_oneshot_del_channel(this->dac_handle_); #endif } @@ -40,8 +50,7 @@ void ESP32DAC::write_state(float state) { state = state * 255; #ifdef USE_ESP_IDF - auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2; - dac_output_voltage(channel, (uint8_t) state); + dac_oneshot_output_voltage(this->dac_handle_, state); #endif #ifdef USE_ARDUINO dacWrite(this->pin_->get_pin(), state); diff --git a/esphome/components/esp32_dac/esp32_dac.h b/esphome/components/esp32_dac/esp32_dac.h index 0fb1ddebf0..63d0c914a1 100644 --- a/esphome/components/esp32_dac/esp32_dac.h +++ b/esphome/components/esp32_dac/esp32_dac.h @@ -7,6 +7,10 @@ #ifdef USE_ESP32 +#ifdef USE_ESP_IDF +#include +#endif + namespace esphome { namespace esp32_dac { @@ -16,6 +20,7 @@ class ESP32DAC : public output::FloatOutput, public Component { /// Initialize pin void setup() override; + void on_safe_shutdown() override; void dump_config() override; /// HARDWARE setup_priority float get_setup_priority() const override { return setup_priority::HARDWARE; } @@ -24,6 +29,9 @@ class ESP32DAC : public output::FloatOutput, public Component { void write_state(float state) override; InternalGPIOPin *pin_; +#ifdef USE_ESP_IDF + dac_oneshot_handle_t dac_handle_; +#endif }; } // namespace esp32_dac diff --git a/esphome/components/esp32_dac/output.py b/esphome/components/esp32_dac/output.py index f119198618..c80780986f 100644 --- a/esphome/components/esp32_dac/output.py +++ b/esphome/components/esp32_dac/output.py @@ -1,15 +1,27 @@ +import esphome.codegen as cg +import esphome.config_validation as cv from esphome import pins from esphome.components import output -import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32.const import VARIANT_ESP32, VARIANT_ESP32S2 from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN DEPENDENCIES = ["esp32"] +DAC_PINS = { + VARIANT_ESP32: (25, 26), + VARIANT_ESP32S2: (17, 18), +} + def valid_dac_pin(value): - num = value[CONF_NUMBER] - cv.one_of(25, 26)(num) + variant = get_esp32_variant() + try: + valid_pins = DAC_PINS[variant] + except KeyError as ex: + raise cv.Invalid(f"DAC is not supported on {variant}") from ex + given_pin = value[CONF_NUMBER] + cv.one_of(*valid_pins)(given_pin) return value From 143b0d3de429a0d9adca0f888829af56ab10904d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:27:11 +1300 Subject: [PATCH 03/23] Fix crash when storage file doesnt exist yet (#8249) --- esphome/dashboard/web_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 67712da9b6..b8562aaccb 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -853,7 +853,7 @@ class InfoRequestHandler(BaseHandler): dashboard = DASHBOARD entry = dashboard.entries.get(yaml_path) - if not entry: + if not entry or entry.storage is None: self.set_status(404) return From 1111aa167f319bad7a778b54745cf495662e8138 Mon Sep 17 00:00:00 2001 From: guillempages Date: Wed, 12 Feb 2025 10:55:32 +0100 Subject: [PATCH 04/23] [online_image]Fix reset if buffer not allocated (#8236) --- .../components/online_image/image_decoder.cpp | 11 +++++++---- esphome/components/online_image/jpeg_image.cpp | 6 ++++-- .../components/online_image/online_image.cpp | 15 ++++++++------- esphome/components/online_image/online_image.h | 17 +++++++++++++++-- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/esphome/components/online_image/image_decoder.cpp b/esphome/components/online_image/image_decoder.cpp index d8c0cc33c4..0ab7dadde3 100644 --- a/esphome/components/online_image/image_decoder.cpp +++ b/esphome/components/online_image/image_decoder.cpp @@ -9,10 +9,10 @@ namespace online_image { static const char *const TAG = "online_image.decoder"; bool ImageDecoder::set_size(int width, int height) { - bool resized = this->image_->resize_(width, height); + bool success = this->image_->resize_(width, height) > 0; this->x_scale_ = static_cast(this->image_->buffer_width_) / width; this->y_scale_ = static_cast(this->image_->buffer_height_) / height; - return resized; + return success; } void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) { @@ -51,8 +51,9 @@ size_t DownloadBuffer::read(size_t len) { } size_t DownloadBuffer::resize(size_t size) { - if (this->size_ == size) { - return size; + if (this->size_ >= size) { + // Avoid useless reallocations; if the buffer is big enough, don't reallocate. + return this->size_; } this->allocator_.deallocate(this->buffer_, this->size_); this->buffer_ = this->allocator_.allocate(size); @@ -61,6 +62,8 @@ size_t DownloadBuffer::resize(size_t size) { this->size_ = size; return size; } else { + ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", size, + this->allocator_.get_max_free_block_size()); this->size_ = 0; return 0; } diff --git a/esphome/components/online_image/jpeg_image.cpp b/esphome/components/online_image/jpeg_image.cpp index 0aff576da8..e5ee3dd8bf 100644 --- a/esphome/components/online_image/jpeg_image.cpp +++ b/esphome/components/online_image/jpeg_image.cpp @@ -58,7 +58,7 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) { } if (!this->jpeg_.openRAM(buffer, size, draw_callback)) { - ESP_LOGE(TAG, "Could not open image for decoding."); + ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError()); return DECODE_ERROR_INVALID_TYPE; } auto jpeg_type = this->jpeg_.getJPEGType(); @@ -73,7 +73,9 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) { this->jpeg_.setUserPointer(this); this->jpeg_.setPixelType(RGB8888); - this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight()); + if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) { + return DECODE_ERROR_OUT_OF_MEMORY; + } if (!this->jpeg_.decode(0, 0, 0)) { ESP_LOGE(TAG, "Error while decoding."); this->jpeg_.close(); diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index 3b3d00a044..3411018901 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -64,33 +64,34 @@ void OnlineImage::release() { } } -bool OnlineImage::resize_(int width_in, int height_in) { +size_t OnlineImage::resize_(int width_in, int height_in) { int width = this->fixed_width_; int height = this->fixed_height_; - if (this->auto_resize_()) { + if (this->is_auto_resize_()) { width = width_in; height = height_in; if (this->width_ != width && this->height_ != height) { this->release(); } } - if (this->buffer_) { - return false; - } size_t new_size = this->get_buffer_size_(width, height); + if (this->buffer_) { + // Buffer already allocated => no need to resize + return new_size; + } ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size); this->buffer_ = this->allocator_.allocate(new_size); if (this->buffer_ == nullptr) { ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size, this->allocator_.get_max_free_block_size()); this->end_connection_(); - return false; + return 0; } this->buffer_width_ = width; this->buffer_height_ = height; this->width_ = width; ESP_LOGV(TAG, "New size: (%d, %d)", width, height); - return true; + return new_size; } void OnlineImage::update() { diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 4abc047083..2d10e528b1 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -99,9 +99,22 @@ class OnlineImage : public PollingComponent, int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; } - ESPHOME_ALWAYS_INLINE bool auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; } + ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; } - bool resize_(int width, int height); + /** + * @brief Resize the image buffer to the requested dimensions. + * + * The buffer will be allocated if not existing. + * If the dimensions have been fixed in the yaml config, the buffer will be created + * with those dimensions and not resized, even on request. + * Otherwise, the old buffer will be deallocated and a new buffer with the requested + * allocated + * + * @param width + * @param height + * @return 0 if no memory could be allocated, the size of the new buffer otherwise. + */ + size_t resize_(int width, int height); /** * @brief Draw a pixel into the buffer. From 92ad6286aa0440292caac66eb9374474608bdd36 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:56:08 -0500 Subject: [PATCH 05/23] [logger] Fix bug causing global log level to be overwritten (#8248) --- esphome/components/logger/__init__.py | 4 ++-- esphome/components/logger/logger.cpp | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index a89bf95c77..113f306327 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -247,8 +247,8 @@ async def to_code(config): ) cg.add(log.pre_setup()) - for tag, level in config[CONF_LOGS].items(): - cg.add(log.set_log_level(tag, LOG_LEVELS[level])) + for tag, log_level in config[CONF_LOGS].items(): + cg.add(log.set_log_level(tag, LOG_LEVELS[log_level])) cg.add_define("USE_LOGGER") this_severity = LOG_LEVEL_SEVERITY.index(level) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 79fc4cf499..57f0ba9f9a 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -102,9 +102,6 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr #endif int HOT Logger::level_for(const char *tag) { - // Uses std::vector<> for low memory footprint, though the vector - // could be sorted to minimize lookup times. This feature isn't used that - // much anyway so it doesn't matter too much. if (this->log_levels_.count(tag) != 0) return this->log_levels_[tag]; return this->current_level_; From 6999cc0581ae1e69fbbaab8027e0e43d77670849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20M=C3=A1rai?= Date: Fri, 14 Feb 2025 01:15:01 +0100 Subject: [PATCH 06/23] Add support for the DAC on the S2 (#8030) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32_dac/esp32_dac.cpp | 23 +++++++++++++++------- esphome/components/esp32_dac/esp32_dac.h | 8 ++++++++ esphome/components/esp32_dac/output.py | 20 +++++++++++++++---- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/esphome/components/esp32_dac/esp32_dac.cpp b/esphome/components/esp32_dac/esp32_dac.cpp index 7f37e2ce47..6f1577b8b1 100644 --- a/esphome/components/esp32_dac/esp32_dac.cpp +++ b/esphome/components/esp32_dac/esp32_dac.cpp @@ -7,13 +7,16 @@ #ifdef USE_ARDUINO #include #endif -#ifdef USE_ESP_IDF -#include -#endif namespace esphome { namespace esp32_dac { +#ifdef USE_ESP32_VARIANT_ESP32S2 +static constexpr uint8_t DAC0_PIN = 17; +#else +static constexpr uint8_t DAC0_PIN = 25; +#endif + static const char *const TAG = "esp32_dac"; void ESP32DAC::setup() { @@ -22,8 +25,15 @@ void ESP32DAC::setup() { this->turn_off(); #ifdef USE_ESP_IDF - auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2; - dac_output_enable(channel); + const dac_channel_t channel = this->pin_->get_pin() == DAC0_PIN ? DAC_CHAN_0 : DAC_CHAN_1; + const dac_oneshot_config_t oneshot_cfg{channel}; + dac_oneshot_new_channel(&oneshot_cfg, &this->dac_handle_); +#endif +} + +void ESP32DAC::on_safe_shutdown() { +#ifdef USE_ESP_IDF + dac_oneshot_del_channel(this->dac_handle_); #endif } @@ -40,8 +50,7 @@ void ESP32DAC::write_state(float state) { state = state * 255; #ifdef USE_ESP_IDF - auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2; - dac_output_voltage(channel, (uint8_t) state); + dac_oneshot_output_voltage(this->dac_handle_, state); #endif #ifdef USE_ARDUINO dacWrite(this->pin_->get_pin(), state); diff --git a/esphome/components/esp32_dac/esp32_dac.h b/esphome/components/esp32_dac/esp32_dac.h index 0fb1ddebf0..63d0c914a1 100644 --- a/esphome/components/esp32_dac/esp32_dac.h +++ b/esphome/components/esp32_dac/esp32_dac.h @@ -7,6 +7,10 @@ #ifdef USE_ESP32 +#ifdef USE_ESP_IDF +#include +#endif + namespace esphome { namespace esp32_dac { @@ -16,6 +20,7 @@ class ESP32DAC : public output::FloatOutput, public Component { /// Initialize pin void setup() override; + void on_safe_shutdown() override; void dump_config() override; /// HARDWARE setup_priority float get_setup_priority() const override { return setup_priority::HARDWARE; } @@ -24,6 +29,9 @@ class ESP32DAC : public output::FloatOutput, public Component { void write_state(float state) override; InternalGPIOPin *pin_; +#ifdef USE_ESP_IDF + dac_oneshot_handle_t dac_handle_; +#endif }; } // namespace esp32_dac diff --git a/esphome/components/esp32_dac/output.py b/esphome/components/esp32_dac/output.py index f119198618..c80780986f 100644 --- a/esphome/components/esp32_dac/output.py +++ b/esphome/components/esp32_dac/output.py @@ -1,15 +1,27 @@ +import esphome.codegen as cg +import esphome.config_validation as cv from esphome import pins from esphome.components import output -import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32.const import VARIANT_ESP32, VARIANT_ESP32S2 from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN DEPENDENCIES = ["esp32"] +DAC_PINS = { + VARIANT_ESP32: (25, 26), + VARIANT_ESP32S2: (17, 18), +} + def valid_dac_pin(value): - num = value[CONF_NUMBER] - cv.one_of(25, 26)(num) + variant = get_esp32_variant() + try: + valid_pins = DAC_PINS[variant] + except KeyError as ex: + raise cv.Invalid(f"DAC is not supported on {variant}") from ex + given_pin = value[CONF_NUMBER] + cv.one_of(*valid_pins)(given_pin) return value From daa796003174623ab31532158c8d3d8ef484b9e5 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:27:11 +1300 Subject: [PATCH 07/23] Fix crash when storage file doesnt exist yet (#8249) --- esphome/dashboard/web_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 67712da9b6..b8562aaccb 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -853,7 +853,7 @@ class InfoRequestHandler(BaseHandler): dashboard = DASHBOARD entry = dashboard.entries.get(yaml_path) - if not entry: + if not entry or entry.storage is None: self.set_status(404) return From e17582544e51aad38233ae8e2f249572d91bfe54 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:28:42 +1300 Subject: [PATCH 08/23] Bump version to 2025.2.0b3 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 7390187d7e..2f3854b8b3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2025.2.0b2" +__version__ = "2025.2.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 93c2878c213acb8cbb88f604b21abeb1302ab2ba Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sat, 15 Feb 2025 23:02:51 -0800 Subject: [PATCH 09/23] don't crash on null pages (#8254) Co-authored-by: Samuel Sieb --- esphome/components/display/display.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 202c64ef14..b12a81e050 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -815,8 +815,20 @@ void Display::test_card() { DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {} void DisplayPage::show() { this->parent_->show_page(this); } -void DisplayPage::show_next() { this->next_->show(); } -void DisplayPage::show_prev() { this->prev_->show(); } +void DisplayPage::show_next() { + if (this->next_ == nullptr) { + ESP_LOGE(TAG, "no next page"); + return; + } + this->next_->show(); +} +void DisplayPage::show_prev() { + if (this->prev_ == nullptr) { + ESP_LOGE(TAG, "no previous page"); + return; + } + this->prev_->show(); +} void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; } void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; } void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; } From e21ef22706e5241a8c1cd3dc6b1583d3f061898d Mon Sep 17 00:00:00 2001 From: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com> Date: Sun, 16 Feb 2025 20:09:42 +0100 Subject: [PATCH 10/23] [scd30] Increase minimal CONF_UPDATE_INTERVAL from 1 to 2 seconds (#8256) --- esphome/components/scd30/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index a900c51a58..cee8cc7b71 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -75,7 +75,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All( cv.positive_time_period_seconds, cv.Range( - min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800) + min=core.TimePeriod(seconds=2), max=core.TimePeriod(seconds=1800) ), ), } From 2e66b3367258a1fd4cb02d46cdcbd32002498c06 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 16 Feb 2025 11:53:19 -0800 Subject: [PATCH 11/23] Bump zeroconf to 0.144.3 (#8253) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8eca21c4bb..bb5bc768e1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ esptool==4.7.0 click==8.1.7 esphome-dashboard==20250212.0 aioesphomeapi==24.6.2 -zeroconf==0.144.1 +zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import glyphsets==1.0.0 From a47e27885fe1c249f7594da8249d4f8d6891def2 Mon Sep 17 00:00:00 2001 From: Ali Jafri Date: Mon, 17 Feb 2025 03:35:54 +0530 Subject: [PATCH 12/23] DHT platform now supports modules with inbuilt external resistor (#8257) --- esphome/components/dht/dht.cpp | 3 ++- esphome/components/dht/sensor.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 5a18f6f36e..f2a33a26ac 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -23,6 +23,7 @@ void DHT::dump_config() { } else { ESP_LOGCONFIG(TAG, " Model: DHT22 (or equivalent)"); } + ESP_LOGCONFIG(TAG, " Internal Pull-up: %s", ONOFF(this->pin_->get_flags() & gpio::FLAG_PULLUP)); LOG_UPDATE_INTERVAL(this); @@ -101,7 +102,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r } else { delayMicroseconds(800); } - this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + this->pin_->pin_mode(this->pin_->get_flags()); { InterruptLock lock; diff --git a/esphome/components/dht/sensor.py b/esphome/components/dht/sensor.py index da92a97e1f..be53df2625 100644 --- a/esphome/components/dht/sensor.py +++ b/esphome/components/dht/sensor.py @@ -34,7 +34,7 @@ DHT = dht_ns.class_("DHT", cg.PollingComponent) CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(DHT), - cv.Required(CONF_PIN): pins.internal_gpio_input_pin_schema, + cv.Required(CONF_PIN): pins.internal_gpio_input_pullup_pin_schema, cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, From a67b85eabf4f584ef4a7d136bee5f04421d8defe Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Sat, 15 Feb 2025 23:02:51 -0800 Subject: [PATCH 13/23] don't crash on null pages (#8254) Co-authored-by: Samuel Sieb --- esphome/components/display/display.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 202c64ef14..b12a81e050 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -815,8 +815,20 @@ void Display::test_card() { DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {} void DisplayPage::show() { this->parent_->show_page(this); } -void DisplayPage::show_next() { this->next_->show(); } -void DisplayPage::show_prev() { this->prev_->show(); } +void DisplayPage::show_next() { + if (this->next_ == nullptr) { + ESP_LOGE(TAG, "no next page"); + return; + } + this->next_->show(); +} +void DisplayPage::show_prev() { + if (this->prev_ == nullptr) { + ESP_LOGE(TAG, "no previous page"); + return; + } + this->prev_->show(); +} void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; } void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; } void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; } From c0804d665d5eed0e82474304c399b87b0a25e0ab Mon Sep 17 00:00:00 2001 From: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com> Date: Sun, 16 Feb 2025 20:09:42 +0100 Subject: [PATCH 14/23] [scd30] Increase minimal CONF_UPDATE_INTERVAL from 1 to 2 seconds (#8256) --- esphome/components/scd30/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index a900c51a58..cee8cc7b71 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -75,7 +75,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All( cv.positive_time_period_seconds, cv.Range( - min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800) + min=core.TimePeriod(seconds=2), max=core.TimePeriod(seconds=1800) ), ), } From e89603fe3b1b489b57ec91436d192ed651bb0048 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 16 Feb 2025 11:53:19 -0800 Subject: [PATCH 15/23] Bump zeroconf to 0.144.3 (#8253) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8eca21c4bb..bb5bc768e1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ esptool==4.7.0 click==8.1.7 esphome-dashboard==20250212.0 aioesphomeapi==24.6.2 -zeroconf==0.144.1 +zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import glyphsets==1.0.0 From 9ee5227fe05f8f91b9a907644dc0565136a3afdd Mon Sep 17 00:00:00 2001 From: Ali Jafri Date: Mon, 17 Feb 2025 03:35:54 +0530 Subject: [PATCH 16/23] DHT platform now supports modules with inbuilt external resistor (#8257) --- esphome/components/dht/dht.cpp | 3 ++- esphome/components/dht/sensor.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 5a18f6f36e..f2a33a26ac 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -23,6 +23,7 @@ void DHT::dump_config() { } else { ESP_LOGCONFIG(TAG, " Model: DHT22 (or equivalent)"); } + ESP_LOGCONFIG(TAG, " Internal Pull-up: %s", ONOFF(this->pin_->get_flags() & gpio::FLAG_PULLUP)); LOG_UPDATE_INTERVAL(this); @@ -101,7 +102,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r } else { delayMicroseconds(800); } - this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + this->pin_->pin_mode(this->pin_->get_flags()); { InterruptLock lock; diff --git a/esphome/components/dht/sensor.py b/esphome/components/dht/sensor.py index da92a97e1f..be53df2625 100644 --- a/esphome/components/dht/sensor.py +++ b/esphome/components/dht/sensor.py @@ -34,7 +34,7 @@ DHT = dht_ns.class_("DHT", cg.PollingComponent) CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(DHT), - cv.Required(CONF_PIN): pins.internal_gpio_input_pin_schema, + cv.Required(CONF_PIN): pins.internal_gpio_input_pullup_pin_schema, cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, From 78b55e22ee4148d3769c50548d73e752b3765bb4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:14:06 +1300 Subject: [PATCH 17/23] Bump version to 2025.2.0b4 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 2f3854b8b3..7c96e6eefb 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2025.2.0b3" +__version__ = "2025.2.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 1eb658cc5b0c8bdae8c7601298714e60eef9c415 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 17 Feb 2025 15:48:24 -0600 Subject: [PATCH 18/23] Replace glyphsets with esphome_glyphsets (#8261) --- esphome/components/font/__init__.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index e2051298fe..4f569379be 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -5,8 +5,8 @@ import os from pathlib import Path import re +import esphome_glyphsets as glyphsets import freetype -import glyphsets import requests from esphome import core, external_files diff --git a/requirements.txt b/requirements.txt index bb5bc768e1..b3a48a0442 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ aioesphomeapi==24.6.2 zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import -glyphsets==1.0.0 +esphome-glyphsets==0.1.0 pillow==10.4.0 freetype-py==2.5.1 From c21b8bd4172c6b4bd7468b5d9e74de85078fb7c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 17 Feb 2025 16:19:11 -0600 Subject: [PATCH 19/23] Switch to native arm runners for docker CI (#8262) --- .github/workflows/ci-docker.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 8de6191205..303a6a777f 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -33,11 +33,11 @@ concurrency: jobs: check-docker: name: Build docker containers - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - arch: [amd64, aarch64] + os: ["ubuntu-latest", "ubuntu-24.04-arm"] build_type: ["ha-addon", "docker", "lint"] steps: - uses: actions/checkout@v4.1.7 @@ -47,8 +47,6 @@ jobs: python-version: "3.9" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.9.0 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3.4.0 - name: Set TAG run: | @@ -58,6 +56,6 @@ jobs: run: | docker/build.py \ --tag "${TAG}" \ - --arch "${{ matrix.arch }}" \ + --arch "${{ matrix.os == 'ubuntu-24.04-arm' && 'aarch64' || 'amd64' }}" \ --build-type "${{ matrix.build_type }}" \ build From 74f7197543e2792262507595b5eccfd8dc0b32f4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 17 Feb 2025 16:27:06 -0600 Subject: [PATCH 20/23] Bump aioesphomeapi to 29.1.0 (#8105) --- esphome/components/api/client.py | 11 ++++++++--- requirements.txt | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index dd013c8c34..c61b8d5ea3 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -1,12 +1,11 @@ from __future__ import annotations import asyncio -import logging from datetime import datetime -from typing import Any +import logging +from typing import TYPE_CHECKING, Any from aioesphomeapi import APIClient -from aioesphomeapi.api_pb2 import SubscribeLogsResponse from aioesphomeapi.log_runner import async_run from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__ @@ -14,6 +13,12 @@ from esphome.core import CORE from . import CONF_ENCRYPTION +if TYPE_CHECKING: + from aioesphomeapi.api_pb2 import ( + SubscribeLogsResponse, # pylint: disable=no-name-in-module + ) + + _LOGGER = logging.getLogger(__name__) diff --git a/requirements.txt b/requirements.txt index b3a48a0442..c15dcbbbf7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.16 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20250212.0 -aioesphomeapi==24.6.2 +aioesphomeapi==29.1.0 zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import From f9da8dbfb85e329be30dfcf02bfc6431ef1fa81c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 17 Feb 2025 15:48:24 -0600 Subject: [PATCH 21/23] Replace glyphsets with esphome_glyphsets (#8261) --- esphome/components/font/__init__.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index e2051298fe..4f569379be 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -5,8 +5,8 @@ import os from pathlib import Path import re +import esphome_glyphsets as glyphsets import freetype -import glyphsets import requests from esphome import core, external_files diff --git a/requirements.txt b/requirements.txt index bb5bc768e1..b3a48a0442 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ aioesphomeapi==24.6.2 zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import -glyphsets==1.0.0 +esphome-glyphsets==0.1.0 pillow==10.4.0 freetype-py==2.5.1 From 64c8bcef2e562ebdb2d398d5c66c80c417b8129f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 17 Feb 2025 16:27:06 -0600 Subject: [PATCH 22/23] Bump aioesphomeapi to 29.1.0 (#8105) --- esphome/components/api/client.py | 11 ++++++++--- requirements.txt | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index dd013c8c34..c61b8d5ea3 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -1,12 +1,11 @@ from __future__ import annotations import asyncio -import logging from datetime import datetime -from typing import Any +import logging +from typing import TYPE_CHECKING, Any from aioesphomeapi import APIClient -from aioesphomeapi.api_pb2 import SubscribeLogsResponse from aioesphomeapi.log_runner import async_run from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__ @@ -14,6 +13,12 @@ from esphome.core import CORE from . import CONF_ENCRYPTION +if TYPE_CHECKING: + from aioesphomeapi.api_pb2 import ( + SubscribeLogsResponse, # pylint: disable=no-name-in-module + ) + + _LOGGER = logging.getLogger(__name__) diff --git a/requirements.txt b/requirements.txt index b3a48a0442..c15dcbbbf7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.16 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20250212.0 -aioesphomeapi==24.6.2 +aioesphomeapi==29.1.0 zeroconf==0.144.3 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import From 6583e178107e63446ad9a21b3ebf82b7533d8c93 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:39:42 +1300 Subject: [PATCH 23/23] Bump version to 2025.2.0b5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 7c96e6eefb..7f576fce67 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2025.2.0b4" +__version__ = "2025.2.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = (