diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index dffc088085..9095016b55 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -60,6 +60,20 @@ RemoteReceiverComponent = remote_receiver_ns.class_( ) +def validate_config(config): + if CORE.is_esp32: + variant = esp32.get_esp32_variant() + if variant in (esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S2): + max_idle = 65535 + else: + max_idle = 32767 + if CONF_CLOCK_RESOLUTION in config: + max_idle = int(max_idle * 1000000 / config[CONF_CLOCK_RESOLUTION]) + if config[CONF_IDLE].total_microseconds > max_idle: + raise cv.Invalid(f"config 'idle' exceeds the maximum value of {max_idle}us") + return config + + def validate_tolerance(value): if isinstance(value, dict): return TOLERANCE_SCHEMA(value) @@ -136,7 +150,9 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.boolean, ), } - ).extend(cv.COMPONENT_SCHEMA) + ) + .extend(cv.COMPONENT_SCHEMA) + .add_extra(validate_config) ) diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index 3d6346baec..3e6172c6d6 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -86,10 +86,9 @@ void RemoteReceiverComponent::setup() { uint32_t event_size = sizeof(rmt_rx_done_event_data_t); uint32_t max_filter_ns = 255u * 1000 / (RMT_CLK_FREQ / 1000000); - uint32_t max_idle_ns = 65535u * 1000; memset(&this->store_.config, 0, sizeof(this->store_.config)); this->store_.config.signal_range_min_ns = std::min(this->filter_us_ * 1000, max_filter_ns); - this->store_.config.signal_range_max_ns = std::min(this->idle_us_ * 1000, max_idle_ns); + this->store_.config.signal_range_max_ns = this->idle_us_ * 1000; this->store_.filter_symbols = this->filter_symbols_; this->store_.receive_size = this->receive_symbols_ * sizeof(rmt_symbol_word_t); this->store_.buffer_size = std::max((event_size + this->store_.receive_size) * 2, this->buffer_size_); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index aec6c17786..b28edaf444 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -151,26 +151,22 @@ void Component::call() { switch (state) { case COMPONENT_STATE_CONSTRUCTION: // State Construction: Call setup and set state to setup - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_SETUP; + this->set_component_state_(COMPONENT_STATE_SETUP); this->call_setup(); break; case COMPONENT_STATE_SETUP: // State setup: Call first loop and set state to loop - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_LOOP; + this->set_component_state_(COMPONENT_STATE_LOOP); this->call_loop(); break; case COMPONENT_STATE_LOOP: // State loop: Call loop this->call_loop(); break; - case COMPONENT_STATE_FAILED: // NOLINT(bugprone-branch-clone) + case COMPONENT_STATE_FAILED: // State failed: Do nothing - break; - case COMPONENT_STATE_LOOP_DONE: // NOLINT(bugprone-branch-clone) + case COMPONENT_STATE_LOOP_DONE: // State loop done: Do nothing, component has finished its work - break; default: break; } @@ -195,25 +191,26 @@ bool Component::should_warn_of_blocking(uint32_t blocking_time) { } void Component::mark_failed() { ESP_LOGE(TAG, "%s was marked as failed", this->get_component_source()); - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_FAILED; + this->set_component_state_(COMPONENT_STATE_FAILED); this->status_set_error(); // Also remove from loop since failed components shouldn't loop App.disable_component_loop_(this); } +void Component::set_component_state_(uint8_t state) { + this->component_state_ &= ~COMPONENT_STATE_MASK; + this->component_state_ |= state; +} void Component::disable_loop() { if ((this->component_state_ & COMPONENT_STATE_MASK) != COMPONENT_STATE_LOOP_DONE) { ESP_LOGVV(TAG, "%s loop disabled", this->get_component_source()); - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_LOOP_DONE; + this->set_component_state_(COMPONENT_STATE_LOOP_DONE); App.disable_component_loop_(this); } } void Component::enable_loop() { if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE) { ESP_LOGVV(TAG, "%s loop enabled", this->get_component_source()); - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_LOOP; + this->set_component_state_(COMPONENT_STATE_LOOP); App.enable_component_loop_(this); } } @@ -233,8 +230,7 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { void Component::reset_to_construction_state() { if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) { ESP_LOGI(TAG, "%s is being reset to construction state", this->get_component_source()); - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= COMPONENT_STATE_CONSTRUCTION; + this->set_component_state_(COMPONENT_STATE_CONSTRUCTION); // Clear error status when resetting this->status_clear_error(); } diff --git a/esphome/core/component.h b/esphome/core/component.h index 3734473a02..5f17c1c22a 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -236,6 +236,9 @@ class Component { virtual void call_setup(); virtual void call_dump_config(); + /// Helper to set component state (clears state bits and sets new state) + void set_component_state_(uint8_t state); + /** Set an interval function with a unique name. Empty name means no cancelling possible. * * This will call f every interval ms. Can be cancelled via CancelInterval(). @@ -405,10 +408,10 @@ class Component { const char *component_source_{nullptr}; uint16_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS}; ///< Warn if blocked for this many ms (max 65.5s) /// State of this component - each bit has a purpose: - /// Bits 0-1: Component state (0x00=CONSTRUCTION, 0x01=SETUP, 0x02=LOOP, 0x03=FAILED) - /// Bit 2: STATUS_LED_WARNING - /// Bit 3: STATUS_LED_ERROR - /// Bits 4-7: Unused - reserved for future expansion (50% of the bits are free) + /// Bits 0-2: Component state (0x00=CONSTRUCTION, 0x01=SETUP, 0x02=LOOP, 0x03=FAILED, 0x04=LOOP_DONE) + /// Bit 3: STATUS_LED_WARNING + /// Bit 4: STATUS_LED_ERROR + /// Bits 5-7: Unused - reserved for future expansion uint8_t component_state_{0x00}; volatile bool pending_enable_loop_{false}; ///< ISR-safe flag for enable_loop_soon_any_context };