esphome 2025.7.4__py3-none-any.whl → 2025.8.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 (754) hide show
  1. esphome/__main__.py +189 -82
  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 +112 -56
  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 +488 -118
  73. esphome/components/atm90e32/atm90e32.h +44 -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 +387 -82
  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 +199 -58
  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 +40 -2
  149. esphome/components/esp32_ble/ble.cpp +12 -8
  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 +2 -4
  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/font/__init__.py +9 -1
  209. esphome/components/fs3000/fs3000.cpp +0 -2
  210. esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
  211. esphome/components/ft63x6/ft63x6.cpp +0 -1
  212. esphome/components/gdk101/gdk101.cpp +0 -1
  213. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
  214. esphome/components/gl_r01_i2c/sensor.py +1 -1
  215. esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
  216. esphome/components/gpio/switch/gpio_switch.cpp +0 -2
  217. esphome/components/gpio_expander/cached_gpio.h +24 -15
  218. esphome/components/gps/__init__.py +6 -2
  219. esphome/components/gps/gps.cpp +50 -49
  220. esphome/components/gps/gps.h +4 -8
  221. esphome/components/gps/time/gps_time.cpp +3 -9
  222. esphome/components/gps/time/gps_time.h +4 -7
  223. esphome/components/graph/__init__.py +1 -1
  224. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
  225. esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
  226. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
  227. esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
  228. esphome/components/haier/climate.py +5 -10
  229. esphome/components/haier/haier_base.cpp +0 -1
  230. esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
  231. esphome/components/hdc1080/hdc1080.cpp +0 -2
  232. esphome/components/heatpumpir/climate.py +2 -2
  233. esphome/components/hlw8012/hlw8012.cpp +0 -1
  234. esphome/components/hm3301/hm3301.cpp +0 -1
  235. esphome/components/hmc5883l/hmc5883l.cpp +0 -1
  236. esphome/components/homeassistant/__init__.py +1 -0
  237. esphome/components/homeassistant/number/__init__.py +1 -0
  238. esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
  239. esphome/components/homeassistant/switch/__init__.py +1 -0
  240. esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
  241. esphome/components/honeywellabp/honeywellabp.cpp +1 -4
  242. esphome/components/host/__init__.py +2 -0
  243. esphome/components/hte501/hte501.cpp +0 -1
  244. esphome/components/http_request/__init__.py +2 -3
  245. esphome/components/http_request/http_request_idf.cpp +2 -2
  246. esphome/components/htu21d/htu21d.cpp +0 -2
  247. esphome/components/htu31d/htu31d.cpp +0 -2
  248. esphome/components/hx711/hx711.cpp +0 -1
  249. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
  250. esphome/components/hydreon_rgxx/sensor.py +4 -5
  251. esphome/components/i2c/i2c_bus.h +1 -1
  252. esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
  253. esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
  254. esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
  255. esphome/components/i2s_audio/__init__.py +6 -5
  256. esphome/components/i2s_audio/i2s_audio.cpp +0 -2
  257. esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
  258. esphome/components/i2s_audio/microphone/__init__.py +4 -6
  259. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +46 -19
  260. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -3
  261. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
  262. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
  263. esphome/components/ili9xxx/display.py +4 -3
  264. esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
  265. esphome/components/image/__init__.py +123 -92
  266. esphome/components/improv_serial/__init__.py +7 -8
  267. esphome/components/ina219/ina219.cpp +0 -1
  268. esphome/components/ina226/ina226.cpp +0 -2
  269. esphome/components/ina260/ina260.cpp +0 -2
  270. esphome/components/ina2xx_base/__init__.py +2 -5
  271. esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
  272. esphome/components/ina3221/ina3221.cpp +0 -1
  273. esphome/components/internal_temperature/internal_temperature.cpp +0 -2
  274. esphome/components/interval/interval.h +5 -9
  275. esphome/components/json/__init__.py +1 -1
  276. esphome/components/kmeteriso/kmeteriso.cpp +0 -2
  277. esphome/components/lc709203f/lc709203f.cpp +0 -2
  278. esphome/components/lcd_gpio/display.py +1 -3
  279. esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
  280. esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
  281. esphome/components/ld2410/__init__.py +4 -6
  282. esphome/components/ld2410/binary_sensor.py +4 -0
  283. esphome/components/ld2410/ld2410.cpp +56 -100
  284. esphome/components/ld2410/ld2410.h +17 -15
  285. esphome/components/ld2410/sensor.py +24 -10
  286. esphome/components/ld2412/__init__.py +46 -0
  287. esphome/components/ld2412/binary_sensor.py +70 -0
  288. esphome/components/ld2412/button/__init__.py +74 -0
  289. esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
  290. esphome/components/ld2412/button/factory_reset_button.h +18 -0
  291. esphome/components/ld2412/button/query_button.cpp +9 -0
  292. esphome/components/ld2412/button/query_button.h +18 -0
  293. esphome/components/ld2412/button/restart_button.cpp +9 -0
  294. esphome/components/ld2412/button/restart_button.h +18 -0
  295. esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
  296. esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
  297. esphome/components/ld2412/ld2412.cpp +861 -0
  298. esphome/components/ld2412/ld2412.h +141 -0
  299. esphome/components/ld2412/number/__init__.py +126 -0
  300. esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
  301. esphome/components/ld2412/number/gate_threshold_number.h +19 -0
  302. esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
  303. esphome/components/ld2412/number/light_threshold_number.h +18 -0
  304. esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
  305. esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
  306. esphome/components/ld2412/select/__init__.py +82 -0
  307. esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
  308. esphome/components/ld2412/select/baud_rate_select.h +18 -0
  309. esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
  310. esphome/components/ld2412/select/distance_resolution_select.h +18 -0
  311. esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
  312. esphome/components/ld2412/select/light_out_control_select.h +18 -0
  313. esphome/components/ld2412/sensor.py +124 -0
  314. esphome/components/ld2412/switch/__init__.py +45 -0
  315. esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
  316. esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
  317. esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
  318. esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
  319. esphome/components/ld2412/text_sensor.py +34 -0
  320. esphome/components/ld2420/ld2420.cpp +0 -1
  321. esphome/components/ld2450/__init__.py +3 -4
  322. esphome/components/ld2450/binary_sensor.py +3 -0
  323. esphome/components/ld2450/ld2450.cpp +77 -165
  324. esphome/components/ld2450/ld2450.h +26 -54
  325. esphome/components/ld2450/sensor.py +120 -6
  326. esphome/components/ld2450/text_sensor.py +5 -4
  327. esphome/components/ld24xx/__init__.py +1 -0
  328. esphome/components/ld24xx/ld24xx.h +65 -0
  329. esphome/components/ledc/ledc_output.cpp +0 -1
  330. esphome/components/libretiny/__init__.py +2 -0
  331. esphome/components/light/__init__.py +0 -1
  332. esphome/components/light/effects.py +70 -45
  333. esphome/components/light/light_call.cpp +101 -66
  334. esphome/components/light/light_color_values.h +16 -11
  335. esphome/components/light/light_json_schema.cpp +46 -44
  336. esphome/components/light/light_state.cpp +8 -11
  337. esphome/components/light/light_traits.h +17 -0
  338. esphome/components/lightwaverf/lightwaverf.cpp +0 -2
  339. esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
  340. esphome/components/lock/__init__.py +0 -1
  341. esphome/components/logger/__init__.py +31 -9
  342. esphome/components/logger/logger.cpp +12 -7
  343. esphome/components/logger/logger.h +25 -14
  344. esphome/components/logger/logger_esp32.cpp +2 -7
  345. esphome/components/logger/logger_esp8266.cpp +2 -4
  346. esphome/components/logger/logger_host.cpp +2 -4
  347. esphome/components/logger/logger_libretiny.cpp +2 -4
  348. esphome/components/logger/logger_rp2040.cpp +2 -4
  349. esphome/components/logger/logger_zephyr.cpp +86 -0
  350. esphome/components/logger/select/logger_level_select.cpp +2 -4
  351. esphome/components/logger/select/logger_level_select.h +2 -4
  352. esphome/components/logger/task_log_buffer.cpp +2 -4
  353. esphome/components/logger/task_log_buffer.h +2 -4
  354. esphome/components/lps22/sensor.py +5 -5
  355. esphome/components/ltr390/ltr390.cpp +0 -2
  356. esphome/components/ltr501/ltr501.cpp +0 -1
  357. esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
  358. esphome/components/lvgl/__init__.py +14 -13
  359. esphome/components/lvgl/automation.py +2 -4
  360. esphome/components/lvgl/defines.py +0 -2
  361. esphome/components/lvgl/helpers.py +1 -1
  362. esphome/components/lvgl/lv_validation.py +7 -4
  363. esphome/components/lvgl/lvgl_esphome.cpp +2 -3
  364. esphome/components/lvgl/styles.py +2 -2
  365. esphome/components/lvgl/types.py +1 -1
  366. esphome/components/lvgl/widgets/__init__.py +2 -2
  367. esphome/components/lvgl/widgets/arc.py +14 -11
  368. esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
  369. esphome/components/lvgl/widgets/qrcode.py +7 -7
  370. esphome/components/lvgl/widgets/spinner.py +6 -6
  371. esphome/components/lvgl/widgets/switch.py +2 -2
  372. esphome/components/lvgl/widgets/tabview.py +3 -3
  373. esphome/components/lvgl/widgets/tileview.py +15 -7
  374. esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
  375. esphome/components/matrix_keypad/__init__.py +4 -3
  376. esphome/components/max17043/max17043.cpp +0 -2
  377. esphome/components/max31855/max31855.cpp +1 -4
  378. esphome/components/max31856/max31856.cpp +0 -4
  379. esphome/components/max31865/max31865.cpp +0 -1
  380. esphome/components/max44009/max44009.cpp +0 -1
  381. esphome/components/max6675/max6675.cpp +1 -4
  382. esphome/components/max6956/max6956.cpp +0 -1
  383. esphome/components/max7219/max7219.cpp +0 -1
  384. esphome/components/max7219digit/display.py +1 -1
  385. esphome/components/max7219digit/max7219digit.cpp +0 -1
  386. esphome/components/max9611/max9611.cpp +0 -1
  387. esphome/components/mcp23008/__init__.py +1 -1
  388. esphome/components/mcp23008/mcp23008.cpp +0 -1
  389. esphome/components/mcp23016/mcp23016.cpp +0 -1
  390. esphome/components/mcp23017/__init__.py +1 -1
  391. esphome/components/mcp23017/mcp23017.cpp +0 -1
  392. esphome/components/mcp23s08/__init__.py +1 -1
  393. esphome/components/mcp23s08/mcp23s08.cpp +0 -1
  394. esphome/components/mcp23s17/__init__.py +1 -1
  395. esphome/components/mcp23s17/mcp23s17.cpp +0 -1
  396. esphome/components/mcp23x08_base/__init__.py +2 -0
  397. esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
  398. esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
  399. esphome/components/mcp23x17_base/__init__.py +2 -0
  400. esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
  401. esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
  402. esphome/components/mcp23xxx_base/__init__.py +11 -5
  403. esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
  404. esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
  405. esphome/components/mcp3008/mcp3008.cpp +1 -4
  406. esphome/components/mcp3204/mcp3204.cpp +1 -4
  407. esphome/components/mcp4461/mcp4461.cpp +0 -1
  408. esphome/components/mcp4725/mcp4725.cpp +0 -1
  409. esphome/components/mcp4728/mcp4728.cpp +0 -1
  410. esphome/components/mcp9600/mcp9600.cpp +0 -2
  411. esphome/components/mcp9808/mcp9808.cpp +0 -2
  412. esphome/components/mdns/__init__.py +3 -0
  413. esphome/components/mdns/mdns_component.cpp +2 -0
  414. esphome/components/mdns/mdns_component.h +4 -0
  415. esphome/components/media_player/__init__.py +40 -0
  416. esphome/components/media_player/automation.h +16 -0
  417. esphome/components/media_player/media_player.cpp +13 -0
  418. esphome/components/media_player/media_player.h +50 -3
  419. esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
  420. esphome/components/mics_4514/mics_4514.cpp +1 -6
  421. esphome/components/midea/ir_transmitter.h +4 -4
  422. esphome/components/mipi/__init__.py +416 -0
  423. esphome/components/mipi_dsi/__init__.py +5 -0
  424. esphome/components/mipi_dsi/display.py +233 -0
  425. esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
  426. esphome/components/mipi_dsi/mipi_dsi.h +123 -0
  427. esphome/components/mipi_dsi/models/__init__.py +0 -0
  428. esphome/components/mipi_dsi/models/guition.py +38 -0
  429. esphome/components/mipi_dsi/models/m5stack.py +57 -0
  430. esphome/components/mipi_dsi/models/waveshare.py +105 -0
  431. esphome/components/mipi_rgb/models/lilygo.py +0 -0
  432. esphome/components/mipi_spi/__init__.py +0 -9
  433. esphome/components/mipi_spi/display.py +220 -256
  434. esphome/components/mipi_spi/mipi_spi.cpp +1 -485
  435. esphome/components/mipi_spi/mipi_spi.h +556 -108
  436. esphome/components/mipi_spi/models/__init__.py +0 -65
  437. esphome/components/mipi_spi/models/adafruit.py +30 -0
  438. esphome/components/mipi_spi/models/amoled.py +41 -5
  439. esphome/components/mipi_spi/models/ili.py +5 -5
  440. esphome/components/mipi_spi/models/jc.py +1 -3
  441. esphome/components/mipi_spi/models/lilygo.py +1 -1
  442. esphome/components/mipi_spi/models/waveshare.py +16 -1
  443. esphome/components/mixer/speaker/__init__.py +4 -5
  444. esphome/components/mlx90393/sensor.py +7 -5
  445. esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
  446. esphome/components/mlx90614/mlx90614.cpp +0 -1
  447. esphome/components/mmc5603/mmc5603.cpp +0 -1
  448. esphome/components/mmc5983/mmc5983.cpp +0 -2
  449. esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
  450. esphome/components/mpr121/__init__.py +7 -6
  451. esphome/components/mpr121/mpr121.cpp +0 -1
  452. esphome/components/mpu6050/mpu6050.cpp +0 -1
  453. esphome/components/mpu6886/mpu6886.cpp +0 -1
  454. esphome/components/mqtt/__init__.py +1 -2
  455. esphome/components/mqtt/mqtt_button.cpp +1 -1
  456. esphome/components/mqtt/mqtt_client.cpp +0 -1
  457. esphome/components/mqtt/mqtt_component.cpp +8 -14
  458. esphome/components/mqtt/mqtt_component.h +0 -7
  459. esphome/components/mqtt/mqtt_sensor.cpp +0 -1
  460. esphome/components/mqtt/mqtt_sensor.h +0 -1
  461. esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
  462. esphome/components/mqtt/mqtt_text_sensor.h +0 -1
  463. esphome/components/ms5611/ms5611.cpp +0 -1
  464. esphome/components/ms8607/ms8607.cpp +0 -1
  465. esphome/components/msa3xx/msa3xx.cpp +0 -2
  466. esphome/components/my9231/my9231.cpp +0 -2
  467. esphome/components/nau7802/nau7802.cpp +0 -1
  468. esphome/components/neopixelbus/light.py +3 -0
  469. esphome/components/network/util.cpp +29 -0
  470. esphome/components/nextion/nextion.cpp +0 -1
  471. esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
  472. esphome/components/npi19/npi19.cpp +0 -2
  473. esphome/components/nrf52/__init__.py +223 -0
  474. esphome/components/nrf52/boards.py +34 -0
  475. esphome/components/nrf52/const.py +18 -0
  476. esphome/components/nrf52/gpio.py +79 -0
  477. esphome/components/number/__init__.py +2 -1
  478. esphome/components/one_wire/__init__.py +1 -2
  479. esphome/components/one_wire/one_wire.cpp +0 -2
  480. esphome/components/one_wire/one_wire.h +0 -2
  481. esphome/components/opentherm/hub.cpp +0 -1
  482. esphome/components/opentherm/number/__init__.py +2 -2
  483. esphome/components/openthread/__init__.py +2 -3
  484. esphome/components/openthread/openthread.cpp +30 -13
  485. esphome/components/openthread/openthread.h +3 -0
  486. esphome/components/openthread/openthread_esp.cpp +3 -1
  487. esphome/components/opt3001/sensor.py +2 -6
  488. esphome/components/output/__init__.py +38 -0
  489. esphome/components/output/automation.h +24 -0
  490. esphome/components/output/switch/output_switch.cpp +0 -2
  491. esphome/components/packages/__init__.py +1 -2
  492. esphome/components/packet_transport/__init__.py +4 -3
  493. esphome/components/pca6416a/pca6416a.cpp +0 -1
  494. esphome/components/pca9554/pca9554.cpp +0 -1
  495. esphome/components/pca9685/pca9685_output.cpp +0 -2
  496. esphome/components/pcf85063/pcf85063.cpp +0 -1
  497. esphome/components/pcf8563/pcf8563.cpp +0 -1
  498. esphome/components/pcf8574/pcf8574.cpp +0 -1
  499. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
  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 +2 -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/sensor/__init__.py +36 -4
  557. esphome/components/sensor/filter.cpp +49 -10
  558. esphome/components/sensor/filter.h +22 -7
  559. esphome/components/sensor/sensor.cpp +0 -1
  560. esphome/components/sensor/sensor.h +0 -9
  561. esphome/components/sfa30/sfa30.cpp +0 -4
  562. esphome/components/sgp30/sgp30.cpp +0 -2
  563. esphome/components/sgp4x/sensor.py +1 -1
  564. esphome/components/sgp4x/sgp4x.cpp +0 -2
  565. esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
  566. esphome/components/sht3xd/sht3xd.cpp +0 -2
  567. esphome/components/sht4x/sht4x.cpp +0 -2
  568. esphome/components/shtcx/shtcx.cpp +0 -1
  569. esphome/components/sim800l/__init__.py +2 -4
  570. esphome/components/sm16716/sm16716.cpp +0 -1
  571. esphome/components/sm2135/sm2135.cpp +0 -1
  572. esphome/components/sm2235/sm2235.cpp +0 -1
  573. esphome/components/sm2335/sm2335.cpp +0 -1
  574. esphome/components/sn74hc165/sn74hc165.cpp +0 -1
  575. esphome/components/sn74hc595/sn74hc595.cpp +0 -1
  576. esphome/components/sntp/sntp_component.cpp +0 -1
  577. esphome/components/sound_level/sensor.py +1 -1
  578. esphome/components/speaker/media_player/__init__.py +21 -33
  579. esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
  580. esphome/components/spi/__init__.py +29 -13
  581. esphome/components/spi/spi.cpp +0 -2
  582. esphome/components/spi_device/spi_device.cpp +1 -4
  583. esphome/components/sprinkler/__init__.py +4 -4
  584. esphome/components/sps30/sps30.cpp +0 -1
  585. esphome/components/ssd1306_base/__init__.py +11 -11
  586. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  587. esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
  588. esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
  589. esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
  590. esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
  591. esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
  592. esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
  593. esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
  594. esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
  595. esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
  596. esphome/components/st7567_spi/st7567_spi.cpp +0 -1
  597. esphome/components/st7701s/display.py +10 -14
  598. esphome/components/st7701s/st7701s.cpp +0 -3
  599. esphome/components/st7735/st7735.cpp +0 -1
  600. esphome/components/st7789v/st7789v.cpp +0 -1
  601. esphome/components/st7920/st7920.cpp +0 -1
  602. esphome/components/status_led/light/status_led_light.cpp +0 -2
  603. esphome/components/status_led/status_led.cpp +0 -1
  604. esphome/components/stepper/__init__.py +2 -4
  605. esphome/components/sts3x/sts3x.cpp +0 -1
  606. esphome/components/substitutions/__init__.py +10 -16
  607. esphome/components/substitutions/jinja.py +24 -1
  608. esphome/components/sun/__init__.py +2 -3
  609. esphome/components/switch/__init__.py +31 -1
  610. esphome/components/switch/automation.h +24 -0
  611. esphome/components/switch/switch.cpp +8 -0
  612. esphome/components/switch/switch.h +8 -0
  613. esphome/components/sx126x/sx126x.cpp +0 -2
  614. esphome/components/sx127x/sx127x.cpp +0 -2
  615. esphome/components/sx1509/__init__.py +7 -5
  616. esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
  617. esphome/components/sx1509/sx1509.cpp +0 -2
  618. esphome/components/syslog/esphome_syslog.cpp +1 -1
  619. esphome/components/tc74/tc74.cpp +0 -1
  620. esphome/components/tca9548a/tca9548a.cpp +0 -1
  621. esphome/components/tca9555/tca9555.cpp +0 -1
  622. esphome/components/tcs34725/tcs34725.cpp +0 -1
  623. esphome/components/tee501/tee501.cpp +0 -1
  624. esphome/components/tem3200/tem3200.cpp +0 -2
  625. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
  626. esphome/components/template/cover/template_cover.cpp +0 -1
  627. esphome/components/template/select/template_select.cpp +0 -1
  628. esphome/components/template/text/template_text.cpp +0 -2
  629. esphome/components/template/valve/template_valve.cpp +0 -1
  630. esphome/components/text/__init__.py +0 -1
  631. esphome/components/text/text_traits.h +2 -0
  632. esphome/components/text_sensor/__init__.py +2 -1
  633. esphome/components/text_sensor/text_sensor.cpp +0 -2
  634. esphome/components/text_sensor/text_sensor.h +0 -8
  635. esphome/components/thermostat/climate.py +4 -4
  636. esphome/components/time/__init__.py +7 -4
  637. esphome/components/time/real_time_clock.cpp +16 -3
  638. esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
  639. esphome/components/tlc5947/tlc5947.cpp +0 -2
  640. esphome/components/tlc5971/tlc5971.cpp +0 -2
  641. esphome/components/tm1621/tm1621.cpp +0 -2
  642. esphome/components/tm1637/tm1637.cpp +0 -2
  643. esphome/components/tm1638/tm1638.cpp +0 -2
  644. esphome/components/tm1651/__init__.py +45 -48
  645. esphome/components/tm1651/tm1651.cpp +213 -47
  646. esphome/components/tm1651/tm1651.h +37 -32
  647. esphome/components/tmp117/tmp117.cpp +0 -2
  648. esphome/components/tsl2561/tsl2561.cpp +0 -1
  649. esphome/components/tsl2591/tsl2591.cpp +0 -1
  650. esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
  651. esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
  652. esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
  653. esphome/components/tuya/climate/__init__.py +9 -10
  654. esphome/components/tuya/number/__init__.py +8 -6
  655. esphome/components/tx20/tx20.cpp +0 -1
  656. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
  657. esphome/components/uart/uart_component_esp8266.cpp +0 -1
  658. esphome/components/uart/uart_component_esp_idf.cpp +0 -2
  659. esphome/components/uart/uart_component_libretiny.cpp +0 -2
  660. esphome/components/uart/uart_component_rp2040.cpp +0 -2
  661. esphome/components/udp/__init__.py +1 -1
  662. esphome/components/ufire_ec/sensor.py +1 -2
  663. esphome/components/ufire_ec/ufire_ec.cpp +0 -2
  664. esphome/components/ufire_ise/sensor.py +1 -2
  665. esphome/components/ufire_ise/ufire_ise.cpp +0 -2
  666. esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
  667. esphome/components/update/__init__.py +0 -1
  668. esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
  669. esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
  670. esphome/components/usb_host/usb_host_client.cpp +0 -1
  671. esphome/components/usb_host/usb_host_component.cpp +0 -1
  672. esphome/components/valve/__init__.py +0 -1
  673. esphome/components/veml3235/veml3235.cpp +0 -3
  674. esphome/components/veml7700/veml7700.cpp +0 -2
  675. esphome/components/version/version_text_sensor.cpp +0 -1
  676. esphome/components/version/version_text_sensor.h +0 -1
  677. esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
  678. esphome/components/voice_assistant/voice_assistant.cpp +9 -8
  679. esphome/components/web_server/__init__.py +13 -0
  680. esphome/components/web_server/web_server.cpp +187 -352
  681. esphome/components/web_server/web_server.h +61 -1
  682. esphome/components/web_server_base/__init__.py +1 -1
  683. esphome/components/web_server_base/web_server_base.cpp +2 -0
  684. esphome/components/web_server_base/web_server_base.h +6 -0
  685. esphome/components/web_server_idf/web_server_idf.cpp +10 -8
  686. esphome/components/web_server_idf/web_server_idf.h +2 -0
  687. esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
  688. esphome/components/weikai_spi/weikai_spi.cpp +1 -1
  689. esphome/components/wifi/__init__.py +8 -43
  690. esphome/components/wifi/wifi_component.cpp +100 -36
  691. esphome/components/wifi/wifi_component.h +5 -1
  692. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
  693. esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
  694. esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
  695. esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
  696. esphome/components/wireguard/wireguard.cpp +0 -2
  697. esphome/components/x9c/x9c.cpp +0 -2
  698. esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
  699. esphome/components/xl9535/xl9535.cpp +0 -2
  700. esphome/components/zephyr/__init__.py +252 -0
  701. esphome/components/zephyr/const.py +16 -0
  702. esphome/components/zephyr/core.cpp +90 -0
  703. esphome/components/zephyr/gpio.cpp +120 -0
  704. esphome/components/zephyr/gpio.h +38 -0
  705. esphome/components/zephyr/pre_build.py.script +4 -0
  706. esphome/components/zephyr/preferences.cpp +156 -0
  707. esphome/components/zephyr/preferences.h +13 -0
  708. esphome/config.py +38 -16
  709. esphome/config_helpers.py +1 -2
  710. esphome/config_validation.py +8 -15
  711. esphome/const.py +26 -1
  712. esphome/core/__init__.py +88 -51
  713. esphome/core/application.cpp +75 -21
  714. esphome/core/application.h +106 -171
  715. esphome/core/color.h +10 -0
  716. esphome/core/component.cpp +41 -25
  717. esphome/core/component.h +9 -6
  718. esphome/core/component_iterator.cpp +61 -261
  719. esphome/core/component_iterator.h +15 -0
  720. esphome/core/config.py +26 -11
  721. esphome/core/defines.h +40 -2
  722. esphome/core/entity_base.h +18 -0
  723. esphome/core/entity_helpers.py +41 -6
  724. esphome/core/helpers.cpp +8 -15
  725. esphome/core/helpers.h +60 -6
  726. esphome/core/lock_free_queue.h +1 -1
  727. esphome/core/scheduler.cpp +277 -74
  728. esphome/core/scheduler.h +89 -27
  729. esphome/cpp_generator.py +2 -6
  730. esphome/cpp_helpers.py +1 -1
  731. esphome/dashboard/dashboard.py +2 -3
  732. esphome/dashboard/dns.py +2 -8
  733. esphome/dashboard/web_server.py +34 -19
  734. esphome/espota2.py +1 -4
  735. esphome/git.py +3 -1
  736. esphome/helpers.py +23 -4
  737. esphome/log.py +3 -1
  738. esphome/mqtt.py +3 -5
  739. esphome/platformio_api.py +7 -4
  740. esphome/types.py +12 -0
  741. esphome/util.py +20 -8
  742. esphome/voluptuous_schema.py +4 -3
  743. esphome/vscode.py +1 -2
  744. esphome/wizard.py +1 -4
  745. esphome/writer.py +5 -107
  746. esphome/yaml_util.py +7 -5
  747. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/METADATA +12 -13
  748. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/RECORD +753 -673
  749. esphome/components/mipi_spi/models/commands.py +0 -82
  750. /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
  751. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/WHEEL +0 -0
  752. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/entry_points.txt +0 -0
  753. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/licenses/LICENSE +0 -0
  754. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/top_level.txt +0 -0
