esphome 2025.4.2__py3-none-any.whl → 2025.5.0__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 (444) 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 +416 -662
  13. esphome/components/api/api_connection.h +256 -57
  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/at581x/at581x.h +4 -4
  27. esphome/components/atm90e32/__init__.py +1 -0
  28. esphome/components/atm90e32/atm90e32.cpp +576 -199
  29. esphome/components/atm90e32/atm90e32.h +128 -31
  30. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  31. esphome/components/atm90e32/button/__init__.py +62 -10
  32. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  33. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  34. esphome/components/atm90e32/number/__init__.py +130 -0
  35. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  36. esphome/components/atm90e32/sensor.py +21 -4
  37. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  38. esphome/components/audio/__init__.py +96 -49
  39. esphome/components/audio/audio.h +48 -0
  40. esphome/components/audio/audio_decoder.cpp +1 -1
  41. esphome/components/audio/audio_resampler.cpp +2 -0
  42. esphome/components/audio/audio_resampler.h +1 -0
  43. esphome/components/ballu/climate.py +2 -9
  44. esphome/components/bang_bang/climate.py +5 -6
  45. esphome/components/bedjet/bedjet_hub.cpp +1 -0
  46. esphome/components/bedjet/climate/__init__.py +3 -8
  47. esphome/components/bedjet/fan/__init__.py +2 -11
  48. esphome/components/binary/fan/__init__.py +13 -16
  49. esphome/components/binary_sensor/__init__.py +13 -10
  50. esphome/components/bl0906/constants.h +16 -16
  51. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  52. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
  54. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  55. esphome/components/button/__init__.py +11 -8
  56. esphome/components/canbus/canbus.cpp +3 -0
  57. esphome/components/canbus/canbus.h +16 -0
  58. esphome/components/ccs811/sensor.py +9 -6
  59. esphome/components/climate/__init__.py +35 -2
  60. esphome/components/climate/climate_mode.h +1 -1
  61. esphome/components/climate/climate_traits.h +63 -57
  62. esphome/components/climate_ir/__init__.py +57 -17
  63. esphome/components/climate_ir_lg/climate.py +2 -5
  64. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  65. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  66. esphome/components/color/__init__.py +2 -0
  67. esphome/components/const/__init__.py +5 -0
  68. esphome/components/coolix/climate.py +2 -9
  69. esphome/components/copy/cover/__init__.py +10 -9
  70. esphome/components/copy/fan/__init__.py +11 -9
  71. esphome/components/copy/lock/__init__.py +11 -9
  72. esphome/components/copy/text/__init__.py +9 -6
  73. esphome/components/cover/__init__.py +37 -2
  74. esphome/components/cse7766/cse7766.cpp +2 -1
  75. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  76. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  77. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  79. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  80. esphome/components/current_based/cover.py +37 -36
  81. esphome/components/current_based/current_based_cover.cpp +2 -1
  82. esphome/components/daikin/climate.py +2 -9
  83. esphome/components/daikin/daikin.cpp +15 -9
  84. esphome/components/daikin/daikin.h +5 -5
  85. esphome/components/daikin_arc/climate.py +2 -7
  86. esphome/components/daikin_brc/climate.py +3 -5
  87. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  88. esphome/components/dallas_temp/dallas_temp.h +0 -1
  89. esphome/components/daly_bms/daly_bms.cpp +2 -1
  90. esphome/components/debug/debug_component.cpp +6 -1
  91. esphome/components/debug/debug_component.h +8 -0
  92. esphome/components/debug/debug_esp32.cpp +109 -254
  93. esphome/components/debug/sensor.py +14 -0
  94. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  95. esphome/components/delonghi/climate.py +2 -9
  96. esphome/components/demo/__init__.py +18 -20
  97. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  98. esphome/components/dps310/sensor.py +6 -6
  99. esphome/components/ee895/sensor.py +9 -9
  100. esphome/components/emmeti/climate.py +2 -9
  101. esphome/components/endstop/cover.py +17 -16
  102. esphome/components/endstop/endstop_cover.cpp +2 -1
  103. esphome/components/ens160_base/__init__.py +12 -9
  104. esphome/components/esp32/__init__.py +60 -3
  105. esphome/components/esp32/core.cpp +11 -5
  106. esphome/components/esp32/gpio.cpp +86 -24
  107. esphome/components/esp32/gpio.py +15 -16
  108. esphome/components/esp32/gpio_esp32.py +1 -2
  109. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  110. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  111. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  112. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  113. esphome/components/esp32_ble/ble.cpp +1 -0
  114. esphome/components/esp32_ble/ble.h +5 -3
  115. esphome/components/esp32_ble/ble_advertising.cpp +2 -1
  116. esphome/components/esp32_ble/ble_advertising.h +1 -0
  117. esphome/components/esp32_ble_server/__init__.py +3 -0
  118. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  119. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  120. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  121. esphome/components/esp32_camera/__init__.py +1 -1
  122. esphome/components/esp32_camera/esp32_camera.cpp +2 -10
  123. esphome/components/esp32_camera/esp32_camera.h +1 -1
  124. esphome/components/esp32_can/esp32_can.cpp +1 -1
  125. esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
  126. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  127. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  128. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  129. esphome/components/esp32_touch/esp32_touch.cpp +1 -1
  130. esphome/components/esp8266/gpio.cpp +69 -8
  131. esphome/components/ethernet/ethernet_component.cpp +1 -1
  132. esphome/components/event/__init__.py +13 -10
  133. esphome/components/factory_reset/switch/__init__.py +7 -21
  134. esphome/components/fan/__init__.py +52 -5
  135. esphome/components/fastled_base/__init__.py +1 -4
  136. esphome/components/fastled_base/fastled_light.cpp +1 -1
  137. esphome/components/feedback/cover.py +38 -33
  138. esphome/components/feedback/feedback_cover.cpp +2 -1
  139. esphome/components/fujitsu_general/climate.py +2 -9
  140. esphome/components/gcja5/gcja5.cpp +2 -1
  141. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  142. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  143. esphome/components/gpio_expander/cached_gpio.h +22 -7
  144. esphome/components/gps/__init__.py +47 -17
  145. esphome/components/gps/gps.cpp +42 -23
  146. esphome/components/gps/gps.h +17 -13
  147. esphome/components/graph/__init__.py +1 -2
  148. esphome/components/gree/climate.py +4 -6
  149. esphome/components/gree/gree.cpp +16 -2
  150. esphome/components/gree/gree.h +2 -2
  151. esphome/components/growatt_solar/growatt_solar.cpp +2 -1
  152. esphome/components/haier/climate.py +37 -34
  153. esphome/components/hbridge/fan/__init__.py +19 -17
  154. esphome/components/he60r/cover.py +4 -5
  155. esphome/components/heatpumpir/climate.py +3 -6
  156. esphome/components/hitachi_ac344/climate.py +2 -9
  157. esphome/components/hitachi_ac424/climate.py +2 -9
  158. esphome/components/hm3301/hm3301.h +1 -1
  159. esphome/components/hte501/sensor.py +6 -6
  160. esphome/components/http_request/__init__.py +39 -6
  161. esphome/components/http_request/http_request.cpp +20 -0
  162. esphome/components/http_request/http_request.h +57 -15
  163. esphome/components/http_request/http_request_arduino.cpp +22 -6
  164. esphome/components/http_request/http_request_arduino.h +4 -3
  165. esphome/components/http_request/http_request_host.cpp +141 -0
  166. esphome/components/http_request/http_request_host.h +37 -0
  167. esphome/components/http_request/http_request_idf.cpp +35 -3
  168. esphome/components/http_request/http_request_idf.h +10 -3
  169. esphome/components/http_request/httplib.h +9691 -0
  170. esphome/components/http_request/update/__init__.py +11 -8
  171. esphome/components/hyt271/sensor.py +6 -6
  172. esphome/components/i2c/i2c.h +4 -0
  173. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  174. esphome/components/i2s_audio/__init__.py +131 -22
  175. esphome/components/i2s_audio/i2s_audio.h +44 -4
  176. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  177. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  178. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  179. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  180. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  181. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  182. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  183. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  184. esphome/components/image/__init__.py +37 -17
  185. esphome/components/image/image.cpp +25 -8
  186. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  187. esphome/components/key_collector/__init__.py +35 -0
  188. esphome/components/key_collector/key_collector.cpp +8 -0
  189. esphome/components/key_collector/key_collector.h +10 -0
  190. esphome/components/kuntze/kuntze.cpp +2 -1
  191. esphome/components/ld2410/ld2410.h +1 -1
  192. esphome/components/ld2450/ld2450.h +1 -1
  193. esphome/components/light/__init__.py +57 -0
  194. esphome/components/lock/__init__.py +51 -4
  195. esphome/components/lock/automation.h +2 -13
  196. esphome/components/logger/__init__.py +22 -0
  197. esphome/components/logger/logger.cpp +154 -103
  198. esphome/components/logger/logger.h +211 -36
  199. esphome/components/logger/task_log_buffer.cpp +138 -0
  200. esphome/components/logger/task_log_buffer.h +69 -0
  201. esphome/components/lvgl/__init__.py +13 -5
  202. esphome/components/lvgl/automation.py +50 -1
  203. esphome/components/lvgl/defines.py +0 -1
  204. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  205. esphome/components/lvgl/text/__init__.py +1 -2
  206. esphome/components/mapping/__init__.py +134 -0
  207. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
  208. esphome/components/max7219digit/max7219digit.cpp +28 -27
  209. esphome/components/mdns/__init__.py +11 -5
  210. esphome/components/mdns/mdns_component.cpp +11 -5
  211. esphome/components/mdns/mdns_component.h +3 -2
  212. esphome/components/mdns/mdns_esp32.cpp +4 -3
  213. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  214. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  215. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  216. esphome/components/media_player/__init__.py +33 -1
  217. esphome/components/mhz19/sensor.py +11 -7
  218. esphome/components/micro_wake_word/__init__.py +99 -31
  219. esphome/components/micro_wake_word/automation.h +54 -0
  220. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  221. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  222. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  223. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  224. esphome/components/micro_wake_word/streaming_model.h +85 -13
  225. esphome/components/microphone/__init__.py +139 -9
  226. esphome/components/microphone/automation.h +14 -2
  227. esphome/components/microphone/microphone.cpp +21 -0
  228. esphome/components/microphone/microphone.h +14 -5
  229. esphome/components/microphone/microphone_source.cpp +95 -0
  230. esphome/components/microphone/microphone_source.h +80 -0
  231. esphome/components/mics_4514/sensor.py +25 -14
  232. esphome/components/midea/climate.py +3 -4
  233. esphome/components/midea_ir/climate.py +3 -5
  234. esphome/components/mipi_spi/__init__.py +15 -0
  235. esphome/components/mipi_spi/display.py +474 -0
  236. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  237. esphome/components/mipi_spi/mipi_spi.h +171 -0
  238. esphome/components/mipi_spi/models/__init__.py +65 -0
  239. esphome/components/mipi_spi/models/amoled.py +72 -0
  240. esphome/components/mipi_spi/models/commands.py +82 -0
  241. esphome/components/mipi_spi/models/cyd.py +10 -0
  242. esphome/components/mipi_spi/models/ili.py +749 -0
  243. esphome/components/mipi_spi/models/jc.py +260 -0
  244. esphome/components/mipi_spi/models/lanbon.py +15 -0
  245. esphome/components/mipi_spi/models/lilygo.py +60 -0
  246. esphome/components/mipi_spi/models/waveshare.py +139 -0
  247. esphome/components/mitsubishi/climate.py +2 -5
  248. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  249. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  250. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  251. esphome/components/mlx90393/sensor.py +5 -0
  252. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  253. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  254. esphome/components/modbus/modbus.cpp +2 -1
  255. esphome/components/mqtt/__init__.py +1 -1
  256. esphome/components/mqtt/mqtt_client.cpp +6 -2
  257. esphome/components/mqtt/mqtt_const.h +4 -0
  258. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  259. esphome/components/mqtt/mqtt_fan.h +2 -0
  260. esphome/components/ms5611/sensor.py +6 -6
  261. esphome/components/ms8607/sensor.py +3 -3
  262. esphome/components/network/__init__.py +1 -1
  263. esphome/components/nextion/base_component.py +17 -16
  264. esphome/components/nextion/display.py +11 -2
  265. esphome/components/nextion/nextion.cpp +39 -1
  266. esphome/components/nextion/nextion.h +50 -0
  267. esphome/components/noblex/climate.py +2 -9
  268. esphome/components/number/__init__.py +12 -9
  269. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  270. esphome/components/one_wire/one_wire_bus.h +14 -8
  271. esphome/components/online_image/bmp_image.cpp +48 -11
  272. esphome/components/online_image/bmp_image.h +2 -0
  273. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  274. esphome/components/opentherm/number/__init__.py +11 -20
  275. esphome/components/opentherm/sensor/__init__.py +3 -3
  276. esphome/components/opentherm/switch/__init__.py +3 -5
  277. esphome/components/output/lock/__init__.py +11 -9
  278. esphome/components/packages/__init__.py +33 -31
  279. esphome/components/packet_transport/__init__.py +201 -0
  280. esphome/components/packet_transport/binary_sensor.py +19 -0
  281. esphome/components/packet_transport/packet_transport.cpp +534 -0
  282. esphome/components/packet_transport/packet_transport.h +154 -0
  283. esphome/components/packet_transport/sensor.py +19 -0
  284. esphome/components/pca9685/pca9685_output.cpp +2 -1
  285. esphome/components/pid/climate.py +2 -4
  286. esphome/components/pm2005/__init__.py +1 -0
  287. esphome/components/pm2005/pm2005.cpp +123 -0
  288. esphome/components/pm2005/pm2005.h +46 -0
  289. esphome/components/pm2005/sensor.py +86 -0
  290. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  291. esphome/components/pmsa003i/pmsa003i.h +25 -25
  292. esphome/components/pmsx003/pmsx003.cpp +195 -230
  293. esphome/components/pmsx003/pmsx003.h +51 -33
  294. esphome/components/pmsx003/sensor.py +21 -11
  295. esphome/components/pn7150/pn7150.h +2 -2
  296. esphome/components/pn7160/pn7160.h +2 -2
  297. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  298. esphome/components/prometheus/prometheus_handler.h +17 -0
  299. esphome/components/psram/__init__.py +7 -5
  300. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  301. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  302. esphome/components/pzem004t/pzem004t.cpp +2 -1
  303. esphome/components/qspi_dbi/__init__.py +0 -1
  304. esphome/components/qspi_dbi/display.py +2 -1
  305. esphome/components/qspi_dbi/models.py +1 -2
  306. esphome/components/remote_base/__init__.py +91 -0
  307. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  308. esphome/components/remote_base/beo4_protocol.h +43 -0
  309. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  310. esphome/components/remote_base/gobox_protocol.h +54 -0
  311. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  312. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  313. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  314. esphome/components/rf_bridge/rf_bridge.cpp +2 -1
  315. esphome/components/scd30/sensor.py +2 -3
  316. esphome/components/scd4x/sensor.py +4 -5
  317. esphome/components/sdp3x/sensor.py +2 -1
  318. esphome/components/sds011/sds011.cpp +2 -1
  319. esphome/components/select/__init__.py +19 -20
  320. esphome/components/sen5x/sen5x.cpp +55 -36
  321. esphome/components/sen5x/sensor.py +1 -1
  322. esphome/components/senseair/sensor.py +3 -3
  323. esphome/components/sensor/__init__.py +158 -14
  324. esphome/components/sensor/filter.cpp +23 -0
  325. esphome/components/sensor/filter.h +22 -0
  326. esphome/components/sgp30/sensor.py +14 -16
  327. esphome/components/sgp4x/sensor.py +1 -1
  328. esphome/components/sht4x/sht4x.cpp +43 -22
  329. esphome/components/sht4x/sht4x.h +1 -1
  330. esphome/components/shtcx/sensor.py +6 -6
  331. esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
  332. esphome/components/sml/text_sensor/__init__.py +4 -6
  333. esphome/components/sound_level/__init__.py +0 -0
  334. esphome/components/sound_level/sensor.py +97 -0
  335. esphome/components/sound_level/sound_level.cpp +194 -0
  336. esphome/components/sound_level/sound_level.h +73 -0
  337. esphome/components/speaker/media_player/__init__.py +4 -8
  338. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  339. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  340. esphome/components/speaker/speaker.h +4 -7
  341. esphome/components/speed/fan/__init__.py +17 -16
  342. esphome/components/spi/spi.h +11 -1
  343. esphome/components/sprinkler/__init__.py +18 -19
  344. esphome/components/sprinkler/sprinkler.cpp +6 -5
  345. esphome/components/switch/__init__.py +32 -42
  346. esphome/components/syslog/__init__.py +41 -0
  347. esphome/components/syslog/esphome_syslog.cpp +49 -0
  348. esphome/components/syslog/esphome_syslog.h +27 -0
  349. esphome/components/t6615/sensor.py +3 -3
  350. esphome/components/t6615/t6615.cpp +2 -1
  351. esphome/components/tca9555/tca9555.cpp +11 -6
  352. esphome/components/tcl112/climate.py +2 -9
  353. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  354. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  355. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  356. esphome/components/template/cover/__init__.py +27 -21
  357. esphome/components/template/fan/__init__.py +14 -12
  358. esphome/components/template/lock/__init__.py +20 -25
  359. esphome/components/template/lock/automation.h +18 -0
  360. esphome/components/template/text/__init__.py +4 -3
  361. esphome/components/template/valve/__init__.py +32 -21
  362. esphome/components/template/valve/automation.h +24 -0
  363. esphome/components/text/__init__.py +32 -1
  364. esphome/components/text_sensor/__init__.py +24 -29
  365. esphome/components/thermostat/climate.py +5 -5
  366. esphome/components/time_based/cover.py +17 -16
  367. esphome/components/time_based/time_based_cover.cpp +2 -1
  368. esphome/components/tm1638/switch/__init__.py +10 -7
  369. esphome/components/tormatic/cover.py +4 -5
  370. esphome/components/toshiba/climate.py +3 -5
  371. esphome/components/touchscreen/touchscreen.cpp +3 -1
  372. esphome/components/tuya/climate/__init__.py +5 -6
  373. esphome/components/tuya/cover/__init__.py +6 -11
  374. esphome/components/tuya/select/__init__.py +15 -5
  375. esphome/components/tuya/select/tuya_select.cpp +6 -1
  376. esphome/components/tuya/select/tuya_select.h +5 -1
  377. esphome/components/uart/packet_transport/__init__.py +20 -0
  378. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  379. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  380. esphome/components/uart/switch/uart_switch.cpp +2 -1
  381. esphome/components/udp/__init__.py +126 -128
  382. esphome/components/udp/automation.h +40 -0
  383. esphome/components/udp/binary_sensor.py +3 -25
  384. esphome/components/udp/packet_transport/__init__.py +29 -0
  385. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  386. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  387. esphome/components/udp/sensor.py +3 -25
  388. esphome/components/udp/udp_component.cpp +26 -470
  389. esphome/components/udp/udp_component.h +21 -128
  390. esphome/components/update/__init__.py +31 -1
  391. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  392. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
  393. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  394. esphome/components/uptime/text_sensor/__init__.py +47 -7
  395. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  396. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  397. esphome/components/valve/__init__.py +34 -3
  398. esphome/components/valve/automation.h +1 -19
  399. esphome/components/vl53l0x/sensor.py +11 -0
  400. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  401. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  402. esphome/components/voice_assistant/__init__.py +36 -10
  403. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  404. esphome/components/voice_assistant/voice_assistant.h +26 -25
  405. esphome/components/waveshare_epaper/display.py +6 -0
  406. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  407. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  408. esphome/components/weikai/weikai.cpp +0 -52
  409. esphome/components/whirlpool/climate.py +3 -5
  410. esphome/components/whynter/climate.py +3 -5
  411. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  412. esphome/components/yashima/climate.py +6 -6
  413. esphome/components/zhlt01/climate.py +2 -7
  414. esphome/config.py +13 -13
  415. esphome/config_validation.py +38 -58
  416. esphome/const.py +15 -1
  417. esphome/core/__init__.py +2 -0
  418. esphome/core/application.cpp +27 -10
  419. esphome/core/application.h +9 -1
  420. esphome/core/automation.h +4 -3
  421. esphome/core/component.cpp +28 -7
  422. esphome/core/component.h +10 -1
  423. esphome/core/defines.h +23 -17
  424. esphome/core/doxygen.h +13 -0
  425. esphome/core/macros.h +4 -0
  426. esphome/core/scheduler.cpp +7 -1
  427. esphome/cpp_generator.py +6 -2
  428. esphome/dashboard/web_server.py +3 -3
  429. esphome/helpers.py +39 -0
  430. esphome/loader.py +4 -0
  431. esphome/log.py +15 -19
  432. esphome/mqtt.py +23 -10
  433. esphome/platformio_api.py +1 -1
  434. esphome/schema_extractors.py +0 -1
  435. esphome/voluptuous_schema.py +3 -1
  436. esphome/vscode.py +15 -0
  437. esphome/wizard.py +47 -37
  438. esphome/zeroconf.py +7 -3
  439. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/METADATA +10 -11
  440. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/RECORD +444 -383
  441. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/WHEEL +1 -1
  442. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/entry_points.txt +0 -0
  443. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/licenses/LICENSE +0 -0
  444. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/top_level.txt +0 -0
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:
esphome/core/defines.h CHANGED
@@ -20,11 +20,6 @@
20
20
 
