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
@@ -0,0 +1,134 @@
1
+ import difflib
2
+
3
+ import esphome.codegen as cg
4
+ import esphome.config_validation as cv
5
+ from esphome.const import CONF_FROM, CONF_ID, CONF_TO
6
+ from esphome.core import CORE
7
+ from esphome.cpp_generator import MockObj, VariableDeclarationExpression, add_global
8
+ from esphome.loader import get_component
9
+
10
+ CODEOWNERS = ["@clydebarrow"]
11
+ MULTI_CONF = True
12
+
13
+ map_ = cg.std_ns.class_("map")
14
+
15
+ CONF_ENTRIES = "entries"
16
+ CONF_CLASS = "class"
17
+
18
+
19
+ class IndexType:
20
+ """
21
+ Represents a type of index in a map.
22
+ """
23
+
24
+ def __init__(self, validator, data_type, conversion):
25
+ self.validator = validator
26
+ self.data_type = data_type
27
+ self.conversion = conversion
28
+
29
+
30
+ INDEX_TYPES = {
31
+ "int": IndexType(cv.int_, cg.int_, int),
32
+ "string": IndexType(cv.string, cg.std_string, str),
33
+ }
34
+
35
+
36
+ def to_schema(value):
37
+ """
38
+ Generate a schema for the 'to' field of a map. This can be either one of the index types or a class name.
39
+ :param value:
40
+ :return:
41
+ """
42
+ return cv.Any(
43
+ cv.one_of(*INDEX_TYPES, lower=True),
44
+ cv.one_of(*CORE.id_classes.keys()),
45
+ )(value)
46
+
47
+
48
+ BASE_SCHEMA = cv.Schema(
49
+ {
50
+ cv.Required(CONF_ID): cv.declare_id(map_),
51
+ cv.Required(CONF_FROM): cv.one_of(*INDEX_TYPES, lower=True),
52
+ cv.Required(CONF_TO): cv.string,
53
+ },
54
+ extra=cv.ALLOW_EXTRA,
55
+ )
56
+
57
+
58
+ def get_object_type(to_):
59
+ """
60
+ Get the object type from a string. Possible formats:
61
+ xxx The name of a component which defines INSTANCE_TYPE
62
+ esphome::xxx::yyy A C++ class name defined in a component
63
+ xxx::yyy A C++ class name defined in a component
64
+ yyy A C++ class name defined in the core
65
+ """
66
+
67
+ if cls := CORE.id_classes.get(to_):
68
+ return cls
69
+ if cls := CORE.id_classes.get(to_.removeprefix("esphome::")):
70
+ return cls
71
+ # get_component will throw a wobbly if we don't check this first.
72
+ if "." in to_:
73
+ return None
74
+ if component := get_component(to_):
75
+ return component.instance_type
76
+ return None
77
+
78
+
79
+ def map_schema(config):
80
+ config = BASE_SCHEMA(config)
81
+ if CONF_ENTRIES not in config or not isinstance(config[CONF_ENTRIES], dict):
82
+ raise cv.Invalid("an entries list is required for a map")
83
+ entries = config[CONF_ENTRIES]
84
+ if len(entries) == 0:
85
+ raise cv.Invalid("Map must have at least one entry")
86
+ to_ = config[CONF_TO]
87
+ if to_ in INDEX_TYPES:
88
+ value_type = INDEX_TYPES[to_].validator
89
+ else:
90
+ value_type = get_object_type(to_)
91
+ if value_type is None:
92
+ matches = difflib.get_close_matches(to_, CORE.id_classes)
93
+ raise cv.Invalid(
94
+ f"No known mappable class name matches '{to_}'; did you mean one of {', '.join(matches)}?"
95
+ )
96
+ value_type = cv.use_id(value_type)
97
+ config[CONF_ENTRIES] = {k: value_type(v) for k, v in entries.items()}
98
+ return config
99
+
100
+
101
+ CONFIG_SCHEMA = map_schema
102
+
103
+
104
+ async def to_code(config):
105
+ entries = config[CONF_ENTRIES]
106
+ from_ = config[CONF_FROM]
107
+ to_ = config[CONF_TO]
108
+ index_conversion = INDEX_TYPES[from_].conversion
109
+ index_type = INDEX_TYPES[from_].data_type
110
+ if to_ in INDEX_TYPES:
111
+ value_conversion = INDEX_TYPES[to_].conversion
112
+ value_type = INDEX_TYPES[to_].data_type
113
+ entries = {
114
+ index_conversion(key): value_conversion(value)
115
+ for key, value in entries.items()
116
+ }
117
+ else:
118
+ entries = {
119
+ index_conversion(key): await cg.get_variable(value)
120
+ for key, value in entries.items()
121
+ }
122
+ value_type = get_object_type(to_)
123
+ if list(entries.values())[0].op != ".":
124
+ value_type = value_type.operator("ptr")
125
+ varid = config[CONF_ID]
126
+ varid.type = map_.template(index_type, value_type)
127
+ var = MockObj(varid, ".")
128
+ decl = VariableDeclarationExpression(varid.type, "", varid)
129
+ add_global(decl)
130
+ CORE.register_variable(varid, var)
131
+
132
+ for key, value in entries.items():
133
+ cg.add(var.insert((key, value)))
134
+ return var
@@ -1,5 +1,6 @@
1
1
  #include "matrix_keypad.h"
