esphome 2025.7.5__py3-none-any.whl → 2025.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (756) hide show
  1. esphome/__main__.py +190 -83
  2. esphome/automation.py +2 -4
  3. esphome/build_gen/__init__.py +0 -0
  4. esphome/build_gen/platformio.py +102 -0
  5. esphome/components/a4988/a4988.cpp +0 -1
  6. esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
  7. esphome/components/absolute_humidity/sensor.py +2 -2
  8. esphome/components/adc/__init__.py +123 -85
  9. esphome/components/adc/adc_sensor.h +98 -35
  10. esphome/components/adc/adc_sensor_common.cpp +10 -4
  11. esphome/components/adc/adc_sensor_esp32.cpp +291 -123
  12. esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
  13. esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
  14. esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
  15. esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
  16. esphome/components/adc/sensor.py +61 -27
  17. esphome/components/adc128s102/adc128s102.cpp +1 -4
  18. esphome/components/ade7880/sensor.py +75 -49
  19. esphome/components/ads1115/ads1115.cpp +0 -1
  20. esphome/components/ads1118/ads1118.cpp +0 -1
  21. esphome/components/ags10/ags10.cpp +0 -4
  22. esphome/components/aht10/aht10.cpp +0 -4
  23. esphome/components/aic3204/aic3204.cpp +0 -2
  24. esphome/components/airthings_wave_plus/__init__.py +1 -1
  25. esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
  26. esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
  27. esphome/components/airthings_wave_plus/sensor.py +55 -28
  28. esphome/components/alarm_control_panel/__init__.py +4 -9
  29. esphome/components/am2315c/am2315c.cpp +0 -2
  30. esphome/components/am2320/am2320.cpp +0 -1
  31. esphome/components/animation/__init__.py +14 -11
  32. esphome/components/apds9306/apds9306.cpp +0 -4
  33. esphome/components/apds9960/apds9960.cpp +0 -1
  34. esphome/components/api/__init__.py +29 -4
  35. esphome/components/api/api_connection.cpp +378 -401
  36. esphome/components/api/api_connection.h +102 -52
  37. esphome/components/api/api_frame_helper.cpp +69 -896
  38. esphome/components/api/api_frame_helper.h +31 -126
  39. esphome/components/api/api_frame_helper_noise.cpp +583 -0
  40. esphome/components/api/api_frame_helper_noise.h +68 -0
  41. esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
  42. esphome/components/api/api_frame_helper_plaintext.h +53 -0
  43. esphome/components/api/api_noise_context.h +2 -4
  44. esphome/components/api/api_pb2.cpp +1601 -1808
  45. esphome/components/api/api_pb2.h +367 -323
  46. esphome/components/api/api_pb2_dump.cpp +1137 -3466
  47. esphome/components/api/api_pb2_includes.h +34 -0
  48. esphome/components/api/api_pb2_service.cpp +94 -105
  49. esphome/components/api/api_pb2_service.h +27 -16
  50. esphome/components/api/api_server.cpp +18 -17
  51. esphome/components/api/api_server.h +8 -5
  52. esphome/components/api/client.py +16 -8
  53. esphome/components/api/custom_api_device.h +68 -14
  54. esphome/components/api/homeassistant_service.h +24 -19
  55. esphome/components/api/list_entities.cpp +3 -5
  56. esphome/components/api/list_entities.h +2 -4
  57. esphome/components/api/proto.cpp +3 -5
  58. esphome/components/api/proto.h +239 -274
  59. esphome/components/api/subscribe_state.cpp +2 -4
  60. esphome/components/api/subscribe_state.h +2 -4
  61. esphome/components/api/user_services.cpp +2 -4
  62. esphome/components/api/user_services.h +8 -8
  63. esphome/components/as3935/as3935.cpp +0 -2
  64. esphome/components/as3935_spi/as3935_spi.cpp +0 -2
  65. esphome/components/as5600/__init__.py +1 -1
  66. esphome/components/as5600/as5600.cpp +0 -2
  67. esphome/components/as5600/sensor/__init__.py +0 -1
  68. esphome/components/as7341/as7341.cpp +0 -1
  69. esphome/components/async_tcp/__init__.py +1 -1
  70. esphome/components/at581x/at581x.cpp +1 -1
  71. esphome/components/atm90e26/atm90e26.cpp +0 -1
  72. esphome/components/atm90e32/atm90e32.cpp +475 -116
  73. esphome/components/atm90e32/atm90e32.h +43 -5
  74. esphome/components/audio/audio.h +2 -2
  75. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
  76. esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
  77. esphome/components/bh1750/bh1750.cpp +0 -1
  78. esphome/components/binary_sensor/__init__.py +14 -12
  79. esphome/components/ble_client/__init__.py +4 -7
  80. esphome/components/bluetooth_proxy/__init__.py +40 -3
  81. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +392 -81
  82. esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
  83. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
  84. esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
  85. esphome/components/bme280_base/bme280_base.cpp +15 -16
  86. esphome/components/bme680/bme680.cpp +2 -3
  87. esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
  88. esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
  89. esphome/components/bmi160/bmi160.cpp +0 -1
  90. esphome/components/bmp085/bmp085.cpp +0 -1
  91. esphome/components/bmp280_base/bmp280_base.cpp +13 -14
  92. esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
  93. esphome/components/bmp581/bmp581.cpp +0 -2
  94. esphome/components/bp1658cj/bp1658cj.cpp +0 -1
  95. esphome/components/bp5758d/bp5758d.cpp +0 -1
  96. esphome/components/button/__init__.py +0 -1
  97. esphome/components/canbus/__init__.py +2 -3
  98. esphome/components/canbus/canbus.cpp +0 -1
  99. esphome/components/cap1188/cap1188.cpp +0 -2
  100. esphome/components/captive_portal/__init__.py +1 -1
  101. esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
  102. esphome/components/ch422g/ch422g.cpp +0 -1
  103. esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
  104. esphome/components/climate/__init__.py +0 -1
  105. esphome/components/climate/climate_traits.h +24 -0
  106. esphome/components/cm1106/cm1106.cpp +0 -1
  107. esphome/components/const/__init__.py +6 -0
  108. esphome/components/cover/__init__.py +0 -1
  109. esphome/components/cover/cover.cpp +9 -13
  110. esphome/components/cs5460a/cs5460a.cpp +0 -2
  111. esphome/components/cse7761/cse7761.cpp +0 -1
  112. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
  113. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
  114. esphome/components/dac7678/dac7678_output.cpp +0 -2
  115. esphome/components/dallas_temp/dallas_temp.cpp +0 -1
  116. esphome/components/datetime/__init__.py +0 -2
  117. esphome/components/debug/__init__.py +15 -1
  118. esphome/components/debug/debug_zephyr.cpp +281 -0
  119. esphome/components/debug/sensor.py +2 -1
  120. esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
  121. esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
  122. esphome/components/dfrobot_sen0395/__init__.py +1 -2
  123. esphome/components/dht/dht.cpp +0 -1
  124. esphome/components/dht12/dht12.cpp +0 -1
  125. esphome/components/display/__init__.py +16 -3
  126. esphome/components/display_menu_base/__init__.py +1 -1
  127. esphome/components/dps310/dps310.cpp +0 -2
  128. esphome/components/ds1307/ds1307.cpp +0 -1
  129. esphome/components/ds2484/ds2484.cpp +0 -1
  130. esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
  131. esphome/components/ee895/ee895.cpp +0 -1
  132. esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
  133. esphome/components/emc2101/emc2101.cpp +0 -2
  134. esphome/components/ens160_base/ens160_base.cpp +0 -2
  135. esphome/components/ens210/ens210.cpp +0 -1
  136. esphome/components/es7210/es7210.cpp +0 -2
  137. esphome/components/es7243e/es7243e.cpp +0 -2
  138. esphome/components/es8156/es8156.cpp +0 -2
  139. esphome/components/es8311/es8311.cpp +0 -2
  140. esphome/components/es8388/es8388.cpp +0 -2
  141. esphome/components/esp32/__init__.py +203 -60
  142. esphome/components/esp32/boards.py +17 -0
  143. esphome/components/esp32/gpio.cpp +0 -1
  144. esphome/components/esp32/gpio.py +1 -2
  145. esphome/components/esp32/gpio_esp32_h2.py +2 -7
  146. esphome/components/esp32/gpio_esp32_p4.py +2 -7
  147. esphome/components/esp32/post_build.py.script +112 -61
  148. esphome/components/esp32_ble/__init__.py +41 -2
  149. esphome/components/esp32_ble/ble.cpp +14 -10
  150. esphome/components/esp32_ble/ble.h +18 -18
  151. esphome/components/esp32_ble/ble_advertising.cpp +5 -5
  152. esphome/components/esp32_ble/ble_advertising.h +7 -5
  153. esphome/components/esp32_ble/ble_event.h +139 -73
  154. esphome/components/esp32_ble/ble_scan_result.h +2 -4
  155. esphome/components/esp32_ble/ble_uuid.cpp +5 -5
  156. esphome/components/esp32_ble/ble_uuid.h +6 -5
  157. esphome/components/esp32_ble_beacon/__init__.py +4 -0
  158. esphome/components/esp32_ble_client/__init__.py +1 -1
  159. esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
  160. esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
  161. esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
  162. esphome/components/esp32_ble_client/ble_client_base.h +17 -6
  163. esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
  164. esphome/components/esp32_ble_client/ble_service.cpp +4 -4
  165. esphome/components/esp32_ble_client/ble_service.h +6 -4
  166. esphome/components/esp32_ble_server/__init__.py +15 -12
  167. esphome/components/esp32_ble_tracker/__init__.py +79 -11
  168. esphome/components/esp32_ble_tracker/automation.h +4 -4
  169. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
  170. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
  171. esphome/components/esp32_camera/__init__.py +13 -1
  172. esphome/components/esp32_camera/esp32_camera.cpp +7 -2
  173. esphome/components/esp32_camera/esp32_camera.h +1 -0
  174. esphome/components/esp32_dac/esp32_dac.cpp +3 -19
  175. esphome/components/esp32_dac/esp32_dac.h +4 -8
  176. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
  177. esphome/components/esp32_rmt_led_strip/light.py +1 -1
  178. esphome/components/esp32_touch/__init__.py +2 -3
  179. esphome/components/esp32_touch/esp32_touch.h +9 -6
  180. esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
  181. esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
  182. esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
  183. esphome/components/esp8266/__init__.py +3 -1
  184. esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
  185. esphome/components/esphome/ota/__init__.py +1 -2
  186. esphome/components/esphome/ota/ota_esphome.cpp +150 -77
  187. esphome/components/esphome/ota/ota_esphome.h +8 -1
  188. esphome/components/espnow/__init__.py +309 -0
  189. esphome/components/espnow/automation.h +175 -0
  190. esphome/components/espnow/espnow_component.cpp +468 -0
  191. esphome/components/espnow/espnow_component.h +183 -0
  192. esphome/components/espnow/espnow_err.h +19 -0
  193. esphome/components/espnow/espnow_packet.h +166 -0
  194. esphome/components/ethernet/__init__.py +7 -1
  195. esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
  196. esphome/components/ethernet/ethernet_component.cpp +0 -1
  197. esphome/components/ethernet/ethernet_component.h +4 -0
  198. esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
  199. esphome/components/event/__init__.py +0 -1
  200. esphome/components/factory_reset/__init__.py +92 -0
  201. esphome/components/factory_reset/factory_reset.cpp +76 -0
  202. esphome/components/factory_reset/factory_reset.h +43 -0
  203. esphome/components/fan/__init__.py +0 -1
  204. esphome/components/fan/fan_traits.h +16 -0
  205. esphome/components/fastled_base/fastled_light.cpp +0 -1
  206. esphome/components/fastled_spi/light.py +1 -3
  207. esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
  208. esphome/components/fs3000/fs3000.cpp +0 -2
  209. esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
  210. esphome/components/ft63x6/ft63x6.cpp +0 -1
  211. esphome/components/gdk101/gdk101.cpp +0 -1
  212. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
  213. esphome/components/gl_r01_i2c/sensor.py +1 -1
  214. esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
  215. esphome/components/gpio/switch/gpio_switch.cpp +0 -2
  216. esphome/components/gpio_expander/cached_gpio.h +24 -15
  217. esphome/components/gps/__init__.py +6 -2
  218. esphome/components/gps/gps.cpp +50 -49
  219. esphome/components/gps/gps.h +4 -8
  220. esphome/components/gps/time/gps_time.cpp +3 -9
  221. esphome/components/gps/time/gps_time.h +4 -7
  222. esphome/components/graph/__init__.py +1 -1
  223. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
  224. esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
  225. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
  226. esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
  227. esphome/components/haier/climate.py +5 -10
  228. esphome/components/haier/haier_base.cpp +0 -1
  229. esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
  230. esphome/components/hdc1080/hdc1080.cpp +0 -2
  231. esphome/components/heatpumpir/climate.py +2 -2
  232. esphome/components/hlw8012/hlw8012.cpp +0 -1
  233. esphome/components/hm3301/hm3301.cpp +0 -1
  234. esphome/components/hmc5883l/hmc5883l.cpp +0 -1
  235. esphome/components/homeassistant/__init__.py +1 -0
  236. esphome/components/homeassistant/number/__init__.py +1 -0
  237. esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
  238. esphome/components/homeassistant/switch/__init__.py +1 -0
  239. esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
  240. esphome/components/honeywellabp/honeywellabp.cpp +1 -4
  241. esphome/components/host/__init__.py +2 -0
  242. esphome/components/hte501/hte501.cpp +0 -1
  243. esphome/components/http_request/__init__.py +2 -3
  244. esphome/components/http_request/http_request_idf.cpp +2 -2
  245. esphome/components/htu21d/htu21d.cpp +0 -2
  246. esphome/components/htu31d/htu31d.cpp +0 -2
  247. esphome/components/hx711/hx711.cpp +0 -1
  248. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
  249. esphome/components/hydreon_rgxx/sensor.py +4 -5
  250. esphome/components/i2c/i2c_bus.h +1 -1
  251. esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
  252. esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
  253. esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
  254. esphome/components/i2s_audio/__init__.py +6 -5
  255. esphome/components/i2s_audio/i2s_audio.cpp +0 -2
  256. esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
  257. esphome/components/i2s_audio/microphone/__init__.py +4 -6
  258. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +0 -1
  259. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +2 -2
  260. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
  261. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
  262. esphome/components/ili9xxx/display.py +4 -3
  263. esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
  264. esphome/components/image/__init__.py +123 -92
  265. esphome/components/improv_serial/__init__.py +7 -8
  266. esphome/components/ina219/ina219.cpp +0 -1
  267. esphome/components/ina226/ina226.cpp +0 -2
  268. esphome/components/ina260/ina260.cpp +0 -2
  269. esphome/components/ina2xx_base/__init__.py +2 -5
  270. esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
  271. esphome/components/ina3221/ina3221.cpp +0 -1
  272. esphome/components/internal_temperature/internal_temperature.cpp +0 -2
  273. esphome/components/interval/interval.h +5 -9
  274. esphome/components/json/__init__.py +1 -1
  275. esphome/components/kmeteriso/kmeteriso.cpp +0 -2
  276. esphome/components/lc709203f/lc709203f.cpp +0 -2
  277. esphome/components/lcd_gpio/display.py +1 -3
  278. esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
  279. esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
  280. esphome/components/ld2410/__init__.py +4 -6
  281. esphome/components/ld2410/binary_sensor.py +4 -0
  282. esphome/components/ld2410/ld2410.cpp +56 -100
  283. esphome/components/ld2410/ld2410.h +17 -15
  284. esphome/components/ld2410/sensor.py +24 -10
  285. esphome/components/ld2412/__init__.py +46 -0
  286. esphome/components/ld2412/binary_sensor.py +70 -0
  287. esphome/components/ld2412/button/__init__.py +74 -0
  288. esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
  289. esphome/components/ld2412/button/factory_reset_button.h +18 -0
  290. esphome/components/ld2412/button/query_button.cpp +9 -0
  291. esphome/components/ld2412/button/query_button.h +18 -0
  292. esphome/components/ld2412/button/restart_button.cpp +9 -0
  293. esphome/components/ld2412/button/restart_button.h +18 -0
  294. esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
  295. esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
  296. esphome/components/ld2412/ld2412.cpp +861 -0
  297. esphome/components/ld2412/ld2412.h +141 -0
  298. esphome/components/ld2412/number/__init__.py +126 -0
  299. esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
  300. esphome/components/ld2412/number/gate_threshold_number.h +19 -0
  301. esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
  302. esphome/components/ld2412/number/light_threshold_number.h +18 -0
  303. esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
  304. esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
  305. esphome/components/ld2412/select/__init__.py +82 -0
  306. esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
  307. esphome/components/ld2412/select/baud_rate_select.h +18 -0
  308. esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
  309. esphome/components/ld2412/select/distance_resolution_select.h +18 -0
  310. esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
  311. esphome/components/ld2412/select/light_out_control_select.h +18 -0
  312. esphome/components/ld2412/sensor.py +124 -0
  313. esphome/components/ld2412/switch/__init__.py +45 -0
  314. esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
  315. esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
  316. esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
  317. esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
  318. esphome/components/ld2412/text_sensor.py +34 -0
  319. esphome/components/ld2420/ld2420.cpp +0 -1
  320. esphome/components/ld2450/__init__.py +3 -4
  321. esphome/components/ld2450/binary_sensor.py +3 -0
  322. esphome/components/ld2450/ld2450.cpp +77 -165
  323. esphome/components/ld2450/ld2450.h +26 -54
  324. esphome/components/ld2450/sensor.py +120 -6
  325. esphome/components/ld2450/text_sensor.py +5 -4
  326. esphome/components/ld24xx/__init__.py +1 -0
  327. esphome/components/ld24xx/ld24xx.h +65 -0
  328. esphome/components/ledc/ledc_output.cpp +0 -1
  329. esphome/components/libretiny/__init__.py +2 -0
  330. esphome/components/light/__init__.py +0 -1
  331. esphome/components/light/effects.py +70 -45
  332. esphome/components/light/light_call.cpp +101 -66
  333. esphome/components/light/light_color_values.h +16 -11
  334. esphome/components/light/light_json_schema.cpp +46 -44
  335. esphome/components/light/light_state.cpp +8 -11
  336. esphome/components/light/light_traits.h +17 -0
  337. esphome/components/lightwaverf/lightwaverf.cpp +0 -2
  338. esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
  339. esphome/components/lock/__init__.py +0 -1
  340. esphome/components/logger/__init__.py +31 -9
  341. esphome/components/logger/logger.cpp +12 -7
  342. esphome/components/logger/logger.h +25 -14
  343. esphome/components/logger/logger_esp32.cpp +2 -7
  344. esphome/components/logger/logger_esp8266.cpp +2 -4
  345. esphome/components/logger/logger_host.cpp +2 -4
  346. esphome/components/logger/logger_libretiny.cpp +2 -4
  347. esphome/components/logger/logger_rp2040.cpp +2 -4
  348. esphome/components/logger/logger_zephyr.cpp +86 -0
  349. esphome/components/logger/select/logger_level_select.cpp +2 -4
  350. esphome/components/logger/select/logger_level_select.h +2 -4
  351. esphome/components/logger/task_log_buffer.cpp +2 -4
  352. esphome/components/logger/task_log_buffer.h +2 -4
  353. esphome/components/lps22/sensor.py +5 -5
  354. esphome/components/ltr390/ltr390.cpp +0 -2
  355. esphome/components/ltr501/ltr501.cpp +0 -1
  356. esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
  357. esphome/components/lvgl/__init__.py +14 -13
  358. esphome/components/lvgl/automation.py +2 -4
  359. esphome/components/lvgl/defines.py +0 -2
  360. esphome/components/lvgl/helpers.py +1 -1
  361. esphome/components/lvgl/lv_validation.py +7 -4
  362. esphome/components/lvgl/lvgl_esphome.cpp +2 -3
  363. esphome/components/lvgl/styles.py +2 -2
  364. esphome/components/lvgl/types.py +1 -1
  365. esphome/components/lvgl/widgets/__init__.py +2 -2
  366. esphome/components/lvgl/widgets/arc.py +14 -11
  367. esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
  368. esphome/components/lvgl/widgets/qrcode.py +7 -7
  369. esphome/components/lvgl/widgets/spinner.py +6 -6
  370. esphome/components/lvgl/widgets/switch.py +2 -2
  371. esphome/components/lvgl/widgets/tabview.py +3 -3
  372. esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
  373. esphome/components/matrix_keypad/__init__.py +4 -3
  374. esphome/components/max17043/max17043.cpp +0 -2
  375. esphome/components/max31855/max31855.cpp +1 -4
  376. esphome/components/max31856/max31856.cpp +0 -4
  377. esphome/components/max31865/max31865.cpp +0 -1
  378. esphome/components/max44009/max44009.cpp +0 -1
  379. esphome/components/max6675/max6675.cpp +1 -4
  380. esphome/components/max6956/max6956.cpp +0 -1
  381. esphome/components/max7219/max7219.cpp +0 -1
  382. esphome/components/max7219digit/display.py +1 -1
  383. esphome/components/max7219digit/max7219digit.cpp +0 -1
  384. esphome/components/max9611/max9611.cpp +0 -1
  385. esphome/components/mcp23008/__init__.py +1 -1
  386. esphome/components/mcp23008/mcp23008.cpp +0 -1
  387. esphome/components/mcp23016/mcp23016.cpp +0 -1
  388. esphome/components/mcp23017/__init__.py +1 -1
  389. esphome/components/mcp23017/mcp23017.cpp +0 -1
  390. esphome/components/mcp23s08/__init__.py +1 -1
  391. esphome/components/mcp23s08/mcp23s08.cpp +0 -1
  392. esphome/components/mcp23s17/__init__.py +1 -1
  393. esphome/components/mcp23s17/mcp23s17.cpp +0 -1
  394. esphome/components/mcp23x08_base/__init__.py +2 -0
  395. esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
  396. esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
  397. esphome/components/mcp23x17_base/__init__.py +2 -0
  398. esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
  399. esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
  400. esphome/components/mcp23xxx_base/__init__.py +11 -5
  401. esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
  402. esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
  403. esphome/components/mcp3008/mcp3008.cpp +1 -4
  404. esphome/components/mcp3204/mcp3204.cpp +1 -4
  405. esphome/components/mcp4461/mcp4461.cpp +0 -1
  406. esphome/components/mcp4725/mcp4725.cpp +0 -1
  407. esphome/components/mcp4728/mcp4728.cpp +0 -1
  408. esphome/components/mcp9600/mcp9600.cpp +0 -2
  409. esphome/components/mcp9808/mcp9808.cpp +0 -2
  410. esphome/components/mdns/__init__.py +3 -0
  411. esphome/components/mdns/mdns_component.cpp +2 -0
  412. esphome/components/mdns/mdns_component.h +4 -0
  413. esphome/components/media_player/__init__.py +40 -0
  414. esphome/components/media_player/automation.h +16 -0
  415. esphome/components/media_player/media_player.cpp +13 -0
  416. esphome/components/media_player/media_player.h +50 -3
  417. esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
  418. esphome/components/mics_4514/mics_4514.cpp +1 -6
  419. esphome/components/midea/ir_transmitter.h +4 -4
  420. esphome/components/mipi/__init__.py +416 -0
  421. esphome/components/mipi_dsi/__init__.py +5 -0
  422. esphome/components/mipi_dsi/display.py +233 -0
  423. esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
  424. esphome/components/mipi_dsi/mipi_dsi.h +123 -0
  425. esphome/components/mipi_dsi/models/__init__.py +0 -0
  426. esphome/components/mipi_dsi/models/guition.py +38 -0
  427. esphome/components/mipi_dsi/models/m5stack.py +57 -0
  428. esphome/components/mipi_dsi/models/waveshare.py +105 -0
  429. esphome/components/mipi_rgb/models/lilygo.py +0 -0
  430. esphome/components/mipi_spi/__init__.py +0 -9
  431. esphome/components/mipi_spi/display.py +220 -256
  432. esphome/components/mipi_spi/mipi_spi.cpp +1 -485
  433. esphome/components/mipi_spi/mipi_spi.h +556 -108
  434. esphome/components/mipi_spi/models/__init__.py +0 -65
  435. esphome/components/mipi_spi/models/adafruit.py +30 -0
  436. esphome/components/mipi_spi/models/amoled.py +41 -5
  437. esphome/components/mipi_spi/models/ili.py +5 -5
  438. esphome/components/mipi_spi/models/jc.py +1 -3
  439. esphome/components/mipi_spi/models/lilygo.py +1 -1
  440. esphome/components/mipi_spi/models/waveshare.py +16 -1
  441. esphome/components/mixer/speaker/__init__.py +4 -5
  442. esphome/components/mlx90393/sensor.py +7 -5
  443. esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
  444. esphome/components/mlx90614/mlx90614.cpp +0 -1
  445. esphome/components/mmc5603/mmc5603.cpp +0 -1
  446. esphome/components/mmc5983/mmc5983.cpp +0 -2
  447. esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
  448. esphome/components/mpr121/__init__.py +7 -6
  449. esphome/components/mpr121/mpr121.cpp +0 -1
  450. esphome/components/mpu6050/mpu6050.cpp +0 -1
  451. esphome/components/mpu6886/mpu6886.cpp +0 -1
  452. esphome/components/mqtt/__init__.py +1 -2
  453. esphome/components/mqtt/mqtt_button.cpp +1 -1
  454. esphome/components/mqtt/mqtt_client.cpp +0 -1
  455. esphome/components/mqtt/mqtt_component.cpp +8 -14
  456. esphome/components/mqtt/mqtt_component.h +0 -7
  457. esphome/components/mqtt/mqtt_sensor.cpp +0 -1
  458. esphome/components/mqtt/mqtt_sensor.h +0 -1
  459. esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
  460. esphome/components/mqtt/mqtt_text_sensor.h +0 -1
  461. esphome/components/ms5611/ms5611.cpp +0 -1
  462. esphome/components/ms8607/ms8607.cpp +0 -1
  463. esphome/components/msa3xx/msa3xx.cpp +0 -2
  464. esphome/components/my9231/my9231.cpp +0 -2
  465. esphome/components/nau7802/nau7802.cpp +0 -1
  466. esphome/components/neopixelbus/light.py +3 -0
  467. esphome/components/network/util.cpp +29 -0
  468. esphome/components/nextion/nextion.cpp +2 -2
  469. esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
  470. esphome/components/npi19/npi19.cpp +0 -2
  471. esphome/components/nrf52/__init__.py +223 -0
  472. esphome/components/nrf52/boards.py +34 -0
  473. esphome/components/nrf52/const.py +18 -0
  474. esphome/components/nrf52/gpio.py +79 -0
  475. esphome/components/number/__init__.py +2 -1
  476. esphome/components/one_wire/__init__.py +1 -2
  477. esphome/components/one_wire/one_wire.cpp +0 -2
  478. esphome/components/one_wire/one_wire.h +0 -2
  479. esphome/components/opentherm/hub.cpp +0 -1
  480. esphome/components/opentherm/number/__init__.py +2 -2
  481. esphome/components/openthread/__init__.py +2 -3
  482. esphome/components/openthread/openthread.cpp +30 -13
  483. esphome/components/openthread/openthread.h +3 -0
  484. esphome/components/openthread/openthread_esp.cpp +3 -1
  485. esphome/components/opt3001/sensor.py +2 -6
  486. esphome/components/output/__init__.py +38 -0
  487. esphome/components/output/automation.h +24 -0
  488. esphome/components/output/switch/output_switch.cpp +0 -2
  489. esphome/components/packages/__init__.py +1 -2
  490. esphome/components/packet_transport/__init__.py +4 -3
  491. esphome/components/pca6416a/pca6416a.cpp +0 -1
  492. esphome/components/pca9554/pca9554.cpp +0 -1
  493. esphome/components/pca9685/pca9685_output.cpp +0 -2
  494. esphome/components/pcf85063/pcf85063.cpp +0 -1
  495. esphome/components/pcf8563/pcf8563.cpp +0 -1
  496. esphome/components/pcf8574/pcf8574.cpp +0 -1
  497. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
  498. esphome/components/pipsolar/pipsolar.cpp +54 -42
  499. esphome/components/pipsolar/pipsolar.h +5 -4
  500. esphome/components/pipsolar/sensor/__init__.py +1 -1
  501. esphome/components/pm2005/pm2005.cpp +0 -1
  502. esphome/components/pmsa003i/pmsa003i.cpp +0 -2
  503. esphome/components/pmwcs3/sensor.py +1 -2
  504. esphome/components/pn532/pn532.cpp +0 -2
  505. esphome/components/pn532_spi/pn532_spi.cpp +0 -2
  506. esphome/components/power_supply/power_supply.cpp +7 -10
  507. esphome/components/power_supply/power_supply.h +1 -1
  508. esphome/components/psram/__init__.py +6 -1
  509. esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
  510. esphome/components/pulse_counter/sensor.py +9 -6
  511. esphome/components/pylontech/pylontech.cpp +0 -1
  512. esphome/components/qmc5883l/qmc5883l.cpp +0 -1
  513. esphome/components/qmp6988/qmp6988.cpp +0 -2
  514. esphome/components/qspi_dbi/display.py +2 -3
  515. esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
  516. esphome/components/qwiic_pir/binary_sensor.py +2 -3
  517. esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
  518. esphome/components/rc522/rc522.cpp +9 -31
  519. esphome/components/rc522_spi/rc522_spi.cpp +0 -1
  520. esphome/components/remote_base/__init__.py +5 -6
  521. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
  522. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
  523. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
  524. esphome/components/remote_transmitter/__init__.py +26 -0
  525. esphome/components/remote_transmitter/automation.h +18 -0
  526. esphome/components/remote_transmitter/remote_transmitter.h +2 -1
  527. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
  528. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  529. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  530. esphome/components/resampler/speaker/__init__.py +4 -5
  531. esphome/components/rf_bridge/__init__.py +4 -8
  532. esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
  533. esphome/components/rp2040/__init__.py +3 -1
  534. esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
  535. esphome/components/rp2040_pio_led_strip/light.py +1 -2
  536. esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
  537. esphome/components/rpi_dpi_rgb/display.py +13 -15
  538. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
  539. esphome/components/runtime_stats/__init__.py +34 -0
  540. esphome/components/runtime_stats/runtime_stats.cpp +102 -0
  541. esphome/components/runtime_stats/runtime_stats.h +132 -0
  542. esphome/components/scd30/scd30.cpp +0 -2
  543. esphome/components/scd30/sensor.py +1 -2
  544. esphome/components/scd4x/scd4x.cpp +0 -1
  545. esphome/components/scd4x/sensor.py +1 -3
  546. esphome/components/sdl/display.py +3 -1
  547. esphome/components/sdl/sdl_esphome.cpp +0 -2
  548. esphome/components/sdp3x/sdp3x.cpp +0 -2
  549. esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
  550. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
  551. esphome/components/select/__init__.py +2 -3
  552. esphome/components/select/select_traits.cpp +1 -1
  553. esphome/components/select/select_traits.h +1 -1
  554. esphome/components/sen0321/sen0321.cpp +0 -1
  555. esphome/components/sen5x/sen5x.cpp +0 -2
  556. esphome/components/senseair/senseair.cpp +7 -3
  557. esphome/components/senseair/senseair.h +11 -0
  558. esphome/components/sensor/__init__.py +36 -4
  559. esphome/components/sensor/filter.cpp +49 -10
  560. esphome/components/sensor/filter.h +22 -7
  561. esphome/components/sensor/sensor.cpp +0 -1
  562. esphome/components/sensor/sensor.h +0 -9
  563. esphome/components/sfa30/sfa30.cpp +0 -4
  564. esphome/components/sgp30/sgp30.cpp +0 -2
  565. esphome/components/sgp4x/sensor.py +1 -1
  566. esphome/components/sgp4x/sgp4x.cpp +0 -2
  567. esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
  568. esphome/components/sht3xd/sht3xd.cpp +0 -2
  569. esphome/components/sht4x/sht4x.cpp +0 -2
  570. esphome/components/shtcx/shtcx.cpp +0 -1
  571. esphome/components/sim800l/__init__.py +2 -4
  572. esphome/components/sm16716/sm16716.cpp +0 -1
  573. esphome/components/sm2135/sm2135.cpp +0 -1
  574. esphome/components/sm2235/sm2235.cpp +0 -1
  575. esphome/components/sm2335/sm2335.cpp +0 -1
  576. esphome/components/sn74hc165/sn74hc165.cpp +0 -1
  577. esphome/components/sn74hc595/sn74hc595.cpp +0 -1
  578. esphome/components/sntp/sntp_component.cpp +0 -1
  579. esphome/components/sound_level/sensor.py +1 -1
  580. esphome/components/speaker/media_player/__init__.py +21 -33
  581. esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
  582. esphome/components/spi/__init__.py +29 -13
  583. esphome/components/spi/spi.cpp +0 -2
  584. esphome/components/spi_device/spi_device.cpp +1 -4
  585. esphome/components/sprinkler/__init__.py +4 -4
  586. esphome/components/sps30/sps30.cpp +0 -1
  587. esphome/components/ssd1306_base/__init__.py +11 -11
  588. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  589. esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
  590. esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
  591. esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
  592. esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
  593. esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
  594. esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
  595. esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
  596. esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
  597. esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
  598. esphome/components/st7567_spi/st7567_spi.cpp +0 -1
  599. esphome/components/st7701s/display.py +10 -14
  600. esphome/components/st7701s/st7701s.cpp +0 -3
  601. esphome/components/st7735/st7735.cpp +0 -1
  602. esphome/components/st7789v/st7789v.cpp +0 -1
  603. esphome/components/st7920/st7920.cpp +0 -1
  604. esphome/components/status_led/light/status_led_light.cpp +0 -2
  605. esphome/components/status_led/status_led.cpp +0 -1
  606. esphome/components/stepper/__init__.py +2 -4
  607. esphome/components/sts3x/sts3x.cpp +0 -1
  608. esphome/components/substitutions/__init__.py +10 -16
  609. esphome/components/substitutions/jinja.py +24 -1
  610. esphome/components/sun/__init__.py +2 -3
  611. esphome/components/switch/__init__.py +31 -1
  612. esphome/components/switch/automation.h +24 -0
  613. esphome/components/switch/switch.cpp +8 -0
  614. esphome/components/switch/switch.h +8 -0
  615. esphome/components/sx126x/sx126x.cpp +0 -2
  616. esphome/components/sx127x/sx127x.cpp +0 -2
  617. esphome/components/sx1509/__init__.py +7 -5
  618. esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
  619. esphome/components/sx1509/sx1509.cpp +0 -2
  620. esphome/components/syslog/esphome_syslog.cpp +1 -1
  621. esphome/components/tc74/tc74.cpp +0 -1
  622. esphome/components/tca9548a/tca9548a.cpp +0 -1
  623. esphome/components/tca9555/tca9555.cpp +0 -1
  624. esphome/components/tcs34725/tcs34725.cpp +0 -1
  625. esphome/components/tee501/tee501.cpp +0 -1
  626. esphome/components/tem3200/tem3200.cpp +0 -2
  627. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
  628. esphome/components/template/cover/template_cover.cpp +0 -1
  629. esphome/components/template/select/template_select.cpp +0 -1
  630. esphome/components/template/text/template_text.cpp +0 -2
  631. esphome/components/template/valve/template_valve.cpp +0 -1
  632. esphome/components/text/__init__.py +0 -1
  633. esphome/components/text/text_traits.h +2 -0
  634. esphome/components/text_sensor/__init__.py +2 -1
  635. esphome/components/text_sensor/text_sensor.cpp +0 -2
  636. esphome/components/text_sensor/text_sensor.h +0 -8
  637. esphome/components/thermostat/climate.py +4 -4
  638. esphome/components/time/__init__.py +7 -4
  639. esphome/components/time/real_time_clock.cpp +16 -3
  640. esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
  641. esphome/components/tlc5947/tlc5947.cpp +0 -2
  642. esphome/components/tlc5971/tlc5971.cpp +0 -2
  643. esphome/components/tm1621/tm1621.cpp +0 -2
  644. esphome/components/tm1637/tm1637.cpp +0 -2
  645. esphome/components/tm1638/tm1638.cpp +0 -2
  646. esphome/components/tm1651/__init__.py +45 -48
  647. esphome/components/tm1651/tm1651.cpp +213 -47
  648. esphome/components/tm1651/tm1651.h +37 -32
  649. esphome/components/tmp117/tmp117.cpp +0 -2
  650. esphome/components/tsl2561/tsl2561.cpp +0 -1
  651. esphome/components/tsl2591/tsl2591.cpp +0 -1
  652. esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
  653. esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
  654. esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
  655. esphome/components/tuya/climate/__init__.py +9 -10
  656. esphome/components/tuya/number/__init__.py +8 -6
  657. esphome/components/tx20/tx20.cpp +0 -1
  658. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
  659. esphome/components/uart/uart_component_esp8266.cpp +0 -1
  660. esphome/components/uart/uart_component_esp_idf.cpp +0 -2
  661. esphome/components/uart/uart_component_libretiny.cpp +0 -2
  662. esphome/components/uart/uart_component_rp2040.cpp +0 -2
  663. esphome/components/udp/__init__.py +1 -1
  664. esphome/components/ufire_ec/sensor.py +1 -2
  665. esphome/components/ufire_ec/ufire_ec.cpp +0 -2
  666. esphome/components/ufire_ise/sensor.py +1 -2
  667. esphome/components/ufire_ise/ufire_ise.cpp +0 -2
  668. esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
  669. esphome/components/update/__init__.py +0 -1
  670. esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
  671. esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
  672. esphome/components/usb_host/usb_host_client.cpp +0 -1
  673. esphome/components/usb_host/usb_host_component.cpp +0 -1
  674. esphome/components/valve/__init__.py +0 -1
  675. esphome/components/veml3235/veml3235.cpp +0 -3
  676. esphome/components/veml7700/veml7700.cpp +0 -2
  677. esphome/components/version/version_text_sensor.cpp +0 -1
  678. esphome/components/version/version_text_sensor.h +0 -1
  679. esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
  680. esphome/components/voice_assistant/voice_assistant.cpp +9 -8
  681. esphome/components/web_server/__init__.py +13 -0
  682. esphome/components/web_server/web_server.cpp +188 -353
  683. esphome/components/web_server/web_server.h +61 -1
  684. esphome/components/web_server_base/__init__.py +1 -1
  685. esphome/components/web_server_base/web_server_base.cpp +2 -0
  686. esphome/components/web_server_base/web_server_base.h +6 -0
  687. esphome/components/web_server_idf/web_server_idf.cpp +10 -8
  688. esphome/components/web_server_idf/web_server_idf.h +2 -0
  689. esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
  690. esphome/components/weikai_spi/weikai_spi.cpp +1 -1
  691. esphome/components/wifi/__init__.py +17 -43
  692. esphome/components/wifi/wifi_component.cpp +100 -36
  693. esphome/components/wifi/wifi_component.h +5 -1
  694. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
  695. esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
  696. esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
  697. esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
  698. esphome/components/wireguard/wireguard.cpp +0 -2
  699. esphome/components/x9c/x9c.cpp +0 -2
  700. esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
  701. esphome/components/xl9535/xl9535.cpp +0 -2
  702. esphome/components/zephyr/__init__.py +252 -0
  703. esphome/components/zephyr/const.py +16 -0
  704. esphome/components/zephyr/core.cpp +90 -0
  705. esphome/components/zephyr/gpio.cpp +120 -0
  706. esphome/components/zephyr/gpio.h +38 -0
  707. esphome/components/zephyr/pre_build.py.script +4 -0
  708. esphome/components/zephyr/preferences.cpp +156 -0
  709. esphome/components/zephyr/preferences.h +13 -0
  710. esphome/config.py +38 -16
  711. esphome/config_helpers.py +1 -2
  712. esphome/config_validation.py +12 -16
  713. esphome/const.py +26 -1
  714. esphome/core/__init__.py +92 -51
  715. esphome/core/application.cpp +75 -21
  716. esphome/core/application.h +106 -171
  717. esphome/core/color.h +10 -0
  718. esphome/core/component.cpp +41 -25
  719. esphome/core/component.h +9 -6
  720. esphome/core/component_iterator.cpp +61 -261
  721. esphome/core/component_iterator.h +15 -0
  722. esphome/core/config.py +26 -11
  723. esphome/core/defines.h +40 -2
  724. esphome/core/entity_base.h +18 -0
  725. esphome/core/entity_helpers.py +45 -10
  726. esphome/core/helpers.cpp +8 -15
  727. esphome/core/helpers.h +60 -6
  728. esphome/core/lock_free_queue.h +1 -1
  729. esphome/core/scheduler.cpp +311 -77
  730. esphome/core/scheduler.h +141 -28
  731. esphome/cpp_generator.py +2 -6
  732. esphome/cpp_helpers.py +1 -1
  733. esphome/dashboard/dashboard.py +2 -3
  734. esphome/dashboard/dns.py +2 -8
  735. esphome/dashboard/web_server.py +34 -19
  736. esphome/espota2.py +1 -4
  737. esphome/git.py +3 -1
  738. esphome/helpers.py +23 -4
  739. esphome/log.py +3 -1
  740. esphome/mqtt.py +3 -5
  741. esphome/platformio_api.py +7 -4
  742. esphome/types.py +12 -0
  743. esphome/util.py +20 -8
  744. esphome/voluptuous_schema.py +4 -3
  745. esphome/vscode.py +1 -2
  746. esphome/wizard.py +1 -4
  747. esphome/writer.py +16 -108
  748. esphome/yaml_util.py +7 -5
  749. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/METADATA +13 -14
  750. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/RECORD +755 -675
  751. esphome/components/mipi_spi/models/commands.py +0 -82
  752. /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
  753. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/WHEEL +0 -0
  754. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/entry_points.txt +0 -0
  755. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/licenses/LICENSE +0 -0
  756. {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/top_level.txt +0 -0
@@ -8,16 +8,366 @@
8
8
 
9
9
  #include "bluetooth_proxy.h"
10
10
 
11
- namespace esphome {
12
- namespace bluetooth_proxy {
11
+ namespace esphome::bluetooth_proxy {
13
12
 
14
13
  static const char *const TAG = "bluetooth_proxy.connection";
15
14
 
15
+ // This function is allocation-free and directly packs UUIDs into the output array
16
+ // using precalculated constants for the Bluetooth base UUID
17
+ static void fill_128bit_uuid_array(std::array<uint64_t, 2> &out, esp_bt_uuid_t uuid_source) {
18
+ // Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB
19
+ // out[0] = bytes 8-15 (big-endian)
20
+ // - For 128-bit UUIDs: use bytes 8-15 as-is
21
+ // - For 16/32-bit UUIDs: insert into bytes 12-15, use 0x00001000 for bytes 8-11
22
+ out[0] = uuid_source.len == ESP_UUID_LEN_128
23
+ ? (((uint64_t) uuid_source.uuid.uuid128[15] << 56) | ((uint64_t) uuid_source.uuid.uuid128[14] << 48) |
24
+ ((uint64_t) uuid_source.uuid.uuid128[13] << 40) | ((uint64_t) uuid_source.uuid.uuid128[12] << 32) |
25
+ ((uint64_t) uuid_source.uuid.uuid128[11] << 24) | ((uint64_t) uuid_source.uuid.uuid128[10] << 16) |
26
+ ((uint64_t) uuid_source.uuid.uuid128[9] << 8) | ((uint64_t) uuid_source.uuid.uuid128[8]))
27
+ : (((uint64_t) (uuid_source.len == ESP_UUID_LEN_16 ? uuid_source.uuid.uuid16 : uuid_source.uuid.uuid32)
28
+ << 32) |
29
+ 0x00001000ULL); // Base UUID bytes 8-11
30
+ // out[1] = bytes 0-7 (big-endian)
31
+ // - For 128-bit UUIDs: use bytes 0-7 as-is
32
+ // - For 16/32-bit UUIDs: use precalculated base UUID constant
33
+ out[1] = uuid_source.len == ESP_UUID_LEN_128
34
+ ? ((uint64_t) uuid_source.uuid.uuid128[7] << 56) | ((uint64_t) uuid_source.uuid.uuid128[6] << 48) |
35
+ ((uint64_t) uuid_source.uuid.uuid128[5] << 40) | ((uint64_t) uuid_source.uuid.uuid128[4] << 32) |
36
+ ((uint64_t) uuid_source.uuid.uuid128[3] << 24) | ((uint64_t) uuid_source.uuid.uuid128[2] << 16) |
37
+ ((uint64_t) uuid_source.uuid.uuid128[1] << 8) | ((uint64_t) uuid_source.uuid.uuid128[0])
38
+ : 0x800000805F9B34FBULL; // Base UUID bytes 0-7: 80-00-00-80-5F-9B-34-FB
39
+ }
40
+
41
+ // Helper to fill UUID in the appropriate format based on client support and UUID type
42
+ static void fill_gatt_uuid(std::array<uint64_t, 2> &uuid_128, uint32_t &short_uuid, const esp_bt_uuid_t &uuid,
43
+ bool use_efficient_uuids) {
44
+ if (!use_efficient_uuids || uuid.len == ESP_UUID_LEN_128) {
45
+ // Use 128-bit format for old clients or when UUID is already 128-bit
46
+ fill_128bit_uuid_array(uuid_128, uuid);
47
+ } else if (uuid.len == ESP_UUID_LEN_16) {
48
+ short_uuid = uuid.uuid.uuid16;
49
+ } else if (uuid.len == ESP_UUID_LEN_32) {
50
+ short_uuid = uuid.uuid.uuid32;
51
+ }
52
+ }
53
+
54
+ // Constants for size estimation
55
+ static constexpr uint8_t SERVICE_OVERHEAD_LEGACY = 25; // UUID(20) + handle(4) + overhead(1)
56
+ static constexpr uint8_t SERVICE_OVERHEAD_EFFICIENT = 10; // UUID(6) + handle(4)
57
+ static constexpr uint8_t CHAR_SIZE_128BIT = 35; // UUID(20) + handle(4) + props(4) + overhead(7)
58
+ static constexpr uint8_t DESC_SIZE_128BIT = 25; // UUID(20) + handle(4) + overhead(1)
59
+ static constexpr uint8_t DESC_SIZE_16BIT = 10; // UUID(6) + handle(4)
60
+ static constexpr uint8_t DESC_PER_CHAR = 1; // Assume 1 descriptor per characteristic
61
+
62
+ // Helper to estimate service size before fetching all data
63
+ /**
64
+ * Estimate the size of a Bluetooth service based on the number of characteristics and UUID format.
65
+ *
66
+ * @param char_count The number of characteristics in the service.
67
+ * @param use_efficient_uuids Whether to use efficient UUIDs (16-bit or 32-bit) for newer APIVersions.
68
+ * @return The estimated size of the service in bytes.
69
+ *
70
+ * This function calculates the size of a Bluetooth service by considering:
71
+ * - A service overhead, which depends on whether efficient UUIDs are used.
72
+ * - The size of each characteristic, assuming 128-bit UUIDs for safety.
73
+ * - The size of descriptors, assuming one 128-bit descriptor per characteristic.
74
+ */
75
+ static size_t estimate_service_size(uint16_t char_count, bool use_efficient_uuids) {
76
+ size_t service_overhead = use_efficient_uuids ? SERVICE_OVERHEAD_EFFICIENT : SERVICE_OVERHEAD_LEGACY;
77
+ // Always assume 128-bit UUIDs for characteristics to be safe
78
+ size_t char_size = CHAR_SIZE_128BIT;
79
+ // Assume one 128-bit descriptor per characteristic
80
+ size_t desc_size = DESC_SIZE_128BIT * DESC_PER_CHAR;
81
+
82
+ return service_overhead + (char_size + desc_size) * char_count;
83
+ }
84
+
85
+ bool BluetoothConnection::supports_efficient_uuids_() const {
86
+ auto *api_conn = this->proxy_->get_api_connection();
87
+ return api_conn && api_conn->client_supports_api_version(1, 12);
88
+ }
89
+
16
90
  void BluetoothConnection::dump_config() {
17
91
  ESP_LOGCONFIG(TAG, "BLE Connection:");
18
92
  BLEClientBase::dump_config();
19
93
  }
20
94
 
95
+ void BluetoothConnection::update_allocated_slot_(uint64_t find_value, uint64_t set_value) {
96
+ auto &allocated = this->proxy_->connections_free_response_.allocated;
97
+ for (auto &slot : allocated) {
98
+ if (slot == find_value) {
99
+ slot = set_value;
100
+ return;
101
+ }
102
+ }
103
+ }
104
+
105
+ void BluetoothConnection::set_address(uint64_t address) {
106
+ // If we're clearing an address (disconnecting), update the pre-allocated message
107
+ if (address == 0 && this->address_ != 0) {
108
+ this->proxy_->connections_free_response_.free++;
109
+ this->update_allocated_slot_(this->address_, 0);
110
+ }
111
+ // If we're setting a new address (connecting), update the pre-allocated message
112
+ else if (address != 0 && this->address_ == 0) {
113
+ this->proxy_->connections_free_response_.free--;
114
+ this->update_allocated_slot_(0, address);
115
+ }
116
+
117
+ // Call parent implementation to actually set the address
118
+ BLEClientBase::set_address(address);
119
+ }
120
+
121
+ void BluetoothConnection::loop() {
122
+ BLEClientBase::loop();
123
+
124
+ // Early return if no active connection
125
+ if (this->address_ == 0) {
126
+ return;
127
+ }
128
+
129
+ // Handle service discovery if in valid range
130
+ if (this->send_service_ >= 0 && this->send_service_ <= this->service_count_) {
131
+ this->send_service_for_discovery_();
132
+ }
133
+
134
+ // Check if we should disable the loop
135
+ // - For V3_WITH_CACHE: Services are never sent, disable after INIT state
136
+ // - For V3_WITHOUT_CACHE: Disable only after service discovery is complete
137
+ // (send_service_ == DONE_SENDING_SERVICES, which is only set after services are sent)
138
+ if (this->state_ != espbt::ClientState::INIT && (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
139
+ this->send_service_ == DONE_SENDING_SERVICES)) {
140
+ this->disable_loop();
141
+ }
142
+ }
143
+
144
+ void BluetoothConnection::reset_connection_(esp_err_t reason) {
145
+ // Send disconnection notification
146
+ this->proxy_->send_device_connection(this->address_, false, 0, reason);
147
+
148
+ // Important: If we were in the middle of sending services, we do NOT send
149
+ // send_gatt_services_done() here. This ensures the client knows that
150
+ // the service discovery was interrupted and can retry. The client
151
+ // (aioesphomeapi) implements a 30-second timeout (DEFAULT_BLE_TIMEOUT)
152
+ // to detect incomplete service discovery rather than relying on us to
153
+ // tell them about a partial list.
154
+ this->set_address(0);
155
+ this->send_service_ = INIT_SENDING_SERVICES;
156
+ this->proxy_->send_connections_free();
157
+ }
158
+
159
+ void BluetoothConnection::send_service_for_discovery_() {
160
+ if (this->send_service_ >= this->service_count_) {
161
+ this->send_service_ = DONE_SENDING_SERVICES;
162
+ this->proxy_->send_gatt_services_done(this->address_);
163
+ this->release_services();
164
+ return;
165
+ }
166
+
167
+ // Early return if no API connection
168
+ auto *api_conn = this->proxy_->get_api_connection();
169
+ if (api_conn == nullptr) {
170
+ this->send_service_ = DONE_SENDING_SERVICES;
171
+ return;
172
+ }
173
+
174
+ // Check if client supports efficient UUIDs
175
+ bool use_efficient_uuids = this->supports_efficient_uuids_();
176
+
177
+ // Prepare response
178
+ api::BluetoothGATTGetServicesResponse resp;
179
+ resp.address = this->address_;
180
+
181
+ // Dynamic batching based on actual size
182
+ // Conservative MTU limit for API messages (accounts for WPA3 overhead)
183
+ static constexpr size_t MAX_PACKET_SIZE = 1360;
184
+
185
+ // Keep running total of actual message size
186
+ size_t current_size = 0;
187
+ api::ProtoSize size;
188
+ resp.calculate_size(size);
189
+ current_size = size.get_size();
190
+
191
+ while (this->send_service_ < this->service_count_) {
192
+ esp_gattc_service_elem_t service_result;
193
+ uint16_t service_count = 1;
194
+ esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->gattc_if_, this->conn_id_, nullptr,
195
+ &service_result, &service_count, this->send_service_);
196
+
197
+ if (service_status != ESP_GATT_OK || service_count == 0) {
198
+ ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
199
+ this->connection_index_, this->address_str().c_str(),
200
+ service_status != ESP_GATT_OK ? "error" : "missing", service_status, service_count, this->send_service_);
201
+ this->send_service_ = DONE_SENDING_SERVICES;
202
+ return;
203
+ }
204
+
205
+ // Get the number of characteristics BEFORE adding to response
206
+ uint16_t total_char_count = 0;
207
+ esp_gatt_status_t char_count_status =
208
+ esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_CHARACTERISTIC,
209
+ service_result.start_handle, service_result.end_handle, 0, &total_char_count);
210
+
211
+ if (char_count_status != ESP_GATT_OK) {
212
+ this->log_connection_error_("esp_ble_gattc_get_attr_count", char_count_status);
213
+ this->send_service_ = DONE_SENDING_SERVICES;
214
+ return;
215
+ }
216
+
217
+ // If this service likely won't fit, send current batch (unless it's the first)
218
+ size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
219
+ if (!resp.services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
220
+ // This service likely won't fit, send current batch
221
+ break;
222
+ }
223
+
224
+ // Now add the service since we know it will likely fit
225
+ resp.services.emplace_back();
226
+ auto &service_resp = resp.services.back();
227
+
228
+ fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
229
+
230
+ service_resp.handle = service_result.start_handle;
231
+
232
+ if (total_char_count > 0) {
233
+ // Reserve space and process characteristics
234
+ service_resp.characteristics.reserve(total_char_count);
235
+ uint16_t char_offset = 0;
236
+ esp_gattc_char_elem_t char_result;
237
+ while (true) { // characteristics
238
+ uint16_t char_count = 1;
239
+ esp_gatt_status_t char_status =
240
+ esp_ble_gattc_get_all_char(this->gattc_if_, this->conn_id_, service_result.start_handle,
241
+ service_result.end_handle, &char_result, &char_count, char_offset);
242
+ if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
243
+ break;
244
+ }
245
+ if (char_status != ESP_GATT_OK) {
246
+ this->log_connection_error_("esp_ble_gattc_get_all_char", char_status);
247
+ this->send_service_ = DONE_SENDING_SERVICES;
248
+ return;
249
+ }
250
+ if (char_count == 0) {
251
+ break;
252
+ }
253
+
254
+ service_resp.characteristics.emplace_back();
255
+ auto &characteristic_resp = service_resp.characteristics.back();
256
+
257
+ fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
258
+
259
+ characteristic_resp.handle = char_result.char_handle;
260
+ characteristic_resp.properties = char_result.properties;
261
+ char_offset++;
262
+
263
+ // Get the number of descriptors directly with one call
264
+ uint16_t total_desc_count = 0;
265
+ esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
266
+ this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
267
+
268
+ if (desc_count_status != ESP_GATT_OK) {
269
+ this->log_connection_error_("esp_ble_gattc_get_attr_count", desc_count_status);
270
+ this->send_service_ = DONE_SENDING_SERVICES;
271
+ return;
272
+ }
273
+ if (total_desc_count == 0) {
274
+ // No descriptors, continue to next characteristic
275
+ continue;
276
+ }
277
+
278
+ // Reserve space and process descriptors
279
+ characteristic_resp.descriptors.reserve(total_desc_count);
280
+ uint16_t desc_offset = 0;
281
+ esp_gattc_descr_elem_t desc_result;
282
+ while (true) { // descriptors
283
+ uint16_t desc_count = 1;
284
+ esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
285
+ this->gattc_if_, this->conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
286
+ if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
287
+ break;
288
+ }
289
+ if (desc_status != ESP_GATT_OK) {
290
+ this->log_connection_error_("esp_ble_gattc_get_all_descr", desc_status);
291
+ this->send_service_ = DONE_SENDING_SERVICES;
292
+ return;
293
+ }
294
+ if (desc_count == 0) {
295
+ break; // No more descriptors
296
+ }
297
+
298
+ characteristic_resp.descriptors.emplace_back();
299
+ auto &descriptor_resp = characteristic_resp.descriptors.back();
300
+
301
+ fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
302
+
303
+ descriptor_resp.handle = desc_result.handle;
304
+ desc_offset++;
305
+ }
306
+ }
307
+ } // end if (total_char_count > 0)
308
+
309
+ // Calculate the actual size of just this service
310
+ api::ProtoSize service_sizer;
311
+ service_resp.calculate_size(service_sizer);
312
+ size_t service_size = service_sizer.get_size() + 1; // +1 for field tag
313
+
314
+ // Check if adding this service would exceed the limit
315
+ if (current_size + service_size > MAX_PACKET_SIZE) {
316
+ // We would go over - pop the last service if we have more than one
317
+ if (resp.services.size() > 1) {
318
+ resp.services.pop_back();
319
+ ESP_LOGD(TAG, "[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
320
+ this->connection_index_, this->address_str().c_str(), this->send_service_, current_size, service_size,
321
+ MAX_PACKET_SIZE);
322
+ // Don't increment send_service_ - we'll retry this service in next batch
323
+ } else {
324
+ // This single service is too large, but we have to send it anyway
325
+ ESP_LOGV(TAG, "[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->connection_index_,
326
+ this->address_str().c_str(), this->send_service_, service_size);
327
+ // Increment so we don't get stuck
328
+ this->send_service_++;
329
+ }
330
+ // Send what we have
331
+ break;
332
+ }
333
+
334
+ // Now we know we're keeping this service, add its size
335
+ current_size += service_size;
336
+ // Successfully added this service, increment counter
337
+ this->send_service_++;
338
+ }
339
+
340
+ // Send the message with dynamically batched services
341
+ api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE);
342
+ }
343
+
344
+ void BluetoothConnection::log_connection_error_(const char *operation, esp_gatt_status_t status) {
345
+ ESP_LOGE(TAG, "[%d] [%s] %s error, status=%d", this->connection_index_, this->address_str().c_str(), operation,
346
+ status);
347
+ }
348
+
349
+ void BluetoothConnection::log_connection_warning_(const char *operation, esp_err_t err) {
350
+ ESP_LOGW(TAG, "[%d] [%s] %s failed, err=%d", this->connection_index_, this->address_str().c_str(), operation, err);
351
+ }
352
+
353
+ void BluetoothConnection::log_gatt_not_connected_(const char *action, const char *type) {
354
+ ESP_LOGW(TAG, "[%d] [%s] Cannot %s GATT %s, not connected.", this->connection_index_, this->address_str().c_str(),
355
+ action, type);
356
+ }
357
+
358
+ void BluetoothConnection::log_gatt_operation_error_(const char *operation, uint16_t handle, esp_gatt_status_t status) {
359
+ ESP_LOGW(TAG, "[%d] [%s] Error %s for handle 0x%2X, status=%d", this->connection_index_, this->address_str().c_str(),
360
+ operation, handle, status);
361
+ }
362
+
363
+ esp_err_t BluetoothConnection::check_and_log_error_(const char *operation, esp_err_t err) {
364
+ if (err != ESP_OK) {
365
+ this->log_connection_warning_(operation, err);
366
+ return err;
367
+ }
368
+ return ESP_OK;
369
+ }
370
+
21
371
  bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