@@ -8,16 +8,369 @@
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 other connections: 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
+ if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
164
+ this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
165
+ this->release_services();
166
+ }
167
+ return;
168
+ }
169
+
170
+ // Early return if no API connection
171
+ auto *api_conn = this->proxy_->get_api_connection();
172
+ if (api_conn == nullptr) {
173
+ this->send_service_ = DONE_SENDING_SERVICES;
174
+ return;
175
+ }
176
+
177
+ // Check if client supports efficient UUIDs
178
+ bool use_efficient_uuids = this->supports_efficient_uuids_();
179
+
180
+ // Prepare response
181
+ api::BluetoothGATTGetServicesResponse resp;
182
+ resp.address = this->address_;
183
+
184
+ // Dynamic batching based on actual size
185
+ // Conservative MTU limit for API messages (accounts for WPA3 overhead)
186
+ static constexpr size_t MAX_PACKET_SIZE = 1360;
187
+
188
+ // Keep running total of actual message size
189
+ size_t current_size = 0;
190
+ api::ProtoSize size;
191
+ resp.calculate_size(size);
192
+ current_size = size.get_size();
193
+
194
+ while (this->send_service_ < this->service_count_) {
195
+ esp_gattc_service_elem_t service_result;
196
+ uint16_t service_count = 1;
197
+ esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->gattc_if_, this->conn_id_, nullptr,
198
+ &service_result, &service_count, this->send_service_);
199
+
200
+ if (service_status != ESP_GATT_OK || service_count == 0) {
201
+ ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
202
+ this->connection_index_, this->address_str().c_str(),
203
+ service_status != ESP_GATT_OK ? "error" : "missing", service_status, service_count, this->send_service_);
204
+ this->send_service_ = DONE_SENDING_SERVICES;
205
+ return;
206
+ }
207
+
208
+ // Get the number of characteristics BEFORE adding to response
209
+ uint16_t total_char_count = 0;
210
+ esp_gatt_status_t char_count_status =
211
+ esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_CHARACTERISTIC,
212
+ service_result.start_handle, service_result.end_handle, 0, &total_char_count);
213
+
214
+ if (char_count_status != ESP_GATT_OK) {
215
+ this->log_connection_error_("esp_ble_gattc_get_attr_count", char_count_status);
216
+ this->send_service_ = DONE_SENDING_SERVICES;
217
+ return;
218
+ }
219
+
220
+ // If this service likely won't fit, send current batch (unless it's the first)
221
+ size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
222
+ if (!resp.services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
223
+ // This service likely won't fit, send current batch
224
+ break;
225
+ }
226
+
227
+ // Now add the service since we know it will likely fit
228
+ resp.services.emplace_back();
229
+ auto &service_resp = resp.services.back();
230
+
231
+ fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
232
+
233
+ service_resp.handle = service_result.start_handle;
234
+
235
+ if (total_char_count > 0) {
236
+ // Reserve space and process characteristics
237
+ service_resp.characteristics.reserve(total_char_count);
238
+ uint16_t char_offset = 0;
239
+ esp_gattc_char_elem_t char_result;
240
+ while (true) { // characteristics
241
+ uint16_t char_count = 1;
242
+ esp_gatt_status_t char_status =
243
+ esp_ble_gattc_get_all_char(this->gattc_if_, this->conn_id_, service_result.start_handle,
244
+ service_result.end_handle, &char_result, &char_count, char_offset);
245
+ if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
246
+ break;
247
+ }
248
+ if (char_status != ESP_GATT_OK) {
249
+ this->log_connection_error_("esp_ble_gattc_get_all_char", char_status);
250
+ this->send_service_ = DONE_SENDING_SERVICES;
251
+ return;
252
+ }
253
+ if (char_count == 0) {
254
+ break;
255
+ }
256
+
257
+ service_resp.characteristics.emplace_back();
258
+ auto &characteristic_resp = service_resp.characteristics.back();
259
+
260
+ fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
261
+
262
+ characteristic_resp.handle = char_result.char_handle;
263
+ characteristic_resp.properties = char_result.properties;
264
+ char_offset++;
265
+
266
+ // Get the number of descriptors directly with one call
267
+ uint16_t total_desc_count = 0;
268
+ esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
269
+ this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
270
+
271
+ if (desc_count_status != ESP_GATT_OK) {
272
+ this->log_connection_error_("esp_ble_gattc_get_attr_count", desc_count_status);
273
+ this->send_service_ = DONE_SENDING_SERVICES;
274
+ return;
275
+ }
276
+ if (total_desc_count == 0) {
277
+ // No descriptors, continue to next characteristic
278
+ continue;
279
+ }
280
+
281
+ // Reserve space and process descriptors
282
+ characteristic_resp.descriptors.reserve(total_desc_count);
283
+ uint16_t desc_offset = 0;
284
+ esp_gattc_descr_elem_t desc_result;
285
+ while (true) { // descriptors
286
+ uint16_t desc_count = 1;
287
+ esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
288
+ this->gattc_if_, this->conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
289
+ if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
290
+ break;
291
+ }
292
+ if (desc_status != ESP_GATT_OK) {
293
+ this->log_connection_error_("esp_ble_gattc_get_all_descr", desc_status);
294
+ this->send_service_ = DONE_SENDING_SERVICES;
295
+ return;
296
+ }
297
+ if (desc_count == 0) {
298
+ break; // No more descriptors
299
+ }
300
+
301
+ characteristic_resp.descriptors.emplace_back();
302
+ auto &descriptor_resp = characteristic_resp.descriptors.back();
303
+
304
+ fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
305
+
306
+ descriptor_resp.handle = desc_result.handle;
307
+ desc_offset++;
308
+ }
309
+ }
310
+ } // end if (total_char_count > 0)
311
+
312
+ // Calculate the actual size of just this service
313
+ api::ProtoSize service_sizer;
314
+ service_resp.calculate_size(service_sizer);
315
+ size_t service_size = service_sizer.get_size() + 1; // +1 for field tag
316
+
317
+ // Check if adding this service would exceed the limit
318
+ if (current_size + service_size > MAX_PACKET_SIZE) {
319
+ // We would go over - pop the last service if we have more than one
320
+ if (resp.services.size() > 1) {
321
+ resp.services.pop_back();
322
+ ESP_LOGD(TAG, "[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
323
+ this->connection_index_, this->address_str().c_str(), this->send_service_, current_size, service_size,
324
+ MAX_PACKET_SIZE);
325
+ // Don't increment send_service_ - we'll retry this service in next batch
326
+ } else {
327
+ // This single service is too large, but we have to send it anyway
328
+ ESP_LOGV(TAG, "[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->connection_index_,
329
+ this->address_str().c_str(), this->send_service_, service_size);
330
+ // Increment so we don't get stuck
331
+ this->send_service_++;
332
+ }
333
+ // Send what we have
334
+ break;
335
+ }
336
+
337
+ // Now we know we're keeping this service, add its size
338
+ current_size += service_size;
339
+ // Successfully added this service, increment counter
340
+ this->send_service_++;
341
+ }
342
+
343
+ // Send the message with dynamically batched services
344
+ api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE);
345
+ }
346
+
347
+ void BluetoothConnection::log_connection_error_(const char *operation, esp_gatt_status_t status) {
348
+ ESP_LOGE(TAG, "[%d] [%s] %s error, status=%d", this->connection_index_, this->address_str().c_str(), operation,
349
+ status);
350
+ }
351
+
352
+ void BluetoothConnection::log_connection_warning_(const char *operation, esp_err_t err) {
353
+ ESP_LOGW(TAG, "[%d] [%s] %s failed, err=%d", this->connection_index_, this->address_str().c_str(), operation, err);
354
+ }
355
+
356
+ void BluetoothConnection::log_gatt_not_connected_(const char *action, const char *type) {
357
+ ESP_LOGW(TAG, "[%d] [%s] Cannot %s GATT %s, not connected.", this->connection_index_, this->address_str().c_str(),
358
+ action, type);
359
+ }
360
+
361
+ void BluetoothConnection::log_gatt_operation_error_(const char *operation, uint16_t handle, esp_gatt_status_t status) {
362
+ ESP_LOGW(TAG, "[%d] [%s] Error %s for handle 0x%2X, status=%d", this->connection_index_, this->address_str().c_str(),
363
+ operation, handle, status);
364
+ }
365
+
366
+ esp_err_t BluetoothConnection::check_and_log_error_(const char *operation, esp_err_t err) {
367
+ if (err != ESP_OK) {
368
+ this->log_connection_warning_(operation, err);
369
+ return err;
370
+ }
371
+ return ESP_OK;
372
+ }
373
+
21
374
  bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
