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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  2. esphome/components/adc/__init__.py +51 -34
  3. esphome/components/airthings_wave_base/__init__.py +1 -1
  4. esphome/components/alarm_control_panel/__init__.py +37 -2
  5. esphome/components/am43/cover/__init__.py +4 -5
  6. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  8. esphome/components/analog_threshold/binary_sensor.py +10 -8
  9. esphome/components/anova/climate.py +4 -5
  10. esphome/components/api/__init__.py +25 -8
  11. esphome/components/api/api_connection.cpp +77 -10
  12. esphome/components/api/api_connection.h +6 -1
  13. esphome/components/api/api_frame_helper.cpp +98 -130
  14. esphome/components/api/api_frame_helper.h +12 -2
  15. esphome/components/api/api_noise_context.h +13 -4
  16. esphome/components/api/api_pb2.cpp +1422 -1
  17. esphome/components/api/api_pb2.h +255 -1
  18. esphome/components/api/api_pb2_service.cpp +162 -49
  19. esphome/components/api/api_pb2_service.h +90 -51
  20. esphome/components/api/api_pb2_size.h +361 -0
  21. esphome/components/api/api_server.cpp +110 -34
  22. esphome/components/api/api_server.h +8 -0
  23. esphome/components/api/proto.h +38 -9
  24. esphome/components/as3935_i2c/as3935_i2c.h +0 -3
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/atm90e32/__init__.py +1 -0
  27. esphome/components/atm90e32/atm90e32.cpp +576 -199
  28. esphome/components/atm90e32/atm90e32.h +128 -31
  29. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  30. esphome/components/atm90e32/button/__init__.py +62 -10
  31. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  32. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  33. esphome/components/atm90e32/number/__init__.py +130 -0
  34. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  35. esphome/components/atm90e32/sensor.py +21 -4
  36. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  37. esphome/components/audio/__init__.py +96 -49
  38. esphome/components/audio/audio.h +48 -0
  39. esphome/components/audio/audio_decoder.cpp +1 -1
  40. esphome/components/audio/audio_resampler.cpp +2 -0
  41. esphome/components/audio/audio_resampler.h +1 -0
  42. esphome/components/ballu/climate.py +2 -9
  43. esphome/components/bang_bang/climate.py +5 -6
  44. esphome/components/bedjet/climate/__init__.py +3 -8
  45. esphome/components/bedjet/fan/__init__.py +2 -11
  46. esphome/components/binary/fan/__init__.py +13 -16
  47. esphome/components/binary_sensor/__init__.py +13 -10
  48. esphome/components/binary_sensor/binary_sensor.cpp +6 -10
  49. esphome/components/binary_sensor/binary_sensor.h +1 -1
  50. esphome/components/binary_sensor/filter.cpp +21 -21
  51. esphome/components/binary_sensor/filter.h +10 -10
  52. esphome/components/bl0906/constants.h +16 -16
  53. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  54. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  55. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +135 -21
  56. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  57. esphome/components/button/__init__.py +11 -8
  58. esphome/components/canbus/canbus.cpp +3 -0
  59. esphome/components/canbus/canbus.h +16 -0
  60. esphome/components/climate/__init__.py +35 -2
  61. esphome/components/climate/climate_mode.h +1 -1
  62. esphome/components/climate/climate_traits.h +63 -57
  63. esphome/components/climate_ir/__init__.py +57 -17
  64. esphome/components/climate_ir_lg/climate.py +2 -5
  65. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  66. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  67. esphome/components/color/__init__.py +2 -0
  68. esphome/components/const/__init__.py +5 -0
  69. esphome/components/coolix/climate.py +2 -9
  70. esphome/components/copy/cover/__init__.py +10 -9
  71. esphome/components/copy/fan/__init__.py +11 -9
  72. esphome/components/copy/lock/__init__.py +11 -9
  73. esphome/components/copy/text/__init__.py +9 -6
  74. esphome/components/cover/__init__.py +37 -2
  75. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  76. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  77. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  79. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  80. esphome/components/current_based/cover.py +37 -36
  81. esphome/components/daikin/climate.py +2 -9
  82. esphome/components/daikin/daikin.cpp +15 -9
  83. esphome/components/daikin/daikin.h +5 -5
  84. esphome/components/daikin_arc/climate.py +2 -7
  85. esphome/components/daikin_brc/climate.py +3 -5
  86. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  87. esphome/components/dallas_temp/dallas_temp.h +0 -1
  88. esphome/components/debug/debug_component.cpp +5 -0
  89. esphome/components/debug/debug_component.h +6 -0
  90. esphome/components/debug/debug_esp32.cpp +109 -254
  91. esphome/components/debug/sensor.py +14 -0
  92. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  93. esphome/components/delonghi/climate.py +2 -9
  94. esphome/components/demo/__init__.py +18 -20
  95. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  96. esphome/components/display/rect.cpp +4 -9
  97. esphome/components/display/rect.h +1 -1
  98. esphome/components/emmeti/climate.py +2 -9
  99. esphome/components/endstop/cover.py +17 -16
  100. esphome/components/esp32/__init__.py +60 -3
  101. esphome/components/esp32/core.cpp +11 -5
  102. esphome/components/esp32/gpio.cpp +86 -24
  103. esphome/components/esp32/gpio.py +15 -16
  104. esphome/components/esp32/gpio_esp32.py +1 -2
  105. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  106. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  107. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  108. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  109. esphome/components/esp32_ble/ble.cpp +1 -8
  110. esphome/components/esp32_ble/ble.h +5 -3
  111. esphome/components/esp32_ble/ble_advertising.h +1 -0
  112. esphome/components/esp32_ble_server/__init__.py +3 -0
  113. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  114. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  115. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  116. esphome/components/esp32_can/esp32_can.cpp +1 -1
  117. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  118. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  119. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  120. esphome/components/esp8266/gpio.cpp +69 -8
  121. esphome/components/event/__init__.py +13 -10
  122. esphome/components/factory_reset/switch/__init__.py +7 -21
  123. esphome/components/fan/__init__.py +52 -5
  124. esphome/components/fastled_base/__init__.py +1 -4
  125. esphome/components/fastled_base/fastled_light.cpp +1 -1
  126. esphome/components/feedback/cover.py +38 -33
  127. esphome/components/fujitsu_general/climate.py +2 -9
  128. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  129. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  130. esphome/components/gpio_expander/cached_gpio.h +22 -7
  131. esphome/components/gps/__init__.py +11 -2
  132. esphome/components/gps/gps.cpp +11 -8
  133. esphome/components/gps/gps.h +9 -6
  134. esphome/components/graph/__init__.py +1 -2
  135. esphome/components/gree/climate.py +4 -6
  136. esphome/components/gree/gree.cpp +16 -2
  137. esphome/components/gree/gree.h +2 -2
  138. esphome/components/haier/climate.py +37 -34
  139. esphome/components/hbridge/fan/__init__.py +19 -17
  140. esphome/components/he60r/cover.py +4 -5
  141. esphome/components/heatpumpir/climate.py +3 -6
  142. esphome/components/hitachi_ac344/climate.py +2 -9
  143. esphome/components/hitachi_ac424/climate.py +2 -9
  144. esphome/components/hlw8012/hlw8012.cpp +1 -1
  145. esphome/components/hm3301/hm3301.h +1 -1
  146. esphome/components/http_request/__init__.py +39 -6
  147. esphome/components/http_request/http_request.cpp +20 -0
  148. esphome/components/http_request/http_request.h +57 -15
  149. esphome/components/http_request/http_request_arduino.cpp +22 -6
  150. esphome/components/http_request/http_request_arduino.h +4 -3
  151. esphome/components/http_request/http_request_host.cpp +141 -0
  152. esphome/components/http_request/http_request_host.h +37 -0
  153. esphome/components/http_request/http_request_idf.cpp +35 -3
  154. esphome/components/http_request/http_request_idf.h +10 -3
  155. esphome/components/http_request/httplib.h +9691 -0
  156. esphome/components/http_request/update/__init__.py +11 -8
  157. esphome/components/i2c/i2c.h +4 -0
  158. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  159. esphome/components/i2s_audio/__init__.py +131 -22
  160. esphome/components/i2s_audio/i2s_audio.h +44 -4
  161. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  162. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  163. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  164. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  165. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  166. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  167. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  168. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  169. esphome/components/image/__init__.py +37 -17
  170. esphome/components/image/image.cpp +25 -8
  171. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  172. esphome/components/key_collector/__init__.py +35 -0
  173. esphome/components/key_collector/key_collector.cpp +8 -0
  174. esphome/components/key_collector/key_collector.h +10 -0
  175. esphome/components/ld2410/ld2410.h +1 -1
  176. esphome/components/ld2450/ld2450.h +1 -1
  177. esphome/components/light/__init__.py +57 -0
  178. esphome/components/lock/__init__.py +51 -4
  179. esphome/components/lock/automation.h +2 -13
  180. esphome/components/logger/__init__.py +21 -0
  181. esphome/components/logger/logger.cpp +125 -95
  182. esphome/components/logger/logger.h +160 -35
  183. esphome/components/logger/task_log_buffer.cpp +138 -0
  184. esphome/components/logger/task_log_buffer.h +69 -0
  185. esphome/components/lvgl/__init__.py +13 -5
  186. esphome/components/lvgl/automation.py +50 -1
  187. esphome/components/lvgl/defines.py +0 -1
  188. esphome/components/lvgl/lv_validation.py +10 -1
  189. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  190. esphome/components/lvgl/schemas.py +14 -14
  191. esphome/components/lvgl/text/__init__.py +1 -2
  192. esphome/components/lvgl/widgets/arc.py +7 -6
  193. esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
  194. esphome/components/lvgl/widgets/checkbox.py +2 -2
  195. esphome/components/lvgl/widgets/dropdown.py +2 -1
  196. esphome/components/lvgl/widgets/img.py +15 -12
  197. esphome/components/mapping/__init__.py +134 -0
  198. esphome/components/max7219digit/max7219digit.cpp +27 -27
  199. esphome/components/mdns/__init__.py +11 -5
  200. esphome/components/mdns/mdns_component.cpp +11 -5
  201. esphome/components/mdns/mdns_component.h +3 -2
  202. esphome/components/mdns/mdns_esp32.cpp +4 -3
  203. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  204. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  205. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  206. esphome/components/media_player/__init__.py +40 -6
  207. esphome/components/micro_wake_word/__init__.py +99 -31
  208. esphome/components/micro_wake_word/automation.h +54 -0
  209. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  210. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  211. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  212. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  213. esphome/components/micro_wake_word/streaming_model.h +85 -13
  214. esphome/components/microphone/__init__.py +139 -9
  215. esphome/components/microphone/automation.h +14 -2
  216. esphome/components/microphone/microphone.cpp +21 -0
  217. esphome/components/microphone/microphone.h +14 -5
  218. esphome/components/microphone/microphone_source.cpp +95 -0
  219. esphome/components/microphone/microphone_source.h +80 -0
  220. esphome/components/mics_4514/sensor.py +25 -14
  221. esphome/components/midea/climate.py +3 -4
  222. esphome/components/midea_ir/climate.py +3 -5
  223. esphome/components/mipi_spi/__init__.py +15 -0
  224. esphome/components/mipi_spi/display.py +474 -0
  225. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  226. esphome/components/mipi_spi/mipi_spi.h +171 -0
  227. esphome/components/mipi_spi/models/__init__.py +65 -0
  228. esphome/components/mipi_spi/models/amoled.py +72 -0
  229. esphome/components/mipi_spi/models/commands.py +82 -0
  230. esphome/components/mipi_spi/models/cyd.py +10 -0
  231. esphome/components/mipi_spi/models/ili.py +749 -0
  232. esphome/components/mipi_spi/models/jc.py +260 -0
  233. esphome/components/mipi_spi/models/lanbon.py +15 -0
  234. esphome/components/mipi_spi/models/lilygo.py +60 -0
  235. esphome/components/mipi_spi/models/waveshare.py +139 -0
  236. esphome/components/mitsubishi/climate.py +2 -5
  237. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  238. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  239. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  240. esphome/components/mlx90393/sensor.py +5 -0
  241. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  242. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  243. esphome/components/mqtt/__init__.py +1 -1
  244. esphome/components/mqtt/mqtt_client.cpp +5 -1
  245. esphome/components/mqtt/mqtt_const.h +4 -0
  246. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  247. esphome/components/mqtt/mqtt_fan.h +2 -0
  248. esphome/components/network/__init__.py +1 -1
  249. esphome/components/nextion/base_component.py +17 -16
  250. esphome/components/nextion/display.py +11 -2
  251. esphome/components/nextion/nextion.cpp +39 -1
  252. esphome/components/nextion/nextion.h +50 -0
  253. esphome/components/noblex/climate.py +2 -9
  254. esphome/components/number/__init__.py +12 -9
  255. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  256. esphome/components/one_wire/one_wire_bus.h +14 -8
  257. esphome/components/online_image/bmp_image.cpp +48 -11
  258. esphome/components/online_image/bmp_image.h +2 -0
  259. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  260. esphome/components/opentherm/number/__init__.py +11 -20
  261. esphome/components/opentherm/sensor/__init__.py +3 -3
  262. esphome/components/opentherm/switch/__init__.py +3 -5
  263. esphome/components/output/lock/__init__.py +11 -9
  264. esphome/components/packages/__init__.py +33 -31
  265. esphome/components/packet_transport/__init__.py +201 -0
  266. esphome/components/packet_transport/binary_sensor.py +19 -0
  267. esphome/components/packet_transport/packet_transport.cpp +534 -0
  268. esphome/components/packet_transport/packet_transport.h +154 -0
  269. esphome/components/packet_transport/sensor.py +19 -0
  270. esphome/components/pca9685/pca9685_output.cpp +2 -1
  271. esphome/components/pid/climate.py +2 -4
  272. esphome/components/pm2005/__init__.py +1 -0
  273. esphome/components/pm2005/pm2005.cpp +123 -0
  274. esphome/components/pm2005/pm2005.h +46 -0
  275. esphome/components/pm2005/sensor.py +86 -0
  276. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  277. esphome/components/pmsa003i/pmsa003i.h +25 -25
  278. esphome/components/pmsx003/pmsx003.cpp +193 -229
  279. esphome/components/pmsx003/pmsx003.h +51 -33
  280. esphome/components/pmsx003/sensor.py +21 -11
  281. esphome/components/pn7150/pn7150.h +2 -2
  282. esphome/components/pn7160/pn7160.h +2 -2
  283. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  284. esphome/components/prometheus/prometheus_handler.h +17 -0
  285. esphome/components/psram/__init__.py +7 -5
  286. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  287. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  288. esphome/components/qspi_dbi/__init__.py +0 -1
  289. esphome/components/qspi_dbi/display.py +2 -1
  290. esphome/components/qspi_dbi/models.py +1 -2
  291. esphome/components/remote_base/__init__.py +91 -0
  292. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  293. esphome/components/remote_base/beo4_protocol.h +43 -0
  294. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  295. esphome/components/remote_base/gobox_protocol.h +54 -0
  296. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  297. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  298. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  299. esphome/components/scd30/sensor.py +2 -3
  300. esphome/components/scd4x/sensor.py +4 -5
  301. esphome/components/sdp3x/sensor.py +2 -1
  302. esphome/components/select/__init__.py +19 -20
  303. esphome/components/sen5x/sensor.py +1 -1
  304. esphome/components/sensor/__init__.py +158 -14
  305. esphome/components/sensor/filter.cpp +23 -0
  306. esphome/components/sensor/filter.h +22 -0
  307. esphome/components/sgp4x/sensor.py +1 -1
  308. esphome/components/sht4x/sht4x.cpp +43 -22
  309. esphome/components/sht4x/sht4x.h +1 -1
  310. esphome/components/sml/text_sensor/__init__.py +4 -6
  311. esphome/components/sound_level/__init__.py +0 -0
  312. esphome/components/sound_level/sensor.py +97 -0
  313. esphome/components/sound_level/sound_level.cpp +194 -0
  314. esphome/components/sound_level/sound_level.h +73 -0
  315. esphome/components/speaker/media_player/__init__.py +4 -8
  316. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  317. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  318. esphome/components/speaker/speaker.h +4 -7
  319. esphome/components/speed/fan/__init__.py +17 -16
  320. esphome/components/spi/spi.h +11 -1
  321. esphome/components/sprinkler/__init__.py +18 -19
  322. esphome/components/switch/__init__.py +32 -42
  323. esphome/components/syslog/__init__.py +41 -0
  324. esphome/components/syslog/esphome_syslog.cpp +49 -0
  325. esphome/components/syslog/esphome_syslog.h +27 -0
  326. esphome/components/tca9555/tca9555.cpp +11 -6
  327. esphome/components/tcl112/climate.py +2 -9
  328. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  329. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  330. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  331. esphome/components/template/cover/__init__.py +27 -21
  332. esphome/components/template/fan/__init__.py +14 -12
  333. esphome/components/template/lock/__init__.py +20 -25
  334. esphome/components/template/lock/automation.h +18 -0
  335. esphome/components/template/text/__init__.py +4 -3
  336. esphome/components/template/valve/__init__.py +32 -21
  337. esphome/components/template/valve/automation.h +24 -0
  338. esphome/components/text/__init__.py +32 -1
  339. esphome/components/text_sensor/__init__.py +24 -29
  340. esphome/components/thermostat/climate.py +5 -5
  341. esphome/components/time_based/cover.py +17 -16
  342. esphome/components/tm1638/switch/__init__.py +10 -7
  343. esphome/components/tormatic/cover.py +4 -5
  344. esphome/components/toshiba/climate.py +3 -5
  345. esphome/components/touchscreen/touchscreen.cpp +3 -1
  346. esphome/components/tt21100/touchscreen/tt21100.cpp +1 -1
  347. esphome/components/tuya/climate/__init__.py +5 -6
  348. esphome/components/tuya/cover/__init__.py +6 -11
  349. esphome/components/tuya/select/__init__.py +15 -5
  350. esphome/components/tuya/select/tuya_select.cpp +6 -1
  351. esphome/components/tuya/select/tuya_select.h +5 -1
  352. esphome/components/uart/packet_transport/__init__.py +20 -0
  353. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  354. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  355. esphome/components/udp/__init__.py +126 -128
  356. esphome/components/udp/automation.h +40 -0
  357. esphome/components/udp/binary_sensor.py +3 -25
  358. esphome/components/udp/packet_transport/__init__.py +29 -0
  359. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  360. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  361. esphome/components/udp/sensor.py +3 -25
  362. esphome/components/udp/udp_component.cpp +26 -470
  363. esphome/components/udp/udp_component.h +21 -128
  364. esphome/components/update/__init__.py +31 -1
  365. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  366. esphome/components/uptime/text_sensor/__init__.py +47 -7
  367. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  368. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  369. esphome/components/valve/__init__.py +34 -3
  370. esphome/components/valve/automation.h +1 -19
  371. esphome/components/vl53l0x/sensor.py +11 -0
  372. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  373. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  374. esphome/components/voice_assistant/__init__.py +36 -10
  375. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  376. esphome/components/voice_assistant/voice_assistant.h +26 -25
  377. esphome/components/waveshare_epaper/display.py +6 -0
  378. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  379. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  380. esphome/components/whirlpool/climate.py +3 -5
  381. esphome/components/whynter/climate.py +3 -5
  382. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  383. esphome/components/yashima/climate.py +6 -6
  384. esphome/components/zhlt01/climate.py +2 -7
  385. esphome/config_validation.py +38 -58
  386. esphome/const.py +15 -1
  387. esphome/core/__init__.py +2 -0
  388. esphome/core/application.cpp +1 -0
  389. esphome/core/application.h +4 -0
  390. esphome/core/automation.h +4 -3
  391. esphome/core/component.cpp +19 -3
  392. esphome/core/component.h +5 -0
  393. esphome/core/defines.h +23 -17
  394. esphome/core/macros.h +4 -0
  395. esphome/core/scheduler.cpp +3 -0
  396. esphome/cpp_generator.py +6 -2
  397. esphome/dashboard/web_server.py +3 -3
  398. esphome/helpers.py +39 -0
  399. esphome/loader.py +4 -0
  400. esphome/mqtt.py +21 -8
  401. esphome/platformio_api.py +1 -1
  402. esphome/schema_extractors.py +0 -1
  403. esphome/vscode.py +15 -0
  404. esphome/wizard.py +2 -2
  405. esphome/zeroconf.py +7 -3
  406. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/METADATA +10 -11
  407. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/RECORD +411 -352
  408. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/WHEEL +1 -1
  409. esphome/components/esp32_ble/const_esp32c6.h +0 -74
  410. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/entry_points.txt +0 -0
  411. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/licenses/LICENSE +0 -0
  412. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,41 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import udp