22
372
  esp_ble_gattc_cb_param_t *param) {
23
373
  if (!BLEClientBase::gattc_event_handler(event, gattc_if, param))
@@ -25,22 +375,25 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
25
375
 
26
376
  switch (event) {
27
377
  case ESP_GATTC_DISCONNECT_EVT: {
378
+ // Don't reset connection yet - wait for CLOSE_EVT to ensure controller has freed resources
379
+ // This prevents race condition where we mark slot as free before controller cleanup is complete
380
+ ESP_LOGD(TAG, "[%d] [%s] Disconnect, reason=0x%02x", this->connection_index_, this->address_str_.c_str(),
381
+ param->disconnect.reason);
382
+ // Send disconnection notification but don't free the slot yet
28
383
  this->proxy_->send_device_connection(this->address_, false, 0, param->disconnect.reason);
29
- this->set_address(0);
30
- this->proxy_->send_connections_free();
31
384
  break;
32
385
  }
33
386
  case ESP_GATTC_CLOSE_EVT: {
34
- this->proxy_->send_device_connection(this->address_, false, 0, param->close.reason);
35
- this->set_address(0);
36
- this->proxy_->send_connections_free();
387
+ ESP_LOGD(TAG, "[%d] [%s] Close, reason=0x%02x, freeing slot", this->connection_index_, this->address_str_.c_str(),
388
+ param->close.reason);
389
+ // Now the GATT connection is fully closed and controller resources are freed
390
+ // Safe to mark the connection slot as available
391
+ this->reset_connection_(param->close.reason);
37
392
  break;
38
393
  }
39
394
  case ESP_GATTC_OPEN_EVT: {
40
395
  if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
41
- this->proxy_->send_device_connection(this->address_, false, 0, param->open.status);
42
- this->set_address(0);
43
- this->proxy_->send_connections_free();
396
+ this->reset_connection_(param->open.status);
44
397
  } else if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
45
398
  this->proxy_->send_device_connection(this->address_, true, this->mtu_);
46
399
  this->proxy_->send_connections_free();
@@ -64,59 +417,54 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
64
417
  case ESP_GATTC_READ_DESCR_EVT:
65
418
  case ESP_GATTC_READ_CHAR_EVT: {
66
419
  if (param->read.status != ESP_GATT_OK) {
67
- ESP_LOGW(TAG, "[%d] [%s] Error reading char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
68
- this->address_str_.c_str(), param->read.handle, param->read.status);
420
+ this->log_gatt_operation_error_("reading char/descriptor", param->read.handle, param->read.status);
69
421
  this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status);
70
422
  break;
71
423
  }
72
424
  api::BluetoothGATTReadResponse resp;
73
425
  resp.address = this->address_;
74
426
  resp.handle = param->read.handle;
75
- resp.data.reserve(param->read.value_len);
76
- // Use bulk insert instead of individual push_backs
77
- resp.data.insert(resp.data.end(), param->read.value, param->read.value + param->read.value_len);
78
- this->proxy_->get_api_connection()->send_message(resp);
427
+ resp.set_data(param->read.value, param->read.value_len);
428
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE);
79
429
  break;
80
430
  }
