esphome 2025.4.2__py3-none-any.whl → 2025.5.0b3__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 (440) hide show
  1. esphome/__main__.py +16 -14
  2. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  3. esphome/components/adc/__init__.py +51 -34
  4. esphome/components/airthings_wave_base/__init__.py +1 -1
  5. esphome/components/alarm_control_panel/__init__.py +37 -2
  6. esphome/components/am43/cover/__init__.py +4 -5
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  8. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  9. esphome/components/analog_threshold/binary_sensor.py +10 -8
  10. esphome/components/anova/climate.py +4 -5
  11. esphome/components/api/__init__.py +25 -8
  12. esphome/components/api/api_connection.cpp +81 -13
  13. esphome/components/api/api_connection.h +13 -1
  14. esphome/components/api/api_frame_helper.cpp +232 -177
  15. esphome/components/api/api_frame_helper.h +61 -8
  16. esphome/components/api/api_noise_context.h +13 -4
  17. esphome/components/api/api_pb2.cpp +1422 -1
  18. esphome/components/api/api_pb2.h +255 -1
  19. esphome/components/api/api_pb2_service.cpp +162 -49
  20. esphome/components/api/api_pb2_service.h +90 -51
  21. esphome/components/api/api_pb2_size.h +361 -0
  22. esphome/components/api/api_server.cpp +110 -34
  23. esphome/components/api/api_server.h +8 -0
  24. esphome/components/api/proto.h +86 -17
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/atm90e32/__init__.py +1 -0
  27. esphome/components/atm90e32/atm90e32.cpp +576 -199
  28. esphome/components/atm90e32/atm90e32.h +128 -31
  29. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  30. esphome/components/atm90e32/button/__init__.py +62 -10
  31. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  32. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  33. esphome/components/atm90e32/number/__init__.py +130 -0
  34. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  35. esphome/components/atm90e32/sensor.py +21 -4
  36. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  37. esphome/components/audio/__init__.py +96 -49
  38. esphome/components/audio/audio.h +48 -0
  39. esphome/components/audio/audio_decoder.cpp +1 -1
  40. esphome/components/audio/audio_resampler.cpp +2 -0
  41. esphome/components/audio/audio_resampler.h +1 -0
  42. esphome/components/ballu/climate.py +2 -9
  43. esphome/components/bang_bang/climate.py +5 -6
  44. esphome/components/bedjet/bedjet_hub.cpp +1 -0
  45. esphome/components/bedjet/climate/__init__.py +3 -8
  46. esphome/components/bedjet/fan/__init__.py +2 -11
  47. esphome/components/binary/fan/__init__.py +13 -16
  48. esphome/components/binary_sensor/__init__.py +13 -10
  49. esphome/components/bl0906/constants.h +16 -16
  50. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  51. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  52. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  54. esphome/components/button/__init__.py +11 -8
  55. esphome/components/canbus/canbus.cpp +3 -0
  56. esphome/components/canbus/canbus.h +16 -0
  57. esphome/components/ccs811/sensor.py +9 -6
  58. esphome/components/climate/__init__.py +35 -2
  59. esphome/components/climate/climate_mode.h +1 -1
  60. esphome/components/climate/climate_traits.h +63 -57
  61. esphome/components/climate_ir/__init__.py +57 -17
  62. esphome/components/climate_ir_lg/climate.py +2 -5
  63. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  64. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  65. esphome/components/color/__init__.py +2 -0
  66. esphome/components/const/__init__.py +5 -0
  67. esphome/components/coolix/climate.py +2 -9
  68. esphome/components/copy/cover/__init__.py +10 -9
  69. esphome/components/copy/fan/__init__.py +11 -9
  70. esphome/components/copy/lock/__init__.py +11 -9
  71. esphome/components/copy/text/__init__.py +9 -6
  72. esphome/components/cover/__init__.py +37 -2
  73. esphome/components/cse7766/cse7766.cpp +2 -1
  74. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  75. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  76. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  77. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  79. esphome/components/current_based/cover.py +37 -36
  80. esphome/components/current_based/current_based_cover.cpp +2 -1
  81. esphome/components/daikin/climate.py +2 -9
  82. esphome/components/daikin/daikin.cpp +15 -9
  83. esphome/components/daikin/daikin.h +5 -5
  84. esphome/components/daikin_arc/climate.py +2 -7
  85. esphome/components/daikin_brc/climate.py +3 -5
  86. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  87. esphome/components/dallas_temp/dallas_temp.h +0 -1
  88. esphome/components/daly_bms/daly_bms.cpp +2 -1
  89. esphome/components/debug/debug_component.cpp +6 -1
  90. esphome/components/debug/debug_component.h +6 -0
  91. esphome/components/debug/debug_esp32.cpp +109 -254
  92. esphome/components/debug/sensor.py +14 -0
  93. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  94. esphome/components/delonghi/climate.py +2 -9
  95. esphome/components/demo/__init__.py +18 -20
  96. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  97. esphome/components/dps310/sensor.py +6 -6
  98. esphome/components/ee895/sensor.py +9 -9
  99. esphome/components/emmeti/climate.py +2 -9
  100. esphome/components/endstop/cover.py +17 -16
  101. esphome/components/endstop/endstop_cover.cpp +2 -1
  102. esphome/components/ens160_base/__init__.py +12 -9
  103. esphome/components/esp32/__init__.py +60 -3
  104. esphome/components/esp32/core.cpp +11 -5
  105. esphome/components/esp32/gpio.cpp +86 -24
  106. esphome/components/esp32/gpio.py +15 -16
  107. esphome/components/esp32/gpio_esp32.py +1 -2
  108. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  109. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  110. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  111. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  112. esphome/components/esp32_ble/ble.cpp +1 -0
  113. esphome/components/esp32_ble/ble.h +5 -3
  114. esphome/components/esp32_ble/ble_advertising.cpp +2 -1
  115. esphome/components/esp32_ble/ble_advertising.h +1 -0
  116. esphome/components/esp32_ble_server/__init__.py +3 -0
  117. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  118. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  119. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  120. esphome/components/esp32_camera/esp32_camera.cpp +2 -1
  121. esphome/components/esp32_camera/esp32_camera.h +1 -1
  122. esphome/components/esp32_can/esp32_can.cpp +1 -1
  123. esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
  124. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  125. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  126. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  127. esphome/components/esp32_touch/esp32_touch.cpp +1 -1
  128. esphome/components/esp8266/gpio.cpp +69 -8
  129. esphome/components/ethernet/ethernet_component.cpp +1 -1
  130. esphome/components/event/__init__.py +13 -10
  131. esphome/components/factory_reset/switch/__init__.py +7 -21
  132. esphome/components/fan/__init__.py +52 -5
  133. esphome/components/fastled_base/__init__.py +1 -4
  134. esphome/components/fastled_base/fastled_light.cpp +1 -1
  135. esphome/components/feedback/cover.py +38 -33
  136. esphome/components/feedback/feedback_cover.cpp +2 -1
  137. esphome/components/fujitsu_general/climate.py +2 -9
  138. esphome/components/gcja5/gcja5.cpp +2 -1
  139. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  140. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  141. esphome/components/gpio_expander/cached_gpio.h +22 -7
  142. esphome/components/gps/__init__.py +47 -17
  143. esphome/components/gps/gps.cpp +42 -23
  144. esphome/components/gps/gps.h +17 -13
  145. esphome/components/graph/__init__.py +1 -2
  146. esphome/components/gree/climate.py +4 -6
  147. esphome/components/gree/gree.cpp +16 -2
  148. esphome/components/gree/gree.h +2 -2
  149. esphome/components/growatt_solar/growatt_solar.cpp +2 -1
  150. esphome/components/haier/climate.py +37 -34
  151. esphome/components/hbridge/fan/__init__.py +19 -17
  152. esphome/components/he60r/cover.py +4 -5
  153. esphome/components/heatpumpir/climate.py +3 -6
  154. esphome/components/hitachi_ac344/climate.py +2 -9
  155. esphome/components/hitachi_ac424/climate.py +2 -9
  156. esphome/components/hm3301/hm3301.h +1 -1
  157. esphome/components/hte501/sensor.py +6 -6
  158. esphome/components/http_request/__init__.py +39 -6
  159. esphome/components/http_request/http_request.cpp +20 -0
  160. esphome/components/http_request/http_request.h +57 -15
  161. esphome/components/http_request/http_request_arduino.cpp +22 -6
  162. esphome/components/http_request/http_request_arduino.h +4 -3
  163. esphome/components/http_request/http_request_host.cpp +141 -0
  164. esphome/components/http_request/http_request_host.h +37 -0
  165. esphome/components/http_request/http_request_idf.cpp +35 -3
  166. esphome/components/http_request/http_request_idf.h +10 -3
  167. esphome/components/http_request/httplib.h +9691 -0
  168. esphome/components/http_request/update/__init__.py +11 -8
  169. esphome/components/hyt271/sensor.py +6 -6
  170. esphome/components/i2c/i2c.h +4 -0
  171. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  172. esphome/components/i2s_audio/__init__.py +131 -22
  173. esphome/components/i2s_audio/i2s_audio.h +44 -4
  174. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  175. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  176. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  177. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  178. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  179. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  180. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  181. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  182. esphome/components/image/__init__.py +37 -17
  183. esphome/components/image/image.cpp +25 -8
  184. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  185. esphome/components/key_collector/__init__.py +35 -0
  186. esphome/components/key_collector/key_collector.cpp +8 -0
  187. esphome/components/key_collector/key_collector.h +10 -0
  188. esphome/components/kuntze/kuntze.cpp +2 -1
  189. esphome/components/ld2410/ld2410.h +1 -1
  190. esphome/components/ld2450/ld2450.h +1 -1
  191. esphome/components/light/__init__.py +57 -0
  192. esphome/components/lock/__init__.py +51 -4
  193. esphome/components/lock/automation.h +2 -13
  194. esphome/components/logger/__init__.py +22 -0
  195. esphome/components/logger/logger.cpp +154 -103
  196. esphome/components/logger/logger.h +211 -36
  197. esphome/components/logger/task_log_buffer.cpp +138 -0
  198. esphome/components/logger/task_log_buffer.h +69 -0
  199. esphome/components/lvgl/__init__.py +13 -5
  200. esphome/components/lvgl/automation.py +50 -1
  201. esphome/components/lvgl/defines.py +0 -1
  202. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  203. esphome/components/lvgl/text/__init__.py +1 -2
  204. esphome/components/mapping/__init__.py +134 -0
  205. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
  206. esphome/components/max7219digit/max7219digit.cpp +28 -27
  207. esphome/components/mdns/__init__.py +11 -5
  208. esphome/components/mdns/mdns_component.cpp +11 -5
  209. esphome/components/mdns/mdns_component.h +3 -2
  210. esphome/components/mdns/mdns_esp32.cpp +4 -3
  211. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  212. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  213. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  214. esphome/components/media_player/__init__.py +33 -1
  215. esphome/components/mhz19/sensor.py +11 -7
  216. esphome/components/micro_wake_word/__init__.py +99 -31
  217. esphome/components/micro_wake_word/automation.h +54 -0
  218. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  219. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  220. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  221. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  222. esphome/components/micro_wake_word/streaming_model.h +85 -13
  223. esphome/components/microphone/__init__.py +139 -9
  224. esphome/components/microphone/automation.h +14 -2
  225. esphome/components/microphone/microphone.cpp +21 -0
  226. esphome/components/microphone/microphone.h +14 -5
  227. esphome/components/microphone/microphone_source.cpp +95 -0
  228. esphome/components/microphone/microphone_source.h +80 -0
  229. esphome/components/mics_4514/sensor.py +25 -14
  230. esphome/components/midea/climate.py +3 -4
  231. esphome/components/midea_ir/climate.py +3 -5
  232. esphome/components/mipi_spi/__init__.py +15 -0
  233. esphome/components/mipi_spi/display.py +474 -0
  234. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  235. esphome/components/mipi_spi/mipi_spi.h +171 -0
  236. esphome/components/mipi_spi/models/__init__.py +65 -0
  237. esphome/components/mipi_spi/models/amoled.py +72 -0
  238. esphome/components/mipi_spi/models/commands.py +82 -0
  239. esphome/components/mipi_spi/models/cyd.py +10 -0
  240. esphome/components/mipi_spi/models/ili.py +749 -0
  241. esphome/components/mipi_spi/models/jc.py +260 -0
  242. esphome/components/mipi_spi/models/lanbon.py +15 -0
  243. esphome/components/mipi_spi/models/lilygo.py +60 -0
  244. esphome/components/mipi_spi/models/waveshare.py +139 -0
  245. esphome/components/mitsubishi/climate.py +2 -5
  246. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  247. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  248. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  249. esphome/components/mlx90393/sensor.py +5 -0
  250. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  251. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  252. esphome/components/modbus/modbus.cpp +2 -1
  253. esphome/components/mqtt/__init__.py +1 -1
  254. esphome/components/mqtt/mqtt_client.cpp +6 -2
  255. esphome/components/mqtt/mqtt_const.h +4 -0
  256. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  257. esphome/components/mqtt/mqtt_fan.h +2 -0
  258. esphome/components/ms5611/sensor.py +6 -6
  259. esphome/components/ms8607/sensor.py +3 -3
  260. esphome/components/network/__init__.py +1 -1
  261. esphome/components/nextion/base_component.py +17 -16
  262. esphome/components/nextion/display.py +11 -2
  263. esphome/components/nextion/nextion.cpp +39 -1
  264. esphome/components/nextion/nextion.h +50 -0
  265. esphome/components/noblex/climate.py +2 -9
  266. esphome/components/number/__init__.py +12 -9
  267. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  268. esphome/components/one_wire/one_wire_bus.h +14 -8
  269. esphome/components/online_image/bmp_image.cpp +48 -11
  270. esphome/components/online_image/bmp_image.h +2 -0
  271. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  272. esphome/components/opentherm/number/__init__.py +11 -20
  273. esphome/components/opentherm/sensor/__init__.py +3 -3
  274. esphome/components/opentherm/switch/__init__.py +3 -5
  275. esphome/components/output/lock/__init__.py +11 -9
  276. esphome/components/packages/__init__.py +33 -31
  277. esphome/components/packet_transport/__init__.py +201 -0
  278. esphome/components/packet_transport/binary_sensor.py +19 -0
  279. esphome/components/packet_transport/packet_transport.cpp +534 -0
  280. esphome/components/packet_transport/packet_transport.h +154 -0
  281. esphome/components/packet_transport/sensor.py +19 -0
  282. esphome/components/pca9685/pca9685_output.cpp +2 -1
  283. esphome/components/pid/climate.py +2 -4
  284. esphome/components/pm2005/__init__.py +1 -0
  285. esphome/components/pm2005/pm2005.cpp +123 -0
  286. esphome/components/pm2005/pm2005.h +46 -0
  287. esphome/components/pm2005/sensor.py +86 -0
  288. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  289. esphome/components/pmsa003i/pmsa003i.h +25 -25
  290. esphome/components/pmsx003/pmsx003.cpp +195 -230
  291. esphome/components/pmsx003/pmsx003.h +51 -33
  292. esphome/components/pmsx003/sensor.py +21 -11
  293. esphome/components/pn7150/pn7150.h +2 -2
  294. esphome/components/pn7160/pn7160.h +2 -2
  295. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  296. esphome/components/prometheus/prometheus_handler.h +17 -0
  297. esphome/components/psram/__init__.py +7 -5
  298. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  299. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  300. esphome/components/pzem004t/pzem004t.cpp +2 -1
  301. esphome/components/qspi_dbi/__init__.py +0 -1
  302. esphome/components/qspi_dbi/display.py +2 -1
  303. esphome/components/qspi_dbi/models.py +1 -2
  304. esphome/components/remote_base/__init__.py +91 -0
  305. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  306. esphome/components/remote_base/beo4_protocol.h +43 -0
  307. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  308. esphome/components/remote_base/gobox_protocol.h +54 -0
  309. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  310. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  311. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  312. esphome/components/rf_bridge/rf_bridge.cpp +2 -1
  313. esphome/components/scd30/sensor.py +2 -3
  314. esphome/components/scd4x/sensor.py +4 -5
  315. esphome/components/sdp3x/sensor.py +2 -1
  316. esphome/components/sds011/sds011.cpp +2 -1
  317. esphome/components/select/__init__.py +19 -20
  318. esphome/components/sen5x/sen5x.cpp +55 -36
  319. esphome/components/sen5x/sensor.py +1 -1
  320. esphome/components/senseair/sensor.py +3 -3
  321. esphome/components/sensor/__init__.py +158 -14
  322. esphome/components/sensor/filter.cpp +23 -0
  323. esphome/components/sensor/filter.h +22 -0
  324. esphome/components/sgp30/sensor.py +14 -16
  325. esphome/components/sgp4x/sensor.py +1 -1
  326. esphome/components/sht4x/sht4x.cpp +43 -22
  327. esphome/components/sht4x/sht4x.h +1 -1
  328. esphome/components/shtcx/sensor.py +6 -6
  329. esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
  330. esphome/components/sml/text_sensor/__init__.py +4 -6
  331. esphome/components/sound_level/__init__.py +0 -0
  332. esphome/components/sound_level/sensor.py +97 -0
  333. esphome/components/sound_level/sound_level.cpp +194 -0
  334. esphome/components/sound_level/sound_level.h +73 -0
  335. esphome/components/speaker/media_player/__init__.py +4 -8
  336. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  337. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  338. esphome/components/speaker/speaker.h +4 -7
  339. esphome/components/speed/fan/__init__.py +17 -16
  340. esphome/components/spi/spi.h +11 -1
  341. esphome/components/sprinkler/__init__.py +18 -19
  342. esphome/components/sprinkler/sprinkler.cpp +6 -5
  343. esphome/components/switch/__init__.py +32 -42
  344. esphome/components/syslog/__init__.py +41 -0
  345. esphome/components/syslog/esphome_syslog.cpp +49 -0
  346. esphome/components/syslog/esphome_syslog.h +27 -0
  347. esphome/components/t6615/sensor.py +3 -3
  348. esphome/components/t6615/t6615.cpp +2 -1
  349. esphome/components/tca9555/tca9555.cpp +11 -6
  350. esphome/components/tcl112/climate.py +2 -9
  351. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  352. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  353. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  354. esphome/components/template/cover/__init__.py +27 -21
  355. esphome/components/template/fan/__init__.py +14 -12
  356. esphome/components/template/lock/__init__.py +20 -25
  357. esphome/components/template/lock/automation.h +18 -0
  358. esphome/components/template/text/__init__.py +4 -3
  359. esphome/components/template/valve/__init__.py +32 -21
  360. esphome/components/template/valve/automation.h +24 -0
  361. esphome/components/text/__init__.py +32 -1
  362. esphome/components/text_sensor/__init__.py +24 -29
  363. esphome/components/thermostat/climate.py +5 -5
  364. esphome/components/time_based/cover.py +17 -16
  365. esphome/components/time_based/time_based_cover.cpp +2 -1
  366. esphome/components/tm1638/switch/__init__.py +10 -7
  367. esphome/components/tormatic/cover.py +4 -5
  368. esphome/components/toshiba/climate.py +3 -5
  369. esphome/components/touchscreen/touchscreen.cpp +3 -1
  370. esphome/components/tuya/climate/__init__.py +5 -6
  371. esphome/components/tuya/cover/__init__.py +6 -11
  372. esphome/components/tuya/select/__init__.py +15 -5
  373. esphome/components/tuya/select/tuya_select.cpp +6 -1
  374. esphome/components/tuya/select/tuya_select.h +5 -1
  375. esphome/components/uart/packet_transport/__init__.py +20 -0
  376. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  377. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  378. esphome/components/uart/switch/uart_switch.cpp +2 -1
  379. esphome/components/udp/__init__.py +126 -128
  380. esphome/components/udp/automation.h +40 -0
  381. esphome/components/udp/binary_sensor.py +3 -25
  382. esphome/components/udp/packet_transport/__init__.py +29 -0
  383. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  384. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  385. esphome/components/udp/sensor.py +3 -25
  386. esphome/components/udp/udp_component.cpp +26 -470
  387. esphome/components/udp/udp_component.h +21 -128
  388. esphome/components/update/__init__.py +31 -1
  389. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  390. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
  391. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  392. esphome/components/uptime/text_sensor/__init__.py +47 -7
  393. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  394. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  395. esphome/components/valve/__init__.py +34 -3
  396. esphome/components/valve/automation.h +1 -19
  397. esphome/components/vl53l0x/sensor.py +11 -0
  398. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  399. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  400. esphome/components/voice_assistant/__init__.py +36 -10
  401. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  402. esphome/components/voice_assistant/voice_assistant.h +26 -25
  403. esphome/components/waveshare_epaper/display.py +6 -0
  404. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  405. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  406. esphome/components/whirlpool/climate.py +3 -5
  407. esphome/components/whynter/climate.py +3 -5
  408. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  409. esphome/components/yashima/climate.py +6 -6
  410. esphome/components/zhlt01/climate.py +2 -7
  411. esphome/config.py +13 -13
  412. esphome/config_validation.py +38 -58
  413. esphome/const.py +15 -1
  414. esphome/core/__init__.py +2 -0
  415. esphome/core/application.cpp +23 -10
  416. esphome/core/application.h +9 -1
  417. esphome/core/automation.h +4 -3
  418. esphome/core/component.cpp +28 -7
  419. esphome/core/component.h +10 -1
  420. esphome/core/defines.h +23 -17
  421. esphome/core/macros.h +4 -0
  422. esphome/core/scheduler.cpp +7 -1
  423. esphome/cpp_generator.py +6 -2
  424. esphome/dashboard/web_server.py +3 -3
  425. esphome/helpers.py +39 -0
  426. esphome/loader.py +4 -0
  427. esphome/log.py +15 -19
  428. esphome/mqtt.py +23 -10
  429. esphome/platformio_api.py +1 -1
  430. esphome/schema_extractors.py +0 -1
  431. esphome/voluptuous_schema.py +3 -1
  432. esphome/vscode.py +15 -0
  433. esphome/wizard.py +47 -37
  434. esphome/zeroconf.py +7 -3
  435. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +10 -11
  436. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +440 -380
  437. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +1 -1
  438. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
  439. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
  440. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -2,7 +2,7 @@ import esphome.codegen as cg
