esphome 2025.6.2__py3-none-any.whl → 2025.7.0b1__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 (601) hide show
  1. esphome/__main__.py +1 -3
  2. esphome/codegen.py +2 -0
  3. esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
  4. esphome/components/adc/__init__.py +25 -1
  5. esphome/components/adc/adc_sensor.h +11 -11
  6. esphome/components/adc/adc_sensor_common.cpp +1 -1
  7. esphome/components/adc/adc_sensor_esp32.cpp +16 -8
  8. esphome/components/ade7880/ade7880.h +0 -2
  9. esphome/components/ads1115/ads1115.h +0 -1
  10. esphome/components/ads1118/ads1118.h +0 -1
  11. esphome/components/ags10/ags10.h +0 -2
  12. esphome/components/aic3204/aic3204.h +0 -1
  13. esphome/components/alarm_control_panel/__init__.py +5 -2
  14. esphome/components/alpha3/alpha3.h +0 -1
  15. esphome/components/am43/cover/am43_cover.h +0 -1
  16. esphome/components/am43/sensor/am43_sensor.h +0 -1
  17. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
  18. esphome/components/anova/anova.cpp +5 -1
  19. esphome/components/anova/anova.h +0 -1
  20. esphome/components/apds9960/apds9960.cpp +1 -1
  21. esphome/components/api/__init__.py +42 -20
  22. esphome/components/api/api_connection.cpp +318 -391
  23. esphome/components/api/api_connection.h +206 -126
  24. esphome/components/api/api_frame_helper.cpp +89 -124
  25. esphome/components/api/api_frame_helper.h +57 -45
  26. esphome/components/api/api_pb2.cpp +414 -4350
  27. esphome/components/api/api_pb2.h +287 -198
  28. esphome/components/api/api_pb2_dump.cpp +4333 -0
  29. esphome/components/api/api_pb2_service.cpp +180 -425
  30. esphome/components/api/api_pb2_service.h +7 -6
  31. esphome/components/api/api_pb2_size.h +2 -4
  32. esphome/components/api/api_server.cpp +138 -167
  33. esphome/components/api/api_server.h +66 -12
  34. esphome/components/api/client.py +10 -4
  35. esphome/components/api/list_entities.cpp +36 -105
  36. esphome/components/api/list_entities.h +31 -23
  37. esphome/components/api/proto.h +26 -3
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/as5600/as5600.h +0 -1
  41. esphome/components/async_tcp/__init__.py +14 -5
  42. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  43. esphome/components/atm90e32/atm90e32.cpp +2 -1
  44. esphome/components/audio/audio_decoder.cpp +1 -1
  45. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  46. esphome/components/b_parasite/b_parasite.h +0 -1
  47. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  48. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  49. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  50. esphome/components/bh1750/bh1750.cpp +5 -5
  51. esphome/components/binary_sensor/__init__.py +82 -5
  52. esphome/components/binary_sensor/automation.h +19 -1
  53. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  54. esphome/components/binary_sensor/binary_sensor.h +11 -25
  55. esphome/components/binary_sensor/filter.cpp +29 -24
  56. esphome/components/binary_sensor/filter.h +20 -10
  57. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  58. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  59. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  60. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  61. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  62. esphome/components/ble_client/switch/ble_switch.h +0 -1
  63. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  64. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  65. esphome/components/ble_presence/ble_presence_device.h +0 -1
  66. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  67. esphome/components/ble_scanner/ble_scanner.h +0 -1
  68. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  69. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  70. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  71. esphome/components/bme680/sensor.py +1 -1
  72. esphome/components/bmp581/bmp581.h +0 -2
  73. esphome/components/button/__init__.py +5 -2
  74. esphome/components/camera/__init__.py +1 -0
  75. esphome/components/camera/camera.cpp +22 -0
  76. esphome/components/camera/camera.h +80 -0
  77. esphome/components/canbus/__init__.py +1 -0
  78. esphome/components/cap1188/cap1188.h +0 -1
  79. esphome/components/captive_portal/__init__.py +12 -2
  80. esphome/components/captive_portal/captive_portal.cpp +12 -2
  81. esphome/components/captive_portal/captive_portal.h +5 -2
  82. esphome/components/ccs811/ccs811.h +0 -2
  83. esphome/components/climate/__init__.py +5 -2
  84. esphome/components/cm1106/sensor.py +2 -2
  85. esphome/components/const/__init__.py +2 -0
  86. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  87. esphome/components/copy/button/copy_button.h +0 -1
  88. esphome/components/copy/cover/copy_cover.h +0 -1
  89. esphome/components/copy/fan/copy_fan.h +0 -1
  90. esphome/components/copy/lock/copy_lock.h +0 -1
  91. esphome/components/copy/number/copy_number.h +0 -1
  92. esphome/components/copy/select/copy_select.h +0 -1
  93. esphome/components/copy/sensor/copy_sensor.h +0 -1
  94. esphome/components/copy/switch/copy_switch.h +0 -1
  95. esphome/components/copy/text/copy_text.h +0 -1
  96. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  97. esphome/components/cover/__init__.py +5 -2
  98. esphome/components/cs5460a/cs5460a.h +0 -1
  99. esphome/components/datetime/__init__.py +4 -2
  100. esphome/components/debug/__init__.py +20 -0
  101. esphome/components/deep_sleep/__init__.py +43 -9
  102. esphome/components/demo/__init__.py +2 -2
  103. esphome/components/display/display.cpp +4 -3
  104. esphome/components/display/display.h +0 -2
  105. esphome/components/display/display_buffer.cpp +1 -1
  106. esphome/components/ds2484/__init__.py +1 -0
  107. esphome/components/ds2484/ds2484.cpp +209 -0
  108. esphome/components/ds2484/ds2484.h +43 -0
  109. esphome/components/ds2484/one_wire.py +37 -0
  110. esphome/components/duty_time/duty_time_sensor.h +0 -1
  111. esphome/components/ens160_base/ens160_base.h +0 -1
  112. esphome/components/es7210/es7210.h +0 -1
  113. esphome/components/es7243e/es7243e.h +0 -1
  114. esphome/components/es8156/es8156.h +0 -1
  115. esphome/components/es8311/es8311.h +0 -1
  116. esphome/components/es8388/es8388.h +0 -1
  117. esphome/components/esp32/__init__.py +102 -135
  118. esphome/components/esp32/core.cpp +0 -4
  119. esphome/components/esp32/gpio.h +1 -1
  120. esphome/components/esp32/helpers.cpp +69 -0
  121. esphome/components/esp32_ble/ble.cpp +5 -6
  122. esphome/components/esp32_ble/ble.h +29 -14
  123. esphome/components/esp32_ble/ble_event.h +6 -6
  124. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  125. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  126. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  127. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  128. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  129. esphome/components/esp32_camera/__init__.py +111 -97
  130. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  131. esphome/components/esp32_camera/esp32_camera.h +35 -30
  132. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  133. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  134. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  135. esphome/components/esp32_hall/sensor.py +2 -21
  136. esphome/components/esp32_hosted/__init__.py +101 -0
  137. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  138. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  139. esphome/components/esp32_rmt/__init__.py +0 -58
  140. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  141. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  142. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  143. esphome/components/esp32_touch/esp32_touch.h +174 -28
  144. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  145. esphome/components/esp32_touch/esp32_touch_v1.cpp +238 -0
  146. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  147. esphome/components/esp8266/__init__.py +1 -0
  148. esphome/components/esp8266/gpio.cpp +10 -10
  149. esphome/components/esp8266/helpers.cpp +31 -0
  150. esphome/components/esphome/ota/__init__.py +1 -0
  151. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  152. esphome/components/ethernet/__init__.py +42 -23
  153. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  154. esphome/components/ethernet/ethernet_component.cpp +69 -29
  155. esphome/components/ethernet/ethernet_component.h +18 -10
  156. esphome/components/event/__init__.py +5 -2
  157. esphome/components/ezo/ezo.h +0 -1
  158. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  159. esphome/components/fan/__init__.py +5 -2
  160. esphome/components/feedback/feedback_cover.h +0 -1
  161. esphome/components/font/__init__.py +92 -82
  162. esphome/components/font/font.cpp +9 -2
  163. esphome/components/font/font.h +20 -5
  164. esphome/components/fs3000/fs3000.h +0 -1
  165. esphome/components/gcja5/gcja5.h +0 -1
  166. esphome/components/gl_r01_i2c/__init__.py +0 -0
  167. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  168. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  169. esphome/components/gl_r01_i2c/sensor.py +36 -0
  170. esphome/components/gp8403/gp8403.h +0 -1
  171. esphome/components/gpio/binary_sensor/__init__.py +17 -0
  172. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  173. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  174. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  175. esphome/components/he60r/he60r.h +0 -1
  176. esphome/components/heatpumpir/climate.py +2 -1
  177. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  178. esphome/components/heatpumpir/heatpumpir.h +1 -0
  179. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  180. esphome/components/host/__init__.py +2 -1
  181. esphome/components/host/helpers.cpp +57 -0
  182. esphome/components/http_request/__init__.py +19 -1
  183. esphome/components/http_request/http_request.h +1 -1
  184. esphome/components/http_request/http_request_arduino.cpp +0 -1
  185. esphome/components/http_request/http_request_arduino.h +1 -0
  186. esphome/components/http_request/http_request_idf.cpp +0 -1
  187. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  188. esphome/components/http_request/update/http_request_update.cpp +28 -9
  189. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  190. esphome/components/hydreon_rgxx/sensor.py +1 -1
  191. esphome/components/i2c/__init__.py +23 -11
  192. esphome/components/i2c/i2c_bus.h +8 -1
  193. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  194. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  195. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  196. esphome/components/i2c_device/i2c_device.h +0 -1
  197. esphome/components/i2s_audio/__init__.py +2 -10
  198. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  199. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  200. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  201. esphome/components/iaqcore/iaqcore.h +0 -2
  202. esphome/components/image/__init__.py +123 -24
  203. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  204. esphome/components/ina219/ina219.cpp +7 -0
  205. esphome/components/ina219/ina219.h +1 -0
  206. esphome/components/ina260/ina260.h +0 -2
  207. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  208. esphome/components/inkplate6/display.py +15 -0
  209. esphome/components/inkplate6/inkplate.cpp +2 -2
  210. esphome/components/integration/integration_sensor.h +0 -1
  211. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  212. esphome/components/internal_temperature/sensor.py +0 -26
  213. esphome/components/interval/interval.h +0 -2
  214. esphome/components/ld2410/button/__init__.py +3 -3
  215. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  216. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  217. esphome/components/ld2410/ld2410.cpp +430 -261
  218. esphome/components/ld2410/ld2410.h +44 -146
  219. esphome/components/ld2410/number/__init__.py +2 -2
  220. esphome/components/ld2410/sensor.py +1 -1
  221. esphome/components/ld2410/switch/__init__.py +1 -1
  222. esphome/components/ld2420/ld2420.cpp +196 -100
  223. esphome/components/ld2420/ld2420.h +46 -118
  224. esphome/components/ld2420/number/__init__.py +2 -2
  225. esphome/components/ld2420/sensor/__init__.py +6 -2
  226. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  227. esphome/components/ld2450/button/__init__.py +3 -3
  228. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  229. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  230. esphome/components/ld2450/ld2450.cpp +384 -232
  231. esphome/components/ld2450/ld2450.h +60 -69
  232. esphome/components/ld2450/switch/__init__.py +1 -1
  233. esphome/components/ledc/ledc_output.cpp +1 -63
  234. esphome/components/libretiny/__init__.py +4 -3
  235. esphome/components/libretiny/const.py +5 -0
  236. esphome/components/libretiny/generate_components.py +1 -0
  237. esphome/components/libretiny/helpers.cpp +35 -0
  238. esphome/components/libretiny/lt_component.cpp +5 -3
  239. esphome/components/light/__init__.py +4 -2
  240. esphome/components/light/addressable_light.h +3 -3
  241. esphome/components/light/light_call.cpp +180 -243
  242. esphome/components/light/light_call.h +72 -20
  243. esphome/components/light/light_color_values.h +14 -14
  244. esphome/components/light/light_state.h +15 -13
  245. esphome/components/light/transformers.h +2 -2
  246. esphome/components/ln882x/__init__.py +52 -0
  247. esphome/components/ln882x/boards.py +285 -0
  248. esphome/components/lock/__init__.py +5 -2
  249. esphome/components/logger/__init__.py +40 -3
  250. esphome/components/logger/logger.cpp +47 -12
  251. esphome/components/logger/logger.h +80 -49
  252. esphome/components/logger/logger_esp32.cpp +3 -3
  253. esphome/components/lps22/__init__.py +0 -0
  254. esphome/components/lps22/lps22.cpp +75 -0
  255. esphome/components/lps22/lps22.h +27 -0
  256. esphome/components/lps22/sensor.py +58 -0
  257. esphome/components/ltr390/ltr390.h +0 -1
  258. esphome/components/ltr501/ltr501.h +0 -1
  259. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  260. esphome/components/lvgl/__init__.py +1 -1
  261. esphome/components/lvgl/schemas.py +66 -6
  262. esphome/components/lvgl/styles.py +24 -16
  263. esphome/components/lvgl/widgets/__init__.py +12 -2
  264. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  265. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  266. esphome/components/max9611/max9611.h +0 -1
  267. esphome/components/mcp23016/__init__.py +1 -1
  268. esphome/components/mcp23xxx_base/__init__.py +1 -1
  269. esphome/components/mcp4461/__init__.py +1 -1
  270. esphome/components/mcp4461/output/__init__.py +3 -2
  271. esphome/components/mcp9600/mcp9600.h +0 -2
  272. esphome/components/md5/md5.cpp +3 -3
  273. esphome/components/md5/md5.h +1 -6
  274. esphome/components/mdns/__init__.py +22 -11
  275. esphome/components/media_player/__init__.py +4 -3
  276. esphome/components/micro_wake_word/__init__.py +1 -5
  277. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  278. esphome/components/microphone/microphone.cpp +7 -9
  279. esphome/components/microphone/microphone.h +0 -2
  280. esphome/components/mipi_spi/display.py +1 -0
  281. esphome/components/mmc5603/mmc5603.cpp +1 -1
  282. esphome/components/modbus/modbus.cpp +33 -15
  283. esphome/components/modbus/modbus.h +9 -0
  284. esphome/components/modbus_controller/__init__.py +42 -10
  285. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  286. esphome/components/modbus_controller/modbus_controller.h +61 -7
  287. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  288. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  289. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  290. esphome/components/mqtt/__init__.py +16 -0
  291. esphome/components/mqtt/mqtt_backend.h +2 -1
  292. esphome/components/mqtt/mqtt_backend_esp32.cpp +126 -45
  293. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  294. esphome/components/mqtt/mqtt_client.cpp +15 -9
  295. esphome/components/mqtt/mqtt_client.h +8 -3
  296. esphome/components/ms8607/ms8607.h +0 -1
  297. esphome/components/neopixelbus/light.py +4 -1
  298. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  299. esphome/components/network/__init__.py +4 -1
  300. esphome/components/network/ip_address.h +1 -0
  301. esphome/components/nextion/__init__.py +16 -0
  302. esphome/components/nextion/base_component.py +1 -0
  303. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  304. esphome/components/nextion/display.py +14 -4
  305. esphome/components/nextion/nextion.cpp +166 -101
  306. esphome/components/nextion/nextion.h +84 -53
  307. esphome/components/nextion/nextion_commands.cpp +11 -10
  308. esphome/components/nextion/nextion_component.cpp +28 -28
  309. esphome/components/nextion/nextion_component.h +53 -18
  310. esphome/components/nextion/nextion_component_base.h +3 -0
  311. esphome/components/nextion/nextion_upload.cpp +36 -0
  312. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  313. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  314. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  315. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  316. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  317. esphome/components/nfc/nfc.cpp +3 -22
  318. esphome/components/nfc/nfc.h +3 -3
  319. esphome/components/number/__init__.py +5 -2
  320. esphome/components/online_image/__init__.py +5 -0
  321. esphome/components/online_image/online_image.cpp +6 -2
  322. esphome/components/online_image/online_image.h +4 -1
  323. esphome/components/opentherm/opentherm.cpp +7 -12
  324. esphome/components/openthread/__init__.py +47 -40
  325. esphome/components/openthread/const.py +1 -0
  326. esphome/components/openthread/openthread_esp.cpp +27 -5
  327. esphome/components/opt3001/__init__.py +0 -0
  328. esphome/components/opt3001/opt3001.cpp +122 -0
  329. esphome/components/opt3001/opt3001.h +27 -0
  330. esphome/components/opt3001/sensor.py +35 -0
  331. esphome/components/ota/__init__.py +17 -0
  332. esphome/components/ota/ota_backend.h +27 -1
  333. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  334. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  335. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  336. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  337. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  338. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  339. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  340. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  341. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  342. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  343. esphome/components/packages/__init__.py +5 -2
  344. esphome/components/packet_transport/binary_sensor.py +61 -4
  345. esphome/components/packet_transport/packet_transport.cpp +31 -1
  346. esphome/components/packet_transport/packet_transport.h +11 -5
  347. esphome/components/pcf8574/__init__.py +1 -1
  348. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  349. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  350. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  351. esphome/components/pmsa003i/pmsa003i.h +0 -1
  352. esphome/components/pmsx003/pmsx003.h +0 -1
  353. esphome/components/pn7150/pn7150.cpp +7 -7
  354. esphome/components/pn7150/pn7150.h +0 -1
  355. esphome/components/pn7160/pn7160.cpp +7 -7
  356. esphome/components/pn7160/pn7160.h +0 -1
  357. esphome/components/preferences/syncer.h +2 -0
  358. esphome/components/prometheus/prometheus_handler.h +1 -1
  359. esphome/components/psram/psram.cpp +0 -20
  360. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  361. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  362. esphome/components/pulse_width/pulse_width.h +0 -1
  363. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  364. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  365. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  366. esphome/components/qr_code/__init__.py +13 -10
  367. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  368. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  369. esphome/components/rc522/rc522.h +0 -1
  370. esphome/components/rdm6300/rdm6300.h +0 -2
  371. esphome/components/remote_base/__init__.py +7 -5
  372. esphome/components/remote_base/remote_base.cpp +24 -21
  373. esphome/components/remote_base/remote_base.h +3 -26
  374. esphome/components/remote_receiver/__init__.py +40 -46
  375. esphome/components/remote_receiver/remote_receiver.h +4 -18
  376. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  377. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  378. esphome/components/remote_transmitter/__init__.py +42 -43
  379. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  380. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  381. esphome/components/resistance/resistance_sensor.h +0 -1
  382. esphome/components/rp2040/__init__.py +1 -0
  383. esphome/components/rp2040/helpers.cpp +55 -0
  384. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  385. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  386. esphome/components/rtttl/__init__.py +4 -4
  387. esphome/components/rtttl/rtttl.cpp +10 -1
  388. esphome/components/ruuvitag/ruuvitag.h +0 -1
  389. esphome/components/safe_mode/safe_mode.cpp +2 -0
  390. esphome/components/safe_mode/safe_mode.h +4 -1
  391. esphome/components/scd30/scd30.h +0 -1
  392. esphome/components/scd30/sensor.py +2 -2
  393. esphome/components/scd4x/scd4x.cpp +61 -54
  394. esphome/components/scd4x/scd4x.h +17 -15
  395. esphome/components/scd4x/sensor.py +4 -4
  396. esphome/components/script/script.h +0 -2
  397. esphome/components/sdp3x/sensor.py +1 -1
  398. esphome/components/select/__init__.py +5 -2
  399. esphome/components/sen5x/sen5x.h +0 -1
  400. esphome/components/senseair/senseair.h +0 -1
  401. esphome/components/sensor/__init__.py +4 -2
  402. esphome/components/sensor/filter.cpp +1 -1
  403. esphome/components/sensor/sensor.cpp +12 -6
  404. esphome/components/sensor/sensor.h +13 -5
  405. esphome/components/servo/servo.h +0 -1
  406. esphome/components/sfa30/sfa30.h +0 -1
  407. esphome/components/sgp30/sgp30.h +0 -1
  408. esphome/components/sgp4x/sgp4x.h +0 -1
  409. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  410. esphome/components/sht4x/sht4x.h +0 -1
  411. esphome/components/sm300d2/sm300d2.h +0 -2
  412. esphome/components/smt100/sensor.py +8 -4
  413. esphome/components/smt100/smt100.cpp +5 -5
  414. esphome/components/smt100/smt100.h +3 -3
  415. esphome/components/sn74hc595/__init__.py +1 -1
  416. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  417. esphome/components/sntp/sntp_component.cpp +9 -3
  418. esphome/components/sntp/time.py +2 -0
  419. esphome/components/socket/__init__.py +17 -0
  420. esphome/components/spi/__init__.py +27 -6
  421. esphome/components/spi/spi.cpp +3 -2
  422. esphome/components/spi/spi.h +9 -3
  423. esphome/components/spi/spi_arduino.cpp +3 -5
  424. esphome/components/spi/spi_esp_idf.cpp +40 -21
  425. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  426. esphome/components/sps30/sps30.h +0 -1
  427. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  428. esphome/components/st7701s/st7701s.cpp +0 -4
  429. esphome/components/status/status_binary_sensor.h +0 -2
  430. esphome/components/substitutions/__init__.py +76 -19
  431. esphome/components/substitutions/jinja.py +99 -0
  432. esphome/components/sun/sun.cpp +3 -4
  433. esphome/components/switch/__init__.py +5 -2
  434. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  435. esphome/components/sx126x/__init__.py +317 -0
  436. esphome/components/sx126x/automation.h +62 -0
  437. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  438. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  439. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  440. esphome/components/sx126x/sx126x.cpp +523 -0
  441. esphome/components/sx126x/sx126x.h +140 -0
  442. esphome/components/sx126x/sx126x_reg.h +163 -0
  443. esphome/components/sx127x/__init__.py +325 -0
  444. esphome/components/sx127x/automation.h +62 -0
  445. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  446. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  447. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  448. esphome/components/sx127x/sx127x.cpp +498 -0
  449. esphome/components/sx127x/sx127x.h +128 -0
  450. esphome/components/sx127x/sx127x_reg.h +295 -0
  451. esphome/components/syslog/esphome_syslog.cpp +5 -3
  452. esphome/components/syslog/esphome_syslog.h +1 -1
  453. esphome/components/tca9555/__init__.py +1 -1
  454. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  455. esphome/components/text/__init__.py +5 -2
  456. esphome/components/text_sensor/__init__.py +5 -2
  457. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  458. esphome/components/thermostat/thermostat_climate.h +43 -39
  459. esphome/components/time/__init__.py +16 -2
  460. esphome/components/time/real_time_clock.cpp +4 -0
  461. esphome/components/time/real_time_clock.h +5 -1
  462. esphome/components/tlc5971/tlc5971.cpp +4 -1
  463. esphome/components/tmp1075/tmp1075.h +0 -2
  464. esphome/components/tof10120/tof10120_sensor.h +0 -1
  465. esphome/components/tormatic/tormatic_cover.h +0 -1
  466. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  467. esphome/components/tsl2591/tsl2591.cpp +1 -1
  468. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  469. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  470. esphome/components/tx20/tx20.cpp +2 -2
  471. esphome/components/uart/__init__.py +18 -0
  472. esphome/components/uart/uart_component_esp_idf.cpp +1 -5
  473. esphome/components/update/__init__.py +5 -2
  474. esphome/components/update/update_entity.h +8 -0
  475. esphome/components/usb_host/__init__.py +5 -2
  476. esphome/components/valve/__init__.py +5 -2
  477. esphome/components/vbus/vbus.h +0 -1
  478. esphome/components/veml3235/veml3235.h +0 -1
  479. esphome/components/veml7700/veml7700.h +0 -1
  480. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  481. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  482. esphome/components/watchdog/watchdog.cpp +0 -4
  483. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  484. esphome/components/web_server/__init__.py +34 -19
  485. esphome/components/web_server/ota/__init__.py +32 -0
  486. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  487. esphome/components/web_server/ota/ota_web_server.h +26 -0
  488. esphome/components/web_server/web_server.cpp +311 -430
  489. esphome/components/web_server/web_server.h +33 -23
  490. esphome/components/web_server/web_server_v1.cpp +4 -5
  491. esphome/components/web_server_base/__init__.py +5 -2
  492. esphome/components/web_server_base/web_server_base.cpp +2 -94
  493. esphome/components/web_server_base/web_server_base.h +5 -25
  494. esphome/components/web_server_idf/multipart.cpp +254 -0
  495. esphome/components/web_server_idf/multipart.h +86 -0
  496. esphome/components/web_server_idf/utils.cpp +32 -0
  497. esphome/components/web_server_idf/utils.h +10 -0
  498. esphome/components/web_server_idf/web_server_idf.cpp +162 -16
  499. esphome/components/web_server_idf/web_server_idf.h +11 -10
  500. esphome/components/wiegand/wiegand.cpp +2 -2
  501. esphome/components/wifi/__init__.py +18 -0
  502. esphome/components/wifi/wifi_component.cpp +17 -22
  503. esphome/components/wifi/wifi_component.h +27 -23
  504. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  505. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  506. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  507. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  508. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  509. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  510. esphome/components/wireguard/__init__.py +2 -11
  511. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  512. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  513. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  514. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  515. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  516. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  517. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  518. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  519. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  520. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  521. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  522. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  523. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  524. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  525. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  526. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  527. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  528. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  529. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  530. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  531. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  532. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  533. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  534. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  535. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  536. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  537. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  538. esphome/components/zyaura/zyaura.h +0 -1
  539. esphome/config.py +88 -22
  540. esphome/config_helpers.py +74 -1
  541. esphome/config_validation.py +12 -1
  542. esphome/const.py +65 -10
  543. esphome/core/__init__.py +18 -2
  544. esphome/core/application.cpp +163 -10
  545. esphome/core/application.h +145 -165
  546. esphome/core/area.h +19 -0
  547. esphome/core/automation.h +58 -9
  548. esphome/core/color.cpp +3 -5
  549. esphome/core/color.h +16 -16
  550. esphome/core/component.cpp +151 -18
  551. esphome/core/component.h +98 -4
  552. esphome/core/component_iterator.cpp +7 -7
  553. esphome/core/component_iterator.h +9 -7
  554. esphome/core/config.py +155 -6
  555. esphome/core/controller.cpp +4 -2
  556. esphome/core/controller.h +1 -1
  557. esphome/core/datatypes.h +2 -2
  558. esphome/core/defines.h +17 -2
  559. esphome/core/device.h +20 -0
  560. esphome/core/entity_base.cpp +20 -15
  561. esphome/core/entity_base.h +76 -0
  562. esphome/core/entity_helpers.py +162 -1
  563. esphome/core/event_pool.h +81 -0
  564. esphome/core/helpers.cpp +75 -230
  565. esphome/core/helpers.h +164 -104
  566. esphome/core/lock_free_queue.h +151 -0
  567. esphome/core/log.cpp +2 -2
  568. esphome/core/log.h +2 -0
  569. esphome/core/optional.h +5 -0
  570. esphome/core/ring_buffer.cpp +2 -2
  571. esphome/core/scheduler.cpp +278 -103
  572. esphome/core/scheduler.h +157 -17
  573. esphome/core/time.cpp +5 -5
  574. esphome/core/time.h +5 -5
  575. esphome/cpp_generator.py +17 -0
  576. esphome/cpp_helpers.py +0 -22
  577. esphome/cpp_types.py +3 -1
  578. esphome/dashboard/entries.py +1 -1
  579. esphome/dashboard/util/text.py +5 -21
  580. esphome/dashboard/web_server.py +9 -1
  581. esphome/helpers.py +47 -0
  582. esphome/loader.py +15 -1
  583. esphome/pins.py +14 -8
  584. esphome/wizard.py +16 -3
  585. esphome/writer.py +21 -3
  586. esphome/yaml_util.py +0 -2
  587. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/METADATA +10 -9
  588. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/RECORD +593 -533
  589. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  590. esphome/components/esp32_ble/queue.h +0 -85
  591. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  592. esphome/components/esp32_hall/esp32_hall.h +0 -23
  593. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  594. esphome/components/ld2410/button/reset_button.cpp +0 -9
  595. esphome/components/ld2450/button/reset_button.cpp +0 -9
  596. esphome/components/openthread/tlv.py +0 -65
  597. /esphome/{dashboard/enum.py → enum.py} +0 -0
  598. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/WHEEL +0 -0
  599. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/entry_points.txt +0 -0
  600. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/licenses/LICENSE +0 -0
  601. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/top_level.txt +0 -0
