esphome 2025.9.3__py3-none-any.whl → 2025.10.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. esphome/__main__.py +94 -31
  2. esphome/address_cache.py +142 -0
  3. esphome/automation.py +130 -32
  4. esphome/build_gen/platformio.py +1 -3
  5. esphome/codegen.py +1 -0
  6. esphome/components/animation/animation.cpp +2 -2
  7. esphome/components/api/__init__.py +166 -3
  8. esphome/components/api/api_connection.cpp +84 -41
  9. esphome/components/api/api_connection.h +22 -16
  10. esphome/components/api/api_frame_helper.cpp +33 -19
  11. esphome/components/api/api_frame_helper.h +19 -4
  12. esphome/components/api/api_frame_helper_noise.cpp +41 -53
  13. esphome/components/api/api_frame_helper_noise.h +1 -1
  14. esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
  15. esphome/components/api/api_frame_helper_plaintext.h +1 -1
  16. esphome/components/api/api_pb2.cpp +189 -15
  17. esphome/components/api/api_pb2.h +132 -20
  18. esphome/components/api/api_pb2_dump.cpp +97 -9
  19. esphome/components/api/api_pb2_service.cpp +118 -160
  20. esphome/components/api/api_pb2_service.h +31 -3
  21. esphome/components/api/api_server.cpp +68 -10
  22. esphome/components/api/api_server.h +32 -4
  23. esphome/components/api/custom_api_device.h +8 -8
  24. esphome/components/api/homeassistant_service.h +123 -6
  25. esphome/components/api/proto.h +6 -2
  26. esphome/components/api/user_services.h +2 -2
  27. esphome/components/as7341/sensor.py +1 -1
  28. esphome/components/audio/__init__.py +1 -1
  29. esphome/components/audio/audio.cpp +1 -1
  30. esphome/components/audio/audio_decoder.cpp +9 -9
  31. esphome/components/bl0906/bl0906.cpp +2 -2
  32. esphome/components/bl0942/bl0942.cpp +2 -2
  33. esphome/components/ble_client/__init__.py +1 -1
  34. esphome/components/bluetooth_proxy/__init__.py +4 -30
  35. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
  36. esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
  37. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
  38. esphome/components/camera_encoder/__init__.py +2 -4
  39. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
  40. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
  41. esphome/components/canbus/canbus.cpp +7 -5
  42. esphome/components/canbus/canbus.h +7 -7
  43. esphome/components/captive_portal/__init__.py +18 -1
  44. esphome/components/captive_portal/captive_portal.cpp +40 -46
  45. esphome/components/captive_portal/captive_portal.h +20 -22
  46. esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
  47. esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
  48. esphome/components/ccs811/ccs811.cpp +1 -1
  49. esphome/components/climate/climate.cpp +10 -7
  50. esphome/components/cm1106/cm1106.cpp +1 -1
  51. esphome/components/copy/lock/copy_lock.cpp +1 -1
  52. esphome/components/cover/cover.cpp +1 -0
  53. esphome/components/daikin_arc/daikin_arc.cpp +19 -12
  54. esphome/components/dashboard_import/dashboard_import.cpp +1 -1
  55. esphome/components/dashboard_import/dashboard_import.h +1 -1
  56. esphome/components/deep_sleep/__init__.py +9 -2
  57. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  58. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  59. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  60. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  61. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  62. esphome/components/epaper_spi/__init__.py +1 -0
  63. esphome/components/epaper_spi/display.py +80 -0
  64. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  65. esphome/components/epaper_spi/epaper_spi.h +93 -0
  66. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  67. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  68. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  69. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  70. esphome/components/es7210/es7210.cpp +3 -3
  71. esphome/components/esp32/__init__.py +256 -340
  72. esphome/components/esp32/boards.py +81 -0
  73. esphome/components/esp32/preferences.cpp +23 -17
  74. esphome/components/esp32_ble/__init__.py +167 -44
  75. esphome/components/esp32_ble/ble.cpp +47 -3
  76. esphome/components/esp32_ble/ble.h +18 -0
  77. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  78. esphome/components/esp32_ble/ble_advertising.h +4 -0
  79. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  80. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  81. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +0 -4
  82. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  83. esphome/components/esp32_ble_server/__init__.py +28 -14
  84. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  85. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  86. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  87. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  88. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  89. esphome/components/esp32_ble_server/ble_server.h +38 -20
  90. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  91. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  92. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  93. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -8
  94. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  95. esphome/components/esp32_camera/__init__.py +1 -3
  96. esphome/components/esp32_can/esp32_can.cpp +22 -4
  97. esphome/components/esp32_can/esp32_can.h +3 -0
  98. esphome/components/esp32_hosted/__init__.py +2 -1
  99. esphome/components/esp32_improv/esp32_improv_component.cpp +135 -65
  100. esphome/components/esp32_improv/esp32_improv_component.h +7 -1
  101. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  102. esphome/components/esp8266/__init__.py +3 -3
  103. esphome/components/esphome/ota/__init__.py +21 -2
  104. esphome/components/esphome/ota/ota_esphome.cpp +456 -146
  105. esphome/components/esphome/ota/ota_esphome.h +49 -2
  106. esphome/components/ethernet/__init__.py +39 -22
  107. esphome/components/ethernet/ethernet_component.cpp +28 -5
  108. esphome/components/ethernet/ethernet_component.h +5 -1
  109. esphome/components/external_components/__init__.py +8 -6
  110. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  111. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  112. esphome/components/font/__init__.py +5 -5
  113. esphome/components/graph/graph.cpp +1 -1
  114. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  115. esphome/components/haier/hon_climate.cpp +2 -2
  116. esphome/components/haier/hon_climate.h +1 -1
  117. esphome/components/hdc1080/hdc1080.cpp +42 -34
  118. esphome/components/hdc1080/hdc1080.h +1 -3
  119. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  120. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  121. esphome/components/http_request/__init__.py +3 -3
  122. esphome/components/htu21d/htu21d.cpp +13 -18
  123. esphome/components/htu21d/htu21d.h +1 -1
  124. esphome/components/i2s_audio/__init__.py +1 -2
  125. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  126. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  127. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  128. esphome/components/improv_serial/improv_serial_component.h +6 -8
  129. esphome/components/json/json_util.cpp +42 -44
  130. esphome/components/json/json_util.h +57 -0
  131. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  132. esphome/components/key_collector/key_collector.h +4 -4
  133. esphome/components/libretiny/__init__.py +6 -6
  134. esphome/components/libretiny/preferences.cpp +23 -16
  135. esphome/components/light/light_call.cpp +98 -120
  136. esphome/components/light/light_call.h +17 -7
  137. esphome/components/lm75b/__init__.py +0 -0
  138. esphome/components/lm75b/lm75b.cpp +39 -0
  139. esphome/components/lm75b/lm75b.h +19 -0
  140. esphome/components/lm75b/sensor.py +34 -0
  141. esphome/components/lock/lock.h +12 -6
  142. esphome/components/logger/__init__.py +15 -27
  143. esphome/components/logger/logger.cpp +10 -20
  144. esphome/components/logger/logger.h +105 -62
  145. esphome/components/logger/logger_esp32.cpp +0 -48
  146. esphome/components/logger/logger_zephyr.cpp +2 -3
  147. esphome/components/logger/select/logger_level_select.cpp +6 -7
  148. esphome/components/logger/select/logger_level_select.h +7 -0
  149. esphome/components/ltr501/ltr501.cpp +7 -6
  150. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  151. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  152. esphome/components/max7219digit/max7219digit.cpp +1 -1
  153. esphome/components/mcp23xxx_base/mcp23xxx_base.h +3 -3
  154. esphome/components/mcp2515/mcp2515.cpp +31 -3
  155. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  156. esphome/components/md5/md5.cpp +0 -26
  157. esphome/components/md5/md5.h +10 -20
  158. esphome/components/mdns/__init__.py +93 -19
  159. esphome/components/mdns/mdns_component.cpp +57 -94
  160. esphome/components/mdns/mdns_component.h +35 -11
  161. esphome/components/mdns/mdns_esp32.cpp +7 -13
  162. esphome/components/mdns/mdns_esp8266.cpp +7 -7
  163. esphome/components/mdns/mdns_libretiny.cpp +3 -4
  164. esphome/components/mdns/mdns_rp2040.cpp +3 -4
  165. esphome/components/mipi/__init__.py +1 -5
  166. esphome/components/mipi_spi/display.py +24 -8
  167. esphome/components/mipi_spi/mipi_spi.h +3 -3
  168. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  169. esphome/components/mmc5603/mmc5603.cpp +3 -3
  170. esphome/components/modbus/modbus.cpp +27 -13
  171. esphome/components/modbus/modbus.h +5 -3
  172. esphome/components/modbus/modbus_definitions.h +86 -0
  173. esphome/components/modbus_controller/__init__.py +29 -1
  174. esphome/components/modbus_controller/const.py +4 -0
  175. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  176. esphome/components/modbus_controller/modbus_controller.h +18 -29
  177. esphome/components/mpr121/mpr121.cpp +41 -42
  178. esphome/components/mpr121/mpr121.h +0 -1
  179. esphome/components/nau7802/nau7802.cpp +2 -2
  180. esphome/components/network/__init__.py +7 -3
  181. esphome/components/nextion/display.py +4 -4
  182. esphome/components/nextion/nextion.cpp +8 -8
  183. esphome/components/number/__init__.py +2 -0
  184. esphome/components/number/number_call.cpp +23 -12
  185. esphome/components/number/number_call.h +5 -0
  186. esphome/components/online_image/bmp_image.cpp +2 -1
  187. esphome/components/online_image/jpeg_image.cpp +4 -2
  188. esphome/components/opentherm/opentherm.cpp +5 -5
  189. esphome/components/opentherm/opentherm.h +3 -3
  190. esphome/components/openthread/openthread.cpp +11 -10
  191. esphome/components/openthread/openthread.h +0 -1
  192. esphome/components/ota/ota_backend.h +1 -0
  193. esphome/components/packages/__init__.py +10 -8
  194. esphome/components/packet_transport/packet_transport.cpp +2 -0
  195. esphome/components/pid/pid_controller.cpp +1 -1
  196. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  197. esphome/components/psram/__init__.py +30 -28
  198. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  199. esphome/components/qmc5883l/qmc5883l.h +3 -0
  200. esphome/components/qmc5883l/sensor.py +31 -12
  201. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  202. esphome/components/remote_receiver/__init__.py +14 -2
  203. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  204. esphome/components/remote_receiver/remote_receiver.h +4 -0
  205. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  206. esphome/components/remote_transmitter/__init__.py +2 -2
  207. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  208. esphome/components/rp2040/__init__.py +11 -11
  209. esphome/components/rtttl/rtttl.cpp +2 -2
  210. esphome/components/scd30/sensor.py +1 -1
  211. esphome/components/script/__init__.py +1 -1
  212. esphome/components/script/script.h +7 -7
  213. esphome/components/select/select.cpp +5 -4
  214. esphome/components/select/select_call.cpp +1 -1
  215. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  216. esphome/components/sensor/__init__.py +2 -0
  217. esphome/components/sha256/__init__.py +22 -0
  218. esphome/components/sha256/sha256.cpp +116 -0
  219. esphome/components/sha256/sha256.h +60 -0
  220. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  221. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  222. esphome/components/spi/__init__.py +0 -3
  223. esphome/components/split_buffer/__init__.py +5 -0
  224. esphome/components/split_buffer/split_buffer.cpp +133 -0
  225. esphome/components/split_buffer/split_buffer.h +40 -0
  226. esphome/components/sps30/sps30.cpp +14 -10
  227. esphome/components/sps30/sps30.h +2 -0
  228. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  229. esphome/components/st7789v/st7789v.cpp +3 -2
  230. esphome/components/statsd/statsd.cpp +1 -1
  231. esphome/components/substitutions/__init__.py +3 -1
  232. esphome/components/substitutions/jinja.py +13 -3
  233. esphome/components/sx126x/__init__.py +16 -0
  234. esphome/components/sx126x/sx126x.cpp +15 -1
  235. esphome/components/sx126x/sx126x.h +9 -1
  236. esphome/components/sx126x/sx126x_reg.h +2 -0
  237. esphome/components/text_sensor/text_sensor.cpp +16 -0
  238. esphome/components/text_sensor/text_sensor.h +3 -10
  239. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  240. esphome/components/tuya/select/tuya_select.cpp +1 -1
  241. esphome/components/tuya/tuya.cpp +29 -4
  242. esphome/components/uart/__init__.py +37 -27
  243. esphome/components/uart/uart.h +6 -0
  244. esphome/components/uart/uart_component.cpp +8 -0
  245. esphome/components/uart/uart_component.h +28 -0
  246. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  247. esphome/components/uart/uart_component_esp_idf.h +5 -2
  248. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  249. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  250. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  251. esphome/components/usb_host/__init__.py +12 -2
  252. esphome/components/usb_host/usb_host.h +89 -14
  253. esphome/components/usb_host/usb_host_client.cpp +157 -22
  254. esphome/components/usb_host/usb_host_component.cpp +1 -1
  255. esphome/components/usb_uart/__init__.py +0 -1
  256. esphome/components/usb_uart/ch34x.cpp +4 -4
  257. esphome/components/usb_uart/cp210x.cpp +3 -3
  258. esphome/components/usb_uart/usb_uart.cpp +88 -32
  259. esphome/components/usb_uart/usb_uart.h +30 -6
  260. esphome/components/valve/valve.cpp +1 -0
  261. esphome/components/veml7700/veml7700.cpp +7 -6
  262. esphome/components/version/version_text_sensor.cpp +2 -1
  263. esphome/components/voice_assistant/voice_assistant.cpp +3 -2
  264. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  265. esphome/components/web_server/list_entities.cpp +3 -4
  266. esphome/components/web_server/list_entities.h +8 -10
  267. esphome/components/web_server/ota/__init__.py +1 -1
  268. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  269. esphome/components/web_server/web_server.cpp +509 -404
  270. esphome/components/web_server/web_server.h +5 -6
  271. esphome/components/web_server/web_server_v1.cpp +21 -19
  272. esphome/components/web_server_base/__init__.py +5 -2
  273. esphome/components/web_server_base/web_server_base.h +27 -7
  274. esphome/components/web_server_idf/__init__.py +1 -1
  275. esphome/components/web_server_idf/multipart.cpp +2 -2
  276. esphome/components/web_server_idf/multipart.h +2 -2
  277. esphome/components/web_server_idf/utils.cpp +2 -2
  278. esphome/components/web_server_idf/utils.h +2 -2
  279. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  280. esphome/components/web_server_idf/web_server_idf.h +12 -10
  281. esphome/components/wifi/__init__.py +13 -11
  282. esphome/components/wifi/wifi_component.cpp +74 -56
  283. esphome/components/wifi/wifi_component.h +4 -4
  284. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  285. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  286. esphome/components/wireguard/__init__.py +1 -1
  287. esphome/components/wts01/__init__.py +0 -0
  288. esphome/components/wts01/sensor.py +41 -0
  289. esphome/components/wts01/wts01.cpp +91 -0
  290. esphome/components/wts01/wts01.h +27 -0
  291. esphome/components/zephyr/__init__.py +5 -5
  292. esphome/components/zwave_proxy/__init__.py +43 -0
  293. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  294. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  295. esphome/config.py +79 -24
  296. esphome/config_validation.py +13 -15
  297. esphome/const.py +9 -2
  298. esphome/core/__init__.py +33 -22
  299. esphome/core/component.cpp +28 -18
  300. esphome/core/component_iterator.h +2 -1
  301. esphome/core/config.py +15 -15
  302. esphome/core/defines.h +21 -0
  303. esphome/core/entity_helpers.py +9 -6
  304. esphome/core/hash_base.h +56 -0
  305. esphome/core/helpers.cpp +19 -3
  306. esphome/core/helpers.h +26 -0
  307. esphome/core/scheduler.cpp +5 -21
  308. esphome/core/scheduler.h +19 -8
  309. esphome/core/string_ref.h +1 -1
  310. esphome/core/time.cpp +5 -5
  311. esphome/cpp_generator.py +4 -29
  312. esphome/dashboard/const.py +21 -4
  313. esphome/dashboard/core.py +10 -8
  314. esphome/dashboard/dns.py +15 -0
  315. esphome/dashboard/entries.py +15 -21
  316. esphome/dashboard/models.py +76 -0
  317. esphome/dashboard/settings.py +7 -7
  318. esphome/dashboard/status/mdns.py +46 -2
  319. esphome/dashboard/web_server.py +367 -93
  320. esphome/espota2.py +112 -32
  321. esphome/external_files.py +6 -7
  322. esphome/git.py +8 -0
  323. esphome/helpers.py +124 -77
  324. esphome/loader.py +8 -9
  325. esphome/pins.py +2 -2
  326. esphome/platformio_api.py +56 -18
  327. esphome/storage_json.py +26 -21
  328. esphome/types.py +30 -2
  329. esphome/util.py +32 -16
  330. esphome/vscode.py +8 -8
  331. esphome/wizard.py +10 -10
  332. esphome/writer.py +50 -15
  333. esphome/yaml_util.py +37 -31
  334. esphome/zeroconf.py +12 -3
  335. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/METADATA +12 -12
  336. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/RECORD +340 -320
  337. esphome/components/event_emitter/__init__.py +0 -5
  338. esphome/components/event_emitter/event_emitter.cpp +0 -14
  339. esphome/components/event_emitter/event_emitter.h +0 -63
  340. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  341. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  342. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  343. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  344. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  345. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  346. esphome/core/string_ref.cpp +0 -12
  347. esphome/dashboard/util/file.py +0 -63
  348. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/WHEEL +0 -0
  349. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/entry_points.txt +0 -0
  350. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/licenses/LICENSE +0 -0
  351. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/top_level.txt +0 -0
