diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index c618a5ca97..1f5812691e 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -22,7 +22,7 @@ runs: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.1.1 with: path: venv # yamllint disable-line rule:line-length diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c4fa65695..38527c20c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.1.1 with: path: venv # yamllint disable-line rule:line-length @@ -302,14 +302,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.1.1 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.1.1 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8995c500ef..26a213f170 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -141,7 +141,7 @@ jobs: echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT - name: Upload digests - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4.4.3 with: name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 47058badce..48240464b3 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -244,7 +244,7 @@ void CSE7766Component::dump_config() { LOG_SENSOR(" ", "Apparent Power", this->apparent_power_sensor_); LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_); LOG_SENSOR(" ", "Power Factor", this->power_factor_sensor_); - this->check_uart_settings(4800); + this->check_uart_settings(4800, 1, uart::UART_CONFIG_PARITY_EVEN); } } // namespace cse7766 diff --git a/esphome/components/cst816/touchscreen/__init__.py b/esphome/components/cst816/touchscreen/__init__.py index a3603ef575..288ca17593 100644 --- a/esphome/components/cst816/touchscreen/__init__.py +++ b/esphome/components/cst816/touchscreen/__init__.py @@ -1,11 +1,10 @@ -import esphome.codegen as cg -import esphome.config_validation as cv - from esphome import pins +import esphome.codegen as cg from esphome.components import i2c, touchscreen -from esphome.const import CONF_INTERRUPT_PIN, CONF_ID, CONF_RESET_PIN -from .. import cst816_ns +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN +from .. import cst816_ns CST816Touchscreen = cst816_ns.class_( "CST816Touchscreen", @@ -14,11 +13,14 @@ CST816Touchscreen = cst816_ns.class_( ) CST816ButtonListener = cst816_ns.class_("CST816ButtonListener") + +CONF_SKIP_PROBE = "skip_probe" CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(CST816Touchscreen), cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_SKIP_PROBE, default=False): cv.boolean, } ).extend(i2c.i2c_device_schema(0x15)) @@ -28,6 +30,7 @@ async def to_code(config): await touchscreen.register_touchscreen(var, config) await i2c.register_i2c_device(var, config) + cg.add(var.set_skip_probe(config[CONF_SKIP_PROBE])) if interrupt_pin := config.get(CONF_INTERRUPT_PIN): cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) if reset_pin := config.get(CONF_RESET_PIN): diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp index 9e59810c7e..7dcb130e20 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp @@ -8,32 +8,33 @@ void CST816Touchscreen::continue_setup_() { this->interrupt_pin_->setup(); this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); } - if (!this->read_byte(REG_CHIP_ID, &this->chip_id_)) { + if (this->read_byte(REG_CHIP_ID, &this->chip_id_)) { + switch (this->chip_id_) { + case CST820_CHIP_ID: + case CST826_CHIP_ID: + case CST716_CHIP_ID: + case CST816S_CHIP_ID: + case CST816D_CHIP_ID: + case CST816T_CHIP_ID: + break; + default: + this->mark_failed(); + this->status_set_error(str_sprintf("Unknown chip ID 0x%02X", this->chip_id_).c_str()); + return; + } + this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION); + } else if (!this->skip_probe_) { + this->status_set_error("Failed to read chip id"); this->mark_failed(); - esph_log_e(TAG, "Failed to read chip id"); return; } - switch (this->chip_id_) { - case CST820_CHIP_ID: - case CST826_CHIP_ID: - case CST716_CHIP_ID: - case CST816S_CHIP_ID: - case CST816D_CHIP_ID: - case CST816T_CHIP_ID: - break; - default: - this->mark_failed(); - esph_log_e(TAG, "Unknown chip ID 0x%02X", this->chip_id_); - return; - } - this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION); if (this->x_raw_max_ == this->x_raw_min_) { this->x_raw_max_ = this->display_->get_native_width(); } if (this->y_raw_max_ == this->y_raw_min_) { this->y_raw_max_ = this->display_->get_native_height(); } - esph_log_config(TAG, "CST816 Touchscreen setup complete"); + ESP_LOGCONFIG(TAG, "CST816 Touchscreen setup complete"); } void CST816Touchscreen::update_button_state_(bool state) { @@ -45,7 +46,7 @@ void CST816Touchscreen::update_button_state_(bool state) { } void CST816Touchscreen::setup() { - esph_log_config(TAG, "Setting up CST816 Touchscreen..."); + ESP_LOGCONFIG(TAG, "Setting up CST816 Touchscreen..."); if (this->reset_pin_ != nullptr) { this->reset_pin_->setup(); this->reset_pin_->digital_write(true); @@ -73,7 +74,7 @@ void CST816Touchscreen::update_touches() { uint16_t x = encode_uint16(data[REG_XPOS_HIGH] & 0xF, data[REG_XPOS_LOW]); uint16_t y = encode_uint16(data[REG_YPOS_HIGH] & 0xF, data[REG_YPOS_LOW]); - esph_log_v(TAG, "Read touch %d/%d", x, y); + ESP_LOGV(TAG, "Read touch %d/%d", x, y); if (x >= this->x_raw_max_) { this->update_button_state_(true); } else { diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.h b/esphome/components/cst816/touchscreen/cst816_touchscreen.h index 24e664e7ee..dc00e675ba 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.h +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.h @@ -45,6 +45,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; } + void set_skip_probe(bool skip_probe) { this->skip_probe_ = skip_probe; } protected: void continue_setup_(); @@ -53,6 +54,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice InternalGPIOPin *interrupt_pin_{}; GPIOPin *reset_pin_{}; uint8_t chip_id_{}; + bool skip_probe_{}; // if set, do not expect to be able to probe the controller on the i2c bus. std::vector button_listeners_; bool button_touched_{}; }; diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index b5ed02e89a..dacd0779b1 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -98,13 +98,13 @@ def validate_pillow_installed(value): except ImportError as err: raise cv.Invalid( "Please install the pillow python package to use this feature. " - '(pip install "pillow==10.2.0")' + '(pip install "pillow==10.4.0")' ) from err - if version.parse(PIL.__version__) != version.parse("10.2.0"): + if version.parse(PIL.__version__) != version.parse("10.4.0"): raise cv.Invalid( - "Please update your pillow installation to 10.2.0. " - '(pip install "pillow==10.2.0")' + "Please update your pillow installation to 10.4.0. " + '(pip install "pillow==10.4.0")' ) return value diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 5033f702de..c141739d2a 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -89,6 +89,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, void dump_config() override; void setup() override; + void on_shutdown() override { this->command(ILI9XXX_SLPIN); } display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 540591d24b..a59e703591 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -34,13 +34,13 @@ async def to_code(config): widget = widget[0] await wait_for_widgets() async with LambdaContext([(cg.std_string, "text_value")]) as control: - await widget.set_property("text", "text_value.c_str())") - lv.event_send(widget.obj, API_EVENT, None) + await widget.set_property("text", "text_value.c_str()") + lv.event_send(widget.obj, API_EVENT, cg.nullptr) control.add(textvar.publish_state(widget.get_value())) async with LambdaContext(EVENT_ARG) as lamb: lv_add(textvar.publish_state(widget.get_value())) async with LvContext(paren): - widget.var.set_control_lambda(await control.get_lambda()) + lv_add(textvar.set_control_lambda(await control.get_lambda())) lv_add( paren.add_event_cb( widget.obj, diff --git a/esphome/components/radon_eye_ble/radon_eye_listener.cpp b/esphome/components/radon_eye_ble/radon_eye_listener.cpp index 340322c188..a4c79db753 100644 --- a/esphome/components/radon_eye_ble/radon_eye_listener.cpp +++ b/esphome/components/radon_eye_ble/radon_eye_listener.cpp @@ -1,5 +1,7 @@ #include "radon_eye_listener.h" #include "esphome/core/log.h" +#include +#include #ifdef USE_ESP32 @@ -10,9 +12,14 @@ static const char *const TAG = "radon_eye_ble"; bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { if (not device.get_name().empty()) { - if (device.get_name().rfind("FR:R", 0) == 0) { - // This is an RD200, I think - ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(), + // Vector containing the prefixes to search for + std::vector prefixes = {"FR:R", "FR:I", "FR:H"}; + + // Check if the device name starts with any of the prefixes + if (std::any_of(prefixes.begin(), prefixes.end(), + [&](const std::string &prefix) { return device.get_name().rfind(prefix, 0) == 0; })) { + // Device found + ESP_LOGD(TAG, "Found Radon Eye device Name: %s (MAC: %s)", device.get_name().c_str(), device.address_str().c_str()); } } diff --git a/esphome/components/template/binary_sensor/__init__.py b/esphome/components/template/binary_sensor/__init__.py index 4ce89503de..c93876380d 100644 --- a/esphome/components/template/binary_sensor/__init__.py +++ b/esphome/components/template/binary_sensor/__init__.py @@ -1,8 +1,10 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import binary_sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE +import esphome.config_validation as cv +from esphome.const import CONF_CONDITION, CONF_ID, CONF_LAMBDA, CONF_STATE +from esphome.cpp_generator import LambdaExpression + from .. import template_ns TemplateBinarySensor = template_ns.class_( @@ -13,7 +15,10 @@ CONFIG_SCHEMA = ( binary_sensor.binary_sensor_schema(TemplateBinarySensor) .extend( { - cv.Optional(CONF_LAMBDA): cv.returning_lambda, + cv.Exclusive(CONF_LAMBDA, CONF_CONDITION): cv.returning_lambda, + cv.Exclusive( + CONF_CONDITION, CONF_CONDITION + ): automation.validate_potentially_and_condition, } ) .extend(cv.COMPONENT_SCHEMA) @@ -24,9 +29,17 @@ async def to_code(config): var = await binary_sensor.new_binary_sensor(config) await cg.register_component(var, config) - if CONF_LAMBDA in config: + if lamb := config.get(CONF_LAMBDA): template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.optional.template(bool) + lamb, [], return_type=cg.optional.template(bool) + ) + cg.add(var.set_template(template_)) + if condition := config.get(CONF_CONDITION): + condition = await automation.build_condition( + condition, cg.TemplateArguments(), [] + ) + template_ = LambdaExpression( + f"return {condition.check()};", [], return_type=cg.optional.template(bool) ) cg.add(var.set_template(template_)) diff --git a/esphome/const.py b/esphome/const.py index 930826bf0a..33a121a75e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.10.0-dev" +__version__ = "2024.11.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( diff --git a/requirements_optional.txt b/requirements_optional.txt index c984d41332..2d57c5fd96 100644 --- a/requirements_optional.txt +++ b/requirements_optional.txt @@ -1,2 +1,2 @@ -pillow==10.2.0 +pillow==10.4.0 cairosvg==2.7.1 diff --git a/tests/components/cst816/common.yaml b/tests/components/cst816/common.yaml index 91abbfd4f6..765a353d1d 100644 --- a/tests/components/cst816/common.yaml +++ b/tests/components/cst816/common.yaml @@ -4,6 +4,7 @@ touchscreen: interrupt_pin: number: 21 reset_pin: GPIO16 + skip_probe: false transform: mirror_x: false mirror_y: false @@ -11,14 +12,14 @@ touchscreen: i2c: sda: 3 - scl: 2 + scl: 4 display: - id: my_display platform: ili9xxx dimensions: 480x320 model: ST7796 - cs_pin: 15 + cs_pin: 18 dc_pin: 20 reset_pin: 22 transform: diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 7ef7772ac9..ad935ae563 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -135,3 +135,9 @@ wifi: time: platform: sntp id: time_id + +text: + - id: lvgl_text + platform: lvgl + widget: hello_label + mode: text diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index c968198e26..1770c1bfbc 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -151,6 +151,10 @@ lvgl: align: center text_font: montserrat_40 border_post: true + on_press: + lvgl.label.update: + id: hello_label + text: Goodbye on_click: then: - lvgl.animimg.stop: anim_img diff --git a/tests/components/template/common.yaml b/tests/components/template/common.yaml index 9e89424d8a..3565926933 100644 --- a/tests/components/template/common.yaml +++ b/tests/components/template/common.yaml @@ -46,6 +46,13 @@ binary_sensor: // Garage Door is closed. return false; } + - platform: template + id: other_binary_sensor + name: "Garage Door Closed" + condition: + sensor.in_range: + id: template_sens + below: 30.0 output: - platform: template