@@ -86,7 +86,7 @@ bool AudioTransferBuffer::reallocate(size_t new_buffer_size) {
86
86
  bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
87
87
  this->buffer_size_ = buffer_size;
88
88
 
89
- RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
89
+ RAMAllocator<uint8_t> allocator;
90
90
 
91
91
  this->buffer_ = allocator.allocate(this->buffer_size_);
92
92
  if (this->buffer_ == nullptr) {
@@ -101,7 +101,7 @@ bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
101
101
 
102
102
  void AudioTransferBuffer::deallocate_buffer_() {
103
103
  if (this->buffer_ != nullptr) {
104
- RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
104
+ RAMAllocator<uint8_t> allocator;
105
105
  allocator.deallocate(this->buffer_, this->buffer_size_);
106
106
  this->buffer_ = nullptr;
107
107
  this->data_start_ = nullptr;
@@ -16,7 +16,6 @@ class BParasite : public Component, public esp32_ble_tracker::ESPBTDeviceListene
16
16
 
17
17
  bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
18
18
  void dump_config() override;
19
- float get_setup_priority() const override { return setup_priority::DATA; }
20
19
 
21
20
  void set_battery_voltage(sensor::Sensor *battery_voltage) { battery_voltage_ = battery_voltage; }
22
21
  void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -480,7 +480,11 @@ void BedJetHub::set_clock(uint8_t hour, uint8_t minute) {
480
480
 
481
481
  /* Internal */
482
482
 
483
- void BedJetHub::loop() {}
483
+ void BedJetHub::loop() {
484
+ // Parent BLEClientNode has a loop() method, but this component uses
485
+ // polling via update() and BLE callbacks so loop isn't needed
486
+ this->disable_loop();
487
+ }
484
488
  void BedJetHub::update() { this->dispatch_status_(); }
485
489
 
486
490
  void BedJetHub::dump_config() {
@@ -83,7 +83,11 @@ void BedJetClimate::reset_state_() {
83
83
  this->publish_state();
84
84
  }
85
85
 
86
- void BedJetClimate::loop() {}
86
+ void BedJetClimate::loop() {
87
+ // This component is controlled via the parent BedJetHub
88
+ // Empty loop not needed, disable to save CPU cycles
89
+ this->disable_loop();
90
+ }
87
91
 
88
92
  void BedJetClimate::control(const ClimateCall &call) {
89
93
  ESP_LOGD(TAG, "Received BedJetClimate::control");
@@ -7,11 +7,13 @@
7
7
 
8
8
  extern "C" {
9
9
  #include "rtos_pub.h"
10
- #include "spi.h"
10
+ // rtos_pub.h must be included before the rest of the includes
11
+
11
12
  #include "arm_arch.h"
12
13
  #include "general_dma_pub.h"
13
14
  #include "gpio_pub.h"
14
15
  #include "icu_pub.h"
16
+ #include "spi.h"
15
17
  #undef SPI_DAT
16
18
  #undef SPI_BASE
17
19
  };
@@ -124,7 +126,7 @@ void BekenSPILEDStripLightOutput::setup() {
124
126
  size_t buffer_size = this->get_buffer_size_();
125
127
  size_t dma_buffer_size = (buffer_size * 8) + (2 * 64);
126
128
 
127
- ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
129
+ RAMAllocator<uint8_t> allocator;
128
130
  this->buf_ = allocator.allocate(buffer_size);
129
131
  if (this->buf_ == nullptr) {
130
132
  ESP_LOGE(TAG, "Cannot allocate LED buffer!");
@@ -50,7 +50,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
50
50
  // turn on (after one-shot sensor automatically powers down)
51
51
  uint8_t turn_on = BH1750_COMMAND_POWER_ON;
52
52
  if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
53
- ESP_LOGW(TAG, "Turning on BH1750 failed");
53
+ ESP_LOGW(TAG, "Power on failed");
54
54
  f(NAN);
55
55
  return;
56
56
  }
@@ -60,7 +60,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
60
60
  uint8_t mtreg_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> 5) & 0b111);
61
61
  uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> 0) & 0b11111);
62
62
  if (this->write(&mtreg_hi, 1) != i2c::ERROR_OK || this->write(&mtreg_lo, 1) != i2c::ERROR_OK) {
63
- ESP_LOGW(TAG, "Setting measurement time for BH1750 failed");
63
+ ESP_LOGW(TAG, "Set measurement time failed");
64
64
  active_mtreg_ = 0;
65
65
  f(NAN);
66
66
  return;
@@ -88,7 +88,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
88
88
  return;
89
89
  }
90
90
  if (this->write(&cmd, 1) != i2c::ERROR_OK) {
91
- ESP_LOGW(TAG, "Starting measurement for BH1750 failed");
91
+ ESP_LOGW(TAG, "Start measurement failed");
92
92
  f(NAN);
93
93
  return;
94
94
  }
@@ -99,7 +99,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
99
99
  this->set_timeout("read", meas_time, [this, mode, mtreg, f]() {
100
100
  uint16_t raw_value;
101
101
  if (this->read(reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
102
- ESP_LOGW(TAG, "Reading BH1750 data failed");
102
+ ESP_LOGW(TAG, "Read data failed");
103
103
  f(NAN);
104
104
  return;
105
105
  }
@@ -156,7 +156,7 @@ void BH1750Sensor::update() {
156
156
  this->publish_state(NAN);
157
157
  return;
158
158
  }
159
- ESP_LOGD(TAG, "'%s': Got illuminance=%.1flx", this->get_name().c_str(), val);
159
+ ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), val);
160
160
  this->status_clear_warning();
161
161
  this->publish_state(val);
162
162
  });
@@ -1,7 +1,10 @@
1
+ from logging import getLogger
2
+
1
3
  from esphome import automation, core
2
4
  from esphome.automation import Condition, maybe_simple_id
3
5
  import esphome.codegen as cg
4
6
  from esphome.components import mqtt, web_server
7
+ from esphome.components.const import CONF_ON_STATE_CHANGE
5
8
  import esphome.config_validation as cv
6
9
  from esphome.const import (
7
10
  CONF_DELAY,
@@ -57,8 +60,8 @@ from esphome.const import (
57
60
  DEVICE_CLASS_WINDOW,
58
61
  )
59
62
  from esphome.core import CORE, coroutine_with_priority
63
+ from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
60
64
  from esphome.cpp_generator import MockObjClass
61
- from esphome.cpp_helpers import setup_entity
62
65
  from esphome.util import Registry
63
66
 
64
67
  CODEOWNERS = ["@esphome/core"]
@@ -98,6 +101,7 @@ IS_PLATFORM_COMPONENT = True
98
101
 
99
102
  CONF_TIME_OFF = "time_off"
100
103
  CONF_TIME_ON = "time_on"
104
+ CONF_TRIGGER_ON_INITIAL_STATE = "trigger_on_initial_state"
101
105
 
102
106
  DEFAULT_DELAY = "1s"
103
107
  DEFAULT_TIME_OFF = "100ms"
@@ -127,15 +131,24 @@ MultiClickTriggerEvent = binary_sensor_ns.struct("MultiClickTriggerEvent")
127
131
  StateTrigger = binary_sensor_ns.class_(
128
132
  "StateTrigger", automation.Trigger.template(bool)
129
133
  )
134
+ StateChangeTrigger = binary_sensor_ns.class_(
135
+ "StateChangeTrigger",
136
+ automation.Trigger.template(cg.optional.template(bool), cg.optional.template(bool)),
137
+ )
138
+
130
139
  BinarySensorPublishAction = binary_sensor_ns.class_(
131
140
  "BinarySensorPublishAction", automation.Action
132
141
  )
142
+ BinarySensorInvalidateAction = binary_sensor_ns.class_(
143
+ "BinarySensorInvalidateAction", automation.Action
144
+ )
133
145
 
134
146
  # Condition
135
147
  BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Condition)
136
148
 
137
149
  # Filters
138
150
  Filter = binary_sensor_ns.class_("Filter")
151
+ TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
139
152
  DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
140
153
  DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
141
154
  DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Component)
@@ -144,6 +157,8 @@ AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Compon
144
157
  LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
145
158
  SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter, cg.Component)
146
159
 
160
+ _LOGGER = getLogger(__name__)
161
+
147
162
  FILTER_REGISTRY = Registry()
148
163
  validate_filters = cv.validate_registry("filter", FILTER_REGISTRY)
149
164
 
@@ -157,6 +172,19 @@ async def invert_filter_to_code(config, filter_id):
157
172
  return cg.new_Pvariable(filter_id)
158
173
 
159
174
 
175
+ @register_filter(
176
+ "timeout",
177
+ TimeoutFilter,
178
+ cv.templatable(cv.positive_time_period_milliseconds),
179
+ )
180
+ async def timeout_filter_to_code(config, filter_id):
181
+ var = cg.new_Pvariable(filter_id)
182
+ await cg.register_component(var, {})
183
+ template_ = await cg.templatable(config, [], cg.uint32)
184
+ cg.add(var.set_timeout_value(template_))
185
+ return var
186
+
187
+
160
188
  @register_filter(
161
189
  "delayed_on_off",
162
190
  DelayedOnOffFilter,
@@ -386,6 +414,14 @@ def validate_click_timing(value):
386
414
  return value
387
415
 
388
416
 
417
+ def validate_publish_initial_state(value):
418
+ value = cv.boolean(value)
419
+ _LOGGER.warning(
420
+ "The 'publish_initial_state' option has been replaced by 'trigger_on_initial_state' and will be removed in a future release"
421
+ )
422
+ return value
423
+
424
+
389
425
  _BINARY_SENSOR_SCHEMA = (
390
426
  cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
391
427
  .extend(cv.MQTT_COMPONENT_SCHEMA)
@@ -395,7 +431,12 @@ _BINARY_SENSOR_SCHEMA = (
395
431
  cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(
396
432
  mqtt.MQTTBinarySensorComponent
397
433
  ),
398
- cv.Optional(CONF_PUBLISH_INITIAL_STATE): cv.boolean,
434
+ cv.Exclusive(
435
+ CONF_PUBLISH_INITIAL_STATE, CONF_TRIGGER_ON_INITIAL_STATE
436
+ ): validate_publish_initial_state,
437
+ cv.Exclusive(
438
+ CONF_TRIGGER_ON_INITIAL_STATE, CONF_TRIGGER_ON_INITIAL_STATE
439
+ ): cv.boolean,
399
440
  cv.Optional(CONF_DEVICE_CLASS): validate_device_class,
400
441
  cv.Optional(CONF_FILTERS): validate_filters,
401
442
  cv.Optional(CONF_ON_PRESS): automation.validate_automation(
@@ -454,11 +495,19 @@ _BINARY_SENSOR_SCHEMA = (
454
495
  cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
455
496
  }
456
497
  ),
498
+ cv.Optional(CONF_ON_STATE_CHANGE): automation.validate_automation(
499
+ {
500
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateChangeTrigger),
501
+ }
502
+ ),
457
503
  }
458
504
  )
459
505
  )
