esphome 2025.9.3__py3-none-any.whl → 2025.10.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. esphome/__main__.py +94 -31
  2. esphome/address_cache.py +142 -0
  3. esphome/automation.py +130 -32
  4. esphome/build_gen/platformio.py +1 -3
  5. esphome/codegen.py +1 -0
  6. esphome/components/animation/animation.cpp +2 -2
  7. esphome/components/api/__init__.py +166 -3
  8. esphome/components/api/api_connection.cpp +84 -41
  9. esphome/components/api/api_connection.h +22 -16
  10. esphome/components/api/api_frame_helper.cpp +33 -19
  11. esphome/components/api/api_frame_helper.h +19 -4
  12. esphome/components/api/api_frame_helper_noise.cpp +41 -53
  13. esphome/components/api/api_frame_helper_noise.h +1 -1
  14. esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
  15. esphome/components/api/api_frame_helper_plaintext.h +1 -1
  16. esphome/components/api/api_pb2.cpp +189 -15
  17. esphome/components/api/api_pb2.h +132 -20
  18. esphome/components/api/api_pb2_dump.cpp +97 -9
  19. esphome/components/api/api_pb2_service.cpp +118 -160
  20. esphome/components/api/api_pb2_service.h +31 -3
  21. esphome/components/api/api_server.cpp +68 -10
  22. esphome/components/api/api_server.h +32 -4
  23. esphome/components/api/custom_api_device.h +8 -8
  24. esphome/components/api/homeassistant_service.h +123 -6
  25. esphome/components/api/proto.h +6 -2
  26. esphome/components/api/user_services.h +2 -2
  27. esphome/components/as7341/sensor.py +1 -1
  28. esphome/components/audio/__init__.py +1 -1
  29. esphome/components/audio/audio.cpp +1 -1
  30. esphome/components/audio/audio_decoder.cpp +9 -9
  31. esphome/components/bl0906/bl0906.cpp +2 -2
  32. esphome/components/bl0942/bl0942.cpp +2 -2
  33. esphome/components/ble_client/__init__.py +1 -1
  34. esphome/components/bluetooth_proxy/__init__.py +4 -30
  35. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
  36. esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
  37. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
  38. esphome/components/camera_encoder/__init__.py +2 -4
  39. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
  40. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
  41. esphome/components/canbus/canbus.cpp +7 -5
  42. esphome/components/canbus/canbus.h +7 -7
  43. esphome/components/captive_portal/__init__.py +18 -1
  44. esphome/components/captive_portal/captive_portal.cpp +40 -46
  45. esphome/components/captive_portal/captive_portal.h +20 -22
  46. esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
  47. esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
  48. esphome/components/ccs811/ccs811.cpp +1 -1
  49. esphome/components/climate/climate.cpp +10 -7
  50. esphome/components/cm1106/cm1106.cpp +1 -1
  51. esphome/components/copy/lock/copy_lock.cpp +1 -1
  52. esphome/components/cover/cover.cpp +1 -0
  53. esphome/components/daikin_arc/daikin_arc.cpp +19 -12
  54. esphome/components/dashboard_import/dashboard_import.cpp +1 -1
  55. esphome/components/dashboard_import/dashboard_import.h +1 -1
  56. esphome/components/deep_sleep/__init__.py +9 -2
  57. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  58. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  59. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  60. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  61. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  62. esphome/components/epaper_spi/__init__.py +1 -0
  63. esphome/components/epaper_spi/display.py +80 -0
  64. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  65. esphome/components/epaper_spi/epaper_spi.h +93 -0
  66. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  67. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  68. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  69. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  70. esphome/components/es7210/es7210.cpp +3 -3
  71. esphome/components/esp32/__init__.py +256 -340
  72. esphome/components/esp32/boards.py +81 -0
  73. esphome/components/esp32/preferences.cpp +23 -17
  74. esphome/components/esp32_ble/__init__.py +167 -44
  75. esphome/components/esp32_ble/ble.cpp +47 -3
  76. esphome/components/esp32_ble/ble.h +18 -0
  77. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  78. esphome/components/esp32_ble/ble_advertising.h +4 -0
  79. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  80. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  81. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +0 -4
  82. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  83. esphome/components/esp32_ble_server/__init__.py +28 -14
  84. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  85. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  86. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  87. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  88. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  89. esphome/components/esp32_ble_server/ble_server.h +38 -20
  90. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  91. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  92. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  93. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -8
  94. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  95. esphome/components/esp32_camera/__init__.py +1 -3
  96. esphome/components/esp32_can/esp32_can.cpp +22 -4
  97. esphome/components/esp32_can/esp32_can.h +3 -0
  98. esphome/components/esp32_hosted/__init__.py +2 -1
  99. esphome/components/esp32_improv/esp32_improv_component.cpp +135 -65
  100. esphome/components/esp32_improv/esp32_improv_component.h +7 -1
  101. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  102. esphome/components/esp8266/__init__.py +3 -3
  103. esphome/components/esphome/ota/__init__.py +21 -2
  104. esphome/components/esphome/ota/ota_esphome.cpp +456 -146
  105. esphome/components/esphome/ota/ota_esphome.h +49 -2
  106. esphome/components/ethernet/__init__.py +39 -22
  107. esphome/components/ethernet/ethernet_component.cpp +28 -5
  108. esphome/components/ethernet/ethernet_component.h +5 -1
  109. esphome/components/external_components/__init__.py +8 -6
  110. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  111. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  112. esphome/components/font/__init__.py +5 -5
  113. esphome/components/graph/graph.cpp +1 -1
  114. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  115. esphome/components/haier/hon_climate.cpp +2 -2
  116. esphome/components/haier/hon_climate.h +1 -1
  117. esphome/components/hdc1080/hdc1080.cpp +42 -34
  118. esphome/components/hdc1080/hdc1080.h +1 -3
  119. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  120. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  121. esphome/components/http_request/__init__.py +3 -3
  122. esphome/components/htu21d/htu21d.cpp +13 -18
  123. esphome/components/htu21d/htu21d.h +1 -1
  124. esphome/components/i2s_audio/__init__.py +1 -2
  125. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  126. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  127. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  128. esphome/components/improv_serial/improv_serial_component.h +6 -8
  129. esphome/components/json/json_util.cpp +42 -44
  130. esphome/components/json/json_util.h +57 -0
  131. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  132. esphome/components/key_collector/key_collector.h +4 -4
  133. esphome/components/libretiny/__init__.py +6 -6
  134. esphome/components/libretiny/preferences.cpp +23 -16
  135. esphome/components/light/light_call.cpp +98 -120
  136. esphome/components/light/light_call.h +17 -7
  137. esphome/components/lm75b/__init__.py +0 -0
  138. esphome/components/lm75b/lm75b.cpp +39 -0
  139. esphome/components/lm75b/lm75b.h +19 -0
  140. esphome/components/lm75b/sensor.py +34 -0
  141. esphome/components/lock/lock.h +12 -6
  142. esphome/components/logger/__init__.py +15 -27
  143. esphome/components/logger/logger.cpp +10 -20
  144. esphome/components/logger/logger.h +105 -62
  145. esphome/components/logger/logger_esp32.cpp +0 -48
  146. esphome/components/logger/logger_zephyr.cpp +2 -3
  147. esphome/components/logger/select/logger_level_select.cpp +6 -7
  148. esphome/components/logger/select/logger_level_select.h +7 -0
  149. esphome/components/ltr501/ltr501.cpp +7 -6
  150. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  151. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  152. esphome/components/max7219digit/max7219digit.cpp +1 -1
  153. esphome/components/mcp23xxx_base/mcp23xxx_base.h +3 -3
  154. esphome/components/mcp2515/mcp2515.cpp +31 -3
  155. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  156. esphome/components/md5/md5.cpp +0 -26
  157. esphome/components/md5/md5.h +10 -20
  158. esphome/components/mdns/__init__.py +93 -19
  159. esphome/components/mdns/mdns_component.cpp +57 -94
  160. esphome/components/mdns/mdns_component.h +35 -11
  161. esphome/components/mdns/mdns_esp32.cpp +7 -13
  162. esphome/components/mdns/mdns_esp8266.cpp +7 -7
  163. esphome/components/mdns/mdns_libretiny.cpp +3 -4
  164. esphome/components/mdns/mdns_rp2040.cpp +3 -4
  165. esphome/components/mipi/__init__.py +1 -5
  166. esphome/components/mipi_spi/display.py +24 -8
  167. esphome/components/mipi_spi/mipi_spi.h +3 -3
  168. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  169. esphome/components/mmc5603/mmc5603.cpp +3 -3
  170. esphome/components/modbus/modbus.cpp +27 -13
  171. esphome/components/modbus/modbus.h +5 -3
  172. esphome/components/modbus/modbus_definitions.h +86 -0
  173. esphome/components/modbus_controller/__init__.py +29 -1
  174. esphome/components/modbus_controller/const.py +4 -0
  175. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  176. esphome/components/modbus_controller/modbus_controller.h +18 -29
  177. esphome/components/mpr121/mpr121.cpp +41 -42
  178. esphome/components/mpr121/mpr121.h +0 -1
  179. esphome/components/nau7802/nau7802.cpp +2 -2
  180. esphome/components/network/__init__.py +7 -3
  181. esphome/components/nextion/display.py +4 -4
  182. esphome/components/nextion/nextion.cpp +8 -8
  183. esphome/components/number/__init__.py +2 -0
  184. esphome/components/number/number_call.cpp +23 -12
  185. esphome/components/number/number_call.h +5 -0
  186. esphome/components/online_image/bmp_image.cpp +2 -1
  187. esphome/components/online_image/jpeg_image.cpp +4 -2
  188. esphome/components/opentherm/opentherm.cpp +5 -5
  189. esphome/components/opentherm/opentherm.h +3 -3
  190. esphome/components/openthread/openthread.cpp +11 -10
  191. esphome/components/openthread/openthread.h +0 -1
  192. esphome/components/ota/ota_backend.h +1 -0
  193. esphome/components/packages/__init__.py +10 -8
  194. esphome/components/packet_transport/packet_transport.cpp +2 -0
  195. esphome/components/pid/pid_controller.cpp +1 -1
  196. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  197. esphome/components/psram/__init__.py +30 -28
  198. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  199. esphome/components/qmc5883l/qmc5883l.h +3 -0
  200. esphome/components/qmc5883l/sensor.py +31 -12
  201. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  202. esphome/components/remote_receiver/__init__.py +14 -2
  203. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  204. esphome/components/remote_receiver/remote_receiver.h +4 -0
  205. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  206. esphome/components/remote_transmitter/__init__.py +2 -2
  207. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  208. esphome/components/rp2040/__init__.py +11 -11
  209. esphome/components/rtttl/rtttl.cpp +2 -2
  210. esphome/components/scd30/sensor.py +1 -1
  211. esphome/components/script/__init__.py +1 -1
  212. esphome/components/script/script.h +7 -7
  213. esphome/components/select/select.cpp +5 -4
  214. esphome/components/select/select_call.cpp +1 -1
  215. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  216. esphome/components/sensor/__init__.py +2 -0
  217. esphome/components/sha256/__init__.py +22 -0
  218. esphome/components/sha256/sha256.cpp +116 -0
  219. esphome/components/sha256/sha256.h +60 -0
  220. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  221. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  222. esphome/components/spi/__init__.py +0 -3
  223. esphome/components/split_buffer/__init__.py +5 -0
  224. esphome/components/split_buffer/split_buffer.cpp +133 -0
  225. esphome/components/split_buffer/split_buffer.h +40 -0
  226. esphome/components/sps30/sps30.cpp +14 -10
  227. esphome/components/sps30/sps30.h +2 -0
  228. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  229. esphome/components/st7789v/st7789v.cpp +3 -2
  230. esphome/components/statsd/statsd.cpp +1 -1
  231. esphome/components/substitutions/__init__.py +3 -1
  232. esphome/components/substitutions/jinja.py +13 -3
  233. esphome/components/sx126x/__init__.py +16 -0
  234. esphome/components/sx126x/sx126x.cpp +15 -1
  235. esphome/components/sx126x/sx126x.h +9 -1
  236. esphome/components/sx126x/sx126x_reg.h +2 -0
  237. esphome/components/text_sensor/text_sensor.cpp +16 -0
  238. esphome/components/text_sensor/text_sensor.h +3 -10
  239. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  240. esphome/components/tuya/select/tuya_select.cpp +1 -1
  241. esphome/components/tuya/tuya.cpp +29 -4
  242. esphome/components/uart/__init__.py +37 -27
  243. esphome/components/uart/uart.h +6 -0
  244. esphome/components/uart/uart_component.cpp +8 -0
  245. esphome/components/uart/uart_component.h +28 -0
  246. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  247. esphome/components/uart/uart_component_esp_idf.h +5 -2
  248. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  249. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  250. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  251. esphome/components/usb_host/__init__.py +12 -2
  252. esphome/components/usb_host/usb_host.h +89 -14
  253. esphome/components/usb_host/usb_host_client.cpp +157 -22
  254. esphome/components/usb_host/usb_host_component.cpp +1 -1
  255. esphome/components/usb_uart/__init__.py +0 -1
  256. esphome/components/usb_uart/ch34x.cpp +4 -4
  257. esphome/components/usb_uart/cp210x.cpp +3 -3
  258. esphome/components/usb_uart/usb_uart.cpp +88 -32
  259. esphome/components/usb_uart/usb_uart.h +30 -6
  260. esphome/components/valve/valve.cpp +1 -0
  261. esphome/components/veml7700/veml7700.cpp +7 -6
  262. esphome/components/version/version_text_sensor.cpp +2 -1
  263. esphome/components/voice_assistant/voice_assistant.cpp +3 -2
  264. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  265. esphome/components/web_server/list_entities.cpp +3 -4
  266. esphome/components/web_server/list_entities.h +8 -10
  267. esphome/components/web_server/ota/__init__.py +1 -1
  268. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  269. esphome/components/web_server/web_server.cpp +509 -404
  270. esphome/components/web_server/web_server.h +5 -6
  271. esphome/components/web_server/web_server_v1.cpp +21 -19
  272. esphome/components/web_server_base/__init__.py +5 -2
  273. esphome/components/web_server_base/web_server_base.h +27 -7
  274. esphome/components/web_server_idf/__init__.py +1 -1
  275. esphome/components/web_server_idf/multipart.cpp +2 -2
  276. esphome/components/web_server_idf/multipart.h +2 -2
  277. esphome/components/web_server_idf/utils.cpp +2 -2
  278. esphome/components/web_server_idf/utils.h +2 -2
  279. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  280. esphome/components/web_server_idf/web_server_idf.h +12 -10
  281. esphome/components/wifi/__init__.py +13 -11
  282. esphome/components/wifi/wifi_component.cpp +74 -56
  283. esphome/components/wifi/wifi_component.h +4 -4
  284. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  285. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  286. esphome/components/wireguard/__init__.py +1 -1
  287. esphome/components/wts01/__init__.py +0 -0
  288. esphome/components/wts01/sensor.py +41 -0
  289. esphome/components/wts01/wts01.cpp +91 -0
  290. esphome/components/wts01/wts01.h +27 -0
  291. esphome/components/zephyr/__init__.py +5 -5
  292. esphome/components/zwave_proxy/__init__.py +43 -0
  293. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  294. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  295. esphome/config.py +79 -24
  296. esphome/config_validation.py +13 -15
  297. esphome/const.py +9 -2
  298. esphome/core/__init__.py +33 -22
  299. esphome/core/component.cpp +28 -18
  300. esphome/core/component_iterator.h +2 -1
  301. esphome/core/config.py +15 -15
  302. esphome/core/defines.h +21 -0
  303. esphome/core/entity_helpers.py +9 -6
  304. esphome/core/hash_base.h +56 -0
  305. esphome/core/helpers.cpp +19 -3
  306. esphome/core/helpers.h +26 -0
  307. esphome/core/scheduler.cpp +5 -21
  308. esphome/core/scheduler.h +19 -8
  309. esphome/core/string_ref.h +1 -1
  310. esphome/core/time.cpp +5 -5
  311. esphome/cpp_generator.py +4 -29
  312. esphome/dashboard/const.py +21 -4
  313. esphome/dashboard/core.py +10 -8
  314. esphome/dashboard/dns.py +15 -0
  315. esphome/dashboard/entries.py +15 -21
  316. esphome/dashboard/models.py +76 -0
  317. esphome/dashboard/settings.py +7 -7
  318. esphome/dashboard/status/mdns.py +46 -2
  319. esphome/dashboard/web_server.py +367 -93
  320. esphome/espota2.py +112 -32
  321. esphome/external_files.py +6 -7
  322. esphome/git.py +8 -0
  323. esphome/helpers.py +124 -77
  324. esphome/loader.py +8 -9
  325. esphome/pins.py +2 -2
  326. esphome/platformio_api.py +56 -18
  327. esphome/storage_json.py +26 -21
  328. esphome/types.py +30 -2
  329. esphome/util.py +32 -16
  330. esphome/vscode.py +8 -8
  331. esphome/wizard.py +10 -10
  332. esphome/writer.py +50 -15
  333. esphome/yaml_util.py +37 -31
  334. esphome/zeroconf.py +12 -3
  335. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/METADATA +12 -12
  336. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/RECORD +340 -320
  337. esphome/components/event_emitter/__init__.py +0 -5
  338. esphome/components/event_emitter/event_emitter.cpp +0 -14
  339. esphome/components/event_emitter/event_emitter.h +0 -63
  340. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  341. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  342. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  343. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  344. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  345. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  346. esphome/core/string_ref.cpp +0 -12
  347. esphome/dashboard/util/file.py +0 -63
  348. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/WHEEL +0 -0
  349. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/entry_points.txt +0 -0
  350. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/licenses/LICENSE +0 -0
  351. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/top_level.txt +0 -0
