esphome 2025.4.2__py3-none-any.whl → 2025.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. esphome/__main__.py +16 -14
  2. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  3. esphome/components/adc/__init__.py +51 -34
  4. esphome/components/airthings_wave_base/__init__.py +1 -1
  5. esphome/components/alarm_control_panel/__init__.py +37 -2
  6. esphome/components/am43/cover/__init__.py +4 -5
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  8. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  9. esphome/components/analog_threshold/binary_sensor.py +10 -8
  10. esphome/components/anova/climate.py +4 -5
  11. esphome/components/api/__init__.py +25 -8
  12. esphome/components/api/api_connection.cpp +416 -662
  13. esphome/components/api/api_connection.h +256 -57
  14. esphome/components/api/api_frame_helper.cpp +232 -177
  15. esphome/components/api/api_frame_helper.h +61 -8
  16. esphome/components/api/api_noise_context.h +13 -4
  17. esphome/components/api/api_pb2.cpp +1422 -1
  18. esphome/components/api/api_pb2.h +255 -1
  19. esphome/components/api/api_pb2_service.cpp +162 -49
  20. esphome/components/api/api_pb2_service.h +90 -51
  21. esphome/components/api/api_pb2_size.h +361 -0
  22. esphome/components/api/api_server.cpp +110 -34
  23. esphome/components/api/api_server.h +8 -0
  24. esphome/components/api/proto.h +86 -17
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/at581x/at581x.h +4 -4
  27. esphome/components/atm90e32/__init__.py +1 -0
  28. esphome/components/atm90e32/atm90e32.cpp +576 -199
  29. esphome/components/atm90e32/atm90e32.h +128 -31
  30. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  31. esphome/components/atm90e32/button/__init__.py +62 -10
  32. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  33. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  34. esphome/components/atm90e32/number/__init__.py +130 -0
  35. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  36. esphome/components/atm90e32/sensor.py +21 -4
  37. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  38. esphome/components/audio/__init__.py +96 -49
  39. esphome/components/audio/audio.h +48 -0
  40. esphome/components/audio/audio_decoder.cpp +1 -1
  41. esphome/components/audio/audio_resampler.cpp +2 -0
  42. esphome/components/audio/audio_resampler.h +1 -0
  43. esphome/components/ballu/climate.py +2 -9
  44. esphome/components/bang_bang/climate.py +5 -6
  45. esphome/components/bedjet/bedjet_hub.cpp +1 -0
  46. esphome/components/bedjet/climate/__init__.py +3 -8
  47. esphome/components/bedjet/fan/__init__.py +2 -11
  48. esphome/components/binary/fan/__init__.py +13 -16
  49. esphome/components/binary_sensor/__init__.py +13 -10
  50. esphome/components/bl0906/constants.h +16 -16
  51. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  52. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
  54. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  55. esphome/components/button/__init__.py +11 -8
  56. esphome/components/canbus/canbus.cpp +3 -0
  57. esphome/components/canbus/canbus.h +16 -0
  58. esphome/components/ccs811/sensor.py +9 -6
  59. esphome/components/climate/__init__.py +35 -2
  60. esphome/components/climate/climate_mode.h +1 -1
  61. esphome/components/climate/climate_traits.h +63 -57
  62. esphome/components/climate_ir/__init__.py +57 -17
  63. esphome/components/climate_ir_lg/climate.py +2 -5
  64. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  65. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  66. esphome/components/color/__init__.py +2 -0
  67. esphome/components/const/__init__.py +5 -0
  68. esphome/components/coolix/climate.py +2 -9
  69. esphome/components/copy/cover/__init__.py +10 -9
  70. esphome/components/copy/fan/__init__.py +11 -9
  71. esphome/components/copy/lock/__init__.py +11 -9
  72. esphome/components/copy/text/__init__.py +9 -6
  73. esphome/components/cover/__init__.py +37 -2
  74. esphome/components/cse7766/cse7766.cpp +2 -1
  75. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  76. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  77. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  79. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  80. esphome/components/current_based/cover.py +37 -36
  81. esphome/components/current_based/current_based_cover.cpp +2 -1
  82. esphome/components/daikin/climate.py +2 -9
  83. esphome/components/daikin/daikin.cpp +15 -9
  84. esphome/components/daikin/daikin.h +5 -5
  85. esphome/components/daikin_arc/climate.py +2 -7
  86. esphome/components/daikin_brc/climate.py +3 -5
  87. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  88. esphome/components/dallas_temp/dallas_temp.h +0 -1
  89. esphome/components/daly_bms/daly_bms.cpp +2 -1
  90. esphome/components/debug/debug_component.cpp +6 -1
  91. esphome/components/debug/debug_component.h +8 -0
  92. esphome/components/debug/debug_esp32.cpp +109 -254
  93. esphome/components/debug/sensor.py +14 -0
  94. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  95. esphome/components/delonghi/climate.py +2 -9
  96. esphome/components/demo/__init__.py +18 -20
  97. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  98. esphome/components/dps310/sensor.py +6 -6
  99. esphome/components/ee895/sensor.py +9 -9
  100. esphome/components/emmeti/climate.py +2 -9
  101. esphome/components/endstop/cover.py +17 -16
  102. esphome/components/endstop/endstop_cover.cpp +2 -1
  103. esphome/components/ens160_base/__init__.py +12 -9
  104. esphome/components/esp32/__init__.py +60 -3
  105. esphome/components/esp32/core.cpp +11 -5
  106. esphome/components/esp32/gpio.cpp +86 -24
  107. esphome/components/esp32/gpio.py +15 -16
  108. esphome/components/esp32/gpio_esp32.py +1 -2
  109. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  110. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  111. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  112. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  113. esphome/components/esp32_ble/ble.cpp +1 -0
  114. esphome/components/esp32_ble/ble.h +5 -3
  115. esphome/components/esp32_ble/ble_advertising.cpp +2 -1
  116. esphome/components/esp32_ble/ble_advertising.h +1 -0
  117. esphome/components/esp32_ble_server/__init__.py +3 -0
  118. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  119. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  120. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  121. esphome/components/esp32_camera/__init__.py +1 -1
  122. esphome/components/esp32_camera/esp32_camera.cpp +2 -10
  123. esphome/components/esp32_camera/esp32_camera.h +1 -1
  124. esphome/components/esp32_can/esp32_can.cpp +1 -1
  125. esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
  126. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  127. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  128. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  129. esphome/components/esp32_touch/esp32_touch.cpp +1 -1
  130. esphome/components/esp8266/gpio.cpp +69 -8
  131. esphome/components/ethernet/ethernet_component.cpp +1 -1
  132. esphome/components/event/__init__.py +13 -10
  133. esphome/components/factory_reset/switch/__init__.py +7 -21
  134. esphome/components/fan/__init__.py +52 -5
  135. esphome/components/fastled_base/__init__.py +1 -4
  136. esphome/components/fastled_base/fastled_light.cpp +1 -1
  137. esphome/components/feedback/cover.py +38 -33
  138. esphome/components/feedback/feedback_cover.cpp +2 -1
  139. esphome/components/fujitsu_general/climate.py +2 -9
  140. esphome/components/gcja5/gcja5.cpp +2 -1
  141. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  142. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  143. esphome/components/gpio_expander/cached_gpio.h +22 -7
  144. esphome/components/gps/__init__.py +47 -17
  145. esphome/components/gps/gps.cpp +42 -23
  146. esphome/components/gps/gps.h +17 -13
  147. esphome/components/graph/__init__.py +1 -2
  148. esphome/components/gree/climate.py +4 -6
  149. esphome/components/gree/gree.cpp +16 -2
  150. esphome/components/gree/gree.h +2 -2
  151. esphome/components/growatt_solar/growatt_solar.cpp +2 -1
  152. esphome/components/haier/climate.py +37 -34
  153. esphome/components/hbridge/fan/__init__.py +19 -17
  154. esphome/components/he60r/cover.py +4 -5
  155. esphome/components/heatpumpir/climate.py +3 -6
  156. esphome/components/hitachi_ac344/climate.py +2 -9
  157. esphome/components/hitachi_ac424/climate.py +2 -9
  158. esphome/components/hm3301/hm3301.h +1 -1
  159. esphome/components/hte501/sensor.py +6 -6
  160. esphome/components/http_request/__init__.py +39 -6
  161. esphome/components/http_request/http_request.cpp +20 -0
  162. esphome/components/http_request/http_request.h +57 -15
  163. esphome/components/http_request/http_request_arduino.cpp +22 -6
  164. esphome/components/http_request/http_request_arduino.h +4 -3
  165. esphome/components/http_request/http_request_host.cpp +141 -0
  166. esphome/components/http_request/http_request_host.h +37 -0
  167. esphome/components/http_request/http_request_idf.cpp +35 -3
  168. esphome/components/http_request/http_request_idf.h +10 -3
  169. esphome/components/http_request/httplib.h +9691 -0
  170. esphome/components/http_request/update/__init__.py +11 -8
  171. esphome/components/hyt271/sensor.py +6 -6
  172. esphome/components/i2c/i2c.h +4 -0
  173. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  174. esphome/components/i2s_audio/__init__.py +131 -22
  175. esphome/components/i2s_audio/i2s_audio.h +44 -4
  176. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  177. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  178. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  179. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  180. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  181. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  182. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  183. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  184. esphome/components/image/__init__.py +37 -17
  185. esphome/components/image/image.cpp +25 -8
  186. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  187. esphome/components/key_collector/__init__.py +35 -0
  188. esphome/components/key_collector/key_collector.cpp +8 -0
  189. esphome/components/key_collector/key_collector.h +10 -0
  190. esphome/components/kuntze/kuntze.cpp +2 -1
  191. esphome/components/ld2410/ld2410.h +1 -1
  192. esphome/components/ld2450/ld2450.h +1 -1
  193. esphome/components/light/__init__.py +57 -0
  194. esphome/components/lock/__init__.py +51 -4
  195. esphome/components/lock/automation.h +2 -13
  196. esphome/components/logger/__init__.py +22 -0
  197. esphome/components/logger/logger.cpp +154 -103
  198. esphome/components/logger/logger.h +211 -36
  199. esphome/components/logger/task_log_buffer.cpp +138 -0
  200. esphome/components/logger/task_log_buffer.h +69 -0
  201. esphome/components/lvgl/__init__.py +13 -5
  202. esphome/components/lvgl/automation.py +50 -1
  203. esphome/components/lvgl/defines.py +0 -1
  204. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  205. esphome/components/lvgl/text/__init__.py +1 -2
  206. esphome/components/mapping/__init__.py +134 -0
  207. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
  208. esphome/components/max7219digit/max7219digit.cpp +28 -27
  209. esphome/components/mdns/__init__.py +11 -5
  210. esphome/components/mdns/mdns_component.cpp +11 -5
  211. esphome/components/mdns/mdns_component.h +3 -2
  212. esphome/components/mdns/mdns_esp32.cpp +4 -3
  213. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  214. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  215. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  216. esphome/components/media_player/__init__.py +33 -1
  217. esphome/components/mhz19/sensor.py +11 -7
  218. esphome/components/micro_wake_word/__init__.py +99 -31
  219. esphome/components/micro_wake_word/automation.h +54 -0
  220. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  221. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  222. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  223. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  224. esphome/components/micro_wake_word/streaming_model.h +85 -13
  225. esphome/components/microphone/__init__.py +139 -9
  226. esphome/components/microphone/automation.h +14 -2
  227. esphome/components/microphone/microphone.cpp +21 -0
  228. esphome/components/microphone/microphone.h +14 -5
  229. esphome/components/microphone/microphone_source.cpp +95 -0
  230. esphome/components/microphone/microphone_source.h +80 -0
  231. esphome/components/mics_4514/sensor.py +25 -14
  232. esphome/components/midea/climate.py +3 -4
  233. esphome/components/midea_ir/climate.py +3 -5
  234. esphome/components/mipi_spi/__init__.py +15 -0
  235. esphome/components/mipi_spi/display.py +474 -0
  236. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  237. esphome/components/mipi_spi/mipi_spi.h +171 -0
  238. esphome/components/mipi_spi/models/__init__.py +65 -0
  239. esphome/components/mipi_spi/models/amoled.py +72 -0
  240. esphome/components/mipi_spi/models/commands.py +82 -0
  241. esphome/components/mipi_spi/models/cyd.py +10 -0
  242. esphome/components/mipi_spi/models/ili.py +749 -0
  243. esphome/components/mipi_spi/models/jc.py +260 -0
  244. esphome/components/mipi_spi/models/lanbon.py +15 -0
  245. esphome/components/mipi_spi/models/lilygo.py +60 -0
  246. esphome/components/mipi_spi/models/waveshare.py +139 -0
  247. esphome/components/mitsubishi/climate.py +2 -5
  248. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  249. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  250. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  251. esphome/components/mlx90393/sensor.py +5 -0
  252. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  253. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  254. esphome/components/modbus/modbus.cpp +2 -1
  255. esphome/components/mqtt/__init__.py +1 -1
  256. esphome/components/mqtt/mqtt_client.cpp +6 -2
  257. esphome/components/mqtt/mqtt_const.h +4 -0
  258. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  259. esphome/components/mqtt/mqtt_fan.h +2 -0
  260. esphome/components/ms5611/sensor.py +6 -6
  261. esphome/components/ms8607/sensor.py +3 -3
  262. esphome/components/network/__init__.py +1 -1
  263. esphome/components/nextion/base_component.py +17 -16
  264. esphome/components/nextion/display.py +11 -2
  265. esphome/components/nextion/nextion.cpp +39 -1
  266. esphome/components/nextion/nextion.h +50 -0
  267. esphome/components/noblex/climate.py +2 -9
  268. esphome/components/number/__init__.py +12 -9
  269. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  270. esphome/components/one_wire/one_wire_bus.h +14 -8
  271. esphome/components/online_image/bmp_image.cpp +48 -11
  272. esphome/components/online_image/bmp_image.h +2 -0
  273. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  274. esphome/components/opentherm/number/__init__.py +11 -20
  275. esphome/components/opentherm/sensor/__init__.py +3 -3
  276. esphome/components/opentherm/switch/__init__.py +3 -5
  277. esphome/components/output/lock/__init__.py +11 -9
  278. esphome/components/packages/__init__.py +33 -31
  279. esphome/components/packet_transport/__init__.py +201 -0
  280. esphome/components/packet_transport/binary_sensor.py +19 -0
  281. esphome/components/packet_transport/packet_transport.cpp +534 -0
  282. esphome/components/packet_transport/packet_transport.h +154 -0
  283. esphome/components/packet_transport/sensor.py +19 -0
  284. esphome/components/pca9685/pca9685_output.cpp +2 -1
  285. esphome/components/pid/climate.py +2 -4
  286. esphome/components/pm2005/__init__.py +1 -0
  287. esphome/components/pm2005/pm2005.cpp +123 -0
  288. esphome/components/pm2005/pm2005.h +46 -0
  289. esphome/components/pm2005/sensor.py +86 -0
  290. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  291. esphome/components/pmsa003i/pmsa003i.h +25 -25
  292. esphome/components/pmsx003/pmsx003.cpp +195 -230
  293. esphome/components/pmsx003/pmsx003.h +51 -33
  294. esphome/components/pmsx003/sensor.py +21 -11
  295. esphome/components/pn7150/pn7150.h +2 -2
  296. esphome/components/pn7160/pn7160.h +2 -2
  297. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  298. esphome/components/prometheus/prometheus_handler.h +17 -0
  299. esphome/components/psram/__init__.py +7 -5
  300. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  301. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  302. esphome/components/pzem004t/pzem004t.cpp +2 -1
  303. esphome/components/qspi_dbi/__init__.py +0 -1
  304. esphome/components/qspi_dbi/display.py +2 -1
  305. esphome/components/qspi_dbi/models.py +1 -2
  306. esphome/components/remote_base/__init__.py +91 -0
  307. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  308. esphome/components/remote_base/beo4_protocol.h +43 -0
  309. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  310. esphome/components/remote_base/gobox_protocol.h +54 -0
  311. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  312. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  313. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  314. esphome/components/rf_bridge/rf_bridge.cpp +2 -1
  315. esphome/components/scd30/sensor.py +2 -3
  316. esphome/components/scd4x/sensor.py +4 -5
  317. esphome/components/sdp3x/sensor.py +2 -1
  318. esphome/components/sds011/sds011.cpp +2 -1
  319. esphome/components/select/__init__.py +19 -20
  320. esphome/components/sen5x/sen5x.cpp +55 -36
  321. esphome/components/sen5x/sensor.py +1 -1
  322. esphome/components/senseair/sensor.py +3 -3
  323. esphome/components/sensor/__init__.py +158 -14
  324. esphome/components/sensor/filter.cpp +23 -0
  325. esphome/components/sensor/filter.h +22 -0
  326. esphome/components/sgp30/sensor.py +14 -16
  327. esphome/components/sgp4x/sensor.py +1 -1
  328. esphome/components/sht4x/sht4x.cpp +43 -22
  329. esphome/components/sht4x/sht4x.h +1 -1
  330. esphome/components/shtcx/sensor.py +6 -6
  331. esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
  332. esphome/components/sml/text_sensor/__init__.py +4 -6
  333. esphome/components/sound_level/__init__.py +0 -0
  334. esphome/components/sound_level/sensor.py +97 -0
  335. esphome/components/sound_level/sound_level.cpp +194 -0
  336. esphome/components/sound_level/sound_level.h +73 -0
  337. esphome/components/speaker/media_player/__init__.py +4 -8
  338. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  339. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  340. esphome/components/speaker/speaker.h +4 -7
  341. esphome/components/speed/fan/__init__.py +17 -16
  342. esphome/components/spi/spi.h +11 -1
  343. esphome/components/sprinkler/__init__.py +18 -19
  344. esphome/components/sprinkler/sprinkler.cpp +6 -5
  345. esphome/components/switch/__init__.py +32 -42
  346. esphome/components/syslog/__init__.py +41 -0
  347. esphome/components/syslog/esphome_syslog.cpp +49 -0
  348. esphome/components/syslog/esphome_syslog.h +27 -0
  349. esphome/components/t6615/sensor.py +3 -3
  350. esphome/components/t6615/t6615.cpp +2 -1
  351. esphome/components/tca9555/tca9555.cpp +11 -6
  352. esphome/components/tcl112/climate.py +2 -9
  353. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  354. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  355. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  356. esphome/components/template/cover/__init__.py +27 -21
  357. esphome/components/template/fan/__init__.py +14 -12
  358. esphome/components/template/lock/__init__.py +20 -25
  359. esphome/components/template/lock/automation.h +18 -0
  360. esphome/components/template/text/__init__.py +4 -3
  361. esphome/components/template/valve/__init__.py +32 -21
  362. esphome/components/template/valve/automation.h +24 -0
  363. esphome/components/text/__init__.py +32 -1
  364. esphome/components/text_sensor/__init__.py +24 -29
  365. esphome/components/thermostat/climate.py +5 -5
  366. esphome/components/time_based/cover.py +17 -16
  367. esphome/components/time_based/time_based_cover.cpp +2 -1
  368. esphome/components/tm1638/switch/__init__.py +10 -7
  369. esphome/components/tormatic/cover.py +4 -5
  370. esphome/components/toshiba/climate.py +3 -5
  371. esphome/components/touchscreen/touchscreen.cpp +3 -1
  372. esphome/components/tuya/climate/__init__.py +5 -6
  373. esphome/components/tuya/cover/__init__.py +6 -11
  374. esphome/components/tuya/select/__init__.py +15 -5
  375. esphome/components/tuya/select/tuya_select.cpp +6 -1
  376. esphome/components/tuya/select/tuya_select.h +5 -1
  377. esphome/components/uart/packet_transport/__init__.py +20 -0
  378. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  379. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  380. esphome/components/uart/switch/uart_switch.cpp +2 -1
  381. esphome/components/udp/__init__.py +126 -128
  382. esphome/components/udp/automation.h +40 -0
  383. esphome/components/udp/binary_sensor.py +3 -25
  384. esphome/components/udp/packet_transport/__init__.py +29 -0
  385. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  386. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  387. esphome/components/udp/sensor.py +3 -25
  388. esphome/components/udp/udp_component.cpp +26 -470
  389. esphome/components/udp/udp_component.h +21 -128
  390. esphome/components/update/__init__.py +31 -1
  391. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  392. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
  393. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  394. esphome/components/uptime/text_sensor/__init__.py +47 -7
  395. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  396. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  397. esphome/components/valve/__init__.py +34 -3
  398. esphome/components/valve/automation.h +1 -19
  399. esphome/components/vl53l0x/sensor.py +11 -0
  400. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  401. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  402. esphome/components/voice_assistant/__init__.py +36 -10
  403. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  404. esphome/components/voice_assistant/voice_assistant.h +26 -25
  405. esphome/components/waveshare_epaper/display.py +6 -0
  406. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  407. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  408. esphome/components/weikai/weikai.cpp +0 -52
  409. esphome/components/whirlpool/climate.py +3 -5
  410. esphome/components/whynter/climate.py +3 -5
  411. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  412. esphome/components/yashima/climate.py +6 -6
  413. esphome/components/zhlt01/climate.py +2 -7
  414. esphome/config.py +13 -13
  415. esphome/config_validation.py +38 -58
  416. esphome/const.py +15 -1
  417. esphome/core/__init__.py +2 -0
  418. esphome/core/application.cpp +27 -10
  419. esphome/core/application.h +9 -1
  420. esphome/core/automation.h +4 -3
  421. esphome/core/component.cpp +28 -7
  422. esphome/core/component.h +10 -1
  423. esphome/core/defines.h +23 -17
  424. esphome/core/doxygen.h +13 -0
  425. esphome/core/macros.h +4 -0
  426. esphome/core/scheduler.cpp +7 -1
  427. esphome/cpp_generator.py +6 -2
  428. esphome/dashboard/web_server.py +3 -3
  429. esphome/helpers.py +39 -0
  430. esphome/loader.py +4 -0
  431. esphome/log.py +15 -19
  432. esphome/mqtt.py +23 -10
  433. esphome/platformio_api.py +1 -1
  434. esphome/schema_extractors.py +0 -1
  435. esphome/voluptuous_schema.py +3 -1
  436. esphome/vscode.py +15 -0
  437. esphome/wizard.py +47 -37
  438. esphome/zeroconf.py +7 -3
  439. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/METADATA +10 -11
  440. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/RECORD +444 -383
  441. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/WHEEL +1 -1
  442. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/entry_points.txt +0 -0
  443. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/licenses/LICENSE +0 -0
  444. {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,153 @@
1
+ #include "beo4_protocol.h"
2
+ #include "esphome/core/log.h"
3
+
4
+ #include <cinttypes>
5
+
6
+ namespace esphome {
7
+ namespace remote_base {
8
+
9
+ static const char *const TAG = "remote.beo4";
10
+
11
+ // beo4 pulse width, high=carrier_pulse low=data_pulse
12
+ constexpr uint16_t PW_CARR_US = 200; // carrier pulse length
13
+ constexpr uint16_t PW_ZERO_US = 2925; // + 200 = 3125 µs
14
+ constexpr uint16_t PW_SAME_US = 6050; // + 200 = 6250 µs
15
+ constexpr uint16_t PW_ONE_US = 9175; // + 200 = 9375 µs
16
+ constexpr uint16_t PW_STOP_US = 12300; // + 200 = 12500 µs
17
+ constexpr uint16_t PW_START_US = 15425; // + 200 = 15625 µs
18
+
19
+ // beo4 pulse codes
20
+ constexpr uint8_t PC_ZERO = (PW_CARR_US + PW_ZERO_US) / 3125; // =1
21
+ constexpr uint8_t PC_SAME = (PW_CARR_US + PW_SAME_US) / 3125; // =2
22
+ constexpr uint8_t PC_ONE = (PW_CARR_US + PW_ONE_US) / 3125; // =3
23
+ constexpr uint8_t PC_STOP = (PW_CARR_US + PW_STOP_US) / 3125; // =4
24
+ constexpr uint8_t PC_START = (PW_CARR_US + PW_START_US) / 3125; // =5
25
+
26
+ // beo4 number of data bits = beoLink+beoSrc+beoCmd = 1+8+8 = 17
27
+ constexpr uint32_t N_BITS = 1 + 8 + 8;
28
+
29
+ // required symbols = 2*(start_sequence + n_bits + stop) = 2*(3+17+1) = 42
30
+ constexpr uint32_t N_SYM = 2 + ((3 + 17 + 1) * 2u); // + 2 = 44
31
+
32
+ // states finite-state-machine decoder
33
+ enum class RxSt { RX_IDLE, RX_DATA, RX_STOP };
34
+
35
+ void Beo4Protocol::encode(RemoteTransmitData *dst, const Beo4Data &data) {
36
+ uint32_t beo_code = ((uint32_t) data.source << 8) + (uint32_t) data.command;
37
+ uint32_t jc = 0, ic = 0;
38
+ uint32_t cur_bit = 0;
39
+ uint32_t pre_bit = 0;
40
+ dst->set_carrier_frequency(455000);
41
+ dst->reserve(N_SYM);
42
+
43
+ // start sequence=zero,zero,start
44
+ dst->item(PW_CARR_US, PW_ZERO_US);
45
+ dst->item(PW_CARR_US, PW_ZERO_US);
46
+ dst->item(PW_CARR_US, PW_START_US);
47
+
48
+ // the data-bit BeoLink is always 0
49
+ dst->item(PW_CARR_US, PW_ZERO_US);
50
+
51
+ // The B&O trick to avoid extra long and extra short
52
+ // code-frames by extracting the data-bits from left
53
+ // to right, then comparing current with previous bit
54
+ // and set pulse to "same" "one" or "zero"
55
+ for (jc = 15, ic = 0; ic < 16; ic++, jc--) {
56
+ cur_bit = ((beo_code) >> jc) & 1;
57
+ if (cur_bit == pre_bit) {
58
+ dst->item(PW_CARR_US, PW_SAME_US);
59
+ } else if (1 == cur_bit) {
60
+ dst->item(PW_CARR_US, PW_ONE_US);
61
+ } else {
62
+ dst->item(PW_CARR_US, PW_ZERO_US);
63
+ }
64
+ pre_bit = cur_bit;
65
+ }
66
+ // complete the frame with stop-symbol and final carrier pulse
67
+ dst->item(PW_CARR_US, PW_STOP_US);
68
+ dst->mark(PW_CARR_US);
69
+ }
70
+
71
+ optional<Beo4Data> Beo4Protocol::decode(RemoteReceiveData src) {
72
+ int32_t n_sym = src.size();
73
+ Beo4Data data{
74
+ .source = 0,
75
+ .command = 0,
76
+ .repeats = 0,
77
+ };
78
+ // suppress dummy codes (TSO7000 hiccups)
79
+ if (n_sym > 42) {
80
+ static uint32_t beo_code = 0;
81
+ RxSt fsm = RxSt::RX_IDLE;
82
+ int32_t ic = 0;
83
+ int32_t jc = 0;
84
+ uint32_t pre_bit = 0;
85
+ uint32_t cnt_bit = 0;
86
+ ESP_LOGD(TAG, "Beo4: n_sym=%" PRId32, n_sym);
87
+ for (jc = 0, ic = 0; ic < (n_sym - 1); ic += 2, jc++) {
88
+ int32_t pulse_width = src[ic] - src[ic + 1];
89
+ // suppress TSOP7000 (dummy pulses)
90
+ if (pulse_width > 1500) {
91
+ int32_t pulse_code = (pulse_width + 1560) / 3125;
92
+ switch (fsm) {
93
+ case RxSt::RX_IDLE: {
94
+ beo_code = 0;
95
+ cnt_bit = 0;
96
+ pre_bit = 0;
97
+ if (PC_START == pulse_code) {
98
+ fsm = RxSt::RX_DATA;
99
+ }
100
+ break;
101
+ }
102
+ case RxSt::RX_DATA: {
103
+ uint32_t cur_bit = 0;
104
+ switch (pulse_code) {
105
+ case PC_ZERO: {
106
+ cur_bit = pre_bit = 0;
107
+ break;
108
+ }
109
+ case PC_SAME: {
110
+ cur_bit = pre_bit;
111
+ break;
112
+ }
113
+ case PC_ONE: {
114
+ cur_bit = pre_bit = 1;
115
+ break;
116
+ }
117
+ default: {
118
+ fsm = RxSt::RX_IDLE;
119
+ break;
120
+ }
121
+ }
122
+ beo_code = (beo_code << 1) + cur_bit;
123
+ if (++cnt_bit == N_BITS) {
124
+ fsm = RxSt::RX_STOP;
125
+ }
126
+ break;
127
+ }
128
+ case RxSt::RX_STOP: {
129
+ if (PC_STOP == pulse_code) {
130
+ data.source = (uint8_t) ((beo_code >> 8) & 0xff);
131
+ data.command = (uint8_t) ((beo_code) &0xff);
132
+ data.repeats++;
133
+ }
134
+ if ((n_sym - ic) < 42) {
135
+ return data;
136
+ } else {
137
+ fsm = RxSt::RX_IDLE;
138
+ }
139
+ break;
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return {}; // decoding failed
146
+ }
147
+
148
+ void Beo4Protocol::dump(const Beo4Data &data) {
149
+ ESP_LOGI(TAG, "Beo4: source=0x%02x command=0x%02x repeats=%d ", data.source, data.command, data.repeats);
150
+ }
151
+
152
+ } // namespace remote_base
153
+ } // namespace esphome
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #include "remote_base.h"
4
+
5
+ #include <cinttypes>
6
+
7
+ namespace esphome {
8
+ namespace remote_base {
9
+
10
+ struct Beo4Data {
11
+ uint8_t source; // beoSource, e.g. video, audio, light...
12
+ uint8_t command; // beoCommend, e.g. volume+, mute,...
13
+ uint8_t repeats; // beoRepeat for repeat commands, e.g. up, down...
14
+
15
+ bool operator==(const Beo4Data &rhs) const { return source == rhs.source && command == rhs.command; }
16
+ };
17
+
18
+ class Beo4Protocol : public RemoteProtocol<Beo4Data> {
19
+ public:
20
+ void encode(RemoteTransmitData *dst, const Beo4Data &data) override;
21
+ optional<Beo4Data> decode(RemoteReceiveData src) override;
22
+ void dump(const Beo4Data &data) override;
23
+ };
24
+
25
+ DECLARE_REMOTE_PROTOCOL(Beo4)
26
+
27
+ template<typename... Ts> class Beo4Action : public RemoteTransmitterActionBase<Ts...> {
28
+ public:
29
+ TEMPLATABLE_VALUE(uint8_t, source)
30
+ TEMPLATABLE_VALUE(uint8_t, command)
31
+ TEMPLATABLE_VALUE(uint8_t, repeats)
32
+
33
+ void encode(RemoteTransmitData *dst, Ts... x) override {
34
+ Beo4Data data{};
35
+ data.source = this->source_.value(x...);
36
+ data.command = this->command_.value(x...);
37
+ data.repeats = this->repeats_.value(x...);
38
+ Beo4Protocol().encode(dst, data);
39
+ }
40
+ };
41
+
42
+ } // namespace remote_base
43
+ } // namespace esphome
@@ -0,0 +1,131 @@
1
+ #include "gobox_protocol.h"
2
+ #include "esphome/core/log.h"
3
+
4
+ namespace esphome {
5
+ namespace remote_base {
6
+
7
+ static const char *const TAG = "remote.gobox";
8
+
9
+ constexpr uint32_t BIT_MARK_US = 580; // 70us seems like a safe time delta for the receiver...
10
+ constexpr uint32_t BIT_ONE_SPACE_US = 1640;
11
+ constexpr uint32_t BIT_ZERO_SPACE_US = 545;
12
+ constexpr uint64_t HEADER = 0b011001001100010uL; // 15 bits
13
+ constexpr uint64_t HEADER_SIZE = 15;
14
+ constexpr uint64_t CODE_SIZE = 17;
15
+
16
+ void GoboxProtocol::dump_timings_(const RawTimings &timings) const {
17
+ ESP_LOGD(TAG, "Gobox: size=%u", timings.size());
18
+ for (int32_t timing : timings) {
19
+ ESP_LOGD(TAG, "Gobox: timing=%ld", (long) timing);
20
+ }
21
+ }
22
+
23
+ void GoboxProtocol::encode(RemoteTransmitData *dst, const GoboxData &data) {
24
+ ESP_LOGI(TAG, "Send Gobox: code=0x%x", data.code);
25
+ dst->set_carrier_frequency(38000);
26
+ dst->reserve((HEADER_SIZE + CODE_SIZE + 1) * 2);
27
+ uint64_t code = (HEADER << CODE_SIZE) | (data.code & ((1UL << CODE_SIZE) - 1));
28
+ ESP_LOGI(TAG, "Send Gobox: code=0x%Lx", code);
29
+ for (int16_t i = (HEADER_SIZE + CODE_SIZE - 1); i >= 0; i--) {
30
+ if (code & ((uint64_t) 1 << i)) {
31
+ dst->item(BIT_MARK_US, BIT_ONE_SPACE_US);
32
+ } else {
33
+ dst->item(BIT_MARK_US, BIT_ZERO_SPACE_US);
34
+ }
35
+ }
36
+ dst->item(BIT_MARK_US, 2000);
37
+
38
+ dump_timings_(dst->get_data());
39
+ }
40
+
41
+ optional<GoboxData> GoboxProtocol::decode(RemoteReceiveData src) {
42
+ if (src.size() < ((HEADER_SIZE + CODE_SIZE) * 2 + 1)) {
43
+ return {};
44
+ }
45
+
46
+ // First check for the header
47
+ uint64_t code = HEADER;
48
+ for (int16_t i = HEADER_SIZE - 1; i >= 0; i--) {
49
+ if (code & ((uint64_t) 1 << i)) {
50
+ if (!src.expect_item(BIT_MARK_US, BIT_ONE_SPACE_US)) {
51
+ return {};
52
+ }
53
+ } else {
54
+ if (!src.expect_item(BIT_MARK_US, BIT_ZERO_SPACE_US)) {
55
+ return {};
56
+ }
57
+ }
58
+ }
59
+
60
+ // Next, build up the code
61
+ code = 0UL;
62
+ for (int16_t i = CODE_SIZE - 1; i >= 0; i--) {
63
+ if (!src.expect_mark(BIT_MARK_US)) {
64
+ return {};
65
+ }
66
+ if (src.expect_space(BIT_ONE_SPACE_US)) {
67
+ code |= (1UL << i);
68
+ } else if (!src.expect_space(BIT_ZERO_SPACE_US)) {
69
+ return {};
70
+ }
71
+ }
72
+
73
+ if (!src.expect_mark(BIT_MARK_US)) {
74
+ return {};
75
+ }
76
+
77
+ dump_timings_(src.get_raw_data());
78
+
79
+ GoboxData out;
80
+ out.code = code;
81
+
82
+ return out;
83
+ }
84
+
85
+ void GoboxProtocol::dump(const GoboxData &data) {
86
+ ESP_LOGI(TAG, "Received Gobox: code=0x%x", data.code);
87
+ switch (data.code) {
88
+ case GOBOX_MENU:
89
+ ESP_LOGI(TAG, "Received Gobox: key=MENU");
90
+ break;
91
+ case GOBOX_RETURN:
92
+ ESP_LOGI(TAG, "Received Gobox: key=RETURN");
93
+ break;
94
+ case GOBOX_UP:
95
+ ESP_LOGI(TAG, "Received Gobox: key=UP");
96
+ break;
97
+ case GOBOX_LEFT:
98
+ ESP_LOGI(TAG, "Received Gobox: key=LEFT");
99
+ break;
100
+ case GOBOX_RIGHT:
101
+ ESP_LOGI(TAG, "Received Gobox: key=RIGHT");
102
+ break;
103
+ case GOBOX_DOWN:
104
+ ESP_LOGI(TAG, "Received Gobox: key=DOWN");
105
+ break;
106
+ case GOBOX_OK:
107
+ ESP_LOGI(TAG, "Received Gobox: key=OK");
108
+ break;
109
+ case GOBOX_TOGGLE:
110
+ ESP_LOGI(TAG, "Received Gobox: key=TOGGLE");
111
+ break;
112
+ case GOBOX_PROFILE:
113
+ ESP_LOGI(TAG, "Received Gobox: key=PROFILE");
114
+ break;
115
+ case GOBOX_FASTER:
116
+ ESP_LOGI(TAG, "Received Gobox: key=FASTER");
117
+ break;
118
+ case GOBOX_SLOWER:
119
+ ESP_LOGI(TAG, "Received Gobox: key=SLOWER");
120
+ break;
121
+ case GOBOX_LOUDER:
122
+ ESP_LOGI(TAG, "Received Gobox: key=LOUDER");
123
+ break;
124
+ case GOBOX_SOFTER:
125
+ ESP_LOGI(TAG, "Received Gobox: key=SOFTER");
126
+ break;
127
+ }
128
+ }
129
+
130
+ } // namespace remote_base
131
+ } // namespace esphome
@@ -0,0 +1,54 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "remote_base.h"
5
+
6
+ namespace esphome {
7
+ namespace remote_base {
8
+
9
+ struct GoboxData {
10
+ int code;
11
+ bool operator==(const GoboxData &rhs) const { return code == rhs.code; }
12
+ };
13
+
14
+ enum {
15
+ GOBOX_MENU = 0xaa55,
16
+ GOBOX_RETURN = 0x22dd,
17
+ GOBOX_UP = 0x0af5,
18
+ GOBOX_LEFT = 0x8a75,
19
+ GOBOX_RIGHT = 0x48b7,
20
+ GOBOX_DOWN = 0xa25d,
21
+ GOBOX_OK = 0xc837,
22
+ GOBOX_TOGGLE = 0xb847,
23
+ GOBOX_PROFILE = 0xfa05,
24
+ GOBOX_FASTER = 0xf00f,
25
+ GOBOX_SLOWER = 0xd02f,
26
+ GOBOX_LOUDER = 0xb04f,
27
+ GOBOX_SOFTER = 0xf807,
28
+ };
29
+
30
+ class GoboxProtocol : public RemoteProtocol<GoboxData> {
31
+ private:
32
+ void dump_timings_(const RawTimings &timings) const;
33
+
34
+ public:
35
+ void encode(RemoteTransmitData *dst, const GoboxData &data) override;
36
+ optional<GoboxData> decode(RemoteReceiveData src) override;
37
+ void dump(const GoboxData &data) override;
38
+ };
39
+
40
+ DECLARE_REMOTE_PROTOCOL(Gobox)
41
+
42
+ template<typename... Ts> class GoboxAction : public RemoteTransmitterActionBase<Ts...> {
43
+ public:
44
+ TEMPLATABLE_VALUE(uint64_t, code);
45
+
46
+ void encode(RemoteTransmitData *dst, Ts... x) override {
47
+ GoboxData data{};
48
+ data.code = this->code_.value(x...);
49
+ GoboxProtocol().encode(dst, data);
50
+ }
51
+ };
52
+
53
+ } // namespace remote_base
54
+ } // namespace esphome
@@ -208,7 +208,6 @@ void RemoteReceiverComponent::loop() {
208
208
  this->store_.buffer_read = next_read;
209
209
 
210
210
  if (!this->temp_.empty()) {
211
- this->temp_.push_back(-this->idle_us_);
212
211
  this->call_listeners_dumpers_();
213
212
  }
214
213
  }
@@ -219,11 +218,9 @@ void RemoteReceiverComponent::loop() {
219
218
  this->decode_rmt_(item, len / sizeof(rmt_item32_t));
220
219
  vRingbufferReturnItem(this->ringbuf_, item);
221
220
 
222
- if (this->temp_.empty())
223
- return;
224
-
225
- this->temp_.push_back(-this->idle_us_);
226
- this->call_listeners_dumpers_();
221
+ if (!this->temp_.empty()) {
222
+ this->call_listeners_dumpers_();
223
+ }
227
224
  }
228
225
  #endif
229
226
  }
@@ -234,6 +231,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_c
234
231
  void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count) {
235
232
  #endif
236
233
  bool prev_level = false;
234
+ bool idle_level = false;
237
235
  uint32_t prev_length = 0;
238
236
  this->temp_.clear();
239
237
  int32_t multiplier = this->pin_->is_inverted() ? -1 : 1;
@@ -266,7 +264,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count)
266
264
  } else if ((bool(item[i].level0) == prev_level) || (item[i].duration0 < filter_ticks)) {
267
265
  prev_length += item[i].duration0;
268
266
  } else {
269
- if (prev_length > 0) {
267
+ if (prev_length >= filter_ticks) {
270
268
  if (prev_level) {
271
269
  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
272
270
  } else {
@@ -276,6 +274,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count)
276
274
  prev_level = bool(item[i].level0);
277
275
  prev_length = item[i].duration0;
278
276
  }
277
+ idle_level = !bool(item[i].level0);
279
278
 
280
279
  if (item[i].duration1 == 0u) {
281
280
  // EOF, sometimes garbage follows, break early
@@ -283,7 +282,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count)
283
282
  } else if ((bool(item[i].level1) == prev_level) || (item[i].duration1 < filter_ticks)) {
284
283
  prev_length += item[i].duration1;
285
284
  } else {
286
- if (prev_length > 0) {
285
+ if (prev_length >= filter_ticks) {
287
286
  if (prev_level) {
288
287
  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
289
288
  } else {
@@ -293,14 +292,22 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count)
293
292
  prev_level = bool(item[i].level1);
294
293
  prev_length = item[i].duration1;
295
294
  }
295
+ idle_level = !bool(item[i].level1);
296
296
  }
297
- if (prev_length > 0) {
297
+ if (prev_length >= filter_ticks && prev_level != idle_level) {
298
298
  if (prev_level) {
299
299
  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
300
300
  } else {
301
301
  this->temp_.push_back(-int32_t(this->to_microseconds_(prev_length)) * multiplier);
302
302
  }
303
303
  }
304
+ if (!this->temp_.empty()) {
305
+ if (idle_level) {
306
+ this->temp_.push_back(this->idle_us_ * multiplier);
307
+ } else {
308
+ this->temp_.push_back(-int32_t(this->idle_us_) * multiplier);
309
+ }
310
+ }
304
311
  }
305
312
 
306
313
  } // namespace remote_receiver
@@ -43,13 +43,18 @@ void ResamplerSpeaker::setup() {
43
43
  return;
44
44
  }
45
45
 
46
- this->output_speaker_->add_audio_output_callback(
47
- [this](uint32_t new_playback_ms, uint32_t remainder_us, uint32_t pending_ms, uint32_t write_timestamp) {
48
- int32_t adjustment = this->playback_differential_ms_;
49
- this->playback_differential_ms_ -= adjustment;
50
- int32_t adjusted_playback_ms = static_cast<int32_t>(new_playback_ms) + adjustment;
51
- this->audio_output_callback_(adjusted_playback_ms, remainder_us, pending_ms, write_timestamp);
52
- });
46
+ this->output_speaker_->add_audio_output_callback([this](uint32_t new_frames, int64_t write_timestamp) {
47
+ if (this->audio_stream_info_.get_sample_rate() != this->target_stream_info_.get_sample_rate()) {
48
+ // Convert the number of frames from the target sample rate to the source sample rate. Track the remainder to
49
+ // avoid losing frames from integer division truncation.
50
+ const uint64_t numerator = new_frames * this->audio_stream_info_.get_sample_rate() + this->callback_remainder_;
51
+ const uint64_t denominator = this->target_stream_info_.get_sample_rate();
52
+ this->callback_remainder_ = numerator % denominator;
53
+ this->audio_output_callback_(numerator / denominator, write_timestamp);
54
+ } else {
55
+ this->audio_output_callback_(new_frames, write_timestamp);
56
+ }
57
+ });
53
58
  }
54
59
 
55
60
  void ResamplerSpeaker::loop() {
@@ -283,7 +288,6 @@ void ResamplerSpeaker::resample_task(void *params) {
283
288
  xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED);
284
289
  }
285
290
 
286
- this_resampler->playback_differential_ms_ = 0;
287
291
  while (err == ESP_OK) {
288
292
  uint32_t event_bits = xEventGroupGetBits(this_resampler->event_group_);
289
293
 
@@ -295,8 +299,6 @@ void ResamplerSpeaker::resample_task(void *params) {
295
299
  int32_t ms_differential = 0;
296
300
  audio::AudioResamplerState resampler_state = resampler->resample(false, &ms_differential);
297
301
 
298
- this_resampler->playback_differential_ms_ += ms_differential;
299
-
300
302
  if (resampler_state == audio::AudioResamplerState::FINISHED) {
301
303
  break;
302
304
  } else if (resampler_state == audio::AudioResamplerState::FAILED) {
@@ -100,7 +100,7 @@ class ResamplerSpeaker : public Component, public speaker::Speaker {
100
100
 
101
101
  uint32_t buffer_duration_ms_;
102
102
 
103
- int32_t playback_differential_ms_{0};
103
+ uint64_t callback_remainder_{0};
104
104
  };
105
105
 
106
106
  } // namespace resampler
@@ -1,5 +1,6 @@
1
1
  #include "rf_bridge.h"
2
2
  #include "esphome/core/log.h"
3
+ #include "esphome/core/application.h"
3
4
  #include <cinttypes>
4
5
  #include <cstring>
5
6
 
@@ -128,7 +129,7 @@ void RFBridgeComponent::write_byte_str_(const std::string &codes) {
128
129
  }
129
130
 
130
131
  void RFBridgeComponent::loop() {
131
- const uint32_t now = millis();
132
+ const uint32_t now = App.get_loop_component_start_time();
132
133
  if (now - this->last_bridge_byte_ > 50) {
133
134
  this->rx_buffer_.clear();
134
135
  this->last_bridge_byte_ = now;
@@ -18,6 +18,8 @@ from esphome.const import (
18
18
  UNIT_CELSIUS,
19
19
  UNIT_PARTS_PER_MILLION,
20
20
  UNIT_PERCENT,
21
+ CONF_AUTOMATIC_SELF_CALIBRATION,
22
+ CONF_AMBIENT_PRESSURE_COMPENSATION,
21
23
  )
22
24
 
23
25
  DEPENDENCIES = ["i2c"]
@@ -33,10 +35,7 @@ ForceRecalibrationWithReference = scd30_ns.class_(
33
35
  "ForceRecalibrationWithReference", automation.Action
34
36
  )
35
37
 
36
- CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration"
37
38
  CONF_ALTITUDE_COMPENSATION = "altitude_compensation"
38
- CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation"
39
-
40
39
 
41
40
  CONFIG_SCHEMA = (
42
41
  cv.Schema(
@@ -20,6 +20,10 @@ from esphome.const import (
20
20
  UNIT_CELSIUS,
21
21
  UNIT_PARTS_PER_MILLION,
22
22
  UNIT_PERCENT,
23
+ CONF_AUTOMATIC_SELF_CALIBRATION,
24
+ CONF_AMBIENT_PRESSURE_COMPENSATION,
25
+ CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE,
26
+ CONF_MEASUREMENT_MODE,
23
27
  )
24
28
 
25
29
  CODEOWNERS = ["@sjtrny", "@martgras"]
@@ -47,11 +51,6 @@ FactoryResetAction = scd4x_ns.class_("FactoryResetAction", automation.Action)
47
51
 
48
52
 
49
53
  CONF_ALTITUDE_COMPENSATION = "altitude_compensation"
50
- CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation"
51
- CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE = "ambient_pressure_compensation_source"
52
- CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration"
53
- CONF_MEASUREMENT_MODE = "measurement_mode"
54
-
55
54
 
56
55
  CONFIG_SCHEMA = (
57
56
  cv.Schema(
@@ -5,6 +5,7 @@ from esphome.const import (
5
5
  DEVICE_CLASS_PRESSURE,
6
6
  STATE_CLASS_MEASUREMENT,
7
7
  UNIT_HECTOPASCAL,
8
+ CONF_MEASUREMENT_MODE,
8
9
  )
9
10
 
10
11
  DEPENDENCIES = ["i2c"]
@@ -22,7 +23,7 @@ MEASUREMENT_MODE = {
22
23
  "mass_flow": MeasurementMode.MASS_FLOW_AVG,
23
24
  "differential_pressure": MeasurementMode.DP_AVG,
24
25
  }
25
- CONF_MEASUREMENT_MODE = "measurement_mode"
26
+
26
27
 
27
28
  CONFIG_SCHEMA = (
28
29
  sensor.sensor_schema(
@@ -1,5 +1,6 @@
1
1
  #include "sds011.h"
2
2
  #include "esphome/core/log.h"
3
+ #include "esphome/core/application.h"
3
4
 
4
5
  namespace esphome {
5
6
  namespace sds011 {
@@ -75,7 +76,7 @@ void SDS011Component::dump_config() {
75
76
  }
76
77
 
77
78
  void SDS011Component::loop() {
78
- const uint32_t now = millis();
79
+ const uint32_t now = App.get_loop_component_start_time();
79
80
  if ((now - this->last_transmission_ >= 500) && this->data_index_) {
80
81
  // last transmission too long ago. Reset RX index.
81
82
  ESP_LOGV(TAG, "Last transmission too long ago. Reset RX index.");
@@ -48,7 +48,7 @@ SELECT_OPERATION_OPTIONS = {
48
48
  }
49
49
 
50
50
 
51
- SELECT_SCHEMA = (
51
+ _SELECT_SCHEMA = (
52
52
  cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
53
53
  .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
54
54
  .extend(
@@ -64,29 +64,28 @@ SELECT_SCHEMA = (
64
64
  )
65
65
  )
66
66
 
67
- _UNDEF = object()
68
-
69
67
 
70
68
  def select_schema(
71
- class_: MockObjClass = _UNDEF,
69
+ class_: MockObjClass,
72
70
  *,
73
- entity_category: str = _UNDEF,
74
- icon: str = _UNDEF,
71
+ entity_category: str = cv.UNDEFINED,
72
+ icon: str = cv.UNDEFINED,
75
73
  ):
76
- schema = cv.Schema({})
77
- if class_ is not _UNDEF:
78
- schema = schema.extend({cv.GenerateID(): cv.declare_id(class_)})
79
- if entity_category is not _UNDEF:
80
- schema = schema.extend(
81
- {
82
- cv.Optional(
83
- CONF_ENTITY_CATEGORY, default=entity_category
84
- ): cv.entity_category
85
- }
86
- )
87
- if icon is not _UNDEF:
88
- schema = schema.extend({cv.Optional(CONF_ICON, default=icon): cv.icon})
89
- return SELECT_SCHEMA.extend(schema)
74
+ schema = {cv.GenerateID(): cv.declare_id(class_)}
75
+
76
+ for key, default, validator in [
77
+ (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
78
+ (CONF_ICON, icon, cv.icon),
79
+ ]:
80
+ if default is not cv.UNDEFINED:
81
+ schema[cv.Optional(key, default=default)] = validator
82
+
83
+ return _SELECT_SCHEMA.extend(schema)
84
+
85
+
86
+ # Remove before 2025.11.0
87
+ SELECT_SCHEMA = select_schema(Select)
88
+ SELECT_SCHEMA.add_extra(cv.deprecated_schema_constant("select"))
90
89
 
91
90
 
92
91
  async def setup_select_core_(var, config, *, options: list[str]):