460
506
 
461
507
 
508
+ _BINARY_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("binary_sensor"))
509
+
510
+
462
511
  def binary_sensor_schema(
463
512
  class_: MockObjClass = cv.UNDEFINED,
464
513
  *,
@@ -489,12 +538,14 @@ BINARY_SENSOR_SCHEMA.add_extra(cv.deprecated_schema_constant("binary_sensor"))
489
538
 
490
539
 
491
540
  async def setup_binary_sensor_core_(var, config):
492
- await setup_entity(var, config)
541
+ await setup_entity(var, config, "binary_sensor")
493
542
 
494
543
  if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
495
544
  cg.add(var.set_device_class(device_class))
496
- if publish_initial_state := config.get(CONF_PUBLISH_INITIAL_STATE):
497
- cg.add(var.set_publish_initial_state(publish_initial_state))
545
+ trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get(
546
+ CONF_PUBLISH_INITIAL_STATE, False
547
+ )
548
+ cg.add(var.set_trigger_on_initial_state(trigger))
498
549
  if inverted := config.get(CONF_INVERTED):
499
550
  cg.add(var.set_inverted(inverted))
500
551
  if filters_config := config.get(CONF_FILTERS):
@@ -542,6 +593,17 @@ async def setup_binary_sensor_core_(var, config):
542
593
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
543
594
  await automation.build_automation(trigger, [(bool, "x")], conf)
544
595
 
596
+ for conf in config.get(CONF_ON_STATE_CHANGE, []):
597
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
598
+ await automation.build_automation(
599
+ trigger,
600
+ [
601
+ (cg.optional.template(bool), "x_previous"),
602
+ (cg.optional.template(bool), "x"),
603
+ ],
604
+ conf,
605
+ )
606
+
545
607
  if mqtt_id := config.get(CONF_MQTT_ID):
546
608
  mqtt_ = cg.new_Pvariable(mqtt_id, var)
547
609
  await mqtt.register_mqtt_component(mqtt_, config)
@@ -591,3 +653,18 @@ async def binary_sensor_is_off_to_code(config, condition_id, template_arg, args)
591
653
  async def to_code(config):
592
654
  cg.add_define("USE_BINARY_SENSOR")
593
655
  cg.add_global(binary_sensor_ns.using)
656
+
657
+
658
+ @automation.register_action(
659
+ "binary_sensor.invalidate_state",
660
+ BinarySensorInvalidateAction,
661
+ cv.maybe_simple_value(
662
+ {
663
+ cv.Required(CONF_ID): cv.use_id(BinarySensor),
664
+ },
665
+ key=CONF_ID,
666
+ ),
667
+ )
668
+ async def binary_sensor_invalidate_state_to_code(config, action_id, template_arg, args):
669
+ paren = await cg.get_variable(config[CONF_ID])
670
+ return cg.new_Pvariable(action_id, template_arg, paren)
@@ -96,7 +96,7 @@ class MultiClickTrigger : public Trigger<>, public Component {
96
96
  : parent_(parent), timing_(std::move(timing)) {}
97
97
 
98
98
  void setup() override {
99
- this->last_state_ = this->parent_->state;
99
+ this->last_state_ = this->parent_->get_state_default(false);
100
100
  auto f = std::bind(&MultiClickTrigger::on_state_, this, std::placeholders::_1);
101
101
  this->parent_->add_on_state_callback(f);
102
102
  }
@@ -130,6 +130,14 @@ class StateTrigger : public Trigger<bool> {
130
130
  }
131
131
  };
132
132
 
133
+ class StateChangeTrigger : public Trigger<optional<bool>, optional<bool> > {
134
+ public:
135
+ explicit StateChangeTrigger(BinarySensor *parent) {
136
+ parent->add_full_state_callback(
137
+ [this](optional<bool> old_state, optional<bool> state) { this->trigger(old_state, state); });
138
+ }
139
+ };
140
+
133
141
  template<typename... Ts> class BinarySensorCondition : public Condition<Ts...> {
134
142
  public:
135
143
  BinarySensorCondition(BinarySensor *parent, bool state) : parent_(parent), state_(state) {}
@@ -154,5 +162,15 @@ template<typename... Ts> class BinarySensorPublishAction : public Action<Ts...>
154
162
  BinarySensor *sensor_;
155
163
  };
156
164
 
165
+ template<typename... Ts> class BinarySensorInvalidateAction : public Action<Ts...> {
166
+ public:
167
+ explicit BinarySensorInvalidateAction(BinarySensor *sensor) : sensor_(sensor) {}
168
+
169
+ void play(Ts... x) override { this->sensor_->invalidate_state(); }
170
+
171
+ protected:
172
+ BinarySensor *sensor_;
173
+ };
174
+
157
175
  } // namespace binary_sensor
