esphome 2024.12.4__py3-none-any.whl → 2025.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. esphome/__main__.py +16 -3
  2. esphome/components/adc/__init__.py +17 -11
  3. esphome/components/adc/adc_sensor.h +17 -0
  4. esphome/components/adc/adc_sensor_common.cpp +55 -0
  5. esphome/components/adc/adc_sensor_esp32.cpp +8 -5
  6. esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
  7. esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
  8. esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
  9. esphome/components/adc/sensor.py +9 -3
  10. esphome/components/ads1115/ads1115.cpp +56 -7
  11. esphome/components/ads1115/ads1115.h +13 -1
  12. esphome/components/ads1115/sensor/__init__.py +16 -0
  13. esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
  14. esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
  15. esphome/components/animation/__init__.py +23 -261
  16. esphome/components/animation/animation.cpp +2 -2
  17. esphome/components/animation/animation.h +2 -1
  18. esphome/components/api/api_pb2.cpp +14 -0
  19. esphome/components/api/api_pb2.h +1 -0
  20. esphome/components/api/client.py +8 -3
  21. esphome/components/audio/__init__.py +112 -0
  22. esphome/components/audio/audio.cpp +67 -0
  23. esphome/components/audio/audio.h +125 -7
  24. esphome/components/audio/audio_decoder.cpp +361 -0
  25. esphome/components/audio/audio_decoder.h +135 -0
  26. esphome/components/audio/audio_reader.cpp +308 -0
  27. esphome/components/audio/audio_reader.h +85 -0
  28. esphome/components/audio/audio_resampler.cpp +159 -0
  29. esphome/components/audio/audio_resampler.h +101 -0
  30. esphome/components/audio/audio_transfer_buffer.cpp +165 -0
  31. esphome/components/audio/audio_transfer_buffer.h +139 -0
  32. esphome/components/audio_adc/__init__.py +41 -0
  33. esphome/components/audio_adc/audio_adc.h +17 -0
  34. esphome/components/audio_adc/automation.h +23 -0
  35. esphome/components/bk72xx/__init__.py +1 -0
  36. esphome/components/ble_client/ble_client.cpp +1 -2
  37. esphome/components/ble_client/sensor/__init__.py +1 -1
  38. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  39. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
  40. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
  41. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
  42. esphome/components/ch422g/ch422g.h +2 -0
  43. esphome/components/climate/__init__.py +1 -1
  44. esphome/components/climate_ir/climate_ir.cpp +2 -1
  45. esphome/components/coolix/coolix.cpp +2 -1
  46. esphome/components/cse7766/cse7766.cpp +8 -16
  47. esphome/components/custom/__init__.py +0 -3
  48. esphome/components/custom/binary_sensor/__init__.py +2 -28
  49. esphome/components/custom/climate/__init__.py +2 -27
  50. esphome/components/custom/cover/__init__.py +2 -27
  51. esphome/components/custom/light/__init__.py +2 -27
  52. esphome/components/custom/output/__init__.py +2 -58
  53. esphome/components/custom/sensor/__init__.py +2 -24
  54. esphome/components/custom/switch/__init__.py +2 -24
  55. esphome/components/custom/text_sensor/__init__.py +2 -29
  56. esphome/components/custom_component/__init__.py +3 -27
  57. esphome/components/daly_bms/daly_bms.cpp +6 -0
  58. esphome/components/daly_bms/daly_bms.h +2 -0
  59. esphome/components/daly_bms/sensor.py +6 -0
  60. esphome/components/debug/debug_component.cpp +4 -0
  61. esphome/components/debug/debug_component.h +14 -0
  62. esphome/components/debug/debug_esp32.cpp +154 -74
  63. esphome/components/dfplayer/dfplayer.cpp +15 -2
  64. esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
  65. esphome/components/dht/dht.cpp +4 -2
  66. esphome/components/dht/sensor.py +1 -1
  67. esphome/components/display/__init__.py +18 -5
  68. esphome/components/display/display.cpp +16 -3
  69. esphome/components/display/rect.cpp +2 -1
  70. esphome/components/es7210/__init__.py +0 -0
  71. esphome/components/es7210/audio_adc.py +51 -0
  72. esphome/components/es7210/es7210.cpp +228 -0
  73. esphome/components/es7210/es7210.h +62 -0
  74. esphome/components/es7210/es7210_const.h +129 -0
  75. esphome/components/es7243e/__init__.py +0 -0
  76. esphome/components/es7243e/audio_adc.py +34 -0
  77. esphome/components/es7243e/es7243e.cpp +125 -0
  78. esphome/components/es7243e/es7243e.h +37 -0
  79. esphome/components/es7243e/es7243e_const.h +54 -0
  80. esphome/components/es8156/__init__.py +0 -0
  81. esphome/components/es8156/audio_dac.py +27 -0
  82. esphome/components/es8156/es8156.cpp +87 -0
  83. esphome/components/es8156/es8156.h +51 -0
  84. esphome/components/es8156/es8156_const.h +68 -0
  85. esphome/components/es8311/audio_dac.py +1 -2
  86. esphome/components/esp32/__init__.py +1 -0
  87. esphome/components/esp32/core.cpp +5 -1
  88. esphome/components/esp32/gpio.h +2 -0
  89. esphome/components/esp32_ble/__init__.py +39 -0
  90. esphome/components/esp32_ble/queue.h +4 -4
  91. esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
  92. esphome/components/esp32_ble_client/ble_client_base.h +2 -0
  93. esphome/components/esp32_ble_server/__init__.py +582 -12
  94. esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
  95. esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
  96. esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
  97. esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
  98. esphome/components/esp32_ble_server/ble_server.cpp +62 -67
  99. esphome/components/esp32_ble_server/ble_server.h +28 -32
  100. esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
  101. esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
  102. esphome/components/esp32_ble_server/ble_service.cpp +17 -15
  103. esphome/components/esp32_ble_server/ble_service.h +10 -14
  104. esphome/components/esp32_ble_tracker/__init__.py +6 -39
  105. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
  106. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
  107. esphome/components/esp32_dac/esp32_dac.cpp +16 -7
  108. esphome/components/esp32_dac/esp32_dac.h +8 -0
  109. esphome/components/esp32_dac/output.py +16 -4
  110. esphome/components/esp32_improv/__init__.py +2 -8
  111. esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
  112. esphome/components/esp32_improv/esp32_improv_component.h +3 -4
  113. esphome/components/esp32_rmt/__init__.py +28 -3
  114. esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
  115. esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
  116. esphome/components/esp32_rmt_led_strip/light.py +72 -7
  117. esphome/components/esp32_touch/esp32_touch.cpp +5 -0
  118. esphome/components/esp8266/__init__.py +1 -0
  119. esphome/components/esp8266/gpio.h +1 -0
  120. esphome/components/ethernet/__init__.py +10 -10
  121. esphome/components/event/event.cpp +4 -2
  122. esphome/components/event/event.h +2 -0
  123. esphome/components/event_emitter/__init__.py +5 -0
  124. esphome/components/event_emitter/event_emitter.cpp +14 -0
  125. esphome/components/event_emitter/event_emitter.h +63 -0
  126. esphome/components/font/__init__.py +1 -1
  127. esphome/components/gcja5/gcja5.cpp +2 -1
  128. esphome/components/graph/graph.cpp +4 -9
  129. esphome/components/haier/haier_base.cpp +2 -1
  130. esphome/components/haier/hon_climate.cpp +2 -1
  131. esphome/components/heatpumpir/heatpumpir.cpp +2 -1
  132. esphome/components/host/__init__.py +1 -0
  133. esphome/components/host/gpio.h +1 -0
  134. esphome/components/http_request/http_request.h +2 -2
  135. esphome/components/http_request/http_request_arduino.cpp +1 -1
  136. esphome/components/http_request/http_request_idf.cpp +1 -1
  137. esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
  138. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
  139. esphome/components/i2s_audio/speaker/__init__.py +53 -6
  140. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
  141. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
  142. esphome/components/ili9xxx/display.py +29 -11
  143. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
  144. esphome/components/ili9xxx/ili9xxx_display.h +2 -1
  145. esphome/components/image/__init__.py +443 -255
  146. esphome/components/image/image.cpp +115 -61
  147. esphome/components/image/image.h +15 -24
  148. esphome/components/json/json_util.cpp +8 -34
  149. esphome/components/libretiny/__init__.py +1 -0
  150. esphome/components/libretiny/gpio_arduino.h +1 -0
  151. esphome/components/light/light_color_values.h +1 -1
  152. esphome/components/logger/__init__.py +45 -9
  153. esphome/components/logger/logger.cpp +16 -14
  154. esphome/components/logger/logger.h +11 -7
  155. esphome/components/logger/select/__init__.py +29 -0
  156. esphome/components/logger/select/logger_level_select.cpp +27 -0
  157. esphome/components/logger/select/logger_level_select.h +15 -0
  158. esphome/components/lvgl/__init__.py +96 -73
  159. esphome/components/lvgl/automation.py +39 -7
  160. esphome/components/lvgl/defines.py +8 -2
  161. esphome/components/lvgl/lvgl_esphome.cpp +8 -15
  162. esphome/components/lvgl/lvgl_esphome.h +20 -5
  163. esphome/components/lvgl/schemas.py +25 -14
  164. esphome/components/lvgl/trigger.py +27 -3
  165. esphome/components/lvgl/widgets/dropdown.py +1 -1
  166. esphome/components/lvgl/widgets/keyboard.py +8 -1
  167. esphome/components/lvgl/widgets/meter.py +2 -1
  168. esphome/components/lvgl/widgets/msgbox.py +1 -1
  169. esphome/components/lvgl/widgets/obj.py +1 -12
  170. esphome/components/lvgl/widgets/page.py +37 -2
  171. esphome/components/lvgl/widgets/tabview.py +1 -1
  172. esphome/components/max6956/max6956.h +2 -0
  173. esphome/components/mcp23016/mcp23016.h +2 -0
  174. esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
  175. esphome/components/mdns/__init__.py +1 -1
  176. esphome/components/media_player/__init__.py +37 -8
  177. esphome/components/media_player/automation.h +11 -2
  178. esphome/components/media_player/media_player.cpp +8 -0
  179. esphome/components/media_player/media_player.h +8 -4
  180. esphome/components/micronova/switch/micronova_switch.cpp +4 -2
  181. esphome/components/midea/ac_automations.h +3 -1
  182. esphome/components/midea/air_conditioner.cpp +7 -5
  183. esphome/components/midea/air_conditioner.h +1 -1
  184. esphome/components/midea/climate.py +4 -2
  185. esphome/components/midea/ir_transmitter.h +36 -5
  186. esphome/components/mixer/__init__.py +0 -0
  187. esphome/components/mixer/speaker/__init__.py +172 -0
  188. esphome/components/mixer/speaker/automation.h +19 -0
  189. esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
  190. esphome/components/mixer/speaker/mixer_speaker.h +207 -0
  191. esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +7 -13
  192. esphome/components/mpr121/mpr121.h +2 -0
  193. esphome/components/mqtt/__init__.py +1 -1
  194. esphome/components/mqtt/mqtt_client.cpp +7 -1
  195. esphome/components/mqtt/mqtt_client.h +1 -1
  196. esphome/components/mqtt/mqtt_climate.cpp +2 -2
  197. esphome/components/network/ip_address.h +2 -0
  198. esphome/components/nextion/automation.h +17 -0
  199. esphome/components/nextion/display.py +42 -17
  200. esphome/components/nextion/nextion.cpp +4 -10
  201. esphome/components/nextion/nextion.h +89 -82
  202. esphome/components/nextion/nextion_commands.cpp +10 -10
  203. esphome/components/ntc/sensor.py +2 -4
  204. esphome/components/online_image/__init__.py +98 -46
  205. esphome/components/online_image/bmp_image.cpp +101 -0
  206. esphome/components/online_image/bmp_image.h +40 -0
  207. esphome/components/online_image/image_decoder.cpp +31 -2
  208. esphome/components/online_image/image_decoder.h +24 -15
  209. esphome/components/online_image/jpeg_image.cpp +92 -0
  210. esphome/components/online_image/jpeg_image.h +34 -0
  211. esphome/components/online_image/online_image.cpp +118 -58
  212. esphome/components/online_image/online_image.h +39 -9
  213. esphome/components/online_image/png_image.cpp +7 -3
  214. esphome/components/online_image/png_image.h +2 -1
  215. esphome/components/opentherm/__init__.py +73 -7
  216. esphome/components/opentherm/automation.h +25 -0
  217. esphome/components/opentherm/const.py +1 -0
  218. esphome/components/opentherm/generate.py +39 -6
  219. esphome/components/opentherm/hub.cpp +117 -79
  220. esphome/components/opentherm/hub.h +31 -15
  221. esphome/components/opentherm/opentherm.cpp +47 -23
  222. esphome/components/opentherm/opentherm.h +27 -6
  223. esphome/components/opentherm/opentherm_macros.h +11 -0
  224. esphome/components/opentherm/schema.py +78 -1
  225. esphome/components/opentherm/validate.py +7 -2
  226. esphome/components/pca6416a/pca6416a.h +2 -0
  227. esphome/components/pca9554/pca9554.h +2 -0
  228. esphome/components/pcf8574/pcf8574.h +2 -0
  229. esphome/components/preferences/__init__.py +2 -4
  230. esphome/components/preferences/syncer.h +10 -3
  231. esphome/components/prometheus/prometheus_handler.cpp +313 -0
  232. esphome/components/prometheus/prometheus_handler.h +48 -7
  233. esphome/components/psram/psram.cpp +8 -1
  234. esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
  235. esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
  236. esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
  237. esphome/components/qspi_dbi/__init__.py +3 -0
  238. esphome/components/qspi_dbi/display.py +74 -47
  239. esphome/components/qspi_dbi/models.py +245 -2
  240. esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
  241. esphome/components/qspi_dbi/qspi_dbi.h +2 -2
  242. esphome/components/remote_base/__init__.py +77 -25
  243. esphome/components/remote_base/remote_base.cpp +1 -1
  244. esphome/components/remote_base/remote_base.h +20 -2
  245. esphome/components/remote_base/toto_protocol.cpp +100 -0
  246. esphome/components/remote_base/toto_protocol.h +45 -0
  247. esphome/components/remote_receiver/__init__.py +55 -10
  248. esphome/components/remote_receiver/remote_receiver.h +36 -3
  249. esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
  250. esphome/components/remote_transmitter/__init__.py +62 -4
  251. esphome/components/remote_transmitter/remote_transmitter.h +21 -2
  252. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
  253. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
  254. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
  255. esphome/components/resampler/__init__.py +0 -0
  256. esphome/components/resampler/speaker/__init__.py +103 -0
  257. esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
  258. esphome/components/resampler/speaker/resampler_speaker.h +107 -0
  259. esphome/components/resistance/resistance_sensor.h +2 -3
  260. esphome/components/resistance/sensor.py +2 -9
  261. esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
  262. esphome/components/rp2040/__init__.py +1 -0
  263. esphome/components/rp2040/gpio.h +1 -0
  264. esphome/components/rtl87xx/__init__.py +2 -0
  265. esphome/components/scd30/sensor.py +1 -1
  266. esphome/components/sdl/binary_sensor.py +270 -0
  267. esphome/components/sdl/sdl_esphome.cpp +16 -0
  268. esphome/components/sdl/sdl_esphome.h +9 -0
  269. esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
  270. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
  271. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
  272. esphome/components/seeed_mr60bha2/sensor.py +9 -1
  273. esphome/components/sn74hc165/sn74hc165.h +3 -0
  274. esphome/components/sn74hc595/sn74hc595.h +3 -0
  275. esphome/components/speaker/__init__.py +5 -4
  276. esphome/components/speaker/media_player/__init__.py +458 -0
  277. esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
  278. esphome/components/speaker/media_player/audio_pipeline.h +159 -0
  279. esphome/components/speaker/media_player/automation.h +26 -0
  280. esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
  281. esphome/components/speaker/media_player/speaker_media_player.h +160 -0
  282. esphome/components/speaker/speaker.h +20 -0
  283. esphome/components/spi/__init__.py +1 -5
  284. esphome/components/spi/spi.cpp +7 -1
  285. esphome/components/spi/spi.h +21 -2
  286. esphome/components/spi_led_strip/light.py +3 -5
  287. esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
  288. esphome/components/spi_led_strip/spi_led_strip.h +8 -60
  289. esphome/components/sprinkler/sprinkler.cpp +3 -1
  290. esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
  291. esphome/components/tca9555/tca9555.h +2 -0
  292. esphome/components/toshiba/toshiba.cpp +2 -1
  293. esphome/components/tuya/light/tuya_light.cpp +4 -2
  294. esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
  295. esphome/components/uart/uart_component_esp_idf.cpp +2 -2
  296. esphome/components/udp/__init__.py +8 -2
  297. esphome/components/udp/udp_component.cpp +25 -56
  298. esphome/components/udp/udp_component.h +3 -0
  299. esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
  300. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
  301. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
  302. esphome/components/uptime/text_sensor/__init__.py +19 -0
  303. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
  304. esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
  305. esphome/components/voice_assistant/voice_assistant.cpp +24 -14
  306. esphome/components/voice_assistant/voice_assistant.h +8 -0
  307. esphome/components/waveshare_epaper/display.py +22 -1
  308. esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
  309. esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
  310. esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
  311. esphome/components/web_server/web_server.cpp +28 -6
  312. esphome/components/weikai/weikai.h +2 -0
  313. esphome/components/wifi/__init__.py +6 -6
  314. esphome/components/wifi/wifi_component.cpp +1 -1
  315. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
  316. esphome/components/wireguard/__init__.py +2 -2
  317. esphome/components/xl9535/xl9535.h +2 -0
  318. esphome/components/xxtea/__init__.py +3 -0
  319. esphome/components/xxtea/xxtea.cpp +46 -0
  320. esphome/components/xxtea/xxtea.h +26 -0
  321. esphome/components/yashima/yashima.cpp +2 -1
  322. esphome/config.py +9 -5
  323. esphome/config_validation.py +55 -17
  324. esphome/const.py +7 -10
  325. esphome/core/__init__.py +6 -13
  326. esphome/core/base_automation.h +1 -0
  327. esphome/core/config.py +59 -72
  328. esphome/core/defines.h +9 -1
  329. esphome/core/gpio.h +7 -0
  330. esphome/core/helpers.cpp +19 -15
  331. esphome/core/helpers.h +57 -8
  332. esphome/core/log.h +9 -7
  333. esphome/cpp_generator.py +2 -2
  334. esphome/dashboard/web_server.py +1 -1
  335. esphome/espota2.py +3 -2
  336. esphome/loader.py +12 -4
  337. esphome/log.py +5 -7
  338. esphome/yaml_util.py +2 -2
  339. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/METADATA +14 -9
  340. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/RECORD +349 -300
  341. esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
  342. esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
  343. esphome/components/custom/climate/custom_climate.h +0 -22
  344. esphome/components/custom/cover/custom_cover.h +0 -21
  345. esphome/components/custom/light/custom_light_output.h +0 -24
  346. esphome/components/custom/output/custom_output.h +0 -37
  347. esphome/components/custom/sensor/custom_sensor.cpp +0 -16
  348. esphome/components/custom/sensor/custom_sensor.h +0 -24
  349. esphome/components/custom/switch/custom_switch.cpp +0 -16
  350. esphome/components/custom/switch/custom_switch.h +0 -24
  351. esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
  352. esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
  353. esphome/components/custom_component/custom_component.h +0 -28
  354. esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
  355. esphome/components/esp32_ble_server/ble_2901.h +0 -19
  356. esphome/components/resistance_sampler/__init__.py +0 -6
  357. esphome/components/resistance_sampler/resistance_sampler.h +0 -10
  358. esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
  359. /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
  360. /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
  361. /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
  362. /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
  363. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/LICENSE +0 -0
  364. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/WHEEL +0 -0
  365. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/entry_points.txt +0 -0
  366. {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/top_level.txt +0 -0
@@ -32,70 +32,36 @@ BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties)
32
32
  this->set_write_no_response_property((properties & PROPERTY_WRITE_NR) != 0);