@@ -73,6 +73,28 @@ void ESP32BLE::advertising_set_manufacturer_data(const std::vector<uint8_t> &dat
73
73
  this->advertising_start();
74
74
  }
75
75
 
76
+ void ESP32BLE::advertising_set_service_data_and_name(std::span<const uint8_t> data, bool include_name) {
77
+ // This method atomically updates both service data and device name inclusion in BLE advertising.
78
+ // When include_name is true, the device name is included in the advertising packet making it
79
+ // visible to passive BLE scanners. When false, the name is only visible in scan response
80
+ // (requires active scanning). This atomic operation ensures we only restart advertising once
81
+ // when changing both properties, avoiding the brief gap that would occur with separate calls.
82
+
83
+ this->advertising_init_();
84
+
85
+ if (include_name) {
86
+ // When including name, clear service data first to avoid packet overflow
87
+ this->advertising_->set_service_data(std::span<const uint8_t>{});
88
+ this->advertising_->set_include_name(true);
89
+ } else {
90
+ // When including service data, clear name first to avoid packet overflow
91
+ this->advertising_->set_include_name(false);
92
+ this->advertising_->set_service_data(data);
93
+ }
94
+
95
+ this->advertising_start();
96
+ }
97
+
76
98
  void ESP32BLE::advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback) {
77
99
  this->advertising_init_();
78
100
  this->advertising_->register_raw_advertisement_callback(std::move(callback));
@@ -167,6 +189,7 @@ bool ESP32BLE::ble_setup_() {
167
189
  }
168
190
  }
169
191
 
192
+ #ifdef USE_ESP32_BLE_SERVER
170
193
  if (!this->gatts_event_handlers_.empty()) {
171
194
  err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler);
172
195
  if (err != ESP_OK) {
@@ -174,7 +197,9 @@ bool ESP32BLE::ble_setup_() {
174
197
  return false;
175
198
  }
176
199
  }
200
+ #endif
177
201
 
202
+ #ifdef USE_ESP32_BLE_CLIENT
178
203
  if (!this->gattc_event_handlers_.empty()) {
179
204
  err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler);
180
205
  if (err != ESP_OK) {
@@ -182,20 +207,23 @@ bool ESP32BLE::ble_setup_() {
182
207
  return false;
183
208
  }
184
209
  }
210
+ #endif
185
211
 
186
212
  std::string name;
187
213
  if (this->name_.has_value()) {
188
214
  name = this->name_.value();
189
215
  if (App.is_name_add_mac_suffix_enabled()) {
190
- name += "-" + get_mac_address().substr(6);
216
+ name += "-";
217
+ name += get_mac_address().substr(6);
191
218
  }
192
219
  } else {
193
220
  name = App.get_name();
194
221
  if (name.length() > 20) {
195
222
  if (App.is_name_add_mac_suffix_enabled()) {
196
- name.erase(name.begin() + 13, name.end() - 7); // Remove characters between 13 and the mac address
223
+ // Keep first 13 chars and last 7 chars (MAC suffix), remove middle
224
+ name.erase(13, name.length() - 20);
197
225
  } else {
198
- name = name.substr(0, 20);
226
+ name.resize(20);
199
227
  }
200
228
  }
201
229
  }
@@ -303,6 +331,7 @@ void ESP32BLE::loop() {
303
331
  BLEEvent *ble_event = this->ble_events_.pop();
304
332
  while (ble_event != nullptr) {
305
333
  switch (ble_event->type_) {
334
+ #ifdef USE_ESP32_BLE_SERVER
306
335
  case BLEEvent::GATTS: {
307
336
  esp_gatts_cb_event_t event = ble_event->event_.gatts.gatts_event;
308
337
  esp_gatt_if_t gatts_if = ble_event->event_.gatts.gatts_if;
@@ -313,6 +342,8 @@ void ESP32BLE::loop() {
313
342
  }
314
343
  break;
315
344
  }
345
+ #endif
346
+ #ifdef USE_ESP32_BLE_CLIENT
316
347
  case BLEEvent::GATTC: {
317
348
  esp_gattc_cb_event_t event = ble_event->event_.gattc.gattc_event;
318
349
  esp_gatt_if_t gattc_if = ble_event->event_.gattc.gattc_if;
@@ -323,6 +354,7 @@ void ESP32BLE::loop() {
323
354
  }
324
355
  break;
325
356
  }
357
+ #endif
326
358
  case BLEEvent::GAP: {
327
359
  esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
328
360
  switch (gap_event) {
@@ -416,13 +448,17 @@ void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_pa
416
448
  event->load_gap_event(e, p);
417
449
  }
418
450
 
451
+ #ifdef USE_ESP32_BLE_CLIENT
419
452
  void load_ble_event(BLEEvent *event, esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
420
453
  event->load_gattc_event(e, i, p);
421
454
  }
455
+ #endif
422
456
 
457
+ #ifdef USE_ESP32_BLE_SERVER
423
458
  void load_ble_event(BLEEvent *event, esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
424
459
  event->load_gatts_event(e, i, p);
425
460
  }
461
+ #endif
426
462
 
427
463
  template<typename... Args> void enqueue_ble_event(Args... args) {
428
464
  // Allocate an event from the pool
@@ -443,8 +479,12 @@ template<typename... Args> void enqueue_ble_event(Args... args) {
443
479
 
444
480
  // Explicit template instantiations for the friend function
445
481
  template void enqueue_ble_event(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t *);
482
+ #ifdef USE_ESP32_BLE_SERVER
446
483
  template void enqueue_ble_event(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *);
484
+ #endif
485
+ #ifdef USE_ESP32_BLE_CLIENT
447
486
  template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *);
487
+ #endif
448
488
 
449
489
  void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
450
490
  switch (event) {
@@ -484,15 +524,19 @@ void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa
484
524
  ESP_LOGW(TAG, "Ignoring unexpected GAP event type: %d", event);
485
525
  }
486
526
 
527
+ #ifdef USE_ESP32_BLE_SERVER
487
528
  void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
488
529
  esp_ble_gatts_cb_param_t *param) {
489
530
  enqueue_ble_event(event, gatts_if, param);
490
531
  }
532
+ #endif
491
533
 
534
+ #ifdef USE_ESP32_BLE_CLIENT
492
535
  void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
493
536
  esp_ble_gattc_cb_param_t *param) {
494
537
  enqueue_ble_event(event, gattc_if, param);
495
538
  }
539
+ #endif
496
540
 
497
541
  float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; }
498
542
 
@@ -9,6 +9,7 @@
9
9
  #endif
10
10
 
11
11
  #include <functional>
12
+ #include <span>
12
13
 
13
14
  #include "esphome/core/automation.h"
14
15
  #include "esphome/core/component.h"
@@ -74,17 +75,21 @@ class GAPScanEventHandler {
74
75
  virtual void gap_scan_event_handler(const BLEScanResult &scan_result) = 0;
75
76
  };
76
77
 
78
+ #ifdef USE_ESP32_BLE_CLIENT
77
79
  class GATTcEventHandler {
78
80
  public:
79
81
  virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
80
82
  esp_ble_gattc_cb_param_t *param) = 0;
81
83
  };
84
+ #endif
82
85
 
86
+ #ifdef USE_ESP32_BLE_SERVER
83
87
  class GATTsEventHandler {
84
88
  public:
85
89
  virtual void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
86
90
  esp_ble_gatts_cb_param_t *param) = 0;
87
91
  };
92
+ #endif
88
93
 
89
94
  class BLEStatusEventHandler {
90
95
  public:
@@ -114,6 +119,7 @@ class ESP32BLE : public Component {
114
119
  void advertising_set_service_data(const std::vector<uint8_t> &data);
115
120
  void advertising_set_manufacturer_data(const std::vector<uint8_t> &data);
116
121
  void advertising_set_appearance(uint16_t appearance) { this->appearance_ = appearance; }
122
+ void advertising_set_service_data_and_name(std::span<const uint8_t> data, bool include_name);
117
123
  void advertising_add_service_uuid(ESPBTUUID uuid);
118
124
  void advertising_remove_service_uuid(ESPBTUUID uuid);
119
125
  void advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback);
@@ -123,16 +129,24 @@ class ESP32BLE : public Component {
123
129
  void register_gap_scan_event_handler(GAPScanEventHandler *handler) {
124
130
  this->gap_scan_event_handlers_.push_back(handler);
125
131
  }
132
+ #ifdef USE_ESP32_BLE_CLIENT
126
133
  void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); }
134
+ #endif
135
+ #ifdef USE_ESP32_BLE_SERVER
127
136
  void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); }
137
+ #endif
128
138
  void register_ble_status_event_handler(BLEStatusEventHandler *handler) {
129
139
  this->ble_status_event_handlers_.push_back(handler);
130
140
  }
131
141
  void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
132
142
 
133
143
  protected:
144
+ #ifdef USE_ESP32_BLE_SERVER
134
145
  static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
146
+ #endif
147
+ #ifdef USE_ESP32_BLE_CLIENT
135
148
  static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
149
+ #endif
136
150
  static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
137
151
 
138
152
  bool ble_setup_();
@@ -148,8 +162,12 @@ class ESP32BLE : public Component {
148
162
  // Vectors (12 bytes each on 32-bit, naturally aligned to 4 bytes)
149
163
  std::vector<GAPEventHandler *> gap_event_handlers_;
150
164
  std::vector<GAPScanEventHandler *> gap_scan_event_handlers_;
165
+ #ifdef USE_ESP32_BLE_CLIENT
151
166
  std::vector<GATTcEventHandler *> gattc_event_handlers_;
167
+ #endif
168
+ #ifdef USE_ESP32_BLE_SERVER
152
169
  std::vector<GATTsEventHandler *> gatts_event_handlers_;
170
+ #endif
153
171
  std::vector<BLEStatusEventHandler *> ble_status_event_handlers_;
154
172
 
155
173
  // Large objects (size depends on template parameters, but typically aligned to 4 bytes)
@@ -43,7 +43,7 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) {
43
43
  this->advertising_uuids_.end());