3
+ from esphome.components.logger import LOG_LEVELS, is_log_level
4
+ from esphome.components.time import RealTimeClock
5
+ from esphome.components.udp import CONF_UDP_ID
6
+ import esphome.config_validation as cv
7
+ from esphome.const import CONF_ID, CONF_LEVEL, CONF_PORT, CONF_TIME_ID
8
+ from esphome.cpp_types import Component, Parented
9
+
10
+ CODEOWNERS = ["@clydebarrow"]
11
+
12
+ DEPENDENCIES = ["udp", "logger", "time"]
13
+
14
+ syslog_ns = cg.esphome_ns.namespace("syslog")
15
+ Syslog = syslog_ns.class_("Syslog", Component, Parented.template(udp.UDPComponent))
16
+
17
+ CONF_STRIP = "strip"
18
+ CONF_FACILITY = "facility"
19
+ CONFIG_SCHEMA = udp.UDP_SCHEMA.extend(
20
+ {
21
+ cv.GenerateID(): cv.declare_id(Syslog),
22
+ cv.GenerateID(CONF_TIME_ID): cv.use_id(RealTimeClock),
23
+ cv.Optional(CONF_PORT, default=514): cv.port,
24
+ cv.Optional(CONF_LEVEL, default="DEBUG"): is_log_level,
25
+ cv.Optional(CONF_STRIP, default=True): cv.boolean,
26
+ cv.Optional(CONF_FACILITY, default=16): cv.int_range(0, 23),
27
+ }
28
+ )
29
+
30
+
31
+ async def to_code(config):
32
+ parent = await cg.get_variable(config[CONF_UDP_ID])
33
+ time = await cg.get_variable(config[CONF_TIME_ID])
34
+ cg.add(parent.set_broadcast_port(config[CONF_PORT]))
35
+ cg.add(parent.set_should_broadcast())
36
+ level = LOG_LEVELS[config[CONF_LEVEL]]
37
+ var = cg.new_Pvariable(config[CONF_ID], level, time)
38
+ await cg.register_component(var, config)
39
+ await cg.register_parented(var, parent)
40
+ cg.add(var.set_strip(config[CONF_STRIP]))
41
+ cg.add(var.set_facility(config[CONF_FACILITY]))
@@ -0,0 +1,49 @@
1
+ #include "esphome_syslog.h"
2
+
3
+ #include "esphome/components/logger/logger.h"
4
+ #include "esphome/core/application.h"
5
+ #include "esphome/core/time.h"
6
+
7
+ namespace esphome {
8
+ namespace syslog {
9
+
10
+ // Map log levels to syslog severity using an array, indexed by ESPHome log level (1-7)
11
+ constexpr int LOG_LEVEL_TO_SYSLOG_SEVERITY[] = {
12
+ 3, // NONE
13
+ 3, // ERROR
14
+ 4, // WARN
15
+ 5, // INFO
16
+ 6, // CONFIG
17
+ 7, // DEBUG
18
+ 7, // VERBOSE
19
+ 7 // VERY_VERBOSE
20
+ };
21
+
22
+ void Syslog::setup() {
23
+ logger::global_logger->add_on_log_callback(
24
+ [this](int level, const char *tag, const char *message) { this->log_(level, tag, message); });
25
+ }
26
+
27
+ void Syslog::log_(const int level, const char *tag, const char *message) const {
28
+ if (level > this->log_level_)
29
+ return;
30
+ // Syslog PRI calculation: facility * 8 + severity
31
+ int severity = 7;
32
+ if ((unsigned) level <= 7) {
33
+ severity = LOG_LEVEL_TO_SYSLOG_SEVERITY[level];
34
+ }
35
+ int pri = this->facility_ * 8 + severity;
36
+ auto timestamp = this->time_->now().strftime("%b %d %H:%M:%S");
37
+ unsigned len = strlen(message);
38
+ // remove color formatting
39
+ if (this->strip_ && message[0] == 0x1B && len > 11) {
40
+ message += 7;
41
+ len -= 11;
42
+ }
43
+
44
+ auto data = str_sprintf("<%d>%s %s %s: %.*s", pri, timestamp.c_str(), App.get_name().c_str(), tag, len, message);
45
+ this->parent_->send_packet((const uint8_t *) data.data(), data.size());
46
+ }
47
+
48
+ } // namespace syslog
49
+ } // namespace esphome
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+ #include "esphome/core/component.h"
3
+ #include "esphome/core/helpers.h"
4
+ #include "esphome/core/log.h"
5
+ #include "esphome/components/udp/udp_component.h"
6
+ #include "esphome/components/time/real_time_clock.h"
7
+
8
+ #ifdef USE_NETWORK
9
+ namespace esphome {
10
+ namespace syslog {
11
+ class Syslog : public Component, public Parented<udp::UDPComponent> {
12
+ public:
13
+ Syslog(int level, time::RealTimeClock *time) : log_level_(level), time_(time) {}
14
+ void setup() override;
15
+ void set_strip(bool strip) { this->strip_ = strip; }
16
+ void set_facility(int facility) { this->facility_ = facility; }
17
+
18
+ protected:
19
+ int log_level_;
20
+ void log_(int level, const char *tag, const char *message) const;
21
+ time::RealTimeClock *time_;
22
+ bool strip_{true};
23
+ int facility_{16};
24
+ };
25
+ } // namespace syslog
26
+ } // namespace esphome
27
+ #endif
@@ -76,15 +76,20 @@ bool TCA9555Component::read_gpio_modes_() {
76
76
  bool TCA9555Component::digital_read_hw(uint8_t pin) {
77
77
  if (this->is_failed())
78
78
  return false;
79
- bool success;
80
- uint8_t data[2];
81
- success = this->read_bytes(TCA9555_INPUT_PORT_REGISTER_0, data, 2);
82
- this->input_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
83
-
84
- if (!success) {
79
+ uint8_t data;
80
+ uint8_t bank_number = pin < 8 ? 0 : 1;
81
+ uint8_t register_to_read = bank_number ? TCA9555_INPUT_PORT_REGISTER_1 : TCA9555_INPUT_PORT_REGISTER_0;
82
+ if (!this->read_bytes(register_to_read, &data, 1)) {
85
83
  this->status_set_warning("Failed to read input register");
86
84
  return false;
87
85
  }
86
+ uint8_t second_half = this->input_mask_ >> 8;
87
+ uint8_t first_half = this->input_mask_;
88
+ if (bank_number) {
89
+ this->input_mask_ = (data << 8) | (uint16_t(first_half) << 0);
90
+ } else {
91
+ this->input_mask_ = (uint16_t(second_half) << 8) | (data << 0);
92
+ }
88
93
 
89
94
  this->status_clear_warning();
90
95
  return true;
@@ -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 = ["@glmnet"]
@@ -9,13 +7,8 @@ CODEOWNERS = ["@glmnet"]
9
7
  tcl112_ns = cg.esphome_ns.namespace("tcl112")
10
8
  Tcl112Climate = tcl112_ns.class_("Tcl112Climate", climate_ir.ClimateIR)
11
9
 
12
- CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
13
- {
14
- cv.GenerateID(): cv.declare_id(Tcl112Climate),
15
- }
16
- )
10
+ CONFIG_SCHEMA = climate_ir.climare_ir_with_receiver_schema(Tcl112Climate)
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)
@@ -1,7 +1,7 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import alarm_control_panel, binary_sensor
3
3
  import esphome.config_validation as cv
4
- from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_INPUT, CONF_RESTORE_MODE
4
+ from esphome.const import CONF_BINARY_SENSORS, CONF_INPUT, CONF_RESTORE_MODE
5
5
 
6
6
  from .. import template_ns
7
7
 
@@ -51,6 +51,7 @@ ALARM_SENSOR_TYPES = {
51
51
  "DELAYED": AlarmSensorType.ALARM_SENSOR_TYPE_DELAYED,
52
52
  "INSTANT": AlarmSensorType.ALARM_SENSOR_TYPE_INSTANT,
53
53
  "DELAYED_FOLLOWER": AlarmSensorType.ALARM_SENSOR_TYPE_DELAYED_FOLLOWER,
54
+ "INSTANT_ALWAYS": AlarmSensorType.ALARM_SENSOR_TYPE_INSTANT_ALWAYS,
54
55
  }
55
56
 
56
57
 
@@ -76,9 +77,9 @@ TEMPLATE_ALARM_CONTROL_PANEL_BINARY_SENSOR_SCHEMA = cv.maybe_simple_value(
76
77
  )
77
78
 
78
79
  TEMPLATE_ALARM_CONTROL_PANEL_SCHEMA = (
79
- alarm_control_panel.ALARM_CONTROL_PANEL_SCHEMA.extend(
80
+ alarm_control_panel.alarm_control_panel_schema(TemplateAlarmControlPanel)
81
+ .extend(
80
82
  {
81
- cv.GenerateID(): cv.declare_id(TemplateAlarmControlPanel),
82
83
  cv.Optional(CONF_CODES): cv.ensure_list(cv.string_strict),
83
84
  cv.Optional(CONF_REQUIRES_CODE_TO_ARM): cv.boolean,
84
85
  cv.Optional(CONF_ARMING_HOME_TIME): cv.positive_time_period_milliseconds,
@@ -99,7 +100,8 @@ TEMPLATE_ALARM_CONTROL_PANEL_SCHEMA = (
99
100
  RESTORE_MODES, upper=True
100
101
  ),
101
102
  }
102
- ).extend(cv.COMPONENT_SCHEMA)
103
+ )
104
+ .extend(cv.COMPONENT_SCHEMA)
103
105
  )
104
106
 
105
107
  CONFIG_SCHEMA = cv.All(
@@ -109,9 +111,8 @@ CONFIG_SCHEMA = cv.All(
109
111
 
110
112
 
111
113
  async def to_code(config):
112
- var = cg.new_Pvariable(config[CONF_ID])
114
+ var = await alarm_control_panel.new_alarm_control_panel(config)
113
115
  await cg.register_component(var, config)
114
- await alarm_control_panel.register_alarm_control_panel(var, config)
115
116
  if CONF_CODES in config:
116
117
  for acode in config[CONF_CODES]:
117
118
  cg.add(var.add_code(acode))
@@ -58,6 +58,9 @@ void TemplateAlarmControlPanel::dump_config() {
58
58
  case ALARM_SENSOR_TYPE_DELAYED_FOLLOWER:
59
59
  sensor_type = "delayed_follower";
60
60
  break;
61
+ case ALARM_SENSOR_TYPE_INSTANT_ALWAYS:
62
+ sensor_type = "instant_always";
63
+ break;
61
64
  case ALARM_SENSOR_TYPE_DELAYED:
62
65
  default:
63
66
  sensor_type = "delayed";
@@ -145,24 +148,25 @@ void TemplateAlarmControlPanel::loop() {
145
148
  continue;
146
149
  }
147
150
 
148
- // If sensor type is of type instant
149
- if (sensor_info.second.type == ALARM_SENSOR_TYPE_INSTANT) {
150
- instant_sensor_not_ready = true;
151
- break;
152
- }
153
- // If sensor type is of type interior follower
154
- if (sensor_info.second.type == ALARM_SENSOR_TYPE_DELAYED_FOLLOWER) {
155
- // Look to see if we are in the pending state
156
- if (this->current_state_ == ACP_STATE_PENDING) {
157
- delayed_sensor_not_ready = true;
158
- } else {
151
+ switch (sensor_info.second.type) {
152
+ case ALARM_SENSOR_TYPE_INSTANT:
159
153
  instant_sensor_not_ready = true;
160
- }
161
- }
162
- // If sensor type is of type delayed
163
- if (sensor_info.second.type == ALARM_SENSOR_TYPE_DELAYED) {
164
- delayed_sensor_not_ready = true;
165
- break;
154
+ break;
155
+ case ALARM_SENSOR_TYPE_INSTANT_ALWAYS:
156
+ instant_sensor_not_ready = true;
157
+ future_state = ACP_STATE_TRIGGERED;
158
+ break;
159
+ case ALARM_SENSOR_TYPE_DELAYED_FOLLOWER:
160
+ // Look to see if we are in the pending state
161
+ if (this->current_state_ == ACP_STATE_PENDING) {
162
+ delayed_sensor_not_ready = true;
163
+ } else {
164
+ instant_sensor_not_ready = true;
165
+ }
166
+ break;
167
+ case ALARM_SENSOR_TYPE_DELAYED:
168
+ default:
169
+ delayed_sensor_not_ready = true;
166
170
  }
167
171
  }
168
172
  }
@@ -27,7 +27,8 @@ enum BinarySensorFlags : uint16_t {
27
27
  enum AlarmSensorType : uint16_t {
28
28
  ALARM_SENSOR_TYPE_DELAYED = 0,
29
29
  ALARM_SENSOR_TYPE_INSTANT,
30
- ALARM_SENSOR_TYPE_DELAYED_FOLLOWER
30
+ ALARM_SENSOR_TYPE_DELAYED_FOLLOWER,
31
+ ALARM_SENSOR_TYPE_INSTANT_ALWAYS,
31
32
  };
32
33
 
33
34
  #endif
@@ -34,31 +34,37 @@ RESTORE_MODES = {
34
34
  CONF_HAS_POSITION = "has_position"
35
35
  CONF_TOGGLE_ACTION = "toggle_action"
36
36
 
37
- CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
38
- {
39
- cv.GenerateID(): cv.declare_id(TemplateCover),
40
- cv.Optional(CONF_LAMBDA): cv.returning_lambda,
41
- cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
42
- cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
43
- cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean,
44
- cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
45
- cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
46
- cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True),
47
- cv.Optional(CONF_TILT_ACTION): automation.validate_automation(single=True),
48
- cv.Optional(CONF_TILT_LAMBDA): cv.returning_lambda,
49
- cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(single=True),
50
- cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True),
51
- cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum(
52
- RESTORE_MODES, upper=True
53
- ),
54
- }
55
- ).extend(cv.COMPONENT_SCHEMA)
37
+ CONFIG_SCHEMA = (
38
+ cover.cover_schema(TemplateCover)
39
+ .extend(
40
+ {
41
+ cv.Optional(CONF_LAMBDA): cv.returning_lambda,
42
+ cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
43
+ cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
44
+ cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean,
45
+ cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
46
+ cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
47
+ cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True),
48
+ cv.Optional(CONF_TILT_ACTION): automation.validate_automation(single=True),
49
+ cv.Optional(CONF_TILT_LAMBDA): cv.returning_lambda,
50
+ cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(
51
+ single=True
52
+ ),
53
+ cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(
54
+ single=True
55
+ ),
56
+ cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum(
57
+ RESTORE_MODES, upper=True
58
+ ),
59
+ }
60
+ )
61
+ .extend(cv.COMPONENT_SCHEMA)
62
+ )
56
63
 
57
64
 
58
65
  async def to_code(config):
59
- var = cg.new_Pvariable(config[CONF_ID])
66
+ var = await cover.new_cover(config)
60
67
  await cg.register_component(var, config)
61
- await cover.register_cover(var, config)
62
68
  if CONF_LAMBDA in config:
63
69
  template_ = await cg.process_lambda(
64
70
  config[CONF_LAMBDA], [], return_type=cg.optional.template(float)
@@ -2,7 +2,7 @@ import esphome.codegen as cg
2
2
  from esphome.components import fan
3
3
  from esphome.components.fan import validate_preset_modes
4
4
  import esphome.config_validation as cv
5
- from esphome.const import CONF_OUTPUT_ID, CONF_PRESET_MODES, CONF_SPEED_COUNT
5
+ from esphome.const import CONF_PRESET_MODES, CONF_SPEED_COUNT
6
6
 
7
7
  from .. import template_ns
8
8
 
@@ -13,21 +13,23 @@ TemplateFan = template_ns.class_("TemplateFan", cg.Component, fan.Fan)
13
13
  CONF_HAS_DIRECTION = "has_direction"
14
14
  CONF_HAS_OSCILLATING = "has_oscillating"
15
15
 
16
- CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
17
- {
18
- cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TemplateFan),
19
- cv.Optional(CONF_HAS_DIRECTION, default=False): cv.boolean,
20
- cv.Optional(CONF_HAS_OSCILLATING, default=False): cv.boolean,
21
- cv.Optional(CONF_SPEED_COUNT): cv.int_range(min=1),
22
- cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
23
- }
24
- ).extend(cv.COMPONENT_SCHEMA)
16
+ CONFIG_SCHEMA = (
17
+ fan.fan_schema(TemplateFan)
18
+ .extend(
19
+ {
20
+ cv.Optional(CONF_HAS_DIRECTION, default=False): cv.boolean,
21
+ cv.Optional(CONF_HAS_OSCILLATING, default=False): cv.boolean,
22
+ cv.Optional(CONF_SPEED_COUNT): cv.int_range(min=1),
23
+ cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
24
+ }
25
+ )
26
+ .extend(cv.COMPONENT_SCHEMA)
27
+ )
25
28
 