81
431
  case ESP_GATTC_WRITE_CHAR_EVT:
82
432
  case ESP_GATTC_WRITE_DESCR_EVT: {
83
433
  if (param->write.status != ESP_GATT_OK) {
84
- ESP_LOGW(TAG, "[%d] [%s] Error writing char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
85
- this->address_str_.c_str(), param->write.handle, param->write.status);
434
+ this->log_gatt_operation_error_("writing char/descriptor", param->write.handle, param->write.status);
86
435
  this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status);
87
436
  break;
88
437
  }
89
438
  api::BluetoothGATTWriteResponse resp;
90
439
  resp.address = this->address_;
91
440
  resp.handle = param->write.handle;
92
- this->proxy_->get_api_connection()->send_message(resp);
441
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE);
93
442
  break;
94
443
  }
95
444
  case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
96
445
  if (param->unreg_for_notify.status != ESP_GATT_OK) {
97
- ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
98
- this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
99
- param->unreg_for_notify.status);
446
+ this->log_gatt_operation_error_("unregistering notifications", param->unreg_for_notify.handle,
447
+ param->unreg_for_notify.status);
100
448
  this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status);
101
449
  break;
102
450
  }
103
451
  api::BluetoothGATTNotifyResponse resp;
104
452
  resp.address = this->address_;