21
21
  // Feature flags
22
22
  #define USE_ALARM_CONTROL_PANEL
23
- #define USE_AUDIO_FLAC_SUPPORT
24
- #define USE_AUDIO_MP3_SUPPORT
25
- #define USE_API
26
- #define USE_API_NOISE
27
- #define USE_API_PLAINTEXT
28
23
  #define USE_BINARY_SENSOR
29
24
  #define USE_BUTTON
30
25
  #define USE_CLIMATE
@@ -79,20 +74,10 @@
79
74
  #define USE_LVGL_TEXTAREA
80
75
  #define USE_LVGL_TILEVIEW
81
76
  #define USE_LVGL_TOUCHSCREEN
82
- #define USE_MD5
83
77
  #define USE_MDNS
84
78
  #define USE_MEDIA_PLAYER
85
- #define USE_MQTT
86
- #define USE_NETWORK
87
79
  #define USE_NEXTION_TFT_UPLOAD
88
80
  #define USE_NUMBER
89
- #define USE_ONLINE_IMAGE_BMP_SUPPORT
90
- #define USE_ONLINE_IMAGE_PNG_SUPPORT
91
- #define USE_ONLINE_IMAGE_JPEG_SUPPORT
92
- #define USE_OTA
93
- #define USE_OTA_PASSWORD
94
- #define USE_OTA_STATE_CALLBACK
95
- #define USE_OTA_VERSION 2
96
81
  #define USE_OUTPUT