22
375
  esp_ble_gattc_cb_param_t *param) {
23
376
  if (!BLEClientBase::gattc_event_handler(event, gattc_if, param))
@@ -25,22 +378,16 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
25
378
 
26
379
  switch (event) {
27
380
  case ESP_GATTC_DISCONNECT_EVT: {
28
- this->proxy_->send_device_connection(this->address_, false, 0, param->disconnect.reason);
29
- this->set_address(0);
30
- this->proxy_->send_connections_free();
381
+ this->reset_connection_(param->disconnect.reason);
31
382
  break;
32
383
  }
33
384
  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();
385
+ this->reset_connection_(param->close.reason);
37
386
  break;
38
387
  }
39
388
  case ESP_GATTC_OPEN_EVT: {
40
389
  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();
390
+ this->reset_connection_(param->open.status);
44
391
  } else if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
45
392
  this->proxy_->send_device_connection(this->address_, true, this->mtu_);
46
393
  this->proxy_->send_connections_free();
@@ -64,59 +411,54 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
64
411
  case ESP_GATTC_READ_DESCR_EVT:
65
412
  case ESP_GATTC_READ_CHAR_EVT: {
66
413
  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);
414
+ this->log_gatt_operation_error_("reading char/descriptor", param->read.handle, param->read.status);
69
415
  this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status);