105
453
  resp.handle = param->unreg_for_notify.handle;
106
- this->proxy_->get_api_connection()->send_message(resp);
454
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
107
455
  break;
108
456
  }
109
457
  case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
110
458
  if (param->reg_for_notify.status != ESP_GATT_OK) {
111
- ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
112
- this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
459
+ this->log_gatt_operation_error_("registering notifications", param->reg_for_notify.handle,
460
+ param->reg_for_notify.status);
113
461
  this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status);
114
462
  break;
115
463
  }
116
464
  api::BluetoothGATTNotifyResponse resp;
117
465
  resp.address = this->address_;
118
466
  resp.handle = param->reg_for_notify.handle;
119
- this->proxy_->get_api_connection()->send_message(resp);
467
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
120
468
  break;
121
469
  }
122
470
  case ESP_GATTC_NOTIFY_EVT: {
@@ -125,10 +473,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
125
473
  api::BluetoothGATTNotifyDataResponse resp;
126
474
  resp.address = this->address_;
127
475
  resp.handle = param->notify.handle;
128
- resp.data.reserve(param->notify.value_len);
129
- // Use bulk insert instead of individual push_backs
130
- resp.data.insert(resp.data.end(), param->notify.value, param->notify.value + param->notify.value_len);
131
- this->proxy_->get_api_connection()->send_message(resp);
476
+ resp.set_data(param->notify.value, param->notify.value_len);
477
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE);
132
478
  break;
