diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 97a7d6fbf6..068f74315c 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -429,15 +429,16 @@ void APIServer::on_shutdown() { #ifdef USE_VOICE_ASSISTANT bool APIServer::start_voice_assistant() { - bool result = false; for (auto &c : this->clients_) { - result |= c->request_voice_assistant(true); + if (c->request_voice_assistant(true)) + return true; } - return result; + return false; } void APIServer::stop_voice_assistant() { for (auto &c : this->clients_) { - c->request_voice_assistant(false); + if (c->request_voice_assistant(false)) + return; } } #endif diff --git a/esphome/components/debug/__init__.py b/esphome/components/debug/__init__.py index c18baa1cca..9742b3b19e 100644 --- a/esphome/components/debug/__init__.py +++ b/esphome/components/debug/__init__.py @@ -17,26 +17,29 @@ debug_ns = cg.esphome_ns.namespace("debug") DebugComponent = debug_ns.class_("DebugComponent", cg.PollingComponent) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(DebugComponent), - cv.Optional(CONF_DEVICE): cv.invalid( - "The 'device' option has been moved to the 'debug' text_sensor component" - ), - cv.Optional(CONF_FREE): cv.invalid( - "The 'free' option has been moved to the 'debug' sensor component" - ), - cv.Optional(CONF_BLOCK): cv.invalid( - "The 'block' option has been moved to the 'debug' sensor component" - ), - cv.Optional(CONF_FRAGMENTATION): cv.invalid( - "The 'fragmentation' option has been moved to the 'debug' sensor component" - ), - cv.Optional(CONF_LOOP_TIME): cv.invalid( - "The 'loop_time' option has been moved to the 'debug' sensor component" - ), - } -).extend(cv.polling_component_schema("60s")) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(DebugComponent), + cv.Optional(CONF_DEVICE): cv.invalid( + "The 'device' option has been moved to the 'debug' text_sensor component" + ), + cv.Optional(CONF_FREE): cv.invalid( + "The 'free' option has been moved to the 'debug' sensor component" + ), + cv.Optional(CONF_BLOCK): cv.invalid( + "The 'block' option has been moved to the 'debug' sensor component" + ), + cv.Optional(CONF_FRAGMENTATION): cv.invalid( + "The 'fragmentation' option has been moved to the 'debug' sensor component" + ), + cv.Optional(CONF_LOOP_TIME): cv.invalid( + "The 'loop_time' option has been moved to the 'debug' sensor component" + ), + } + ).extend(cv.polling_component_schema("60s")), + cv.only_on(["esp32", "esp8266"]), +) async def to_code(config): diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index d27b0ca4cd..4043f32dcb 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -77,10 +77,12 @@ void FingerprintGrowComponent::finish_enrollment(uint8_t result) { this->enrollment_done_callback_.call(this->enrollment_slot_); this->get_fingerprint_count_(); } else { - this->enrollment_failed_callback_.call(this->enrollment_slot_); + if (this->enrollment_slot_ != ENROLLMENT_SLOT_UNUSED) { + this->enrollment_failed_callback_.call(this->enrollment_slot_); + } } this->enrollment_image_ = 0; - this->enrollment_slot_ = 0; + this->enrollment_slot_ = ENROLLMENT_SLOT_UNUSED; if (this->enrolling_binary_sensor_ != nullptr) { this->enrolling_binary_sensor_->publish_state(false); } diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index fd316237f7..f414146e64 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -13,6 +13,8 @@ namespace fingerprint_grow { static const uint16_t START_CODE = 0xEF01; +static const uint16_t ENROLLMENT_SLOT_UNUSED = 0xFFFF; + enum GrowPacketType { COMMAND = 0x01, DATA = 0x02, @@ -158,7 +160,7 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic uint32_t new_password_ = -1; GPIOPin *sensing_pin_{nullptr}; uint8_t enrollment_image_ = 0; - uint16_t enrollment_slot_ = 0; + uint16_t enrollment_slot_ = ENROLLMENT_SLOT_UNUSED; uint8_t enrollment_buffers_ = 5; bool waiting_removal_ = false; uint32_t last_aura_led_control_ = 0; diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index e08622a3ae..d80ab1fd1d 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -3,6 +3,7 @@ #include "i2c_bus_arduino.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" +#include "esphome/core/application.h" #include #include @@ -227,10 +228,14 @@ void ArduinoI2CBus::recover_() { // When SCL is kept LOW at this point, we might be looking at a device // that applies clock stretching. Wait for the release of the SCL line, // but not forever. There is no specification for the maximum allowed - // time. We'll stick to 500ms here. - auto wait = 20; + // time. We yield and reset the WDT, so as to avoid triggering reset. + // No point in trying to recover the bus by forcing a uC reset. Bus + // should recover in a few ms or less else not likely to recovery at + // all. + auto wait = 250; while (wait-- && digitalRead(scl_pin_) == LOW) { // NOLINT - delay(25); + App.feed_wdt(); + delayMicroseconds(half_period_usec * 2); } if (digitalRead(scl_pin_) == LOW) { // NOLINT ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle"); diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index 5178f6d4f2..51688322f6 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -4,6 +4,7 @@ #include "esphome/core/hal.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" +#include "esphome/core/application.h" #include #include @@ -273,10 +274,14 @@ void IDFI2CBus::recover_() { // When SCL is kept LOW at this point, we might be looking at a device // that applies clock stretching. Wait for the release of the SCL line, // but not forever. There is no specification for the maximum allowed - // time. We'll stick to 500ms here. - auto wait = 20; + // time. We yield and reset the WDT, so as to avoid triggering reset. + // No point in trying to recover the bus by forcing a uC reset. Bus + // should recover in a few ms or less else not likely to recovery at + // all. + auto wait = 250; while (wait-- && gpio_get_level(scl_pin) == 0) { - delay(25); + App.feed_wdt(); + delayMicroseconds(half_period_usec * 2); } if (gpio_get_level(scl_pin) == 0) { ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle"); diff --git a/esphome/const.py b/esphome/const.py index 6796f8d606..e6f5c8e5f0 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.4.1" +__version__ = "2023.4.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"