esphome 2025.7.4__py3-none-any.whl → 2025.8.0b1__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 (754) hide show
  1. esphome/__main__.py +189 -82
  2. esphome/automation.py +2 -4
  3. esphome/build_gen/__init__.py +0 -0
  4. esphome/build_gen/platformio.py +102 -0
  5. esphome/components/a4988/a4988.cpp +0 -1
  6. esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
  7. esphome/components/absolute_humidity/sensor.py +2 -2
  8. esphome/components/adc/__init__.py +123 -85
  9. esphome/components/adc/adc_sensor.h +98 -35
  10. esphome/components/adc/adc_sensor_common.cpp +10 -4
  11. esphome/components/adc/adc_sensor_esp32.cpp +291 -123
  12. esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
  13. esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
  14. esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
  15. esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
  16. esphome/components/adc/sensor.py +61 -27
  17. esphome/components/adc128s102/adc128s102.cpp +1 -4
  18. esphome/components/ade7880/sensor.py +75 -49
  19. esphome/components/ads1115/ads1115.cpp +0 -1
  20. esphome/components/ads1118/ads1118.cpp +0 -1
  21. esphome/components/ags10/ags10.cpp +0 -4
  22. esphome/components/aht10/aht10.cpp +0 -4
  23. esphome/components/aic3204/aic3204.cpp +0 -2
  24. esphome/components/airthings_wave_plus/__init__.py +1 -1
  25. esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
  26. esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
  27. esphome/components/airthings_wave_plus/sensor.py +55 -28
  28. esphome/components/alarm_control_panel/__init__.py +4 -9
  29. esphome/components/am2315c/am2315c.cpp +0 -2
  30. esphome/components/am2320/am2320.cpp +0 -1
  31. esphome/components/animation/__init__.py +14 -11
  32. esphome/components/apds9306/apds9306.cpp +0 -4
  33. esphome/components/apds9960/apds9960.cpp +0 -1
  34. esphome/components/api/__init__.py +29 -4
  35. esphome/components/api/api_connection.cpp +378 -401
  36. esphome/components/api/api_connection.h +112 -56
  37. esphome/components/api/api_frame_helper.cpp +69 -896
  38. esphome/components/api/api_frame_helper.h +31 -126
  39. esphome/components/api/api_frame_helper_noise.cpp +583 -0
  40. esphome/components/api/api_frame_helper_noise.h +68 -0
  41. esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
  42. esphome/components/api/api_frame_helper_plaintext.h +53 -0
  43. esphome/components/api/api_noise_context.h +2 -4
  44. esphome/components/api/api_pb2.cpp +1601 -1808
  45. esphome/components/api/api_pb2.h +367 -323
  46. esphome/components/api/api_pb2_dump.cpp +1137 -3466
  47. esphome/components/api/api_pb2_includes.h +34 -0
  48. esphome/components/api/api_pb2_service.cpp +94 -105
  49. esphome/components/api/api_pb2_service.h +27 -16
  50. esphome/components/api/api_server.cpp +18 -17
  51. esphome/components/api/api_server.h +8 -5
  52. esphome/components/api/client.py +16 -8
  53. esphome/components/api/custom_api_device.h +68 -14
  54. esphome/components/api/homeassistant_service.h +24 -19
  55. esphome/components/api/list_entities.cpp +3 -5
  56. esphome/components/api/list_entities.h +2 -4
  57. esphome/components/api/proto.cpp +3 -5
  58. esphome/components/api/proto.h +239 -274
  59. esphome/components/api/subscribe_state.cpp +2 -4
  60. esphome/components/api/subscribe_state.h +2 -4
  61. esphome/components/api/user_services.cpp +2 -4
  62. esphome/components/api/user_services.h +8 -8
  63. esphome/components/as3935/as3935.cpp +0 -2
  64. esphome/components/as3935_spi/as3935_spi.cpp +0 -2
  65. esphome/components/as5600/__init__.py +1 -1
  66. esphome/components/as5600/as5600.cpp +0 -2
  67. esphome/components/as5600/sensor/__init__.py +0 -1
  68. esphome/components/as7341/as7341.cpp +0 -1
  69. esphome/components/async_tcp/__init__.py +1 -1
  70. esphome/components/at581x/at581x.cpp +1 -1
  71. esphome/components/atm90e26/atm90e26.cpp +0 -1
  72. esphome/components/atm90e32/atm90e32.cpp +488 -118
  73. esphome/components/atm90e32/atm90e32.h +44 -5
  74. esphome/components/audio/audio.h +2 -2
  75. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
  76. esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
  77. esphome/components/bh1750/bh1750.cpp +0 -1
  78. esphome/components/binary_sensor/__init__.py +14 -12
  79. esphome/components/ble_client/__init__.py +4 -7
  80. esphome/components/bluetooth_proxy/__init__.py +40 -3
  81. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +387 -82
  82. esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
  83. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
  84. esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
  85. esphome/components/bme280_base/bme280_base.cpp +15 -16
  86. esphome/components/bme680/bme680.cpp +2 -3
  87. esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
  88. esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
  89. esphome/components/bmi160/bmi160.cpp +0 -1
  90. esphome/components/bmp085/bmp085.cpp +0 -1
  91. esphome/components/bmp280_base/bmp280_base.cpp +13 -14
  92. esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
  93. esphome/components/bmp581/bmp581.cpp +0 -2
  94. esphome/components/bp1658cj/bp1658cj.cpp +0 -1
  95. esphome/components/bp5758d/bp5758d.cpp +0 -1
  96. esphome/components/button/__init__.py +0 -1
  97. esphome/components/canbus/__init__.py +2 -3
  98. esphome/components/canbus/canbus.cpp +0 -1
  99. esphome/components/cap1188/cap1188.cpp +0 -2
  100. esphome/components/captive_portal/__init__.py +1 -1
  101. esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
  102. esphome/components/ch422g/ch422g.cpp +0 -1
  103. esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
  104. esphome/components/climate/__init__.py +0 -1
  105. esphome/components/climate/climate_traits.h +24 -0
  106. esphome/components/cm1106/cm1106.cpp +0 -1
  107. esphome/components/const/__init__.py +6 -0
  108. esphome/components/cover/__init__.py +0 -1
  109. esphome/components/cover/cover.cpp +9 -13
  110. esphome/components/cs5460a/cs5460a.cpp +0 -2
  111. esphome/components/cse7761/cse7761.cpp +0 -1
  112. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
  113. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
  114. esphome/components/dac7678/dac7678_output.cpp +0 -2
  115. esphome/components/dallas_temp/dallas_temp.cpp +0 -1
  116. esphome/components/datetime/__init__.py +0 -2
  117. esphome/components/debug/__init__.py +15 -1
  118. esphome/components/debug/debug_zephyr.cpp +281 -0
  119. esphome/components/debug/sensor.py +2 -1
  120. esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
  121. esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
  122. esphome/components/dfrobot_sen0395/__init__.py +1 -2
  123. esphome/components/dht/dht.cpp +0 -1
  124. esphome/components/dht12/dht12.cpp +0 -1
  125. esphome/components/display/__init__.py +16 -3
  126. esphome/components/display_menu_base/__init__.py +1 -1
  127. esphome/components/dps310/dps310.cpp +0 -2
  128. esphome/components/ds1307/ds1307.cpp +0 -1
  129. esphome/components/ds2484/ds2484.cpp +0 -1
  130. esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
  131. esphome/components/ee895/ee895.cpp +0 -1
  132. esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
  133. esphome/components/emc2101/emc2101.cpp +0 -2
  134. esphome/components/ens160_base/ens160_base.cpp +0 -2
  135. esphome/components/ens210/ens210.cpp +0 -1
  136. esphome/components/es7210/es7210.cpp +0 -2
  137. esphome/components/es7243e/es7243e.cpp +0 -2
  138. esphome/components/es8156/es8156.cpp +0 -2
  139. esphome/components/es8311/es8311.cpp +0 -2
  140. esphome/components/es8388/es8388.cpp +0 -2
  141. esphome/components/esp32/__init__.py +199 -58
  142. esphome/components/esp32/boards.py +17 -0
  143. esphome/components/esp32/gpio.cpp +0 -1
  144. esphome/components/esp32/gpio.py +1 -2
  145. esphome/components/esp32/gpio_esp32_h2.py +2 -7
  146. esphome/components/esp32/gpio_esp32_p4.py +2 -7
  147. esphome/components/esp32/post_build.py.script +112 -61
  148. esphome/components/esp32_ble/__init__.py +40 -2
  149. esphome/components/esp32_ble/ble.cpp +12 -8
  150. esphome/components/esp32_ble/ble.h +18 -18
  151. esphome/components/esp32_ble/ble_advertising.cpp +5 -5
  152. esphome/components/esp32_ble/ble_advertising.h +7 -5
  153. esphome/components/esp32_ble/ble_event.h +2 -4
  154. esphome/components/esp32_ble/ble_scan_result.h +2 -4
  155. esphome/components/esp32_ble/ble_uuid.cpp +5 -5
  156. esphome/components/esp32_ble/ble_uuid.h +6 -5
  157. esphome/components/esp32_ble_beacon/__init__.py +4 -0
  158. esphome/components/esp32_ble_client/__init__.py +1 -1
  159. esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
  160. esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
  161. esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
  162. esphome/components/esp32_ble_client/ble_client_base.h +17 -6
  163. esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
  164. esphome/components/esp32_ble_client/ble_service.cpp +4 -4
  165. esphome/components/esp32_ble_client/ble_service.h +6 -4
  166. esphome/components/esp32_ble_server/__init__.py +15 -12
  167. esphome/components/esp32_ble_tracker/__init__.py +79 -11
  168. esphome/components/esp32_ble_tracker/automation.h +4 -4
  169. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
  170. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
  171. esphome/components/esp32_camera/__init__.py +13 -1
  172. esphome/components/esp32_camera/esp32_camera.cpp +7 -2
  173. esphome/components/esp32_camera/esp32_camera.h +1 -0
  174. esphome/components/esp32_dac/esp32_dac.cpp +3 -19
  175. esphome/components/esp32_dac/esp32_dac.h +4 -8
  176. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
  177. esphome/components/esp32_rmt_led_strip/light.py +1 -1
  178. esphome/components/esp32_touch/__init__.py +2 -3
  179. esphome/components/esp32_touch/esp32_touch.h +9 -6
  180. esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
  181. esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
  182. esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
  183. esphome/components/esp8266/__init__.py +3 -1
  184. esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
  185. esphome/components/esphome/ota/__init__.py +1 -2
  186. esphome/components/esphome/ota/ota_esphome.cpp +150 -77
  187. esphome/components/esphome/ota/ota_esphome.h +8 -1
  188. esphome/components/espnow/__init__.py +309 -0
  189. esphome/components/espnow/automation.h +175 -0
  190. esphome/components/espnow/espnow_component.cpp +468 -0
  191. esphome/components/espnow/espnow_component.h +183 -0
  192. esphome/components/espnow/espnow_err.h +19 -0
  193. esphome/components/espnow/espnow_packet.h +166 -0
  194. esphome/components/ethernet/__init__.py +7 -1
  195. esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
  196. esphome/components/ethernet/ethernet_component.cpp +0 -1
  197. esphome/components/ethernet/ethernet_component.h +4 -0
  198. esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
  199. esphome/components/event/__init__.py +0 -1
  200. esphome/components/factory_reset/__init__.py +92 -0
  201. esphome/components/factory_reset/factory_reset.cpp +76 -0
  202. esphome/components/factory_reset/factory_reset.h +43 -0
  203. esphome/components/fan/__init__.py +0 -1
  204. esphome/components/fan/fan_traits.h +16 -0
  205. esphome/components/fastled_base/fastled_light.cpp +0 -1
  206. esphome/components/fastled_spi/light.py +1 -3
  207. esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
  208. esphome/components/font/__init__.py +9 -1
  209. esphome/components/fs3000/fs3000.cpp +0 -2
  210. esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
  211. esphome/components/ft63x6/ft63x6.cpp +0 -1
  212. esphome/components/gdk101/gdk101.cpp +0 -1
  213. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
  214. esphome/components/gl_r01_i2c/sensor.py +1 -1
  215. esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
  216. esphome/components/gpio/switch/gpio_switch.cpp +0 -2
  217. esphome/components/gpio_expander/cached_gpio.h +24 -15
  218. esphome/components/gps/__init__.py +6 -2
  219. esphome/components/gps/gps.cpp +50 -49
  220. esphome/components/gps/gps.h +4 -8
  221. esphome/components/gps/time/gps_time.cpp +3 -9
  222. esphome/components/gps/time/gps_time.h +4 -7
  223. esphome/components/graph/__init__.py +1 -1
  224. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
  225. esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
  226. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
  227. esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
  228. esphome/components/haier/climate.py +5 -10
  229. esphome/components/haier/haier_base.cpp +0 -1
  230. esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
  231. esphome/components/hdc1080/hdc1080.cpp +0 -2
  232. esphome/components/heatpumpir/climate.py +2 -2
  233. esphome/components/hlw8012/hlw8012.cpp +0 -1
  234. esphome/components/hm3301/hm3301.cpp +0 -1
  235. esphome/components/hmc5883l/hmc5883l.cpp +0 -1
  236. esphome/components/homeassistant/__init__.py +1 -0
  237. esphome/components/homeassistant/number/__init__.py +1 -0
  238. esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
  239. esphome/components/homeassistant/switch/__init__.py +1 -0
  240. esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
  241. esphome/components/honeywellabp/honeywellabp.cpp +1 -4
  242. esphome/components/host/__init__.py +2 -0
  243. esphome/components/hte501/hte501.cpp +0 -1
  244. esphome/components/http_request/__init__.py +2 -3
  245. esphome/components/http_request/http_request_idf.cpp +2 -2
  246. esphome/components/htu21d/htu21d.cpp +0 -2
  247. esphome/components/htu31d/htu31d.cpp +0 -2
  248. esphome/components/hx711/hx711.cpp +0 -1
  249. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
  250. esphome/components/hydreon_rgxx/sensor.py +4 -5
  251. esphome/components/i2c/i2c_bus.h +1 -1
  252. esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
  253. esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
  254. esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
  255. esphome/components/i2s_audio/__init__.py +6 -5
  256. esphome/components/i2s_audio/i2s_audio.cpp +0 -2
  257. esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
  258. esphome/components/i2s_audio/microphone/__init__.py +4 -6
  259. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +46 -19
  260. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -3
  261. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
  262. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
  263. esphome/components/ili9xxx/display.py +4 -3
  264. esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
  265. esphome/components/image/__init__.py +123 -92
  266. esphome/components/improv_serial/__init__.py +7 -8
  267. esphome/components/ina219/ina219.cpp +0 -1
  268. esphome/components/ina226/ina226.cpp +0 -2
  269. esphome/components/ina260/ina260.cpp +0 -2
  270. esphome/components/ina2xx_base/__init__.py +2 -5
  271. esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
  272. esphome/components/ina3221/ina3221.cpp +0 -1
  273. esphome/components/internal_temperature/internal_temperature.cpp +0 -2
  274. esphome/components/interval/interval.h +5 -9
  275. esphome/components/json/__init__.py +1 -1
  276. esphome/components/kmeteriso/kmeteriso.cpp +0 -2
  277. esphome/components/lc709203f/lc709203f.cpp +0 -2
  278. esphome/components/lcd_gpio/display.py +1 -3
  279. esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
  280. esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
  281. esphome/components/ld2410/__init__.py +4 -6
  282. esphome/components/ld2410/binary_sensor.py +4 -0
  283. esphome/components/ld2410/ld2410.cpp +56 -100
  284. esphome/components/ld2410/ld2410.h +17 -15
  285. esphome/components/ld2410/sensor.py +24 -10
  286. esphome/components/ld2412/__init__.py +46 -0
  287. esphome/components/ld2412/binary_sensor.py +70 -0
  288. esphome/components/ld2412/button/__init__.py +74 -0
  289. esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
  290. esphome/components/ld2412/button/factory_reset_button.h +18 -0
  291. esphome/components/ld2412/button/query_button.cpp +9 -0
  292. esphome/components/ld2412/button/query_button.h +18 -0
  293. esphome/components/ld2412/button/restart_button.cpp +9 -0
  294. esphome/components/ld2412/button/restart_button.h +18 -0
  295. esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
  296. esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
  297. esphome/components/ld2412/ld2412.cpp +861 -0
  298. esphome/components/ld2412/ld2412.h +141 -0
  299. esphome/components/ld2412/number/__init__.py +126 -0
  300. esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
  301. esphome/components/ld2412/number/gate_threshold_number.h +19 -0
  302. esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
  303. esphome/components/ld2412/number/light_threshold_number.h +18 -0
  304. esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
  305. esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
  306. esphome/components/ld2412/select/__init__.py +82 -0
  307. esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
  308. esphome/components/ld2412/select/baud_rate_select.h +18 -0
  309. esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
  310. esphome/components/ld2412/select/distance_resolution_select.h +18 -0
  311. esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
  312. esphome/components/ld2412/select/light_out_control_select.h +18 -0
  313. esphome/components/ld2412/sensor.py +124 -0
  314. esphome/components/ld2412/switch/__init__.py +45 -0
  315. esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
  316. esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
  317. esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
  318. esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
  319. esphome/components/ld2412/text_sensor.py +34 -0
  320. esphome/components/ld2420/ld2420.cpp +0 -1
  321. esphome/components/ld2450/__init__.py +3 -4
  322. esphome/components/ld2450/binary_sensor.py +3 -0
  323. esphome/components/ld2450/ld2450.cpp +77 -165
  324. esphome/components/ld2450/ld2450.h +26 -54
  325. esphome/components/ld2450/sensor.py +120 -6
  326. esphome/components/ld2450/text_sensor.py +5 -4
  327. esphome/components/ld24xx/__init__.py +1 -0
  328. esphome/components/ld24xx/ld24xx.h +65 -0
  329. esphome/components/ledc/ledc_output.cpp +0 -1
  330. esphome/components/libretiny/__init__.py +2 -0
  331. esphome/components/light/__init__.py +0 -1
  332. esphome/components/light/effects.py +70 -45
  333. esphome/components/light/light_call.cpp +101 -66
  334. esphome/components/light/light_color_values.h +16 -11
  335. esphome/components/light/light_json_schema.cpp +46 -44
  336. esphome/components/light/light_state.cpp +8 -11
  337. esphome/components/light/light_traits.h +17 -0
  338. esphome/components/lightwaverf/lightwaverf.cpp +0 -2
  339. esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
  340. esphome/components/lock/__init__.py +0 -1
  341. esphome/components/logger/__init__.py +31 -9
  342. esphome/components/logger/logger.cpp +12 -7
  343. esphome/components/logger/logger.h +25 -14
  344. esphome/components/logger/logger_esp32.cpp +2 -7
  345. esphome/components/logger/logger_esp8266.cpp +2 -4
  346. esphome/components/logger/logger_host.cpp +2 -4
  347. esphome/components/logger/logger_libretiny.cpp +2 -4
  348. esphome/components/logger/logger_rp2040.cpp +2 -4
  349. esphome/components/logger/logger_zephyr.cpp +86 -0
  350. esphome/components/logger/select/logger_level_select.cpp +2 -4
  351. esphome/components/logger/select/logger_level_select.h +2 -4
  352. esphome/components/logger/task_log_buffer.cpp +2 -4
  353. esphome/components/logger/task_log_buffer.h +2 -4
  354. esphome/components/lps22/sensor.py +5 -5
  355. esphome/components/ltr390/ltr390.cpp +0 -2
  356. esphome/components/ltr501/ltr501.cpp +0 -1
  357. esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
  358. esphome/components/lvgl/__init__.py +14 -13
  359. esphome/components/lvgl/automation.py +2 -4
  360. esphome/components/lvgl/defines.py +0 -2
  361. esphome/components/lvgl/helpers.py +1 -1
  362. esphome/components/lvgl/lv_validation.py +7 -4
  363. esphome/components/lvgl/lvgl_esphome.cpp +2 -3
  364. esphome/components/lvgl/styles.py +2 -2
  365. esphome/components/lvgl/types.py +1 -1
  366. esphome/components/lvgl/widgets/__init__.py +2 -2
  367. esphome/components/lvgl/widgets/arc.py +14 -11
  368. esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
  369. esphome/components/lvgl/widgets/qrcode.py +7 -7
  370. esphome/components/lvgl/widgets/spinner.py +6 -6
  371. esphome/components/lvgl/widgets/switch.py +2 -2
  372. esphome/components/lvgl/widgets/tabview.py +3 -3
  373. esphome/components/lvgl/widgets/tileview.py +15 -7
  374. esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
  375. esphome/components/matrix_keypad/__init__.py +4 -3
  376. esphome/components/max17043/max17043.cpp +0 -2
  377. esphome/components/max31855/max31855.cpp +1 -4
  378. esphome/components/max31856/max31856.cpp +0 -4
  379. esphome/components/max31865/max31865.cpp +0 -1
  380. esphome/components/max44009/max44009.cpp +0 -1
  381. esphome/components/max6675/max6675.cpp +1 -4
  382. esphome/components/max6956/max6956.cpp +0 -1
  383. esphome/components/max7219/max7219.cpp +0 -1
  384. esphome/components/max7219digit/display.py +1 -1
  385. esphome/components/max7219digit/max7219digit.cpp +0 -1
  386. esphome/components/max9611/max9611.cpp +0 -1
  387. esphome/components/mcp23008/__init__.py +1 -1
  388. esphome/components/mcp23008/mcp23008.cpp +0 -1
  389. esphome/components/mcp23016/mcp23016.cpp +0 -1
  390. esphome/components/mcp23017/__init__.py +1 -1
  391. esphome/components/mcp23017/mcp23017.cpp +0 -1
  392. esphome/components/mcp23s08/__init__.py +1 -1
  393. esphome/components/mcp23s08/mcp23s08.cpp +0 -1
  394. esphome/components/mcp23s17/__init__.py +1 -1
  395. esphome/components/mcp23s17/mcp23s17.cpp +0 -1
  396. esphome/components/mcp23x08_base/__init__.py +2 -0
  397. esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
  398. esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
  399. esphome/components/mcp23x17_base/__init__.py +2 -0
  400. esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
  401. esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
  402. esphome/components/mcp23xxx_base/__init__.py +11 -5
  403. esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
  404. esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
  405. esphome/components/mcp3008/mcp3008.cpp +1 -4
  406. esphome/components/mcp3204/mcp3204.cpp +1 -4
  407. esphome/components/mcp4461/mcp4461.cpp +0 -1
  408. esphome/components/mcp4725/mcp4725.cpp +0 -1
  409. esphome/components/mcp4728/mcp4728.cpp +0 -1
  410. esphome/components/mcp9600/mcp9600.cpp +0 -2
  411. esphome/components/mcp9808/mcp9808.cpp +0 -2
  412. esphome/components/mdns/__init__.py +3 -0
  413. esphome/components/mdns/mdns_component.cpp +2 -0
  414. esphome/components/mdns/mdns_component.h +4 -0
  415. esphome/components/media_player/__init__.py +40 -0
  416. esphome/components/media_player/automation.h +16 -0
  417. esphome/components/media_player/media_player.cpp +13 -0
  418. esphome/components/media_player/media_player.h +50 -3
  419. esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
  420. esphome/components/mics_4514/mics_4514.cpp +1 -6
  421. esphome/components/midea/ir_transmitter.h +4 -4
  422. esphome/components/mipi/__init__.py +416 -0
  423. esphome/components/mipi_dsi/__init__.py +5 -0
  424. esphome/components/mipi_dsi/display.py +233 -0
  425. esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
  426. esphome/components/mipi_dsi/mipi_dsi.h +123 -0
  427. esphome/components/mipi_dsi/models/__init__.py +0 -0
  428. esphome/components/mipi_dsi/models/guition.py +38 -0
  429. esphome/components/mipi_dsi/models/m5stack.py +57 -0
  430. esphome/components/mipi_dsi/models/waveshare.py +105 -0
  431. esphome/components/mipi_rgb/models/lilygo.py +0 -0
  432. esphome/components/mipi_spi/__init__.py +0 -9
  433. esphome/components/mipi_spi/display.py +220 -256
  434. esphome/components/mipi_spi/mipi_spi.cpp +1 -485
  435. esphome/components/mipi_spi/mipi_spi.h +556 -108
  436. esphome/components/mipi_spi/models/__init__.py +0 -65
  437. esphome/components/mipi_spi/models/adafruit.py +30 -0
  438. esphome/components/mipi_spi/models/amoled.py +41 -5
  439. esphome/components/mipi_spi/models/ili.py +5 -5
  440. esphome/components/mipi_spi/models/jc.py +1 -3
  441. esphome/components/mipi_spi/models/lilygo.py +1 -1
  442. esphome/components/mipi_spi/models/waveshare.py +16 -1
  443. esphome/components/mixer/speaker/__init__.py +4 -5
  444. esphome/components/mlx90393/sensor.py +7 -5
  445. esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
  446. esphome/components/mlx90614/mlx90614.cpp +0 -1
  447. esphome/components/mmc5603/mmc5603.cpp +0 -1
  448. esphome/components/mmc5983/mmc5983.cpp +0 -2
  449. esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
  450. esphome/components/mpr121/__init__.py +7 -6
  451. esphome/components/mpr121/mpr121.cpp +0 -1
  452. esphome/components/mpu6050/mpu6050.cpp +0 -1
  453. esphome/components/mpu6886/mpu6886.cpp +0 -1
  454. esphome/components/mqtt/__init__.py +1 -2
  455. esphome/components/mqtt/mqtt_button.cpp +1 -1
  456. esphome/components/mqtt/mqtt_client.cpp +0 -1
  457. esphome/components/mqtt/mqtt_component.cpp +8 -14
  458. esphome/components/mqtt/mqtt_component.h +0 -7
  459. esphome/components/mqtt/mqtt_sensor.cpp +0 -1
  460. esphome/components/mqtt/mqtt_sensor.h +0 -1
  461. esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
  462. esphome/components/mqtt/mqtt_text_sensor.h +0 -1
  463. esphome/components/ms5611/ms5611.cpp +0 -1
  464. esphome/components/ms8607/ms8607.cpp +0 -1
  465. esphome/components/msa3xx/msa3xx.cpp +0 -2
  466. esphome/components/my9231/my9231.cpp +0 -2
  467. esphome/components/nau7802/nau7802.cpp +0 -1
  468. esphome/components/neopixelbus/light.py +3 -0
  469. esphome/components/network/util.cpp +29 -0
  470. esphome/components/nextion/nextion.cpp +0 -1
  471. esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
  472. esphome/components/npi19/npi19.cpp +0 -2
  473. esphome/components/nrf52/__init__.py +223 -0
  474. esphome/components/nrf52/boards.py +34 -0
  475. esphome/components/nrf52/const.py +18 -0
  476. esphome/components/nrf52/gpio.py +79 -0
  477. esphome/components/number/__init__.py +2 -1
  478. esphome/components/one_wire/__init__.py +1 -2
  479. esphome/components/one_wire/one_wire.cpp +0 -2
  480. esphome/components/one_wire/one_wire.h +0 -2
  481. esphome/components/opentherm/hub.cpp +0 -1
  482. esphome/components/opentherm/number/__init__.py +2 -2
  483. esphome/components/openthread/__init__.py +2 -3
  484. esphome/components/openthread/openthread.cpp +30 -13
  485. esphome/components/openthread/openthread.h +3 -0
  486. esphome/components/openthread/openthread_esp.cpp +3 -1
  487. esphome/components/opt3001/sensor.py +2 -6
  488. esphome/components/output/__init__.py +38 -0
  489. esphome/components/output/automation.h +24 -0
  490. esphome/components/output/switch/output_switch.cpp +0 -2
  491. esphome/components/packages/__init__.py +1 -2
  492. esphome/components/packet_transport/__init__.py +4 -3
  493. esphome/components/pca6416a/pca6416a.cpp +0 -1
  494. esphome/components/pca9554/pca9554.cpp +0 -1
  495. esphome/components/pca9685/pca9685_output.cpp +0 -2
  496. esphome/components/pcf85063/pcf85063.cpp +0 -1
  497. esphome/components/pcf8563/pcf8563.cpp +0 -1
  498. esphome/components/pcf8574/pcf8574.cpp +0 -1
  499. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
  500. esphome/components/pipsolar/sensor/__init__.py +1 -1
  501. esphome/components/pm2005/pm2005.cpp +0 -1
  502. esphome/components/pmsa003i/pmsa003i.cpp +0 -2
  503. esphome/components/pmwcs3/sensor.py +1 -2
  504. esphome/components/pn532/pn532.cpp +0 -2
  505. esphome/components/pn532_spi/pn532_spi.cpp +0 -2
  506. esphome/components/power_supply/power_supply.cpp +7 -10
  507. esphome/components/power_supply/power_supply.h +1 -1
  508. esphome/components/psram/__init__.py +2 -1
  509. esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
  510. esphome/components/pulse_counter/sensor.py +9 -6
  511. esphome/components/pylontech/pylontech.cpp +0 -1
  512. esphome/components/qmc5883l/qmc5883l.cpp +0 -1
  513. esphome/components/qmp6988/qmp6988.cpp +0 -2
  514. esphome/components/qspi_dbi/display.py +2 -3
  515. esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
  516. esphome/components/qwiic_pir/binary_sensor.py +2 -3
  517. esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
  518. esphome/components/rc522/rc522.cpp +9 -31
  519. esphome/components/rc522_spi/rc522_spi.cpp +0 -1
  520. esphome/components/remote_base/__init__.py +5 -6
  521. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
  522. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
  523. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
  524. esphome/components/remote_transmitter/__init__.py +26 -0
  525. esphome/components/remote_transmitter/automation.h +18 -0
  526. esphome/components/remote_transmitter/remote_transmitter.h +2 -1
  527. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
  528. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  529. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  530. esphome/components/resampler/speaker/__init__.py +4 -5
  531. esphome/components/rf_bridge/__init__.py +4 -8
  532. esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
  533. esphome/components/rp2040/__init__.py +3 -1
  534. esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
  535. esphome/components/rp2040_pio_led_strip/light.py +1 -2
  536. esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
  537. esphome/components/rpi_dpi_rgb/display.py +13 -15
  538. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
  539. esphome/components/runtime_stats/__init__.py +34 -0
  540. esphome/components/runtime_stats/runtime_stats.cpp +102 -0
  541. esphome/components/runtime_stats/runtime_stats.h +132 -0
  542. esphome/components/scd30/scd30.cpp +0 -2
  543. esphome/components/scd30/sensor.py +1 -2
  544. esphome/components/scd4x/scd4x.cpp +0 -1
  545. esphome/components/scd4x/sensor.py +1 -3
  546. esphome/components/sdl/display.py +3 -1
  547. esphome/components/sdl/sdl_esphome.cpp +0 -2
  548. esphome/components/sdp3x/sdp3x.cpp +0 -2
  549. esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
  550. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
  551. esphome/components/select/__init__.py +2 -3
  552. esphome/components/select/select_traits.cpp +1 -1
  553. esphome/components/select/select_traits.h +1 -1
  554. esphome/components/sen0321/sen0321.cpp +0 -1
  555. esphome/components/sen5x/sen5x.cpp +0 -2
  556. esphome/components/sensor/__init__.py +36 -4
  557. esphome/components/sensor/filter.cpp +49 -10
  558. esphome/components/sensor/filter.h +22 -7
  559. esphome/components/sensor/sensor.cpp +0 -1
  560. esphome/components/sensor/sensor.h +0 -9
  561. esphome/components/sfa30/sfa30.cpp +0 -4
  562. esphome/components/sgp30/sgp30.cpp +0 -2
  563. esphome/components/sgp4x/sensor.py +1 -1
  564. esphome/components/sgp4x/sgp4x.cpp +0 -2
  565. esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
  566. esphome/components/sht3xd/sht3xd.cpp +0 -2
  567. esphome/components/sht4x/sht4x.cpp +0 -2
  568. esphome/components/shtcx/shtcx.cpp +0 -1
  569. esphome/components/sim800l/__init__.py +2 -4
  570. esphome/components/sm16716/sm16716.cpp +0 -1
  571. esphome/components/sm2135/sm2135.cpp +0 -1
  572. esphome/components/sm2235/sm2235.cpp +0 -1
  573. esphome/components/sm2335/sm2335.cpp +0 -1
  574. esphome/components/sn74hc165/sn74hc165.cpp +0 -1
  575. esphome/components/sn74hc595/sn74hc595.cpp +0 -1
  576. esphome/components/sntp/sntp_component.cpp +0 -1
  577. esphome/components/sound_level/sensor.py +1 -1
  578. esphome/components/speaker/media_player/__init__.py +21 -33
  579. esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
  580. esphome/components/spi/__init__.py +29 -13
  581. esphome/components/spi/spi.cpp +0 -2
  582. esphome/components/spi_device/spi_device.cpp +1 -4
  583. esphome/components/sprinkler/__init__.py +4 -4
  584. esphome/components/sps30/sps30.cpp +0 -1
  585. esphome/components/ssd1306_base/__init__.py +11 -11
  586. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  587. esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
  588. esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
  589. esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
  590. esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
  591. esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
  592. esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
  593. esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
  594. esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
  595. esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
  596. esphome/components/st7567_spi/st7567_spi.cpp +0 -1
  597. esphome/components/st7701s/display.py +10 -14
  598. esphome/components/st7701s/st7701s.cpp +0 -3
  599. esphome/components/st7735/st7735.cpp +0 -1
  600. esphome/components/st7789v/st7789v.cpp +0 -1
  601. esphome/components/st7920/st7920.cpp +0 -1
  602. esphome/components/status_led/light/status_led_light.cpp +0 -2
  603. esphome/components/status_led/status_led.cpp +0 -1
  604. esphome/components/stepper/__init__.py +2 -4
  605. esphome/components/sts3x/sts3x.cpp +0 -1
  606. esphome/components/substitutions/__init__.py +10 -16
  607. esphome/components/substitutions/jinja.py +24 -1
  608. esphome/components/sun/__init__.py +2 -3
  609. esphome/components/switch/__init__.py +31 -1
  610. esphome/components/switch/automation.h +24 -0
  611. esphome/components/switch/switch.cpp +8 -0
  612. esphome/components/switch/switch.h +8 -0
  613. esphome/components/sx126x/sx126x.cpp +0 -2
  614. esphome/components/sx127x/sx127x.cpp +0 -2
  615. esphome/components/sx1509/__init__.py +7 -5
  616. esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
  617. esphome/components/sx1509/sx1509.cpp +0 -2
  618. esphome/components/syslog/esphome_syslog.cpp +1 -1
  619. esphome/components/tc74/tc74.cpp +0 -1
  620. esphome/components/tca9548a/tca9548a.cpp +0 -1
  621. esphome/components/tca9555/tca9555.cpp +0 -1
  622. esphome/components/tcs34725/tcs34725.cpp +0 -1
  623. esphome/components/tee501/tee501.cpp +0 -1
  624. esphome/components/tem3200/tem3200.cpp +0 -2
  625. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
  626. esphome/components/template/cover/template_cover.cpp +0 -1
  627. esphome/components/template/select/template_select.cpp +0 -1
  628. esphome/components/template/text/template_text.cpp +0 -2
  629. esphome/components/template/valve/template_valve.cpp +0 -1
  630. esphome/components/text/__init__.py +0 -1
  631. esphome/components/text/text_traits.h +2 -0
  632. esphome/components/text_sensor/__init__.py +2 -1
  633. esphome/components/text_sensor/text_sensor.cpp +0 -2
  634. esphome/components/text_sensor/text_sensor.h +0 -8
  635. esphome/components/thermostat/climate.py +4 -4
  636. esphome/components/time/__init__.py +7 -4
  637. esphome/components/time/real_time_clock.cpp +16 -3
  638. esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
  639. esphome/components/tlc5947/tlc5947.cpp +0 -2
  640. esphome/components/tlc5971/tlc5971.cpp +0 -2
  641. esphome/components/tm1621/tm1621.cpp +0 -2
  642. esphome/components/tm1637/tm1637.cpp +0 -2
  643. esphome/components/tm1638/tm1638.cpp +0 -2
  644. esphome/components/tm1651/__init__.py +45 -48
  645. esphome/components/tm1651/tm1651.cpp +213 -47
  646. esphome/components/tm1651/tm1651.h +37 -32
  647. esphome/components/tmp117/tmp117.cpp +0 -2
  648. esphome/components/tsl2561/tsl2561.cpp +0 -1
  649. esphome/components/tsl2591/tsl2591.cpp +0 -1
  650. esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
  651. esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
  652. esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
  653. esphome/components/tuya/climate/__init__.py +9 -10
  654. esphome/components/tuya/number/__init__.py +8 -6
  655. esphome/components/tx20/tx20.cpp +0 -1
  656. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
  657. esphome/components/uart/uart_component_esp8266.cpp +0 -1
  658. esphome/components/uart/uart_component_esp_idf.cpp +0 -2
  659. esphome/components/uart/uart_component_libretiny.cpp +0 -2
  660. esphome/components/uart/uart_component_rp2040.cpp +0 -2
  661. esphome/components/udp/__init__.py +1 -1
  662. esphome/components/ufire_ec/sensor.py +1 -2
  663. esphome/components/ufire_ec/ufire_ec.cpp +0 -2
  664. esphome/components/ufire_ise/sensor.py +1 -2
  665. esphome/components/ufire_ise/ufire_ise.cpp +0 -2
  666. esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
  667. esphome/components/update/__init__.py +0 -1
  668. esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
  669. esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
  670. esphome/components/usb_host/usb_host_client.cpp +0 -1
  671. esphome/components/usb_host/usb_host_component.cpp +0 -1
  672. esphome/components/valve/__init__.py +0 -1
  673. esphome/components/veml3235/veml3235.cpp +0 -3
  674. esphome/components/veml7700/veml7700.cpp +0 -2
  675. esphome/components/version/version_text_sensor.cpp +0 -1
  676. esphome/components/version/version_text_sensor.h +0 -1
  677. esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
  678. esphome/components/voice_assistant/voice_assistant.cpp +9 -8
  679. esphome/components/web_server/__init__.py +13 -0
  680. esphome/components/web_server/web_server.cpp +187 -352
  681. esphome/components/web_server/web_server.h +61 -1
  682. esphome/components/web_server_base/__init__.py +1 -1
  683. esphome/components/web_server_base/web_server_base.cpp +2 -0
  684. esphome/components/web_server_base/web_server_base.h +6 -0
  685. esphome/components/web_server_idf/web_server_idf.cpp +10 -8
  686. esphome/components/web_server_idf/web_server_idf.h +2 -0
  687. esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
  688. esphome/components/weikai_spi/weikai_spi.cpp +1 -1
  689. esphome/components/wifi/__init__.py +8 -43
  690. esphome/components/wifi/wifi_component.cpp +100 -36
  691. esphome/components/wifi/wifi_component.h +5 -1
  692. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
  693. esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
  694. esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
  695. esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
  696. esphome/components/wireguard/wireguard.cpp +0 -2
  697. esphome/components/x9c/x9c.cpp +0 -2
  698. esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
  699. esphome/components/xl9535/xl9535.cpp +0 -2
  700. esphome/components/zephyr/__init__.py +252 -0
  701. esphome/components/zephyr/const.py +16 -0
  702. esphome/components/zephyr/core.cpp +90 -0
  703. esphome/components/zephyr/gpio.cpp +120 -0
  704. esphome/components/zephyr/gpio.h +38 -0
  705. esphome/components/zephyr/pre_build.py.script +4 -0
  706. esphome/components/zephyr/preferences.cpp +156 -0
  707. esphome/components/zephyr/preferences.h +13 -0
  708. esphome/config.py +38 -16
  709. esphome/config_helpers.py +1 -2
  710. esphome/config_validation.py +8 -15
  711. esphome/const.py +26 -1
  712. esphome/core/__init__.py +88 -51
  713. esphome/core/application.cpp +75 -21
  714. esphome/core/application.h +106 -171
  715. esphome/core/color.h +10 -0
  716. esphome/core/component.cpp +41 -25
  717. esphome/core/component.h +9 -6
  718. esphome/core/component_iterator.cpp +61 -261
  719. esphome/core/component_iterator.h +15 -0
  720. esphome/core/config.py +26 -11
  721. esphome/core/defines.h +40 -2
  722. esphome/core/entity_base.h +18 -0
  723. esphome/core/entity_helpers.py +41 -6
  724. esphome/core/helpers.cpp +8 -15
  725. esphome/core/helpers.h +60 -6
  726. esphome/core/lock_free_queue.h +1 -1
  727. esphome/core/scheduler.cpp +277 -74
  728. esphome/core/scheduler.h +89 -27
  729. esphome/cpp_generator.py +2 -6
  730. esphome/cpp_helpers.py +1 -1
  731. esphome/dashboard/dashboard.py +2 -3
  732. esphome/dashboard/dns.py +2 -8
  733. esphome/dashboard/web_server.py +34 -19
  734. esphome/espota2.py +1 -4
  735. esphome/git.py +3 -1
  736. esphome/helpers.py +23 -4
  737. esphome/log.py +3 -1
  738. esphome/mqtt.py +3 -5
  739. esphome/platformio_api.py +7 -4
  740. esphome/types.py +12 -0
  741. esphome/util.py +20 -8
  742. esphome/voluptuous_schema.py +4 -3
  743. esphome/vscode.py +1 -2
  744. esphome/wizard.py +1 -4
  745. esphome/writer.py +5 -107
  746. esphome/yaml_util.py +7 -5
  747. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/METADATA +12 -13
  748. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/RECORD +753 -673
  749. esphome/components/mipi_spi/models/commands.py +0 -82
  750. /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
  751. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/WHEEL +0 -0
  752. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/entry_points.txt +0 -0
  753. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/licenses/LICENSE +0 -0
  754. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/top_level.txt +0 -0
