diff --git a/esphome/components/ens160/sensor.py b/esphome/components/ens160/sensor.py index 55f0ff7b6f..393b63bae1 100644 --- a/esphome/components/ens160/sensor.py +++ b/esphome/components/ens160/sensor.py @@ -9,7 +9,7 @@ from esphome.const import ( CONF_TVOC, DEVICE_CLASS_AQI, DEVICE_CLASS_CARBON_DIOXIDE, - DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, ICON_CHEMICAL_WEAPON, ICON_MOLECULE_CO2, ICON_RADIATOR, @@ -45,11 +45,10 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_PARTS_PER_BILLION, icon=ICON_RADIATOR, accuracy_decimals=0, - device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS, state_class=STATE_CLASS_MEASUREMENT, ), cv.Required(CONF_AQI): sensor.sensor_schema( - unit_of_measurement=UNIT_INDEX, icon=ICON_CHEMICAL_WEAPON, accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index e431997276..be302bd489 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -97,7 +97,7 @@ UART_SELECTION_LIBRETINY = { COMPONENT_RTL87XX: [DEFAULT, UART0, UART1, UART2], } -ESP_IDF_UARTS = [USB_CDC, USB_SERIAL_JTAG] +ESP_ARDUINO_UNSUPPORTED_USB_UARTS = [USB_SERIAL_JTAG] UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1] @@ -124,8 +124,8 @@ is_log_level = cv.one_of(*LOG_LEVELS, upper=True) def uart_selection(value): if CORE.is_esp32: - if value.upper() in ESP_IDF_UARTS and not CORE.using_esp_idf: - raise cv.Invalid(f"Only esp-idf framework supports {value}.") + if CORE.using_arduino and value.upper() in ESP_ARDUINO_UNSUPPORTED_USB_UARTS: + raise cv.Invalid(f"Arduino framework does not support {value}.") variant = get_esp32_variant() if variant in UART_SELECTION_ESP32: return cv.one_of(*UART_SELECTION_ESP32[variant], upper=True)(value) @@ -171,6 +171,8 @@ CONFIG_SCHEMA = cv.All( CONF_HARDWARE_UART, esp8266=UART0, esp32=UART0, + esp32_s2=USB_CDC, + esp32_s3=USB_CDC, rp2040=USB_CDC, bk72xx=DEFAULT, rtl87xx=DEFAULT, @@ -258,6 +260,10 @@ async def to_code(config): if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH): cg.add_build_flag("-DUSE_STORE_LOG_STR_IN_FLASH") + if CORE.using_arduino: + if config[CONF_HARDWARE_UART] == USB_CDC: + cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1") + if CORE.using_esp_idf: if config[CONF_HARDWARE_UART] == USB_CDC: add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_USB_CDC", True) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 2d2524b5f4..e0ca0806cb 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -236,8 +236,13 @@ void Logger::pre_setup() { this->hw_serial_ = &Serial1; Serial1.begin(this->baud_rate_); #else +#if ARDUINO_USB_CDC_ON_BOOT this->hw_serial_ = &Serial; Serial.begin(this->baud_rate_); +#else + this->hw_serial_ = &Serial; + Serial.begin(this->baud_rate_); +#endif #endif #ifdef USE_ESP8266 if (this->uart_ == UART_SELECTION_UART0_SWAP) { @@ -265,12 +270,35 @@ void Logger::pre_setup() { Serial2.begin(this->baud_rate_); break; #endif +#if defined(USE_ESP32) && \ + (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3)) +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case UART_SELECTION_USB_CDC: +#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) + case UART_SELECTION_USB_SERIAL_JTAG: +#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 +#ifdef USE_ESP32_VARIANT_ESP32C3 + this->hw_serial_ = &Serial; + Serial.begin(this->baud_rate_); +#endif // USE_ESP32_VARIANT_ESP32C3 +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#if ARDUINO_USB_CDC_ON_BOOT + this->hw_serial_ = &Serial; + Serial.begin(this->baud_rate_); +#else + this->hw_serial_ = &Serial; + Serial.begin(this->baud_rate_); +#endif // ARDUINO_USB_CDC_ON_BOOT +#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 + break; +#endif // USE_ESP32 && (USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32C3) #ifdef USE_RP2040 case UART_SELECTION_USB_CDC: this->hw_serial_ = &Serial; Serial.begin(this->baud_rate_); break; -#endif +#endif // USE_RP2040 } #endif // USE_ARDUINO #ifdef USE_ESP_IDF @@ -393,14 +421,12 @@ const char *const UART_SELECTIONS[] = { "UART2", #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARINT_ESP32C6 && !USE_ESP32_VARIANT_ESP32S2 && // !USE_ESP32_VARIANT_ESP32S3 && !USE_ESP32_VARIANT_ESP32H2 -#if defined(USE_ESP_IDF) #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) "USB_CDC", #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) "USB_SERIAL_JTAG", #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 -#endif // USE_ESP_IDF }; #endif // USE_ESP32 #ifdef USE_ESP8266 diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 3816b1dd14..68efc056df 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -45,7 +45,6 @@ enum UARTSelection { UART_SELECTION_UART2, #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32C6 && !USE_ESP32_VARIANT_ESP32S2 && // !USE_ESP32_VARIANT_ESP32S3 && !USE_ESP32_VARIANT_ESP32H2 -#ifdef USE_ESP_IDF #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) UART_SELECTION_USB_CDC, #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 @@ -54,7 +53,6 @@ enum UARTSelection { UART_SELECTION_USB_SERIAL_JTAG, #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 || // USE_ESP32_VARIANT_ESP32H2 -#endif // USE_ESP_IDF #endif // USE_ESP32 #ifdef USE_ESP8266 UART_SELECTION_UART0_SWAP, diff --git a/esphome/components/template/cover/__init__.py b/esphome/components/template/cover/__init__.py index 8844ddd6ab..43d0be99b4 100644 --- a/esphome/components/template/cover/__init__.py +++ b/esphome/components/template/cover/__init__.py @@ -31,6 +31,7 @@ RESTORE_MODES = { } CONF_HAS_POSITION = "has_position" +CONF_TOGGLE_ACTION = "toggle_action" CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( { @@ -44,6 +45,7 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_TILT_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_TILT_LAMBDA): cv.returning_lambda, + cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum( RESTORE_MODES, upper=True @@ -74,6 +76,11 @@ async def to_code(config): var.get_stop_trigger(), [], config[CONF_STOP_ACTION] ) cg.add(var.set_has_stop(True)) + if CONF_TOGGLE_ACTION in config: + await automation.build_automation( + var.get_toggle_trigger(), [], config[CONF_TOGGLE_ACTION] + ) + cg.add(var.set_has_toggle(True)) if CONF_TILT_ACTION in config: await automation.build_automation( var.get_tilt_trigger(), [(float, "tilt")], config[CONF_TILT_ACTION] diff --git a/esphome/components/template/cover/template_cover.cpp b/esphome/components/template/cover/template_cover.cpp index b16e439943..2d6c3087ae 100644 --- a/esphome/components/template/cover/template_cover.cpp +++ b/esphome/components/template/cover/template_cover.cpp @@ -12,6 +12,7 @@ TemplateCover::TemplateCover() : open_trigger_(new Trigger<>()), close_trigger_(new Trigger<>), stop_trigger_(new Trigger<>()), + toggle_trigger_(new Trigger<>()), position_trigger_(new Trigger()), tilt_trigger_(new Trigger()) {} void TemplateCover::setup() { @@ -68,6 +69,7 @@ float TemplateCover::get_setup_priority() const { return setup_priority::HARDWAR Trigger<> *TemplateCover::get_open_trigger() const { return this->open_trigger_; } Trigger<> *TemplateCover::get_close_trigger() const { return this->close_trigger_; } Trigger<> *TemplateCover::get_stop_trigger() const { return this->stop_trigger_; } +Trigger<> *TemplateCover::get_toggle_trigger() const { return this->toggle_trigger_; } void TemplateCover::dump_config() { LOG_COVER("", "Template Cover", this); } void TemplateCover::control(const CoverCall &call) { if (call.get_stop()) { @@ -76,6 +78,12 @@ void TemplateCover::control(const CoverCall &call) { this->prev_command_trigger_ = this->stop_trigger_; this->publish_state(); } + if (call.get_toggle().has_value()) { + this->stop_prev_trigger_(); + this->toggle_trigger_->trigger(); + this->prev_command_trigger_ = this->toggle_trigger_; + this->publish_state(); + } if (call.get_position().has_value()) { auto pos = *call.get_position(); this->stop_prev_trigger_(); @@ -110,6 +118,7 @@ CoverTraits TemplateCover::get_traits() { auto traits = CoverTraits(); traits.set_is_assumed_state(this->assumed_state_); traits.set_supports_stop(this->has_stop_); + traits.set_supports_toggle(this->has_toggle_); traits.set_supports_position(this->has_position_); traits.set_supports_tilt(this->has_tilt_); return traits; @@ -118,6 +127,7 @@ Trigger *TemplateCover::get_position_trigger() const { return this->posit Trigger *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; } void TemplateCover::set_tilt_lambda(std::function()> &&tilt_f) { this->tilt_f_ = tilt_f; } void TemplateCover::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } +void TemplateCover::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } void TemplateCover::set_has_position(bool has_position) { this->has_position_ = has_position; } void TemplateCover::set_has_tilt(bool has_tilt) { this->has_tilt_ = has_tilt; } void TemplateCover::stop_prev_trigger_() { diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 4ff5caf1db..958c94b0a6 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -21,6 +21,7 @@ class TemplateCover : public cover::Cover, public Component { Trigger<> *get_open_trigger() const; Trigger<> *get_close_trigger() const; Trigger<> *get_stop_trigger() const; + Trigger<> *get_toggle_trigger() const; Trigger *get_position_trigger() const; Trigger *get_tilt_trigger() const; void set_optimistic(bool optimistic); @@ -29,6 +30,7 @@ class TemplateCover : public cover::Cover, public Component { void set_has_stop(bool has_stop); void set_has_position(bool has_position); void set_has_tilt(bool has_tilt); + void set_has_toggle(bool has_toggle); void set_restore_mode(TemplateCoverRestoreMode restore_mode) { restore_mode_ = restore_mode; } void setup() override; @@ -50,7 +52,9 @@ class TemplateCover : public cover::Cover, public Component { Trigger<> *open_trigger_; Trigger<> *close_trigger_; bool has_stop_{false}; + bool has_toggle_{false}; Trigger<> *stop_trigger_; + Trigger<> *toggle_trigger_; Trigger<> *prev_command_trigger_{nullptr}; Trigger *position_trigger_; bool has_position_{false}; diff --git a/esphome/config_validation.py b/esphome/config_validation.py index ad2ee11512..7b94608509 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1518,6 +1518,13 @@ class GenerateID(Optional): super().__init__(key, default=lambda: None) +def _get_priority_default(*args): + for arg in args: + if arg is not vol.UNDEFINED: + return arg + return vol.UNDEFINED + + class SplitDefault(Optional): """Mark this key to have a split default for ESP8266/ESP32.""" @@ -1528,6 +1535,12 @@ class SplitDefault(Optional): esp32=vol.UNDEFINED, esp32_arduino=vol.UNDEFINED, esp32_idf=vol.UNDEFINED, + esp32_s2=vol.UNDEFINED, + esp32_s2_arduino=vol.UNDEFINED, + esp32_s2_idf=vol.UNDEFINED, + esp32_s3=vol.UNDEFINED, + esp32_s3_arduino=vol.UNDEFINED, + esp32_s3_idf=vol.UNDEFINED, rp2040=vol.UNDEFINED, bk72xx=vol.UNDEFINED, rtl87xx=vol.UNDEFINED, @@ -1536,10 +1549,22 @@ class SplitDefault(Optional): super().__init__(key) self._esp8266_default = vol.default_factory(esp8266) self._esp32_arduino_default = vol.default_factory( - esp32_arduino if esp32 is vol.UNDEFINED else esp32 + _get_priority_default(esp32, esp32_arduino) ) self._esp32_idf_default = vol.default_factory( - esp32_idf if esp32 is vol.UNDEFINED else esp32 + _get_priority_default(esp32, esp32_idf) + ) + self._esp32_s2_arduino_default = vol.default_factory( + _get_priority_default(esp32_s2, esp32, esp32_s2_arduino, esp32_arduino) + ) + self._esp32_s2_idf_default = vol.default_factory( + _get_priority_default(esp32_s2, esp32, esp32_s2_idf, esp32_idf) + ) + self._esp32_s3_arduino_default = vol.default_factory( + _get_priority_default(esp32_s3, esp32, esp32_s3_arduino, esp32_arduino) + ) + self._esp32_s3_idf_default = vol.default_factory( + _get_priority_default(esp32_s3, esp32, esp32_s3_idf, esp32_idf) ) self._rp2040_default = vol.default_factory(rp2040) self._bk72xx_default = vol.default_factory(bk72xx) @@ -1550,10 +1575,29 @@ class SplitDefault(Optional): def default(self): if CORE.is_esp8266: return self._esp8266_default - if CORE.is_esp32 and CORE.using_arduino: - return self._esp32_arduino_default - if CORE.is_esp32 and CORE.using_esp_idf: - return self._esp32_idf_default + if CORE.is_esp32: + from esphome.components.esp32 import get_esp32_variant + from esphome.components.esp32.const import ( + VARIANT_ESP32S2, + VARIANT_ESP32S3, + ) + + variant = get_esp32_variant() + if variant == VARIANT_ESP32S2: + if CORE.using_arduino: + return self._esp32_s2_arduino_default + if CORE.using_esp_idf: + return self._esp32_s2_idf_default + elif variant == VARIANT_ESP32S3: + if CORE.using_arduino: + return self._esp32_s3_arduino_default + if CORE.using_esp_idf: + return self._esp32_s3_idf_default + else: + if CORE.using_arduino: + return self._esp32_arduino_default + if CORE.using_esp_idf: + return self._esp32_idf_default if CORE.is_rp2040: return self._rp2040_default if CORE.is_bk72xx: diff --git a/esphome/const.py b/esphome/const.py index b8495a3a7c..6c2a520331 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.12.0b1" +__version__ = "2023.12.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = (