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
@@ -33,6 +33,7 @@ from esphome.const import (
33
33
  UNIT_DEGREES,
34
34
  UNIT_HERTZ,
35
35
  UNIT_VOLT,
36
+ UNIT_VOLT_AMPS,
36
37
  UNIT_VOLT_AMPS_REACTIVE,
37
38
  UNIT_WATT,
38
39
  UNIT_WATT_HOURS,
@@ -45,10 +46,17 @@ CONF_GAIN_PGA = "gain_pga"
45
46
  CONF_CURRENT_PHASES = "current_phases"
46
47
  CONF_GAIN_VOLTAGE = "gain_voltage"
47
48
  CONF_GAIN_CT = "gain_ct"
49
+ CONF_OFFSET_VOLTAGE = "offset_voltage"
50
+ CONF_OFFSET_CURRENT = "offset_current"
51
+ CONF_OFFSET_ACTIVE_POWER = "offset_active_power"
52
+ CONF_OFFSET_REACTIVE_POWER = "offset_reactive_power"
48
53
  CONF_HARMONIC_POWER = "harmonic_power"
49
54
  CONF_PEAK_CURRENT = "peak_current"
50
55
  CONF_PEAK_CURRENT_SIGNED = "peak_current_signed"
51
56
  CONF_ENABLE_OFFSET_CALIBRATION = "enable_offset_calibration"
57
+ CONF_ENABLE_GAIN_CALIBRATION = "enable_gain_calibration"
58
+ CONF_PHASE_STATUS = "phase_status"
59
+ CONF_FREQUENCY_STATUS = "frequency_status"
52
60
  UNIT_DEG = "degrees"
53
61
  LINE_FREQS = {
54
62
  "50HZ": 50,
@@ -92,10 +100,11 @@ ATM90E32_PHASE_SCHEMA = cv.Schema(
92
100
  unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
93
101
  icon=ICON_LIGHTBULB,
94
102
  accuracy_decimals=2,
103
+ device_class=DEVICE_CLASS_POWER,
95
104
  state_class=STATE_CLASS_MEASUREMENT,
96
105
  ),
97
106
  cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema(
98
- unit_of_measurement=UNIT_WATT,
107
+ unit_of_measurement=UNIT_VOLT_AMPS,
99
108
  accuracy_decimals=2,
100
109
  device_class=DEVICE_CLASS_POWER,
101
110
  state_class=STATE_CLASS_MEASUREMENT,
@@ -137,6 +146,10 @@ ATM90E32_PHASE_SCHEMA = cv.Schema(
137
146
  ),
138
147
  cv.Optional(CONF_GAIN_VOLTAGE, default=7305): cv.uint16_t,
139
148
  cv.Optional(CONF_GAIN_CT, default=27961): cv.uint16_t,
149
+ cv.Optional(CONF_OFFSET_VOLTAGE, default=0): cv.int_,
150
+ cv.Optional(CONF_OFFSET_CURRENT, default=0): cv.int_,
151
+ cv.Optional(CONF_OFFSET_ACTIVE_POWER, default=0): cv.int_,
152
+ cv.Optional(CONF_OFFSET_REACTIVE_POWER, default=0): cv.int_,
140
153
  }
141
154
  )
142
155
 
@@ -164,9 +177,10 @@ CONFIG_SCHEMA = (
164
177
  cv.Optional(CONF_CURRENT_PHASES, default="3"): cv.enum(
165
178
  CURRENT_PHASES, upper=True
166
179
  ),
167
- cv.Optional(CONF_GAIN_PGA, default="2X"): cv.enum(PGA_GAINS, upper=True),
180
+ cv.Optional(CONF_GAIN_PGA, default="1X"): cv.enum(PGA_GAINS, upper=True),
168
181
  cv.Optional(CONF_PEAK_CURRENT_SIGNED, default=False): cv.boolean,
169
182
  cv.Optional(CONF_ENABLE_OFFSET_CALIBRATION, default=False): cv.boolean,
183
+ cv.Optional(CONF_ENABLE_GAIN_CALIBRATION, default=False): cv.boolean,
170
184
  }
171
185
  )