@@ -36,9 +36,8 @@ from esphome.const import (
36
36
  __version__,
37
37
  )
38
38
  from esphome.core import CORE, HexInt, TimePeriod
39
- from esphome.cpp_generator import RawExpression
40
39
  import esphome.final_validate as fv
41
- from esphome.helpers import copy_file_if_changed, mkdir_p, write_file_if_changed
40
+ from esphome.helpers import copy_file_if_changed, write_file_if_changed
42
41
  from esphome.types import ConfigType
43
42
  from esphome.writer import clean_cmake_cache
44
43
 
@@ -157,8 +156,6 @@ def set_core_data(config):
157
156
  conf = config[CONF_FRAMEWORK]
158
157
  if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF:
159
158
  CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "esp-idf"
160
- CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {}
161
- CORE.data[KEY_ESP32][KEY_COMPONENTS] = {}
162
159
  elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
163
160
  CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino"
164
161
  if variant not in ARDUINO_ALLOWED_VARIANTS:
@@ -166,6 +163,8 @@ def set_core_data(config):
166
163
  f"ESPHome does not support using the Arduino framework for the {variant}. Please use the ESP-IDF framework instead.",
167
164
  path=[CONF_FRAMEWORK, CONF_TYPE],
168
165
  )
166
+ CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {}
167
+ CORE.data[KEY_ESP32][KEY_COMPONENTS] = {}
169
168
  CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse(
170
169
  config[CONF_FRAMEWORK][CONF_VERSION]
171
170
  )