133
479
  }
134
480
  default:
@@ -157,8 +503,7 @@ void BluetoothConnection::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
157
503
 
158
504
  esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
159
505
  if (!this->connected()) {
160
- ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not connected.", this->connection_index_,
161
- this->address_str_.c_str());
506
+ this->log_gatt_not_connected_("read", "characteristic");
162
507
  return ESP_GATT_NOT_CONNECTED;
163
508
  }
164
509
 
@@ -166,18 +511,12 @@ esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
166
511
  handle);
167
512
 
168
513
  esp_err_t err = esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
169
- if (err != ERR_OK) {
170
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
171
- this->address_str_.c_str(), err);
172
- return err;
173
- }
174
- return ESP_OK;
514
+ return this->check_and_log_error_("esp_ble_gattc_read_char", err);
175
515
  }
176
516
 
177
517
  esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::string &data, bool response) {
178
518
  if (!this->connected()) {
179
- ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not connected.", this->connection_index_,
180
- this->address_str_.c_str());
519
+ this->log_gatt_not_connected_("write", "characteristic");
181
520
  return ESP_GATT_NOT_CONNECTED;
182
521
  }
183
522
  ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -186,36 +525,24 @@ esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::
186
525
  esp_err_t err =
187
526
  esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
188
527
  response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