97
82
  #define USE_POWER_SUPPLY
98
83
  #define USE_QR_CODE
@@ -107,14 +92,34 @@
107
92
  #define USE_UART_DEBUGGER
108
93
  #define USE_UPDATE
109
94
  #define USE_VALVE
95
+
96
+ // Feature flags which do not work for zephyr
97
+ #ifndef USE_ZEPHYR
98
+ #define USE_AUDIO_FLAC_SUPPORT
99
+ #define USE_AUDIO_MP3_SUPPORT
100
+ #define USE_API
101
+ #define USE_API_NOISE
102
+ #define USE_API_PLAINTEXT
103
+ #define USE_MD5
104
+ #define USE_MQTT
105
+ #define USE_NETWORK
106
+ #define USE_ONLINE_IMAGE_BMP_SUPPORT
107
+ #define USE_ONLINE_IMAGE_PNG_SUPPORT
108
+ #define USE_ONLINE_IMAGE_JPEG_SUPPORT
109
+ #define USE_OTA
110
+ #define USE_OTA_PASSWORD
111
+ #define USE_OTA_STATE_CALLBACK
112
+ #define USE_OTA_VERSION 2
110
113
  #define USE_WIFI
111
114
  #define USE_WIFI_AP
112
115
  #define USE_WIREGUARD