44
44
  }
45
45
 
46
- void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
46
+ void BLEAdvertising::set_service_data(std::span<const uint8_t> data) {
47
47
  delete[] this->advertising_data_.p_service_data;
48
48
  this->advertising_data_.p_service_data = nullptr;
49
49
  this->advertising_data_.service_data_len = data.size();
@@ -54,6 +54,10 @@ void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
54
54
  }
55
55
  }
56
56
 
57
+ void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
58
+ this->set_service_data(std::span<const uint8_t>(data));
59
+ }
60
+
57
61
  void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
58
62
  delete[] this->advertising_data_.p_manufacturer_data;
59
63
  this->advertising_data_.p_manufacturer_data = nullptr;
@@ -84,7 +88,7 @@ esp_err_t BLEAdvertising::services_advertisement_() {
84
88
  esp_err_t err;
85
89
 
86
90
  this->advertising_data_.set_scan_rsp = false;
87
- this->advertising_data_.include_name = !this->scan_response_;
91
+ this->advertising_data_.include_name = this->include_name_in_adv_ || !this->scan_response_;
88
92
  this->advertising_data_.include_txpower = !this->scan_response_;
89
93
  err = esp_ble_gap_config_adv_data(&this->advertising_data_);
90
94
  if (err != ESP_OK) {
@@ -148,7 +152,7 @@ void BLEAdvertising::loop() {
148
152
  if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) {
149
153
  this->stop();
150
154
  this->current_adv_index_ += 1;
151
- if (this->current_adv_index_ >= this->raw_advertisements_callbacks_.size()) {
155
+ if (static_cast<size_t>(this->current_adv_index_) >= this->raw_advertisements_callbacks_.size()) {
152
156
  this->current_adv_index_ = -1;
153
157
  }
154
158
  this->start();
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include <array>
6
6
  #include <functional>
7
+ #include <span>
7
8
  #include <vector>
8
9
 
9
10
  #ifdef USE_ESP32
@@ -36,6 +37,8 @@ class BLEAdvertising {
36
37
  void set_manufacturer_data(const std::vector<uint8_t> &data);
37
38
  void set_appearance(uint16_t appearance) { this->advertising_data_.appearance = appearance; }
38
39
  void set_service_data(const std::vector<uint8_t> &data);
40
+ void set_service_data(std::span<const uint8_t> data);
41
+ void set_include_name(bool include_name) { this->include_name_in_adv_ = include_name; }
39
42
  void register_raw_advertisement_callback(std::function<void(bool)> &&callback);
40
43
 
41
44
  void start();
@@ -45,6 +48,7 @@ class BLEAdvertising {
45
48
  esp_err_t services_advertisement_();
46
49
 
47
50
  bool scan_response_;
51
+ bool include_name_in_adv_{false};
48
52
  esp_ble_adv_data_t advertising_data_;
49
53
  esp_ble_adv_data_t scan_response_data_;
50
54
  esp_ble_adv_params_t advertising_params_;
@@ -42,32 +42,18 @@ ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) {
42
42
  ESPBTUUID ESPBTUUID::from_raw(const std::string &data) {
43
43
  ESPBTUUID ret;
44
44
  if (data.length() == 4) {
45
- ret.uuid_.len = ESP_UUID_LEN_16;
46
- ret.uuid_.uuid.uuid16 = 0;
47
- for (uint i = 0; i < data.length(); i += 2) {
48
- uint8_t msb = data.c_str()[i];
49
- uint8_t lsb = data.c_str()[i + 1];
50
- uint8_t lsb_shift = i <= 2 ? (2 - i) * 4 : 0;
51
-
52
- if (msb > '9')
53
- msb -= 7;
54
- if (lsb > '9')
55
- lsb -= 7;
56
- ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
45
+ // 16-bit UUID as 4-character hex string
46
+ auto parsed = parse_hex<uint16_t>(data);
47
+ if (parsed.has_value()) {
48
+ ret.uuid_.len = ESP_UUID_LEN_16;
49
+ ret.uuid_.uuid.uuid16 = parsed.value();
57
50
  }
58
51
  } else if (data.length() == 8) {
59
- ret.uuid_.len = ESP_UUID_LEN_32;
60
- ret.uuid_.uuid.uuid32 = 0;
61
- for (uint i = 0; i < data.length(); i += 2) {
62
- uint8_t msb = data.c_str()[i];
63
- uint8_t lsb = data.c_str()[i + 1];
64
- uint8_t lsb_shift = i <= 6 ? (6 - i) * 4 : 0;
65
-
66
- if (msb > '9')
67
- msb -= 7;
68
- if (lsb > '9')
69
- lsb -= 7;
70
- ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
52
+ // 32-bit UUID as 8-character hex string
53
+ auto parsed = parse_hex<uint32_t>(data);
54
+ if (parsed.has_value()) {
55
+ ret.uuid_.len = ESP_UUID_LEN_32;
56
+ ret.uuid_.uuid.uuid32 = parsed.value();
71
57
  }
72
58
  } else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be
73
59
  // investigated (lack of time)
@@ -145,28 +131,16 @@ bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const {
145
131
  if (this->uuid_.len == uuid.uuid_.len) {
146
132
  switch (this->uuid_.len) {
147
133
  case ESP_UUID_LEN_16:
148
- if (uuid.uuid_.uuid.uuid16 == this->uuid_.uuid.uuid16) {
149
- return true;
150
- }
151
- break;
134
+ return this->uuid_.uuid.uuid16 == uuid.uuid_.uuid.uuid16;
152
135
  case ESP_UUID_LEN_32:
153
- if (uuid.uuid_.uuid.uuid32 == this->uuid_.uuid.uuid32) {
154
- return true;
155
- }
156
- break;
136
+ return this->uuid_.uuid.uuid32 == uuid.uuid_.uuid.uuid32;
157
137
  case ESP_UUID_LEN_128:
158
- for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) {
159
- if (uuid.uuid_.uuid.uuid128[i] != this->uuid_.uuid.uuid128[i]) {
160
- return false;
161
- }
162
- }
163
- return true;
164
- break;
138
+ return memcmp(this->uuid_.uuid.uuid128, uuid.uuid_.uuid.uuid128, ESP_UUID_LEN_128) == 0;
139
+ default:
140
+ return false;
165
141
  }
166
- } else {
167
- return this->as_128bit() == uuid.as_128bit();
168
142
  }
169
- return false;
143
+ return this->as_128bit() == uuid.as_128bit();
170
144
  }
171
145
  esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; }
172
146
  std::string ESPBTUUID::to_string() const {
@@ -4,7 +4,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
4
4
  from esphome.components.esp32_ble import CONF_BLE_ID
5
5
  import esphome.config_validation as cv
6
6
  from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID
7
- from esphome.core import CORE, TimePeriod
7
+ from esphome.core import TimePeriod
8
8
 
9
9
  AUTO_LOAD = ["esp32_ble"]
10
10
  DEPENDENCIES = ["esp32"]
@@ -86,6 +86,5 @@ async def to_code(config):
86
86
 
87
87
  cg.add_define("USE_ESP32_BLE_ADVERTISING")
88
88
 
89
- if CORE.using_esp_idf:
90
- add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
91
- add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
89
+ add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
90
+ add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
@@ -14,10 +14,6 @@
14
14
  #include "esphome/core/hal.h"
15
15
  #include "esphome/core/helpers.h"
16
16
 
17
- #ifdef USE_ARDUINO
18
- #include <esp32-hal-bt.h>
19
- #endif
20
-
21
17
  namespace esphome {
22
18
  namespace esp32_ble_beacon {
23
19
 
@@ -43,13 +43,6 @@ void BLEClientBase::setup() {
43
43
  void BLEClientBase::set_state(espbt::ClientState st) {
44
44
  ESP_LOGV(TAG, "[%d] [%s] Set state %d", this->connection_index_, this->address_str_.c_str(), (int) st);
45
45
  ESPBTClient::set_state(st);
46
-
47
- if (st == espbt::ClientState::READY_TO_CONNECT) {
48
- // Enable loop for state processing
49
- this->enable_loop();
50
- // Connect immediately instead of waiting for next loop
51
- this->connect();
52
- }
53
46
  }
54
47
 
55
48
  void BLEClientBase::loop() {
@@ -65,8 +58,8 @@ void BLEClientBase::loop() {
65
58
  }
66
59
  this->set_state(espbt::ClientState::IDLE);
67
60
  }
68
- // If its idle, we can disable the loop as set_state
69
- // will enable it again when we need to connect.
61
+ // If idle, we can disable the loop as connect()
62
+ // will enable it again when a connection is needed.
70
63
  else if (this->state_ == espbt::ClientState::IDLE) {
71
64
  this->disable_loop();
72
65
  }
@@ -108,9 +101,20 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) {
108
101
  #endif
109
102
 
110
103
  void BLEClientBase::connect() {
104
+ // Prevent duplicate connection attempts
105
+ if (this->state_ == espbt::ClientState::CONNECTING || this->state_ == espbt::ClientState::CONNECTED ||
106
+ this->state_ == espbt::ClientState::ESTABLISHED) {
107
+ ESP_LOGW(TAG, "[%d] [%s] Connection already in progress, state=%s", this->connection_index_,
108
+ this->address_str_.c_str(), espbt::client_state_to_string(this->state_));
109
+ return;
110
+ }
111
111
  ESP_LOGI(TAG, "[%d] [%s] 0x%02x Connecting", this->connection_index_, this->address_str_.c_str(),
112
112
  this->remote_addr_type_);
113
113
  this->paired_ = false;
114
+ // Enable loop for state processing
115
+ this->enable_loop();
116
+ // Immediately transition to CONNECTING to prevent duplicate connection attempts
117
+ this->set_state(espbt::ClientState::CONNECTING);
114
118
 
115
119
  // Determine connection parameters based on connection type
116
120
  if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
@@ -168,7 +172,7 @@ void BLEClientBase::unconditional_disconnect() {
168
172
  this->log_gattc_warning_("esp_ble_gattc_close", err);
169
173
  }
170
174
 
171
- if (this->state_ == espbt::ClientState::READY_TO_CONNECT || this->state_ == espbt::ClientState::DISCOVERED) {
175
+ if (this->state_ == espbt::ClientState::DISCOVERED) {
172
176
  this->set_address(0);
173
177
  this->set_state(espbt::ClientState::IDLE);
174
178
  } else {
@@ -212,8 +216,6 @@ void BLEClientBase::handle_connection_result_(esp_err_t ret) {
212
216
  if (ret) {
213
217
  this->log_gattc_warning_("esp_ble_gattc_open", ret);
214
218
  this->set_state(espbt::ClientState::IDLE);
215
- } else {
216
- this->set_state(espbt::ClientState::CONNECTING);
217
219
  }
218
220
  }
219
221
 
@@ -26,7 +26,7 @@ from esphome.const import (
26
26
  from esphome.core import CORE
27
27
  from esphome.schema_extractors import SCHEMA_EXTRACT
28
28
 
29
- AUTO_LOAD = ["esp32_ble", "bytebuffer", "event_emitter"]
29
+ AUTO_LOAD = ["esp32_ble", "bytebuffer"]
30
30
  CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"]
31
31
  DEPENDENCIES = ["esp32"]
32
32
  DOMAIN = "esp32_ble_server"
@@ -488,6 +488,7 @@ async def to_code_descriptor(descriptor_conf, char_var):
488
488
  cg.add(desc_var.set_value(value))
489
489
  if CONF_ON_WRITE in descriptor_conf:
490
490
  on_write_conf = descriptor_conf[CONF_ON_WRITE]
491
+ cg.add_define("USE_ESP32_BLE_SERVER_DESCRIPTOR_ON_WRITE")
491
492
  await automation.build_automation(
492
493
  BLETriggers_ns.create_descriptor_on_write_trigger(desc_var),
493
494
  [(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
@@ -505,23 +506,32 @@ async def to_code_characteristic(service_var, char_conf):
505
506
  )
506
507
  if CONF_ON_WRITE in char_conf:
507
508
  on_write_conf = char_conf[CONF_ON_WRITE]
509
+ cg.add_define("USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE")
508
510
  await automation.build_automation(
509
511
  BLETriggers_ns.create_characteristic_on_write_trigger(char_var),
510
512
  [(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
511
513
  on_write_conf,
512
514
  )
513
515
  if CONF_VALUE in char_conf:
514
- action_conf = {
515
- CONF_ID: char_conf[CONF_ID],
516
- CONF_VALUE: char_conf[CONF_VALUE],
517
- }
518
- value_action = await ble_server_characteristic_set_value(
519
- action_conf,
520
- char_conf[CONF_CHAR_VALUE_ACTION_ID_],
521
- cg.TemplateArguments(),
522
- {},
523
- )
524
- cg.add(value_action.play())
516
+ # Check if the value is templated (Lambda)
517
+ value_data = char_conf[CONF_VALUE][CONF_DATA]
518
+ if isinstance(value_data, cv.Lambda):
519
+ # Templated value - need the full action infrastructure
520
+ action_conf = {
521
+ CONF_ID: char_conf[CONF_ID],
522
+ CONF_VALUE: char_conf[CONF_VALUE],
523
+ }
524
+ value_action = await ble_server_characteristic_set_value(
525
+ action_conf,
526
+ char_conf[CONF_CHAR_VALUE_ACTION_ID_],
527
+ cg.TemplateArguments(),
528
+ {},
529
+ )
530
+ cg.add(value_action.play())
531
+ else:
532
+ # Static value - just set it directly without action infrastructure
533
+ value = await parse_value(char_conf[CONF_VALUE], {})
534
+ cg.add(char_var.set_value(value))
525
535
  for descriptor_conf in char_conf[CONF_DESCRIPTORS]:
526
536
  await to_code_descriptor(descriptor_conf, char_var)
527
537
 
@@ -560,12 +570,14 @@ async def to_code(config):
560
570
  else:
561
571
  cg.add(var.enqueue_start_service(service_var))
562
572
  if CONF_ON_CONNECT in config:
573
+ cg.add_define("USE_ESP32_BLE_SERVER_ON_CONNECT")
563
574
  await automation.build_automation(
564
575
  BLETriggers_ns.create_server_on_connect_trigger(var),
565
576
  [(cg.uint16, "id")],
566
577
  config[CONF_ON_CONNECT],
567
578
  )
568
579
  if CONF_ON_DISCONNECT in config:
580
+ cg.add_define("USE_ESP32_BLE_SERVER_ON_DISCONNECT")
569
581
  await automation.build_automation(
570
582
  BLETriggers_ns.create_server_on_disconnect_trigger(var),
571
583
  [(cg.uint16, "id")],
@@ -573,8 +585,7 @@ async def to_code(config):
573
585
  )
574
586
  cg.add_define("USE_ESP32_BLE_SERVER")
575
587
  cg.add_define("USE_ESP32_BLE_ADVERTISING")
576
- if CORE.using_esp_idf:
577
- add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
588
+ add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
578
589
 
579
590
 
580
591
  @automation.register_action(
@@ -595,6 +606,7 @@ async def ble_server_characteristic_set_value(config, action_id, template_arg, a
595
606
  var = cg.new_Pvariable(action_id, template_arg, paren)
596
607
  value = await parse_value(config[CONF_VALUE], args)
597
608
  cg.add(var.set_buffer(value))
609
+ cg.add_define("USE_ESP32_BLE_SERVER_SET_VALUE_ACTION")
598
610
  return var
599
611
 
600
612
 
@@ -613,6 +625,7 @@ async def ble_server_descriptor_set_value(config, action_id, template_arg, args)
613
625
  var = cg.new_Pvariable(action_id, template_arg, paren)
614
626
  value = await parse_value(config[CONF_VALUE], args)
615
627
  cg.add(var.set_buffer(value))
628
+ cg.add_define("USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION")
616
629
  return var
617
630
 
618
631
 
@@ -630,4 +643,5 @@ async def ble_server_descriptor_set_value(config, action_id, template_arg, args)
630
643
  )
631
644
  async def ble_server_characteristic_notify(config, action_id, template_arg, args):
632
645
  paren = await cg.get_variable(config[CONF_ID])
646
+ cg.add_define("USE_ESP32_BLE_SERVER_NOTIFY_ACTION")
633
647
  return cg.new_Pvariable(action_id, template_arg, paren)