158
176
  } // namespace esphome
@@ -7,43 +7,26 @@ namespace binary_sensor {
7
7
 
8
8
  static const char *const TAG = "binary_sensor";
9
9
 
10
- void BinarySensor::add_on_state_callback(std::function<void(bool)> &&callback) {
11
- this->state_callback_.add(std::move(callback));
12
- }
13
-
14
- void BinarySensor::publish_state(bool state) {
15
- if (!this->publish_dedup_.next(state))
16
- return;
10
+ void BinarySensor::publish_state(bool new_state) {
17
11
  if (this->filter_list_ == nullptr) {
18
- this->send_state_internal(state, false);
12
+ this->send_state_internal(new_state);
19
13
  } else {
20
- this->filter_list_->input(state, false);
14
+ this->filter_list_->input(new_state);
21
15
  }
22
16
  }
23
- void BinarySensor::publish_initial_state(bool state) {
24
- if (!this->publish_dedup_.next(state))
25
- return;
26
- if (this->filter_list_ == nullptr) {
27
- this->send_state_internal(state, true);
28
- } else {
29
- this->filter_list_->input(state, true);
30
- }
17
+ void BinarySensor::publish_initial_state(bool new_state) {
18
+ this->invalidate_state();
19
+ this->publish_state(new_state);
31
20
  }
32
- void BinarySensor::send_state_internal(bool state, bool is_initial) {
33
- if (is_initial) {
34
- ESP_LOGD(TAG, "'%s': Sending initial state %s", this->get_name().c_str(), ONOFF(state));
35
- } else {
36
- ESP_LOGD(TAG, "'%s': Sending state %s", this->get_name().c_str(), ONOFF(state));
37
- }
38
- this->has_state_ = true;
39
- this->state = state;
40
- if (!is_initial || this->publish_initial_state_) {
41
- this->state_callback_.call(state);
21
+ void BinarySensor::send_state_internal(bool new_state) {
22
+ // copy the new state to the visible property for backwards compatibility, before any callbacks
23
+ this->state = new_state;
24
+ // Note that set_state_ de-dups and will only trigger callbacks if the state has actually changed
25
+ if (this->set_state_(new_state)) {
26
+ ESP_LOGD(TAG, "'%s': New state is %s", this->get_name().c_str(), ONOFF(new_state));
42
27
  }
43
28
  }
44
29
 
45
- BinarySensor::BinarySensor() : state(false) {}
46
-
47
30
  void BinarySensor::add_filter(Filter *filter) {
48
31
  filter->parent_ = this;
49
32
  if (this->filter_list_ == nullptr) {
@@ -60,7 +43,6 @@ void BinarySensor::add_filters(const std::vector<Filter *> &filters) {
60
43
  this->add_filter(filter);
61
44
  }
62
45
  }
63
- bool BinarySensor::has_state() const { return this->has_state_; }
64
46
  bool BinarySensor::is_status_binary_sensor() const { return false; }
65
47
 
66
48
  } // namespace binary_sensor
@@ -1,6 +1,5 @@
1
1
  #pragma once
2
2
 
3
- #include "esphome/core/component.h"
4
3
  #include "esphome/core/entity_base.h"
5
4
  #include "esphome/core/helpers.h"
6
5
  #include "esphome/components/binary_sensor/filter.h"
@@ -34,52 +33,39 @@ namespace binary_sensor {
34
33
  * The sub classes should notify the front-end of new states via the publish_state() method which
35
34
  * handles inverted inputs for you.
36
35
  */
37
- class BinarySensor : public EntityBase, public EntityBase_DeviceClass {
36
+ class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceClass {
38
37
  public:
39
- explicit BinarySensor();
40
-
41
- /** Add a callback to be notified of state changes.
42
- *
43
- * @param callback The void(bool) callback.
44
- */
45
- void add_on_state_callback(std::function<void(bool)> &&callback);
38
+ explicit BinarySensor(){};
46
39
 
47
40
  /** Publish a new state to the front-end.
48
41
  *
49
- * @param state The new state.
42
+ * @param new_state The new state.
50
43
  */
51
- void publish_state(bool state);
44
+ void publish_state(bool new_state);
52
45
 
53
46
  /** Publish the initial state, this will not make the callback manager send callbacks
54
47
  * and is meant only for the initial state on boot.
55
48
  *
56
- * @param state The new state.
49
+ * @param new_state The new state.
57
50
  */
58
- void publish_initial_state(bool state);
59
-
60
- /// The current reported state of the binary sensor.
61
- bool state{false};
51
+ void publish_initial_state(bool new_state);
62
52
 
63
53
  void add_filter(Filter *filter);
64
54
  void add_filters(const std::vector<Filter *> &filters);
65
55
 
66
- void set_publish_initial_state(bool publish_initial_state) { this->publish_initial_state_ = publish_initial_state; }
67
-
68
56
  // ========== INTERNAL METHODS ==========
69
57
  // (In most use cases you won't need these)
70
- void send_state_internal(bool state, bool is_initial);
58
+ void send_state_internal(bool new_state);
71
59
 
72
60
  /// Return whether this binary sensor has outputted a state.
73
- virtual bool has_state() const;
74
-
75
61
  virtual bool is_status_binary_sensor() const;
76
62
 
63
+ // For backward compatibility, provide an accessible property
64
+
65
+ bool state{};
66
+
77
67
  protected:
78
- CallbackManager<void(bool)> state_callback_{};
79
68
  Filter *filter_list_{nullptr};
80
- bool has_state_{false};
81
- bool publish_initial_state_{false};
82
- Deduplicator<bool> publish_dedup_;
83
69
  };
84
70
 
85
71
  class BinarySensorInitiallyOff : public BinarySensor {
@@ -9,37 +9,42 @@ namespace binary_sensor {
9
9
 
10
10
  static const char *const TAG = "sensor.filter";
11
11
 
12
- void Filter::output(bool value, bool is_initial) {
13
- if (!this->dedup_.next(value))
14
- return;
15
-
12
+ void Filter::output(bool value) {
16
13
  if (this->next_ == nullptr) {
17
- this->parent_->send_state_internal(value, is_initial);
14
+ this->parent_->send_state_internal(value);
18
15
  } else {
19
- this->next_->input(value, is_initial);
16
+ this->next_->input(value);
20
17
  }
21
18
  }
22
- void Filter::input(bool value, bool is_initial) {
23
- auto b = this->new_value(value, is_initial);
19
+ void Filter::input(bool value) {
20
+ if (!this->dedup_.next(value))
21
+ return;
22
+ auto b = this->new_value(value);
24
23
  if (b.has_value()) {
25
- this->output(*b, is_initial);
24
+ this->output(*b);
26
25
  }
27
26
  }
28
27
 
29
- optional<bool> DelayedOnOffFilter::new_value(bool value, bool is_initial) {
28
+ void TimeoutFilter::input(bool value) {
29
+ this->set_timeout("timeout", this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
30
+ // we do not de-dup here otherwise changes from invalid to valid state will not be output
31
+ this->output(value);
32
+ }
33
+
34
+ optional<bool> DelayedOnOffFilter::new_value(bool value) {
30
35
  if (value) {
31
- this->set_timeout("ON_OFF", this->on_delay_.value(), [this, is_initial]() { this->output(true, is_initial); });
36
+ this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });
32
37
  } else {
33
- this->set_timeout("ON_OFF", this->off_delay_.value(), [this, is_initial]() { this->output(false, is_initial); });
38
+ this->set_timeout("ON_OFF", this->off_delay_.value(), [this]() { this->output(false); });
34
39
  }
35
40
  return {};
36
41
  }
37
42
 
38
43
  float DelayedOnOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
39
44
 
40
- optional<bool> DelayedOnFilter::new_value(bool value, bool is_initial) {
45
+ optional<bool> DelayedOnFilter::new_value(bool value) {
41
46
  if (value) {
42
- this->set_timeout("ON", this->delay_.value(), [this, is_initial]() { this->output(true, is_initial); });
47
+ this->set_timeout("ON", this->delay_.value(), [this]() { this->output(true); });
43
48
  return {};
44
49
  } else {
45
50
  this->cancel_timeout("ON");
@@ -49,9 +54,9 @@ optional<bool> DelayedOnFilter::new_value(bool value, bool is_initial) {
49
54
 
50
55
  float DelayedOnFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
51
56
 
52
- optional<bool> DelayedOffFilter::new_value(bool value, bool is_initial) {
57
+ optional<bool> DelayedOffFilter::new_value(bool value) {
53
58
  if (!value) {
54
- this->set_timeout("OFF", this->delay_.value(), [this, is_initial]() { this->output(false, is_initial); });
59
+ this->set_timeout("OFF", this->delay_.value(), [this]() { this->output(false); });
55
60
  return {};
56
61
  } else {
57
62
  this->cancel_timeout("OFF");
@@ -61,11 +66,11 @@ optional<bool> DelayedOffFilter::new_value(bool value, bool is_initial) {
61
66
 
62
67
  float DelayedOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
63
68
 
64
- optional<bool> InvertFilter::new_value(bool value, bool is_initial) { return !value; }
69
+ optional<bool> InvertFilter::new_value(bool value) { return !value; }
65
70
 
66
71
  AutorepeatFilter::AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings) : timings_(std::move(timings)) {}
67
72
 
68
- optional<bool> AutorepeatFilter::new_value(bool value, bool is_initial) {
73
+ optional<bool> AutorepeatFilter::new_value(bool value) {
69
74
  if (value) {
70
75
  // Ignore if already running
71
76
  if (this->active_timing_ != 0)
@@ -101,7 +106,7 @@ void AutorepeatFilter::next_timing_() {
101
106
 
102
107
  void AutorepeatFilter::next_value_(bool val) {
103
108
  const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
104
- this->output(val, false); // This is at least the second one so not initial
109
+ this->output(val); // This is at least the second one so not initial
105
110
  this->set_timeout("ON_OFF", val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); });
106
111
  }
107
112
 
@@ -109,18 +114,18 @@ float AutorepeatFilter::get_setup_priority() const { return setup_priority::HARD
109
114
 
110
115
  LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
111
116
 
112
- optional<bool> LambdaFilter::new_value(bool value, bool is_initial) { return this->f_(value); }
117
+ optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
113
118
 
114
- optional<bool> SettleFilter::new_value(bool value, bool is_initial) {
119
+ optional<bool> SettleFilter::new_value(bool value) {
115
120
  if (!this->steady_) {
116
- this->set_timeout("SETTLE", this->delay_.value(), [this, value, is_initial]() {
121
+ this->set_timeout("SETTLE", this->delay_.value(), [this, value]() {
117
122
  this->steady_ = true;
118
- this->output(value, is_initial);
123
+ this->output(value);
119
124
  });
120
125
  return {};
121
126
  } else {
122
127
  this->steady_ = false;
123
- this->output(value, is_initial);
128
+ this->output(value);
124
129
  this->set_timeout("SETTLE", this->delay_.value(), [this]() { this->steady_ = true; });
125
130
  return value;
126
131
  }