172
186
  .extend(cv.polling_component_schema("60s"))
@@ -185,6 +199,10 @@ async def to_code(config):
185
199
  conf = config[phase]
186
200
  cg.add(var.set_volt_gain(i, conf[CONF_GAIN_VOLTAGE]))
187
201
  cg.add(var.set_ct_gain(i, conf[CONF_GAIN_CT]))
202
+ cg.add(var.set_voltage_offset(i, conf[CONF_OFFSET_VOLTAGE]))
203
+ cg.add(var.set_current_offset(i, conf[CONF_OFFSET_CURRENT]))
204
+ cg.add(var.set_active_power_offset(i, conf[CONF_OFFSET_ACTIVE_POWER]))
205
+ cg.add(var.set_reactive_power_offset(i, conf[CONF_OFFSET_REACTIVE_POWER]))
188
206
  if voltage_config := conf.get(CONF_VOLTAGE):
189
207
  sens = await sensor.new_sensor(voltage_config)
190
208
  cg.add(var.set_voltage_sensor(i, sens))
@@ -218,16 +236,15 @@ async def to_code(config):
218
236
  if peak_current_config := conf.get(CONF_PEAK_CURRENT):
219
237
  sens = await sensor.new_sensor(peak_current_config)
220
238
  cg.add(var.set_peak_current_sensor(i, sens))
221
-
222
239
  if frequency_config := config.get(CONF_FREQUENCY):
223
240
  sens = await sensor.new_sensor(frequency_config)
224
241
  cg.add(var.set_freq_sensor(sens))
225
242
  if chip_temperature_config := config.get(CONF_CHIP_TEMPERATURE):
226
243
  sens = await sensor.new_sensor(chip_temperature_config)
227
244
  cg.add(var.set_chip_temperature_sensor(sens))
228
-
229
245
  cg.add(var.set_line_freq(config[CONF_LINE_FREQUENCY]))
230
246
  cg.add(var.set_current_phases(config[CONF_CURRENT_PHASES]))
231
247
  cg.add(var.set_pga_gain(config[CONF_GAIN_PGA]))
232
248
  cg.add(var.set_peak_current_signed(config[CONF_PEAK_CURRENT_SIGNED]))
233
249
  cg.add(var.set_enable_offset_calibration(config[CONF_ENABLE_OFFSET_CALIBRATION]))
250
+ cg.add(var.set_enable_gain_calibration(config[CONF_ENABLE_GAIN_CALIBRATION]))
@@ -0,0 +1,48 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import text_sensor
3
+ import esphome.config_validation as cv
4
+ from esphome.const import CONF_ID, CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C
5
+
6
+ from ..sensor import ATM90E32Component
7
+
8
+ CONF_PHASE_STATUS = "phase_status"
9
+ CONF_FREQUENCY_STATUS = "frequency_status"
10
+ PHASE_KEYS = [CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C]
11
+
12
+ PHASE_STATUS_SCHEMA = cv.Schema(
13
+ {
14
+ cv.Optional(CONF_PHASE_A): text_sensor.text_sensor_schema(
15
+ icon="mdi:flash-alert"
16
+ ),
17
+ cv.Optional(CONF_PHASE_B): text_sensor.text_sensor_schema(
18
+ icon="mdi:flash-alert"
19
+ ),
20
+ cv.Optional(CONF_PHASE_C): text_sensor.text_sensor_schema(
21
+ icon="mdi:flash-alert"
22
+ ),
23
+ }
24
+ )
25
+
26
+ CONFIG_SCHEMA = cv.Schema(
27
+ {
28
+ cv.GenerateID(): cv.use_id(ATM90E32Component),
29
+ cv.Optional(CONF_PHASE_STATUS): PHASE_STATUS_SCHEMA,
30
+ cv.Optional(CONF_FREQUENCY_STATUS): text_sensor.text_sensor_schema(
31
+ icon="mdi:lightbulb-alert"
32
+ ),
33
+ }
34
+ )
35
+
36
+
37
+ async def to_code(config):
38
+ parent = await cg.get_variable(config[CONF_ID])
39
+
40
+ if phase_cfg := config.get(CONF_PHASE_STATUS):
41
+ for i, key in enumerate(PHASE_KEYS):
42
+ if sub_phase_cfg := phase_cfg.get(key):
43
+ sens = await text_sensor.new_text_sensor(sub_phase_cfg)
44
+ cg.add(parent.set_phase_status_text_sensor(i, sens))
45
+
46
+ if freq_status_config := config.get(CONF_FREQUENCY_STATUS):
47
+ sens = await text_sensor.new_text_sensor(freq_status_config)
48
+ cg.add(parent.set_freq_status_text_sensor(sens))
@@ -37,29 +37,32 @@ AUDIO_COMPONENT_SCHEMA = cv.Schema(
37
37
  )