26
29
 
27
30
  async def to_code(config):
28
- var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
31
+ var = await fan.new_fan(config)
29
32
  await cg.register_component(var, config)
30
- await fan.register_fan(var, config)
31
33
 
32
34
  cg.add(var.set_has_direction(config[CONF_HAS_DIRECTION]))
33
35
  cg.add(var.set_has_oscillating(config[CONF_HAS_OSCILLATING]))
@@ -17,17 +17,11 @@ from .. import template_ns
17
17
 
18
18
  TemplateLock = template_ns.class_("TemplateLock", lock.Lock, cg.Component)
19
19
 
20
- LockState = lock.lock_ns.enum("LockState")
21
-
22
- LOCK_STATES = {
23
- "LOCKED": LockState.LOCK_STATE_LOCKED,
24
- "UNLOCKED": LockState.LOCK_STATE_UNLOCKED,
25
- "JAMMED": LockState.LOCK_STATE_JAMMED,
26
- "LOCKING": LockState.LOCK_STATE_LOCKING,
27
- "UNLOCKING": LockState.LOCK_STATE_UNLOCKING,
28
- }
29
-
30
- validate_lock_state = cv.enum(LOCK_STATES, upper=True)
20
+ TemplateLockPublishAction = template_ns.class_(
21
+ "TemplateLockPublishAction",
22
+ automation.Action,
23
+ cg.Parented.template(TemplateLock),
24
+ )
31
25
 