esphome/core/scheduler.h CHANGED
@@ -1,9 +1,13 @@
1
1
  #pragma once
2
2
 
3
+ #include "esphome/core/defines.h"
3
4
  #include <vector>
4
5
  #include <memory>
5
6
  #include <cstring>
6
7
  #include <deque>
8
+ #ifdef ESPHOME_THREAD_MULTI_ATOMICS
9
+ #include <atomic>
10
+ #endif
7
11
 
8
12
  #include "esphome/core/component.h"
9
13
  #include "esphome/core/helpers.h"
@@ -11,8 +15,15 @@
11
15
  namespace esphome {
12
16
 
13
17
  class Component;
18
+ struct RetryArgs;
19
+
20
+ // Forward declaration of retry_handler - needs to be non-static for friend declaration
21
+ void retry_handler(const std::shared_ptr<RetryArgs> &args);
14
22
 
15
23
  class Scheduler {
24
+ // Allow retry_handler to access protected members
25
+ friend void ::esphome::retry_handler(const std::shared_ptr<RetryArgs> &args);
26
+
16
27
  public:
17
28
  // Public API - accepts std::string for backward compatibility
18
29
  void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function<void()> func);
@@ -50,11 +61,21 @@ class Scheduler {
50
61
  bool cancel_interval(Component *component, const char *name);
51
62
  void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts,
52
63
  std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f);
64
+ void set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts,
65
+ std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f);
53
66
  bool cancel_retry(Component *component, const std::string &name);