70
416
  break;
71
417
  }
72
418
  api::BluetoothGATTReadResponse resp;
73
419
  resp.address = this->address_;
74
420
  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);
421
+ resp.set_data(param->read.value, param->read.value_len);
422
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE);
79
423
  break;
80
424
  }
81
425
  case ESP_GATTC_WRITE_CHAR_EVT:
82
426
  case ESP_GATTC_WRITE_DESCR_EVT: {
83
427
  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);
428
+ this->log_gatt_operation_error_("writing char/descriptor", param->write.handle, param->write.status);
86
429
  this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status);
87
430
  break;
88
431
  }
89
432
  api::BluetoothGATTWriteResponse resp;
90
433
  resp.address = this->address_;
91
434
  resp.handle = param->write.handle;
92
- this->proxy_->get_api_connection()->send_message(resp);
435
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE);
93
436
  break;
94
437
  }
95
438
  case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
96
439
  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);
440
+ this->log_gatt_operation_error_("unregistering notifications", param->unreg_for_notify.handle,
441
+ param->unreg_for_notify.status);
100
442
  this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status);
101
443
  break;
102
444
  }
103
445
  api::BluetoothGATTNotifyResponse resp;
104
446
  resp.address = this->address_;
105
447
  resp.handle = param->unreg_for_notify.handle;