2
2
  from esphome.components import climate, remote_transmitter, sensor
3
3
  from esphome.components.remote_base import CONF_TRANSMITTER_ID
4
4
  import esphome.config_validation as cv
5
- from esphome.const import CONF_ID, CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT
5
+ from esphome.const import CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT
6
6
 
7
7
  AUTO_LOAD = ["sensor"]
8
8
 
@@ -10,9 +10,9 @@ yashima_ns = cg.esphome_ns.namespace("yashima")
10
10
  YashimaClimate = yashima_ns.class_("YashimaClimate", climate.Climate, cg.Component)
11
11
 
12
12
  CONFIG_SCHEMA = cv.All(
13
- climate.CLIMATE_SCHEMA.extend(
13
+ climate.climate_schema(YashimaClimate)
14
+ .extend(
14
15
  {
15
- cv.GenerateID(): cv.declare_id(YashimaClimate),
16
16
  cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(
17
17
  remote_transmitter.RemoteTransmitterComponent
18
18
  ),
@@ -20,14 +20,14 @@ CONFIG_SCHEMA = cv.All(
20
20
  cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
21
21
  cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
22
22
  }
23
- ).extend(cv.COMPONENT_SCHEMA)
23
+ )
24
+ .extend(cv.COMPONENT_SCHEMA)
24
25
  )
25
26
 
26
27
 
27
28
  async def to_code(config):
28
- var = cg.new_Pvariable(config[CONF_ID])
29
+ var = await climate.new_climate(config)
29
30
  await cg.register_component(var, config)
30
- await climate.register_climate(var, config)
31
31
 
32
32
  cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
33
33
  cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
@@ -1,7 +1,5 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import climate_ir
3
- import esphome.config_validation as cv
4
- from esphome.const import CONF_ID
5
3
 
6
4
  AUTO_LOAD = ["climate_ir"]
7
5
  CODEOWNERS = ["@cfeenstra1024"]
@@ -9,11 +7,8 @@ CODEOWNERS = ["@cfeenstra1024"]
9
7
  zhlt01_ns = cg.esphome_ns.namespace("zhlt01")
10
8
  ZHLT01Climate = zhlt01_ns.class_("ZHLT01Climate", climate_ir.ClimateIR)
11
9
 
12
- CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
13
- {cv.GenerateID(): cv.declare_id(ZHLT01Climate)}
14
- )
10
+ CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(ZHLT01Climate)
15
11
 