189
- if (err != ERR_OK) {
190
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
191
- this->address_str_.c_str(), err);
192
- return err;
193
- }
194
- return ESP_OK;
528
+ return this->check_and_log_error_("esp_ble_gattc_write_char", err);
195
529
  }
196
530
 
197
531
  esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
198
532
  if (!this->connected()) {
199
- ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not connected.", this->connection_index_,
200
- this->address_str_.c_str());
533
+ this->log_gatt_not_connected_("read", "descriptor");
201
534
  return ESP_GATT_NOT_CONNECTED;
202
535
  }
203
536
  ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
204
537
  handle);
205
538
 
206
539
  esp_err_t err = esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
207
- if (err != ERR_OK) {
208
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
209
- this->address_str_.c_str(), err);
210
- return err;
211
- }
212
- return ESP_OK;
540
+ return this->check_and_log_error_("esp_ble_gattc_read_char_descr", err);
213
541
  }
214
542
 
215
543
  esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
216
544
  if (!this->connected()) {
217
- ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
218
- this->address_str_.c_str());
545
+ this->log_gatt_not_connected_("write", "descriptor");
219
546
  return ESP_GATT_NOT_CONNECTED;
220
547
  }
221
548
  ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -224,18 +551,12 @@ esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::stri
224
551
  esp_err_t err = esp_ble_gattc_write_char_descr(
225
552
  this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
226
553
  response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
227
- if (err != ERR_OK) {
228
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
229
- this->address_str_.c_str(), err);
230
- return err;
231
- }
232
- return ESP_OK;
554
+ return this->check_and_log_error_("esp_ble_gattc_write_char_descr", err);
233
555
  }