116
+ #endif
113
117
 
114
118
  // Arduino-specific feature flags
115
119
  #ifdef USE_ARDUINO
116
120
  #define USE_PROMETHEUS
117
121
  #define USE_WIFI_WPA2_EAP
122
+ #define USE_I2S_LEGACY
118
123
  #endif
119
124
 
120
125
  // IDF-specific feature flags
@@ -131,7 +136,6 @@
131
136
  #define USE_ESP32_BLE_SERVER
132
137
  #define USE_ESP32_CAMERA
133
138
  #define USE_IMPROV
134
- #define USE_MICRO_WAKE_WORD_VAD
135
139
  #define USE_MICROPHONE
136
140
  #define USE_PSRAM
137
141
  #define USE_SOCKET_IMPL_BSD_SOCKETS
@@ -148,7 +152,9 @@
148
152
  #endif
149
153
 
150
154
  #ifdef USE_ESP_IDF
151
- #define USE_ESP_IDF_VERSION_CODE VERSION_CODE(5, 1, 5)
155
+ #define USE_ESP_IDF_VERSION_CODE VERSION_CODE(5, 1, 6)
156
+ #define USE_MICRO_WAKE_WORD
157
+ #define USE_MICRO_WAKE_WORD_VAD
152
158
  #endif
153
159
 