16
12
 
17
13
  async def to_code(config):
18
- var = cg.new_Pvariable(config[CONF_ID])
19
- await climate_ir.register_climate_ir(var, config)
14
+ await climate_ir.new_climate_ir(config)
esphome/config.py CHANGED
@@ -28,7 +28,7 @@ import esphome.core.config as core_config
28
28
  import esphome.final_validate as fv
29
29
  from esphome.helpers import indent
30
30
  from esphome.loader import ComponentManifest, get_component, get_platform
31
- from esphome.log import Fore, color
31
+ from esphome.log import AnsiFore, color
32
32
  from esphome.types import ConfigFragmentType, ConfigType
33
33
  from esphome.util import OrderedDict, safe_print
34
34
  from esphome.voluptuous_schema import ExtraKeysInvalid
@@ -959,7 +959,7 @@ def line_info(config, path, highlight=True):
959
959
  if obj:
960
960
  mark = obj.start_mark
961
961
  source = f"[source {mark.document}:{mark.line + 1}]"
962
- return color(Fore.CYAN, source)
962
+ return color(AnsiFore.CYAN, source)
963
963
  return "None"
964
964
 
965
965
 
@@ -983,7 +983,7 @@ def dump_dict(
983
983
  if at_root:
984
984
  error = config.get_error_for_path(path)
985
985
  if error is not None:
986
- ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n"
986
+ ret += f"\n{color(AnsiFore.BOLD_RED, _format_vol_invalid(error, config))}\n"
987
987
 
988
988
  if isinstance(conf, (list, tuple)):
989
989
  multiline = True
@@ -995,11 +995,11 @@ def dump_dict(
995
995
  path_ = path + [i]
996
996
  error = config.get_error_for_path(path_)
997
997
  if error is not None:
998
- ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n"
998
+ ret += f"\n{color(AnsiFore.BOLD_RED, _format_vol_invalid(error, config))}\n"
999
999
 
1000
1000
  sep = "- "
1001
1001
  if config.is_in_error_path(path_):
1002
- sep = color(Fore.RED, sep)
1002
+ sep = color(AnsiFore.RED, sep)
1003
1003
  msg, _ = dump_dict(config, path_, at_root=False)
1004
1004
  msg = indent(msg)
1005
1005
  inf = line_info(config, path_, highlight=config.is_in_error_path(path_))
@@ -1018,11 +1018,11 @@ def dump_dict(
1018
1018
  path_ = path + [k]
1019
1019
  error = config.get_error_for_path(path_)
1020
1020
  if error is not None:
1021
- ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n"
1021
+ ret += f"\n{color(AnsiFore.BOLD_RED, _format_vol_invalid(error, config))}\n"
1022
1022
 
1023
1023
  st = f"{k}: "
1024
1024
  if config.is_in_error_path(path_):
1025
- st = color(Fore.RED, st)
1025
+ st = color(AnsiFore.RED, st)
1026
1026
  msg, m = dump_dict(config, path_, at_root=False)
1027
1027
 
1028
1028
  inf = line_info(config, path_, highlight=config.is_in_error_path(path_))
@@ -1044,7 +1044,7 @@ def dump_dict(
1044
1044
  if len(conf) > 80:
1045
1045
  conf = f"|-\n{indent(conf)}"
1046
1046
  error = config.get_error_for_path(path)
1047
- col = Fore.BOLD_RED if error else Fore.KEEP
1047
+ col = AnsiFore.BOLD_RED if error else AnsiFore.KEEP
1048
1048
  ret += color(col, str(conf))
1049
1049
  elif isinstance(conf, core.Lambda):
1050
1050
  if is_secret(conf):
@@ -1052,13 +1052,13 @@ def dump_dict(
1052
1052
 
1053
1053
  conf = f"!lambda |-\n{indent(str(conf.value))}"
1054
1054
  error = config.get_error_for_path(path)
1055
- col = Fore.BOLD_RED if error else Fore.KEEP
1055
+ col = AnsiFore.BOLD_RED if error else AnsiFore.KEEP
1056
1056
  ret += color(col, conf)
1057
1057
  elif conf is None:
1058
1058
  pass
1059
1059
  else:
1060
1060
  error = config.get_error_for_path(path)
1061
- col = Fore.BOLD_RED if error else Fore.KEEP
1061
+ col = AnsiFore.BOLD_RED if error else AnsiFore.KEEP
1062
1062
  ret += color(col, str(conf))
1063
1063
  multiline = "\n" in ret
1064
1064
 
@@ -1100,13 +1100,13 @@ def read_config(command_line_substitutions):
1100
1100
  if not CORE.verbose:
1101
1101
  res = strip_default_ids(res)
1102
1102
 
1103
- safe_print(color(Fore.BOLD_RED, "Failed config"))
1103
+ safe_print(color(AnsiFore.BOLD_RED, "Failed config"))
1104
1104
  safe_print("")
1105
1105
  for path, domain in res.output_paths:
1106
1106
  if not res.is_in_error_path(path):
1107
1107
  continue
1108
1108
 
1109
- errstr = color(Fore.BOLD_RED, f"{domain}:")
1109
+ errstr = color(AnsiFore.BOLD_RED, f"{domain}:")
1110
1110
  errline = line_info(res, path)
1111
1111
  if errline:
1112
1112
  errstr += f" {errline}"
@@ -1121,7 +1121,7 @@ def read_config(command_line_substitutions):
1121
1121
  safe_print(indent("\n".join(split_dump[:i])))
1122
1122
 
1123
1123
  for err in res.errors:
1124
- safe_print(color(Fore.BOLD_RED, err.msg))
1124
+ safe_print(color(AnsiFore.BOLD_RED, err.msg))
1125
1125
  safe_print("")
1126
1126
 
1127
1127
  return None
@@ -56,7 +56,6 @@ from esphome.const import (
56
56
  KEY_CORE,
57
57
  KEY_FRAMEWORK_VERSION,
58
58
  KEY_TARGET_FRAMEWORK,
59
- KEY_TARGET_PLATFORM,
60
59
  PLATFORM_ESP32,
61
60
  PLATFORM_ESP8266,
62
61
  PLATFORM_RP2040,
@@ -117,7 +116,7 @@ RequiredFieldInvalid = vol.RequiredFieldInvalid
117
116
  ROOT_CONFIG_PATH = object()
118
117
 
119
118
  RESERVED_IDS = [
120
- # C++ keywords http://en.cppreference.com/w/cpp/keyword
119
+ # C++ keywords https://en.cppreference.com/w/cpp/keyword
121
120
  "alarm",
122
121
  "alignas",
123
122
  "alignof",
@@ -1942,70 +1941,28 @@ def platformio_version_constraint(value):
1942
1941
 
1943
1942
  def require_framework_version(
1944
1943
  *,
1945
- esp_idf=None,
1946
- esp32_arduino=None,
1947
- esp8266_arduino=None,
1948
- rp2040_arduino=None,
1949
- bk72xx_libretiny=None,
1950
- host=None,
1951
1944
  max_version=False,
1952
1945
  extra_message=None,
1946
+ **kwargs,
1953
1947
  ):
1954
1948
  def validator(value):
1955
1949
  core_data = CORE.data[KEY_CORE]
1956
1950
  framework = core_data[KEY_TARGET_FRAMEWORK]
1957
- if framework == "esp-idf":
1958
- if esp_idf is None:
1959
- msg = "This feature is incompatible with esp-idf"
1960
- if extra_message:
1961
- msg += f". {extra_message}"
1962
- raise Invalid(msg)
1963
- required = esp_idf
1964
- elif CORE.is_bk72xx and framework == "arduino":
1965
- if bk72xx_libretiny is None:
1966
- msg = "This feature is incompatible with BK72XX"
1967
- if extra_message:
1968
- msg += f". {extra_message}"
1969
- raise Invalid(msg)
1970
- required = bk72xx_libretiny
1971
- elif CORE.is_esp32 and framework == "arduino":
1972
- if esp32_arduino is None:
1973
- msg = "This feature is incompatible with ESP32 using arduino framework"
1974
- if extra_message:
1975
- msg += f". {extra_message}"
1976
- raise Invalid(msg)
1977
- required = esp32_arduino
1978
- elif CORE.is_esp8266 and framework == "arduino":
1979
- if esp8266_arduino is None:
1980
- msg = "This feature is incompatible with ESP8266"
1981
- if extra_message:
1982
- msg += f". {extra_message}"
1983
- raise Invalid(msg)
1984
- required = esp8266_arduino
1985
- elif CORE.is_rp2040 and framework == "arduino":
1986
- if rp2040_arduino is None:
1987
- msg = "This feature is incompatible with RP2040"
1988
- if extra_message:
1989
- msg += f". {extra_message}"
1990
- raise Invalid(msg)
1991
- required = rp2040_arduino
1992
- elif CORE.is_host and framework == "host":
1993
- if host is None:
1994
- msg = "This feature is incompatible with host platform"
1995
- if extra_message:
1996
- msg += f". {extra_message}"
1997
- raise Invalid(msg)
1998
- required = host
1951
+
1952
+ if CORE.is_host and framework == "host":
1953
+ key = "host"
1954
+ elif framework == "esp-idf":
1955
+ key = "esp_idf"
1999
1956
  else:
2000
- raise Invalid(
2001
- f"""
2002
- Internal Error: require_framework_version does not support this platform configuration
2003
- platform: {core_data[KEY_TARGET_PLATFORM]}
2004
- framework: {framework}
1957
+ key = CORE.target_platform + "_" + framework
2005
1958
 
2006
- Please report this issue on GitHub -> https://github.com/esphome/issues/issues/new?template=bug_report.yml.
2007
- """
2008
- )
1959
+ if key not in kwargs:
1960
+ msg = f"This feature is incompatible with {CORE.target_platform.upper()} using {framework} framework"
1961
+ if extra_message:
1962
+ msg += f". {extra_message}"
1963
+ raise Invalid(msg)
1964
+
1965
+ required = kwargs[key]
2009
1966
 
2010
1967
  if max_version:
2011
1968
  if core_data[KEY_FRAMEWORK_VERSION] > required:
@@ -2115,3 +2072,26 @@ def rename_key(old_key, new_key):
2115
2072
  return config
2116
2073
 
2117
2074
  return validator
2075
+
2076
+
2077
+ # Remove before 2025.11.0
2078
+ def deprecated_schema_constant(entity_type: str):
2079
+ def validator(config):
2080
+ type: str = "unknown"
2081
+ if (id := config.get(CONF_ID)) is not None and isinstance(id, core.ID):
2082
+ type = str(id.type).split("::", maxsplit=1)[0]
2083
+ _LOGGER.warning(
2084
+ "Using `%s.%s_SCHEMA` is deprecated and will be removed in ESPHome 2025.11.0. "
2085
+ "Please use `%s.%s_schema(...)` instead. "
2086
+ "If you are seeing this, report an issue to the external_component author and ask them to update it. "
2087
+ "https://developers.esphome.io/blog/2025/05/14/_schema-deprecations/. "
2088
+ "Component using this schema: %s",
2089
+ entity_type,
2090
+ entity_type.upper(),
2091
+ entity_type,
2092
+ entity_type,
2093
+ type,
2094
+ )
2095
+ return config
2096
+
2097
+ return validator
esphome/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants used by esphome."""
2
2
 
3
- __version__ = "2025.4.2"
3
+ __version__ = "2025.5.0b3"
4
4
 
5
5
  ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
6
6
  VALID_SUBSTITUTIONS_CHARACTERS = (
@@ -45,6 +45,8 @@ CONF_ALLOW_OTHER_USES = "allow_other_uses"
45
45
  CONF_ALPHA = "alpha"
46
46
  CONF_ALTITUDE = "altitude"
47
47
  CONF_AMBIENT_LIGHT = "ambient_light"
48
+ CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation"
49
+ CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE = "ambient_pressure_compensation_source"
48
50
  CONF_AMMONIA = "ammonia"
49
51
  CONF_ANALOG = "analog"
50
52
  CONF_AND = "and"
@@ -63,6 +65,7 @@ CONF_AUTH = "auth"
63
65
  CONF_AUTO_CLEAR_ENABLED = "auto_clear_enabled"
64
66
  CONF_AUTO_MODE = "auto_mode"
65
67
  CONF_AUTOCONF = "autoconf"
68
+ CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration"
66
69
  CONF_AUTOMATION_ID = "automation_id"
67
70
  CONF_AVAILABILITY = "availability"
68
71
  CONF_AWAY = "away"
@@ -157,6 +160,7 @@ CONF_CONDITION = "condition"
157
160
  CONF_CONDITION_ID = "condition_id"
158
161
  CONF_CONDUCTIVITY = "conductivity"
159
162
  CONF_CONSTANT_BRIGHTNESS = "constant_brightness"
163
+ CONF_CONTINUOUS = "continuous"
160
164
  CONF_CONTRAST = "contrast"
161
165
  CONF_COOL_ACTION = "cool_action"
162
166
  CONF_COOL_DEADBAND = "cool_deadband"
@@ -217,7 +221,9 @@ CONF_DIMENSIONS = "dimensions"
217
221
  CONF_DIO_PIN = "dio_pin"
218
222
  CONF_DIR_PIN = "dir_pin"
219
223
  CONF_DIRECTION = "direction"
224
+ CONF_DIRECTION_COMMAND_TOPIC = "direction_command_topic"
220
225
  CONF_DIRECTION_OUTPUT = "direction_output"
226
+ CONF_DIRECTION_STATE_TOPIC = "direction_state_topic"
221
227
  CONF_DISABLE_CRC = "disable_crc"
222
228
  CONF_DISABLED = "disabled"
223
229
  CONF_DISABLED_BY_DEFAULT = "disabled_by_default"
@@ -330,6 +336,7 @@ CONF_FULL_SPECTRUM = "full_spectrum"
330
336
  CONF_FULL_SPECTRUM_COUNTS = "full_spectrum_counts"
331
337
  CONF_FULL_UPDATE_EVERY = "full_update_every"
332
338
  CONF_GAIN = "gain"
339
+ CONF_GAIN_FACTOR = "gain_factor"
333
340
  CONF_GAMMA_CORRECT = "gamma_correct"
334
341
  CONF_GAS_RESISTANCE = "gas_resistance"
335
342
  CONF_GATEWAY = "gateway"
@@ -401,6 +408,7 @@ CONF_INITIAL_OPTION = "initial_option"
401
408
  CONF_INITIAL_STATE = "initial_state"
402
409
  CONF_INITIAL_VALUE = "initial_value"
403
410
  CONF_INPUT = "input"
411
+ CONF_INT_DATAPOINT = "int_datapoint"
404
412
  CONF_INTEGRATION_TIME = "integration_time"
405
413
  CONF_INTENSITY = "intensity"
406
414
  CONF_INTERLOCK = "interlock"
@@ -477,6 +485,7 @@ CONF_MAX_VALUE = "max_value"
477
485
  CONF_MAX_VOLTAGE = "max_voltage"
478
486
  CONF_MDNS = "mdns"
479
487
  CONF_MEASUREMENT_DURATION = "measurement_duration"
488
+ CONF_MEASUREMENT_MODE = "measurement_mode"
480
489
  CONF_MEASUREMENT_SEQUENCE_NUMBER = "measurement_sequence_number"
481
490
  CONF_MEDIA_PLAYER = "media_player"
482
491
  CONF_MEDIUM = "medium"
@@ -795,6 +804,7 @@ CONF_SHUTDOWN_MESSAGE = "shutdown_message"
795
804
  CONF_SIGNAL_STRENGTH = "signal_strength"
796
805
  CONF_SINGLE_LIGHT_ID = "single_light_id"
797
806
  CONF_SIZE = "size"
807
+ CONF_SKIP_CERT_CN_CHECK = "skip_cert_cn_check"
798
808
  CONF_SLEEP_DURATION = "sleep_duration"
799
809
  CONF_SLEEP_PIN = "sleep_pin"
800
810
  CONF_SLEEP_WHEN_DONE = "sleep_when_done"
@@ -891,6 +901,8 @@ CONF_TIMES = "times"
891
901
  CONF_TIMEZONE = "timezone"
892
902
  CONF_TIMING = "timing"
893
903
  CONF_TO = "to"
904
+ CONF_TO_NTC_RESISTANCE = "to_ntc_resistance"
905
+ CONF_TO_NTC_TEMPERATURE = "to_ntc_temperature"
894
906
  CONF_TOLERANCE = "tolerance"
895
907
  CONF_TOPIC = "topic"
896
908
  CONF_TOPIC_PREFIX = "topic_prefix"
@@ -1080,6 +1092,7 @@ UNIT_KILOWATT = "kW"
1080
1092
  UNIT_KILOWATT_HOURS = "kWh"
1081
1093
  UNIT_LITRE = "L"
1082
1094
  UNIT_LUX = "lx"
1095
+ UNIT_MEGAJOULE = "MJ"
1083
1096
  UNIT_METER = "m"
1084
1097
  UNIT_METER_PER_SECOND_SQUARED = "m/s²"
1085
1098
  UNIT_MICROAMP = "µA"
@@ -1093,6 +1106,7 @@ UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³"
1093
1106
  UNIT_MILLIMETER = "mm"
1094
1107
  UNIT_MILLISECOND = "ms"
1095
1108
  UNIT_MILLISIEMENS_PER_CENTIMETER = "mS/cm"
1109
+ UNIT_MILLIVOLT = "mV"
1096
1110
  UNIT_MINUTE = "min"
1097
1111
  UNIT_OHM = "Ω"
1098
1112
  UNIT_PARTS_PER_BILLION = "ppb"
esphome/core/__init__.py CHANGED
@@ -518,6 +518,8 @@ class EsphomeCore:
518
518
  self.verbose = False
519
519
  # Whether ESPHome was started in quiet mode
520
520
  self.quiet = False
521
+ # A list of all known ID classes
522
+ self.id_classes = {}
521
523
 
522
524
  def reset(self):
523
525
  from esphome.pins import PIN_SCHEMA_REGISTRY
@@ -67,21 +67,32 @@ void Application::loop() {
67
67
  uint32_t new_app_state = 0;
68
68
 
69
69
  this->scheduler.call();
70
- this->feed_wdt();
70
+
71
+ // Get the initial loop time at the start
72
+ uint32_t last_op_end_time = millis();
73
+
74
+ // Feed WDT with time
75
+ this->feed_wdt(last_op_end_time);
76
+
71
77
  for (Component *component : this->looping_components_) {
78
+ // Update the cached time before each component runs
79
+ this->loop_component_start_time_ = last_op_end_time;
80
+
72
81
  {
73
- WarnIfComponentBlockingGuard guard{component};
82
+ this->set_current_component(component);
83
+ WarnIfComponentBlockingGuard guard{component, last_op_end_time};
74
84
  component->call();
85
+ // Use the finish method to get the current time as the end time
86
+ last_op_end_time = guard.finish();
75
87
  }
76
88
  new_app_state |= component->get_component_state();
77
89
  this->app_state_ |= new_app_state;
78
- this->feed_wdt();
90
+ this->feed_wdt(last_op_end_time);
79
91
  }
80
92
  this->app_state_ = new_app_state;
81
93
 
82
- const uint32_t now = millis();
83
-
84
- auto elapsed = now - this->last_loop_;
94
+ // Use the last component's end time instead of calling millis() again
95
+ auto elapsed = last_op_end_time - this->last_loop_;
85
96
  if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) {
86
97
  yield();
87
98
  } else {
@@ -93,7 +104,7 @@ void Application::loop() {
93
104
  delay_time = std::min(next_schedule, delay_time);
94
105
  delay(delay_time);
95
106
  }
96
- this->last_loop_ = now;
107
+ this->last_loop_ = last_op_end_time;
97
108
 
98
109
  if (this->dump_config_at_ < this->components_.size()) {
99
110
  if (this->dump_config_at_ == 0) {
@@ -108,10 +119,12 @@ void Application::loop() {
108
119
  }
109
120
  }
110
121
 
111
- void IRAM_ATTR HOT Application::feed_wdt() {
122
+ void IRAM_ATTR HOT Application::feed_wdt(uint32_t time) {
112
123
  static uint32_t last_feed = 0;
113
- uint32_t now = micros();
114
- if (now - last_feed > 3000) {
124
+ // Use provided time if available, otherwise get current time
125
+ uint32_t now = time ? time : millis();
126
+ // Compare in milliseconds (3ms threshold)
127
+ if (now - last_feed > 3) {
115
128
  arch_feed_wdt();
116
129
  last_feed = now;
117
130
  #ifdef USE_STATUS_LED
@@ -97,6 +97,9 @@ class Application {
97
97
  this->compilation_time_ = compilation_time;
98
98
  }
99
99
 
100
+ void set_current_component(Component *component) { this->current_component_ = component; }
101
+ Component *get_current_component() { return this->current_component_; }
102
+
100
103
  #ifdef USE_BINARY_SENSOR
101
104
  void register_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
102
105
  this->binary_sensors_.push_back(binary_sensor);
@@ -214,6 +217,9 @@ class Application {
214
217
 
215
218
  std::string get_compilation_time() const { return this->compilation_time_; }
216
219
 
220
+ /// Get the cached time in milliseconds from when the current component started its loop execution
221
+ inline uint32_t IRAM_ATTR HOT get_loop_component_start_time() const { return this->loop_component_start_time_; }
222
+
217
223
  /** Set the target interval with which to run the loop() calls.
218
224
  * If the loop() method takes longer than the target interval, ESPHome won't
219
225
  * sleep in loop(), but if the time spent in loop() is small than the target, ESPHome
@@ -233,7 +239,7 @@ class Application {
233
239
 
234
240
  void schedule_dump_config() { this->dump_config_at_ = 0; }
235
241
 
236
- void feed_wdt();
242
+ void feed_wdt(uint32_t time = 0);
237
243
 
238
244
  void reboot();
239
245
 
@@ -547,6 +553,8 @@ class Application {
547
553
  uint32_t loop_interval_{16};
548
554
  size_t dump_config_at_{SIZE_MAX};
549
555
  uint32_t app_state_{0};
556
+ Component *current_component_{nullptr};
557
+ uint32_t loop_component_start_time_{0};
550
558
  };
551
559
 
552
560
  /// Global storage of Application pointer - only one Application can exist.
esphome/core/automation.h CHANGED
@@ -1,10 +1,11 @@
1
1
  #pragma once
2
2
 
3
- #include <vector>
4
3
  #include "esphome/core/component.h"
5
- #include "esphome/core/helpers.h"
6
4
  #include "esphome/core/defines.h"
5
+ #include "esphome/core/helpers.h"
7
6
  #include "esphome/core/preferences.h"
7
+ #include <utility>
8
+ #include <vector>
8
9
 
9
10
  namespace esphome {
10
11
 
@@ -27,7 +28,7 @@ template<typename T, typename... X> class TemplatableValue {
27
28
  TemplatableValue() : type_(NONE) {}
28
29
 
29
30
  template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0>
30
- TemplatableValue(F value) : type_(VALUE), value_(value) {}
31
+ TemplatableValue(F value) : type_(VALUE), value_(std::move(value)) {}
31
32
 
32
33
  template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0>
33
34
  TemplatableValue(F f) : type_(LAMBDA), f_(f) {}
@@ -39,6 +39,9 @@ const uint32_t STATUS_LED_OK = 0x0000;
39
39
  const uint32_t STATUS_LED_WARNING = 0x0100;
40
40
  const uint32_t STATUS_LED_ERROR = 0x0200;
41
41
 
42
+ const uint32_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning
43
+ const uint32_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again
44
+
42
45
  uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
43
46
 
44
47
  float Component::get_loop_priority() const { return 0.0f; }
@@ -115,6 +118,13 @@ const char *Component::get_component_source() const {
115
118
  return "<unknown>";
116
119
  return this->component_source_;
117
120
  }
121
+ bool Component::should_warn_of_blocking(uint32_t blocking_time) {
122
+ if (blocking_time > this->warn_if_blocking_over_) {
123
+ this->warn_if_blocking_over_ = blocking_time + WARN_IF_BLOCKING_INCREMENT_MS;
124
+ return true;
125
+ }
126
+ return false;
127
+ }
118
128
  void Component::mark_failed() {
119
129
  ESP_LOGE(TAG, "Component %s was marked as failed.", this->get_component_source());
120
130
  this->component_state_ &= ~COMPONENT_STATE_MASK;
@@ -230,16 +240,27 @@ void PollingComponent::stop_poller() {
230
240
  uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; }
231
241
  void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
232
242
 
233
- WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component)
234
- : started_(millis()), component_(component) {}
235
- WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {
236
- uint32_t now = millis();
237
- if (now - started_ > 50) {
243
+ WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component, uint32_t start_time)
244
+ : started_(start_time), component_(component) {}
245
+ uint32_t WarnIfComponentBlockingGuard::finish() {
246
+ uint32_t curr_time = millis();
247
+
248
+ uint32_t blocking_time = curr_time - this->started_;
249
+ bool should_warn;
250
+ if (this->component_ != nullptr) {
251
+ should_warn = this->component_->should_warn_of_blocking(blocking_time);
252
+ } else {
253
+ should_warn = blocking_time > WARN_IF_BLOCKING_OVER_MS;
254
+ }
255
+ if (should_warn) {
238
256
  const char *src = component_ == nullptr ? "<null>" : component_->get_component_source();
239
- ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, (now - started_));
257
+ ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, blocking_time);
240
258
  ESP_LOGW(TAG, "Components should block for at most 30 ms.");
241
- ;
242
259
  }
260
+
261
+ return curr_time;
243
262
  }
244
263
 
264
+ WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {}
265
+
245
266
  } // namespace esphome
esphome/core/component.h CHANGED
@@ -65,6 +65,8 @@ extern const uint32_t STATUS_LED_ERROR;
65
65
 
66
66
  enum class RetryResult { DONE, RETRY };
67
67
 
68
+ extern const uint32_t WARN_IF_BLOCKING_OVER_MS;
69
+
68
70
  class Component {
69
71
  public:
70
72
  /** Where the component's initialization should happen.
@@ -158,6 +160,8 @@ class Component {
158
160
  */
159
161
  const char *get_component_source() const;
160
162
 
163
+ bool should_warn_of_blocking(uint32_t blocking_time);
164
+
161
165
  protected:
162
166
  friend class Application;
163
167
 
@@ -284,6 +288,7 @@ class Component {
284
288
  uint32_t component_state_{0x0000}; ///< State of this component.
285
289
  float setup_priority_override_{NAN};
286
290
  const char *component_source_{nullptr};
291
+ uint32_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS};
287
292
  std::string error_message_{};
288
293
  };
289
294
 
@@ -334,7 +339,11 @@ class PollingComponent : public Component {
334
339
 
335
340
  class WarnIfComponentBlockingGuard {
336
341
  public:
337
- WarnIfComponentBlockingGuard(Component *component);
342
+ WarnIfComponentBlockingGuard(Component *component, uint32_t start_time);
343
+
344
+ // Finish the timing operation and return the current time
345
+ uint32_t finish();
346
+
338
347
  ~WarnIfComponentBlockingGuard();
339
348
 
340
349
  protected: