mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into integration
This commit is contained in:
		| @@ -219,7 +219,7 @@ def has_mqtt_logging() -> bool: | ||||
|     if CONF_TOPIC not in log_topic: | ||||
|         return False | ||||
|  | ||||
|     return log_topic[CONF_LEVEL] != "NONE" | ||||
|     return log_topic.get(CONF_LEVEL, None) != "NONE" | ||||
|  | ||||
|  | ||||
| def has_mqtt() -> bool: | ||||
|   | ||||
| @@ -36,7 +36,6 @@ from esphome.const import ( | ||||
|     __version__, | ||||
| ) | ||||
| from esphome.core import CORE, HexInt, TimePeriod | ||||
| from esphome.cpp_generator import RawExpression | ||||
| import esphome.final_validate as fv | ||||
| from esphome.helpers import copy_file_if_changed, mkdir_p, write_file_if_changed | ||||
| from esphome.types import ConfigType | ||||
| @@ -157,8 +156,6 @@ def set_core_data(config): | ||||
|     conf = config[CONF_FRAMEWORK] | ||||
|     if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: | ||||
|         CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "esp-idf" | ||||
|         CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {} | ||||
|         CORE.data[KEY_ESP32][KEY_COMPONENTS] = {} | ||||
|     elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO: | ||||
|         CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino" | ||||
|         if variant not in ARDUINO_ALLOWED_VARIANTS: | ||||
| @@ -166,6 +163,8 @@ def set_core_data(config): | ||||
|                 f"ESPHome does not support using the Arduino framework for the {variant}. Please use the ESP-IDF framework instead.", | ||||
|                 path=[CONF_FRAMEWORK, CONF_TYPE], | ||||
|             ) | ||||
|     CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {} | ||||
|     CORE.data[KEY_ESP32][KEY_COMPONENTS] = {} | ||||
|     CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( | ||||
|         config[CONF_FRAMEWORK][CONF_VERSION] | ||||
|     ) | ||||
| @@ -236,8 +235,6 @@ SdkconfigValueType = bool | int | HexInt | str | RawSdkconfigValue | ||||
|  | ||||
| def add_idf_sdkconfig_option(name: str, value: SdkconfigValueType): | ||||
|     """Set an esp-idf sdkconfig value.""" | ||||
|     if not CORE.using_esp_idf: | ||||
|         raise ValueError("Not an esp-idf project") | ||||
|     CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS][name] = value | ||||
|  | ||||
|  | ||||
| @@ -252,8 +249,6 @@ def add_idf_component( | ||||
|     submodules: list[str] | None = None, | ||||
| ): | ||||
|     """Add an esp-idf component to the project.""" | ||||
|     if not CORE.using_esp_idf: | ||||
|         raise ValueError("Not an esp-idf project") | ||||
|     if not repo and not ref and not path: | ||||
|         raise ValueError("Requires at least one of repo, ref or path") | ||||
|     if refresh or submodules or components: | ||||
| @@ -367,47 +362,49 @@ SUPPORTED_PIOARDUINO_ESP_IDF_5X = [ | ||||
| ] | ||||
|  | ||||
|  | ||||
| def _arduino_check_versions(value): | ||||
| def _check_versions(value): | ||||
|     value = value.copy() | ||||
|     lookups = { | ||||
|         "dev": (cv.Version(3, 2, 1), "https://github.com/espressif/arduino-esp32.git"), | ||||
|         "latest": (cv.Version(3, 2, 1), None), | ||||
|         "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), | ||||
|     } | ||||
|     if value[CONF_TYPE] == FRAMEWORK_ARDUINO: | ||||
|         lookups = { | ||||
|             "dev": ( | ||||
|                 cv.Version(3, 2, 1), | ||||
|                 "https://github.com/espressif/arduino-esp32.git", | ||||
|             ), | ||||
|             "latest": (cv.Version(3, 2, 1), None), | ||||
|             "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), | ||||
|         } | ||||
|  | ||||
|     if value[CONF_VERSION] in lookups: | ||||
|         if CONF_SOURCE in value: | ||||
|             raise cv.Invalid( | ||||
|                 "Framework version needs to be explicitly specified when custom source is used." | ||||
|             ) | ||||
|         if value[CONF_VERSION] in lookups: | ||||
|             if CONF_SOURCE in value: | ||||
|                 raise cv.Invalid( | ||||
|                     "Framework version needs to be explicitly specified when custom source is used." | ||||
|                 ) | ||||
|  | ||||
|         version, source = lookups[value[CONF_VERSION]] | ||||
|     else: | ||||
|         version = cv.Version.parse(cv.version_number(value[CONF_VERSION])) | ||||
|         source = value.get(CONF_SOURCE, None) | ||||
|             version, source = lookups[value[CONF_VERSION]] | ||||
|         else: | ||||
|             version = cv.Version.parse(cv.version_number(value[CONF_VERSION])) | ||||
|             source = value.get(CONF_SOURCE, None) | ||||
|  | ||||
|     value[CONF_VERSION] = str(version) | ||||
|     value[CONF_SOURCE] = source or _format_framework_arduino_version(version) | ||||
|         value[CONF_VERSION] = str(version) | ||||
|         value[CONF_SOURCE] = source or _format_framework_arduino_version(version) | ||||
|  | ||||
|     value[CONF_PLATFORM_VERSION] = value.get( | ||||
|         CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION)) | ||||
|     ) | ||||
|  | ||||
|     if value[CONF_SOURCE].startswith("http"): | ||||
|         # prefix is necessary or platformio will complain with a cryptic error | ||||
|         value[CONF_SOURCE] = f"framework-arduinoespressif32@{value[CONF_SOURCE]}" | ||||
|  | ||||
|     if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION: | ||||
|         _LOGGER.warning( | ||||
|             "The selected Arduino framework version is not the recommended one. " | ||||
|             "If there are connectivity or build issues please remove the manual version." | ||||
|         value[CONF_PLATFORM_VERSION] = value.get( | ||||
|             CONF_PLATFORM_VERSION, | ||||
|             _parse_platform_version(str(ARDUINO_PLATFORM_VERSION)), | ||||
|         ) | ||||
|  | ||||
|     return value | ||||
|         if value[CONF_SOURCE].startswith("http"): | ||||
|             # prefix is necessary or platformio will complain with a cryptic error | ||||
|             value[CONF_SOURCE] = f"framework-arduinoespressif32@{value[CONF_SOURCE]}" | ||||
|  | ||||
|         if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION: | ||||
|             _LOGGER.warning( | ||||
|                 "The selected Arduino framework version is not the recommended one. " | ||||
|                 "If there are connectivity or build issues please remove the manual version." | ||||
|             ) | ||||
|  | ||||
|         return value | ||||
|  | ||||
| def _esp_idf_check_versions(value): | ||||
|     value = value.copy() | ||||
|     lookups = { | ||||
|         "dev": (cv.Version(5, 4, 2), "https://github.com/espressif/esp-idf.git"), | ||||
|         "latest": (cv.Version(5, 2, 2), None), | ||||
| @@ -589,24 +586,6 @@ def final_validate(config): | ||||
|     return config | ||||
|  | ||||
|  | ||||
| ARDUINO_FRAMEWORK_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict, | ||||
|             cv.Optional(CONF_SOURCE): cv.string_strict, | ||||
|             cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version, | ||||
|             cv.Optional(CONF_ADVANCED, default={}): cv.Schema( | ||||
|                 { | ||||
|                     cv.Optional( | ||||
|                         CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False | ||||
|                     ): cv.boolean, | ||||
|                 } | ||||
|             ), | ||||
|         } | ||||
|     ), | ||||
|     _arduino_check_versions, | ||||
| ) | ||||
|  | ||||
| CONF_SDKCONFIG_OPTIONS = "sdkconfig_options" | ||||
| CONF_ENABLE_LWIP_DHCP_SERVER = "enable_lwip_dhcp_server" | ||||
| CONF_ENABLE_LWIP_MDNS_QUERIES = "enable_lwip_mdns_queries" | ||||
| @@ -625,9 +604,14 @@ def _validate_idf_component(config: ConfigType) -> ConfigType: | ||||
|     return config | ||||
|  | ||||
|  | ||||
| ESP_IDF_FRAMEWORK_SCHEMA = cv.All( | ||||
| FRAMEWORK_ESP_IDF = "esp-idf" | ||||
| FRAMEWORK_ARDUINO = "arduino" | ||||
| FRAMEWORK_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Optional(CONF_TYPE, default=FRAMEWORK_ARDUINO): cv.one_of( | ||||
|                 FRAMEWORK_ESP_IDF, FRAMEWORK_ARDUINO | ||||
|             ), | ||||
|             cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict, | ||||
|             cv.Optional(CONF_RELEASE): cv.string_strict, | ||||
|             cv.Optional(CONF_SOURCE): cv.string_strict, | ||||
| @@ -691,7 +675,7 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All( | ||||
|             ), | ||||
|         } | ||||
|     ), | ||||
|     _esp_idf_check_versions, | ||||
|     _check_versions, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @@ -758,32 +742,18 @@ def _set_default_framework(config): | ||||
|         config = config.copy() | ||||
|  | ||||
|         variant = config[CONF_VARIANT] | ||||
|         config[CONF_FRAMEWORK] = FRAMEWORK_SCHEMA({}) | ||||
|         if variant in ARDUINO_ALLOWED_VARIANTS: | ||||
|             config[CONF_FRAMEWORK] = ARDUINO_FRAMEWORK_SCHEMA({}) | ||||
|             config[CONF_FRAMEWORK][CONF_TYPE] = FRAMEWORK_ARDUINO | ||||
|             # Show the migration message | ||||
|             _show_framework_migration_message( | ||||
|                 config.get(CONF_NAME, "This device"), variant | ||||
|             ) | ||||
|         else: | ||||
|             config[CONF_FRAMEWORK] = ESP_IDF_FRAMEWORK_SCHEMA({}) | ||||
|             config[CONF_FRAMEWORK][CONF_TYPE] = FRAMEWORK_ESP_IDF | ||||
|  | ||||
|     return config | ||||
|  | ||||
|  | ||||
| FRAMEWORK_ESP_IDF = "esp-idf" | ||||
| FRAMEWORK_ARDUINO = "arduino" | ||||
| FRAMEWORK_SCHEMA = cv.typed_schema( | ||||
|     { | ||||
|         FRAMEWORK_ESP_IDF: ESP_IDF_FRAMEWORK_SCHEMA, | ||||
|         FRAMEWORK_ARDUINO: ARDUINO_FRAMEWORK_SCHEMA, | ||||
|     }, | ||||
|     lower=True, | ||||
|     space="-", | ||||
| ) | ||||
|  | ||||
|  | ||||
| FLASH_SIZES = [ | ||||
|     "2MB", | ||||
|     "4MB", | ||||
| @@ -851,139 +821,145 @@ async def to_code(config): | ||||
|         os.path.join(os.path.dirname(__file__), "post_build.py.script"), | ||||
|     ) | ||||
|  | ||||
|     freq = config[CONF_CPU_FREQUENCY][:-3] | ||||
|     if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: | ||||
|         cg.add_platformio_option("framework", "espidf") | ||||
|         cg.add_build_flag("-DUSE_ESP_IDF") | ||||
|         cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF") | ||||
|         cg.add_build_flag("-Wno-nonnull-compare") | ||||
|  | ||||
|         cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) | ||||
|  | ||||
|         add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) | ||||
|         add_idf_sdkconfig_option( | ||||
|             f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True | ||||
|         ) | ||||
|         add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False) | ||||
|         add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True) | ||||
|         add_idf_sdkconfig_option( | ||||
|             "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv" | ||||
|         ) | ||||
|  | ||||
|         # Increase freertos tick speed from 100Hz to 1kHz so that delay() resolution is 1ms | ||||
|         add_idf_sdkconfig_option("CONFIG_FREERTOS_HZ", 1000) | ||||
|  | ||||
|         # Setup watchdog | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_PANIC", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False) | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False) | ||||
|  | ||||
|         # Disable dynamic log level control to save memory | ||||
|         add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False) | ||||
|  | ||||
|         # Set default CPU frequency | ||||
|         add_idf_sdkconfig_option(f"CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_{freq}", True) | ||||
|  | ||||
|         # Apply LWIP optimization settings | ||||
|         advanced = conf[CONF_ADVANCED] | ||||
|         # DHCP server: only disable if explicitly set to false | ||||
|         # WiFi component handles its own optimization when AP mode is not used | ||||
|         if ( | ||||
|             CONF_ENABLE_LWIP_DHCP_SERVER in advanced | ||||
|             and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER] | ||||
|         ): | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False) | ||||
|         if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True): | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False) | ||||
|         if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False): | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0) | ||||
|         if advanced.get(CONF_EXECUTE_FROM_PSRAM, False): | ||||
|             add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True) | ||||
|             add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) | ||||
|  | ||||
|         # Apply LWIP core locking for better socket performance | ||||
|         # This is already enabled by default in Arduino framework, where it provides | ||||
|         # significant performance benefits. Our benchmarks show socket operations are | ||||
|         # 24-200% faster with core locking enabled: | ||||
|         # - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default) | ||||
|         # - Up to 200% slower under load when all operations queue through tcpip_thread | ||||
|         # Enabling this makes ESP-IDF socket performance match Arduino framework. | ||||
|         if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True): | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True) | ||||
|         if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True): | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True) | ||||
|  | ||||
|         cg.add_platformio_option("board_build.partitions", "partitions.csv") | ||||
|         if CONF_PARTITIONS in config: | ||||
|             add_extra_build_file( | ||||
|                 "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS]) | ||||
|             ) | ||||
|  | ||||
|         if assertion_level := advanced.get(CONF_ASSERTION_LEVEL): | ||||
|             for key, flag in ASSERTION_LEVELS.items(): | ||||
|                 add_idf_sdkconfig_option(flag, assertion_level == key) | ||||
|  | ||||
|         add_idf_sdkconfig_option("CONFIG_COMPILER_OPTIMIZATION_DEFAULT", False) | ||||
|         compiler_optimization = advanced.get(CONF_COMPILER_OPTIMIZATION) | ||||
|         for key, flag in COMPILER_OPTIMIZATIONS.items(): | ||||
|             add_idf_sdkconfig_option(flag, compiler_optimization == key) | ||||
|  | ||||
|         add_idf_sdkconfig_option( | ||||
|             "CONFIG_LWIP_ESP_LWIP_ASSERT", | ||||
|             conf[CONF_ADVANCED][CONF_ENABLE_LWIP_ASSERT], | ||||
|         ) | ||||
|  | ||||
|         if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC): | ||||
|             add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True) | ||||
|             add_idf_sdkconfig_option( | ||||
|                 "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False | ||||
|             ) | ||||
|         if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES): | ||||
|             _LOGGER.warning( | ||||
|                 "Using experimental features in ESP-IDF may result in unexpected failures." | ||||
|             ) | ||||
|             add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True) | ||||
|  | ||||
|         cg.add_define( | ||||
|             "USE_ESP_IDF_VERSION_CODE", | ||||
|             cg.RawExpression( | ||||
|                 f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})" | ||||
|             ), | ||||
|         ) | ||||
|  | ||||
|         add_idf_sdkconfig_option( | ||||
|             f"CONFIG_LOG_DEFAULT_LEVEL_{conf[CONF_LOG_LEVEL]}", True | ||||
|         ) | ||||
|  | ||||
|         for name, value in conf[CONF_SDKCONFIG_OPTIONS].items(): | ||||
|             add_idf_sdkconfig_option(name, RawSdkconfigValue(value)) | ||||
|  | ||||
|         for component in conf[CONF_COMPONENTS]: | ||||
|             add_idf_component( | ||||
|                 name=component[CONF_NAME], | ||||
|                 repo=component.get(CONF_SOURCE), | ||||
|                 ref=component.get(CONF_REF), | ||||
|                 path=component.get(CONF_PATH), | ||||
|             ) | ||||
|     elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO: | ||||
|         cg.add_platformio_option("framework", "arduino") | ||||
|     else: | ||||
|         cg.add_platformio_option("framework", "arduino, espidf") | ||||
|         cg.add_build_flag("-DUSE_ARDUINO") | ||||
|         cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO") | ||||
|         cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) | ||||
|  | ||||
|         if CONF_PARTITIONS in config: | ||||
|             cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS]) | ||||
|         else: | ||||
|             cg.add_platformio_option("board_build.partitions", "partitions.csv") | ||||
|  | ||||
|         cg.add_platformio_option( | ||||
|             "board_build.embed_txtfiles", | ||||
|             [ | ||||
|                 "managed_components/espressif__esp_insights/server_certs/https_server.crt", | ||||
|                 "managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt", | ||||
|                 "managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt", | ||||
|                 "managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt", | ||||
|             ], | ||||
|         ) | ||||
|         cg.add_define( | ||||
|             "USE_ARDUINO_VERSION_CODE", | ||||
|             cg.RawExpression( | ||||
|                 f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})" | ||||
|             ), | ||||
|         ) | ||||
|         cg.add(RawExpression(f"setCpuFrequencyMhz({freq})")) | ||||
|         add_idf_sdkconfig_option("CONFIG_AUTOSTART_ARDUINO", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_MBEDTLS_PSK_MODES", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True) | ||||
|  | ||||
|     cg.add_build_flag("-Wno-nonnull-compare") | ||||
|  | ||||
|     cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) | ||||
|  | ||||
|     add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) | ||||
|     add_idf_sdkconfig_option( | ||||
|         f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True | ||||
|     ) | ||||
|     add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False) | ||||
|     add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv") | ||||
|  | ||||
|     # Increase freertos tick speed from 100Hz to 1kHz so that delay() resolution is 1ms | ||||
|     add_idf_sdkconfig_option("CONFIG_FREERTOS_HZ", 1000) | ||||
|  | ||||
|     # Setup watchdog | ||||
|     add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_PANIC", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False) | ||||
|     add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False) | ||||
|  | ||||
|     # Disable dynamic log level control to save memory | ||||
|     add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False) | ||||
|  | ||||
|     # Set default CPU frequency | ||||
|     add_idf_sdkconfig_option( | ||||
|         f"CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_{config[CONF_CPU_FREQUENCY][:-3]}", True | ||||
|     ) | ||||
|  | ||||
|     # Apply LWIP optimization settings | ||||
|     advanced = conf[CONF_ADVANCED] | ||||
|     # DHCP server: only disable if explicitly set to false | ||||
|     # WiFi component handles its own optimization when AP mode is not used | ||||
|     # When using Arduino with Ethernet, DHCP server functions must be available | ||||
|     # for the Network library to compile, even if not actively used | ||||
|     if ( | ||||
|         CONF_ENABLE_LWIP_DHCP_SERVER in advanced | ||||
|         and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER] | ||||
|         and not ( | ||||
|             conf[CONF_TYPE] == FRAMEWORK_ARDUINO | ||||
|             and "ethernet" in CORE.loaded_integrations | ||||
|         ) | ||||
|     ): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False) | ||||
|     if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False) | ||||
|     if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0) | ||||
|     if advanced.get(CONF_EXECUTE_FROM_PSRAM, False): | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) | ||||
|  | ||||
|     # Apply LWIP core locking for better socket performance | ||||
|     # This is already enabled by default in Arduino framework, where it provides | ||||
|     # significant performance benefits. Our benchmarks show socket operations are | ||||
|     # 24-200% faster with core locking enabled: | ||||
|     # - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default) | ||||
|     # - Up to 200% slower under load when all operations queue through tcpip_thread | ||||
|     # Enabling this makes ESP-IDF socket performance match Arduino framework. | ||||
|     if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True) | ||||
|     if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True) | ||||
|  | ||||
|     cg.add_platformio_option("board_build.partitions", "partitions.csv") | ||||
|     if CONF_PARTITIONS in config: | ||||
|         add_extra_build_file( | ||||
|             "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS]) | ||||
|         ) | ||||
|  | ||||
|     if assertion_level := advanced.get(CONF_ASSERTION_LEVEL): | ||||
|         for key, flag in ASSERTION_LEVELS.items(): | ||||
|             add_idf_sdkconfig_option(flag, assertion_level == key) | ||||
|  | ||||
|     add_idf_sdkconfig_option("CONFIG_COMPILER_OPTIMIZATION_DEFAULT", False) | ||||
|     compiler_optimization = advanced.get(CONF_COMPILER_OPTIMIZATION) | ||||
|     for key, flag in COMPILER_OPTIMIZATIONS.items(): | ||||
|         add_idf_sdkconfig_option(flag, compiler_optimization == key) | ||||
|  | ||||
|     add_idf_sdkconfig_option( | ||||
|         "CONFIG_LWIP_ESP_LWIP_ASSERT", | ||||
|         conf[CONF_ADVANCED][CONF_ENABLE_LWIP_ASSERT], | ||||
|     ) | ||||
|  | ||||
|     if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC): | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False) | ||||
|     if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES): | ||||
|         _LOGGER.warning( | ||||
|             "Using experimental features in ESP-IDF may result in unexpected failures." | ||||
|         ) | ||||
|         add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True) | ||||
|  | ||||
|     cg.add_define( | ||||
|         "USE_ESP_IDF_VERSION_CODE", | ||||
|         cg.RawExpression( | ||||
|             f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})" | ||||
|         ), | ||||
|     ) | ||||
|  | ||||
|     add_idf_sdkconfig_option(f"CONFIG_LOG_DEFAULT_LEVEL_{conf[CONF_LOG_LEVEL]}", True) | ||||
|  | ||||
|     for name, value in conf[CONF_SDKCONFIG_OPTIONS].items(): | ||||
|         add_idf_sdkconfig_option(name, RawSdkconfigValue(value)) | ||||
|  | ||||
|     for component in conf[CONF_COMPONENTS]: | ||||
|         add_idf_component( | ||||
|             name=component[CONF_NAME], | ||||
|             repo=component.get(CONF_SOURCE), | ||||
|             ref=component.get(CONF_REF), | ||||
|             path=component.get(CONF_PATH), | ||||
|         ) | ||||
|  | ||||
|  | ||||
| APP_PARTITION_SIZES = { | ||||
| @@ -1057,6 +1033,7 @@ def _write_sdkconfig(): | ||||
|         ) | ||||
|         + "\n" | ||||
|     ) | ||||
|  | ||||
|     if write_file_if_changed(internal_path, contents): | ||||
|         # internal changed, update real one | ||||
|         write_file_if_changed(sdk_path, contents) | ||||
| @@ -1088,34 +1065,32 @@ def _write_idf_component_yml(): | ||||
|  | ||||
| # Called by writer.py | ||||
| def copy_files(): | ||||
|     if ( | ||||
|         CORE.using_arduino | ||||
|         and "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES] | ||||
|     ): | ||||
|         write_file_if_changed( | ||||
|             CORE.relative_build_path("partitions.csv"), | ||||
|             get_arduino_partition_csv( | ||||
|                 CORE.platformio_options.get("board_upload.flash_size") | ||||
|             ), | ||||
|         ) | ||||
|     if CORE.using_esp_idf: | ||||
|         _write_sdkconfig() | ||||
|         _write_idf_component_yml() | ||||
|         if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: | ||||
|     _write_sdkconfig() | ||||
|     _write_idf_component_yml() | ||||
|  | ||||
|     if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: | ||||
|         if CORE.using_arduino: | ||||
|             write_file_if_changed( | ||||
|                 CORE.relative_build_path("partitions.csv"), | ||||
|                 get_arduino_partition_csv( | ||||
|                     CORE.platformio_options.get("board_upload.flash_size") | ||||
|                 ), | ||||
|             ) | ||||
|         else: | ||||
|             write_file_if_changed( | ||||
|                 CORE.relative_build_path("partitions.csv"), | ||||
|                 get_idf_partition_csv( | ||||
|                     CORE.platformio_options.get("board_upload.flash_size") | ||||
|                 ), | ||||
|             ) | ||||
|         # IDF build scripts look for version string to put in the build. | ||||
|         # However, if the build path does not have an initialized git repo, | ||||
|         # and no version.txt file exists, the CMake script fails for some setups. | ||||
|         # Fix by manually pasting a version.txt file, containing the ESPHome version | ||||
|         write_file_if_changed( | ||||
|             CORE.relative_build_path("version.txt"), | ||||
|             __version__, | ||||
|         ) | ||||
|     # IDF build scripts look for version string to put in the build. | ||||
|     # However, if the build path does not have an initialized git repo, | ||||
|     # and no version.txt file exists, the CMake script fails for some setups. | ||||
|     # Fix by manually pasting a version.txt file, containing the ESPHome version | ||||
|     write_file_if_changed( | ||||
|         CORE.relative_build_path("version.txt"), | ||||
|         __version__, | ||||
|     ) | ||||
|  | ||||
|     for file in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES].values(): | ||||
|         if file[KEY_PATH].startswith("http"): | ||||
|   | ||||
| @@ -12,7 +12,7 @@ from esphome.const import ( | ||||
|     CONF_NAME, | ||||
|     CONF_NAME_ADD_MAC_SUFFIX, | ||||
| ) | ||||
| from esphome.core import CORE, TimePeriod | ||||
| from esphome.core import TimePeriod | ||||
| import esphome.final_validate as fv | ||||
|  | ||||
| DEPENDENCIES = ["esp32"] | ||||
| @@ -261,43 +261,40 @@ async def to_code(config): | ||||
|         cg.add(var.set_name(name)) | ||||
|     await cg.register_component(var, config) | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) | ||||
|  | ||||
|         # Register the core BLE loggers that are always needed | ||||
|         register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI) | ||||
|     # Register the core BLE loggers that are always needed | ||||
|     register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI) | ||||
|  | ||||
|         # Apply logger settings if log disabling is enabled | ||||
|         if config.get(CONF_DISABLE_BT_LOGS, False): | ||||
|             # Disable all Bluetooth loggers that are not required | ||||
|             for logger in BTLoggers: | ||||
|                 if logger not in _required_loggers: | ||||
|                     add_idf_sdkconfig_option(f"{logger.value}_NONE", True) | ||||
|     # Apply logger settings if log disabling is enabled | ||||
|     if config.get(CONF_DISABLE_BT_LOGS, False): | ||||
|         # Disable all Bluetooth loggers that are not required | ||||
|         for logger in BTLoggers: | ||||
|             if logger not in _required_loggers: | ||||
|                 add_idf_sdkconfig_option(f"{logger.value}_NONE", True) | ||||
|  | ||||
|         # Set BLE connection establishment timeout to match aioesphomeapi/bleak-retry-connector | ||||
|         # Default is 20 seconds instead of ESP-IDF's 30 seconds. Because there is no way to | ||||
|         # cancel a BLE connection in progress, when aioesphomeapi times out at 20 seconds, | ||||
|         # the connection slot remains occupied for the remaining time, preventing new connection | ||||
|         # attempts and wasting valuable connection slots. | ||||
|         if CONF_CONNECTION_TIMEOUT in config: | ||||
|             timeout_seconds = int(config[CONF_CONNECTION_TIMEOUT].total_seconds) | ||||
|             add_idf_sdkconfig_option( | ||||
|                 "CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT", timeout_seconds | ||||
|             ) | ||||
|             # Increase GATT client connection retry count for problematic devices | ||||
|             # Default in ESP-IDF is 3, we increase to 10 for better reliability with | ||||
|             # low-power/timing-sensitive devices | ||||
|             add_idf_sdkconfig_option("CONFIG_BT_GATTC_CONNECT_RETRY_COUNT", 10) | ||||
|     # Set BLE connection establishment timeout to match aioesphomeapi/bleak-retry-connector | ||||
|     # Default is 20 seconds instead of ESP-IDF's 30 seconds. Because there is no way to | ||||
|     # cancel a BLE connection in progress, when aioesphomeapi times out at 20 seconds, | ||||
|     # the connection slot remains occupied for the remaining time, preventing new connection | ||||
|     # attempts and wasting valuable connection slots. | ||||
|     if CONF_CONNECTION_TIMEOUT in config: | ||||
|         timeout_seconds = int(config[CONF_CONNECTION_TIMEOUT].total_seconds) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT", timeout_seconds) | ||||
|         # Increase GATT client connection retry count for problematic devices | ||||
|         # Default in ESP-IDF is 3, we increase to 10 for better reliability with | ||||
|         # low-power/timing-sensitive devices | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_GATTC_CONNECT_RETRY_COUNT", 10) | ||||
|  | ||||
|         # Set the maximum number of notification registrations | ||||
|         # This controls how many BLE characteristics can have notifications enabled | ||||
|         # across all connections for a single GATT client interface | ||||
|         # https://github.com/esphome/issues/issues/6808 | ||||
|         if CONF_MAX_NOTIFICATIONS in config: | ||||
|             add_idf_sdkconfig_option( | ||||
|                 "CONFIG_BT_GATTC_NOTIF_REG_MAX", config[CONF_MAX_NOTIFICATIONS] | ||||
|             ) | ||||
|     # Set the maximum number of notification registrations | ||||
|     # This controls how many BLE characteristics can have notifications enabled | ||||
|     # across all connections for a single GATT client interface | ||||
|     # https://github.com/esphome/issues/issues/6808 | ||||
|     if CONF_MAX_NOTIFICATIONS in config: | ||||
|         add_idf_sdkconfig_option( | ||||
|             "CONFIG_BT_GATTC_NOTIF_REG_MAX", config[CONF_MAX_NOTIFICATIONS] | ||||
|         ) | ||||
|  | ||||
|     cg.add_define("USE_ESP32_BLE") | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option | ||||
| from esphome.components.esp32_ble import CONF_BLE_ID | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID | ||||
| from esphome.core import CORE, TimePeriod | ||||
| from esphome.core import TimePeriod | ||||
|  | ||||
| AUTO_LOAD = ["esp32_ble"] | ||||
| DEPENDENCIES = ["esp32"] | ||||
| @@ -86,6 +86,5 @@ async def to_code(config): | ||||
|  | ||||
|     cg.add_define("USE_ESP32_BLE_ADVERTISING") | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True) | ||||
|   | ||||
| @@ -573,8 +573,7 @@ async def to_code(config): | ||||
|         ) | ||||
|     cg.add_define("USE_ESP32_BLE_SERVER") | ||||
|     cg.add_define("USE_ESP32_BLE_ADVERTISING") | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|  | ||||
|  | ||||
| @automation.register_action( | ||||
|   | ||||
| @@ -342,19 +342,18 @@ async def to_code(config): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|         await automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|         if config.get(CONF_SOFTWARE_COEXISTENCE): | ||||
|             add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True) | ||||
|         # https://github.com/espressif/esp-idf/issues/4101 | ||||
|         # https://github.com/espressif/esp-idf/issues/2503 | ||||
|         # Match arduino CONFIG_BTU_TASK_STACK_SIZE | ||||
|         # https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866 | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192) | ||||
|         add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9) | ||||
|         add_idf_sdkconfig_option( | ||||
|             "CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS] | ||||
|         ) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||
|     if config.get(CONF_SOFTWARE_COEXISTENCE): | ||||
|         add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True) | ||||
|     # https://github.com/espressif/esp-idf/issues/4101 | ||||
|     # https://github.com/espressif/esp-idf/issues/2503 | ||||
|     # Match arduino CONFIG_BTU_TASK_STACK_SIZE | ||||
|     # https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866 | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192) | ||||
|     add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9) | ||||
|     add_idf_sdkconfig_option( | ||||
|         "CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS] | ||||
|     ) | ||||
|  | ||||
|     cg.add_define("USE_OTA_STATE_CALLBACK")  # To be notified when an OTA update starts | ||||
|     cg.add_define("USE_ESP32_BLE_CLIENT") | ||||
|   | ||||
| @@ -21,7 +21,6 @@ from esphome.const import ( | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_VSYNC_PIN, | ||||
| ) | ||||
| from esphome.core import CORE | ||||
| from esphome.core.entity_helpers import setup_entity | ||||
| import esphome.final_validate as fv | ||||
|  | ||||
| @@ -344,8 +343,7 @@ async def to_code(config): | ||||
|  | ||||
|     cg.add_define("USE_CAMERA") | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_component(name="espressif/esp32-camera", ref="2.1.1") | ||||
|     add_idf_component(name="espressif/esp32-camera", ref="2.1.1") | ||||
|  | ||||
|     for conf in config.get(CONF_ON_STREAM_START, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|   | ||||
| @@ -322,11 +322,8 @@ async def to_code(config): | ||||
|         cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED])) | ||||
|  | ||||
|         cg.add_define("USE_ETHERNET_SPI") | ||||
|         if CORE.using_esp_idf: | ||||
|             add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) | ||||
|             add_idf_sdkconfig_option( | ||||
|                 f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True | ||||
|             ) | ||||
|         add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) | ||||
|         add_idf_sdkconfig_option(f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True) | ||||
|     elif config[CONF_TYPE] == "OPENETH": | ||||
|         cg.add_define("USE_ETHERNET_OPENETH") | ||||
|         add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True) | ||||
| @@ -359,10 +356,9 @@ async def to_code(config): | ||||
|     cg.add_define("USE_ETHERNET") | ||||
|  | ||||
|     # Disable WiFi when using Ethernet to save memory | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False) | ||||
|         # Also disable WiFi/BT coexistence since WiFi is disabled | ||||
|         add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False) | ||||
|     add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False) | ||||
|     # Also disable WiFi/BT coexistence since WiFi is disabled | ||||
|     add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False) | ||||
|  | ||||
|     if CORE.using_arduino: | ||||
|         cg.add_library("WiFi", None) | ||||
|   | ||||
| @@ -262,8 +262,7 @@ async def to_code(config): | ||||
|         cg.add_define("USE_I2S_LEGACY") | ||||
|  | ||||
|     # Helps avoid callbacks being skipped due to processor load | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True) | ||||
|  | ||||
|     cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN])) | ||||
|     if CONF_I2S_BCLK_PIN in config: | ||||
|   | ||||
| @@ -15,11 +15,10 @@ static const char *const TAG = "improv_serial"; | ||||
|  | ||||
| void ImprovSerialComponent::setup() { | ||||
|   global_improv_serial_component = this; | ||||
| #ifdef USE_ARDUINO | ||||
|   this->hw_serial_ = logger::global_logger->get_hw_serial(); | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|   this->uart_num_ = logger::global_logger->get_uart_num(); | ||||
| #elif defined(USE_ARDUINO) | ||||
|   this->hw_serial_ = logger::global_logger->get_hw_serial(); | ||||
| #endif | ||||
|  | ||||
|   if (wifi::global_wifi_component->has_sta()) { | ||||
| @@ -34,13 +33,7 @@ void ImprovSerialComponent::dump_config() { ESP_LOGCONFIG(TAG, "Improv Serial:") | ||||
| optional<uint8_t> ImprovSerialComponent::read_byte_() { | ||||
|   optional<uint8_t> byte; | ||||
|   uint8_t data = 0; | ||||
| #ifdef USE_ARDUINO | ||||
|   if (this->hw_serial_->available()) { | ||||
|     this->hw_serial_->readBytes(&data, 1); | ||||
|     byte = data; | ||||
|   } | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|   switch (logger::global_logger->get_uart()) { | ||||
|     case logger::UART_SELECTION_UART0: | ||||
|     case logger::UART_SELECTION_UART1: | ||||
| @@ -76,16 +69,18 @@ optional<uint8_t> ImprovSerialComponent::read_byte_() { | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| #elif defined(USE_ARDUINO) | ||||
|   if (this->hw_serial_->available()) { | ||||
|     this->hw_serial_->readBytes(&data, 1); | ||||
|     byte = data; | ||||
|   } | ||||
| #endif | ||||
|   return byte; | ||||
| } | ||||
|  | ||||
| void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) { | ||||
|   data.push_back('\n'); | ||||
| #ifdef USE_ARDUINO | ||||
|   this->hw_serial_->write(data.data(), data.size()); | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|   switch (logger::global_logger->get_uart()) { | ||||
|     case logger::UART_SELECTION_UART0: | ||||
|     case logger::UART_SELECTION_UART1: | ||||
| @@ -112,6 +107,8 @@ void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) { | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| #elif defined(USE_ARDUINO) | ||||
|   this->hw_serial_->write(data.data(), data.size()); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,10 +9,7 @@ | ||||
| #include <improv.h> | ||||
| #include <vector> | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
| #include <HardwareSerial.h> | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
| #include <driver/uart.h> | ||||
| #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ | ||||
|     defined(USE_ESP32_VARIANT_ESP32H2) | ||||
| @@ -22,6 +19,8 @@ | ||||
| #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) | ||||
| #include <esp_private/usb_console.h> | ||||
| #endif | ||||
| #elif defined(USE_ARDUINO) | ||||
| #include <HardwareSerial.h> | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -60,11 +59,10 @@ class ImprovSerialComponent : public Component, public improv_base::ImprovBase { | ||||
|   optional<uint8_t> read_byte_(); | ||||
|   void write_data_(std::vector<uint8_t> &data); | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
|   Stream *hw_serial_{nullptr}; | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|   uart_port_t uart_num_; | ||||
| #elif defined(USE_ARDUINO) | ||||
|   Stream *hw_serial_{nullptr}; | ||||
| #endif | ||||
|  | ||||
|   std::vector<uint8_t> rx_buffer_; | ||||
|   | ||||
| @@ -117,8 +117,6 @@ UART_SELECTION_LIBRETINY = { | ||||
|     COMPONENT_RTL87XX: [DEFAULT, UART0, UART1, UART2], | ||||
| } | ||||
|  | ||||
| ESP_ARDUINO_UNSUPPORTED_USB_UARTS = [USB_SERIAL_JTAG] | ||||
|  | ||||
| UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1] | ||||
|  | ||||
| UART_SELECTION_NRF52 = [USB_CDC, UART0] | ||||
| @@ -153,13 +151,7 @@ is_log_level = cv.one_of(*LOG_LEVELS, upper=True) | ||||
|  | ||||
| def uart_selection(value): | ||||
|     if CORE.is_esp32: | ||||
|         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 CORE.using_esp_idf and variant == VARIANT_ESP32C3 and value == USB_CDC: | ||||
|             raise cv.Invalid( | ||||
|                 f"{value} is not supported for variant {variant} when using ESP-IDF." | ||||
|             ) | ||||
|         if variant in UART_SELECTION_ESP32: | ||||
|             return cv.one_of(*UART_SELECTION_ESP32[variant], upper=True)(value) | ||||
|     if CORE.is_esp8266: | ||||
| @@ -226,14 +218,11 @@ CONFIG_SCHEMA = cv.All( | ||||
|                 esp8266=UART0, | ||||
|                 esp32=UART0, | ||||
|                 esp32_s2=USB_CDC, | ||||
|                 esp32_s3_arduino=USB_CDC, | ||||
|                 esp32_s3_idf=USB_SERIAL_JTAG, | ||||
|                 esp32_c3_arduino=USB_CDC, | ||||
|                 esp32_c3_idf=USB_SERIAL_JTAG, | ||||
|                 esp32_c5_idf=USB_SERIAL_JTAG, | ||||
|                 esp32_c6_arduino=USB_CDC, | ||||
|                 esp32_c6_idf=USB_SERIAL_JTAG, | ||||
|                 esp32_p4_idf=USB_SERIAL_JTAG, | ||||
|                 esp32_s3=USB_SERIAL_JTAG, | ||||
|                 esp32_c3=USB_SERIAL_JTAG, | ||||
|                 esp32_c5=USB_SERIAL_JTAG, | ||||
|                 esp32_c6=USB_SERIAL_JTAG, | ||||
|                 esp32_p4=USB_SERIAL_JTAG, | ||||
|                 rp2040=USB_CDC, | ||||
|                 bk72xx=DEFAULT, | ||||
|                 ln882x=DEFAULT, | ||||
| @@ -346,15 +335,7 @@ 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 and config[CONF_HARDWARE_UART] == USB_CDC: | ||||
|         cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1") | ||||
|         if CORE.is_esp32 and get_esp32_variant() in ( | ||||
|             VARIANT_ESP32C3, | ||||
|             VARIANT_ESP32C6, | ||||
|         ): | ||||
|             cg.add_build_flag("-DARDUINO_USB_MODE=1") | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|     if CORE.is_esp32: | ||||
|         if config[CONF_HARDWARE_UART] == USB_CDC: | ||||
|             add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_USB_CDC", True) | ||||
|         elif config[CONF_HARDWARE_UART] == USB_SERIAL_JTAG: | ||||
|   | ||||
| @@ -173,24 +173,8 @@ void Logger::init_log_buffer(size_t total_buffer_size) { | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifndef USE_ZEPHYR | ||||
| #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32) | ||||
| void Logger::loop() { | ||||
| #if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO) | ||||
|   if (this->uart_ == UART_SELECTION_USB_CDC) { | ||||
|     static bool opened = false; | ||||
|     if (opened == Serial) { | ||||
|       return; | ||||
|     } | ||||
|     if (false == opened) { | ||||
|       App.schedule_dump_config(); | ||||
|     } | ||||
|     opened = !opened; | ||||
|   } | ||||
| #endif | ||||
|   this->process_messages_(); | ||||
| } | ||||
| #endif | ||||
| #ifdef USE_ESPHOME_TASK_LOG_BUFFER | ||||
| void Logger::loop() { this->process_messages_(); } | ||||
| #endif | ||||
|  | ||||
| void Logger::process_messages_() { | ||||
|   | ||||
| @@ -16,18 +16,18 @@ | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_ARDUINO | ||||
| #if defined(USE_ESP8266) || defined(USE_ESP32) | ||||
| #if defined(USE_ESP8266) | ||||
| #include <HardwareSerial.h> | ||||
| #endif  // USE_ESP8266 || USE_ESP32 | ||||
| #endif  // USE_ESP8266 | ||||
| #ifdef USE_RP2040 | ||||
| #include <HardwareSerial.h> | ||||
| #include <SerialUSB.h> | ||||
| #endif  // USE_RP2040 | ||||
| #endif  // USE_ARDUINO | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
| #include <driver/uart.h> | ||||
| #endif  // USE_ESP_IDF | ||||
| #endif  // USE_ESP32 | ||||
|  | ||||
| #ifdef USE_ZEPHYR | ||||
| #include <zephyr/kernel.h> | ||||
| @@ -110,19 +110,17 @@ class Logger : public Component { | ||||
| #ifdef USE_ESPHOME_TASK_LOG_BUFFER | ||||
|   void init_log_buffer(size_t total_buffer_size); | ||||
| #endif | ||||
| #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32) || defined(USE_ZEPHYR) | ||||
| #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)) | ||||
|   void loop() override; | ||||
| #endif | ||||
|   /// Manually set the baud rate for serial, set to 0 to disable. | ||||
|   void set_baud_rate(uint32_t baud_rate); | ||||
|   uint32_t get_baud_rate() const { return baud_rate_; } | ||||
| #ifdef USE_ARDUINO | ||||
| #if defined(USE_ARDUINO) && !defined(USE_ESP32) | ||||
|   Stream *get_hw_serial() const { return hw_serial_; } | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
|   uart_port_t get_uart_num() const { return uart_num_; } | ||||
| #endif | ||||
| #ifdef USE_ESP32 | ||||
|   uart_port_t get_uart_num() const { return uart_num_; } | ||||
|   void create_pthread_key() { pthread_key_create(&log_recursion_key_, nullptr); } | ||||
| #endif | ||||
| #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) | ||||
| @@ -232,7 +230,7 @@ class Logger : public Component { | ||||
|   // Group 4-byte aligned members first | ||||
|   uint32_t baud_rate_; | ||||
|   char *tx_buffer_{nullptr}; | ||||
| #ifdef USE_ARDUINO | ||||
| #if defined(USE_ARDUINO) && !defined(USE_ESP32) | ||||
|   Stream *hw_serial_{nullptr}; | ||||
| #endif | ||||
| #if defined(USE_ZEPHYR) | ||||
| @@ -246,9 +244,7 @@ class Logger : public Component { | ||||
|   // - Main task uses a dedicated member variable for efficiency | ||||
|   // - Other tasks use pthread TLS with a dynamically created key via pthread_key_create | ||||
|   pthread_key_t log_recursion_key_;  // 4 bytes | ||||
| #endif | ||||
| #ifdef USE_ESP_IDF | ||||
|   uart_port_t uart_num_;  // 4 bytes (enum defaults to int size) | ||||
|   uart_port_t uart_num_;             // 4 bytes (enum defaults to int size) | ||||
| #endif | ||||
|  | ||||
|   // Large objects (internally aligned) | ||||
| @@ -380,15 +376,7 @@ class Logger : public Component { | ||||
|     // will be processed on the next main loop iteration since: | ||||
|     // - disable_loop() takes effect immediately | ||||
|     // - enable_loop_soon_any_context() sets a pending flag that's checked at loop start | ||||
| #if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO) | ||||
|     // Only disable if not using USB CDC (which needs loop for connection detection) | ||||
|     if (this->uart_ != UART_SELECTION_USB_CDC) { | ||||
|       this->disable_loop(); | ||||
|     } | ||||
| #else | ||||
|     // No USB CDC support, always safe to disable | ||||
|     this->disable_loop(); | ||||
| #endif | ||||
|   } | ||||
| #endif | ||||
| }; | ||||
|   | ||||
| @@ -1,11 +1,8 @@ | ||||
| #ifdef USE_ESP32 | ||||
| #include "logger.h" | ||||
|  | ||||
| #if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_ESP_IDF) | ||||
| #include <esp_log.h> | ||||
| #endif  // USE_ESP32_FRAMEWORK_ARDUINO || USE_ESP_IDF | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
| #include <driver/uart.h> | ||||
|  | ||||
| #ifdef USE_LOGGER_USB_SERIAL_JTAG | ||||
| @@ -25,16 +22,12 @@ | ||||
| #include <cstdint> | ||||
| #include <cstdio> | ||||
|  | ||||
| #endif  // USE_ESP_IDF | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| namespace esphome::logger { | ||||
|  | ||||
| static const char *const TAG = "logger"; | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
|  | ||||
| #ifdef USE_LOGGER_USB_SERIAL_JTAG | ||||
| static void init_usb_serial_jtag_() { | ||||
|   setvbuf(stdin, NULL, _IONBF, 0);  // Disable buffering on stdin | ||||
| @@ -89,42 +82,8 @@ void init_uart(uart_port_t uart_num, uint32_t baud_rate, int tx_buffer_size) { | ||||
|   uart_driver_install(uart_num, uart_buffer_size, uart_buffer_size, 10, nullptr, 0); | ||||
| } | ||||
|  | ||||
| #endif  // USE_ESP_IDF | ||||
|  | ||||
| void Logger::pre_setup() { | ||||
|   if (this->baud_rate_ > 0) { | ||||
| #ifdef USE_ARDUINO | ||||
|     switch (this->uart_) { | ||||
|       case UART_SELECTION_UART0: | ||||
| #if ARDUINO_USB_CDC_ON_BOOT | ||||
|         this->hw_serial_ = &Serial0; | ||||
|         Serial0.begin(this->baud_rate_); | ||||
| #else | ||||
|         this->hw_serial_ = &Serial; | ||||
|         Serial.begin(this->baud_rate_); | ||||
| #endif | ||||
|         break; | ||||
|       case UART_SELECTION_UART1: | ||||
|         this->hw_serial_ = &Serial1; | ||||
|         Serial1.begin(this->baud_rate_); | ||||
|         break; | ||||
| #ifdef USE_ESP32_VARIANT_ESP32 | ||||
|       case UART_SELECTION_UART2: | ||||
|         this->hw_serial_ = &Serial2; | ||||
|         Serial2.begin(this->baud_rate_); | ||||
|         break; | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_LOGGER_USB_CDC | ||||
|       case UART_SELECTION_USB_CDC: | ||||
|         this->hw_serial_ = &Serial; | ||||
|         Serial.begin(this->baud_rate_); | ||||
|         break; | ||||
| #endif | ||||
|     } | ||||
| #endif  // USE_ARDUINO | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
|     this->uart_num_ = UART_NUM_0; | ||||
|     switch (this->uart_) { | ||||
|       case UART_SELECTION_UART0: | ||||
| @@ -151,21 +110,17 @@ void Logger::pre_setup() { | ||||
|         break; | ||||
| #endif | ||||
|     } | ||||
| #endif  // USE_ESP_IDF | ||||
|   } | ||||
|  | ||||
|   global_logger = this; | ||||
| #if defined(USE_ESP_IDF) || defined(USE_ESP32_FRAMEWORK_ARDUINO) | ||||
|   esp_log_set_vprintf(esp_idf_log_vprintf_); | ||||
|   if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE) { | ||||
|     esp_log_level_set("*", ESP_LOG_VERBOSE); | ||||
|   } | ||||
| #endif  // USE_ESP_IDF || USE_ESP32_FRAMEWORK_ARDUINO | ||||
|  | ||||
|   ESP_LOGI(TAG, "Log initialized"); | ||||
| } | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
| void HOT Logger::write_msg_(const char *msg) { | ||||
|   if ( | ||||
| #if defined(USE_LOGGER_USB_CDC) && !defined(USE_LOGGER_USB_SERIAL_JTAG) | ||||
| @@ -186,9 +141,6 @@ void HOT Logger::write_msg_(const char *msg) { | ||||
|     uart_write_bytes(this->uart_num_, "\n", 1); | ||||
|   } | ||||
| } | ||||
| #else | ||||
| void HOT Logger::write_msg_(const char *msg) { this->hw_serial_->println(msg); } | ||||
| #endif | ||||
|  | ||||
| const LogString *Logger::get_uart_selection_() { | ||||
|   switch (this->uart_) { | ||||
|   | ||||
| @@ -12,8 +12,8 @@ namespace esphome::logger { | ||||
|  | ||||
| static const char *const TAG = "logger"; | ||||
|  | ||||
| void Logger::loop() { | ||||
| #ifdef USE_LOGGER_USB_CDC | ||||
| void Logger::loop() { | ||||
|   if (this->uart_ != UART_SELECTION_USB_CDC || nullptr == this->uart_dev_) { | ||||
|     return; | ||||
|   } | ||||
| @@ -30,9 +30,8 @@ void Logger::loop() { | ||||
|     App.schedule_dump_config(); | ||||
|   } | ||||
|   opened = !opened; | ||||
| #endif | ||||
|   this->process_messages_(); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void Logger::pre_setup() { | ||||
|   if (this->baud_rate_ > 0) { | ||||
|   | ||||
| @@ -47,9 +47,13 @@ async def to_code(config): | ||||
|             cg.add_define( | ||||
|                 "USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT] | ||||
|             ) | ||||
|         if CORE.using_esp_idf: | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6) | ||||
|             add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6) | ||||
|         if CORE.is_esp32: | ||||
|             if CORE.using_esp_idf: | ||||
|                 add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6) | ||||
|                 add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6) | ||||
|             else: | ||||
|                 add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", True) | ||||
|                 add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", True) | ||||
|         elif enable_ipv6: | ||||
|             cg.add_build_flag("-DCONFIG_LWIP_IPV6") | ||||
|             cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") | ||||
|   | ||||
| @@ -153,10 +153,10 @@ async def to_code(config): | ||||
|     if CONF_TFT_URL in config: | ||||
|         cg.add_define("USE_NEXTION_TFT_UPLOAD") | ||||
|         cg.add(var.set_tft_url(config[CONF_TFT_URL])) | ||||
|         if CORE.is_esp32 and CORE.using_arduino: | ||||
|             cg.add_library("NetworkClientSecure", None) | ||||
|             cg.add_library("HTTPClient", None) | ||||
|         elif CORE.is_esp32 and CORE.using_esp_idf: | ||||
|         if CORE.is_esp32: | ||||
|             if CORE.using_arduino: | ||||
|                 cg.add_library("NetworkClientSecure", None) | ||||
|                 cg.add_library("HTTPClient", None) | ||||
|             esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True) | ||||
|             esp32.add_idf_sdkconfig_option( | ||||
|                 "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True | ||||
|   | ||||
| @@ -121,33 +121,30 @@ async def to_code(config): | ||||
|         if config[CONF_MODE] == TYPE_OCTAL: | ||||
|             cg.add_platformio_option("board_build.arduino.memory_type", "qio_opi") | ||||
|  | ||||
|     if CORE.using_esp_idf: | ||||
|         add_idf_sdkconfig_option( | ||||
|             f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True | ||||
|         ) | ||||
|         add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) | ||||
|     add_idf_sdkconfig_option( | ||||
|         f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True | ||||
|     ) | ||||
|     add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_SPIRAM", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) | ||||
|  | ||||
|         add_idf_sdkconfig_option( | ||||
|             f"CONFIG_SPIRAM_MODE_{SDK_MODES[config[CONF_MODE]]}", True | ||||
|         ) | ||||
|     add_idf_sdkconfig_option(f"CONFIG_SPIRAM_MODE_{SDK_MODES[config[CONF_MODE]]}", True) | ||||
|  | ||||
|         # Remove MHz suffix, convert to int | ||||
|         speed = int(config[CONF_SPEED][:-3]) | ||||
|         add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed) | ||||
|         if config[CONF_MODE] == TYPE_OCTAL and speed == 120: | ||||
|             add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) | ||||
|             add_idf_sdkconfig_option("CONFIG_BOOTLOADER_FLASH_DC_AWARE", True) | ||||
|             if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0): | ||||
|                 add_idf_sdkconfig_option( | ||||
|                     "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True | ||||
|                 ) | ||||
|         if config[CONF_ENABLE_ECC]: | ||||
|             add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True) | ||||
|     # Remove MHz suffix, convert to int | ||||
|     speed = int(config[CONF_SPEED][:-3]) | ||||
|     add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True) | ||||
|     add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed) | ||||
|     if config[CONF_MODE] == TYPE_OCTAL and speed == 120: | ||||
|         add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) | ||||
|         add_idf_sdkconfig_option("CONFIG_BOOTLOADER_FLASH_DC_AWARE", True) | ||||
|         if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0): | ||||
|             add_idf_sdkconfig_option( | ||||
|                 "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True | ||||
|             ) | ||||
|     if config[CONF_ENABLE_ECC]: | ||||
|         add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True) | ||||
|  | ||||
|     cg.add_define("USE_PSRAM") | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,6 @@ from esphome.const import ( | ||||
|     CONF_DUMMY_RECEIVER_ID, | ||||
|     CONF_ID, | ||||
|     CONF_INVERT, | ||||
|     CONF_INVERTED, | ||||
|     CONF_LAMBDA, | ||||
|     CONF_NUMBER, | ||||
|     CONF_PORT, | ||||
| @@ -39,9 +38,6 @@ uart_ns = cg.esphome_ns.namespace("uart") | ||||
| UARTComponent = uart_ns.class_("UARTComponent") | ||||
|  | ||||
| IDFUARTComponent = uart_ns.class_("IDFUARTComponent", UARTComponent, cg.Component) | ||||
| ESP32ArduinoUARTComponent = uart_ns.class_( | ||||
|     "ESP32ArduinoUARTComponent", UARTComponent, cg.Component | ||||
| ) | ||||
| ESP8266UartComponent = uart_ns.class_( | ||||
|     "ESP8266UartComponent", UARTComponent, cg.Component | ||||
| ) | ||||
| @@ -53,7 +49,6 @@ HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Compon | ||||
|  | ||||
| NATIVE_UART_CLASSES = ( | ||||
|     str(IDFUARTComponent), | ||||
|     str(ESP32ArduinoUARTComponent), | ||||
|     str(ESP8266UartComponent), | ||||
|     str(RP2040UartComponent), | ||||
|     str(LibreTinyUARTComponent), | ||||
| @@ -119,20 +114,6 @@ def validate_rx_pin(value): | ||||
|     return value | ||||
|  | ||||
|  | ||||
| def validate_invert_esp32(config): | ||||
|     if ( | ||||
|         CORE.is_esp32 | ||||
|         and CORE.using_arduino | ||||
|         and CONF_TX_PIN in config | ||||
|         and CONF_RX_PIN in config | ||||
|         and config[CONF_TX_PIN][CONF_INVERTED] != config[CONF_RX_PIN][CONF_INVERTED] | ||||
|     ): | ||||
|         raise cv.Invalid( | ||||
|             "Different invert values for TX and RX pin are not supported for ESP32 when using Arduino." | ||||
|         ) | ||||
|     return config | ||||
|  | ||||
|  | ||||
| def validate_host_config(config): | ||||
|     if CORE.is_host: | ||||
|         if CONF_TX_PIN in config or CONF_RX_PIN in config: | ||||
| @@ -151,10 +132,7 @@ def _uart_declare_type(value): | ||||
|     if CORE.is_esp8266: | ||||
|         return cv.declare_id(ESP8266UartComponent)(value) | ||||
|     if CORE.is_esp32: | ||||
|         if CORE.using_arduino: | ||||
|             return cv.declare_id(ESP32ArduinoUARTComponent)(value) | ||||
|         if CORE.using_esp_idf: | ||||
|             return cv.declare_id(IDFUARTComponent)(value) | ||||
|         return cv.declare_id(IDFUARTComponent)(value) | ||||
|     if CORE.is_rp2040: | ||||
|         return cv.declare_id(RP2040UartComponent)(value) | ||||
|     if CORE.is_libretiny: | ||||
| @@ -255,7 +233,6 @@ CONFIG_SCHEMA = cv.All( | ||||
|         } | ||||
|     ).extend(cv.COMPONENT_SCHEMA), | ||||
|     cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT), | ||||
|     validate_invert_esp32, | ||||
|     validate_host_config, | ||||
| ) | ||||
|  | ||||
| @@ -444,8 +421,10 @@ async def uart_write_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
| FILTER_SOURCE_FILES = filter_source_files_from_platform( | ||||
|     { | ||||
|         "uart_component_esp32_arduino.cpp": {PlatformFramework.ESP32_ARDUINO}, | ||||
|         "uart_component_esp_idf.cpp": {PlatformFramework.ESP32_IDF}, | ||||
|         "uart_component_esp_idf.cpp": { | ||||
|             PlatformFramework.ESP32_IDF, | ||||
|             PlatformFramework.ESP32_ARDUINO, | ||||
|         }, | ||||
|         "uart_component_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO}, | ||||
|         "uart_component_host.cpp": {PlatformFramework.HOST_NATIVE}, | ||||
|         "uart_component_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO}, | ||||
|   | ||||
| @@ -1,214 +0,0 @@ | ||||
| #ifdef USE_ESP32_FRAMEWORK_ARDUINO | ||||
| #include "uart_component_esp32_arduino.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include "esphome/core/defines.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| #ifdef USE_LOGGER | ||||
| #include "esphome/components/logger/logger.h" | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uart { | ||||
| static const char *const TAG = "uart.arduino_esp32"; | ||||
|  | ||||
| static const uint32_t UART_PARITY_EVEN = 0 << 0; | ||||
| static const uint32_t UART_PARITY_ODD = 1 << 0; | ||||
| static const uint32_t UART_PARITY_ENABLE = 1 << 1; | ||||
| static const uint32_t UART_NB_BIT_5 = 0 << 2; | ||||
| static const uint32_t UART_NB_BIT_6 = 1 << 2; | ||||
| static const uint32_t UART_NB_BIT_7 = 2 << 2; | ||||
| static const uint32_t UART_NB_BIT_8 = 3 << 2; | ||||
| static const uint32_t UART_NB_STOP_BIT_1 = 1 << 4; | ||||
| static const uint32_t UART_NB_STOP_BIT_2 = 3 << 4; | ||||
| static const uint32_t UART_TICK_APB_CLOCK = 1 << 27; | ||||
|  | ||||
| uint32_t ESP32ArduinoUARTComponent::get_config() { | ||||
|   uint32_t config = 0; | ||||
|  | ||||
|   /* | ||||
|    * All bits numbers below come from | ||||
|    * framework-arduinoespressif32/cores/esp32/esp32-hal-uart.h | ||||
|    * And more specifically conf0 union in uart_dev_t. | ||||
|    * | ||||
|    * Below is bit used from conf0 union. | ||||
|    * <name>:<bits position>  <values> | ||||
|    * parity:0                0:even 1:odd | ||||
|    * parity_en:1             Set this bit to enable uart parity check. | ||||
|    * bit_num:2-4             0:5bits 1:6bits 2:7bits 3:8bits | ||||
|    * stop_bit_num:4-6        stop bit. 1:1bit  2:1.5bits  3:2bits | ||||
|    * tick_ref_always_on:27   select the clock.1:apb clock:ref_tick | ||||
|    */ | ||||
|  | ||||
|   if (this->parity_ == UART_CONFIG_PARITY_EVEN) { | ||||
|     config |= UART_PARITY_EVEN | UART_PARITY_ENABLE; | ||||
|   } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { | ||||
|     config |= UART_PARITY_ODD | UART_PARITY_ENABLE; | ||||
|   } | ||||
|  | ||||
|   switch (this->data_bits_) { | ||||
|     case 5: | ||||
|       config |= UART_NB_BIT_5; | ||||
|       break; | ||||
|     case 6: | ||||
|       config |= UART_NB_BIT_6; | ||||
|       break; | ||||
|     case 7: | ||||
|       config |= UART_NB_BIT_7; | ||||
|       break; | ||||
|     case 8: | ||||
|       config |= UART_NB_BIT_8; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   if (this->stop_bits_ == 1) { | ||||
|     config |= UART_NB_STOP_BIT_1; | ||||
|   } else { | ||||
|     config |= UART_NB_STOP_BIT_2; | ||||
|   } | ||||
|  | ||||
|   config |= UART_TICK_APB_CLOCK; | ||||
|  | ||||
|   return config; | ||||
| } | ||||
|  | ||||
| void ESP32ArduinoUARTComponent::setup() { | ||||
|   // Use Arduino HardwareSerial UARTs if all used pins match the ones | ||||
|   // preconfigured by the platform. For example if RX disabled but TX pin | ||||
|   // is 1 we still want to use Serial. | ||||
|   bool is_default_tx, is_default_rx; | ||||
| #ifdef CONFIG_IDF_TARGET_ESP32C3 | ||||
|   is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 21; | ||||
|   is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 20; | ||||
| #else | ||||
|   is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 1; | ||||
|   is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 3; | ||||
| #endif | ||||
|   static uint8_t next_uart_num = 0; | ||||
|   if (is_default_tx && is_default_rx && next_uart_num == 0) { | ||||
| #if ARDUINO_USB_CDC_ON_BOOT | ||||
|     this->hw_serial_ = &Serial0; | ||||
| #else | ||||
|     this->hw_serial_ = &Serial; | ||||
| #endif | ||||
|     next_uart_num++; | ||||
|   } else { | ||||
| #ifdef USE_LOGGER | ||||
|     bool logger_uses_hardware_uart = true; | ||||
|  | ||||
| #ifdef USE_LOGGER_USB_CDC | ||||
|     if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) { | ||||
|       // this is not a hardware UART, ignore it | ||||
|       logger_uses_hardware_uart = false; | ||||
|     } | ||||
| #endif  // USE_LOGGER_USB_CDC | ||||
|  | ||||
| #ifdef USE_LOGGER_USB_SERIAL_JTAG | ||||
|     if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) { | ||||
|       // this is not a hardware UART, ignore it | ||||
|       logger_uses_hardware_uart = false; | ||||
|     } | ||||
| #endif  // USE_LOGGER_USB_SERIAL_JTAG | ||||
|  | ||||
|     if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 && | ||||
|         logger::global_logger->get_uart() == next_uart_num) { | ||||
|       next_uart_num++; | ||||
|     } | ||||
| #endif  // USE_LOGGER | ||||
|  | ||||
|     if (next_uart_num >= SOC_UART_NUM) { | ||||
|       ESP_LOGW(TAG, "Maximum number of UART components created already."); | ||||
|       this->mark_failed(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this->number_ = next_uart_num; | ||||
|     this->hw_serial_ = new HardwareSerial(next_uart_num++);  // NOLINT(cppcoreguidelines-owning-memory) | ||||
|   } | ||||
|  | ||||
|   this->load_settings(false); | ||||
| } | ||||
|  | ||||
| void ESP32ArduinoUARTComponent::load_settings(bool dump_config) { | ||||
|   int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; | ||||
|   int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; | ||||
|   bool invert = false; | ||||
|   if (tx_pin_ != nullptr && tx_pin_->is_inverted()) | ||||
|     invert = true; | ||||
|   if (rx_pin_ != nullptr && rx_pin_->is_inverted()) | ||||
|     invert = true; | ||||
|   this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); | ||||
|   this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert); | ||||
|   if (dump_config) { | ||||
|     ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->number_); | ||||
|     this->dump_config(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void ESP32ArduinoUARTComponent::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "UART Bus %d:", this->number_); | ||||
|   LOG_PIN("  TX Pin: ", tx_pin_); | ||||
|   LOG_PIN("  RX Pin: ", rx_pin_); | ||||
|   if (this->rx_pin_ != nullptr) { | ||||
|     ESP_LOGCONFIG(TAG, "  RX Buffer Size: %u", this->rx_buffer_size_); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, | ||||
|                 "  Baud Rate: %u baud\n" | ||||
|                 "  Data Bits: %u\n" | ||||
|                 "  Parity: %s\n" | ||||
|                 "  Stop bits: %u", | ||||
|                 this->baud_rate_, this->data_bits_, LOG_STR_ARG(parity_to_str(this->parity_)), this->stop_bits_); | ||||
|   this->check_logger_conflict(); | ||||
| } | ||||
|  | ||||
| void ESP32ArduinoUARTComponent::write_array(const uint8_t *data, size_t len) { | ||||
|   this->hw_serial_->write(data, len); | ||||
| #ifdef USE_UART_DEBUGGER | ||||
|   for (size_t i = 0; i < len; i++) { | ||||
|     this->debug_callback_.call(UART_DIRECTION_TX, data[i]); | ||||
|   } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool ESP32ArduinoUARTComponent::peek_byte(uint8_t *data) { | ||||
|   if (!this->check_read_timeout_()) | ||||
|     return false; | ||||
|   *data = this->hw_serial_->peek(); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool ESP32ArduinoUARTComponent::read_array(uint8_t *data, size_t len) { | ||||
|   if (!this->check_read_timeout_(len)) | ||||
|     return false; | ||||
|   this->hw_serial_->readBytes(data, len); | ||||
| #ifdef USE_UART_DEBUGGER | ||||
|   for (size_t i = 0; i < len; i++) { | ||||
|     this->debug_callback_.call(UART_DIRECTION_RX, data[i]); | ||||
|   } | ||||
| #endif | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| int ESP32ArduinoUARTComponent::available() { return this->hw_serial_->available(); } | ||||
| void ESP32ArduinoUARTComponent::flush() { | ||||
|   ESP_LOGVV(TAG, "    Flushing"); | ||||
|   this->hw_serial_->flush(); | ||||
| } | ||||
|  | ||||
| void ESP32ArduinoUARTComponent::check_logger_conflict() { | ||||
| #ifdef USE_LOGGER | ||||
|   if (this->hw_serial_ == nullptr || logger::global_logger->get_baud_rate() == 0) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if (this->hw_serial_ == logger::global_logger->get_hw_serial()) { | ||||
|     ESP_LOGW(TAG, "  You're using the same serial port for logging and the UART component. Please " | ||||
|                   "disable logging over the serial port by setting logger->baud_rate to 0."); | ||||
|   } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| }  // namespace uart | ||||
| }  // namespace esphome | ||||
| #endif  // USE_ESP32_FRAMEWORK_ARDUINO | ||||
| @@ -1,60 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #ifdef USE_ESP32_FRAMEWORK_ARDUINO | ||||
|  | ||||
| #include <driver/uart.h> | ||||
| #include <HardwareSerial.h> | ||||
| #include <vector> | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "uart_component.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uart { | ||||
|  | ||||
| class ESP32ArduinoUARTComponent : public UARTComponent, public Component { | ||||
|  public: | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override { return setup_priority::BUS; } | ||||
|  | ||||
|   void write_array(const uint8_t *data, size_t len) override; | ||||
|  | ||||
|   bool peek_byte(uint8_t *data) override; | ||||
|   bool read_array(uint8_t *data, size_t len) override; | ||||
|  | ||||
|   int available() override; | ||||
|   void flush() override; | ||||
|  | ||||
|   uint32_t get_config(); | ||||
|  | ||||
|   HardwareSerial *get_hw_serial() { return this->hw_serial_; } | ||||
|   uint8_t get_hw_serial_number() { return this->number_; } | ||||
|  | ||||
|   /** | ||||
|    * Load the UART with the current settings. | ||||
|    * @param dump_config (Optional, default `true`): True for displaying new settings or | ||||
|    * false to change it quitely | ||||
|    * | ||||
|    * Example: | ||||
|    * ```cpp | ||||
|    * id(uart1).load_settings(); | ||||
|    * ``` | ||||
|    * | ||||
|    * This will load the current UART interface with the latest settings (baud_rate, parity, etc). | ||||
|    */ | ||||
|   void load_settings(bool dump_config) override; | ||||
|   void load_settings() override { this->load_settings(true); } | ||||
|  | ||||
|  protected: | ||||
|   void check_logger_conflict() override; | ||||
|  | ||||
|   HardwareSerial *hw_serial_{nullptr}; | ||||
|   uint8_t number_{0}; | ||||
| }; | ||||
|  | ||||
| }  // namespace uart | ||||
| }  // namespace esphome | ||||
|  | ||||
| #endif  // USE_ESP32_FRAMEWORK_ARDUINO | ||||
| @@ -1,4 +1,4 @@ | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|  | ||||
| #include "uart_component_esp_idf.h" | ||||
| #include <cinttypes> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #ifdef USE_ESP_IDF | ||||
| #ifdef USE_ESP32 | ||||
|  | ||||
| #include <driver/uart.h> | ||||
| #include "esphome/core/component.h" | ||||
| @@ -55,4 +55,4 @@ class IDFUARTComponent : public UARTComponent, public Component { | ||||
| }  // namespace uart | ||||
| }  // namespace esphome | ||||
|  | ||||
| #endif  // USE_ESP_IDF | ||||
| #endif  // USE_ESP32 | ||||
|   | ||||
| @@ -402,7 +402,7 @@ async def to_code(config): | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False) | ||||
|  | ||||
|     # Disable Enterprise WiFi support if no EAP is configured | ||||
|     if CORE.is_esp32 and CORE.using_esp_idf and not has_eap: | ||||
|     if CORE.is_esp32 and not has_eap: | ||||
|         add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT", False) | ||||
|  | ||||
|     cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) | ||||
|   | ||||
| @@ -118,7 +118,7 @@ async def to_code(config): | ||||
|  | ||||
|     # Workaround for crash on IDF 5+ | ||||
|     # See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651 | ||||
|     if CORE.using_esp_idf: | ||||
|     if CORE.is_esp32: | ||||
|         add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True) | ||||
|  | ||||
|     # This flag is added here because the esp_wireguard library statically | ||||
|   | ||||
| @@ -71,6 +71,8 @@ FILTER_PLATFORMIO_LINES = [ | ||||
|     r" - tool-esptool.* \(.*\)", | ||||
|     r" - toolchain-.* \(.*\)", | ||||
|     r"Creating BIN file .*", | ||||
|     r"Warning! Could not find file \".*.crt\"", | ||||
|     r"Warning! Arduino framework as an ESP-IDF component doesn't handle the `variant` field! The default `esp32` variant will be used.", | ||||
| ] | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import os | ||||
| import random | ||||
| import string | ||||
| from typing import Literal, NotRequired, TypedDict, Unpack | ||||
| import unicodedata | ||||
|  | ||||
| import voluptuous as vol | ||||
| @@ -103,11 +104,25 @@ HARDWARE_BASE_CONFIGS = { | ||||
| } | ||||
|  | ||||
|  | ||||
| def sanitize_double_quotes(value): | ||||
| def sanitize_double_quotes(value: str) -> str: | ||||
|     return value.replace("\\", "\\\\").replace('"', '\\"') | ||||
|  | ||||
|  | ||||
| def wizard_file(**kwargs): | ||||
| class WizardFileKwargs(TypedDict): | ||||
|     """Keyword arguments for wizard_file function.""" | ||||
|  | ||||
|     name: str | ||||
|     platform: Literal["ESP8266", "ESP32", "RP2040", "BK72XX", "LN882X", "RTL87XX"] | ||||
|     board: str | ||||
|     ssid: NotRequired[str] | ||||
|     psk: NotRequired[str] | ||||
|     password: NotRequired[str] | ||||
|     ota_password: NotRequired[str] | ||||
|     api_encryption_key: NotRequired[str] | ||||
|     friendly_name: NotRequired[str] | ||||
|  | ||||
|  | ||||
| def wizard_file(**kwargs: Unpack[WizardFileKwargs]) -> str: | ||||
|     letters = string.ascii_letters + string.digits | ||||
|     ap_name_base = kwargs["name"].replace("_", " ").title() | ||||
|     ap_name = f"{ap_name_base} Fallback Hotspot" | ||||
| @@ -180,7 +195,25 @@ captive_portal: | ||||
|     return config | ||||
|  | ||||
|  | ||||
| def wizard_write(path, **kwargs): | ||||
| class WizardWriteKwargs(TypedDict): | ||||
|     """Keyword arguments for wizard_write function.""" | ||||
|  | ||||
|     name: str | ||||
|     type: Literal["basic", "empty", "upload"] | ||||
|     # Required for "basic" type | ||||
|     board: NotRequired[str] | ||||
|     platform: NotRequired[str] | ||||
|     ssid: NotRequired[str] | ||||
|     psk: NotRequired[str] | ||||
|     password: NotRequired[str] | ||||
|     ota_password: NotRequired[str] | ||||
|     api_encryption_key: NotRequired[str] | ||||
|     friendly_name: NotRequired[str] | ||||
|     # Required for "upload" type | ||||
|     file_text: NotRequired[str] | ||||
|  | ||||
|  | ||||
| def wizard_write(path: str, **kwargs: Unpack[WizardWriteKwargs]) -> bool: | ||||
|     from esphome.components.bk72xx import boards as bk72xx_boards | ||||
|     from esphome.components.esp32 import boards as esp32_boards | ||||
|     from esphome.components.esp8266 import boards as esp8266_boards | ||||
| @@ -237,14 +270,14 @@ def wizard_write(path, **kwargs): | ||||
|  | ||||
| if get_bool_env(ENV_QUICKWIZARD): | ||||
|  | ||||
|     def sleep(time): | ||||
|     def sleep(time: float) -> None: | ||||
|         pass | ||||
|  | ||||
| else: | ||||
|     from time import sleep | ||||
|  | ||||
|  | ||||
| def safe_print_step(step, big): | ||||
| def safe_print_step(step: int, big: str) -> None: | ||||
|     safe_print() | ||||
|     safe_print() | ||||
|     safe_print(f"============= STEP {step} =============") | ||||
| @@ -253,14 +286,14 @@ def safe_print_step(step, big): | ||||
|     sleep(0.25) | ||||
|  | ||||
|  | ||||
| def default_input(text, default): | ||||
| def default_input(text: str, default: str) -> str: | ||||
|     safe_print() | ||||
|     safe_print(f"Press ENTER for default ({default})") | ||||
|     return safe_input(text.format(default)) or default | ||||
|  | ||||
|  | ||||
| # From https://stackoverflow.com/a/518232/8924614 | ||||
| def strip_accents(value): | ||||
| def strip_accents(value: str) -> str: | ||||
|     return "".join( | ||||
|         c | ||||
|         for c in unicodedata.normalize("NFD", str(value)) | ||||
| @@ -268,7 +301,7 @@ def strip_accents(value): | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def wizard(path): | ||||
| def wizard(path: str) -> int: | ||||
|     from esphome.components.bk72xx import boards as bk72xx_boards | ||||
|     from esphome.components.esp32 import boards as esp32_boards | ||||
|     from esphome.components.esp8266 import boards as esp8266_boards | ||||
| @@ -509,6 +542,7 @@ def wizard(path): | ||||
|         ssid=ssid, | ||||
|         psk=psk, | ||||
|         password=password, | ||||
|         type="basic", | ||||
|     ): | ||||
|         return 1 | ||||
|  | ||||
|   | ||||
| @@ -317,10 +317,16 @@ def clean_build(): | ||||
|  | ||||
|     # Clean PlatformIO cache to resolve CMake compiler detection issues | ||||
|     # This helps when toolchain paths change or get corrupted | ||||
|     cache_dir = CORE.platformio_cache_dir | ||||
|     if os.path.isdir(cache_dir): | ||||
|         _LOGGER.info("Deleting PlatformIO cache %s", cache_dir) | ||||
|         shutil.rmtree(cache_dir) | ||||
|     try: | ||||
|         from platformio.project.helpers import get_project_cache_dir | ||||
|     except ImportError: | ||||
|         # PlatformIO is not available, skip cache cleaning | ||||
|         pass | ||||
|     else: | ||||
|         cache_dir = get_project_cache_dir() | ||||
|         if cache_dir and cache_dir.strip() and os.path.isdir(cache_dir): | ||||
|             _LOGGER.info("Deleting PlatformIO cache %s", cache_dir) | ||||
|             shutil.rmtree(cache_dir) | ||||
|  | ||||
|  | ||||
| GITIGNORE_CONTENT = """# Gitignore settings for ESPHome | ||||
|   | ||||
		Reference in New Issue
	
	Block a user