234
556
 
235
557
  esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enable) {
236
558
  if (!this->connected()) {
237
- ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not connected.", this->connection_index_,
238
- this->address_str_.c_str());
559
+ this->log_gatt_not_connected_("notify", "characteristic");
239
560
  return ESP_GATT_NOT_CONNECTED;
240
561
  }
241
562
 
@@ -243,29 +564,19 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl
243
564
  ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
244
565
  this->address_str_.c_str(), handle);
245
566
  esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, handle);
246
- if (err != ESP_OK) {
247
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
248
- this->address_str_.c_str(), err);
249
- return err;
250
- }
251
- } else {
252
- ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
253
- this->address_str_.c_str(), handle);
254
- esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
255
- if (err != ESP_OK) {
256
- ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
257
- this->address_str_.c_str(), err);
258
- return err;
259
- }
567
+ return this->check_and_log_error_("esp_ble_gattc_register_for_notify", err);
260
568
  }
261
- return ESP_OK;
569
+
570
+ ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
571
+ this->address_str_.c_str(), handle);
572
+ esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
573
+ return this->check_and_log_error_("esp_ble_gattc_unregister_for_notify", err);
262
574
  }
263
575
 
264
576
  esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() {
265
577
  return this->proxy_->get_advertisement_parser_type();
266
578
  }