@@ -236,8 +235,6 @@ SdkconfigValueType = bool | int | HexInt | str | RawSdkconfigValue
236
235
 
237
236
  def add_idf_sdkconfig_option(name: str, value: SdkconfigValueType):
238
237
  """Set an esp-idf sdkconfig value."""
239
- if not CORE.using_esp_idf:
240
- raise ValueError("Not an esp-idf project")
241
238
  CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS][name] = value
242
239
 
243
240
 
@@ -252,8 +249,6 @@ def add_idf_component(
252
249
  submodules: list[str] | None = None,
253
250
  ):
254
251
  """Add an esp-idf component to the project."""
255
- if not CORE.using_esp_idf:
256
- raise ValueError("Not an esp-idf project")
257
252
  if not repo and not ref and not path:
258
253
  raise ValueError("Requires at least one of repo, ref or path")
259
254
  if refresh or submodules or components:
@@ -277,14 +272,14 @@ def add_idf_component(
277
272
  }
278
273
 
279
274
 
280
- def add_extra_script(stage: str, filename: str, path: str):
275
+ def add_extra_script(stage: str, filename: str, path: Path):
281
276
  """Add an extra script to the project."""
282
277
  key = f"{stage}:{filename}"
283
278
  if add_extra_build_file(filename, path):
284
279
  cg.add_platformio_option("extra_scripts", [key])
285
280
 
286
281
 
287
- def add_extra_build_file(filename: str, path: str) -> bool:
282
+ def add_extra_build_file(filename: str, path: Path) -> bool:
288
283
  """Add an extra build file to the project."""
