esphome 2025.4.1__py3-none-any.whl → 2025.5.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  2. esphome/components/adc/__init__.py +51 -34
  3. esphome/components/airthings_wave_base/__init__.py +1 -1
  4. esphome/components/alarm_control_panel/__init__.py +37 -2
  5. esphome/components/am43/cover/__init__.py +4 -5
  6. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  8. esphome/components/analog_threshold/binary_sensor.py +10 -8
  9. esphome/components/anova/climate.py +4 -5
  10. esphome/components/api/__init__.py +25 -8
  11. esphome/components/api/api_connection.cpp +77 -10
  12. esphome/components/api/api_connection.h +6 -1
  13. esphome/components/api/api_frame_helper.cpp +98 -130
  14. esphome/components/api/api_frame_helper.h +12 -2
  15. esphome/components/api/api_noise_context.h +13 -4
  16. esphome/components/api/api_pb2.cpp +1422 -1
  17. esphome/components/api/api_pb2.h +255 -1
  18. esphome/components/api/api_pb2_service.cpp +162 -49
  19. esphome/components/api/api_pb2_service.h +90 -51
  20. esphome/components/api/api_pb2_size.h +361 -0
  21. esphome/components/api/api_server.cpp +110 -34
  22. esphome/components/api/api_server.h +8 -0
  23. esphome/components/api/proto.h +38 -9
  24. esphome/components/as3935_i2c/as3935_i2c.h +0 -3
  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/climate/__init__.py +3 -8
  45. esphome/components/bedjet/fan/__init__.py +2 -11
  46. esphome/components/binary/fan/__init__.py +13 -16
  47. esphome/components/binary_sensor/__init__.py +13 -10
  48. esphome/components/binary_sensor/binary_sensor.cpp +6 -10
  49. esphome/components/binary_sensor/binary_sensor.h +1 -1
  50. esphome/components/binary_sensor/filter.cpp +21 -21
  51. esphome/components/binary_sensor/filter.h +10 -10
  52. esphome/components/bl0906/constants.h +16 -16
  53. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  54. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  55. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +135 -21
  56. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  57. esphome/components/button/__init__.py +11 -8
  58. esphome/components/canbus/canbus.cpp +3 -0
  59. esphome/components/canbus/canbus.h +16 -0
  60. esphome/components/climate/__init__.py +35 -2
  61. esphome/components/climate/climate_mode.h +1 -1
  62. esphome/components/climate/climate_traits.h +63 -57
  63. esphome/components/climate_ir/__init__.py +57 -17
  64. esphome/components/climate_ir_lg/climate.py +2 -5
  65. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  66. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  67. esphome/components/color/__init__.py +2 -0
  68. esphome/components/const/__init__.py +5 -0
  69. esphome/components/coolix/climate.py +2 -9
  70. esphome/components/copy/cover/__init__.py +10 -9
  71. esphome/components/copy/fan/__init__.py +11 -9
  72. esphome/components/copy/lock/__init__.py +11 -9
  73. esphome/components/copy/text/__init__.py +9 -6
  74. esphome/components/cover/__init__.py +37 -2
  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/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/debug/debug_component.cpp +5 -0
  89. esphome/components/debug/debug_component.h +6 -0
  90. esphome/components/debug/debug_esp32.cpp +109 -254
  91. esphome/components/debug/sensor.py +14 -0
  92. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  93. esphome/components/delonghi/climate.py +2 -9
  94. esphome/components/demo/__init__.py +18 -20
  95. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  96. esphome/components/display/rect.cpp +4 -9
  97. esphome/components/display/rect.h +1 -1
  98. esphome/components/emmeti/climate.py +2 -9
  99. esphome/components/endstop/cover.py +17 -16
  100. esphome/components/esp32/__init__.py +60 -3
  101. esphome/components/esp32/core.cpp +11 -5
  102. esphome/components/esp32/gpio.cpp +86 -24
  103. esphome/components/esp32/gpio.py +15 -16
  104. esphome/components/esp32/gpio_esp32.py +1 -2
  105. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  106. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  107. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  108. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  109. esphome/components/esp32_ble/ble.cpp +1 -8
  110. esphome/components/esp32_ble/ble.h +5 -3
  111. esphome/components/esp32_ble/ble_advertising.h +1 -0
  112. esphome/components/esp32_ble_server/__init__.py +3 -0
  113. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  114. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  115. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  116. esphome/components/esp32_can/esp32_can.cpp +1 -1
  117. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  118. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  119. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  120. esphome/components/esp8266/gpio.cpp +69 -8
  121. esphome/components/event/__init__.py +13 -10
  122. esphome/components/factory_reset/switch/__init__.py +7 -21
  123. esphome/components/fan/__init__.py +52 -5
  124. esphome/components/fastled_base/__init__.py +1 -4
  125. esphome/components/fastled_base/fastled_light.cpp +1 -1
  126. esphome/components/feedback/cover.py +38 -33
  127. esphome/components/fujitsu_general/climate.py +2 -9
  128. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  129. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  130. esphome/components/gpio_expander/cached_gpio.h +22 -7
  131. esphome/components/gps/__init__.py +11 -2
  132. esphome/components/gps/gps.cpp +11 -8
  133. esphome/components/gps/gps.h +9 -6
  134. esphome/components/graph/__init__.py +1 -2
  135. esphome/components/gree/climate.py +4 -6
  136. esphome/components/gree/gree.cpp +16 -2
  137. esphome/components/gree/gree.h +2 -2
  138. esphome/components/haier/climate.py +37 -34
  139. esphome/components/hbridge/fan/__init__.py +19 -17
  140. esphome/components/he60r/cover.py +4 -5
  141. esphome/components/heatpumpir/climate.py +3 -6
  142. esphome/components/hitachi_ac344/climate.py +2 -9
  143. esphome/components/hitachi_ac424/climate.py +2 -9
  144. esphome/components/hlw8012/hlw8012.cpp +1 -1
  145. esphome/components/hm3301/hm3301.h +1 -1
  146. esphome/components/http_request/__init__.py +39 -6
  147. esphome/components/http_request/http_request.cpp +20 -0
  148. esphome/components/http_request/http_request.h +57 -15
  149. esphome/components/http_request/http_request_arduino.cpp +22 -6
  150. esphome/components/http_request/http_request_arduino.h +4 -3
  151. esphome/components/http_request/http_request_host.cpp +141 -0
  152. esphome/components/http_request/http_request_host.h +37 -0
  153. esphome/components/http_request/http_request_idf.cpp +35 -3
  154. esphome/components/http_request/http_request_idf.h +10 -3
  155. esphome/components/http_request/httplib.h +9691 -0
  156. esphome/components/http_request/update/__init__.py +11 -8
  157. esphome/components/i2c/i2c.h +4 -0
  158. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  159. esphome/components/i2s_audio/__init__.py +131 -22
  160. esphome/components/i2s_audio/i2s_audio.h +44 -4
  161. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  162. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  163. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  164. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  165. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  166. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  167. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  168. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  169. esphome/components/image/__init__.py +37 -17
  170. esphome/components/image/image.cpp +25 -8
  171. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  172. esphome/components/key_collector/__init__.py +35 -0
  173. esphome/components/key_collector/key_collector.cpp +8 -0
  174. esphome/components/key_collector/key_collector.h +10 -0
  175. esphome/components/ld2410/ld2410.h +1 -1
  176. esphome/components/ld2450/ld2450.h +1 -1
  177. esphome/components/light/__init__.py +57 -0
  178. esphome/components/lock/__init__.py +51 -4
  179. esphome/components/lock/automation.h +2 -13
  180. esphome/components/logger/__init__.py +21 -0
  181. esphome/components/logger/logger.cpp +125 -95
  182. esphome/components/logger/logger.h +160 -35
  183. esphome/components/logger/task_log_buffer.cpp +138 -0
  184. esphome/components/logger/task_log_buffer.h +69 -0
  185. esphome/components/lvgl/__init__.py +13 -5
  186. esphome/components/lvgl/automation.py +50 -1
  187. esphome/components/lvgl/defines.py +0 -1
  188. esphome/components/lvgl/lv_validation.py +10 -1
  189. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  190. esphome/components/lvgl/schemas.py +14 -14
  191. esphome/components/lvgl/text/__init__.py +1 -2
  192. esphome/components/lvgl/widgets/arc.py +7 -6
  193. esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
  194. esphome/components/lvgl/widgets/checkbox.py +2 -2
  195. esphome/components/lvgl/widgets/dropdown.py +2 -1
  196. esphome/components/lvgl/widgets/img.py +15 -12
  197. esphome/components/mapping/__init__.py +134 -0
  198. esphome/components/max7219digit/max7219digit.cpp +27 -27
  199. esphome/components/mdns/__init__.py +11 -5
  200. esphome/components/mdns/mdns_component.cpp +11 -5
  201. esphome/components/mdns/mdns_component.h +3 -2
  202. esphome/components/mdns/mdns_esp32.cpp +4 -3
  203. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  204. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  205. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  206. esphome/components/media_player/__init__.py +40 -6
  207. esphome/components/micro_wake_word/__init__.py +99 -31
  208. esphome/components/micro_wake_word/automation.h +54 -0
  209. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  210. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  211. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  212. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  213. esphome/components/micro_wake_word/streaming_model.h +85 -13
  214. esphome/components/microphone/__init__.py +139 -9
  215. esphome/components/microphone/automation.h +14 -2
  216. esphome/components/microphone/microphone.cpp +21 -0
  217. esphome/components/microphone/microphone.h +14 -5
  218. esphome/components/microphone/microphone_source.cpp +95 -0
  219. esphome/components/microphone/microphone_source.h +80 -0
  220. esphome/components/mics_4514/sensor.py +25 -14
  221. esphome/components/midea/climate.py +3 -4
  222. esphome/components/midea_ir/climate.py +3 -5
  223. esphome/components/mipi_spi/__init__.py +15 -0
  224. esphome/components/mipi_spi/display.py +474 -0
  225. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  226. esphome/components/mipi_spi/mipi_spi.h +171 -0
  227. esphome/components/mipi_spi/models/__init__.py +65 -0
  228. esphome/components/mipi_spi/models/amoled.py +72 -0
  229. esphome/components/mipi_spi/models/commands.py +82 -0
  230. esphome/components/mipi_spi/models/cyd.py +10 -0
  231. esphome/components/mipi_spi/models/ili.py +749 -0
  232. esphome/components/mipi_spi/models/jc.py +260 -0
  233. esphome/components/mipi_spi/models/lanbon.py +15 -0
  234. esphome/components/mipi_spi/models/lilygo.py +60 -0
  235. esphome/components/mipi_spi/models/waveshare.py +139 -0
  236. esphome/components/mitsubishi/climate.py +2 -5
  237. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  238. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  239. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  240. esphome/components/mlx90393/sensor.py +5 -0
  241. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  242. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  243. esphome/components/mqtt/__init__.py +1 -1
  244. esphome/components/mqtt/mqtt_client.cpp +5 -1
  245. esphome/components/mqtt/mqtt_const.h +4 -0
  246. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  247. esphome/components/mqtt/mqtt_fan.h +2 -0
  248. esphome/components/network/__init__.py +1 -1
  249. esphome/components/nextion/base_component.py +17 -16
  250. esphome/components/nextion/display.py +11 -2
  251. esphome/components/nextion/nextion.cpp +39 -1
  252. esphome/components/nextion/nextion.h +50 -0
  253. esphome/components/noblex/climate.py +2 -9
  254. esphome/components/number/__init__.py +12 -9
  255. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  256. esphome/components/one_wire/one_wire_bus.h +14 -8
  257. esphome/components/online_image/bmp_image.cpp +48 -11
  258. esphome/components/online_image/bmp_image.h +2 -0
  259. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  260. esphome/components/opentherm/number/__init__.py +11 -20
  261. esphome/components/opentherm/sensor/__init__.py +3 -3
  262. esphome/components/opentherm/switch/__init__.py +3 -5
  263. esphome/components/output/lock/__init__.py +11 -9
  264. esphome/components/packages/__init__.py +33 -31
  265. esphome/components/packet_transport/__init__.py +201 -0
  266. esphome/components/packet_transport/binary_sensor.py +19 -0
  267. esphome/components/packet_transport/packet_transport.cpp +534 -0
  268. esphome/components/packet_transport/packet_transport.h +154 -0
  269. esphome/components/packet_transport/sensor.py +19 -0
  270. esphome/components/pca9685/pca9685_output.cpp +2 -1
  271. esphome/components/pid/climate.py +2 -4
  272. esphome/components/pm2005/__init__.py +1 -0
  273. esphome/components/pm2005/pm2005.cpp +123 -0
  274. esphome/components/pm2005/pm2005.h +46 -0
  275. esphome/components/pm2005/sensor.py +86 -0
  276. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  277. esphome/components/pmsa003i/pmsa003i.h +25 -25
  278. esphome/components/pmsx003/pmsx003.cpp +193 -229
  279. esphome/components/pmsx003/pmsx003.h +51 -33
  280. esphome/components/pmsx003/sensor.py +21 -11
  281. esphome/components/pn7150/pn7150.h +2 -2
  282. esphome/components/pn7160/pn7160.h +2 -2
  283. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  284. esphome/components/prometheus/prometheus_handler.h +17 -0
  285. esphome/components/psram/__init__.py +7 -5
  286. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  287. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  288. esphome/components/qspi_dbi/__init__.py +0 -1
  289. esphome/components/qspi_dbi/display.py +2 -1
  290. esphome/components/qspi_dbi/models.py +1 -2
  291. esphome/components/remote_base/__init__.py +91 -0
  292. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  293. esphome/components/remote_base/beo4_protocol.h +43 -0
  294. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  295. esphome/components/remote_base/gobox_protocol.h +54 -0
  296. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  297. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  298. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  299. esphome/components/scd30/sensor.py +2 -3
  300. esphome/components/scd4x/sensor.py +4 -5
  301. esphome/components/sdp3x/sensor.py +2 -1
  302. esphome/components/select/__init__.py +19 -20
  303. esphome/components/sen5x/sensor.py +1 -1
  304. esphome/components/sensor/__init__.py +158 -14
  305. esphome/components/sensor/filter.cpp +23 -0
  306. esphome/components/sensor/filter.h +22 -0
  307. esphome/components/sgp4x/sensor.py +1 -1
  308. esphome/components/sht4x/sht4x.cpp +43 -22
  309. esphome/components/sht4x/sht4x.h +1 -1
  310. esphome/components/sml/text_sensor/__init__.py +4 -6
  311. esphome/components/sound_level/__init__.py +0 -0
  312. esphome/components/sound_level/sensor.py +97 -0
  313. esphome/components/sound_level/sound_level.cpp +194 -0
  314. esphome/components/sound_level/sound_level.h +73 -0
  315. esphome/components/speaker/media_player/__init__.py +4 -8
  316. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  317. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  318. esphome/components/speaker/speaker.h +4 -7
  319. esphome/components/speed/fan/__init__.py +17 -16
  320. esphome/components/spi/spi.h +11 -1
  321. esphome/components/sprinkler/__init__.py +18 -19
  322. esphome/components/switch/__init__.py +32 -42
  323. esphome/components/syslog/__init__.py +41 -0
  324. esphome/components/syslog/esphome_syslog.cpp +49 -0
  325. esphome/components/syslog/esphome_syslog.h +27 -0
  326. esphome/components/tca9555/tca9555.cpp +11 -6
  327. esphome/components/tcl112/climate.py +2 -9
  328. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  329. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  330. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  331. esphome/components/template/cover/__init__.py +27 -21
  332. esphome/components/template/fan/__init__.py +14 -12
  333. esphome/components/template/lock/__init__.py +20 -25
  334. esphome/components/template/lock/automation.h +18 -0
  335. esphome/components/template/text/__init__.py +4 -3
  336. esphome/components/template/valve/__init__.py +32 -21
  337. esphome/components/template/valve/automation.h +24 -0
  338. esphome/components/text/__init__.py +32 -1
  339. esphome/components/text_sensor/__init__.py +24 -29
  340. esphome/components/thermostat/climate.py +5 -5
  341. esphome/components/time_based/cover.py +17 -16
  342. esphome/components/tm1638/switch/__init__.py +10 -7
  343. esphome/components/tormatic/cover.py +4 -5
  344. esphome/components/toshiba/climate.py +3 -5
  345. esphome/components/touchscreen/touchscreen.cpp +3 -1
  346. esphome/components/tt21100/touchscreen/tt21100.cpp +1 -1
  347. esphome/components/tuya/climate/__init__.py +5 -6
  348. esphome/components/tuya/cover/__init__.py +6 -11
  349. esphome/components/tuya/select/__init__.py +15 -5
  350. esphome/components/tuya/select/tuya_select.cpp +6 -1
  351. esphome/components/tuya/select/tuya_select.h +5 -1
  352. esphome/components/uart/packet_transport/__init__.py +20 -0
  353. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  354. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  355. esphome/components/udp/__init__.py +126 -128
  356. esphome/components/udp/automation.h +40 -0
  357. esphome/components/udp/binary_sensor.py +3 -25
  358. esphome/components/udp/packet_transport/__init__.py +29 -0
  359. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  360. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  361. esphome/components/udp/sensor.py +3 -25
  362. esphome/components/udp/udp_component.cpp +26 -470
  363. esphome/components/udp/udp_component.h +21 -128
  364. esphome/components/update/__init__.py +31 -1
  365. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  366. esphome/components/uptime/text_sensor/__init__.py +47 -7
  367. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  368. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  369. esphome/components/valve/__init__.py +34 -3
  370. esphome/components/valve/automation.h +1 -19
  371. esphome/components/vl53l0x/sensor.py +11 -0
  372. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  373. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  374. esphome/components/voice_assistant/__init__.py +36 -10
  375. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  376. esphome/components/voice_assistant/voice_assistant.h +26 -25
  377. esphome/components/waveshare_epaper/display.py +6 -0
  378. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  379. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  380. esphome/components/whirlpool/climate.py +3 -5
  381. esphome/components/whynter/climate.py +3 -5
  382. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  383. esphome/components/yashima/climate.py +6 -6
  384. esphome/components/zhlt01/climate.py +2 -7
  385. esphome/config_validation.py +38 -58
  386. esphome/const.py +15 -1
  387. esphome/core/__init__.py +2 -0
  388. esphome/core/application.cpp +1 -0
  389. esphome/core/application.h +4 -0
  390. esphome/core/automation.h +4 -3
  391. esphome/core/component.cpp +19 -3
  392. esphome/core/component.h +5 -0
  393. esphome/core/defines.h +23 -17
  394. esphome/core/macros.h +4 -0
  395. esphome/core/scheduler.cpp +3 -0
  396. esphome/cpp_generator.py +6 -2
  397. esphome/dashboard/web_server.py +3 -3
  398. esphome/helpers.py +39 -0
  399. esphome/loader.py +4 -0
  400. esphome/mqtt.py +21 -8
  401. esphome/platformio_api.py +1 -1
  402. esphome/schema_extractors.py +0 -1
  403. esphome/vscode.py +15 -0
  404. esphome/wizard.py +2 -2
  405. esphome/zeroconf.py +7 -3
  406. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/METADATA +10 -11
  407. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/RECORD +411 -352
  408. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/WHEEL +1 -1
  409. esphome/components/esp32_ble/const_esp32c6.h +0 -74
  410. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/entry_points.txt +0 -0
  411. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/licenses/LICENSE +0 -0
  412. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,194 @@