154
160
  #if defined(USE_ESP32_VARIANT_ESP32S2)
esphome/core/doxygen.h ADDED
@@ -0,0 +1,13 @@
1
+ #pragma once
2
+
3
+ namespace esphome {
4
+
5
+ /*! @mainpage ESPHome source code documentation
6
+ This documentation provides references to the ESPHome source code classes and methods.
7
+
8
+ @details This documentation site is purely for reference and does not contain any user documentation.
9
+ If you are contributing to ESPHome or building an ESPHome component, then you should be starting at
10
+ https://developers.esphome.io.
11
+ */
12
+
13
+ } // namespace esphome
esphome/core/macros.h CHANGED
@@ -2,3 +2,7 @@
2
2
 
3
3
  // Helper macro to define a version code, whose value can be compared against other version codes.
4
4
  #define VERSION_CODE(major, minor, patch) ((major) << 16 | (minor) << 8 | (patch))
5
+
6
+ #ifdef USE_ARDUINO
7
+ #include <Arduino.h>
8
+ #endif
@@ -1,4 +1,6 @@
1
1
  #include "scheduler.h"
2
+
3
+ #include "application.h"
2
4
  #include "esphome/core/defines.h"
3
5
  #include "esphome/core/log.h"
4
6
  #include "esphome/core/helpers.h"