289
284
  if filename not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]:
290
285
  CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES][filename] = {
@@ -301,14 +296,9 @@ def _format_framework_arduino_version(ver: cv.Version) -> str:
301
296
  return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{str(ver)}/esp32-{str(ver)}.zip"
302
297
 
303
298
 
304
- def _format_framework_espidf_version(
305
- ver: cv.Version, release: str, for_platformio: bool
306
- ) -> str:
307
- # format the given arduino (https://github.com/espressif/esp-idf/releases) version to
299
+ def _format_framework_espidf_version(ver: cv.Version, release: str) -> str:
300
+ # format the given espidf (https://github.com/pioarduino/esp-idf/releases) version to
308
301
  # a PIO platformio/framework-espidf value
309
- # List of package versions: https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
310
- if for_platformio:
311
- return f"platformio/framework-espidf@~3.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
312
302
  if release:
313
303
  return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{str(ver)}.{release}/esp-idf-v{str(ver)}.zip"
314
304
  return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{str(ver)}/esp-idf-v{str(ver)}.zip"
@@ -322,154 +312,115 @@ def _format_framework_espidf_version(
322
312
 
323
313
  # The default/recommended arduino framework version
324
314
  # - https://github.com/espressif/arduino-esp32/releases
325
- RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 2, 1)
326
- # The platform-espressif32 version to use for arduino frameworks
327
- # - https://github.com/pioarduino/platform-espressif32/releases
328
- ARDUINO_PLATFORM_VERSION = cv.Version(54, 3, 21, "2")
315
+ ARDUINO_FRAMEWORK_VERSION_LOOKUP = {
316
+ "recommended": cv.Version(3, 2, 1),
317
+ "latest": cv.Version(3, 3, 2),
318
+ "dev": cv.Version(3, 3, 2),
319
+ }
320
+ ARDUINO_PLATFORM_VERSION_LOOKUP = {
321
+ cv.Version(3, 3, 2): cv.Version(55, 3, 31, "1"),
322
+ cv.Version(3, 3, 1): cv.Version(55, 3, 31, "1"),
323
+ cv.Version(3, 3, 0): cv.Version(55, 3, 30, "2"),
324
+ cv.Version(3, 2, 1): cv.Version(54, 3, 21, "2"),
325
+ cv.Version(3, 2, 0): cv.Version(54, 3, 20),
326
+ cv.Version(3, 1, 3): cv.Version(53, 3, 13),
327
+ cv.Version(3, 1, 2): cv.Version(53, 3, 12),
328
+ cv.Version(3, 1, 1): cv.Version(53, 3, 11),
329
+ cv.Version(3, 1, 0): cv.Version(53, 3, 10),
330
+ }
329
331
 
330
332
  # The default/recommended esp-idf framework version
331
333
  # - https://github.com/espressif/esp-idf/releases
332
- # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
333
- RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(5, 4, 2)
334
- # The platformio/espressif32 version to use for esp-idf frameworks
335
- # - https://github.com/platformio/platform-espressif32/releases
336
- # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
337
- ESP_IDF_PLATFORM_VERSION = cv.Version(54, 3, 21, "2")
338
-
339
- # List based on https://registry.platformio.org/tools/platformio/framework-espidf/versions
340
- SUPPORTED_PLATFORMIO_ESP_IDF_5X = [
341
- cv.Version(5, 3, 1),
342
- cv.Version(5, 3, 0),
343
- cv.Version(5, 2, 2),
344
- cv.Version(5, 2, 1),
345
- cv.Version(5, 1, 2),
346
- cv.Version(5, 1, 1),
347
- cv.Version(5, 1, 0),
348
- cv.Version(5, 0, 2),
349
- cv.Version(5, 0, 1),
350
- cv.Version(5, 0, 0),
351
- ]
334
+ ESP_IDF_FRAMEWORK_VERSION_LOOKUP = {
335
+ "recommended": cv.Version(5, 4, 2),
336
+ "latest": cv.Version(5, 5, 1),
337
+ "dev": cv.Version(5, 5, 1),
338
+ }
339
+ ESP_IDF_PLATFORM_VERSION_LOOKUP = {
340
+ cv.Version(5, 5, 1): cv.Version(55, 3, 31, "1"),
341
+ cv.Version(5, 5, 0): cv.Version(55, 3, 31, "1"),
342
+ cv.Version(5, 4, 2): cv.Version(54, 3, 21, "2"),
343
+ cv.Version(5, 4, 1): cv.Version(54, 3, 21, "2"),
344
+ cv.Version(5, 4, 0): cv.Version(54, 3, 21, "2"),
345
+ cv.Version(5, 3, 2): cv.Version(53, 3, 13),
346
+ cv.Version(5, 3, 1): cv.Version(53, 3, 13),
347
+ cv.Version(5, 3, 0): cv.Version(53, 3, 13),
348
+ cv.Version(5, 1, 6): cv.Version(51, 3, 7),
349
+ cv.Version(5, 1, 5): cv.Version(51, 3, 7),
350
+ }
352
351
 
353
- # pioarduino versions that don't require a release number
354
- # List based on https://github.com/pioarduino/esp-idf/releases
355
- SUPPORTED_PIOARDUINO_ESP_IDF_5X = [
356
- cv.Version(5, 5, 0),
357
- cv.Version(5, 4, 2),
358
- cv.Version(5, 4, 1),
359
- cv.Version(5, 4, 0),
360
- cv.Version(5, 3, 3),
361
- cv.Version(5, 3, 2),
362
- cv.Version(5, 3, 1),
363
- cv.Version(5, 3, 0),
364
- cv.Version(5, 1, 5),
365
- cv.Version(5, 1, 6),
366
- ]
352
+ # The platform-espressif32 version
353
+ # - https://github.com/pioarduino/platform-espressif32/releases
354
+ PLATFORM_VERSION_LOOKUP = {
355
+ "recommended": cv.Version(54, 3, 21, "2"),
356
+ "latest": cv.Version(55, 3, 31, "1"),
357
+ "dev": cv.Version(55, 3, 31, "1"),
358
+ }
367
359
 
368
360
 
369
- def _arduino_check_versions(value):
361
+ def _check_versions(value):
370
362
  value = value.copy()
371
- lookups = {
372
- "dev": (cv.Version(3, 2, 1), "https://github.com/espressif/arduino-esp32.git"),
373
- "latest": (cv.Version(3, 2, 1), None),
374
- "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
375
- }
376
-
377
- if value[CONF_VERSION] in lookups:
378
- if CONF_SOURCE in value:
363
+
364
+ if value[CONF_VERSION] in PLATFORM_VERSION_LOOKUP:
365
+ if CONF_SOURCE in value or CONF_PLATFORM_VERSION in value:
379
366
  raise cv.Invalid(
380
- "Framework version needs to be explicitly specified when custom source is used."
367
+ "Version needs to be explicitly set when a custom source or platform_version is used."
381
368
  )
382
369
 
383
- version, source = lookups[value[CONF_VERSION]]
370
+ platform_lookup = PLATFORM_VERSION_LOOKUP[value[CONF_VERSION]]
371
+ value[CONF_PLATFORM_VERSION] = _parse_platform_version(str(platform_lookup))
372
+
373
+ if value[CONF_TYPE] == FRAMEWORK_ARDUINO:
374
+ version = ARDUINO_FRAMEWORK_VERSION_LOOKUP[value[CONF_VERSION]]
375
+ else:
376
+ version = ESP_IDF_FRAMEWORK_VERSION_LOOKUP[value[CONF_VERSION]]
384
377
  else:
385
378
  version = cv.Version.parse(cv.version_number(value[CONF_VERSION]))
386
- source = value.get(CONF_SOURCE, None)
387
379
 
388
380
  value[CONF_VERSION] = str(version)
389
- value[CONF_SOURCE] = source or _format_framework_arduino_version(version)
390
-
391
- value[CONF_PLATFORM_VERSION] = value.get(
392
- CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
393
- )
394
-
395
- if value[CONF_SOURCE].startswith("http"):
396
- # prefix is necessary or platformio will complain with a cryptic error
397
- value[CONF_SOURCE] = f"framework-arduinoespressif32@{value[CONF_SOURCE]}"
398
381
 
399
- if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION:
400
- _LOGGER.warning(
401
- "The selected Arduino framework version is not the recommended one. "
402
- "If there are connectivity or build issues please remove the manual version."
382
+ if value[CONF_TYPE] == FRAMEWORK_ARDUINO:
383
+ if version < cv.Version(3, 0, 0):
384
+ raise cv.Invalid("Only Arduino 3.0+ is supported.")
385
+ recommended_version = ARDUINO_FRAMEWORK_VERSION_LOOKUP["recommended"]
386
+ platform_lookup = ARDUINO_PLATFORM_VERSION_LOOKUP.get(version)
387
+ value[CONF_SOURCE] = value.get(
388
+ CONF_SOURCE, _format_framework_arduino_version(version)
403
389
  )
404
-
405
- return value
406
-
407
-
408
- def _esp_idf_check_versions(value):
409
- value = value.copy()
410
- lookups = {
411
- "dev": (cv.Version(5, 4, 2), "https://github.com/espressif/esp-idf.git"),
412
- "latest": (cv.Version(5, 2, 2), None),
413
- "recommended": (RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION, None),
414
- }
415
-
416
- if value[CONF_VERSION] in lookups:
417
- if CONF_SOURCE in value:
418
- raise cv.Invalid(
419
- "Framework version needs to be explicitly specified when custom source is used."
390
+ if value[CONF_SOURCE].startswith("http"):
391
+ value[CONF_SOURCE] = (
392
+ f"pioarduino/framework-arduinoespressif32@{value[CONF_SOURCE]}"
420
393
  )
421
-
422
- version, source = lookups[value[CONF_VERSION]]
423
394
  else:
424
- version = cv.Version.parse(cv.version_number(value[CONF_VERSION]))
425
- source = value.get(CONF_SOURCE, None)
426
-
427
- if version < cv.Version(5, 0, 0):
428
- raise cv.Invalid("Only ESP-IDF 5.0+ is supported.")
429
-
430
- # flag this for later *before* we set value[CONF_PLATFORM_VERSION] below
431
- has_platform_ver = CONF_PLATFORM_VERSION in value
432
-
433
- value[CONF_PLATFORM_VERSION] = value.get(
434
- CONF_PLATFORM_VERSION, _parse_platform_version(str(ESP_IDF_PLATFORM_VERSION))
435
- )
436
-
437
- if (
438
- is_platformio := _platform_is_platformio(value[CONF_PLATFORM_VERSION])
439
- ) and version not in SUPPORTED_PLATFORMIO_ESP_IDF_5X:
440
- raise cv.Invalid(
441
- f"ESP-IDF {str(version)} not supported by platformio/espressif32"
395
+ if version < cv.Version(5, 0, 0):
396
+ raise cv.Invalid("Only ESP-IDF 5.0+ is supported.")
397
+ recommended_version = ESP_IDF_FRAMEWORK_VERSION_LOOKUP["recommended"]
398
+ platform_lookup = ESP_IDF_PLATFORM_VERSION_LOOKUP.get(version)
399
+ value[CONF_SOURCE] = value.get(
400
+ CONF_SOURCE,
401
+ _format_framework_espidf_version(version, value.get(CONF_RELEASE, None)),
442
402
  )
403
+ if value[CONF_SOURCE].startswith("http"):
404
+ value[CONF_SOURCE] = f"pioarduino/framework-espidf@{value[CONF_SOURCE]}"
443
405
 
444
- if (
445
- version in SUPPORTED_PLATFORMIO_ESP_IDF_5X
446
- and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X
447
- ) and not has_platform_ver:
448
- raise cv.Invalid(
449
- f"ESP-IDF {value[CONF_VERSION]} may be supported by platformio/espressif32; please specify '{CONF_PLATFORM_VERSION}'"
450
- )
406
+ if CONF_PLATFORM_VERSION not in value:
407
+ if platform_lookup is None:
408
+ raise cv.Invalid(
409
+ "Framework version not recognized; please specify platform_version"
410
+ )
411
+ value[CONF_PLATFORM_VERSION] = _parse_platform_version(str(platform_lookup))
451
412
 
452
- if (
453
- not is_platformio
454
- and CONF_RELEASE not in value
455
- and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X
456
- ):
457
- raise cv.Invalid(
458
- f"ESP-IDF {value[CONF_VERSION]} is not available with pioarduino; you may need to specify '{CONF_RELEASE}'"
413
+ if version != recommended_version:
414
+ _LOGGER.warning(
415
+ "The selected framework version is not the recommended one. "
416
+ "If there are connectivity or build issues please remove the manual version."
459
417
  )
460
418
 
461
- value[CONF_VERSION] = str(version)
462
- value[CONF_SOURCE] = source or _format_framework_espidf_version(
463
- version, value.get(CONF_RELEASE, None), is_platformio
464
- )
465
-
466
- if value[CONF_SOURCE].startswith("http"):
467
- # prefix is necessary or platformio will complain with a cryptic error
468
- value[CONF_SOURCE] = f"framework-espidf@{value[CONF_SOURCE]}"
469
-
470
- if version != RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION:
419
+ if value[CONF_PLATFORM_VERSION] != _parse_platform_version(
420
+ str(PLATFORM_VERSION_LOOKUP["recommended"])
421
+ ):
471
422
  _LOGGER.warning(
472
- "The selected ESP-IDF framework version is not the recommended one. "
423
+ "The selected platform version is not the recommended one. "
473
424
  "If there are connectivity or build issues please remove the manual version."
474
425
  )
475
426
 
@@ -479,26 +430,14 @@ def _esp_idf_check_versions(value):
479
430
  def _parse_platform_version(value):
480
431
  try:
481
432
  ver = cv.Version.parse(cv.version_number(value))
482
- if ver.major >= 50: # a pioarduino version
483
- release = f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}"
484
- if ver.extra:
485
- release += f"-{ver.extra}"
486
- return f"https://github.com/pioarduino/platform-espressif32/releases/download/{release}/platform-espressif32.zip"
487
- # if platform version is a valid version constraint, prefix the default package
488
- cv.platformio_version_constraint(value)
489
- return f"platformio/espressif32@{value}"
433
+ release = f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}"
434
+ if ver.extra:
435
+ release += f"-{ver.extra}"
436
+ return f"https://github.com/pioarduino/platform-espressif32/releases/download/{release}/platform-espressif32.zip"
490
437
  except cv.Invalid:
491
438
  return value
492
439
 
493
440
 
494
- def _platform_is_platformio(value):
495
- try:
496
- ver = cv.Version.parse(cv.version_number(value))
497
- return ver.major < 50
498
- except cv.Invalid:
499
- return "platformio" in value
500
-
501
-
502
441
  def _detect_variant(value):
503
442
  board = value.get(CONF_BOARD)
504
443
  variant = value.get(CONF_VARIANT)
@@ -588,24 +527,6 @@ def final_validate(config):
588
527
  return config
589
528
 
590
529
 
591
- ARDUINO_FRAMEWORK_SCHEMA = cv.All(
592
- cv.Schema(
593
- {
594
- cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict,
595
- cv.Optional(CONF_SOURCE): cv.string_strict,
596
- cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version,
597
- cv.Optional(CONF_ADVANCED, default={}): cv.Schema(
598
- {
599
- cv.Optional(
600
- CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False
601
- ): cv.boolean,
602
- }
603
- ),
604
- }
605
- ),
606
- _arduino_check_versions,
607
- )
608
-
609
530
  CONF_SDKCONFIG_OPTIONS = "sdkconfig_options"
610
531
  CONF_ENABLE_LWIP_DHCP_SERVER = "enable_lwip_dhcp_server"
611
532
  CONF_ENABLE_LWIP_MDNS_QUERIES = "enable_lwip_mdns_queries"
@@ -624,9 +545,14 @@ def _validate_idf_component(config: ConfigType) -> ConfigType:
624
545
  return config
625
546
 
626
547
 
627
- ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
548
+ FRAMEWORK_ESP_IDF = "esp-idf"
549
+ FRAMEWORK_ARDUINO = "arduino"
550
+ FRAMEWORK_SCHEMA = cv.All(
628
551
  cv.Schema(
629
552
  {
553
+ cv.Optional(CONF_TYPE, default=FRAMEWORK_ARDUINO): cv.one_of(
554
+ FRAMEWORK_ESP_IDF, FRAMEWORK_ARDUINO
555
+ ),
630
556
  cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict,
631
557
  cv.Optional(CONF_RELEASE): cv.string_strict,
632
558
  cv.Optional(CONF_SOURCE): cv.string_strict,
@@ -690,7 +616,7 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
690
616
  ),
691
617
  }
692
618
  ),
693
- _esp_idf_check_versions,
619
+ _check_versions,
694
620
  )
695
621
 
696
622
 
@@ -720,6 +646,7 @@ def _show_framework_migration_message(name: str, variant: str) -> None:
720
646
  + "Why change? ESP-IDF offers:\n"
721
647
  + color(AnsiFore.GREEN, " ✨ Up to 40% smaller binaries\n")
722
648
  + color(AnsiFore.GREEN, " 🚀 Better performance and optimization\n")
649
+ + color(AnsiFore.GREEN, " ⚡ 2-3x faster compile times\n")
723
650
  + color(AnsiFore.GREEN, " 📦 Custom-built firmware for your exact needs\n")
724
651
  + color(
725
652
  AnsiFore.GREEN,
@@ -727,7 +654,6 @@ def _show_framework_migration_message(name: str, variant: str) -> None:
727
654
  )
728
655
  + "\n"
729
656
  + "Trade-offs:\n"
730
- + color(AnsiFore.YELLOW, " ⏱️ Compile times are ~25% longer\n")
731
657
  + color(AnsiFore.YELLOW, " 🔄 Some components need migration\n")
732
658
  + "\n"
733
659
  + "What should I do?\n"
@@ -757,32 +683,18 @@ def _set_default_framework(config):
757
683
  config = config.copy()
758
684
 
759
685
  variant = config[CONF_VARIANT]
686
+ config[CONF_FRAMEWORK] = FRAMEWORK_SCHEMA({})
760
687
  if variant in ARDUINO_ALLOWED_VARIANTS:
761
- config[CONF_FRAMEWORK] = ARDUINO_FRAMEWORK_SCHEMA({})
762
688
  config[CONF_FRAMEWORK][CONF_TYPE] = FRAMEWORK_ARDUINO
763
- # Show the migration message
764
689
  _show_framework_migration_message(
765
690
  config.get(CONF_NAME, "This device"), variant
766
691
  )
767
692
  else:
768
- config[CONF_FRAMEWORK] = ESP_IDF_FRAMEWORK_SCHEMA({})
769
693
  config[CONF_FRAMEWORK][CONF_TYPE] = FRAMEWORK_ESP_IDF
770
694
 
771
695
  return config
772
696
 
773
697
 
774
- FRAMEWORK_ESP_IDF = "esp-idf"
775
- FRAMEWORK_ARDUINO = "arduino"
776
- FRAMEWORK_SCHEMA = cv.typed_schema(
777
- {
778
- FRAMEWORK_ESP_IDF: ESP_IDF_FRAMEWORK_SCHEMA,
779
- FRAMEWORK_ARDUINO: ARDUINO_FRAMEWORK_SCHEMA,
780
- },
781
- lower=True,
782
- space="-",
783
- )
784
-
785
-
786
698
  FLASH_SIZES = [
787
699
  "2MB",
788
700
  "4MB",
@@ -837,6 +749,8 @@ async def to_code(config):
837
749
 
838
750
  conf = config[CONF_FRAMEWORK]
839
751
  cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION])
752
+ if CONF_SOURCE in conf:
753
+ cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
840
754
 
841
755
  if conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_CUSTOM_MAC]:
