diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9d955df85f..82cf605342 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -171,7 +171,7 @@ jobs: - uses: actions/checkout@v4.2.2 - name: Download digests - uses: actions/download-artifact@v4.3.0 + uses: actions/download-artifact@v5.0.0 with: pattern: digests-* path: /tmp/digests diff --git a/esphome/components/absolute_humidity/sensor.py b/esphome/components/absolute_humidity/sensor.py index 62a2c8ab7c..caaa546e25 100644 --- a/esphome/components/absolute_humidity/sensor.py +++ b/esphome/components/absolute_humidity/sensor.py @@ -5,7 +5,7 @@ from esphome.const import ( CONF_EQUATION, CONF_HUMIDITY, CONF_TEMPERATURE, - ICON_WATER, + DEVICE_CLASS_ABSOLUTE_HUMIDITY, STATE_CLASS_MEASUREMENT, UNIT_GRAMS_PER_CUBIC_METER, ) @@ -27,8 +27,8 @@ EQUATION = { CONFIG_SCHEMA = ( sensor.sensor_schema( unit_of_measurement=UNIT_GRAMS_PER_CUBIC_METER, - icon=ICON_WATER, accuracy_decimals=2, + device_class=DEVICE_CLASS_ABSOLUTE_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ) .extend( diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 4f4f4d08a5..d1ee7af4ea 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -1,7 +1,7 @@ -#ifdef USE_ESP32 - #include "ble.h" +#ifdef USE_ESP32 + #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index b4173d8ff4..e373554ea9 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -1,5 +1,7 @@ #pragma once +#include "esphome/core/defines.h" + #include #include #include diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index fba9dbd97e..4b09d521b6 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -333,33 +333,37 @@ class ESP32BLETracker : public Component, return counts; } - uint8_t app_id_{0}; - + // Group 1: Large objects (12+ bytes) - vectors and callback manager + std::vector listeners_; + std::vector clients_; + CallbackManager scanner_state_callbacks_; #ifdef USE_ESP32_BLE_DEVICE /// Vector of addresses that have already been printed in print_bt_device_info std::vector already_discovered_; #endif - std::vector listeners_; - /// Client parameters. - std::vector clients_; + + // Group 2: Structs (aligned to 4 bytes) /// A structure holding the ESP BLE scan parameters. esp_ble_scan_params_t scan_params_; + ClientStateCounts client_state_counts_; + + // Group 3: 4-byte types /// The interval in seconds to perform scans. uint32_t scan_duration_; uint32_t scan_interval_; uint32_t scan_window_; + esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS}; + esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS}; + + // Group 4: 1-byte types (enums, uint8_t, bool) + uint8_t app_id_{0}; uint8_t scan_start_fail_count_{0}; + ScannerState scanner_state_{ScannerState::IDLE}; bool scan_continuous_; bool scan_active_; - ScannerState scanner_state_{ScannerState::IDLE}; - CallbackManager scanner_state_callbacks_; bool ble_was_disabled_{true}; bool raw_advertisements_{false}; bool parse_advertisements_{false}; - - esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS}; - esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS}; - ClientStateCounts client_state_counts_; #ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE bool coex_prefer_ble_{false}; #endif diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 5a91b1c750..fb1973e26f 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -171,8 +171,8 @@ class ESP32TouchComponent : public Component { // based on the filter configuration uint32_t read_touch_value(touch_pad_t pad) const; - // Helper to update touch state with a known state - void update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched); + // Helper to update touch state with a known state and value + void update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched, uint32_t value); // Helper to read touch value and update state for a given child bool check_and_update_touch_state_(ESP32TouchBinarySensor *child); @@ -234,9 +234,13 @@ class ESP32TouchBinarySensor : public binary_sensor::BinarySensor { touch_pad_t get_touch_pad() const { return this->touch_pad_; } uint32_t get_threshold() const { return this->threshold_; } void set_threshold(uint32_t threshold) { this->threshold_ = threshold; } -#ifdef USE_ESP32_VARIANT_ESP32 + + /// Get the raw touch measurement value. + /// @note Although this method may appear unused within the component, it is a public API + /// used by lambdas in user configurations for custom touch value processing. + /// @return The current raw touch sensor reading uint32_t get_value() const { return this->value_; } -#endif + uint32_t get_wakeup_threshold() const { return this->wakeup_threshold_; } protected: @@ -245,9 +249,8 @@ class ESP32TouchBinarySensor : public binary_sensor::BinarySensor { touch_pad_t touch_pad_{TOUCH_PAD_MAX}; uint32_t threshold_{0}; uint32_t benchmark_{}; -#ifdef USE_ESP32_VARIANT_ESP32 + /// Stores the last raw touch measurement value. uint32_t value_{0}; -#endif bool last_state_{false}; const uint32_t wakeup_threshold_{0}; diff --git a/esphome/components/esp32_touch/esp32_touch_common.cpp b/esphome/components/esp32_touch/esp32_touch_common.cpp index 2d93de077e..a0b1df38c1 100644 --- a/esphome/components/esp32_touch/esp32_touch_common.cpp +++ b/esphome/components/esp32_touch/esp32_touch_common.cpp @@ -100,6 +100,8 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) { #else // Read the value being used for touch detection uint32_t value = this->read_touch_value(child->get_touch_pad()); + // Store the value for get_value() access in lambdas + child->value_ = value; ESP_LOGD(TAG, "Touch Pad '%s' (T%d): %d", child->get_name().c_str(), child->get_touch_pad(), value); #endif } diff --git a/esphome/components/esp32_touch/esp32_touch_v2.cpp b/esphome/components/esp32_touch/esp32_touch_v2.cpp index afd2655fd7..9662b009f6 100644 --- a/esphome/components/esp32_touch/esp32_touch_v2.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v2.cpp @@ -10,8 +10,11 @@ namespace esp32_touch { static const char *const TAG = "esp32_touch"; -// Helper to update touch state with a known state -void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched) { +// Helper to update touch state with a known state and value +void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched, uint32_t value) { + // Store the value for get_value() access in lambdas + child->value_ = value; + // Always update timer when touched if (is_touched) { child->last_touch_time_ = App.get_loop_component_start_time(); @@ -21,9 +24,8 @@ void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, boo child->last_state_ = is_touched; child->publish_state(is_touched); if (is_touched) { - // ESP32-S2/S3 v2: touched when value > threshold ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 " > threshold: %" PRIu32 ")", child->get_name().c_str(), - this->read_touch_value(child->touch_pad_), child->threshold_ + child->benchmark_); + value, child->threshold_ + child->benchmark_); } else { ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str()); } @@ -41,7 +43,7 @@ bool ESP32TouchComponent::check_and_update_touch_state_(ESP32TouchBinarySensor * child->get_name().c_str(), child->touch_pad_, value, child->threshold_, child->benchmark_); bool is_touched = value > child->benchmark_ + child->threshold_; - this->update_touch_state_(child, is_touched); + this->update_touch_state_(child, is_touched, value); return is_touched; } @@ -296,7 +298,9 @@ void ESP32TouchComponent::loop() { this->check_and_update_touch_state_(child); } else if (event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { // We only get ACTIVE interrupts now, releases are detected by timeout - this->update_touch_state_(child, true); // Always touched for ACTIVE interrupts + // Read the current value + uint32_t value = this->read_touch_value(child->touch_pad_); + this->update_touch_state_(child, true, value); // Always touched for ACTIVE interrupts } break; } diff --git a/esphome/components/ld2410/__init__.py b/esphome/components/ld2410/__init__.py index 4918190179..b492bbcd14 100644 --- a/esphome/components/ld2410/__init__.py +++ b/esphome/components/ld2410/__init__.py @@ -14,18 +14,16 @@ ld2410_ns = cg.esphome_ns.namespace("ld2410") LD2410Component = ld2410_ns.class_("LD2410Component", cg.Component, uart.UARTDevice) CONF_LD2410_ID = "ld2410_id" - CONF_MAX_MOVE_DISTANCE = "max_move_distance" CONF_MAX_STILL_DISTANCE = "max_still_distance" -CONF_STILL_THRESHOLDS = [f"g{x}_still_threshold" for x in range(9)] CONF_MOVE_THRESHOLDS = [f"g{x}_move_threshold" for x in range(9)] +CONF_STILL_THRESHOLDS = [f"g{x}_still_threshold" for x in range(9)] CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(LD2410Component), - cv.Optional(CONF_THROTTLE, default="1000ms"): cv.All( - cv.positive_time_period_milliseconds, - cv.Range(min=cv.TimePeriod(milliseconds=1)), + cv.Optional(CONF_THROTTLE): cv.invalid( + f"{CONF_THROTTLE} has been removed; use per-sensor filters, instead" ), cv.Optional(CONF_MAX_MOVE_DISTANCE): cv.invalid( f"The '{CONF_MAX_MOVE_DISTANCE}' option has been moved to the '{CONF_MAX_MOVE_DISTANCE}'" @@ -75,7 +73,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - cg.add(var.set_throttle(config[CONF_THROTTLE])) CALIBRATION_ACTION_SCHEMA = maybe_simple_id( diff --git a/esphome/components/ld2410/binary_sensor.py b/esphome/components/ld2410/binary_sensor.py index d2938754e9..4e35f67fbe 100644 --- a/esphome/components/ld2410/binary_sensor.py +++ b/esphome/components/ld2410/binary_sensor.py @@ -22,19 +22,23 @@ CONFIG_SCHEMA = { cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_OCCUPANCY, + filters=[{"settle": cv.TimePeriod(milliseconds=1000)}], icon=ICON_ACCOUNT, ), cv.Optional(CONF_HAS_MOVING_TARGET): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_MOTION, + filters=[{"settle": cv.TimePeriod(milliseconds=1000)}], icon=ICON_MOTION_SENSOR, ), cv.Optional(CONF_HAS_STILL_TARGET): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_OCCUPANCY, + filters=[{"settle": cv.TimePeriod(milliseconds=1000)}], icon=ICON_MOTION_SENSOR, ), cv.Optional(CONF_OUT_PIN_PRESENCE_STATUS): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_PRESENCE, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + filters=[{"settle": cv.TimePeriod(milliseconds=1000)}], icon=ICON_ACCOUNT, ), } diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index e0287465f8..5c3af54ad8 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -188,9 +188,8 @@ void LD2410Component::dump_config() { ESP_LOGCONFIG(TAG, "LD2410:\n" " Firmware version: %s\n" - " MAC address: %s\n" - " Throttle: %u ms", - version.c_str(), mac_str.c_str(), this->throttle_); + " MAC address: %s", + version.c_str(), mac_str.c_str()); #ifdef USE_BINARY_SENSOR ESP_LOGCONFIG(TAG, "Binary Sensors:"); LOG_BINARY_SENSOR(" ", "Target", this->target_binary_sensor_); @@ -306,11 +305,6 @@ void LD2410Component::send_command_(uint8_t command, const uint8_t *command_valu } void LD2410Component::handle_periodic_data_() { - // Reduce data update rate to reduce home assistant database growth - // Check this first to prevent unnecessary processing done in later checks/parsing - if (App.get_loop_component_start_time() - this->last_periodic_millis_ < this->throttle_) { - return; - } // 4 frame header bytes + 2 length bytes + 1 data end byte + 1 crc byte + 4 frame footer bytes // data header=0xAA, data footer=0x55, crc=0x00 if (this->buffer_pos_ < 12 || !ld2410::validate_header_footer(DATA_FRAME_HEADER, this->buffer_data_) || @@ -318,9 +312,6 @@ void LD2410Component::handle_periodic_data_() { this->buffer_data_[this->buffer_pos_ - 5] != CHECK) { return; } - // Save the timestamp after validating the frame so, if invalid, we'll take the next frame immediately - this->last_periodic_millis_ = App.get_loop_component_start_time(); - /* Data Type: 7th 0x01: Engineering mode diff --git a/esphome/components/ld2410/ld2410.h b/esphome/components/ld2410/ld2410.h index e9225ccfe4..54fe1ce14d 100644 --- a/esphome/components/ld2410/ld2410.h +++ b/esphome/components/ld2410/ld2410.h @@ -93,7 +93,6 @@ class LD2410Component : public Component, public uart::UARTDevice { void set_gate_move_sensor(uint8_t gate, sensor::Sensor *s); void set_gate_still_sensor(uint8_t gate, sensor::Sensor *s); #endif - void set_throttle(uint16_t value) { this->throttle_ = value; }; void set_bluetooth_password(const std::string &password); void set_engineering_mode(bool enable); void read_all_info(); @@ -116,8 +115,6 @@ class LD2410Component : public Component, public uart::UARTDevice { void query_light_control_(); void restart_(); - uint32_t last_periodic_millis_ = 0; - uint16_t throttle_ = 0; uint8_t light_function_ = 0; uint8_t light_threshold_ = 0; uint8_t out_pin_level_ = 0; diff --git a/esphome/components/ld2410/sensor.py b/esphome/components/ld2410/sensor.py index 92245ea9a6..fca2b2ceca 100644 --- a/esphome/components/ld2410/sensor.py +++ b/esphome/components/ld2410/sensor.py @@ -18,42 +18,50 @@ from esphome.const import ( from . import CONF_LD2410_ID, LD2410Component DEPENDENCIES = ["ld2410"] -CONF_STILL_DISTANCE = "still_distance" -CONF_MOVING_ENERGY = "moving_energy" -CONF_STILL_ENERGY = "still_energy" + CONF_DETECTION_DISTANCE = "detection_distance" CONF_MOVE_ENERGY = "move_energy" +CONF_MOVING_ENERGY = "moving_energy" +CONF_STILL_DISTANCE = "still_distance" +CONF_STILL_ENERGY = "still_energy" + CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, - unit_of_measurement=UNIT_CENTIMETER, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_SIGNAL, + unit_of_measurement=UNIT_CENTIMETER, ), cv.Optional(CONF_STILL_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, - unit_of_measurement=UNIT_CENTIMETER, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_SIGNAL, + unit_of_measurement=UNIT_CENTIMETER, ), cv.Optional(CONF_MOVING_ENERGY): sensor.sensor_schema( - unit_of_measurement=UNIT_PERCENT, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_MOTION_SENSOR, + unit_of_measurement=UNIT_PERCENT, ), cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( - unit_of_measurement=UNIT_PERCENT, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_FLASH, + unit_of_measurement=UNIT_PERCENT, ), cv.Optional(CONF_LIGHT): sensor.sensor_schema( device_class=DEVICE_CLASS_ILLUMINANCE, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_LIGHTBULB, ), cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, - unit_of_measurement=UNIT_CENTIMETER, + filters=[{"throttle_with_priority": cv.TimePeriod(milliseconds=1000)}], icon=ICON_SIGNAL, + unit_of_measurement=UNIT_CENTIMETER, ), } ) @@ -63,14 +71,20 @@ CONFIG_SCHEMA = CONFIG_SCHEMA.extend( cv.Optional(f"g{x}"): cv.Schema( { cv.Optional(CONF_MOVE_ENERGY): sensor.sensor_schema( - unit_of_measurement=UNIT_PERCENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + filters=[ + {"throttle_with_priority": cv.TimePeriod(milliseconds=1000)} + ], icon=ICON_MOTION_SENSOR, + unit_of_measurement=UNIT_PERCENT, ), cv.Optional(CONF_STILL_ENERGY): sensor.sensor_schema( - unit_of_measurement=UNIT_PERCENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + filters=[ + {"throttle_with_priority": cv.TimePeriod(milliseconds=1000)} + ], icon=ICON_FLASH, + unit_of_measurement=UNIT_PERCENT, ), } ) diff --git a/tests/components/esp32_touch/common-get-value.yaml b/tests/components/esp32_touch/common-get-value.yaml new file mode 100644 index 0000000000..4066303797 --- /dev/null +++ b/tests/components/esp32_touch/common-get-value.yaml @@ -0,0 +1,18 @@ +binary_sensor: + - platform: esp32_touch + name: ESP32 Touch Pad Get Value + pin: ${pin} + threshold: 1000 + id: esp32_touch_pad_get_value + on_press: + then: + - lambda: |- + // Test that get_value() compiles and works + uint32_t value = id(esp32_touch_pad_get_value).get_value(); + ESP_LOGD("test", "Touch value on press: %u", value); + on_release: + then: + - lambda: |- + // Test get_value() on release + uint32_t value = id(esp32_touch_pad_get_value).get_value(); + ESP_LOGD("test", "Touch value on release: %u", value); diff --git a/tests/components/esp32_touch/test.esp32-idf.yaml b/tests/components/esp32_touch/test.esp32-idf.yaml index 25316b8646..5158613eb1 100644 --- a/tests/components/esp32_touch/test.esp32-idf.yaml +++ b/tests/components/esp32_touch/test.esp32-idf.yaml @@ -2,3 +2,4 @@ substitutions: pin: GPIO27 <<: !include common.yaml +<<: !include common-get-value.yaml diff --git a/tests/components/esp32_touch/test.esp32-s2-idf.yaml b/tests/components/esp32_touch/test.esp32-s2-idf.yaml index 575d758fae..b9f5671969 100644 --- a/tests/components/esp32_touch/test.esp32-s2-idf.yaml +++ b/tests/components/esp32_touch/test.esp32-s2-idf.yaml @@ -2,3 +2,4 @@ substitutions: pin: GPIO12 <<: !include common-variants.yaml +<<: !include common-get-value.yaml diff --git a/tests/components/esp32_touch/test.esp32-s3-idf.yaml b/tests/components/esp32_touch/test.esp32-s3-idf.yaml index 575d758fae..b9f5671969 100644 --- a/tests/components/esp32_touch/test.esp32-s3-idf.yaml +++ b/tests/components/esp32_touch/test.esp32-s3-idf.yaml @@ -2,3 +2,4 @@ substitutions: pin: GPIO12 <<: !include common-variants.yaml +<<: !include common-get-value.yaml