33
33
  }
34
34
 
35
- void BLECharacteristic::set_value(std::vector<uint8_t> value) {
35
+ void BLECharacteristic::set_value(ByteBuffer buffer) { this->set_value(buffer.get_data()); }
36
+
37
+ void BLECharacteristic::set_value(const std::vector<uint8_t> &buffer) {
36
38
  xSemaphoreTake(this->set_value_lock_, 0L);
37
- this->value_ = std::move(value);
39
+ this->value_ = buffer;
38
40
  xSemaphoreGive(this->set_value_lock_);
39
41
  }
40
- void BLECharacteristic::set_value(const std::string &value) {
41
- this->set_value(std::vector<uint8_t>(value.begin(), value.end()));
42
- }
43
- void BLECharacteristic::set_value(const uint8_t *data, size_t length) {
44
- this->set_value(std::vector<uint8_t>(data, data + length));
45
- }
46
- void BLECharacteristic::set_value(uint8_t &data) {
47
- uint8_t temp[1];
48
- temp[0] = data;
49
- this->set_value(temp, 1);
50
- }
51
- void BLECharacteristic::set_value(uint16_t &data) {
52
- uint8_t temp[2];
53
- temp[0] = data;
54
- temp[1] = data >> 8;
55
- this->set_value(temp, 2);
56
- }
57
- void BLECharacteristic::set_value(uint32_t &data) {
58
- uint8_t temp[4];
59
- temp[0] = data;
60
- temp[1] = data >> 8;
61
- temp[2] = data >> 16;
62
- temp[3] = data >> 24;
63
- this->set_value(temp, 4);
64
- }
65
- void BLECharacteristic::set_value(int &data) {
66
- uint8_t temp[4];
67
- temp[0] = data;
68
- temp[1] = data >> 8;
69
- temp[2] = data >> 16;
70
- temp[3] = data >> 24;
71
- this->set_value(temp, 4);
72
- }
73
- void BLECharacteristic::set_value(float &data) {
74
- float temp = data;
75
- this->set_value((uint8_t *) &temp, 4);
76
- }
77
- void BLECharacteristic::set_value(double &data) {
78
- double temp = data;
79
- this->set_value((uint8_t *) &temp, 8);
80
- }
81
- void BLECharacteristic::set_value(bool &data) {
82
- uint8_t temp[1];
83
- temp[0] = data;
84
- this->set_value(temp, 1);
42
+ void BLECharacteristic::set_value(const std::string &buffer) {
43
+ this->set_value(std::vector<uint8_t>(buffer.begin(), buffer.end()));
85
44
  }
86
45
 
87
- void BLECharacteristic::notify(bool notification) {
88
- if (!notification) {
89
- ESP_LOGW(TAG, "notification=false is not yet supported");
90
- // TODO: Handle when notification=false
91
- }
92
- if (this->service_->get_server()->get_connected_client_count() == 0)
46
+ void BLECharacteristic::notify() {
47
+ if (this->service_ == nullptr || this->service_->get_server() == nullptr ||
48
+ this->service_->get_server()->get_connected_client_count() == 0)
93
49
  return;
94
50
 
95
51
  for (auto &client : this->service_->get_server()->get_clients()) {
96
52
  size_t length = this->value_.size();
97
- esp_err_t err = esp_ble_gatts_send_indicate(this->service_->get_server()->get_gatts_if(), client.first,
98
- this->handle_, length, this->value_.data(), false);
53
+ // If the client is not in the list of clients to notify, skip it
54
+ if (this->clients_to_notify_.count(client) == 0)
55
+ continue;
56
+ // If the client is in the list of clients to notify, check if it requires an ack (i.e. INDICATE)
57
+ bool require_ack = this->clients_to_notify_[client];
58
+ // TODO: Remove this block when INDICATE acknowledgment is supported
59
+ if (require_ack) {
60
+ ESP_LOGW(TAG, "INDICATE acknowledgment is not yet supported (i.e. it works as a NOTIFY)");
61
+ require_ack = false;
62
+ }
63
+ esp_err_t err = esp_ble_gatts_send_indicate(this->service_->get_server()->get_gatts_if(), client, this->handle_,
64
+ length, this->value_.data(), require_ack);
99
65
  if (err != ESP_OK) {
100
66
  ESP_LOGE(TAG, "esp_ble_gatts_send_indicate failed %d", err);
101
67
  return;
@@ -103,7 +69,24 @@ void BLECharacteristic::notify(bool notification) {
103
69
  }
104
70
  }
105
71
 
106
- void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { this->descriptors_.push_back(descriptor); }
72
+ void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) {
73
+ // If the descriptor is the CCCD descriptor, listen to its write event to know if the client wants to be notified
74
+ if (descriptor->get_uuid() == ESPBTUUID::from_uint16(ESP_GATT_UUID_CHAR_CLIENT_CONFIG)) {
75
+ descriptor->on(BLEDescriptorEvt::VectorEvt::ON_WRITE, [this](const std::vector<uint8_t> &value, uint16_t conn_id) {
76
+ if (value.size() != 2)
77
+ return;
78
+ uint16_t cccd = encode_uint16(value[1], value[0]);
79
+ bool notify = (cccd & 1) != 0;
80
+ bool indicate = (cccd & 2) != 0;
81
+ if (notify || indicate) {
82
+ this->clients_to_notify_[conn_id] = indicate;
83
+ } else {
84
+ this->clients_to_notify_.erase(conn_id);
85
+ }
86
+ });
87
+ }
88
+ this->descriptors_.push_back(descriptor);
89
+ }
107
90
 
108
91
  void BLECharacteristic::remove_descriptor(BLEDescriptor *descriptor) {
109
92
  this->descriptors_.erase(std::remove(this->descriptors_.begin(), this->descriptors_.end(), descriptor),
@@ -223,6 +206,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
223
206
  if (!param->read.need_rsp)
224
207
  break; // For some reason you can request a read but not want a response
225
208
 
209
+ this->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::emit_(BLECharacteristicEvt::EmptyEvt::ON_READ,
210
+ param->read.conn_id);
211
+
226
212
  uint16_t max_offset = 22;
227
213
 
228
214
  esp_gatt_rsp_t response;
@@ -262,13 +248,13 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
262
248
  }
263
249
  case ESP_GATTS_WRITE_EVT: {
264
250
  if (this->handle_ != param->write.handle)
265
- return;
251
+ break;
266
252
 
267
253
  if (param->write.is_prep) {
268
254
  this->value_.insert(this->value_.end(), param->write.value, param->write.value + param->write.len);
269
255
  this->write_event_ = true;
270
256
  } else {
271
- this->set_value(param->write.value, param->write.len);
257
+ this->set_value(ByteBuffer::wrap(param->write.value, param->write.len));
272
258
  }
273
259
 
274
260
  if (param->write.need_rsp) {
@@ -289,7 +275,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
289
275
  }
290
276
 
291
277
  if (!param->write.is_prep) {
292
- this->on_write_(this->value_);
278
+ this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_(
279
+ BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->write.conn_id);
293
280
  }
294
281
 
295
282
  break;
@@ -300,7 +287,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
300
287
  break;
301
288
  this->write_event_ = false;
302
289
  if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
303
- this->on_write_(this->value_);
290
+ this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_(
291
+ BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->exec_write.conn_id);
304
292
  }
305
293
  esp_err_t err =
306
294
  esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr);
@@ -2,8 +2,11 @@
2
2
 
3
3
  #include "ble_descriptor.h"
4
4
  #include "esphome/components/esp32_ble/ble_uuid.h"
5
+ #include "esphome/components/event_emitter/event_emitter.h"
6
+ #include "esphome/components/bytebuffer/bytebuffer.h"
5
7
 
6
8
  #include <vector>
9
+ #include <unordered_map>
7
10
 
8
11
  #ifdef USE_ESP32
9
12
 
@@ -19,24 +22,30 @@ namespace esphome {
19
22
  namespace esp32_ble_server {
20
23
 
21
24
  using namespace esp32_ble;
25
+ using namespace bytebuffer;
26
+ using namespace event_emitter;
22
27
 
23
28
  class BLEService;
24
29
 
25
- class BLECharacteristic {
30
+ namespace BLECharacteristicEvt {
31
+ enum VectorEvt {
32
+ ON_WRITE,
33
+ };
34
+
35
+ enum EmptyEvt {
36
+ ON_READ,
37
+ };
38
+ } // namespace BLECharacteristicEvt
39
+
40
+ class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>,
41
+ public EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t> {
26
42
  public:
27
43
  BLECharacteristic(ESPBTUUID uuid, uint32_t properties);
28
44
  ~BLECharacteristic();
29
45
 
30
- void set_value(const uint8_t *data, size_t length);
31
- void set_value(std::vector<uint8_t> value);
32
- void set_value(const std::string &value);
33
- void set_value(uint8_t &data);
34
- void set_value(uint16_t &data);
35
- void set_value(uint32_t &data);
36
- void set_value(int &data);
37
- void set_value(float &data);
38
- void set_value(double &data);
39
- void set_value(bool &data);
46
+ void set_value(ByteBuffer buffer);
47
+ void set_value(const std::vector<uint8_t> &buffer);
48
+ void set_value(const std::string &buffer);
40
49
 
41
50
  void set_broadcast_property(bool value);
42
51
  void set_indicate_property(bool value);
@@ -45,13 +54,12 @@ class BLECharacteristic {
45
54
  void set_write_property(bool value);
46
55
  void set_write_no_response_property(bool value);
47
56
 
48
- void notify(bool notification = true);
57
+ void notify();
49
58
 
50
59
  void do_create(BLEService *service);
60
+ void do_delete() { this->clients_to_notify_.clear(); }
51
61
  void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
52
62
 
53
- void on_write(const std::function<void(const std::vector<uint8_t> &)> &&func) { this->on_write_ = func; }
54
-
55
63
  void add_descriptor(BLEDescriptor *descriptor);
56
64
  void remove_descriptor(BLEDescriptor *descriptor);
57
65
 
@@ -71,7 +79,7 @@ class BLECharacteristic {
71
79
 
72
80
  protected:
73
81
  bool write_event_{false};
74
- BLEService *service_;
82
+ BLEService *service_{};
75
83
  ESPBTUUID uuid_;
76
84
  esp_gatt_char_prop_t properties_;
77
85
  uint16_t handle_{0xFFFF};
@@ -81,8 +89,7 @@ class BLECharacteristic {
81
89
  SemaphoreHandle_t set_value_lock_;
82
90
 
83
91
  std::vector<BLEDescriptor *> descriptors_;
84
-
85
- std::function<void(const std::vector<uint8_t> &)> on_write_;
92
+ std::unordered_map<uint16_t, bool> clients_to_notify_;
86
93
 
87
94
  esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
88
95
 
@@ -12,11 +12,19 @@ namespace esp32_ble_server {
12
12
 
13
13
  static const char *const TAG = "esp32_ble_server.descriptor";
14
14
 
15
- BLEDescriptor::BLEDescriptor(ESPBTUUID uuid, uint16_t max_len) {
15
+ static RAMAllocator<uint8_t> descriptor_allocator{}; // NOLINT
16
+
17
+ BLEDescriptor::BLEDescriptor(ESPBTUUID uuid, uint16_t max_len, bool read, bool write) {
16
18
  this->uuid_ = uuid;
17
19
  this->value_.attr_len = 0;
18
20
  this->value_.attr_max_len = max_len;
19
- this->value_.attr_value = (uint8_t *) malloc(max_len); // NOLINT
21
+ this->value_.attr_value = descriptor_allocator.allocate(max_len);
22
+ if (read) {
23
+ this->permissions_ |= ESP_GATT_PERM_READ;
24
+ }
25
+ if (write) {
26
+ this->permissions_ |= ESP_GATT_PERM_WRITE;
27
+ }
20
28
  }
21
29
 
22
30
  BLEDescriptor::~BLEDescriptor() { free(this->value_.attr_value); } // NOLINT
@@ -38,14 +46,15 @@ void BLEDescriptor::do_create(BLECharacteristic *characteristic) {
38
46
  this->state_ = CREATING;
39
47
  }
40
48
 
41
- void BLEDescriptor::set_value(const std::string &value) { this->set_value((uint8_t *) value.data(), value.length()); }
42
- void BLEDescriptor::set_value(const uint8_t *data, size_t length) {
49
+ void BLEDescriptor::set_value(std::vector<uint8_t> buffer) {
50
+ size_t length = buffer.size();
51
+
43
52
  if (length > this->value_.attr_max_len) {
44
53
  ESP_LOGE(TAG, "Size %d too large, must be no bigger than %d", length, this->value_.attr_max_len);
45
54
  return;
46
55
  }
47
56
  this->value_.attr_len = length;
48
- memcpy(this->value_.attr_value, data, length);
57
+ memcpy(this->value_.attr_value, buffer.data(), length);
49
58
  }
50
59
 
51
60
  void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
@@ -61,10 +70,13 @@ void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
61
70
  break;
62
71
  }
63
72
  case ESP_GATTS_WRITE_EVT: {
64
- if (this->handle_ == param->write.handle) {
65
- this->value_.attr_len = param->write.len;
66
- memcpy(this->value_.attr_value, param->write.value, param->write.len);
67
- }
73
+ if (this->handle_ != param->write.handle)
74
+ break;
75
+ this->value_.attr_len = param->write.len;
76
+ memcpy(this->value_.attr_value, param->write.value, param->write.len);
77
+ this->emit_(BLEDescriptorEvt::VectorEvt::ON_WRITE,
78
+ std::vector<uint8_t>(param->write.value, param->write.value + param->write.len),
79
+ param->write.conn_id);
68
80
  break;
69
81
  }
70
82
  default:
@@ -1,6 +1,8 @@
1
1
  #pragma once
2
2
 
3
3
  #include "esphome/components/esp32_ble/ble_uuid.h"
4
+ #include "esphome/components/event_emitter/event_emitter.h"
5
+ #include "esphome/components/bytebuffer/bytebuffer.h"
4
6
 
5
7
  #ifdef USE_ESP32
6
8
 
@@ -11,17 +13,26 @@ namespace esphome {
11
13
  namespace esp32_ble_server {
12
14
 
13
15
  using namespace esp32_ble;
16
+ using namespace bytebuffer;
17
+ using namespace event_emitter;
14
18
 
15
19
  class BLECharacteristic;
16
20
 
17
- class BLEDescriptor {
21
+ namespace BLEDescriptorEvt {
22
+ enum VectorEvt {
23
+ ON_WRITE,
24
+ };
25
+ } // namespace BLEDescriptorEvt
26
+
27
+ class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>, uint16_t> {
18
28
  public:
19
- BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100);
29
+ BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100, bool read = true, bool write = true);
20
30
  virtual ~BLEDescriptor();
21
31
  void do_create(BLECharacteristic *characteristic);
32
+ ESPBTUUID get_uuid() const { return this->uuid_; }
22
33
 
23
- void set_value(const std::string &value);
24
- void set_value(const uint8_t *data, size_t length);
34
+ void set_value(std::vector<uint8_t> buffer);
35
+ void set_value(ByteBuffer buffer) { this->set_value(buffer.get_data()); }
25
36
 
26
37
  void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
27
38
 
@@ -33,9 +44,9 @@ class BLEDescriptor {
33
44
  ESPBTUUID uuid_;
34
45
  uint16_t handle_{0xFFFF};
35
46
 
36
- esp_attr_value_t value_;
47
+ esp_attr_value_t value_{};
37
48
 
38
- esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
49
+ esp_gatt_perm_t permissions_{};
39
50
 
40
51
  enum State : uint8_t {
41
52
  FAILED = 0x00,
@@ -19,11 +19,6 @@ namespace esp32_ble_server {
19
19
 
20
20
  static const char *const TAG = "esp32_ble_server";
21
21
 
22
- static const uint16_t DEVICE_INFORMATION_SERVICE_UUID = 0x180A;
23
- static const uint16_t MODEL_UUID = 0x2A24;
24
- static const uint16_t VERSION_UUID = 0x2A26;
25
- static const uint16_t MANUFACTURER_UUID = 0x2A29;
26
-
27
22
  void BLEServer::setup() {
28
23
  if (this->parent_->is_failed()) {
29
24
  this->mark_failed();
@@ -38,9 +33,27 @@ void BLEServer::loop() {
38
33
  return;
39
34
  }
40
35
  switch (this->state_) {
41
- case RUNNING:
42
- return;
43
-
36
+ case RUNNING: {
37
+ // Start all services that are pending to start
38
+ if (!this->services_to_start_.empty()) {
39
+ uint16_t index_to_remove = 0;
40
+ // Iterate over the services to start
41
+ for (unsigned i = 0; i < this->services_to_start_.size(); i++) {
42
+ BLEService *service = this->services_to_start_[i];
43
+ if (service->is_created()) {
44
+ service->start(); // Needs to be called once per characteristic in the service
45
+ } else {
46
+ index_to_remove = i + 1;
47
+ }
48
+ }
49
+ // Remove the services that have been started
50
+ if (index_to_remove > 0) {
51
+ this->services_to_start_.erase(this->services_to_start_.begin(),
52
+ this->services_to_start_.begin() + index_to_remove - 1);
53
+ }
54
+ }
55
+ break;
56
+ }
44
57
  case INIT: {
45
58
  esp_err_t err = esp_ble_gatts_app_register(0);
46
59
  if (err != ESP_OK) {
@@ -53,29 +66,26 @@ void BLEServer::loop() {
53
66
  }
54
67
  case REGISTERING: {
55
68
  if (this->registered_) {
69
+ // Create the device information service first so
70
+ // it is at the top of the GATT table
71
+ this->device_information_service_->do_create(this);
56
72
  // Create all services previously created
57
73
  for (auto &pair : this->services_) {
74
+ if (pair.second == this->device_information_service_) {
75
+ continue;
76
+ }
58
77
  pair.second->do_create(this);
59
78
  }
60
- if (this->device_information_service_ == nullptr) {
61
- this->create_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID));
62
- this->device_information_service_ =
63
- this->get_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID));
64
- this->create_device_characteristics_();
65
- }
66
79
  this->state_ = STARTING_SERVICE;
67
80
  }
68
81
  break;
69
82
  }
70
83
  case STARTING_SERVICE: {
71
- if (!this->device_information_service_->is_created()) {
72
- break;
73
- }
74
84
  if (this->device_information_service_->is_running()) {
75
85
  this->state_ = RUNNING;
76
86
  this->restart_advertising_();
77
87
  ESP_LOGD(TAG, "BLE server setup successfully");
78
- } else if (!this->device_information_service_->is_starting()) {
88
+ } else if (this->device_information_service_->is_created()) {
79
89
  this->device_information_service_->start();
80
90
  }
81
91
  break;
@@ -93,81 +103,66 @@ void BLEServer::restart_advertising_() {
93
103
  }
94
104
  }
95
105
 
96
- bool BLEServer::create_device_characteristics_() {
97
- if (this->model_.has_value()) {
98
- BLECharacteristic *model =
99
- this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
100
- model->set_value(this->model_.value());
101
- } else {
102
- BLECharacteristic *model =
103
- this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
104
- model->set_value(ESPHOME_BOARD);
105
- }
106
-
107
- BLECharacteristic *version =
108
- this->device_information_service_->create_characteristic(VERSION_UUID, BLECharacteristic::PROPERTY_READ);
109
- version->set_value("ESPHome " ESPHOME_VERSION);
110
-
111
- BLECharacteristic *manufacturer =
112
- this->device_information_service_->create_characteristic(MANUFACTURER_UUID, BLECharacteristic::PROPERTY_READ);
113
- manufacturer->set_value(this->manufacturer_);
114
-
115
- return true;
116
- }
117
-
118
- void BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t num_handles, uint8_t inst_id) {
106
+ BLEService *BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t num_handles) {
119
107
  ESP_LOGV(TAG, "Creating BLE service - %s", uuid.to_string().c_str());
120
- // If the service already exists, do nothing
121
- BLEService *service = this->get_service(uuid);
122
- if (service != nullptr) {
123
- ESP_LOGW(TAG, "BLE service %s already exists", uuid.to_string().c_str());
124
- return;
108
+ // Calculate the inst_id for the service
109
+ uint8_t inst_id = 0;
110
+ for (; inst_id < 0xFF; inst_id++) {
111
+ if (this->get_service(uuid, inst_id) == nullptr) {
112
+ break;
113
+ }
114
+ }
115
+ if (inst_id == 0xFF) {
116
+ ESP_LOGW(TAG, "Could not create BLE service %s, too many instances", uuid.to_string().c_str());
117
+ return nullptr;
125
118
  }
126
- service = new BLEService(uuid, num_handles, inst_id, advertise); // NOLINT(cppcoreguidelines-owning-memory)
127
- this->services_.emplace(uuid.to_string(), service);
128
- service->do_create(this);
119
+ BLEService *service = // NOLINT(cppcoreguidelines-owning-memory)
120
+ new BLEService(uuid, num_handles, inst_id, advertise);
121
+ this->services_.emplace(BLEServer::get_service_key(uuid, inst_id), service);
122
+ if (this->parent_->is_active() && this->registered_) {
123
+ service->do_create(this);
124
+ }
125
+ return service;
129
126
  }
130
127
 
131
- void BLEServer::remove_service(ESPBTUUID uuid) {
132
- ESP_LOGV(TAG, "Removing BLE service - %s", uuid.to_string().c_str());
133
- BLEService *service = this->get_service(uuid);
128
+ void BLEServer::remove_service(ESPBTUUID uuid, uint8_t inst_id) {
129
+ ESP_LOGV(TAG, "Removing BLE service - %s %d", uuid.to_string().c_str(), inst_id);
130
+ BLEService *service = this->get_service(uuid, inst_id);
134
131
  if (service == nullptr) {
135
- ESP_LOGW(TAG, "BLE service %s not found", uuid.to_string().c_str());
132
+ ESP_LOGW(TAG, "BLE service %s %d does not exist", uuid.to_string().c_str(), inst_id);
136
133
  return;
137
134
  }
138
135
  service->do_delete();
139
136
  delete service; // NOLINT(cppcoreguidelines-owning-memory)
140
- this->services_.erase(uuid.to_string());
137
+ this->services_.erase(BLEServer::get_service_key(uuid, inst_id));
141
138
  }
142
139
 
143
- BLEService *BLEServer::get_service(ESPBTUUID uuid) {
140
+ BLEService *BLEServer::get_service(ESPBTUUID uuid, uint8_t inst_id) {
144
141
  BLEService *service = nullptr;
145
- if (this->services_.count(uuid.to_string()) > 0) {
146
- service = this->services_.at(uuid.to_string());
142
+ if (this->services_.count(BLEServer::get_service_key(uuid, inst_id)) > 0) {
143
+ service = this->services_.at(BLEServer::get_service_key(uuid, inst_id));
147
144
  }
148
145
  return service;
149
146
  }
150
147
 
148
+ std::string BLEServer::get_service_key(ESPBTUUID uuid, uint8_t inst_id) {
149
+ return uuid.to_string() + std::to_string(inst_id);
150
+ }
151
+
151
152
  void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
152
153
  esp_ble_gatts_cb_param_t *param) {
153
154
  switch (event) {
154
155
  case ESP_GATTS_CONNECT_EVT: {
155
156
  ESP_LOGD(TAG, "BLE Client connected");
156
- this->add_client_(param->connect.conn_id, (void *) this);
157
- this->connected_clients_++;
158
- for (auto *component : this->service_components_) {
159
- component->on_client_connect();
160
- }
157
+ this->add_client_(param->connect.conn_id);
158
+ this->emit_(BLEServerEvt::EmptyEvt::ON_CONNECT, param->connect.conn_id);
161
159
  break;
162
160
  }
163
161
  case ESP_GATTS_DISCONNECT_EVT: {
164
162
  ESP_LOGD(TAG, "BLE Client disconnected");
165
- if (this->remove_client_(param->disconnect.conn_id))
166
- this->connected_clients_--;
163
+ this->remove_client_(param->disconnect.conn_id);
167
164
  this->parent_->advertising_start();
168
- for (auto *component : this->service_components_) {
169
- component->on_client_disconnect();
170
- }
165
+ this->emit_(BLEServerEvt::EmptyEvt::ON_DISCONNECT, param->disconnect.conn_id);
171
166
  break;
172
167
  }
173
168
  case ESP_GATTS_REG_EVT: {
@@ -4,36 +4,38 @@
4
4
  #include "ble_characteristic.h"
5
5
 
6
6
  #include "esphome/components/esp32_ble/ble.h"
7
- #include "esphome/components/esp32_ble/ble_advertising.h"
8
7
  #include "esphome/components/esp32_ble/ble_uuid.h"
9
- #include "esphome/components/esp32_ble/queue.h"
8
+ #include "esphome/components/bytebuffer/bytebuffer.h"
10
9
  #include "esphome/core/component.h"
11
10
  #include "esphome/core/helpers.h"
12
- #include "esphome/core/preferences.h"
13
11
 
14
12
  #include <memory>
15
13
  #include <vector>
16
14
  #include <unordered_map>
15
+ #include <unordered_set>
17
16
 
18
17
  #ifdef USE_ESP32
19
18
 
20
- #include <esp_gap_ble_api.h>
21
19
  #include <esp_gatts_api.h>
22
20
 
23
21
  namespace esphome {
24
22
  namespace esp32_ble_server {
25
23
 
26
24
  using namespace esp32_ble;
25
+ using namespace bytebuffer;
27
26
 
28
- class BLEServiceComponent {
29
- public:
30
- virtual void on_client_connect(){};
31
- virtual void on_client_disconnect(){};
32
- virtual void start();
33
- virtual void stop();
27
+ namespace BLEServerEvt {
28
+ enum EmptyEvt {
29
+ ON_CONNECT,
30
+ ON_DISCONNECT,
34
31
  };
32
+ } // namespace BLEServerEvt
35
33
 
36
- class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEventHandler, public Parented<ESP32BLE> {
34
+ class BLEServer : public Component,
35
+ public GATTsEventHandler,
36
+ public BLEStatusEventHandler,
37
+ public Parented<ESP32BLE>,
38
+ public EventEmitter<BLEServerEvt::EmptyEvt, uint16_t> {
37
39
  public:
38
40
  void setup() override;
39
41
  void loop() override;
@@ -44,47 +46,41 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
44
46
  void teardown();
45
47
  bool is_running();
46
48
 
47
- void set_manufacturer(const std::string &manufacturer) { this->manufacturer_ = manufacturer; }
48
- void set_model(const std::string &model) { this->model_ = model; }
49
49
  void set_manufacturer_data(const std::vector<uint8_t> &data) {
50
50
  this->manufacturer_data_ = data;
51
51
  this->restart_advertising_();
52
52
  }
53
53
 
54
- void create_service(ESPBTUUID uuid, bool advertise = false, uint16_t num_handles = 15, uint8_t inst_id = 0);
55
- void remove_service(ESPBTUUID uuid);
56
- BLEService *get_service(ESPBTUUID uuid);
54
+ BLEService *create_service(ESPBTUUID uuid, bool advertise = false, uint16_t num_handles = 15);
55
+ void remove_service(ESPBTUUID uuid, uint8_t inst_id = 0);
56
+ BLEService *get_service(ESPBTUUID uuid, uint8_t inst_id = 0);
57
+ void enqueue_start_service(BLEService *service) { this->services_to_start_.push_back(service); }
58
+ void set_device_information_service(BLEService *service) { this->device_information_service_ = service; }
57
59
 
58
60
  esp_gatt_if_t get_gatts_if() { return this->gatts_if_; }
59
- uint32_t get_connected_client_count() { return this->connected_clients_; }
60
- const std::unordered_map<uint16_t, void *> &get_clients() { return this->clients_; }
61
+ uint32_t get_connected_client_count() { return this->clients_.size(); }
62
+ const std::unordered_set<uint16_t> &get_clients() { return this->clients_; }
61
63
 
62
64
  void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
63
65
  esp_ble_gatts_cb_param_t *param) override;
64
66
 
65
67
  void ble_before_disabled_event_handler() override;
66
68
 
67
- void register_service_component(BLEServiceComponent *component) { this->service_components_.push_back(component); }
68
-
69
69
  protected:
70
- bool create_device_characteristics_();
70
+ static std::string get_service_key(ESPBTUUID uuid, uint8_t inst_id);
71
71
  void restart_advertising_();
72
72
 
73
- void add_client_(uint16_t conn_id, void *client) { this->clients_.emplace(conn_id, client); }
74
- bool remove_client_(uint16_t conn_id) { return this->clients_.erase(conn_id) > 0; }
73
+ void add_client_(uint16_t conn_id) { this->clients_.insert(conn_id); }
74
+ void remove_client_(uint16_t conn_id) { this->clients_.erase(conn_id); }
75
75
 
76
- std::string manufacturer_;
77
- optional<std::string> model_;
78
- std::vector<uint8_t> manufacturer_data_;
76
+ std::vector<uint8_t> manufacturer_data_{};
79
77
  esp_gatt_if_t gatts_if_{0};
80
78
  bool registered_{false};
81
79
 
82
- uint32_t connected_clients_{0};
83
- std::unordered_map<uint16_t, void *> clients_;
84
- std::unordered_map<std::string, BLEService *> services_;
85
- BLEService *device_information_service_;
86
-
87
- std::vector<BLEServiceComponent *> service_components_;
80
+ std::unordered_set<uint16_t> clients_;
81
+ std::unordered_map<std::string, BLEService *> services_{};
82
+ std::vector<BLEService *> services_to_start_{};
83
+ BLEService *device_information_service_{};
88
84
 
89
85
  enum State : uint8_t {
90
86
  INIT = 0x00,