@@ -215,6 +217,7 @@ void HOT Scheduler::call() {
215
217
  this->pop_raw_();
216
218
  continue;
217
219
  }
220
+ App.set_current_component(item->component);
218
221
 
219
222
  #ifdef ESPHOME_DEBUG_SCHEDULER
220
223
  ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")",
@@ -226,8 +229,11 @@ void HOT Scheduler::call() {
226
229
  // - timeouts/intervals get added, potentially invalidating vector pointers
227
230
  // - timeouts/intervals get cancelled
228
231
  {
229
- WarnIfComponentBlockingGuard guard{item->component};
232
+ uint32_t now_ms = millis();
233
+ WarnIfComponentBlockingGuard guard{item->component, now_ms};
230
234
  item->callback();
235
+ // Call finish to ensure blocking time is properly calculated and reported
236
+ guard.finish();
231
237
  }
232
238
  }
233
239
 
esphome/cpp_generator.py CHANGED
@@ -789,13 +789,17 @@ class MockObj(Expression):
789
789
 
790
790
  def class_(self, name: str, *parents: "MockObjClass") -> "MockObjClass":
791
791
  op = "" if self.op == "" else "::"
792
- return MockObjClass(f"{self.base}{op}{name}", ".", parents=parents)
792
+ result = MockObjClass(f"{self.base}{op}{name}", ".", parents=parents)
793
+ CORE.id_classes[str(result)] = result
794
+ return result
793
795
 
794
796
  def struct(self, name: str) -> "MockObjClass":
795
797
  return self.class_(name)
796
798
 
797
799
  def enum(self, name: str, is_class: bool = False) -> "MockObj":
798
- return MockObjEnum(enum=name, is_class=is_class, base=self.base, op=self.op)
800
+ result = MockObjEnum(enum=name, is_class=is_class, base=self.base, op=self.op)
801
+ CORE.id_classes[str(result)] = result
802
+ return result
799
803
 
800
804
  def operator(self, name: str) -> "MockObj":
801
805
  """Various other operations.
@@ -38,7 +38,7 @@ import yaml
38
38
  from yaml.nodes import Node
39
39
 
40
40
  from esphome import const, platformio_api, yaml_util
41
- from esphome.helpers import get_bool_env, mkdir_p
41
+ from esphome.helpers import get_bool_env, mkdir_p, sort_ip_addresses
42
42
  from esphome.storage_json import (
43
43
  StorageJSON,
44
44
  archive_storage_path,
@@ -336,7 +336,7 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
336
336
  # Use the IP address if available but only
337
337
  # if the API is loaded and the device is online
338
338
  # since MQTT logging will not work otherwise
339
- port = address_list[0]
339
+ port = sort_ip_addresses(address_list)[0]
340
340
  elif (
341
341
  entry.address
342
342
  and (
@@ -347,7 +347,7 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
347
347
  and not isinstance(address_list, Exception)
348
348
  ):
349
349
  # If mdns is not available, try to use the DNS cache
350
- port = address_list[0]
350
+ port = sort_ip_addresses(address_list)[0]
351
351
 
352
352
  return [
353
353
  *DASHBOARD_COMMAND,
esphome/helpers.py CHANGED
@@ -200,6 +200,45 @@ def resolve_ip_address(host, port):
200
200
  return res
201
201
 
202
202
 
203
+ def sort_ip_addresses(address_list: list[str]) -> list[str]:
204
+ """Takes a list of IP addresses in string form, e.g. from mDNS or MQTT,
205
+ and sorts them into the best order to actually try connecting to them.
206
+
207
+ This is roughly based on RFC6724 but a lot simpler: First we choose
208
+ IPv6 addresses, then Legacy IP addresses, and lowest priority is
209
+ link-local IPv6 addresses that don't have a link specified (which
210
+ are useless, but mDNS does provide them in that form). Addresses
211
+ which cannot be parsed are silently dropped.
212
+ """
213
+ import socket
214
+
215
+ # First "resolve" all the IP addresses to getaddrinfo() tuples of the form
216
+ # (family, type, proto, canonname, sockaddr)
217
+ res: list[
218
+ tuple[
219
+ int,
220
+ int,
221
+ int,
222
+ Union[str, None],
223
+ Union[tuple[str, int], tuple[str, int, int, int]],
224
+ ]
225
+ ] = []
226
+ for addr in address_list:
227
+ # This should always work as these are supposed to be IP addresses
228
+ try:
229
+ res += socket.getaddrinfo(
230
+ addr, 0, proto=socket.IPPROTO_TCP, flags=socket.AI_NUMERICHOST
231
+ )
232
+ except OSError:
233
+ _LOGGER.info("Failed to parse IP address '%s'", addr)
234
+
235
+ # Now use that information to sort them.
236
+ res.sort(key=addr_preference_)
237
+
238
+ # Finally, turn the getaddrinfo() tuples back into plain hostnames.
239
+ return [socket.getnameinfo(r[4], socket.NI_NUMERICHOST)[0] for r in res]
240
+
241
+
203
242
  def get_bool_env(var, default=False):
204
243
  value = os.getenv(var, default)
205
244
  if isinstance(value, str):
esphome/loader.py CHANGED
@@ -91,6 +91,10 @@ class ComponentManifest:
91
91
  def codeowners(self) -> list[str]:
92
92
  return getattr(self.module, "CODEOWNERS", [])
93
93
 
94
+ @property
95
+ def instance_type(self) -> list[str]:
96
+ return getattr(self.module, "INSTANCE_TYPE", None)
97
+
94
98
  @property
95
99
  def final_validate_schema(self) -> Optional[Callable[[ConfigType], None]]:
96
100
  """Components can declare a `FINAL_VALIDATE_SCHEMA` cv.Schema that gets called