67
+ bool cancel_retry(Component *component, const char *name);
54
68
 
55
- optional<uint32_t> next_schedule_in();
69
+ // Calculate when the next scheduled item should run
70
+ // @param now Fresh timestamp from millis() - must not be stale/cached
71
+ // Returns the time in milliseconds until the next scheduled item, or nullopt if no items
72
+ // This method performs cleanup of removed items before checking the schedule
73
+ // IMPORTANT: This method should only be called from the main thread (loop task).
74
+ optional<uint32_t> next_schedule_in(uint32_t now);
56
75
 
57
- void call();
76
+ // Execute all scheduled items that are ready
77
+ // @param now Fresh timestamp from millis() - must not be stale/cached
78
+ void call(uint32_t now);
58
79
 
59
80
  void process_to_add();
60
81
 
@@ -80,11 +101,18 @@ class Scheduler {
80
101
  enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1;
81
102
  bool remove : 1;
82
103
  bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[])
83
- // 5 bits padding
104
+ bool is_retry : 1; // True if this is a retry timeout
105
+ // 4 bits padding
84
106
 
85
107
  // Constructor
86
108
  SchedulerItem()
87
- : component(nullptr), interval(0), next_execution_(0), type(TIMEOUT), remove(false), name_is_dynamic(false) {
109
+ : component(nullptr),
110
+ interval(0),
111
+ next_execution_(0),
112
+ type(TIMEOUT),
113
+ remove(false),
114
+ name_is_dynamic(false),
115
+ is_retry(false) {
88
116
  name_.static_name = nullptr;
89
117
  }
90
118
 
@@ -136,15 +164,22 @@ class Scheduler {
136
164
 
137
165
  // Common implementation for both timeout and interval
138
166
  void set_timer_common_(Component *component, SchedulerItem::Type type, bool is_static_string, const void *name_ptr,
139
- uint32_t delay, std::function<void()> func);
167
+ uint32_t delay, std::function<void()> func, bool is_retry = false);
140
168
 
141
- uint64_t millis_();
142
- void cleanup_();
169
+ // Common implementation for retry
170
+ void set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, uint32_t initial_wait_time,
171
+ uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor);
172
+
173
+ uint64_t millis_64_(uint32_t now);
174
+ // Cleanup logically deleted items from the scheduler
175
+ // Returns the number of items remaining after cleanup
176
+ // IMPORTANT: This method should only be called from the main thread (loop task).
177
+ size_t cleanup_();
143
178
  void pop_raw_();