267
579
 
268
- } // namespace bluetooth_proxy
269
- } // namespace esphome
580
+ } // namespace esphome::bluetooth_proxy
270
581
 
271
582
  #endif // USE_ESP32
@@ -4,14 +4,14 @@
4
4
 
5
5
  #include "esphome/components/esp32_ble_client/ble_client_base.h"
6
6
 
7
- namespace esphome {
8
- namespace bluetooth_proxy {
7
+ namespace esphome::bluetooth_proxy {
9
8
 
10
9
  class BluetoothProxy;
11
10
 
12
11
  class BluetoothConnection : public esp32_ble_client::BLEClientBase {
13
12
  public:
14
13
  void dump_config() override;
14
+ void loop() override;
15
15
  bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
16
16
  esp_ble_gattc_cb_param_t *param) override;
17
17
  void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
@@ -24,22 +24,33 @@ class BluetoothConnection : public esp32_ble_client::BLEClientBase {
24
24
 
25
25
  esp_err_t notify_characteristic(uint16_t handle, bool enable);
26
26
 
27
+ void set_address(uint64_t address) override;
28
+
27
29
  protected:
28
30
  friend class BluetoothProxy;
29
31
 
32
+ bool supports_efficient_uuids_() const;
33
+ void send_service_for_discovery_();
34
+ void reset_connection_(esp_err_t reason);
35
+ void update_allocated_slot_(uint64_t find_value, uint64_t set_value);
36
+ void log_connection_error_(const char *operation, esp_gatt_status_t status);
37
+ void log_connection_warning_(const char *operation, esp_err_t err);
38
+ void log_gatt_not_connected_(const char *action, const char *type);
39
+ void log_gatt_operation_error_(const char *operation, uint16_t handle, esp_gatt_status_t status);
40
+ esp_err_t check_and_log_error_(const char *operation, esp_err_t err);
41
+
30
42
  // Memory optimized layout for 32-bit systems
31
43
  // Group 1: Pointers (4 bytes each, naturally aligned)
32
44
  BluetoothProxy *proxy_;
33
45
 
34
46
  // Group 2: 2-byte types
35
- int16_t send_service_{-2}; // Needs to handle negative values and service count
47
+ int16_t send_service_{-3}; // -3 = INIT_SENDING_SERVICES, -2 = DONE_SENDING_SERVICES, >=0 = service index
36
48
 
37
49
  // Group 3: 1-byte types
38
50
  bool seen_mtu_or_services_{false};
39
51
  // 1 byte used, 1 byte padding
40
52
  };
41
53
 
42
- } // namespace bluetooth_proxy
43
- } // namespace esphome
54
+ } // namespace esphome::bluetooth_proxy
44
55
 
45
56
  #endif // USE_ESP32