38
38
 
39
39
 
40
- _UNDEF = object()
41
-
42
-
43
40
  def set_stream_limits(
44
- min_bits_per_sample: int = _UNDEF,
45
- max_bits_per_sample: int = _UNDEF,
46
- min_channels: int = _UNDEF,
47
- max_channels: int = _UNDEF,
48
- min_sample_rate: int = _UNDEF,
49
- max_sample_rate: int = _UNDEF,
41
+ min_bits_per_sample: int = cv.UNDEFINED,
42
+ max_bits_per_sample: int = cv.UNDEFINED,
43
+ min_channels: int = cv.UNDEFINED,
44
+ max_channels: int = cv.UNDEFINED,
45
+ min_sample_rate: int = cv.UNDEFINED,
46
+ max_sample_rate: int = cv.UNDEFINED,
50
47
  ):
48
+ """Sets the limits for the audio stream that audio component can handle
49
+
50
+ When the component sinks audio (e.g., a speaker), these indicate the limits to the audio it can receive.
51
+ When the component sources audio (e.g., a microphone), these indicate the limits to the audio it can send.
52
+ """
53
+
51
54
  def set_limits_in_config(config):
52
- if min_bits_per_sample is not _UNDEF:
55
+ if min_bits_per_sample is not cv.UNDEFINED:
53
56
  config[CONF_MIN_BITS_PER_SAMPLE] = min_bits_per_sample
54
- if max_bits_per_sample is not _UNDEF:
57
+ if max_bits_per_sample is not cv.UNDEFINED:
55
58
  config[CONF_MAX_BITS_PER_SAMPLE] = max_bits_per_sample
56
- if min_channels is not _UNDEF:
59
+ if min_channels is not cv.UNDEFINED:
57
60
  config[CONF_MIN_CHANNELS] = min_channels
58
- if max_channels is not _UNDEF:
61
+ if max_channels is not cv.UNDEFINED:
59
62
  config[CONF_MAX_CHANNELS] = max_channels
60
- if min_sample_rate is not _UNDEF:
63
+ if min_sample_rate is not cv.UNDEFINED:
61
64
  config[CONF_MIN_SAMPLE_RATE] = min_sample_rate
62
- if max_sample_rate is not _UNDEF:
65
+ if max_sample_rate is not cv.UNDEFINED:
63
66
  config[CONF_MAX_SAMPLE_RATE] = max_sample_rate
64
67
 
65
68
  return set_limits_in_config
@@ -69,43 +72,87 @@ def final_validate_audio_schema(
69
72
  name: str,
70
73
  *,
71
74
  audio_device: str,
72
- bits_per_sample: int,
73
- channels: int,
74
- sample_rate: int,
75
+ bits_per_sample: int = cv.UNDEFINED,
76
+ channels: int = cv.UNDEFINED,
77
+ sample_rate: int = cv.UNDEFINED,
78
+ enabled_channels: list[int] = cv.UNDEFINED,
79
+ audio_device_issue: bool = False,
75
80
  ):