esphome/log.py CHANGED
@@ -1,9 +1,10 @@
1
+ from enum import Enum
1
2
  import logging
2
3
 
3
4
  from esphome.core import CORE
4
5
 
5
6
 
6
- class AnsiFore:
7
+ class AnsiFore(Enum):
7
8
  KEEP = ""
8
9
  BLACK = "\033[30m"
9
10
  RED = "\033[31m"
@@ -26,7 +27,7 @@ class AnsiFore:
26
27
  BOLD_RESET = "\033[1;39m"
27
28
 
28
29
 
29
- class AnsiStyle:
30
+ class AnsiStyle(Enum):
30
31
  BRIGHT = "\033[1m"
31
32
  BOLD = "\033[1m"
32
33
  DIM = "\033[2m"
@@ -35,16 +36,10 @@ class AnsiStyle:
35
36
  RESET_ALL = "\033[0m"
36
37
 
37
38
 
38
- Fore = AnsiFore()
39
- Style = AnsiStyle()
40
-
41
-
42
- def color(col: str, msg: str, reset: bool = True) -> bool:
43
- if col and not col.startswith("\033["):
44
- raise ValueError("Color must be value from esphome.log.Fore")
45
- s = str(col) + msg
39
+ def color(col: AnsiFore, msg: str, reset: bool = True) -> str:
40
+ s = col.value + msg
46
41
  if reset and col:
47
- s += str(Style.RESET_ALL)
42
+ s += AnsiStyle.RESET_ALL.value
48
43
  return s
49
44
 
50
45
 
@@ -54,20 +49,21 @@ class ESPHomeLogFormatter(logging.Formatter):
54
49
  fmt += "%(levelname)s %(message)s"
55
50
  super().__init__(fmt=fmt, style="%")
56
51
 
57
- def format(self, record):
52
+ # @override
53
+ def format(self, record: logging.LogRecord) -> str:
58
54
  formatted = super().format(record)
59
55
  prefix = {
60
- "DEBUG": Fore.CYAN,
61
- "INFO": Fore.GREEN,
62
- "WARNING": Fore.YELLOW,
63
- "ERROR": Fore.RED,
64
- "CRITICAL": Fore.RED,
56
+ "DEBUG": AnsiFore.CYAN.value,
57
+ "INFO": AnsiFore.GREEN.value,
58
+ "WARNING": AnsiFore.YELLOW.value,
59
+ "ERROR": AnsiFore.RED.value,
60
+ "CRITICAL": AnsiFore.RED.value,
65
61
  }.get(record.levelname, "")
66
- return f"{prefix}{formatted}{Style.RESET_ALL}"
62
+ return f"{prefix}{formatted}{AnsiStyle.RESET_ALL.value}"
67
63
 
68
64
 
69
65
  def setup_log(
70
- log_level=logging.INFO,
66
+ log_level: int = logging.INFO,
71
67
  include_timestamp: bool = False,
72
68
  ) -> None:
73
69
  import colorama
esphome/mqtt.py CHANGED
@@ -3,6 +3,7 @@ import hashlib
3
3
  import json
4
4
  import logging
5
5
  import ssl
6
+ import tempfile
6
7
  import time
7
8
 
8
9
  import paho.mqtt.client as mqtt