842
756
  cg.add_define("USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC")
@@ -847,142 +761,146 @@ async def to_code(config):
847
761
  add_extra_script(
848
762
  "post",
849
763
  "post_build.py",
850
- os.path.join(os.path.dirname(__file__), "post_build.py.script"),
764
+ Path(__file__).parent / "post_build.py.script",
851
765
  )
852
766
 
853
- freq = config[CONF_CPU_FREQUENCY][:-3]
854
767
  if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF:
855
768
  cg.add_platformio_option("framework", "espidf")
856
769
  cg.add_build_flag("-DUSE_ESP_IDF")
857
770
  cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF")
858
- cg.add_build_flag("-Wno-nonnull-compare")
859
-
860
- cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
861
-
862
- add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True)
863
- add_idf_sdkconfig_option(
864
- f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True
771
+ else:
772
+ cg.add_platformio_option("framework", "arduino, espidf")
773
+ cg.add_build_flag("-DUSE_ARDUINO")
774
+ cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO")
775
+ cg.add_platformio_option(
776
+ "board_build.embed_txtfiles",
777
+ [
778
+ "managed_components/espressif__esp_insights/server_certs/https_server.crt",
779
+ "managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt",
780
+ "managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt",
781
+ "managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt",
782
+ ],
865
783
  )
866
- add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False)
867
- add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True)
868
- add_idf_sdkconfig_option(
869
- "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv"
784
+ cg.add_define(
785
+ "USE_ARDUINO_VERSION_CODE",
786
+ cg.RawExpression(
787
+ f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})"
788
+ ),
870
789
  )