1
+ #include "sound_level.h"
2
+
3
+ #ifdef USE_ESP32
4
+
5
+ #include "esphome/core/log.h"
6
+
7
+ #include <cmath>
8
+ #include <cstdint>
9
+
10
+ namespace esphome {
11
+ namespace sound_level {
12
+
13
+ static const char *const TAG = "sound_level";
14
+
15
+ static const uint32_t AUDIO_BUFFER_DURATION_MS = 30;
16
+ static const uint32_t RING_BUFFER_DURATION_MS = 120;
17
+
18
+ // Square INT16_MIN since INT16_MIN^2 > INT16_MAX^2
19
+ static const double MAX_SAMPLE_SQUARED_DENOMINATOR = INT16_MIN * INT16_MIN;
20
+
21
+ void SoundLevelComponent::dump_config() {
22
+ ESP_LOGCONFIG(TAG, "Sound Level Component:");
23
+ ESP_LOGCONFIG(TAG, " Measurement Duration: %" PRIu32 " ms", measurement_duration_ms_);
24
+ LOG_SENSOR(" ", "Peak:", this->peak_sensor_);
25
+
26
+ LOG_SENSOR(" ", "RMS:", this->rms_sensor_);
27
+ }
28
+
29
+ void SoundLevelComponent::setup() {
30
+ this->microphone_source_->add_data_callback([this](const std::vector<uint8_t> &data) {
31
+ std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock();
32
+ if (this->ring_buffer_.use_count() == 2) {
33
+ // ``audio_buffer_`` and ``temp_ring_buffer`` share ownership of a ring buffer, so its safe/useful to write
34
+ temp_ring_buffer->write((void *) data.data(), data.size());
35
+ }
36
+ });
37
+
38
+ if (!this->microphone_source_->is_passive()) {
39
+ // Automatically start the microphone if not in passive mode
40
+ this->microphone_source_->start();
41
+ }
42
+ }
43
+
44
+ void SoundLevelComponent::loop() {
45
+ if ((this->peak_sensor_ == nullptr) && (this->rms_sensor_ == nullptr)) {
46
+ // No sensors configured, nothing to do
47
+ return;
48
+ }
49
+
50
+ if (this->microphone_source_->is_running() && !this->status_has_error()) {
51
+ // Allocate buffers
52
+ if (this->start_()) {
53
+ this->status_clear_warning();
54
+ }
55
+ } else {
56
+ if (!this->status_has_warning()) {
57
+ this->status_set_warning("Microphone isn't running, can't compute statistics");
58
+
59
+ // Deallocate buffers, if necessary
60
+ this->stop_();
61
+
62
+ // Reset sensor outputs
63
+ if (this->peak_sensor_ != nullptr) {
64
+ this->peak_sensor_->publish_state(NAN);
65
+ }
66
+ if (this->rms_sensor_ != nullptr) {
67
+ this->rms_sensor_->publish_state(NAN);
68
+ }
69
+
70
+ // Reset accumulators
71
+ this->squared_peak_ = 0;
72
+ this->squared_samples_sum_ = 0;
73
+ this->sample_count_ = 0;
74
+ }
75
+
76
+ return;
77
+ }
78
+
79
+ if (this->status_has_error()) {
80
+ return;
81
+ }
82
+
83
+ // Copy data from ring buffer into the transfer buffer - don't block to avoid slowing the main loop
84
+ this->audio_buffer_->transfer_data_from_source(0);
85
+
86
+ if (this->audio_buffer_->available() == 0) {
87
+ // No new audio available for processing
88
+ return;
89
+ }
90
+
91
+ const uint32_t samples_in_window =
92
+ this->microphone_source_->get_audio_stream_info().ms_to_samples(this->measurement_duration_ms_);
93
+ const uint32_t samples_available_to_process =
94
+ this->microphone_source_->get_audio_stream_info().bytes_to_samples(this->audio_buffer_->available());
95
+ const uint32_t samples_to_process = std::min(samples_in_window - this->sample_count_, samples_available_to_process);
96
+
97
+ // MicrophoneSource always provides int16 samples due to Python codegen settings
98
+ const int16_t *audio_data = reinterpret_cast<const int16_t *>(this->audio_buffer_->get_buffer_start());
99
+
100
+ // Process all the new audio samples
101
+ for (uint32_t i = 0; i < samples_to_process; ++i) {
102
+ // Squaring int16 samples won't overflow an int32
103
+ int32_t squared_sample = static_cast<int32_t>(audio_data[i]) * static_cast<int32_t>(audio_data[i]);
104
+
105
+ if (this->peak_sensor_ != nullptr) {
106
+ this->squared_peak_ = std::max(this->squared_peak_, squared_sample);
107
+ }
108
+
109
+ if (this->rms_sensor_ != nullptr) {
110
+ // Squared sum is an uint64 type - at max levels, an uint32 type would overflow after ~8 samples
111
+ this->squared_samples_sum_ += squared_sample;
112
+ }
113
+
114
+ ++this->sample_count_;
115
+ }
116
+
117
+ // Remove the processed samples from ``audio_buffer_``
118
+ this->audio_buffer_->decrease_buffer_length(
119
+ this->microphone_source_->get_audio_stream_info().samples_to_bytes(samples_to_process));
120
+
121
+ if (this->sample_count_ == samples_in_window) {
122
+ // Processed enough samples for the measurement window, compute and publish the sensor values
123
+ if (this->peak_sensor_ != nullptr) {
124
+ const float peak_db = 10.0f * log10(static_cast<float>(this->squared_peak_) / MAX_SAMPLE_SQUARED_DENOMINATOR);
125
+ this->peak_sensor_->publish_state(peak_db);
126
+
127
+ this->squared_peak_ = 0; // reset accumulator
128
+ }
129
+
130
+ if (this->rms_sensor_ != nullptr) {
131
+ // Calculations are done with doubles instead of floats - floats lose precision for even modest window durations
132
+ const double rms_db = 10.0 * log10((this->squared_samples_sum_ / MAX_SAMPLE_SQUARED_DENOMINATOR) /
133
+ static_cast<double>(samples_in_window));
134
+ this->rms_sensor_->publish_state(rms_db);
135
+
136
+ this->squared_samples_sum_ = 0; // reset accumulator
137
+ }
138
+
139
+ this->sample_count_ = 0; // reset counter
140
+ }
141
+ }
142
+
143
+ void SoundLevelComponent::start() {
144
+ if (this->microphone_source_->is_passive()) {
145
+ ESP_LOGW(TAG, "Can't start the microphone in passive mode");
146
+ return;
147
+ }
148
+ this->microphone_source_->start();
149
+ }
150
+
151
+ void SoundLevelComponent::stop() {
152
+ if (this->microphone_source_->is_passive()) {
153
+ ESP_LOGW(TAG, "Can't stop microphone in passive mode");
154
+ return;
155
+ }
156
+ this->microphone_source_->stop();
157
+ }
158
+
159
+ bool SoundLevelComponent::start_() {
160
+ if (this->audio_buffer_ != nullptr) {
161
+ return true;
162
+ }
163
+
164
+ // Allocate a transfer buffer
165
+ this->audio_buffer_ = audio::AudioSourceTransferBuffer::create(
166
+ this->microphone_source_->get_audio_stream_info().ms_to_bytes(AUDIO_BUFFER_DURATION_MS));
167
+ if (this->audio_buffer_ == nullptr) {
168
+ this->status_momentary_error("Failed to allocate transfer buffer", 15000);
169
+ return false;
170
+ }
171
+
172
+ // Allocates a new ring buffer, adds it as a source for the transfer buffer, and points ring_buffer_ to it
173
+ this->ring_buffer_.reset(); // Reset pointer to any previous ring buffer allocation
174
+ std::shared_ptr<RingBuffer> temp_ring_buffer =
175
+ RingBuffer::create(this->microphone_source_->get_audio_stream_info().ms_to_bytes(RING_BUFFER_DURATION_MS));
176
+ if (temp_ring_buffer.use_count() == 0) {
177
+ this->status_momentary_error("Failed to allocate ring buffer", 15000);
178
+ this->stop_();
179
+ return false;
180
+ } else {
181
+ this->ring_buffer_ = temp_ring_buffer;
182
+ this->audio_buffer_->set_source(temp_ring_buffer);
183
+ }
184
+
185
+ this->status_clear_error();
186
+ return true;
187
+ }
188
+
189
+ void SoundLevelComponent::stop_() { this->audio_buffer_.reset(); }
190
+
191
+ } // namespace sound_level
192
+ } // namespace esphome
193
+
194
+ #endif
@@ -0,0 +1,73 @@
1
+ #pragma once
2
+
3
+ #ifdef USE_ESP32
4
+
5
+ #include "esphome/components/audio/audio_transfer_buffer.h"
6
+ #include "esphome/components/microphone/microphone_source.h"
7
+ #include "esphome/components/sensor/sensor.h"
8
+
9
+ #include "esphome/core/component.h"
10
+ #include "esphome/core/ring_buffer.h"
11
+
12
+ namespace esphome {
13
+ namespace sound_level {
14
+
15
+ class SoundLevelComponent : public Component {
16
+ public:
17
+ void dump_config() override;
18
+ void setup() override;
19
+ void loop() override;
20
+
21
+ float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; }
22
+
23
+ void set_measurement_duration(uint32_t measurement_duration_ms) {
24
+ this->measurement_duration_ms_ = measurement_duration_ms;
25
+ }
26
+ void set_microphone_source(microphone::MicrophoneSource *microphone_source) {
27
+ this->microphone_source_ = microphone_source;
28
+ }
29
+ void set_peak_sensor(sensor::Sensor *peak_sensor) { this->peak_sensor_ = peak_sensor; }
30
+ void set_rms_sensor(sensor::Sensor *rms_sensor) { this->rms_sensor_ = rms_sensor; }
31
+
32
+ /// @brief Starts the MicrophoneSource to start measuring sound levels
33
+ void start();
34
+
35
+ /// @brief Stops the MicrophoneSource
36
+ void stop();
37
+
38
+ protected:
39
+ /// @brief Internal start command that, if necessary, allocates ``audio_buffer_`` and a ring buffer which
40
+ /// ``audio_buffer_`` owns and ``ring_buffer_`` points to. Returns true if allocations were successful.
41
+ bool start_();
42
+
43
+ /// @brief Internal stop command the deallocates ``audio_buffer_`` (which automatically deallocates its ring buffer)
44
+ void stop_();
45
+
46
+ microphone::MicrophoneSource *microphone_source_{nullptr};
47
+
48
+ sensor::Sensor *peak_sensor_{nullptr};
49
+ sensor::Sensor *rms_sensor_{nullptr};
50
+
51
+ std::unique_ptr<audio::AudioSourceTransferBuffer> audio_buffer_;
52
+ std::weak_ptr<RingBuffer> ring_buffer_;
53
+
54
+ int32_t squared_peak_{0};
55
+ uint64_t squared_samples_sum_{0};
56
+ uint32_t sample_count_{0};
57
+
58
+ uint32_t measurement_duration_ms_;
59
+ };
60
+
61
+ template<typename... Ts> class StartAction : public Action<Ts...>, public Parented<SoundLevelComponent> {
62
+ public:
63
+ void play(Ts... x) override { this->parent_->start(); }
64
+ };
65
+
66
+ template<typename... Ts> class StopAction : public Action<Ts...>, public Parented<SoundLevelComponent> {
67
+ public:
68
+ void play(Ts... x) override { this->parent_->stop(); }
69
+ };
70
+
71
+ } // namespace sound_level
72
+ } // namespace esphome
73
+ #endif
@@ -271,9 +271,8 @@ PIPELINE_SCHEMA = cv.Schema(
271
271
  )