106
- this->proxy_->get_api_connection()->send_message(resp);
448
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
107
449
  break;
108
450
  }
109
451
  case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
110
452
  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);
453
+ this->log_gatt_operation_error_("registering notifications", param->reg_for_notify.handle,
454
+ param->reg_for_notify.status);
113
455
  this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status);
114
456
  break;
115
457
  }
116
458
  api::BluetoothGATTNotifyResponse resp;
117
459
  resp.address = this->address_;
118
460
  resp.handle = param->reg_for_notify.handle;
119
- this->proxy_->get_api_connection()->send_message(resp);
461
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
120
462
  break;
121
463
  }
122
464
  case ESP_GATTC_NOTIFY_EVT: {
@@ -125,10 +467,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
125
467
  api::BluetoothGATTNotifyDataResponse resp;
126
468
  resp.address = this->address_;
127
469
  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);
470
+ resp.set_data(param->notify.value, param->notify.value_len);
471
+ this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE);
132
472
  break;
133
473
  }
134
474
  default:
@@ -157,8 +497,7 @@ void BluetoothConnection::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
157
497
 
158
498
  esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
159
499
  if (!this->connected()) {
160
- ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not connected.", this->connection_index_,
161
- this->address_str_.c_str());
500
+ this->log_gatt_not_connected_("read", "characteristic");
162
501
  return ESP_GATT_NOT_CONNECTED;