790
+ add_idf_sdkconfig_option("CONFIG_AUTOSTART_ARDUINO", True)
791
+ add_idf_sdkconfig_option("CONFIG_MBEDTLS_PSK_MODES", True)
792
+ add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True)
871
793
 
872
- # Increase freertos tick speed from 100Hz to 1kHz so that delay() resolution is 1ms
873
- add_idf_sdkconfig_option("CONFIG_FREERTOS_HZ", 1000)
874
-
875
- # Setup watchdog
876
- add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT", True)
877
- add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_PANIC", True)
878
- add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False)
879
- add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False)
880
-
881
- # Disable dynamic log level control to save memory
882
- add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False)
883
-
884
- # Set default CPU frequency
885
- add_idf_sdkconfig_option(f"CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_{freq}", True)
886
-
887
- # Apply LWIP optimization settings
888
- advanced = conf[CONF_ADVANCED]
889
- # DHCP server: only disable if explicitly set to false
890
- # WiFi component handles its own optimization when AP mode is not used
891
- if (
892
- CONF_ENABLE_LWIP_DHCP_SERVER in advanced
893
- and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER]
894
- ):
895
- add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
896
- if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True):
897
- add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False)
898
- if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False):
899
- add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0)
900
- if advanced.get(CONF_EXECUTE_FROM_PSRAM, False):
901
- add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True)
902
- add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True)
903
-
904
- # Apply LWIP core locking for better socket performance
905
- # This is already enabled by default in Arduino framework, where it provides
906
- # significant performance benefits. Our benchmarks show socket operations are
907
- # 24-200% faster with core locking enabled:
908
- # - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default)
909
- # - Up to 200% slower under load when all operations queue through tcpip_thread
910
- # Enabling this makes ESP-IDF socket performance match Arduino framework.
911
- if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True):
912
- add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True)
913
- if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True):
914
- add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True)
915
-
916
- cg.add_platformio_option("board_build.partitions", "partitions.csv")
917
- if CONF_PARTITIONS in config:
918
- add_extra_build_file(
919
- "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS])
920
- )
794
+ cg.add_build_flag("-Wno-nonnull-compare")
921
795
 