272
272
 
273
273
  CONFIG_SCHEMA = cv.All(
274
- media_player.MEDIA_PLAYER_SCHEMA.extend(
274
+ media_player.media_player_schema(SpeakerMediaPlayer).extend(
275
275
  {
276
- cv.GenerateID(): cv.declare_id(SpeakerMediaPlayer),
277
276
  cv.Required(CONF_ANNOUNCEMENT_PIPELINE): PIPELINE_SCHEMA,
278
277
  cv.Optional(CONF_MEDIA_PIPELINE): PIPELINE_SCHEMA,
279
278
  cv.Optional(CONF_BUFFER_SIZE, default=1000000): cv.int_range(
@@ -332,22 +331,19 @@ async def to_code(config):
332
331
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSS", 1436)
333
332
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSL", 60000)
334
333
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_SND_BUF_DEFAULT", 65535)
335
- esp32.add_idf_sdkconfig_option(
336
- "CONFIG_TCP_WND_DEFAULT", 65535
337
- ) # Adjusted from referenced settings to avoid compilation error
334
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_WND_DEFAULT", 512000)
338
335
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_RECVMBOX_SIZE", 512)
339
336
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_QUEUE_OOSEQ", True)
340
337
  esp32.add_idf_sdkconfig_option("CONFIG_TCP_OVERSIZE_MSS", True)
341
338
  esp32.add_idf_sdkconfig_option("CONFIG_LWIP_WND_SCALE", True)
342
- esp32.add_idf_sdkconfig_option("CONFIG_TCP_RCV_SCALE", 3)
339
+ esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RCV_SCALE", 3)
343
340
  esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 512)
344
341
 
345
342
  # Allocate wifi buffers in PSRAM
346
343
  esp32.add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
347
344
 
348
- var = cg.new_Pvariable(config[CONF_ID])
345
+ var = await media_player.new_media_player(config)
349
346
  await cg.register_component(var, config)
350
- await media_player.register_media_player(var, config)
351
347
 
352
348
  cg.add_define("USE_OTA_STATE_CALLBACK")
353
349
 
@@ -106,16 +106,6 @@ void SpeakerMediaPlayer::setup() {
106
106
  ESP_LOGE(TAG, "Failed to create media pipeline");
107
107
  this->mark_failed();
108
108
  }
109
-
110
- // Setup callback to track the duration of audio played by the media pipeline
111
- this->media_speaker_->add_audio_output_callback(
112
- [this](uint32_t new_playback_ms, uint32_t remainder_us, uint32_t pending_ms, uint32_t write_timestamp) {
113
- this->playback_ms_ += new_playback_ms;
114
- this->remainder_us_ = remainder_us;
115
- this->pending_ms_ = pending_ms;
116
- this->last_audio_write_timestamp_ = write_timestamp;
117
- this->playback_us_ = this->playback_ms_ * 1000 + this->remainder_us_;
118
- });
119
109
  }
120
110
 
121
111
  ESP_LOGI(TAG, "Set up speaker media player");
@@ -321,7 +311,6 @@ void SpeakerMediaPlayer::loop() {
321
311
  AudioPipelineState old_media_pipeline_state = this->media_pipeline_state_;
322
312
  if (this->media_pipeline_ != nullptr) {
323
313
  this->media_pipeline_state_ = this->media_pipeline_->process_state();
324
- this->decoded_playback_ms_ = this->media_pipeline_->get_playback_ms();
325
314
  }
326
315
 
327
316
  if (this->media_pipeline_state_ == AudioPipelineState::ERROR_READING) {
@@ -379,13 +368,6 @@ void SpeakerMediaPlayer::loop() {
379
368
  } else if (this->media_pipeline_state_ == AudioPipelineState::PLAYING) {
380
369
  this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
381
370
  } else if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
382
- // Reset playback durations
383
- this->decoded_playback_ms_ = 0;
384
- this->playback_us_ = 0;
385
- this->playback_ms_ = 0;
386
- this->remainder_us_ = 0;
387
- this->pending_ms_ = 0;
388
-
389
371
  if (!media_playlist_.empty()) {
390
372
  uint32_t timeout_ms = 0;
391
373
  if (old_media_pipeline_state == AudioPipelineState::PLAYING) {
@@ -73,10 +73,6 @@ class SpeakerMediaPlayer : public Component, public media_player::MediaPlayer {
73
73
 
74
74
  void play_file(audio::AudioFile *media_file, bool announcement, bool enqueue);
75
75
 
76
- uint32_t get_playback_ms() const { return this->playback_ms_; }
77
- uint32_t get_playback_us() const { return this->playback_us_; }
78
- uint32_t get_decoded_playback_ms() const { return this->decoded_playback_ms_; }
79
-
80
76
  void set_playlist_delay_ms(AudioPipelineType pipeline_type, uint32_t delay_ms);
81
77
 
82
78
  protected:
@@ -141,13 +137,6 @@ class SpeakerMediaPlayer : public Component, public media_player::MediaPlayer {
141
137
  Trigger<> *mute_trigger_ = new Trigger<>();
142
138
  Trigger<> *unmute_trigger_ = new Trigger<>();
143
139
  Trigger<float> *volume_trigger_ = new Trigger<float>();
144
-
145
- uint32_t decoded_playback_ms_{0};
146
- uint32_t playback_us_{0};
147
- uint32_t playback_ms_{0};
148
- uint32_t remainder_us_{0};
149
- uint32_t pending_ms_{0};
150
- uint32_t last_audio_write_timestamp_{0};
151
140
  };
152
141
 
153
142
  } // namespace speaker
@@ -104,12 +104,9 @@ class Speaker {
104
104
 
105
105
  /// Callback function for sending the duration of the audio written to the speaker since the last callback.
106
106
  /// Parameters:
107
- /// - Duration in milliseconds. Never rounded and should always be less than or equal to the actual duration.
108
- /// - Remainder duration in microseconds. Rounded duration after subtracting the previous parameter from the actual
109
- /// duration.
110
- /// - Duration of remaining, unwritten audio buffered in the speaker in milliseconds.
111
- /// - System time in microseconds when the last write was completed.
112
- void add_audio_output_callback(std::function<void(uint32_t, uint32_t, uint32_t, uint32_t)> &&callback) {
107
+ /// - Frames played
108
+ /// - System time in microseconds when the frames were written to the DAC
109
+ void add_audio_output_callback(std::function<void(uint32_t, int64_t)> &&callback) {
113
110
  this->audio_output_callback_.add(std::move(callback));
114
111
  }
115
112
 
@@ -123,7 +120,7 @@ class Speaker {
123
120
  audio_dac::AudioDac *audio_dac_{nullptr};
124
121
  #endif
125
122
 
126
- CallbackManager<void(uint32_t, uint32_t, uint32_t, uint32_t)> audio_output_callback_{};
123
+ CallbackManager<void(uint32_t, int64_t)> audio_output_callback_{};
127
124
  };
128
125
 
129
126
  } // namespace speaker
@@ -6,7 +6,6 @@ from esphome.const import (
6
6
  CONF_DIRECTION_OUTPUT,
7
7
  CONF_OSCILLATION_OUTPUT,
8
8
  CONF_OUTPUT,
9
- CONF_OUTPUT_ID,
10
9
  CONF_PRESET_MODES,
11
10
  CONF_SPEED,
12
11
  CONF_SPEED_COUNT,
@@ -16,25 +15,27 @@ from .. import speed_ns
16
15
 
17
16
  SpeedFan = speed_ns.class_("SpeedFan", cg.Component, fan.Fan)
18
17
 
19
- CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
20
- {
21
- cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SpeedFan),
22
- cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput),
23
- cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput),
24
- cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput),
25
- cv.Optional(CONF_SPEED): cv.invalid(
26
- "Configuring individual speeds is deprecated."
27
- ),
28
- cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
29
- cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
30
- }
31
- ).extend(cv.COMPONENT_SCHEMA)
18
+ CONFIG_SCHEMA = (
19
+ fan.fan_schema(SpeedFan)
20
+ .extend(
21
+ {
22
+ cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput),
23
+ cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput),
24
+ cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput),
25
+ cv.Optional(CONF_SPEED): cv.invalid(
26
+ "Configuring individual speeds is deprecated."
27
+ ),
28
+ cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
29
+ cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
30
+ }
31
+ )
32
+ .extend(cv.COMPONENT_SCHEMA)
33
+ )
32
34
 
33
35
 
34
36
  async def to_code(config):
35
- var = cg.new_Pvariable(config[CONF_OUTPUT_ID], config[CONF_SPEED_COUNT])
37
+ var = await fan.new_fan(config, config[CONF_SPEED_COUNT])
36
38
  await cg.register_component(var, config)
37
- await fan.register_fan(var, config)
38
39
 
39
40
  output_ = await cg.get_variable(config[CONF_OUTPUT])
40
41
  cg.add(var.set_output(output_))
@@ -1,5 +1,4 @@
1
1
  #pragma once
2
-
3
2
  #include "esphome/core/application.h"
4
3
  #include "esphome/core/component.h"
5
4
  #include "esphome/core/hal.h"
@@ -28,6 +27,11 @@ using SPIInterface = spi_host_device_t;
28
27
 
29
28
  #endif // USE_ESP_IDF
30
29
 
30
+ #ifdef USE_ZEPHYR
31
+ // TODO supprse clang-tidy. Remove after SPI driver for nrf52 is added.
32
+ using SPIInterface = void *;
33
+ #endif
34
+
31
35
  /**
32
36
  * Implementation of SPI Controller mode.
33
37
  */
@@ -351,6 +355,12 @@ class SPIComponent : public Component {
351
355
 
352
356
  void setup() override;
353
357
  void dump_config() override;
358
+ size_t get_bus_width() const {
359
+ if (this->data_pins_.empty()) {
360
+ return 1;
361
+ }
362
+ return this->data_pins_.size();
363
+ }
354
364
 
355
365
  protected:
356
366
  GPIOPin *clk_pin_{nullptr};
@@ -4,7 +4,6 @@ import esphome.codegen as cg
4
4
  from esphome.components import number, switch
5
5
  import esphome.config_validation as cv
6
6
  from esphome.const import (
7
- CONF_ENTITY_CATEGORY,
8
7
  CONF_ID,
9
8
  CONF_INITIAL_VALUE,
10
9
  CONF_MAX_VALUE,
@@ -296,12 +295,11 @@ SPRINKLER_VALVE_SCHEMA = cv.Schema(
296
295
  cv.Optional(CONF_PUMP_SWITCH_ID): cv.use_id(switch.Switch),
297
296
  cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_seconds,
298
297
  cv.Optional(CONF_RUN_DURATION_NUMBER): cv.maybe_simple_value(
299
- number.NUMBER_SCHEMA.extend(
298
+ number.number_schema(
299
+ SprinklerControllerNumber, entity_category=ENTITY_CATEGORY_CONFIG
300
+ )
301
+ .extend(
300
302
  {
301
- cv.GenerateID(): cv.declare_id(SprinklerControllerNumber),
302
- cv.Optional(
303
- CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_CONFIG
304
- ): cv.entity_category,
305
303
  cv.Optional(CONF_INITIAL_VALUE, default=900): cv.positive_int,
306
304
  cv.Optional(CONF_MAX_VALUE, default=86400): cv.positive_int,
307
305
  cv.Optional(CONF_MIN_VALUE, default=1): cv.positive_int,
@@ -314,7 +312,8 @@ SPRINKLER_VALVE_SCHEMA = cv.Schema(
314
312
  CONF_UNIT_OF_MEASUREMENT, default=UNIT_SECOND
315
313
  ): cv.one_of(UNIT_MINUTE, UNIT_SECOND, lower="True"),
316
314
  }
317
- ).extend(cv.COMPONENT_SCHEMA),
315
+ )
316
+ .extend(cv.COMPONENT_SCHEMA),
318
317
  validate_min_max,
319
318
  key=CONF_NAME,
320
319
  ),
@@ -371,12 +370,11 @@ SPRINKLER_CONTROLLER_SCHEMA = cv.Schema(
371
370
  cv.Optional(CONF_NEXT_PREV_IGNORE_DISABLED, default=False): cv.boolean,
372
371
  cv.Optional(CONF_MANUAL_SELECTION_DELAY): cv.positive_time_period_seconds,
373
372
  cv.Optional(CONF_MULTIPLIER_NUMBER): cv.maybe_simple_value(
374
- number.NUMBER_SCHEMA.extend(
373
+ number.number_schema(
374
+ SprinklerControllerNumber, entity_category=ENTITY_CATEGORY_CONFIG
375
+ )
376
+ .extend(
375
377
  {
376
- cv.GenerateID(): cv.declare_id(SprinklerControllerNumber),
377
- cv.Optional(
378
- CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_CONFIG
379
- ): cv.entity_category,
380
378
  cv.Optional(CONF_INITIAL_VALUE, default=1): cv.positive_float,
381
379
  cv.Optional(CONF_MAX_VALUE, default=10): cv.positive_float,
382
380
  cv.Optional(CONF_MIN_VALUE, default=0): cv.positive_float,
@@ -386,18 +384,18 @@ SPRINKLER_CONTROLLER_SCHEMA = cv.Schema(
386
384
  single=True
387
385
  ),
388
386
  }
389
- ).extend(cv.COMPONENT_SCHEMA),
387
+ )
388
+ .extend(cv.COMPONENT_SCHEMA),
390
389
  validate_min_max,
391
390
  key=CONF_NAME,
392
391
  ),
393
392
  cv.Optional(CONF_REPEAT): cv.positive_int,
394
393
  cv.Optional(CONF_REPEAT_NUMBER): cv.maybe_simple_value(
395
- number.NUMBER_SCHEMA.extend(
394
+ number.number_schema(
395
+ SprinklerControllerNumber, entity_category=ENTITY_CATEGORY_CONFIG
396
+ )
397
+ .extend(
396
398
  {
397
- cv.GenerateID(): cv.declare_id(SprinklerControllerNumber),
398
- cv.Optional(
399
- CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_CONFIG
400
- ): cv.entity_category,
401
399
  cv.Optional(CONF_INITIAL_VALUE, default=0): cv.positive_int,
402
400
  cv.Optional(CONF_MAX_VALUE, default=10): cv.positive_int,
403
401
  cv.Optional(CONF_MIN_VALUE, default=0): cv.positive_int,
@@ -407,7 +405,8 @@ SPRINKLER_CONTROLLER_SCHEMA = cv.Schema(
407
405
  single=True
408
406
  ),
409
407
  }
410
- ).extend(cv.COMPONENT_SCHEMA),
408
+ )
409
+ .extend(cv.COMPONENT_SCHEMA),
411
410
  validate_min_max,
412
411
  key=CONF_NAME,
413
412
  ),
@@ -72,6 +72,9 @@ _SWITCH_SCHEMA = (
72
72
  {
73
73
  cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSwitchComponent),
74
74
  cv.Optional(CONF_INVERTED): cv.boolean,
75
+ cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum(
76
+ RESTORE_MODES, upper=True, space="_"
77
+ ),
75
78
  cv.Optional(CONF_ON_TURN_ON): automation.validate_automation(
76
79
  {
77
80
  cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOnTrigger),
@@ -87,57 +90,44 @@ _SWITCH_SCHEMA = (
87
90
  )
88
91
  )
89
92
 
90
- _UNDEF = object()
91
-
92
93
 
93
94
  def switch_schema(
94
- class_: MockObjClass = _UNDEF,
95
+ class_: MockObjClass,
95
96
  *,
96
- entity_category: str = _UNDEF,
97
- device_class: str = _UNDEF,
98
- icon: str = _UNDEF,
99
97
  block_inverted: bool = False,
100
- default_restore_mode: str = "ALWAYS_OFF",
98
+ default_restore_mode: str = cv.UNDEFINED,
99
+ device_class: str = cv.UNDEFINED,
100
+ entity_category: str = cv.UNDEFINED,
101
+ icon: str = cv.UNDEFINED,
101
102
  ):
102
- schema = _SWITCH_SCHEMA.extend(
103
- {
104
- cv.Optional(CONF_RESTORE_MODE, default=default_restore_mode): cv.enum(
105
- RESTORE_MODES, upper=True, space="_"
106
- ),
107
- }
108
- )
109
- if class_ is not _UNDEF:
110
- schema = schema.extend({cv.GenerateID(): cv.declare_id(class_)})
111
- if entity_category is not _UNDEF:
112
- schema = schema.extend(
113
- {
114
- cv.Optional(
115
- CONF_ENTITY_CATEGORY, default=entity_category
116
- ): cv.entity_category
117
- }
118
- )
119
- if device_class is not _UNDEF:
120
- schema = schema.extend(
121
- {
122
- cv.Optional(
123
- CONF_DEVICE_CLASS, default=device_class
124
- ): validate_device_class
125
- }
126
- )
127
- if icon is not _UNDEF:
128
- schema = schema.extend({cv.Optional(CONF_ICON, default=icon): cv.icon})
103
+ schema = {cv.GenerateID(): cv.declare_id(class_)}
104
+
105
+ for key, default, validator in [
106
+ (CONF_DEVICE_CLASS, device_class, validate_device_class),
107
+ (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
108
+ (CONF_ICON, icon, cv.icon),
109
+ (
110
+ CONF_RESTORE_MODE,
111
+ default_restore_mode,
112
+ cv.enum(RESTORE_MODES, upper=True, space="_")
113
+ if default_restore_mode is not cv.UNDEFINED
114
+ else cv.UNDEFINED,
115
+ ),
116
+ ]:
117
+ if default is not cv.UNDEFINED:
118
+ schema[cv.Optional(key, default=default)] = validator
119
+
129
120
  if block_inverted:
130
- schema = schema.extend(
131
- {
132
- cv.Optional(CONF_INVERTED): cv.invalid(
133
- "Inverted is not supported for this platform!"
134
- )
135
- }
121
+ schema[cv.Optional(CONF_INVERTED)] = cv.invalid(
122
+ "Inverted is not supported for this platform!"
136
123
  )
137
- return schema
124
+
125
+ return _SWITCH_SCHEMA.extend(schema)
138
126
 
139
127
 
140
- SWITCH_SCHEMA = switch_schema() # for compatibility
128
+ # Remove before 2025.11.0
129
+ SWITCH_SCHEMA = switch_schema(Switch)
130
+ SWITCH_SCHEMA.add_extra(cv.deprecated_schema_constant("switch"))
141
131
 
142
132
 
143
133
  async def setup_switch_core_(var, config):