2
2
  #include "esphome/core/log.h"
3
+ #include "esphome/core/application.h"
3
4
 
4
5
  namespace esphome {
5
6
  namespace matrix_keypad {
@@ -28,7 +29,7 @@ void MatrixKeypad::setup() {
28
29
  void MatrixKeypad::loop() {
29
30
  static uint32_t active_start = 0;
30
31
  static int active_key = -1;
31
- uint32_t now = millis();
32
+ uint32_t now = App.get_loop_component_start_time();
32
33
  int key = -1;
33
34
  bool error = false;
34
35
  int pos = 0, row, col;
@@ -2,8 +2,11 @@
2
2
  #include "esphome/core/log.h"
3
3
  #include "esphome/core/helpers.h"
4
4
  #include "esphome/core/hal.h"
5
+ #include "esphome/core/application.h"
5
6
  #include "max7219font.h"
6
7
 
8
+ #include <algorithm>
9
+
7
10
  namespace esphome {
8
11
  namespace max7219digit {
9
12
 
@@ -61,45 +64,42 @@ void MAX7219Component::dump_config() {
61
64
  }
62
65
 
63
66
  void MAX7219Component::loop() {
64
- uint32_t now = millis();
65
-
67
+ const uint32_t now = App.get_loop_component_start_time();
68
+ const uint32_t millis_since_last_scroll = now - this->last_scroll_;
69
+ const size_t first_line_size = this->max_displaybuffer_[0].size();
66
70
  // check if the buffer has shrunk past the current position since last update
67
- if ((this->max_displaybuffer_[0].size() >= this->old_buffer_size_ + 3) ||
68
- (this->max_displaybuffer_[0].size() <= this->old_buffer_size_ - 3)) {
71
+ if ((first_line_size >= this->old_buffer_size_ + 3) || (first_line_size <= this->old_buffer_size_ - 3)) {
72
+ ESP_LOGV(TAG, "Buffer size changed %d to %d", this->old_buffer_size_, first_line_size);
69
73
  this->stepsleft_ = 0;
70
74
  this->display();
71
- this->old_buffer_size_ = this->max_displaybuffer_[0].size();
75
+ this->old_buffer_size_ = first_line_size;
72
76
  }
73
77
 
74
- // Reset the counter back to 0 when full string has been displayed.
75
- if (this->stepsleft_ > this->max_displaybuffer_[0].size())
76
- this->stepsleft_ = 0;
77
-
78
- // Return if there is no need to scroll or scroll is off
79
- if (!this->scroll_ || (this->max_displaybuffer_[0].size() <= (size_t) get_width_internal())) {
78
+ if (!this->scroll_ || (first_line_size <= (size_t) get_width_internal())) {
79
+ ESP_LOGVV(TAG, "Return if there is no need to scroll or scroll is off.");
80
80
  this->display();
81
81
  return;
82
82
  }
83
83
 
84
- if ((this->stepsleft_ == 0) && (now - this->last_scroll_ < this->scroll_delay_)) {
84
+ if ((this->stepsleft_ == 0) && (millis_since_last_scroll < this->scroll_delay_)) {
85
+ ESP_LOGVV(TAG, "At first step. Waiting for scroll delay");
85
86
  this->display();
86
87
  return;
87
88
  }
88
89
 
89
- // Dwell time at end of string in case of stop at end
90
90
  if (this->scroll_mode_ == ScrollMode::STOP) {
91
- if (this->stepsleft_ >= this->max_displaybuffer_[0].size() - (size_t) get_width_internal() + 1) {
92
- if (now - this->last_scroll_ >= this->scroll_dwell_) {
93
- this->stepsleft_ = 0;
94
- this->last_scroll_ = now;
95
- this->display();
91
+ if (this->stepsleft_ + get_width_internal() == first_line_size + 1) {
92
+ if (millis_since_last_scroll < this->scroll_dwell_) {
93
+ ESP_LOGVV(TAG, "Dwell time at end of string in case of stop at end. Step %d, since last scroll %d, dwell %d.",
94
+ this->stepsleft_, millis_since_last_scroll, this->scroll_dwell_);
95
+ return;
96
96
  }
97
- return;
97
+ ESP_LOGV(TAG, "Dwell time passed. Continue scrolling.");
98
98
  }
99
99
  }
100
100
 
101
- // Actual call to scroll left action
102
- if (now - this->last_scroll_ >= this->scroll_speed_) {
101
+ if (millis_since_last_scroll >= this->scroll_speed_) {
102
+ ESP_LOGVV(TAG, "Call to scroll left action");
103
103
  this->last_scroll_ = now;
104
104
  this->scroll_left();
105
105
  this->display();
@@ -227,19 +227,20 @@ void MAX7219Component::scroll(bool on_off) { this->set_scroll(on_off); }
227
227
 
228
228
  void MAX7219Component::scroll_left() {
229
229
  for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
230
+ auto scroll = [&](std::vector<uint8_t> &line, uint16_t steps) {
231
+ std::rotate(line.begin(), std::next(line.begin(), steps), line.end());
232
+ };
230
233
  if (this->update_) {
231
234
  this->max_displaybuffer_[chip_line].push_back(this->bckgrnd_);
232
- for (uint16_t i = 0; i < this->stepsleft_; i++) {
233
- this->max_displaybuffer_[chip_line].push_back(this->max_displaybuffer_[chip_line].front());
234
- this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
235
- }
235
+ scroll(this->max_displaybuffer_[chip_line],
236
+ (this->stepsleft_ + 1) % (this->max_displaybuffer_[chip_line].size()));
236
237
  } else {
237
- this->max_displaybuffer_[chip_line].push_back(this->max_displaybuffer_[chip_line].front());
238
- this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
238
+ scroll(this->max_displaybuffer_[chip_line], 1);
239
239
  }
240
240
  }
241
241
  this->update_ = false;
242
242
  this->stepsleft_++;
243
+ this->stepsleft_ %= this->max_displaybuffer_[0].size();
243
244
  }
244
245
 
245
246
  void MAX7219Component::send_char(uint8_t chip, uint8_t data) {
@@ -35,8 +35,8 @@ SERVICE_SCHEMA = cv.Schema(
35
35
  {
36
36
  cv.Required(CONF_SERVICE): cv.string,
37
37
  cv.Required(CONF_PROTOCOL): cv.string,
38
- cv.Optional(CONF_PORT, default=0): cv.Any(0, cv.port),
39
- cv.Optional(CONF_TXT, default={}): {cv.string: cv.string},
38
+ cv.Optional(CONF_PORT, default=0): cv.templatable(cv.Any(0, cv.port)),
39
+ cv.Optional(CONF_TXT, default={}): {cv.string: cv.templatable(cv.string)},
40
40
  }
41
41
  )
42
42
 
@@ -102,12 +102,18 @@ async def to_code(config):
102
102
 
103
103
  for service in config[CONF_SERVICES]:
104
104
  txt = [
105
- mdns_txt_record(txt_key, txt_value)
105
+ cg.StructInitializer(
106
+ MDNSTXTRecord,
107
+ ("key", txt_key),
108
+ ("value", await cg.templatable(txt_value, [], cg.std_string)),
109
+ )
106
110
  for txt_key, txt_value in service[CONF_TXT].items()
107
111
  ]
108
-
109
112
  exp = mdns_service(
110
- service[CONF_SERVICE], service[CONF_PROTOCOL], service[CONF_PORT], txt
113
+ service[CONF_SERVICE],
114
+ service[CONF_PROTOCOL],
115
+ await cg.templatable(service[CONF_PORT], [], cg.uint16),
116
+ txt,
111
117
  )
112
118
 
113
119
  cg.add(var.add_extra_service(exp))
@@ -1,9 +1,9 @@
1
1
  #include "esphome/core/defines.h"
2
2
  #ifdef USE_MDNS
3
- #include "mdns_component.h"
4
- #include "esphome/core/version.h"
5
3
  #include "esphome/core/application.h"
6
4
  #include "esphome/core/log.h"
5
+ #include "esphome/core/version.h"
6
+ #include "mdns_component.h"
7
7
 
8
8
  #ifdef USE_API
9
9
  #include "esphome/components/api/api_server.h"
@@ -62,7 +62,11 @@ void MDNSComponent::compile_records_() {
62
62
  #endif
63
63
 
64
64
  #ifdef USE_API_NOISE
65
- service.txt_records.push_back({"api_encryption", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"});
65
+ if (api::global_api_server->get_noise_ctx()->has_psk()) {
66
+ service.txt_records.push_back({"api_encryption", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"});
67
+ } else {
68
+ service.txt_records.push_back({"api_encryption_supported", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"});
69
+ }
66
70
  #endif
67
71
 
68
72
  #ifdef ESPHOME_PROJECT_NAME
@@ -117,9 +121,11 @@ void MDNSComponent::dump_config() {
117
121
  ESP_LOGCONFIG(TAG, " Hostname: %s", this->hostname_.c_str());
118
122
  ESP_LOGV(TAG, " Services:");
119
123
  for (const auto &service : this->services_) {
120
- ESP_LOGV(TAG, " - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(), service.port);
124
+ ESP_LOGV(TAG, " - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(),
125
+ const_cast<TemplatableValue<uint16_t> &>(service.port).value());
121
126
  for (const auto &record : service.txt_records) {
122
- ESP_LOGV(TAG, " TXT: %s = %s", record.key.c_str(), record.value.c_str());
127
+ ESP_LOGV(TAG, " TXT: %s = %s", record.key.c_str(),
128
+ const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
123
129
  }
124
130
  }
125
131
  }
@@ -3,6 +3,7 @@
3
3
  #ifdef USE_MDNS
4
4
  #include <string>
5
5
  #include <vector>
6
+ #include "esphome/core/automation.h"
6
7
  #include "esphome/core/component.h"
7
8
 
8
9
  namespace esphome {
@@ -10,7 +11,7 @@ namespace mdns {
10
11
 
11
12
  struct MDNSTXTRecord {
12
13
  std::string key;
13
- std::string value;
14
+ TemplatableValue<std::string> value;
14
15
  };
15
16
 
16
17
  struct MDNSService {
@@ -20,7 +21,7 @@ struct MDNSService {
20
21
  // second label indicating protocol _including_ underscore character prefix
21
22
  // as defined in RFC6763 Section 7, like "_tcp" or "_udp"
22
23
  std::string proto;
23
- uint16_t port;
24
+ TemplatableValue<uint16_t> port;
24
25
  std::vector<MDNSTXTRecord> txt_records;
25
26
  };
26
27
 
@@ -31,11 +31,12 @@ void MDNSComponent::setup() {
31
31
  mdns_txt_item_t it{};
32
32
  // dup strings to ensure the pointer is valid even after the record loop
33
33
  it.key = strdup(record.key.c_str());
34
- it.value = strdup(record.value.c_str());
34
+ it.value = strdup(const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
35
35
  txt_records.push_back(it);
36
36
  }
37
- err = mdns_service_add(nullptr, service.service_type.c_str(), service.proto.c_str(), service.port,
38
- txt_records.data(), txt_records.size());
37
+ uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
38
+ err = mdns_service_add(nullptr, service.service_type.c_str(), service.proto.c_str(), port, txt_records.data(),
39
+ txt_records.size());
39
40
 
40
41
  // free records
41
42
  for (const auto &it : txt_records) {
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
29
29
  while (*service_type == '_') {
30
30
  service_type++;
31
31
  }
32
- MDNS.addService(service_type, proto, service.port);
32
+ uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
33
+ MDNS.addService(service_type, proto, port);
33
34
  for (const auto &record : service.txt_records) {
34
- MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str());
35
+ MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
36
+ const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
35
37
  }
36
38
  }
37
39
  }
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
29
29
  while (*service_type == '_') {
30
30
  service_type++;
31
31
  }
32
- MDNS.addService(service_type, proto, service.port);
32
+ uint16_t port_ = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
33
+ MDNS.addService(service_type, proto, port_);
33
34
  for (const auto &record : service.txt_records) {
34
- MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str());
35
+ MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
36
+ const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
35
37
  }
36
38
  }
37
39
  }
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
29
29
  while (*service_type == '_') {
30
30
  service_type++;
31
31
  }
32
- MDNS.addService(service_type, proto, service.port);
32
+ uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
33
+ MDNS.addService(service_type, proto, port);
33
34
  for (const auto &record : service.txt_records) {
34
- MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str());
35
+ MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
36
+ const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
35
37
  }
36
38
  }
37
39
  }
@@ -2,6 +2,8 @@ from esphome import automation
2
2
  import esphome.codegen as cg
3
3
  import esphome.config_validation as cv
4
4
  from esphome.const import (
5
+ CONF_ENTITY_CATEGORY,
6
+ CONF_ICON,
5
7
  CONF_ID,
6
8
  CONF_ON_IDLE,
7
9
  CONF_ON_STATE,
@@ -10,6 +12,7 @@ from esphome.const import (
10
12
  )
11
13
  from esphome.core import CORE
12
14
  from esphome.coroutine import coroutine_with_priority
15
+ from esphome.cpp_generator import MockObjClass
13
16
  from esphome.cpp_helpers import setup_entity
14
17
 
15
18
  CODEOWNERS = ["@jesserockz"]
@@ -103,7 +106,13 @@ async def register_media_player(var, config):
103
106
  await setup_media_player_core_(var, config)
104
107
 
105
108
 
106
- MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
109
+ async def new_media_player(config, *args):
110
+ var = cg.new_Pvariable(config[CONF_ID], *args)
111
+ await register_media_player(var, config)
112
+ return var
113
+
114
+
115
+ _MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
107
116
  {
108
117
  cv.Optional(CONF_ON_STATE): automation.validate_automation(
109
118
  {
@@ -134,6 +143,29 @@ MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
134
143
  )
135
144
 
136
145
 
146
+ def media_player_schema(
147
+ class_: MockObjClass,
148
+ *,
149
+ entity_category: str = cv.UNDEFINED,
150
+ icon: str = cv.UNDEFINED,
151
+ ) -> cv.Schema:
152
+ schema = {cv.GenerateID(CONF_ID): cv.declare_id(class_)}
153
+
154
+ for key, default, validator in [
155
+ (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
156
+ (CONF_ICON, icon, cv.icon),
157
+ ]:
158
+ if default is not cv.UNDEFINED:
159
+ schema[cv.Optional(key, default=default)] = validator
160
+
161
+ return _MEDIA_PLAYER_SCHEMA.extend(schema)
162
+
163
+
164
+ # Remove before 2025.11.0
165
+ MEDIA_PLAYER_SCHEMA = media_player_schema(MediaPlayer)
166
+ MEDIA_PLAYER_SCHEMA.add_extra(cv.deprecated_schema_constant("media_player"))
167
+
168
+
137
169
  MEDIA_PLAYER_ACTION_SCHEMA = automation.maybe_simple_id(
138
170
  cv.Schema(
139
171
  {
@@ -32,7 +32,7 @@ CONFIG_SCHEMA = (
32
32
  cv.Schema(
33
33
  {
34
34
  cv.GenerateID(): cv.declare_id(MHZ19Component),
35
- cv.Required(CONF_CO2): sensor.sensor_schema(
35
+ cv.Optional(CONF_CO2): sensor.sensor_schema(
36
36
  unit_of_measurement=UNIT_PARTS_PER_MILLION,
37
37
  icon=ICON_MOLECULE_CO2,
38
38
  accuracy_decimals=0,
@@ -61,16 +61,20 @@ async def to_code(config):
61
61
  await cg.register_component(var, config)
62
62
  await uart.register_uart_device(var, config)
63
63
 
64
- if CONF_CO2 in config:
65
- sens = await sensor.new_sensor(config[CONF_CO2])
64
+ if co2 := config.get(CONF_CO2):
65
+ sens = await sensor.new_sensor(co2)
66
66
  cg.add(var.set_co2_sensor(sens))
67
67
 
68
- if CONF_TEMPERATURE in config:
69
- sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
68
+ if temperature := config.get(CONF_TEMPERATURE):
69
+ sens = await sensor.new_sensor(temperature)
70
70
  cg.add(var.set_temperature_sensor(sens))
71
71
 
72
- if CONF_AUTOMATIC_BASELINE_CALIBRATION in config:
73
- cg.add(var.set_abc_enabled(config[CONF_AUTOMATIC_BASELINE_CALIBRATION]))
72
+ if (
73
+ automatic_baseline_calibration := config.get(
74
+ CONF_AUTOMATIC_BASELINE_CALIBRATION
75
+ )
76
+ ) is not None:
77
+ cg.add(var.set_abc_enabled(automatic_baseline_calibration))
74
78
 
75
79
  cg.add(var.set_warmup_seconds(config[CONF_WARMUP_TIME]))
76
80