922
- if assertion_level := advanced.get(CONF_ASSERTION_LEVEL):
923
- for key, flag in ASSERTION_LEVELS.items():
924
- add_idf_sdkconfig_option(flag, assertion_level == key)
796
+ add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True)
797
+ add_idf_sdkconfig_option(
798
+ f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True
799
+ )
800
+ add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False)
801
+ add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True)
802
+ add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv")
925
803
 
926
- add_idf_sdkconfig_option("CONFIG_COMPILER_OPTIMIZATION_DEFAULT", False)
927
- compiler_optimization = advanced.get(CONF_COMPILER_OPTIMIZATION)
928
- for key, flag in COMPILER_OPTIMIZATIONS.items():
929
- add_idf_sdkconfig_option(flag, compiler_optimization == key)
804
+ # Increase freertos tick speed from 100Hz to 1kHz so that delay() resolution is 1ms
805
+ add_idf_sdkconfig_option("CONFIG_FREERTOS_HZ", 1000)
930
806
 
931
- add_idf_sdkconfig_option(
932
- "CONFIG_LWIP_ESP_LWIP_ASSERT",
933
- conf[CONF_ADVANCED][CONF_ENABLE_LWIP_ASSERT],
934
- )
807
+ # Setup watchdog
808
+ add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT", True)
809
+ add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_PANIC", True)
810
+ add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False)
811
+ add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False)
935
812
 
936
- if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC):
937
- add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True)
938
- add_idf_sdkconfig_option(
939
- "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False
940
- )
941
- if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES):
942
- _LOGGER.warning(
943
- "Using experimental features in ESP-IDF may result in unexpected failures."
944
- )
945
- add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True)
813
+ # Disable dynamic log level control to save memory
814
+ add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False)
946
815
 
947
- cg.add_define(
948
- "USE_ESP_IDF_VERSION_CODE",
949
- cg.RawExpression(
950
- f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})"
951
- ),
816
+ # Set default CPU frequency
817
+ add_idf_sdkconfig_option(
818
+ f"CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_{config[CONF_CPU_FREQUENCY][:-3]}", True
819
+ )
820
+
821
+ # Apply LWIP optimization settings
822
+ advanced = conf[CONF_ADVANCED]
823
+ # DHCP server: only disable if explicitly set to false
824
+ # WiFi component handles its own optimization when AP mode is not used
825
+ # When using Arduino with Ethernet, DHCP server functions must be available
826
+ # for the Network library to compile, even if not actively used
827
+ if (
828
+ CONF_ENABLE_LWIP_DHCP_SERVER in advanced
829
+ and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER]
830
+ and not (
831
+ conf[CONF_TYPE] == FRAMEWORK_ARDUINO
832
+ and "ethernet" in CORE.loaded_integrations
952
833
  )
834
+ ):
835
+ add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
836
+ if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True):
837
+ add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False)
838
+ if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False):
839
+ add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0)
840
+ if advanced.get(CONF_EXECUTE_FROM_PSRAM, False):
841
+ add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True)
842
+ add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True)
843
+
844
+ # Apply LWIP core locking for better socket performance
845
+ # This is already enabled by default in Arduino framework, where it provides
846
+ # significant performance benefits. Our benchmarks show socket operations are
847
+ # 24-200% faster with core locking enabled:
848
+ # - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default)
849
+ # - Up to 200% slower under load when all operations queue through tcpip_thread
850
+ # Enabling this makes ESP-IDF socket performance match Arduino framework.
851
+ if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True):
852
+ add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True)
853
+ if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True):
854
+ add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True)
855
+
856
+ cg.add_platformio_option("board_build.partitions", "partitions.csv")
857
+ if CONF_PARTITIONS in config:
858
+ add_extra_build_file(
859
+ "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS])
860
+ )
861
+
862
+ if assertion_level := advanced.get(CONF_ASSERTION_LEVEL):
863
+ for key, flag in ASSERTION_LEVELS.items():
864
+ add_idf_sdkconfig_option(flag, assertion_level == key)
865
+
866
+ add_idf_sdkconfig_option("CONFIG_COMPILER_OPTIMIZATION_DEFAULT", False)
867
+ compiler_optimization = advanced.get(CONF_COMPILER_OPTIMIZATION)
868
+ for key, flag in COMPILER_OPTIMIZATIONS.items():
869
+ add_idf_sdkconfig_option(flag, compiler_optimization == key)
870
+
871
+ add_idf_sdkconfig_option(
872
+ "CONFIG_LWIP_ESP_LWIP_ASSERT",
873
+ conf[CONF_ADVANCED][CONF_ENABLE_LWIP_ASSERT],
874
+ )
953
875
 