32
26
 
33
27
  def validate(config):
@@ -42,9 +36,9 @@ def validate(config):
42
36
 
43
37
 
44
38
  CONFIG_SCHEMA = cv.All(
45
- lock.LOCK_SCHEMA.extend(
39
+ lock.lock_schema(TemplateLock)
40
+ .extend(
46
41
  {
47
- cv.GenerateID(): cv.declare_id(TemplateLock),
48
42
  cv.Optional(CONF_LAMBDA): cv.returning_lambda,
49
43
  cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
50
44
  cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
@@ -54,19 +48,19 @@ CONFIG_SCHEMA = cv.All(
54
48
  cv.Optional(CONF_LOCK_ACTION): automation.validate_automation(single=True),
55
49
  cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
56
50
  }
57
- ).extend(cv.COMPONENT_SCHEMA),
51
+ )
52
+ .extend(cv.COMPONENT_SCHEMA),
58
53
  validate,
59
54
  )
60
55
 
61
56
 
62
57
  async def to_code(config):
63
- var = cg.new_Pvariable(config[CONF_ID])
58
+ var = await lock.new_lock(config)
64
59
  await cg.register_component(var, config)
65
- await lock.register_lock(var, config)
66
60
 
67
61
  if CONF_LAMBDA in config:
68
62
  template_ = await cg.process_lambda(
69
- config[CONF_LAMBDA], [], return_type=cg.optional.template(LockState)
63
+ config[CONF_LAMBDA], [], return_type=cg.optional.template(lock.LockState)
70
64
  )
71
65
  cg.add(var.set_state_lambda(template_))
72
66
  if CONF_UNLOCK_ACTION in config:
@@ -88,17 +82,18 @@ async def to_code(config):
88
82
 
89
83
  @automation.register_action(
90
84
  "lock.template.publish",
91
- lock.LockPublishAction,
92
- cv.Schema(
85
+ TemplateLockPublishAction,
86
+ cv.maybe_simple_value(
93
87
  {
94
- cv.Required(CONF_ID): cv.use_id(lock.Lock),
95
- cv.Required(CONF_STATE): cv.templatable(validate_lock_state),
96
- }
88
+ cv.GenerateID(): cv.use_id(TemplateLock),
89
+ cv.Required(CONF_STATE): cv.templatable(lock.validate_lock_state),
90
+ },
91
+ key=CONF_STATE,
97
92
  ),
98
93
  )
99
94
  async def lock_template_publish_to_code(config, action_id, template_arg, args):
100
- paren = await cg.get_variable(config[CONF_ID])
101
- var = cg.new_Pvariable(action_id, template_arg, paren)
102
- template_ = await cg.templatable(config[CONF_STATE], args, LockState)
95
+ var = cg.new_Pvariable(action_id, template_arg)
96
+ await cg.register_parented(var, config[CONF_ID])
97
+ template_ = await cg.templatable(config[CONF_STATE], args, lock.LockState)
103
98
  cg.add(var.set_state(template_))
104
99
  return var
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "template_lock.h"
4
+
5
+ #include "esphome/core/automation.h"
6
+
7
+ namespace esphome {
8
+ namespace template_ {
9
+
10
+ template<typename... Ts> class TemplateLockPublishAction : public Action<Ts...>, public Parented<TemplateLock> {
11
+ public:
12
+ TEMPLATABLE_VALUE(lock::LockState, state)
13
+
14
+ void play(Ts... x) override { this->parent_->publish_state(this->state_.value(x...)); }
15
+ };
16
+
17
+ } // namespace template_
18
+ } // namespace esphome
@@ -46,9 +46,9 @@ def validate(config):
46
46
 
47
47
 
48
48
  CONFIG_SCHEMA = cv.All(
49
- text.TEXT_SCHEMA.extend(
49
+ text.text_schema(TemplateText)
50
+ .extend(
50
51
  {
51
- cv.GenerateID(): cv.declare_id(TemplateText),
52
52
  cv.Optional(CONF_MIN_LENGTH, default=0): cv.int_range(min=0, max=255),
53
53
  cv.Optional(CONF_MAX_LENGTH, default=255): cv.int_range(min=0, max=255),
54
54
  cv.Optional(CONF_PATTERN): cv.string,
@@ -58,7 +58,8 @@ CONFIG_SCHEMA = cv.All(
58
58
  cv.Optional(CONF_INITIAL_VALUE): cv.string_strict,
59
59
  cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean,
60
60
  }
61
- ).extend(cv.polling_component_schema("60s")),
61
+ )
62
+ .extend(cv.polling_component_schema("60s")),
62
63
  validate,
63
64
  )
64
65
 
@@ -21,6 +21,10 @@ from .. import template_ns
21
21
 
22
22
  TemplateValve = template_ns.class_("TemplateValve", valve.Valve, cg.Component)
23
23
 
24
+ TemplateValvePublishAction = template_ns.class_(
25
+ "TemplateValvePublishAction", automation.Action, cg.Parented.template(TemplateValve)
26
+ )
27
+
24
28
  TemplateValveRestoreMode = template_ns.enum("TemplateValveRestoreMode")
25
29
  RESTORE_MODES = {
26
30
  "NO_RESTORE": TemplateValveRestoreMode.VALVE_NO_RESTORE,
@@ -31,23 +35,30 @@ RESTORE_MODES = {
31
35
  CONF_HAS_POSITION = "has_position"
32
36
  CONF_TOGGLE_ACTION = "toggle_action"
33
37
 
34
- CONFIG_SCHEMA = valve.VALVE_SCHEMA.extend(
35
- {
36
- cv.GenerateID(): cv.declare_id(TemplateValve),
37
- cv.Optional(CONF_LAMBDA): cv.returning_lambda,
38
- cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
39
- cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
40
- cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean,
41
- cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
42
- cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
43
- cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True),
44
- cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(single=True),
45
- cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True),
46
- cv.Optional(CONF_RESTORE_MODE, default="NO_RESTORE"): cv.enum(
47
- RESTORE_MODES, upper=True
48
- ),
49
- }
50
- ).extend(cv.COMPONENT_SCHEMA)
38
+ CONFIG_SCHEMA = (
39
+ valve.valve_schema(TemplateValve)
40
+ .extend(
41
+ {
42
+ cv.Optional(CONF_LAMBDA): cv.returning_lambda,
43
+ cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
44
+ cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
45
+ cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean,
46
+ cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
47
+ cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
48
+ cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True),
49
+ cv.Optional(CONF_TOGGLE_ACTION): automation.validate_automation(
50
+ single=True
51
+ ),
52
+ cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(
53
+ single=True
54
+ ),
55
+ cv.Optional(CONF_RESTORE_MODE, default="NO_RESTORE"): cv.enum(
56
+ RESTORE_MODES, upper=True
57
+ ),
58
+ }
59
+ )
60
+ .extend(cv.COMPONENT_SCHEMA)
61
+ )
51
62
 
52
63
 
53
64
  async def to_code(config):
@@ -90,10 +101,10 @@ async def to_code(config):
90
101
 
91
102
  @automation.register_action(
92
103
  "valve.template.publish",
93
- valve.ValvePublishAction,
104
+ TemplateValvePublishAction,
94
105
  cv.Schema(
95
106
  {
96
- cv.Required(CONF_ID): cv.use_id(valve.Valve),
107
+ cv.GenerateID(): cv.use_id(TemplateValve),
97
108
  cv.Exclusive(CONF_STATE, "pos"): cv.templatable(valve.validate_valve_state),
98
109
  cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.percentage),
99
110
  cv.Optional(CONF_CURRENT_OPERATION): cv.templatable(
@@ -103,8 +114,8 @@ async def to_code(config):
103
114
  ),
104
115
  )
105
116
  async def valve_template_publish_to_code(config, action_id, template_arg, args):
106
- paren = await cg.get_variable(config[CONF_ID])
107
- var = cg.new_Pvariable(action_id, template_arg, paren)
117
+ var = cg.new_Pvariable(action_id, template_arg)
118
+ await cg.register_parented(var, config[CONF_ID])
108
119
  if state_config := config.get(CONF_STATE):
109
120
  template_ = await cg.templatable(state_config, args, float)
110
121
  cg.add(var.set_position(template_))
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include "template_valve.h"
4
+
5
+ #include "esphome/core/automation.h"
6
+
7
+ namespace esphome {
8
+ namespace template_ {
9
+
10
+ template<typename... Ts> class TemplateValvePublishAction : public Action<Ts...>, public Parented<TemplateValve> {
11
+ TEMPLATABLE_VALUE(float, position)
12
+ TEMPLATABLE_VALUE(valve::ValveOperation, current_operation)
13
+
14
+ void play(Ts... x) override {
15
+ if (this->position_.has_value())
16
+ this->parent_->position = this->position_.value(x...);
17
+ if (this->current_operation_.has_value())
18
+ this->parent_->current_operation = this->current_operation_.value(x...);
19
+ this->parent_->publish_state();
20
+ }
21
+ };
22
+
23
+ } // namespace template_
24
+ } // namespace esphome