@@ -10,6 +11,8 @@ import paho.mqtt.client as mqtt
10
11
  from esphome.const import (
11
12
  CONF_BROKER,
12
13
  CONF_CERTIFICATE_AUTHORITY,
14
+ CONF_CLIENT_CERTIFICATE,
15
+ CONF_CLIENT_CERTIFICATE_KEY,
13
16
  CONF_DISCOVERY_PREFIX,
14
17
  CONF_ESPHOME,
15
18
  CONF_LOG_TOPIC,
@@ -17,6 +20,7 @@ from esphome.const import (
17
20
  CONF_NAME,
18
21
  CONF_PASSWORD,
19
22
  CONF_PORT,
23
+ CONF_SKIP_CERT_CN_CHECK,
20
24
  CONF_SSL_FINGERPRINTS,
21
25
  CONF_TOPIC,
22
26
  CONF_TOPIC_PREFIX,
@@ -24,7 +28,7 @@ from esphome.const import (
24
28
  )
25
29
  from esphome.core import CORE, EsphomeError
26
30
  from esphome.helpers import get_int_env, get_str_env
27
- from esphome.log import Fore, color
31
+ from esphome.log import AnsiFore, color
28
32
  from esphome.util import safe_print
29
33
 
30
34
  _LOGGER = logging.getLogger(__name__)
@@ -102,15 +106,24 @@ def prepare(
102
106
  if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get(
103
107
  CONF_CERTIFICATE_AUTHORITY
104
108
  ):
105
- tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member
106
- client.tls_set(
107
- ca_certs=None,
108
- certfile=None,
109
- keyfile=None,
110
- cert_reqs=ssl.CERT_REQUIRED,
111
- tls_version=tls_version,
112
- ciphers=None,
109
+ context = ssl.create_default_context(
110
+ cadata=config[CONF_MQTT].get(CONF_CERTIFICATE_AUTHORITY)
113
111
  )
112
+ if config[CONF_MQTT].get(CONF_SKIP_CERT_CN_CHECK):
113
+ context.check_hostname = False
114
+ if config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE) and config[CONF_MQTT].get(
115
+ CONF_CLIENT_CERTIFICATE_KEY
116
+ ):
117
+ with (
118
+ tempfile.NamedTemporaryFile(mode="w+") as cert_file,
119
+ tempfile.NamedTemporaryFile(mode="w+") as key_file,
120
+ ):
121
+ cert_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE))
122
+ cert_file.flush()
123
+ key_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE_KEY))
124
+ key_file.flush()
125
+ context.load_cert_chain(cert_file, key_file)
126
+ client.tls_set_context(context)
114
127
 
115
128
  try:
116
129
  host = str(config[CONF_MQTT][CONF_BROKER])
@@ -278,7 +291,7 @@ def get_fingerprint(config):
278
291
 
279
292
  sha1 = hashlib.sha1(cert_der).hexdigest()
280
293
 
281
- safe_print(f"SHA1 Fingerprint: {color(Fore.CYAN, sha1)}")
294
+ safe_print(f"SHA1 Fingerprint: {color(AnsiFore.CYAN, sha1)}")
282
295
  safe_print(
283
296
  f"Copy the string above into mqtt.ssl_fingerprints section of {CORE.config_path}"
284
297
  )
esphome/platformio_api.py CHANGED
@@ -53,7 +53,7 @@ FILTER_PLATFORMIO_LINES = [
53
53
  f"You can ignore this message, if `.*{IGNORE_LIB_WARNINGS}.*` is a built-in library.*",
54
54
  r"Scanning dependencies...",
55
55
  r"Found \d+ compatible libraries",
56
- r"Memory Usage -> http://bit.ly/pio-memory-usage",
56
+ r"Memory Usage -> https://bit.ly/pio-memory-usage",
57
57
  r"Found: https://platformio.org/lib/show/.*",
58
58
  r"Using cache: .*",
59
59
  r"Installing dependencies",
@@ -42,7 +42,6 @@ def schema_extractor_extended(func):
42
42
 
43
43
  def decorate(*args, **kwargs):
44
44
  ret = func(*args, **kwargs)
45
- assert len(args) == 2
46
45
  extended_schemas[repr(ret)] = args
47
46
  return ret
48
47
 
@@ -15,7 +15,9 @@ class ExtraKeysInvalid(vol.Invalid):
15
15
  def ensure_multiple_invalid(err):
16
16
  if isinstance(err, vol.MultipleInvalid):
17
17
  return err
18
- return vol.MultipleInvalid(err)
18
+ if isinstance(err, list):
19
+ return vol.MultipleInvalid(err)
20
+ return vol.MultipleInvalid([err])
19
21
 
20
22
 
21
23
  # pylint: disable=protected-access, unidiomatic-typecheck
esphome/vscode.py CHANGED
@@ -7,6 +7,7 @@ from typing import Any
7
7
 
8
8
  from esphome.config import Config, _format_vol_invalid, validate_config
9
9
  import esphome.config_validation as cv
10
+ from esphome.const import __version__ as ESPHOME_VERSION
10
11
  from esphome.core import CORE, DocumentRange
11
12
  from esphome.yaml_util import parse_yaml
12
13
 
@@ -97,7 +98,21 @@ def _ace_loader(fname: str) -> dict[str, Any]:
97
98
  return parse_yaml(fname, raw_yaml_stream)
98
99
 
99
100
 
101
+ def _print_version():
102
+ """Print ESPHome version."""
103
+ print(
104
+ json.dumps(
105
+ {
106
+ "type": "version",
107
+ "value": ESPHOME_VERSION,
108
+ }
109
+ )
110
+ )
111
+
112
+
100
113
  def read_config(args):
114
+ _print_version()
115
+
101
116
  while True:
102
117
  CORE.reset()
103
118
  data = json.loads(input())