163
502
  }
164
503
 
@@ -166,18 +505,12 @@ esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
166
505
  handle);
167
506
 
168
507
  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;
508
+ return this->check_and_log_error_("esp_ble_gattc_read_char", err);
175
509
  }
176
510
 
177
511
  esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::string &data, bool response) {
178
512
  if (!this->connected()) {
179
- ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not connected.", this->connection_index_,
180
- this->address_str_.c_str());
513
+ this->log_gatt_not_connected_("write", "characteristic");
181
514
  return ESP_GATT_NOT_CONNECTED;
182
515
  }
183
516
  ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -186,36 +519,24 @@ esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::
186
519
  esp_err_t err =
187
520
  esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
188
521
  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;
522
+ return this->check_and_log_error_("esp_ble_gattc_write_char", err);
195
523
  }
196
524
 
197
525
  esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
198
526
  if (!this->connected()) {
199
- ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not connected.", this->connection_index_,
200
- this->address_str_.c_str());
527
+ this->log_gatt_not_connected_("read", "descriptor");
201
528
  return ESP_GATT_NOT_CONNECTED;
202
529
  }
203
530
  ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
204
531
  handle);
205
532
 
206
533
  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;
534
+ return this->check_and_log_error_("esp_ble_gattc_read_char_descr", err);
213
535
  }