954
- add_idf_sdkconfig_option(
955
- f"CONFIG_LOG_DEFAULT_LEVEL_{conf[CONF_LOG_LEVEL]}", True
876
+ if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC):
877
+ add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True)
878
+ add_idf_sdkconfig_option("CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False)
879
+ if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES):
880
+ _LOGGER.warning(
881
+ "Using experimental features in ESP-IDF may result in unexpected failures."
956
882
  )
883
+ add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True)
957
884
 
958
- for name, value in conf[CONF_SDKCONFIG_OPTIONS].items():
959
- add_idf_sdkconfig_option(name, RawSdkconfigValue(value))
885
+ cg.add_define(
886
+ "USE_ESP_IDF_VERSION_CODE",
887
+ cg.RawExpression(
888
+ f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})"
889
+ ),
890
+ )
960
891
 
961
- for component in conf[CONF_COMPONENTS]:
962
- add_idf_component(
963
- name=component[CONF_NAME],
964
- repo=component.get(CONF_SOURCE),
965
- ref=component.get(CONF_REF),
966
- path=component.get(CONF_PATH),
967
- )
968
- elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
969
- cg.add_platformio_option("framework", "arduino")
970
- cg.add_build_flag("-DUSE_ARDUINO")
971
- cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO")
972
- cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
892
+ add_idf_sdkconfig_option(f"CONFIG_LOG_DEFAULT_LEVEL_{conf[CONF_LOG_LEVEL]}", True)
973
893
 
974
- if CONF_PARTITIONS in config:
975
- cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
976
- else:
977
- cg.add_platformio_option("board_build.partitions", "partitions.csv")
894
+ for name, value in conf[CONF_SDKCONFIG_OPTIONS].items():
895
+ add_idf_sdkconfig_option(name, RawSdkconfigValue(value))
978
896
 
979
- cg.add_define(
980
- "USE_ARDUINO_VERSION_CODE",
981
- cg.RawExpression(
982
- f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})"
983
- ),
897
+ for component in conf[CONF_COMPONENTS]:
898
+ add_idf_component(
899
+ name=component[CONF_NAME],
900
+ repo=component.get(CONF_SOURCE),
901
+ ref=component.get(CONF_REF),
902
+ path=component.get(CONF_PATH),
984
903
  )
985
- cg.add(RawExpression(f"setCpuFrequencyMhz({freq})"))
986
904
 
987
905
 
988
906
  APP_PARTITION_SIZES = {
@@ -1056,13 +974,14 @@ def _write_sdkconfig():
1056
974
  )
1057
975
  + "\n"
1058
976
  )
977
+
1059
978
  if write_file_if_changed(internal_path, contents):
1060
979
  # internal changed, update real one
1061
980
  write_file_if_changed(sdk_path, contents)
1062
981
 
1063
982
 
1064
983
  def _write_idf_component_yml():
1065
- yml_path = Path(CORE.relative_build_path("src/idf_component.yml"))
984
+ yml_path = CORE.relative_build_path("src/idf_component.yml")
1066
985
  if CORE.data[KEY_ESP32][KEY_COMPONENTS]:
1067
986
  components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS]
1068
987
  dependencies = {}
@@ -1080,51 +999,48 @@ def _write_idf_component_yml():
1080
999
  contents = ""
1081
1000
  if write_file_if_changed(yml_path, contents):
1082
1001
  dependencies_lock = CORE.relative_build_path("dependencies.lock")
1083
- if os.path.isfile(dependencies_lock):
1084
- os.remove(dependencies_lock)
1002
+ if dependencies_lock.is_file():
1003
+ dependencies_lock.unlink()
1085
1004
  clean_cmake_cache()
1086
1005
 
1087
1006
 
1088
1007
  # Called by writer.py
1089
1008
  def copy_files():
1090
- if (
1091
- CORE.using_arduino
1092
- and "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]
1093
- ):
1094
- write_file_if_changed(
1095
- CORE.relative_build_path("partitions.csv"),
1096
- get_arduino_partition_csv(
1097
- CORE.platformio_options.get("board_upload.flash_size")
1098
- ),
1099
- )
1100
- if CORE.using_esp_idf:
1101
- _write_sdkconfig()
1102
- _write_idf_component_yml()
1103
- if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]:
1009
+ _write_sdkconfig()
1010
+ _write_idf_component_yml()
1011
+
1012
+ if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]:
1013
+ if CORE.using_arduino:
1014
+ write_file_if_changed(
1015
+ CORE.relative_build_path("partitions.csv"),
1016
+ get_arduino_partition_csv(
1017
+ CORE.platformio_options.get("board_upload.flash_size")
1018
+ ),
1019
+ )
1020
+ else:
1104
1021
  write_file_if_changed(
1105
1022
  CORE.relative_build_path("partitions.csv"),
1106
1023
  get_idf_partition_csv(
1107
1024
  CORE.platformio_options.get("board_upload.flash_size")
1108
1025
  ),
1109
1026
  )
1110
- # IDF build scripts look for version string to put in the build.
1111
- # However, if the build path does not have an initialized git repo,
1112
- # and no version.txt file exists, the CMake script fails for some setups.
1113
- # Fix by manually pasting a version.txt file, containing the ESPHome version
1114
- write_file_if_changed(
1115
- CORE.relative_build_path("version.txt"),
1116
- __version__,
1117
- )
1027
+ # IDF build scripts look for version string to put in the build.
1028
+ # However, if the build path does not have an initialized git repo,
1029
+ # and no version.txt file exists, the CMake script fails for some setups.
1030
+ # Fix by manually pasting a version.txt file, containing the ESPHome version
1031
+ write_file_if_changed(
1032
+ CORE.relative_build_path("version.txt"),
1033
+ __version__,
1034
+ )
1118
1035
 
1119
1036
  for file in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES].values():
1120
- if file[KEY_PATH].startswith("http"):
1037
+ name: str = file[KEY_NAME]
1038
+ path: Path = file[KEY_PATH]
1039
+ if str(path).startswith("http"):
1121
1040
  import requests
1122
1041
 
1123
- mkdir_p(CORE.relative_build_path(os.path.dirname(file[KEY_NAME])))
1124
- with open(CORE.relative_build_path(file[KEY_NAME]), "wb") as f:
1125
- f.write(requests.get(file[KEY_PATH], timeout=30).content)
1042
+ CORE.relative_build_path(name).parent.mkdir(parents=True, exist_ok=True)
1043
+ content = requests.get(path, timeout=30).content
1044
+ CORE.relative_build_path(name).write_bytes(content)
1126
1045
  else:
1127
- copy_file_if_changed(
1128
- file[KEY_PATH],
1129
- CORE.relative_build_path(file[KEY_NAME]),
1130
- )
1046
+ copy_file_if_changed(path, CORE.relative_build_path(name))