81
+ """Validates audio compatibility when passed between different components.
82
+
83
+ The component derived from ``AUDIO_COMPONENT_SCHEMA`` should call ``set_stream_limits`` in a validator to specify its compatible settings
84
+
85
+ - If audio_device_issue is True, then the error message indicates the user should adjust the AUDIO_COMPONENT_SCHEMA derived component's configuration to match the values passed to this function
86
+ - If audio_device_issue is False, then the error message indicates the user should adjust the configuration of the component calling this function, as it falls out of the valid stream limits
87
+
88
+ Args:
89
+ name (str): Friendly name of the component calling this function with an audio component to validate
90
+ audio_device (str): The configuration parameter name that contains the ID of an AUDIO_COMPONENT_SCHEMA derived component to validate against
91
+ bits_per_sample (int, optional): The desired bits per sample
92
+ channels (int, optional): The desired number of channels
93
+ sample_rate (int, optional): The desired sample rate
94
+ enabled_channels (list[int], optional): The desired enabled channels
95
+ audio_device_issue (bool, optional): Format the error message to indicate the problem is in the configuration for the ``audio_device`` component. Defaults to False.
96
+ """
97
+
76
98
  def validate_audio_compatiblity(audio_config):
77
99
  audio_schema = {}
78
100
 
79
- try:
80
- cv.int_range(
81
- min=audio_config.get(CONF_MIN_BITS_PER_SAMPLE),
82
- max=audio_config.get(CONF_MAX_BITS_PER_SAMPLE),
83
- )(bits_per_sample)
84
- except cv.Invalid as exc:
85
- raise cv.Invalid(
86
- f"Invalid configuration for the {name} component. The {CONF_BITS_PER_SAMPLE} {str(exc)}"
87
- ) from exc
88
-
89
- try:
90
- cv.int_range(
91
- min=audio_config.get(CONF_MIN_CHANNELS),
92
- max=audio_config.get(CONF_MAX_CHANNELS),
93
- )(channels)
94
- except cv.Invalid as exc:
95
- raise cv.Invalid(
96
- f"Invalid configuration for the {name} component. The {CONF_NUM_CHANNELS} {str(exc)}"
97
- ) from exc
98
-
99
- try:
100
- cv.int_range(
101
- min=audio_config.get(CONF_MIN_SAMPLE_RATE),
102
- max=audio_config.get(CONF_MAX_SAMPLE_RATE),
103
- )(sample_rate)
104
- return cv.Schema(audio_schema, extra=cv.ALLOW_EXTRA)(audio_config)
105
- except cv.Invalid as exc:
106
- raise cv.Invalid(
107
- f"Invalid configuration for the {name} component. The {CONF_SAMPLE_RATE} {str(exc)}"
108
- ) from exc
101
+ if bits_per_sample is not cv.UNDEFINED:
102
+ try:
103
+ cv.int_range(
104
+ min=audio_config.get(CONF_MIN_BITS_PER_SAMPLE),
105
+ max=audio_config.get(CONF_MAX_BITS_PER_SAMPLE),
106
+ )(bits_per_sample)
107
+ except cv.Invalid as exc:
108
+ if audio_device_issue:
109
+ error_string = f"Invalid configuration for the specified {audio_device}. The {name} component requires {bits_per_sample} bits per sample."
110
+ else:
111
+ error_string = f"Invalid configuration for the {name} component. The {CONF_BITS_PER_SAMPLE} {str(exc)}"
112
+ raise cv.Invalid(error_string) from exc
113
+
114
+ if channels is not cv.UNDEFINED:
115
+ try:
116
+ cv.int_range(
117
+ min=audio_config.get(CONF_MIN_CHANNELS),
118
+ max=audio_config.get(CONF_MAX_CHANNELS),
119
+ )(channels)
120
+ except cv.Invalid as exc:
121
+ if audio_device_issue:
122
+ error_string = f"Invalid configuration for the specified {audio_device}. The {name} component requires {channels} channels."
123
+ else:
124
+ error_string = f"Invalid configuration for the {name} component. The {CONF_NUM_CHANNELS} {str(exc)}"
125
+ raise cv.Invalid(error_string) from exc
126
+
127
+ if sample_rate is not cv.UNDEFINED:
128
+ try:
129
+ cv.int_range(
130
+ min=audio_config.get(CONF_MIN_SAMPLE_RATE),
131
+ max=audio_config.get(CONF_MAX_SAMPLE_RATE),
132
+ )(sample_rate)
133
+ except cv.Invalid as exc:
134
+ if audio_device_issue:
135
+ error_string = f"Invalid configuration for the specified {audio_device}. The {name} component requires a {sample_rate} sample rate."
136
+ else:
137
+ error_string = f"Invalid configuration for the {name} component. The {CONF_SAMPLE_RATE} {str(exc)}"
138
+ raise cv.Invalid(error_string) from exc
139
+
140
+ if enabled_channels is not cv.UNDEFINED:
141
+ for channel in enabled_channels:
142
+ try:
143
+ # Channels are 0-indexed
144
+ cv.int_range(
145
+ min=0,
146
+ max=audio_config.get(CONF_MAX_CHANNELS) - 1,
147
+ )(channel)
148
+ except cv.Invalid as exc:
149
+ if audio_device_issue:
150
+ error_string = f"Invalid configuration for the specified {audio_device}. The {name} component requires channel {channel}."
151
+ else:
152
+ error_string = f"Invalid configuration for the {name} component. Enabled channel {channel} {str(exc)}"
153
+ raise cv.Invalid(error_string) from exc
154
+
155
+ return cv.Schema(audio_schema, extra=cv.ALLOW_EXTRA)(audio_config)
109
156
 