214
536
 
215
537
  esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
216
538
  if (!this->connected()) {
217
- ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
218
- this->address_str_.c_str());
539
+ this->log_gatt_not_connected_("write", "descriptor");
219
540
  return ESP_GATT_NOT_CONNECTED;
220
541
  }
221
542
  ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -224,18 +545,12 @@ esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::stri
224
545
  esp_err_t err = esp_ble_gattc_write_char_descr(
225
546
  this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
226
547
  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;
548
+ return this->check_and_log_error_("esp_ble_gattc_write_char_descr", err);
233
549
  }
234
550
 
235
551
  esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enable) {
236
552
  if (!this->connected()) {
237
- ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not connected.", this->connection_index_,
238
- this->address_str_.c_str());
553
+ this->log_gatt_not_connected_("notify", "characteristic");
239
554
  return ESP_GATT_NOT_CONNECTED;
240
555
  }
241
556
 
@@ -243,29 +558,19 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl
243
558
  ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
244
559
  this->address_str_.c_str(), handle);
245
560
  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
- }
561
+ return this->check_and_log_error_("esp_ble_gattc_register_for_notify", err);
260
562
  }
261
- return ESP_OK;
563
+
564
+ ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
565
+ this->address_str_.c_str(), handle);
566
+ esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
567
+ return this->check_and_log_error_("esp_ble_gattc_unregister_for_notify", err);
262
568
  }
263
569
 
264
570
  esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() {
265
571
  return this->proxy_->get_advertisement_parser_type();
266
572
  }
267
573
 
268
- } // namespace bluetooth_proxy
269
- } // namespace esphome
574
+ } // namespace esphome::bluetooth_proxy
270
575
 
271
576
  #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