144
179
 
145
180
  private:
146
181
  // Helper to cancel items by name - must be called with lock held
147
- bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type);
182
+ bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type, bool match_retry = false);
148
183
 
149
184
  // Helper to extract name as const char* from either static string or std::string
150
185
  inline const char *get_name_cstr_(bool is_static_string, const void *name_ptr) {
@@ -156,8 +191,9 @@ class Scheduler {
156
191
 
157
192
  // Helper function to check if item matches criteria for cancellation
158
193
  inline bool HOT matches_item_(const std::unique_ptr<SchedulerItem> &item, Component *component, const char *name_cstr,
159
- SchedulerItem::Type type) {
160
- if (item->component != component || item->type != type || item->remove) {
194
+ SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const {
195
+ if (item->component != component || item->type != type || (skip_removed && item->remove) ||
196
+ (match_retry && !item->is_retry)) {
161
197
  return false;
162
198
  }
163
199
  const char *item_name = item->get_name();
@@ -176,37 +212,63 @@ class Scheduler {
176
212
  }
177
213
 
178
214
  // Helper to execute a scheduler item
179
- void execute_item_(SchedulerItem *item);
215
+ void execute_item_(SchedulerItem *item, uint32_t now);
180
216
 
181
217
  // Helper to check if item should be skipped
182
218
  bool should_skip_item_(const SchedulerItem *item) const {
183
219
  return item->remove || (item->component != nullptr && item->component->is_failed());
184
220
  }
185
221
 
186
- // Check if the scheduler has no items.
187
- // IMPORTANT: This method should only be called from the main thread (loop task).
188
- // It performs cleanup of removed items and checks if the queue is empty.
189
- // The items_.empty() check at the end is done without a lock for performance,
190
- // which is safe because this is only called from the main thread while other
191
- // threads only add items (never remove them).
192
- bool empty_() {
193
- this->cleanup_();
194
- return this->items_.empty();
222
+ // Template helper to check if any item in a container matches our criteria
223
+ template<typename Container>
224
+ bool has_cancelled_timeout_in_container_(const Container &container, Component *component, const char *name_cstr,
225
+ bool match_retry) const {
226
+ for (const auto &item : container) {
227
+ if (item->remove && this->matches_item_(item, component, name_cstr, SchedulerItem::TIMEOUT, match_retry,
228
+ /* skip_removed= */ false)) {
229
+ return true;
230
+ }
231
+ }
232
+ return false;
195
233
  }
196
234
 
197
235
  Mutex lock_;
198
236
  std::vector<std::unique_ptr<SchedulerItem>> items_;
199
237
  std::vector<std::unique_ptr<SchedulerItem>> to_add_;
200
- #if !defined(USE_ESP8266) && !defined(USE_RP2040)
201
- // ESP8266 and RP2040 don't need the defer queue because:
202
- // ESP8266: Single-core with no preemptive multitasking
203
- // RP2040: Currently has empty mutex implementation in ESPHome
204
- // Both platforms save 40 bytes of RAM by excluding this
238
+ #ifndef ESPHOME_THREAD_SINGLE
239
+ // Single-core platforms don't need the defer queue and save 40 bytes of RAM
205
240
  std::deque<std::unique_ptr<SchedulerItem>> defer_queue_; // FIFO queue for defer() calls
206
- #endif
241
+ #endif /* ESPHOME_THREAD_SINGLE */
242
+ uint32_t to_remove_{0};
243
+
244
+ #ifdef ESPHOME_THREAD_MULTI_ATOMICS
245
+ /*
246
+ * Multi-threaded platforms with atomic support: last_millis_ needs atomic for lock-free updates
247
+ *
248
+ * MEMORY-ORDERING NOTE
249
+ * --------------------
250
+ * `last_millis_` and `millis_major_` form a single 64-bit timestamp split in half.
251
+ * Writers publish `last_millis_` with memory_order_release and readers use
252
+ * memory_order_acquire. This ensures that once a reader sees the new low word,
253
+ * it also observes the corresponding increment of `millis_major_`.
254
+ */
255
+ std::atomic<uint32_t> last_millis_{0};
256
+ #else /* not ESPHOME_THREAD_MULTI_ATOMICS */
257
+ // Platforms without atomic support or single-threaded platforms
207
258
  uint32_t last_millis_{0};
259
+ #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
260
+
261
+ /*
262
+ * Upper 16 bits of the 64-bit millis counter. Incremented only while holding
263
+ * `lock_`; read concurrently. Atomic (relaxed) avoids a formal data race.
264
+ * Ordering relative to `last_millis_` is provided by its release store and the
265
+ * corresponding acquire loads.
266
+ */
267
+ #ifdef ESPHOME_THREAD_MULTI_ATOMICS
268
+ std::atomic<uint16_t> millis_major_{0};
269
+ #else /* not ESPHOME_THREAD_MULTI_ATOMICS */
208
270
  uint16_t millis_major_{0};
209
- uint32_t to_remove_{0};
271
+ #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
210
272
  };
211
273
 
212
274
  } // namespace esphome
esphome/cpp_generator.py CHANGED
@@ -771,8 +771,7 @@ class MockObj(Expression):
771
771
  if attr.startswith("P") and self.op not in ["::", ""]:
772
772
  attr = attr[1:]
773
773
  next_op = "->"
774
- if attr.startswith("_"):
775
- attr = attr[1:]
774
+ attr = attr.removeprefix("_")
776
775
  return MockObj(f"{self.base}{self.op}{attr}", next_op)
777
776
 
778
777
  def __call__(self, *args: SafeExpType) -> "MockObj":
@@ -1037,10 +1036,7 @@ class MockObjClass(MockObj):
1037
1036
  def inherits_from(self, other: "MockObjClass") -> bool:
1038
1037
  if str(self) == str(other):
1039
1038
  return True
1040
- for parent in self._parents:
1041
- if str(parent) == str(other):
1042
- return True
1043
- return False
1039
+ return any(str(parent) == str(other) for parent in self._parents)
1044
1040
 
1045
1041
  def template(self, *args: SafeExpType) -> "MockObjClass":
1046
1042
  if len(args) != 1 or not isinstance(args[0], TemplateArguments):
esphome/cpp_helpers.py CHANGED
@@ -115,7 +115,7 @@ async def build_registry_list(registry, config):
115
115
 
116
116
  async def past_safe_mode():
117
117
  if CONF_SAFE_MODE not in CORE.config:
118
- return
118
+ return None
119
119
 
120
120
  def _safe_mode_generator():
121
121
  while True:
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  from asyncio import events
5
5
  from concurrent.futures import ThreadPoolExecutor
6
+ import contextlib
6
7
  import logging
7
8
  import os
8
9
  import socket
@@ -125,10 +126,8 @@ def start_dashboard(args) -> None:
125
126
 
126
127
  asyncio.set_event_loop_policy(DashboardEventLoopPolicy(settings.verbose))
127
128
 
128
- try:
129
+ with contextlib.suppress(KeyboardInterrupt):
129
130
  asyncio.run(async_start(args))
130
- except KeyboardInterrupt:
131
- pass
132
131
 
133
132
 
134
133
  async def async_start(args) -> None:
esphome/dashboard/dns.py CHANGED
@@ -3,15 +3,9 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  from contextlib import suppress
5
5
  from ipaddress import ip_address
6
- import sys
7
6
 
8
7
  from icmplib import NameLookupError, async_resolve
9
8
 
10
- if sys.version_info >= (3, 11):
11
- from asyncio import timeout as async_timeout
12
- else:
13
- from async_timeout import timeout as async_timeout
14
-
15
9
  RESOLVE_TIMEOUT = 3.0
16
10
 
17
11
 
@@ -20,9 +14,9 @@ async def _async_resolve_wrapper(hostname: str) -> list[str] | Exception:
20
14
  with suppress(ValueError):
21
15
  return [str(ip_address(hostname))]
22
16
  try:
23
- async with async_timeout(RESOLVE_TIMEOUT):
17
+ async with asyncio.timeout(RESOLVE_TIMEOUT):
24
18
  return await async_resolve(hostname)
25
- except (asyncio.TimeoutError, NameLookupError, UnicodeError) as ex:
19
+ except (TimeoutError, NameLookupError, UnicodeError) as ex:
26
20
  return ex
27
21
 
28
22
 
@@ -144,7 +144,7 @@ def websocket_class(cls):
144
144
  if not hasattr(cls, "_message_handlers"):
145
145
  cls._message_handlers = {}
146
146
 
147
- for _, method in cls.__dict__.items():
147
+ for method in cls.__dict__.values():
148
148
  if hasattr(method, "_message_handler"):
149
149
  cls._message_handlers[method._message_handler] = method
150
150
 
@@ -229,6 +229,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
229
229
  stdin=subprocess.PIPE,
230
230
  stdout=subprocess.PIPE,
231
231
  stderr=subprocess.STDOUT,
232
+ close_fds=False,
232
233
  )
233
234
  stdout_thread = threading.Thread(target=self._stdout_thread)
234
235
  stdout_thread.daemon = True
@@ -324,39 +325,53 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
324
325
  configuration = json_message["configuration"]
325
326
  config_file = settings.rel_path(configuration)
326
327
  port = json_message["port"]
328
+ addresses: list[str] = []
327
329
  if (
328
330
  port == "OTA" # pylint: disable=too-many-boolean-expressions
329
331
  and (entry := entries.get(config_file))
330
332
  and entry.loaded_integrations
331
333
  and "api" in entry.loaded_integrations
332
334
  ):
333
- if (mdns := dashboard.mdns_status) and (
334
- address_list := await mdns.async_resolve_host(entry.name)
335
- ):
336
- # Use the IP address if available but only
337
- # if the API is loaded and the device is online
338
- # since MQTT logging will not work otherwise
339
- port = sort_ip_addresses(address_list)[0]
340
- elif (
341
- entry.address
335
+ # First priority: entry.address AKA use_address
336
+ if (
337
+ (use_address := entry.address)
342
338
  and (
343
339
  address_list := await dashboard.dns_cache.async_resolve(
344
- entry.address, time.monotonic()
340
+ use_address, time.monotonic()
345
341
  )
346
342
  )
347
343
  and not isinstance(address_list, Exception)
348
344
  ):
349
- # If mdns is not available, try to use the DNS cache
350
- port = sort_ip_addresses(address_list)[0]
345
+ addresses.extend(sort_ip_addresses(address_list))
351
346
 
352
- return [
353
- *DASHBOARD_COMMAND,
354
- *args,
355
- config_file,
356
- "--device",
357
- port,
347
+ # Second priority: mDNS
348
+ if (
349
+ (mdns := dashboard.mdns_status)
350
+ and (address_list := await mdns.async_resolve_host(entry.name))
351
+ and (
352
+ new_addresses := [
353
+ addr for addr in address_list if addr not in addresses
354
+ ]
355
+ )
356
+ ):
357
+ # Use the IP address if available but only
358
+ # if the API is loaded and the device is online
359
+ # since MQTT logging will not work otherwise
360
+ addresses.extend(sort_ip_addresses(new_addresses))
361
+
362
+ if not addresses:
363
+ # If no address was found, use the port directly
364
+ # as otherwise they will get the chooser which
365
+ # does not work with the dashboard as there is no
366
+ # interactive way to get keyboard input
367
+ addresses = [port]
368
+
369
+ device_args: list[str] = [
370
+ arg for address in addresses for arg in ("--device", address)
358
371
  ]
359
372
 
373
+ return [*DASHBOARD_COMMAND, *args, config_file, *device_args]
374
+
360
375
 
361
376
  class EsphomeLogsHandler(EsphomePortCommandWebSocket):
362
377
  async def build_command(self, json_message: dict[str, Any]) -> list[str]:
esphome/espota2.py CHANGED
@@ -88,10 +88,7 @@ def recv_decode(sock, amount, decode=True):
88
88
 
89
89
 
90
90
  def receive_exactly(sock, amount, msg, expect, decode=True):
91
- if decode:
92
- data = []
93
- else:
94
- data = b""
91
+ data = [] if decode else b""
95
92
 
96
93
  try:
97
94
  data += recv_decode(sock, 1, decode=decode)
esphome/git.py CHANGED
@@ -17,7 +17,9 @@ _LOGGER = logging.getLogger(__name__)
17
17
  def run_git_command(cmd, cwd=None) -> str:
18
18
  _LOGGER.debug("Running git command: %s", " ".join(cmd))
19
19
  try:
20
- ret = subprocess.run(cmd, cwd=cwd, capture_output=True, check=False)
20
+ ret = subprocess.run(
21
+ cmd, cwd=cwd, capture_output=True, check=False, close_fds=False
22
+ )
21
23
  except FileNotFoundError as err:
22
24
  raise cv.Invalid(
23
25
  "git is not installed but required for external_components.\n"
esphome/helpers.py CHANGED
@@ -9,6 +9,8 @@ import re
9
9
  import tempfile
10
10
  from urllib.parse import urlparse
11
11
 
12
+ from esphome.const import __version__ as ESPHOME_VERSION
13
+
12
14
  _LOGGER = logging.getLogger(__name__)
13
15
 
14
16
  IS_MACOS = platform.system() == "Darwin"
@@ -96,9 +98,7 @@ def cpp_string_escape(string, encoding="utf-8"):
96
98
  def _should_escape(byte: int) -> bool:
97
99
  if not 32 <= byte < 127:
98
100
  return True
99
- if byte in (ord("\\"), ord('"')):
100
- return True
101
- return False
101
+ return byte in (ord("\\"), ord('"'))
102
102
 
103
103
  if isinstance(string, str):
104
104
  string = string.encode(encoding)
@@ -114,7 +114,9 @@ def cpp_string_escape(string, encoding="utf-8"):
114
114
  def run_system_command(*args):
115
115
  import subprocess
116
116
 
117
- with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
117
+ with subprocess.Popen(
118
+ args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False
119
+ ) as p:
118
120
  stdout, stderr = p.communicate()
119
121
  rc = p.returncode
120
122
  return rc, stdout, stderr
@@ -505,3 +507,20 @@ _DISALLOWED_CHARS = re.compile(r"[^a-zA-Z0-9-_]")
505
507
  def sanitize(value):
506
508
  """Same behaviour as `helpers.cpp` method `str_sanitize`."""
507
509
  return _DISALLOWED_CHARS.sub("_", value)
510
+
511
+
512
+ def docs_url(path: str) -> str:
513
+ """Return the URL to the documentation for a given path."""
514
+ # Local import to avoid circular import
515
+ from esphome.config_validation import Version
516
+
517
+ version = Version.parse(ESPHOME_VERSION)
518
+ if version.is_beta:
519
+ docs_format = "https://beta.esphome.io/{path}"
520
+ elif version.is_dev:
521
+ docs_format = "https://next.esphome.io/{path}"
522
+ else:
523
+ docs_format = "https://esphome.io/{path}"
524
+
525
+ path = path.removeprefix("/")
526
+ return docs_format.format(path=path)
esphome/log.py CHANGED
@@ -37,6 +37,8 @@ class AnsiStyle(Enum):
37
37
 
38
38
 
39
39
  def color(col: AnsiFore, msg: str, reset: bool = True) -> str:
40
+ if col == AnsiFore.KEEP:
41
+ return msg
40
42
  s = col.value + msg
41
43
  if reset and col:
42
44
  s += AnsiStyle.RESET_ALL.value
@@ -61,7 +63,7 @@ class ESPHomeLogFormatter(logging.Formatter):
61
63
  }.get(record.levelname, "")
62
64
  message = f"{prefix}{formatted}{AnsiStyle.RESET_ALL.value}"
63
65
  if CORE.dashboard:
64
- try:
66
+ try: # noqa: SIM105
65
67
  message = message.replace("\033", "\\033")
66
68
  except UnicodeEncodeError:
67
69
  pass
esphome/mqtt.py CHANGED
@@ -1,3 +1,4 @@
1
+ import contextlib
1
2
  from datetime import datetime
2
3
  import hashlib
3
4
  import json
@@ -35,7 +36,7 @@ _LOGGER = logging.getLogger(__name__)
35
36
 
36
37
 
37
38
  def config_from_env():
38
- config = {
39
+ return {
39
40
  CONF_MQTT: {
40
41
  CONF_USERNAME: get_str_env("ESPHOME_DASHBOARD_MQTT_USERNAME"),
41
42
  CONF_PASSWORD: get_str_env("ESPHOME_DASHBOARD_MQTT_PASSWORD"),
@@ -43,7 +44,6 @@ def config_from_env():
43
44
  CONF_PORT: get_int_env("ESPHOME_DASHBOARD_MQTT_PORT", 1883),
44
45
  },
45
46
  }
46
- return config
47
47
 
48
48
 
49
49
  def initialize(
@@ -52,10 +52,8 @@ def initialize(
52
52
  client = prepare(
53
53
  config, subscriptions, on_message, on_connect, username, password, client_id
54
54
  )
55
- try:
55
+ with contextlib.suppress(KeyboardInterrupt):
56
56
  client.loop_forever()
57
- except KeyboardInterrupt:
58
- pass
59
57
  return 0
60
58
 
61
59
 
esphome/platformio_api.py CHANGED
@@ -61,6 +61,7 @@ FILTER_PLATFORMIO_LINES = [
61
61
  r"Advanced Memory Usage is available via .*",
62
62
  r"Merged .* ELF section",
63
63
  r"esptool.py v.*",
64
+ r"esptool v.*",
64
65
  r"Checking size .*",
65
66
  r"Retrieving maximum program size .*",
66
67
  r"PLATFORM: .*",
@@ -131,9 +132,11 @@ def _load_idedata(config):
131
132
  temp_idedata = Path(CORE.relative_internal_path("idedata", f"{CORE.name}.json"))
132
133
 
133
134
  changed = False
134
- if not platformio_ini.is_file() or not temp_idedata.is_file():
135
- changed = True
136
- elif platformio_ini.stat().st_mtime >= temp_idedata.stat().st_mtime:
135
+ if (
136
+ not platformio_ini.is_file()
137
+ or not temp_idedata.is_file()
138
+ or platformio_ini.stat().st_mtime >= temp_idedata.stat().st_mtime
139
+ ):
137
140
  changed = True
138
141
 
139
142
  if not changed:
@@ -208,7 +211,7 @@ def _decode_pc(config, addr):
208
211
  return
209
212
  command = [idedata.addr2line_path, "-pfiaC", "-e", idedata.firmware_elf_path, addr]
210
213
  try:
211
- translation = subprocess.check_output(command).decode().strip()
214
+ translation = subprocess.check_output(command, close_fds=False).decode().strip()
212
215
  except Exception: # pylint: disable=broad-except
213
216
  _LOGGER.debug("Caught exception for command %s", command, exc_info=1)
214
217
  return
esphome/types.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """This helper module tracks commonly used types in the esphome python codebase."""
2
2
 
3
+ from typing import TypedDict
4
+
3
5
  from esphome.core import ID, EsphomeCore, Lambda
4
6
 
5
7
  ConfigFragmentType = (
@@ -16,3 +18,13 @@ ConfigFragmentType = (
16
18
  ConfigType = dict[str, ConfigFragmentType]
17
19
  CoreType = EsphomeCore
18
20
  ConfigPathType = str | int
21
+
22
+
23
+ class EntityMetadata(TypedDict):
24
+ """Metadata stored for each entity to help with duplicate detection."""
25
+
26
+ name: str
27
+ device_id: str
28
+ platform: str
29
+ entity_id: str
30
+ component: str
esphome/util.py CHANGED
@@ -6,6 +6,7 @@ from pathlib import Path
6
6
  import re
7
7
  import subprocess
8
8
  import sys
9
+ from typing import Any
9
10
 
10
11
  from esphome import const
11
12
 
@@ -59,7 +60,7 @@ def safe_print(message="", end="\n"):
59
60
  from esphome.core import CORE
60
61
 
61
62
  if CORE.dashboard:
62
- try:
63
+ try: # noqa: SIM105
63
64
  message = message.replace("\033", "\\033")
64
65
  except UnicodeEncodeError:
65
66
  pass
@@ -110,7 +111,7 @@ class RedirectText:
110
111
  def __getattr__(self, item):
111
112
  return getattr(self._out, item)
112
113
 
113
- def _write_color_replace(self, s):
114
+ def _write_color_replace(self, s: str | bytes) -> None:
114
115
  from esphome.core import CORE
115
116
 
116
117
  if CORE.dashboard:
@@ -121,7 +122,7 @@ class RedirectText:
121
122
  s = s.replace("\033", "\\033")
122
123
  self._out.write(s)
123
124
 
124
- def write(self, s):
125
+ def write(self, s: str | bytes) -> int:
125
126
  # s is usually a str already (self._out is of type TextIOWrapper)
126
127
  # However, s is sometimes also a bytes object in python3. Let's make sure it's a
127
128
  # str
@@ -223,7 +224,7 @@ def run_external_command(
223
224
  return retval
224
225
 
225
226
 
226
- def run_external_process(*cmd, **kwargs):
227
+ def run_external_process(*cmd: str, **kwargs: Any) -> int | str:
227
228
  full_cmd = " ".join(shlex_quote(x) for x in cmd)
228
229
  _LOGGER.debug("Running: %s", full_cmd)
229
230
  filter_lines = kwargs.get("filter_lines")
@@ -238,7 +239,12 @@ def run_external_process(*cmd, **kwargs):
238
239
 
239
240
  try:
240
241
  proc = subprocess.run(
241
- cmd, stdout=sub_stdout, stderr=sub_stderr, encoding="utf-8", check=False
242
+ cmd,
243
+ stdout=sub_stdout,
244
+ stderr=sub_stderr,
245
+ encoding="utf-8",
246
+ check=False,
247
+ close_fds=False,
242
248
  )
243
249
  return proc.stdout if capture_stdout else proc.returncode
244
250
  except KeyboardInterrupt: # pylint: disable=try-except-raise
@@ -266,7 +272,7 @@ class OrderedDict(collections.OrderedDict):
266
272
  return dict(self).__repr__()
267
273
 
268
274
 
269
- def list_yaml_files(folders):
275
+ def list_yaml_files(folders: list[str]) -> list[str]:
270
276
  files = filter_yaml_files(
271
277
  [os.path.join(folder, p) for folder in folders for p in os.listdir(folder)]
272
278
  )
@@ -274,7 +280,7 @@ def list_yaml_files(folders):
274
280
  return files
275
281
 
276
282
 
277
- def filter_yaml_files(files):
283
+ def filter_yaml_files(files: list[str]) -> list[str]:
278
284
  return [
279
285
  f
280
286
  for f in files
@@ -345,5 +351,11 @@ def get_esp32_arduino_flash_error_help() -> str | None:
345
351
  + "2. Clean build files and compile again\n"
346
352
  + "\n"
347
353
  + "Note: ESP-IDF uses less flash space and provides better performance.\n"
348
- + "Some Arduino-specific libraries may need alternatives.\n\n"
354
+ + "Some Arduino-specific libraries may need alternatives.\n"
355
+ + "\n"
356
+ + "For detailed migration instructions, see:\n"
357
+ + color(
358
+ AnsiFore.BLUE,
359
+ "https://esphome.io/guides/esp32_arduino_to_idf.html\n\n",
360
+ )
349
361
  )
@@ -225,9 +225,10 @@ class _Schema(vol.Schema):
225
225
  return ret
226
226
 
227
227
  schema = schemas[0]
228
+ extra_schemas = self._extra_schemas.copy()
229
+ if isinstance(schema, _Schema):
230
+ extra_schemas.extend(schema._extra_schemas)
228
231
  if isinstance(schema, vol.Schema):
229
232
  schema = schema.schema
230
233
  ret = super().extend(schema, extra=extra)
231
- return _Schema(
232
- ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas.copy()
233
- )
234
+ return _Schema(ret.schema, extra=ret.extra, extra_schemas=extra_schemas)
esphome/vscode.py CHANGED
@@ -81,8 +81,7 @@ def _print_file_read_event(path: str) -> None:
81
81
 
82
82
  def _request_and_get_stream_on_stdin(fname: str) -> StringIO:
83
83
  _print_file_read_event(fname)
84
- raw_yaml_stream = StringIO(_read_file_content_from_json_on_stdin())
85
- return raw_yaml_stream
84
+ return StringIO(_read_file_content_from_json_on_stdin())
86
85
 
87
86
 
88
87
  def _vscode_loader(fname: str) -> dict[str, Any]:
esphome/wizard.py CHANGED
@@ -116,10 +116,7 @@ def wizard_file(**kwargs):
116
116
  kwargs["fallback_name"] = ap_name
117
117
  kwargs["fallback_psk"] = "".join(random.choice(letters) for _ in range(12))
118
118
 
119
- if kwargs.get("friendly_name"):
120
- base = BASE_CONFIG_FRIENDLY
121
- else:
122
- base = BASE_CONFIG
119
+ base = BASE_CONFIG_FRIENDLY if kwargs.get("friendly_name") else BASE_CONFIG
123
120
 
124
121
  config = base.format(**kwargs)
125
122