110
157
  return cv.Schema(
111
158
  {
@@ -118,4 +165,4 @@ def final_validate_audio_schema(
118
165
 
119
166
 
120
167
  async def to_code(config):
121
- cg.add_library("esphome/esp-audio-libs", "1.1.3")
168
+ cg.add_library("esphome/esp-audio-libs", "1.1.4")
@@ -135,5 +135,53 @@ const char *audio_file_type_to_string(AudioFileType file_type);
135
135
  void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor,
136
136
  size_t samples_to_scale);
137
137
 
138
+ /// @brief Unpacks a quantized audio sample into a Q31 fixed-point number.
139
+ /// @param data Pointer to uint8_t array containing the audio sample
140
+ /// @param bytes_per_sample The number of bytes per sample
141
+ /// @return Q31 sample
142
+ inline int32_t unpack_audio_sample_to_q31(const uint8_t *data, size_t bytes_per_sample) {
143
+ int32_t sample = 0;
144
+ if (bytes_per_sample == 1) {
145
+ sample |= data[0] << 24;
146
+ } else if (bytes_per_sample == 2) {
147
+ sample |= data[0] << 16;
148
+ sample |= data[1] << 24;
149
+ } else if (bytes_per_sample == 3) {
150
+ sample |= data[0] << 8;
151
+ sample |= data[1] << 16;
152
+ sample |= data[2] << 24;
153
+ } else if (bytes_per_sample == 4) {
154
+ sample |= data[0];
155
+ sample |= data[1] << 8;
156
+ sample |= data[2] << 16;
157
+ sample |= data[3] << 24;
158
+ }
159
+
160
+ return sample;
161
+ }
162
+
163
+ /// @brief Packs a Q31 fixed-point number as an audio sample with the specified number of bytes per sample.
164
+ /// Packs the most significant bits - no dithering is applied.
165
+ /// @param sample Q31 fixed-point number to pack
166
+ /// @param data Pointer to data array to store
167
+ /// @param bytes_per_sample The audio data's bytes per sample
168
+ inline void pack_q31_as_audio_sample(int32_t sample, uint8_t *data, size_t bytes_per_sample) {
169
+ if (bytes_per_sample == 1) {
170
+ data[0] = static_cast<uint8_t>(sample >> 24);
171
+ } else if (bytes_per_sample == 2) {
172
+ data[0] = static_cast<uint8_t>(sample >> 16);
173
+ data[1] = static_cast<uint8_t>(sample >> 24);
174
+ } else if (bytes_per_sample == 3) {
175
+ data[0] = static_cast<uint8_t>(sample >> 8);
176
+ data[1] = static_cast<uint8_t>(sample >> 16);
177
+ data[2] = static_cast<uint8_t>(sample >> 24);
178
+ } else if (bytes_per_sample == 4) {
179
+ data[0] = static_cast<uint8_t>(sample);
180
+ data[1] = static_cast<uint8_t>(sample >> 8);
181
+ data[2] = static_cast<uint8_t>(sample >> 16);
182
+ data[3] = static_cast<uint8_t>(sample >> 24);
183
+ }
184
+ }
185
+
138
186
  } // namespace audio
139
187
  } // namespace esphome
@@ -171,7 +171,7 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
171
171
 
172
172
  bytes_available_before_processing = this->input_transfer_buffer_->available();
173
173
 
174
- if ((this->potentially_failed_count_ > 10) && (bytes_read == 0)) {
174
+ if ((this->potentially_failed_count_ > 0) && (bytes_read == 0)) {
175
175
  // Failed to decode in last attempt and there is no new data
176
176
 
177
177
  if ((this->input_transfer_buffer_->free() == 0) && first_loop_iteration) {
@@ -4,6 +4,8 @@
4
4
 
5
5
  #include "esphome/core/hal.h"
6
6
 
7
+ #include <cstring>
8
+
7
9
  namespace esphome {
8
10
  namespace audio {
9
11
 
@@ -6,6 +6,7 @@
6
6
  #include "audio_transfer_buffer.h"
7
7
 
8
8
  #include "esphome/core/defines.h"
9
+ #include "esphome/core/helpers.h"
9
10
  #include "esphome/core/ring_buffer.h"
10
11
 
11
12
  #ifdef USE_SPEAKER
@@ -1,7 +1,5 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import climate_ir
3
- import esphome.config_validation as cv
4
- from esphome.const import CONF_ID
5
3
 
6
4
  AUTO_LOAD = ["climate_ir"]
7
5
  CODEOWNERS = ["@bazuchan"]
@@ -9,13 +7,8 @@ CODEOWNERS = ["@bazuchan"]
9
7
  ballu_ns = cg.esphome_ns.namespace("ballu")
10
8
  BalluClimate = ballu_ns.class_("BalluClimate", climate_ir.ClimateIR)
11
9
 
12
- CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
13
- {
14
- cv.GenerateID(): cv.declare_id(BalluClimate),
15
- }
16
- )
10
+ CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(BalluClimate)
17
11
 
18
12
 
19
13
  async def to_code(config):
20
- var = cg.new_Pvariable(config[CONF_ID])
21
- await climate_ir.register_climate_ir(var, config)
14
+ await climate_ir.new_climate_ir(config)
@@ -9,7 +9,6 @@ from esphome.const import (
9
9
  CONF_DEFAULT_TARGET_TEMPERATURE_LOW,
10
10
  CONF_HEAT_ACTION,
11
11
  CONF_HUMIDITY_SENSOR,
12
- CONF_ID,
13
12
  CONF_IDLE_ACTION,
14
13
  CONF_SENSOR,
15
14
  )
@@ -19,9 +18,9 @@ BangBangClimate = bang_bang_ns.class_("BangBangClimate", climate.Climate, cg.Com
19
18
  BangBangClimateTargetTempConfig = bang_bang_ns.struct("BangBangClimateTargetTempConfig")
20
19
 
21
20
  CONFIG_SCHEMA = cv.All(
22
- climate.CLIMATE_SCHEMA.extend(
21
+ climate.climate_schema(BangBangClimate)
22
+ .extend(
23
23
  {
24
- cv.GenerateID(): cv.declare_id(BangBangClimate),
25
24
  cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
26
25
  cv.Optional(CONF_HUMIDITY_SENSOR): cv.use_id(sensor.Sensor),
27
26
  cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
@@ -36,15 +35,15 @@ CONFIG_SCHEMA = cv.All(
36
35
  }
37
36
  ),
38
37
  }
39
- ).extend(cv.COMPONENT_SCHEMA),
38
+ )
39
+ .extend(cv.COMPONENT_SCHEMA),
40
40
  cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_HEAT_ACTION),
41
41
  )
42
42
 
43
43
 
44
44
  async def to_code(config):
45
- var = cg.new_Pvariable(config[CONF_ID])
45
+ var = await climate.new_climate(config)
46
46
  await cg.register_component(var, config)
47
- await climate.register_climate(var, config)
48
47
 
49
48
  sens = await cg.get_variable(config[CONF_SENSOR])
50
49
  cg.add(var.set_sensor(sens))
@@ -3,6 +3,7 @@
3
3
  #include "bedjet_hub.h"
4
4
  #include "bedjet_child.h"
5
5
  #include "bedjet_const.h"
6
+ #include "esphome/core/application.h"
6
7
  #include <cinttypes>
7
8
 
8
9
  namespace esphome {
@@ -1,11 +1,8 @@
1
- import logging
2
-
3
1
  import esphome.codegen as cg
4
2
  from esphome.components import ble_client, climate
5
3
  import esphome.config_validation as cv
6
4
  from esphome.const import (
7
5
  CONF_HEAT_MODE,
8
- CONF_ID,
9
6
  CONF_RECEIVE_TIMEOUT,
10
7
  CONF_TEMPERATURE_SOURCE,
11
8
  CONF_TIME_ID,
@@ -13,7 +10,6 @@ from esphome.const import (
13
10
 
14
11
  from .. import BEDJET_CLIENT_SCHEMA, bedjet_ns, register_bedjet_child
15
12
 
16
- _LOGGER = logging.getLogger(__name__)
17
13
  CODEOWNERS = ["@jhansche"]
18
14
  DEPENDENCIES = ["bedjet"]
19
15
 
@@ -30,9 +26,9 @@ BEDJET_TEMPERATURE_SOURCES = {
30
26
  }
31
27
 
32
28
  CONFIG_SCHEMA = (
33
- climate.CLIMATE_SCHEMA.extend(
29
+ climate.climate_schema(BedJetClimate)
30
+ .extend(
34
31
  {
35
- cv.GenerateID(): cv.declare_id(BedJetClimate),
36
32
  cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum(
37
33
  BEDJET_HEAT_MODES, lower=True
38
34
  ),
@@ -63,9 +59,8 @@ CONFIG_SCHEMA = (
63
59
 
64
60
 
65
61
  async def to_code(config):
66
- var = cg.new_Pvariable(config[CONF_ID])
62
+ var = await climate.new_climate(config)
67
63
  await cg.register_component(var, config)
68
- await climate.register_climate(var, config)
69
64
  await register_bedjet_child(var, config)
70
65
 
71
66
  cg.add(var.set_heating_mode(config[CONF_HEAT_MODE]))
@@ -1,31 +1,22 @@
1
- import logging
2
-
3
1
  import esphome.codegen as cg
4
2
  from esphome.components import fan
5
3
  import esphome.config_validation as cv
6
- from esphome.const import CONF_ID
7
4
 
8
5
  from .. import BEDJET_CLIENT_SCHEMA, bedjet_ns, register_bedjet_child
9
6
 
10
- _LOGGER = logging.getLogger(__name__)
11
7
  CODEOWNERS = ["@jhansche"]
12
8
  DEPENDENCIES = ["bedjet"]
13
9
 
14
10
  BedJetFan = bedjet_ns.class_("BedJetFan", fan.Fan, cg.PollingComponent)
15
11
 
16
12
  CONFIG_SCHEMA = (
17
- fan.FAN_SCHEMA.extend(
18
- {
19
- cv.GenerateID(): cv.declare_id(BedJetFan),
20
- }
21
- )
13
+ fan.fan_schema(BedJetFan)
22
14
  .extend(cv.polling_component_schema("60s"))
23
15
  .extend(BEDJET_CLIENT_SCHEMA)
24
16
  )
25
17
 
26
18
 
27
19
  async def to_code(config):
28
- var = cg.new_Pvariable(config[CONF_ID])
20
+ var = await fan.new_fan(config)
29
21
  await cg.register_component(var, config)
30
- await fan.register_fan(var, config)
31
22
  await register_bedjet_child(var, config)
@@ -1,31 +1,28 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import fan, output
3
3
  import esphome.config_validation as cv
4
- from esphome.const import (
5
- CONF_DIRECTION_OUTPUT,
6
- CONF_OSCILLATION_OUTPUT,
7
- CONF_OUTPUT,
8
- CONF_OUTPUT_ID,
9
- )
4
+ from esphome.const import CONF_DIRECTION_OUTPUT, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT
10
5
 
11
6
  from .. import binary_ns
12
7
 
13
8
  BinaryFan = binary_ns.class_("BinaryFan", fan.Fan, cg.Component)
14
9
 
15
- CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
16
- {
17
- cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryFan),
18
- cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
19
- cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput),
20
- cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput),
21
- }
22
- ).extend(cv.COMPONENT_SCHEMA)
10
+ CONFIG_SCHEMA = (
11
+ fan.fan_schema(BinaryFan)
12
+ .extend(
13
+ {
14
+ cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
15
+ cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput),
16
+ cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput),
17
+ }
18
+ )
19
+ .extend(cv.COMPONENT_SCHEMA)
20
+ )
23
21
 
24
22
 
25
23
  async def to_code(config):
26
- var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
24
+ var = await fan.new_fan(config)
27
25
  await cg.register_component(var, config)
28
- await fan.register_fan(var, config)
29
26
 
30
27
  output_ = await cg.get_variable(config[CONF_OUTPUT])
31
28
  cg.add(var.set_output(output_))
@@ -386,7 +386,7 @@ def validate_click_timing(value):
386
386
  return value
387
387
 
388
388
 
389
- BINARY_SENSOR_SCHEMA = (
389
+ _BINARY_SENSOR_SCHEMA = (
390
390
  cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
391
391
  .extend(cv.MQTT_COMPONENT_SCHEMA)
392
392
  .extend(
@@ -458,19 +458,17 @@ BINARY_SENSOR_SCHEMA = (
458
458
  )
459
459
  )
460
460
 
461
- _UNDEF = object()
462
-
463
461
 
464
462
  def binary_sensor_schema(
465
- class_: MockObjClass = _UNDEF,
463
+ class_: MockObjClass = cv.UNDEFINED,
466
464
  *,
467
- icon: str = _UNDEF,
468
- entity_category: str = _UNDEF,
469
- device_class: str = _UNDEF,
465
+ icon: str = cv.UNDEFINED,
466
+ entity_category: str = cv.UNDEFINED,
467
+ device_class: str = cv.UNDEFINED,
470
468
  ) -> cv.Schema:
471
469
  schema = {}
472
470
 
473
- if class_ is not _UNDEF:
471
+ if class_ is not cv.UNDEFINED:
474
472
  # Not cv.optional
475
473
  schema[cv.GenerateID()] = cv.declare_id(class_)
476
474
 
@@ -479,10 +477,15 @@ def binary_sensor_schema(
479
477
  (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
480
478
  (CONF_DEVICE_CLASS, device_class, validate_device_class),
481
479
  ]:
482
- if default is not _UNDEF:
480
+ if default is not cv.UNDEFINED:
483
481
  schema[cv.Optional(key, default=default)] = validator
484
482
 
485
- return BINARY_SENSOR_SCHEMA.extend(schema)
483
+ return _BINARY_SENSOR_SCHEMA.extend(schema)
484
+
485
+
486
+ # Remove before 2025.11.0
487
+ BINARY_SENSOR_SCHEMA = binary_sensor_schema()
488
+ BINARY_SENSOR_SCHEMA.add_extra(cv.deprecated_schema_constant("binary_sensor"))
486
489
 
487
490
 
488
491
  async def setup_binary_sensor_core_(var, config):