esphome 2025.6.2__py3-none-any.whl → 2025.7.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 (648) hide show
  1. esphome/__main__.py +1 -3
  2. esphome/codegen.py +2 -0
  3. esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
  4. esphome/components/adc/__init__.py +25 -1
  5. esphome/components/adc/adc_sensor.h +11 -11
  6. esphome/components/adc/adc_sensor_common.cpp +1 -1
  7. esphome/components/adc/adc_sensor_esp32.cpp +16 -8
  8. esphome/components/ade7880/ade7880.h +0 -2
  9. esphome/components/ads1115/ads1115.h +0 -1
  10. esphome/components/ads1118/ads1118.h +0 -1
  11. esphome/components/ags10/ags10.h +0 -2
  12. esphome/components/aic3204/aic3204.h +0 -1
  13. esphome/components/alarm_control_panel/__init__.py +5 -2
  14. esphome/components/alpha3/alpha3.h +0 -1
  15. esphome/components/am43/cover/am43_cover.h +0 -1
  16. esphome/components/am43/sensor/am43_sensor.h +0 -1
  17. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
  18. esphome/components/anova/anova.cpp +5 -1
  19. esphome/components/anova/anova.h +0 -1
  20. esphome/components/apds9960/apds9960.cpp +1 -1
  21. esphome/components/api/__init__.py +57 -21
  22. esphome/components/api/api_connection.cpp +344 -539
  23. esphome/components/api/api_connection.h +224 -141
  24. esphome/components/api/api_frame_helper.cpp +91 -127
  25. esphome/components/api/api_frame_helper.h +64 -54
  26. esphome/components/api/api_pb2.cpp +1837 -9044
  27. esphome/components/api/api_pb2.h +532 -685
  28. esphome/components/api/api_pb2_dump.cpp +4432 -0
  29. esphome/components/api/api_pb2_service.cpp +184 -425
  30. esphome/components/api/api_pb2_service.h +13 -6
  31. esphome/components/api/api_server.cpp +131 -167
  32. esphome/components/api/api_server.h +38 -10
  33. esphome/components/api/client.py +10 -4
  34. esphome/components/api/custom_api_device.h +8 -0
  35. esphome/components/api/list_entities.cpp +37 -104
  36. esphome/components/api/list_entities.h +33 -23
  37. esphome/components/api/proto.h +532 -26
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/api/user_services.h +2 -0
  41. esphome/components/as3935_spi/as3935_spi.h +0 -2
  42. esphome/components/as5600/as5600.h +0 -1
  43. esphome/components/async_tcp/__init__.py +14 -5
  44. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  45. esphome/components/atm90e32/atm90e32.cpp +2 -1
  46. esphome/components/audio/audio_decoder.cpp +1 -1
  47. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  48. esphome/components/b_parasite/b_parasite.h +0 -1
  49. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  50. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  51. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  52. esphome/components/bh1750/bh1750.cpp +5 -5
  53. esphome/components/binary_sensor/__init__.py +82 -5
  54. esphome/components/binary_sensor/automation.h +19 -1
  55. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  56. esphome/components/binary_sensor/binary_sensor.h +11 -25
  57. esphome/components/binary_sensor/filter.cpp +29 -24
  58. esphome/components/binary_sensor/filter.h +20 -10
  59. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  60. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  61. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  62. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  63. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  64. esphome/components/ble_client/switch/ble_switch.h +0 -1
  65. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  66. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  67. esphome/components/ble_presence/ble_presence_device.h +0 -1
  68. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  69. esphome/components/ble_scanner/ble_scanner.h +0 -1
  70. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  71. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  72. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  73. esphome/components/bme680/sensor.py +1 -1
  74. esphome/components/bmp581/bmp581.h +0 -2
  75. esphome/components/button/__init__.py +5 -2
  76. esphome/components/camera/__init__.py +1 -0
  77. esphome/components/camera/camera.cpp +22 -0
  78. esphome/components/camera/camera.h +80 -0
  79. esphome/components/canbus/__init__.py +1 -0
  80. esphome/components/cap1188/cap1188.h +0 -1
  81. esphome/components/captive_portal/__init__.py +12 -2
  82. esphome/components/captive_portal/captive_portal.cpp +12 -2
  83. esphome/components/captive_portal/captive_portal.h +5 -2
  84. esphome/components/ccs811/ccs811.h +0 -2
  85. esphome/components/climate/__init__.py +5 -2
  86. esphome/components/cm1106/sensor.py +2 -2
  87. esphome/components/const/__init__.py +2 -0
  88. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  89. esphome/components/copy/button/copy_button.h +0 -1
  90. esphome/components/copy/cover/copy_cover.h +0 -1
  91. esphome/components/copy/fan/copy_fan.h +0 -1
  92. esphome/components/copy/lock/copy_lock.h +0 -1
  93. esphome/components/copy/number/copy_number.h +0 -1
  94. esphome/components/copy/select/copy_select.h +0 -1
  95. esphome/components/copy/sensor/copy_sensor.h +0 -1
  96. esphome/components/copy/switch/copy_switch.h +0 -1
  97. esphome/components/copy/text/copy_text.h +0 -1
  98. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  99. esphome/components/cover/__init__.py +5 -2
  100. esphome/components/cs5460a/cs5460a.h +0 -1
  101. esphome/components/datetime/__init__.py +4 -2
  102. esphome/components/debug/__init__.py +20 -0
  103. esphome/components/debug/debug_esp32.cpp +2 -0
  104. esphome/components/deep_sleep/__init__.py +43 -9
  105. esphome/components/demo/__init__.py +2 -2
  106. esphome/components/display/display.cpp +4 -3
  107. esphome/components/display/display.h +0 -2
  108. esphome/components/display/display_buffer.cpp +1 -1
  109. esphome/components/ds2484/__init__.py +1 -0
  110. esphome/components/ds2484/ds2484.cpp +209 -0
  111. esphome/components/ds2484/ds2484.h +43 -0
  112. esphome/components/ds2484/one_wire.py +37 -0
  113. esphome/components/duty_time/duty_time_sensor.h +0 -1
  114. esphome/components/ens160_base/ens160_base.h +0 -1
  115. esphome/components/es7210/es7210.h +0 -1
  116. esphome/components/es7243e/es7243e.h +0 -1
  117. esphome/components/es8156/es8156.h +0 -1
  118. esphome/components/es8311/es8311.h +0 -1
  119. esphome/components/es8388/es8388.h +0 -1
  120. esphome/components/esp32/__init__.py +103 -135
  121. esphome/components/esp32/core.cpp +0 -4
  122. esphome/components/esp32/gpio.h +1 -1
  123. esphome/components/esp32/helpers.cpp +69 -0
  124. esphome/components/esp32_ble/ble.cpp +5 -6
  125. esphome/components/esp32_ble/ble.h +29 -14
  126. esphome/components/esp32_ble/ble_event.h +6 -6
  127. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  128. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  129. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  130. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  131. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  132. esphome/components/esp32_camera/__init__.py +112 -98
  133. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  134. esphome/components/esp32_camera/esp32_camera.h +35 -30
  135. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  136. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  137. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  138. esphome/components/esp32_hall/sensor.py +2 -21
  139. esphome/components/esp32_hosted/__init__.py +101 -0
  140. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  141. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  142. esphome/components/esp32_rmt/__init__.py +0 -58
  143. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  144. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  145. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  146. esphome/components/esp32_touch/esp32_touch.h +174 -28
  147. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  148. esphome/components/esp32_touch/esp32_touch_v1.cpp +240 -0
  149. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  150. esphome/components/esp8266/__init__.py +2 -0
  151. esphome/components/esp8266/gpio.cpp +10 -10
  152. esphome/components/esp8266/helpers.cpp +31 -0
  153. esphome/components/esp_ldo/__init__.py +10 -8
  154. esphome/components/esp_ldo/esp_ldo.h +3 -0
  155. esphome/components/esphome/ota/__init__.py +1 -0
  156. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  157. esphome/components/ethernet/__init__.py +42 -23
  158. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  159. esphome/components/ethernet/ethernet_component.cpp +69 -29
  160. esphome/components/ethernet/ethernet_component.h +18 -10
  161. esphome/components/event/__init__.py +5 -2
  162. esphome/components/ezo/ezo.h +0 -1
  163. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  164. esphome/components/fan/__init__.py +5 -2
  165. esphome/components/fan/fan.cpp +4 -0
  166. esphome/components/feedback/feedback_cover.h +0 -1
  167. esphome/components/font/__init__.py +92 -82
  168. esphome/components/font/font.cpp +9 -2
  169. esphome/components/font/font.h +20 -5
  170. esphome/components/fs3000/fs3000.h +0 -1
  171. esphome/components/gcja5/gcja5.h +0 -1
  172. esphome/components/gl_r01_i2c/__init__.py +0 -0
  173. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  174. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  175. esphome/components/gl_r01_i2c/sensor.py +36 -0
  176. esphome/components/gp8403/gp8403.h +0 -1
  177. esphome/components/gpio/binary_sensor/__init__.py +39 -1
  178. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  179. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  180. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  181. esphome/components/he60r/he60r.h +0 -1
  182. esphome/components/heatpumpir/climate.py +2 -1
  183. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  184. esphome/components/heatpumpir/heatpumpir.h +1 -0
  185. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  186. esphome/components/host/__init__.py +3 -1
  187. esphome/components/host/helpers.cpp +57 -0
  188. esphome/components/http_request/__init__.py +19 -1
  189. esphome/components/http_request/http_request.h +1 -1
  190. esphome/components/http_request/http_request_arduino.cpp +0 -1
  191. esphome/components/http_request/http_request_arduino.h +1 -0
  192. esphome/components/http_request/http_request_idf.cpp +0 -1
  193. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  194. esphome/components/http_request/update/http_request_update.cpp +35 -16
  195. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  196. esphome/components/hydreon_rgxx/sensor.py +1 -1
  197. esphome/components/i2c/__init__.py +23 -11
  198. esphome/components/i2c/i2c_bus.h +8 -1
  199. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  200. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  201. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  202. esphome/components/i2c_device/i2c_device.h +0 -1
  203. esphome/components/i2s_audio/__init__.py +2 -10
  204. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  205. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  206. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  207. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  208. esphome/components/iaqcore/iaqcore.h +0 -2
  209. esphome/components/image/__init__.py +123 -24
  210. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  211. esphome/components/ina219/ina219.cpp +7 -0
  212. esphome/components/ina219/ina219.h +1 -0
  213. esphome/components/ina260/ina260.h +0 -2
  214. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  215. esphome/components/inkplate6/display.py +15 -0
  216. esphome/components/inkplate6/inkplate.cpp +2 -2
  217. esphome/components/integration/integration_sensor.h +0 -1
  218. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  219. esphome/components/internal_temperature/sensor.py +0 -26
  220. esphome/components/interval/interval.h +0 -2
  221. esphome/components/json/__init__.py +1 -1
  222. esphome/components/json/json_util.cpp +56 -63
  223. esphome/components/ld2410/button/__init__.py +3 -3
  224. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  225. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  226. esphome/components/ld2410/ld2410.cpp +421 -268
  227. esphome/components/ld2410/ld2410.h +44 -146
  228. esphome/components/ld2410/number/__init__.py +2 -2
  229. esphome/components/ld2410/sensor.py +1 -1
  230. esphome/components/ld2410/switch/__init__.py +1 -1
  231. esphome/components/ld2420/binary_sensor/ld2420_binary_sensor.cpp +2 -2
  232. esphome/components/ld2420/button/reconfig_buttons.cpp +1 -1
  233. esphome/components/ld2420/ld2420.cpp +252 -147
  234. esphome/components/ld2420/ld2420.h +52 -126
  235. esphome/components/ld2420/number/__init__.py +2 -2
  236. esphome/components/ld2420/number/gate_config_number.cpp +1 -1
  237. esphome/components/ld2420/select/operating_mode_select.cpp +1 -1
  238. esphome/components/ld2420/sensor/__init__.py +6 -2
  239. esphome/components/ld2420/sensor/ld2420_sensor.cpp +2 -2
  240. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  241. esphome/components/ld2420/text_sensor/text_sensor.cpp +2 -2
  242. esphome/components/ld2450/button/__init__.py +3 -3
  243. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  244. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  245. esphome/components/ld2450/ld2450.cpp +384 -232
  246. esphome/components/ld2450/ld2450.h +60 -69
  247. esphome/components/ld2450/switch/__init__.py +1 -1
  248. esphome/components/ledc/ledc_output.cpp +1 -63
  249. esphome/components/libretiny/__init__.py +5 -3
  250. esphome/components/libretiny/const.py +5 -0
  251. esphome/components/libretiny/generate_components.py +1 -0
  252. esphome/components/libretiny/helpers.cpp +35 -0
  253. esphome/components/libretiny/lt_component.cpp +5 -3
  254. esphome/components/light/__init__.py +4 -2
  255. esphome/components/light/addressable_light.h +3 -3
  256. esphome/components/light/light_call.cpp +180 -243
  257. esphome/components/light/light_call.h +72 -20
  258. esphome/components/light/light_color_values.h +14 -14
  259. esphome/components/light/light_json_schema.cpp +17 -16
  260. esphome/components/light/light_state.h +15 -13
  261. esphome/components/light/transformers.h +2 -2
  262. esphome/components/ln882x/__init__.py +52 -0
  263. esphome/components/ln882x/boards.py +285 -0
  264. esphome/components/lock/__init__.py +5 -2
  265. esphome/components/logger/__init__.py +40 -3
  266. esphome/components/logger/logger.cpp +47 -12
  267. esphome/components/logger/logger.h +80 -49
  268. esphome/components/logger/logger_esp32.cpp +3 -3
  269. esphome/components/lps22/__init__.py +0 -0
  270. esphome/components/lps22/lps22.cpp +75 -0
  271. esphome/components/lps22/lps22.h +27 -0
  272. esphome/components/lps22/sensor.py +58 -0
  273. esphome/components/ltr390/ltr390.h +0 -1
  274. esphome/components/ltr501/ltr501.h +0 -1
  275. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  276. esphome/components/lvgl/__init__.py +1 -1
  277. esphome/components/lvgl/schemas.py +66 -6
  278. esphome/components/lvgl/styles.py +24 -16
  279. esphome/components/lvgl/widgets/__init__.py +12 -2
  280. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  281. esphome/components/lvgl/widgets/meter.py +20 -13
  282. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  283. esphome/components/max9611/max9611.h +0 -1
  284. esphome/components/mcp23016/__init__.py +1 -1
  285. esphome/components/mcp23xxx_base/__init__.py +1 -1
  286. esphome/components/mcp4461/__init__.py +1 -1
  287. esphome/components/mcp4461/output/__init__.py +3 -2
  288. esphome/components/mcp9600/mcp9600.h +0 -2
  289. esphome/components/md5/md5.cpp +3 -3
  290. esphome/components/md5/md5.h +1 -6
  291. esphome/components/mdns/__init__.py +22 -11
  292. esphome/components/media_player/__init__.py +4 -3
  293. esphome/components/micro_wake_word/__init__.py +1 -5
  294. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  295. esphome/components/microphone/microphone.cpp +7 -9
  296. esphome/components/microphone/microphone.h +0 -2
  297. esphome/components/mipi_spi/display.py +1 -0
  298. esphome/components/mmc5603/mmc5603.cpp +1 -1
  299. esphome/components/modbus/modbus.cpp +33 -15
  300. esphome/components/modbus/modbus.h +9 -0
  301. esphome/components/modbus_controller/__init__.py +42 -10
  302. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  303. esphome/components/modbus_controller/modbus_controller.h +61 -7
  304. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  305. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  306. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  307. esphome/components/mqtt/__init__.py +16 -0
  308. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -1
  309. esphome/components/mqtt/mqtt_backend.h +2 -1
  310. esphome/components/mqtt/mqtt_backend_esp32.cpp +132 -47
  311. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  312. esphome/components/mqtt/mqtt_binary_sensor.cpp +1 -0
  313. esphome/components/mqtt/mqtt_button.cpp +4 -1
  314. esphome/components/mqtt/mqtt_client.cpp +17 -9
  315. esphome/components/mqtt/mqtt_client.h +8 -3
  316. esphome/components/mqtt/mqtt_climate.cpp +6 -4
  317. esphome/components/mqtt/mqtt_component.cpp +3 -1
  318. esphome/components/mqtt/mqtt_cover.cpp +1 -0
  319. esphome/components/mqtt/mqtt_date.cpp +4 -3
  320. esphome/components/mqtt/mqtt_datetime.cpp +7 -6
  321. esphome/components/mqtt/mqtt_event.cpp +6 -3
  322. esphome/components/mqtt/mqtt_fan.cpp +1 -0
  323. esphome/components/mqtt/mqtt_light.cpp +8 -4
  324. esphome/components/mqtt/mqtt_lock.cpp +3 -1
  325. esphome/components/mqtt/mqtt_number.cpp +1 -0
  326. esphome/components/mqtt/mqtt_select.cpp +2 -1
  327. esphome/components/mqtt/mqtt_sensor.cpp +3 -1
  328. esphome/components/mqtt/mqtt_switch.cpp +3 -1
  329. esphome/components/mqtt/mqtt_text.cpp +1 -0
  330. esphome/components/mqtt/mqtt_text_sensor.cpp +3 -1
  331. esphome/components/mqtt/mqtt_time.cpp +4 -3
  332. esphome/components/mqtt/mqtt_update.cpp +1 -0
  333. esphome/components/mqtt/mqtt_valve.cpp +3 -1
  334. esphome/components/ms8607/ms8607.cpp +1 -1
  335. esphome/components/ms8607/ms8607.h +0 -1
  336. esphome/components/neopixelbus/light.py +4 -1
  337. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  338. esphome/components/network/__init__.py +4 -1
  339. esphome/components/network/ip_address.h +1 -0
  340. esphome/components/nextion/__init__.py +16 -0
  341. esphome/components/nextion/base_component.py +1 -0
  342. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  343. esphome/components/nextion/display.py +14 -4
  344. esphome/components/nextion/nextion.cpp +166 -101
  345. esphome/components/nextion/nextion.h +84 -53
  346. esphome/components/nextion/nextion_commands.cpp +11 -10
  347. esphome/components/nextion/nextion_component.cpp +28 -28
  348. esphome/components/nextion/nextion_component.h +53 -18
  349. esphome/components/nextion/nextion_component_base.h +3 -0
  350. esphome/components/nextion/nextion_upload.cpp +36 -0
  351. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  352. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  353. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  354. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  355. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  356. esphome/components/nfc/nfc.cpp +3 -22
  357. esphome/components/nfc/nfc.h +3 -3
  358. esphome/components/number/__init__.py +5 -2
  359. esphome/components/online_image/__init__.py +9 -1
  360. esphome/components/online_image/online_image.cpp +17 -7
  361. esphome/components/online_image/online_image.h +10 -2
  362. esphome/components/opentherm/opentherm.cpp +7 -12
  363. esphome/components/opentherm/output/output.cpp +1 -1
  364. esphome/components/openthread/__init__.py +47 -40
  365. esphome/components/openthread/const.py +1 -0
  366. esphome/components/openthread/openthread_esp.cpp +27 -5
  367. esphome/components/opt3001/__init__.py +0 -0
  368. esphome/components/opt3001/opt3001.cpp +122 -0
  369. esphome/components/opt3001/opt3001.h +27 -0
  370. esphome/components/opt3001/sensor.py +35 -0
  371. esphome/components/ota/__init__.py +17 -0
  372. esphome/components/ota/ota_backend.h +27 -1
  373. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  374. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  375. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  376. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  377. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  378. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  379. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  380. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  381. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  382. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  383. esphome/components/packages/__init__.py +5 -2
  384. esphome/components/packet_transport/binary_sensor.py +61 -4
  385. esphome/components/packet_transport/packet_transport.cpp +34 -1
  386. esphome/components/packet_transport/packet_transport.h +11 -5
  387. esphome/components/pcf8574/__init__.py +1 -1
  388. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  389. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  390. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  391. esphome/components/pmsa003i/pmsa003i.h +0 -1
  392. esphome/components/pmsx003/pmsx003.h +0 -1
  393. esphome/components/pn7150/pn7150.cpp +7 -7
  394. esphome/components/pn7150/pn7150.h +0 -1
  395. esphome/components/pn7160/pn7160.cpp +7 -7
  396. esphome/components/pn7160/pn7160.h +0 -1
  397. esphome/components/preferences/syncer.h +2 -0
  398. esphome/components/prometheus/prometheus_handler.h +1 -1
  399. esphome/components/psram/psram.cpp +0 -20
  400. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  401. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  402. esphome/components/pulse_width/pulse_width.h +0 -1
  403. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  404. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  405. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  406. esphome/components/qr_code/__init__.py +13 -10
  407. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  408. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  409. esphome/components/rc522/rc522.h +0 -1
  410. esphome/components/rdm6300/rdm6300.h +0 -2
  411. esphome/components/remote_base/__init__.py +7 -5
  412. esphome/components/remote_base/remote_base.cpp +24 -21
  413. esphome/components/remote_base/remote_base.h +3 -26
  414. esphome/components/remote_receiver/__init__.py +40 -46
  415. esphome/components/remote_receiver/remote_receiver.h +4 -18
  416. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  417. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  418. esphome/components/remote_transmitter/__init__.py +42 -43
  419. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  420. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  421. esphome/components/resistance/resistance_sensor.h +0 -1
  422. esphome/components/rp2040/__init__.py +2 -0
  423. esphome/components/rp2040/helpers.cpp +55 -0
  424. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  425. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  426. esphome/components/rtttl/__init__.py +4 -4
  427. esphome/components/rtttl/rtttl.cpp +10 -1
  428. esphome/components/ruuvitag/ruuvitag.h +0 -1
  429. esphome/components/safe_mode/safe_mode.cpp +2 -0
  430. esphome/components/safe_mode/safe_mode.h +4 -1
  431. esphome/components/scd30/scd30.h +0 -1
  432. esphome/components/scd30/sensor.py +2 -2
  433. esphome/components/scd4x/scd4x.cpp +61 -54
  434. esphome/components/scd4x/scd4x.h +17 -15
  435. esphome/components/scd4x/sensor.py +4 -4
  436. esphome/components/script/script.h +0 -2
  437. esphome/components/sdp3x/sensor.py +1 -1
  438. esphome/components/select/__init__.py +5 -2
  439. esphome/components/sen5x/sen5x.h +0 -1
  440. esphome/components/senseair/senseair.h +0 -1
  441. esphome/components/sensor/__init__.py +4 -2
  442. esphome/components/sensor/filter.cpp +1 -1
  443. esphome/components/sensor/sensor.cpp +12 -6
  444. esphome/components/sensor/sensor.h +13 -5
  445. esphome/components/servo/servo.cpp +2 -2
  446. esphome/components/servo/servo.h +0 -1
  447. esphome/components/sfa30/sfa30.h +0 -1
  448. esphome/components/sgp30/sgp30.h +0 -1
  449. esphome/components/sgp4x/sgp4x.h +0 -1
  450. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  451. esphome/components/sht4x/sht4x.h +0 -1
  452. esphome/components/sm300d2/sm300d2.h +0 -2
  453. esphome/components/smt100/sensor.py +8 -4
  454. esphome/components/smt100/smt100.cpp +5 -5
  455. esphome/components/smt100/smt100.h +3 -3
  456. esphome/components/sn74hc595/__init__.py +1 -1
  457. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  458. esphome/components/sntp/sntp_component.cpp +9 -3
  459. esphome/components/sntp/time.py +2 -0
  460. esphome/components/socket/__init__.py +17 -0
  461. esphome/components/spi/__init__.py +27 -6
  462. esphome/components/spi/spi.cpp +3 -2
  463. esphome/components/spi/spi.h +9 -3
  464. esphome/components/spi/spi_arduino.cpp +3 -5
  465. esphome/components/spi/spi_esp_idf.cpp +40 -21
  466. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  467. esphome/components/sps30/sps30.h +0 -1
  468. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  469. esphome/components/st7701s/st7701s.cpp +0 -4
  470. esphome/components/status/status_binary_sensor.h +0 -2
  471. esphome/components/substitutions/__init__.py +81 -21
  472. esphome/components/substitutions/jinja.py +99 -0
  473. esphome/components/sun/sun.cpp +3 -4
  474. esphome/components/switch/__init__.py +5 -2
  475. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  476. esphome/components/sx126x/__init__.py +317 -0
  477. esphome/components/sx126x/automation.h +62 -0
  478. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  479. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  480. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  481. esphome/components/sx126x/sx126x.cpp +523 -0
  482. esphome/components/sx126x/sx126x.h +140 -0
  483. esphome/components/sx126x/sx126x_reg.h +163 -0
  484. esphome/components/sx127x/__init__.py +325 -0
  485. esphome/components/sx127x/automation.h +62 -0
  486. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  487. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  488. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  489. esphome/components/sx127x/sx127x.cpp +498 -0
  490. esphome/components/sx127x/sx127x.h +128 -0
  491. esphome/components/sx127x/sx127x_reg.h +295 -0
  492. esphome/components/syslog/esphome_syslog.cpp +5 -3
  493. esphome/components/syslog/esphome_syslog.h +1 -1
  494. esphome/components/tca9555/__init__.py +1 -1
  495. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  496. esphome/components/text/__init__.py +5 -2
  497. esphome/components/text_sensor/__init__.py +5 -2
  498. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  499. esphome/components/thermostat/thermostat_climate.h +43 -39
  500. esphome/components/time/__init__.py +16 -2
  501. esphome/components/time/real_time_clock.cpp +4 -0
  502. esphome/components/time/real_time_clock.h +5 -1
  503. esphome/components/tlc5971/tlc5971.cpp +4 -1
  504. esphome/components/tmp1075/tmp1075.h +0 -2
  505. esphome/components/tof10120/tof10120_sensor.h +0 -1
  506. esphome/components/tormatic/tormatic_cover.h +0 -1
  507. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  508. esphome/components/tsl2591/tsl2591.cpp +1 -1
  509. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  510. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  511. esphome/components/tx20/tx20.cpp +2 -2
  512. esphome/components/uart/__init__.py +18 -0
  513. esphome/components/uart/uart_component_esp_idf.cpp +1 -5
  514. esphome/components/update/__init__.py +5 -2
  515. esphome/components/update/update_entity.h +8 -0
  516. esphome/components/usb_host/__init__.py +5 -2
  517. esphome/components/usb_host/usb_host_client.cpp +10 -10
  518. esphome/components/usb_uart/cp210x.cpp +1 -1
  519. esphome/components/usb_uart/usb_uart.cpp +41 -44
  520. esphome/components/usb_uart/usb_uart.h +4 -3
  521. esphome/components/valve/__init__.py +5 -2
  522. esphome/components/vbus/vbus.h +0 -1
  523. esphome/components/veml3235/veml3235.h +0 -1
  524. esphome/components/veml7700/veml7700.h +0 -1
  525. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  526. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  527. esphome/components/watchdog/watchdog.cpp +0 -4
  528. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  529. esphome/components/web_server/__init__.py +34 -19
  530. esphome/components/web_server/ota/__init__.py +32 -0
  531. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  532. esphome/components/web_server/ota/ota_web_server.h +26 -0
  533. esphome/components/web_server/web_server.cpp +324 -439
  534. esphome/components/web_server/web_server.h +33 -23
  535. esphome/components/web_server/web_server_v1.cpp +4 -5
  536. esphome/components/web_server_base/__init__.py +5 -2
  537. esphome/components/web_server_base/web_server_base.cpp +2 -94
  538. esphome/components/web_server_base/web_server_base.h +5 -25
  539. esphome/components/web_server_idf/multipart.cpp +254 -0
  540. esphome/components/web_server_idf/multipart.h +86 -0
  541. esphome/components/web_server_idf/utils.cpp +32 -0
  542. esphome/components/web_server_idf/utils.h +10 -0
  543. esphome/components/web_server_idf/web_server_idf.cpp +164 -16
  544. esphome/components/web_server_idf/web_server_idf.h +11 -10
  545. esphome/components/wiegand/wiegand.cpp +2 -2
  546. esphome/components/wifi/__init__.py +18 -0
  547. esphome/components/wifi/wifi_component.cpp +17 -22
  548. esphome/components/wifi/wifi_component.h +27 -23
  549. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  550. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  551. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  552. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  553. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  554. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  555. esphome/components/wireguard/__init__.py +2 -11
  556. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  557. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  558. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  559. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  560. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  561. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  562. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  563. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  564. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  565. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  566. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  567. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  568. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  569. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  570. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  571. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  572. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  573. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  574. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  575. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  576. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  577. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  578. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  579. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  580. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  581. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  582. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  583. esphome/components/zyaura/zyaura.h +0 -1
  584. esphome/config.py +88 -22
  585. esphome/config_helpers.py +74 -1
  586. esphome/config_validation.py +12 -1
  587. esphome/const.py +65 -10
  588. esphome/core/__init__.py +18 -2
  589. esphome/core/application.cpp +169 -10
  590. esphome/core/application.h +145 -165
  591. esphome/core/area.h +19 -0
  592. esphome/core/automation.h +58 -9
  593. esphome/core/color.cpp +3 -5
  594. esphome/core/color.h +16 -16
  595. esphome/core/component.cpp +156 -22
  596. esphome/core/component.h +98 -4
  597. esphome/core/component_iterator.cpp +11 -9
  598. esphome/core/component_iterator.h +12 -10
  599. esphome/core/config.py +155 -6
  600. esphome/core/controller.cpp +4 -2
  601. esphome/core/controller.h +1 -1
  602. esphome/core/datatypes.h +2 -2
  603. esphome/core/defines.h +17 -2
  604. esphome/core/device.h +20 -0
  605. esphome/core/entity_base.cpp +20 -15
  606. esphome/core/entity_base.h +76 -0
  607. esphome/core/entity_helpers.py +168 -1
  608. esphome/core/event_pool.h +81 -0
  609. esphome/core/helpers.cpp +75 -230
  610. esphome/core/helpers.h +165 -105
  611. esphome/core/lock_free_queue.h +151 -0
  612. esphome/core/log.cpp +2 -2
  613. esphome/core/log.h +2 -0
  614. esphome/core/optional.h +5 -0
  615. esphome/core/ring_buffer.cpp +2 -2
  616. esphome/core/scheduler.cpp +275 -103
  617. esphome/core/scheduler.h +154 -17
  618. esphome/core/time.cpp +5 -5
  619. esphome/core/time.h +5 -5
  620. esphome/cpp_generator.py +17 -0
  621. esphome/cpp_helpers.py +0 -22
  622. esphome/cpp_types.py +3 -1
  623. esphome/dashboard/entries.py +1 -1
  624. esphome/dashboard/util/text.py +5 -21
  625. esphome/dashboard/web_server.py +9 -1
  626. esphome/helpers.py +47 -0
  627. esphome/loader.py +15 -1
  628. esphome/pins.py +14 -8
  629. esphome/platformio_api.py +2 -0
  630. esphome/wizard.py +17 -4
  631. esphome/writer.py +44 -3
  632. esphome/yaml_util.py +0 -2
  633. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/METADATA +10 -9
  634. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/RECORD +639 -580
  635. esphome/components/api/api_pb2_size.h +0 -361
  636. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  637. esphome/components/esp32_ble/queue.h +0 -85
  638. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  639. esphome/components/esp32_hall/esp32_hall.h +0 -23
  640. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  641. esphome/components/ld2410/button/reset_button.cpp +0 -9
  642. esphome/components/ld2450/button/reset_button.cpp +0 -9
  643. esphome/components/openthread/tlv.py +0 -65
  644. /esphome/{dashboard/enum.py → enum.py} +0 -0
  645. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/WHEEL +0 -0
  646. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/entry_points.txt +0 -0
  647. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/licenses/LICENSE +0 -0
  648. {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,16 @@ void BLEClientBase::setup() {
22
22
  this->connection_index_ = connection_index++;
23
23
  }
24
24
 
25
+ void BLEClientBase::set_state(espbt::ClientState st) {
26
+ ESP_LOGV(TAG, "[%d] [%s] Set state %d", this->connection_index_, this->address_str_.c_str(), (int) st);
27
+ ESPBTClient::set_state(st);
28
+
29
+ if (st == espbt::ClientState::READY_TO_CONNECT) {
30
+ // Enable loop when we need to connect
31
+ this->enable_loop();
32
+ }
33
+ }
34
+
25
35
  void BLEClientBase::loop() {
26
36
  if (!esp32_ble::global_ble->is_active()) {
27
37
  this->set_state(espbt::ClientState::INIT);
@@ -37,9 +47,14 @@ void BLEClientBase::loop() {
37
47
  }
38
48
  // READY_TO_CONNECT means we have discovered the device
39
49
  // and the scanner has been stopped by the tracker.
40
- if (this->state_ == espbt::ClientState::READY_TO_CONNECT) {
50
+ else if (this->state_ == espbt::ClientState::READY_TO_CONNECT) {
41
51
  this->connect();
42
52
  }
53
+ // If its idle, we can disable the loop as set_state
54
+ // will enable it again when we need to connect.
55
+ else if (this->state_ == espbt::ClientState::IDLE) {
56
+ this->disable_loop();
57
+ }
43
58
  }
44
59
 
45
60
  float BLEClientBase::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
@@ -481,17 +496,17 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
481
496
  if (length > 2) {
482
497
  return (float) encode_uint16(value[1], value[2]);
483
498
  }
484
- // fall through
499
+ [[fallthrough]];
485
500
  case 0x7: // uint24.
486
501
  if (length > 3) {
487
502
  return (float) encode_uint24(value[1], value[2], value[3]);
488
503
  }
489
- // fall through
504
+ [[fallthrough]];
490
505
  case 0x8: // uint32.
491
506
  if (length > 4) {
492
507
  return (float) encode_uint32(value[1], value[2], value[3], value[4]);
493
508
  }
494
- // fall through
509
+ [[fallthrough]];
495
510
  case 0xC: // int8.
496
511
  return (float) ((int8_t) value[1]);
497
512
  case 0xD: // int12.
@@ -499,12 +514,12 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
499
514
  if (length > 2) {
500
515
  return (float) ((int16_t) (value[1] << 8) + (int16_t) value[2]);
501
516
  }
502
- // fall through
517
+ [[fallthrough]];
503
518
  case 0xF: // int24.
504
519
  if (length > 3) {
505
520
  return (float) ((int32_t) (value[1] << 16) + (int32_t) (value[2] << 8) + (int32_t) (value[3]));
506
521
  }
507
- // fall through
522
+ [[fallthrough]];
508
523
  case 0x10: // int32.
509
524
  if (length > 4) {
510
525
  return (float) ((int32_t) (value[1] << 24) + (int32_t) (value[2] << 16) + (int32_t) (value[3] << 8) +
@@ -93,21 +93,36 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
93
93
 
94
94
  bool check_addr(esp_bd_addr_t &addr) { return memcmp(addr, this->remote_bda_, sizeof(esp_bd_addr_t)) == 0; }
95
95
 
96
+ void set_state(espbt::ClientState st) override;
97
+
96
98
  protected:
99
+ // Memory optimized layout for 32-bit systems
100
+ // Group 1: 8-byte types
101
+ uint64_t address_{0};
102
+
103
+ // Group 2: Container types (grouped for memory optimization)
104
+ std::string address_str_{};
105
+ std::vector<BLEService *> services_;
106
+
107
+ // Group 3: 4-byte types
97
108
  int gattc_if_;
109
+ esp_gatt_status_t status_{ESP_GATT_OK};
110
+
111
+ // Group 4: Arrays (6 bytes)
98
112
  esp_bd_addr_t remote_bda_;
99
- esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC};
113
+
114
+ // Group 5: 2-byte types
100
115
  uint16_t conn_id_{UNSET_CONN_ID};
101
- uint64_t address_{0};
102
- bool auto_connect_{false};
103
- std::string address_str_{};
104
- uint8_t connection_index_;
105
- int16_t service_count_{0};
106
116
  uint16_t mtu_{23};
107
- bool paired_{false};
117
+
118
+ // Group 6: 1-byte types and small enums
119
+ esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC};
108
120
  espbt::ConnectionType connection_type_{espbt::ConnectionType::V1};
109
- std::vector<BLEService *> services_;
110
- esp_gatt_status_t status_{ESP_GATT_OK};
121
+ uint8_t connection_index_;
122
+ uint8_t service_count_{0}; // ESP32 has max handles < 255, typical devices have < 50 services
123
+ bool auto_connect_{false};
124
+ bool paired_{false};
125
+ // 6 bytes used, 2 bytes padding
111
126
 
112
127
  void log_event_(const char *name);
113
128
  };
@@ -29,8 +29,6 @@ from esphome.const import (
29
29
  CONF_ON_BLE_SERVICE_DATA_ADVERTISE,
30
30
  CONF_SERVICE_UUID,
31
31
  CONF_TRIGGER_ID,
32
- KEY_CORE,
33
- KEY_FRAMEWORK_VERSION,
34
32
  )
35
33
  from esphome.core import CORE
36
34
 
@@ -323,10 +321,7 @@ async def to_code(config):
323
321
  # https://github.com/espressif/esp-idf/issues/2503
324
322
  # Match arduino CONFIG_BTU_TASK_STACK_SIZE
325
323
  # https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
326
- if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(4, 4, 6):
327
- add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
328
- else:
329
- add_idf_sdkconfig_option("CONFIG_BTU_TASK_STACK_SIZE", 8192)
324
+ add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
330
325
  add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9)
331
326
  add_idf_sdkconfig_option(
332
327
  "CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS]
@@ -335,8 +330,7 @@ async def to_code(config):
335
330
  # max notifications in 5.x, setting CONFIG_BT_ACL_CONNECTIONS
336
331
  # is enough in 4.x
337
332
  # https://github.com/esphome/issues/issues/6808
338
- if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 0, 0):
339
- add_idf_sdkconfig_option("CONFIG_BT_GATTC_NOTIF_REG_MAX", 9)
333
+ add_idf_sdkconfig_option("CONFIG_BT_GATTC_NOTIF_REG_MAX", 9)
340
334
 
341
335
  cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
342
336
  cg.add_define("USE_ESP32_BLE_CLIENT")
@@ -122,10 +122,10 @@ void ESP32BLETracker::loop() {
122
122
  // Consumer side: This runs in the main loop thread
123
123
  if (this->scanner_state_ == ScannerState::RUNNING) {
124
124
  // Load our own index with relaxed ordering (we're the only writer)
125
- size_t read_idx = this->ring_read_index_.load(std::memory_order_relaxed);
125
+ uint8_t read_idx = this->ring_read_index_.load(std::memory_order_relaxed);
126
126
 
127
127
  // Load producer's index with acquire to see their latest writes
128
- size_t write_idx = this->ring_write_index_.load(std::memory_order_acquire);
128
+ uint8_t write_idx = this->ring_write_index_.load(std::memory_order_acquire);
129
129
 
130
130
  while (read_idx != write_idx) {
131
131
  // Process one result at a time directly from ring buffer
@@ -409,11 +409,11 @@ void ESP32BLETracker::gap_scan_event_handler(const BLEScanResult &scan_result) {
409
409
  // IMPORTANT: Only this thread writes to ring_write_index_
410
410
 
411
411
  // Load our own index with relaxed ordering (we're the only writer)
412
- size_t write_idx = this->ring_write_index_.load(std::memory_order_relaxed);
413
- size_t next_write_idx = (write_idx + 1) % SCAN_RESULT_BUFFER_SIZE;
412
+ uint8_t write_idx = this->ring_write_index_.load(std::memory_order_relaxed);
413
+ uint8_t next_write_idx = (write_idx + 1) % SCAN_RESULT_BUFFER_SIZE;
414
414
 
415
415
  // Load consumer's index with acquire to see their latest updates
416
- size_t read_idx = this->ring_read_index_.load(std::memory_order_acquire);
416
+ uint8_t read_idx = this->ring_read_index_.load(std::memory_order_acquire);
417
417
 
418
418
  // Check if buffer is full
419
419
  if (next_write_idx != read_idx) {
@@ -133,7 +133,7 @@ class ESPBTDeviceListener {
133
133
  ESP32BLETracker *parent_{nullptr};
134
134
  };
135
135
 
136
- enum class ClientState {
136
+ enum class ClientState : uint8_t {
137
137
  // Connection is allocated
138
138
  INIT,
139
139
  // Client is disconnecting
@@ -169,7 +169,7 @@ enum class ScannerState {
169
169
  STOPPED,
170
170
  };
171
171
 
172
- enum class ConnectionType {
172
+ enum class ConnectionType : uint8_t {
173
173
  // The default connection type, we hold all the services in ram
174
174
  // for the duration of the connection.
175
175
  V1,
@@ -197,15 +197,19 @@ class ESPBTClient : public ESPBTDeviceListener {
197
197
  }
198
198
  }
199
199
  ClientState state() const { return state_; }
200
- int app_id;
200
+
201
+ // Memory optimized layout
202
+ uint8_t app_id; // App IDs are small integers assigned sequentially
201
203
 
202
204
  protected:
205
+ // Group 1: 1-byte types
203
206
  ClientState state_{ClientState::INIT};
204
207
  // want_disconnect_ is set to true when a disconnect is requested
205
208
  // while the client is connecting. This is used to disconnect the
206
209
  // client as soon as we get the connection id (conn_id_) from the
207
210
  // ESP_GATTC_OPEN_EVT event.
208
211
  bool want_disconnect_{false};
212
+ // 2 bytes used, 2 bytes padding
209
213
  };
210
214
 
211
215
  class ESP32BLETracker : public Component,
@@ -266,7 +270,7 @@ class ESP32BLETracker : public Component,
266
270
  /// Called to set the scanner state. Will also call callbacks to let listeners know when state is changed.
267
271
  void set_scanner_state_(ScannerState state);
268
272
 
269
- int app_id_{0};
273
+ uint8_t app_id_{0};
270
274
 
271
275
  /// Vector of addresses that have already been printed in print_bt_device_info
272
276
  std::vector<uint64_t> already_discovered_;
@@ -293,9 +297,9 @@ class ESP32BLETracker : public Component,
293
297
  // Consumer: ESPHome main loop (loop() method)
294
298
  // This design ensures zero blocking in the BT callback and prevents scan result loss
295
299
  BLEScanResult *scan_ring_buffer_;
296
- std::atomic<size_t> ring_write_index_{0}; // Written only by BT callback (producer)
297
- std::atomic<size_t> ring_read_index_{0}; // Written only by main loop (consumer)
298
- std::atomic<size_t> scan_results_dropped_{0}; // Tracks buffer overflow events
300
+ std::atomic<uint8_t> ring_write_index_{0}; // Written only by BT callback (producer)
301
+ std::atomic<uint8_t> ring_read_index_{0}; // Written only by main loop (consumer)
302
+ std::atomic<uint16_t> scan_results_dropped_{0}; // Tracks buffer overflow events
299
303
 
300
304
  esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
301
305
  esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
@@ -1,5 +1,6 @@
1
1
  from esphome import automation, pins
2
2
  import esphome.codegen as cg
3
+ from esphome.components import i2c
3
4
  from esphome.components.esp32 import add_idf_component
4
5
  import esphome.config_validation as cv
5
6
  from esphome.const import (
@@ -7,6 +8,7 @@ from esphome.const import (
7
8
  CONF_CONTRAST,
8
9
  CONF_DATA_PINS,
9
10
  CONF_FREQUENCY,
11
+ CONF_I2C_ID,
10
12
  CONF_ID,
11
13
  CONF_PIN,
12
14
  CONF_RESET_PIN,
@@ -17,11 +19,11 @@ from esphome.const import (
17
19
  CONF_VSYNC_PIN,
18
20
  )
19
21
  from esphome.core import CORE
20
- from esphome.cpp_helpers import setup_entity
22
+ from esphome.core.entity_helpers import setup_entity
21
23
 
22
24
  DEPENDENCIES = ["esp32"]
23
25
 
24
- AUTO_LOAD = ["psram"]
26
+ AUTO_LOAD = ["camera", "psram"]
25
27
 
26
28
  esp32_camera_ns = cg.esphome_ns.namespace("esp32_camera")
27
29
  ESP32Camera = esp32_camera_ns.class_("ESP32Camera", cg.PollingComponent, cg.EntityBase)
@@ -149,93 +151,104 @@ CONF_ON_IMAGE = "on_image"
149
151
 
150
152
  camera_range_param = cv.int_range(min=-2, max=2)
151
153
 
152
- CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
153
- {
154
- cv.GenerateID(): cv.declare_id(ESP32Camera),
155
- # pin assignment
156
- cv.Required(CONF_DATA_PINS): cv.All(
157
- [pins.internal_gpio_input_pin_number], cv.Length(min=8, max=8)
158
- ),
159
- cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_input_pin_number,
160
- cv.Required(CONF_HREF_PIN): pins.internal_gpio_input_pin_number,
161
- cv.Required(CONF_PIXEL_CLOCK_PIN): pins.internal_gpio_input_pin_number,
162
- cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema(
163
- {
164
- cv.Required(CONF_PIN): pins.internal_gpio_input_pin_number,
165
- cv.Optional(CONF_FREQUENCY, default="20MHz"): cv.All(
166
- cv.frequency, cv.Range(min=8e6, max=20e6)
167
- ),
168
- }
169
- ),
170
- cv.Required(CONF_I2C_PINS): cv.Schema(
171
- {
172
- cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
173
- cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
174
- }
175
- ),
176
- cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
177
- cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
178
- # image
179
- cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum(
180
- FRAME_SIZES, upper=True
181
- ),
182
- cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=6, max=63),
183
- cv.Optional(CONF_CONTRAST, default=0): camera_range_param,
184
- cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
185
- cv.Optional(CONF_SATURATION, default=0): camera_range_param,
186
- cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean,
187
- cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean,
188
- cv.Optional(CONF_SPECIAL_EFFECT, default="NONE"): cv.enum(
189
- ENUM_SPECIAL_EFFECT, upper=True
190
- ),
191
- # exposure
192
- cv.Optional(CONF_AGC_MODE, default="AUTO"): cv.enum(
193
- ENUM_GAIN_CONTROL_MODE, upper=True
194
- ),
195
- cv.Optional(CONF_AEC2, default=False): cv.boolean,
196
- cv.Optional(CONF_AE_LEVEL, default=0): camera_range_param,
197
- cv.Optional(CONF_AEC_VALUE, default=300): cv.int_range(min=0, max=1200),
198
- # gains
199
- cv.Optional(CONF_AEC_MODE, default="AUTO"): cv.enum(
200
- ENUM_GAIN_CONTROL_MODE, upper=True
201
- ),
202
- cv.Optional(CONF_AGC_VALUE, default=0): cv.int_range(min=0, max=30),
203
- cv.Optional(CONF_AGC_GAIN_CEILING, default="2X"): cv.enum(
204
- ENUM_GAIN_CEILING, upper=True
205
- ),
206
- # white balance
207
- cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(ENUM_WB_MODE, upper=True),
208
- # test pattern
209
- cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
210
- # framerates
211
- cv.Optional(CONF_MAX_FRAMERATE, default="10 fps"): cv.All(
212
- cv.framerate, cv.Range(min=0, min_included=False, max=60)
213
- ),
214
- cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All(
215
- cv.framerate, cv.Range(min=0, max=1)
216
- ),
217
- cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2),
218
- cv.Optional(CONF_ON_STREAM_START): automation.validate_automation(
219
- {
220
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
221
- ESP32CameraStreamStartTrigger
222
- ),
223
- }
224
- ),
225
- cv.Optional(CONF_ON_STREAM_STOP): automation.validate_automation(
226
- {
227
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
228
- ESP32CameraStreamStopTrigger
229
- ),
230
- }
231
- ),
232
- cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
233
- {
234
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32CameraImageTrigger),
235
- }
236
- ),
237
- }
238
- ).extend(cv.COMPONENT_SCHEMA)
154
+ CONFIG_SCHEMA = cv.All(
155
+ cv.ENTITY_BASE_SCHEMA.extend(
156
+ {
157
+ cv.GenerateID(): cv.declare_id(ESP32Camera),
158
+ # pin assignment
159
+ cv.Required(CONF_DATA_PINS): cv.All(
160
+ [pins.internal_gpio_input_pin_number], cv.Length(min=8, max=8)
161
+ ),
162
+ cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_input_pin_number,
163
+ cv.Required(CONF_HREF_PIN): pins.internal_gpio_input_pin_number,
164
+ cv.Required(CONF_PIXEL_CLOCK_PIN): pins.internal_gpio_input_pin_number,
165
+ cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema(
166
+ {
167
+ cv.Required(CONF_PIN): pins.internal_gpio_input_pin_number,
168
+ cv.Optional(CONF_FREQUENCY, default="20MHz"): cv.All(
169
+ cv.frequency, cv.Range(min=8e6, max=20e6)
170
+ ),
171
+ }
172
+ ),
173
+ cv.Optional(CONF_I2C_PINS): cv.Schema(
174
+ {
175
+ cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
176
+ cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
177
+ }
178
+ ),
179
+ cv.Optional(CONF_I2C_ID): cv.Any(
180
+ cv.use_id(i2c.InternalI2CBus),
181
+ msg="I2C bus must be an internal ESP32 I2C bus",
182
+ ),
183
+ cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
184
+ cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
185
+ # image
186
+ cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum(
187
+ FRAME_SIZES, upper=True
188
+ ),
189
+ cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=6, max=63),
190
+ cv.Optional(CONF_CONTRAST, default=0): camera_range_param,
191
+ cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
192
+ cv.Optional(CONF_SATURATION, default=0): camera_range_param,
193
+ cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean,
194
+ cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean,
195
+ cv.Optional(CONF_SPECIAL_EFFECT, default="NONE"): cv.enum(
196
+ ENUM_SPECIAL_EFFECT, upper=True
197
+ ),
198
+ # exposure
199
+ cv.Optional(CONF_AGC_MODE, default="AUTO"): cv.enum(
200
+ ENUM_GAIN_CONTROL_MODE, upper=True
201
+ ),
202
+ cv.Optional(CONF_AEC2, default=False): cv.boolean,
203
+ cv.Optional(CONF_AE_LEVEL, default=0): camera_range_param,
204
+ cv.Optional(CONF_AEC_VALUE, default=300): cv.int_range(min=0, max=1200),
205
+ # gains
206
+ cv.Optional(CONF_AEC_MODE, default="AUTO"): cv.enum(
207
+ ENUM_GAIN_CONTROL_MODE, upper=True
208
+ ),
209
+ cv.Optional(CONF_AGC_VALUE, default=0): cv.int_range(min=0, max=30),
210
+ cv.Optional(CONF_AGC_GAIN_CEILING, default="2X"): cv.enum(
211
+ ENUM_GAIN_CEILING, upper=True
212
+ ),
213
+ # white balance
214
+ cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(
215
+ ENUM_WB_MODE, upper=True
216
+ ),
217
+ # test pattern
218
+ cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
219
+ # framerates
220
+ cv.Optional(CONF_MAX_FRAMERATE, default="10 fps"): cv.All(
221
+ cv.framerate, cv.Range(min=0, min_included=False, max=60)
222
+ ),
223
+ cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All(
224
+ cv.framerate, cv.Range(min=0, max=1)
225
+ ),
226
+ cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2),
227
+ cv.Optional(CONF_ON_STREAM_START): automation.validate_automation(
228
+ {
229
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
230
+ ESP32CameraStreamStartTrigger
231
+ ),
232
+ }
233
+ ),
234
+ cv.Optional(CONF_ON_STREAM_STOP): automation.validate_automation(
235
+ {
236
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
237
+ ESP32CameraStreamStopTrigger
238
+ ),
239
+ }
240
+ ),
241
+ cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
242
+ {
243
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
244
+ ESP32CameraImageTrigger
245
+ ),
246
+ }
247
+ ),
248
+ }
249
+ ).extend(cv.COMPONENT_SCHEMA),
250
+ cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID),
251
+ )
239
252
 
240
253
  SETTERS = {
241
254
  # pin assignment
@@ -270,8 +283,9 @@ SETTERS = {
270
283
 
271
284
 
272
285
  async def to_code(config):
286
+ cg.add_define("USE_CAMERA")
273
287
  var = cg.new_Pvariable(config[CONF_ID])
274
- await setup_entity(var, config)
288
+ await setup_entity(var, config, "camera")
275
289
  await cg.register_component(var, config)
276
290
 
277
291
  for key, setter in SETTERS.items():
@@ -280,8 +294,12 @@ async def to_code(config):
280
294
 
281
295
  extclk = config[CONF_EXTERNAL_CLOCK]
282
296
  cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
283
- i2c_pins = config[CONF_I2C_PINS]
284
- cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
297
+ if i2c_id := config.get(CONF_I2C_ID):
298
+ i2c_hub = await cg.get_variable(i2c_id)
299
+ cg.add(var.set_i2c_id(i2c_hub))
300
+ else:
301
+ i2c_pins = config[CONF_I2C_PINS]
302
+ cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
285
303
  cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
286
304
  if config[CONF_IDLE_FRAMERATE] == 0:
287
305
  cg.add(var.set_idle_update_interval(0))
@@ -290,14 +308,10 @@ async def to_code(config):
290
308
  cg.add(var.set_frame_buffer_count(config[CONF_FRAME_BUFFER_COUNT]))
291
309
  cg.add(var.set_frame_size(config[CONF_RESOLUTION]))
292
310
 
293
- cg.add_define("USE_ESP32_CAMERA")
311
+ cg.add_define("USE_CAMERA")
294
312
 
295
313
  if CORE.using_esp_idf:
296
- add_idf_component(
297
- name="esp32-camera",
298
- repo="https://github.com/espressif/esp32-camera.git",
299
- ref="v2.0.15",
300
- )
314
+ add_idf_component(name="espressif/esp32-camera", ref="2.0.15")
301
315
 
302
316
  for conf in config.get(CONF_ON_STREAM_START, []):
303
317
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
@@ -1,9 +1,9 @@
1
1
  #ifdef USE_ESP32
2
2
 
3
3
  #include "esp32_camera.h"
4
- #include "esphome/core/log.h"
5
- #include "esphome/core/hal.h"
6
4
  #include "esphome/core/application.h"
5
+ #include "esphome/core/hal.h"
6
+ #include "esphome/core/log.h"
7
7
 
8
8
  #include <freertos/task.h>
9
9
 
@@ -14,7 +14,11 @@ static const char *const TAG = "esp32_camera";
14
14
 
15
15
  /* ---------------- public API (derivated) ---------------- */
16
16
  void ESP32Camera::setup() {
17
- global_esp32_camera = this;
17
+ #ifdef USE_I2C
18
+ if (this->i2c_bus_ != nullptr) {
19
+ this->config_.sccb_i2c_port = this->i2c_bus_->get_port();
20
+ }
21
+ #endif
18
22
 
19
23
  /* initialize time to now */
20
24
  this->last_update_ = millis();
@@ -37,7 +41,7 @@ void ESP32Camera::setup() {
37
41
  xTaskCreatePinnedToCore(&ESP32Camera::framebuffer_task,
38
42
  "framebuffer_task", // name
39
43
  1024, // stack size
40
- nullptr, // task pv params
44
+ this, // task pv params
41
45
  1, // priority
42
46
  nullptr, // handle
43
47
  1 // core
@@ -170,7 +174,7 @@ void ESP32Camera::loop() {
170
174
  const uint32_t now = App.get_loop_component_start_time();
171
175
  if (this->idle_update_interval_ != 0 && now - this->last_idle_request_ > this->idle_update_interval_) {
172
176
  this->last_idle_request_ = now;
173
- this->request_image(IDLE);
177
+ this->request_image(camera::IDLE);
174
178
  }
175
179
 
176
180
  // Check if we should fetch a new image
@@ -196,7 +200,7 @@ void ESP32Camera::loop() {
196
200
  xQueueSend(this->framebuffer_return_queue_, &fb, portMAX_DELAY);
197
201
  return;
198
202
  }
199
- this->current_image_ = std::make_shared<CameraImage>(fb, this->single_requesters_ | this->stream_requesters_);
203
+ this->current_image_ = std::make_shared<ESP32CameraImage>(fb, this->single_requesters_ | this->stream_requesters_);
200
204
 
201
205
  ESP_LOGD(TAG, "Got Image: len=%u", fb->len);
202
206
  this->new_image_callback_.call(this->current_image_);
@@ -219,8 +223,6 @@ ESP32Camera::ESP32Camera() {
219
223
  this->config_.fb_count = 1;
220
224
  this->config_.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
221
225
  this->config_.fb_location = CAMERA_FB_IN_PSRAM;
222
-
223
- global_esp32_camera = this;
224
226
  }
225
227
 
226
228
  /* ---------------- setters ---------------- */
@@ -246,6 +248,13 @@ void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
246
248
  this->config_.pin_sccb_sda = sda;
247
249
  this->config_.pin_sccb_scl = scl;
248
250
  }
251
+ #ifdef USE_I2C
252
+ void ESP32Camera::set_i2c_id(i2c::InternalI2CBus *i2c_bus) {
253
+ this->i2c_bus_ = i2c_bus;
254
+ this->config_.pin_sccb_sda = -1;
255
+ this->config_.pin_sccb_scl = -1;
256
+ }
257
+ #endif // USE_I2C
249
258
  void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
250
259
  void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
251
260
 
@@ -343,7 +352,7 @@ void ESP32Camera::set_frame_buffer_count(uint8_t fb_count) {
343
352
  }
344
353
 
345
354
  /* ---------------- public API (specific) ---------------- */
346
- void ESP32Camera::add_image_callback(std::function<void(std::shared_ptr<CameraImage>)> &&callback) {
355
+ void ESP32Camera::add_image_callback(std::function<void(std::shared_ptr<camera::CameraImage>)> &&callback) {
347
356
  this->new_image_callback_.add(std::move(callback));
348
357
  }
349
358
  void ESP32Camera::add_stream_start_callback(std::function<void()> &&callback) {
@@ -352,15 +361,16 @@ void ESP32Camera::add_stream_start_callback(std::function<void()> &&callback) {
352
361
  void ESP32Camera::add_stream_stop_callback(std::function<void()> &&callback) {
353
362
  this->stream_stop_callback_.add(std::move(callback));
354
363
  }
355
- void ESP32Camera::start_stream(CameraRequester requester) {
364
+ void ESP32Camera::start_stream(camera::CameraRequester requester) {
356
365
  this->stream_start_callback_.call();
357
366
  this->stream_requesters_ |= (1U << requester);
358
367
  }
359
- void ESP32Camera::stop_stream(CameraRequester requester) {
368
+ void ESP32Camera::stop_stream(camera::CameraRequester requester) {
360
369
  this->stream_stop_callback_.call();
361
370
  this->stream_requesters_ &= ~(1U << requester);
362
371
  }
363
- void ESP32Camera::request_image(CameraRequester requester) { this->single_requesters_ |= (1U << requester); }
372
+ void ESP32Camera::request_image(camera::CameraRequester requester) { this->single_requesters_ |= (1U << requester); }
373
+ camera::CameraImageReader *ESP32Camera::create_image_reader() { return new ESP32CameraImageReader; }
364
374
  void ESP32Camera::update_camera_parameters() {
365
375
  sensor_t *s = esp_camera_sensor_get();
366
376
  /* update image */
@@ -389,39 +399,39 @@ void ESP32Camera::update_camera_parameters() {
389
399
  bool ESP32Camera::has_requested_image_() const { return this->single_requesters_ || this->stream_requesters_; }
390
400
  bool ESP32Camera::can_return_image_() const { return this->current_image_.use_count() == 1; }
391
401
  void ESP32Camera::framebuffer_task(void *pv) {
402
+ ESP32Camera *that = (ESP32Camera *) pv;
392
403
  while (true) {
393
404
  camera_fb_t *framebuffer = esp_camera_fb_get();
394
- xQueueSend(global_esp32_camera->framebuffer_get_queue_, &framebuffer, portMAX_DELAY);
405
+ xQueueSend(that->framebuffer_get_queue_, &framebuffer, portMAX_DELAY);
395
406
  // return is no-op for config with 1 fb
396
- xQueueReceive(global_esp32_camera->framebuffer_return_queue_, &framebuffer, portMAX_DELAY);
407
+ xQueueReceive(that->framebuffer_return_queue_, &framebuffer, portMAX_DELAY);
397
408
  esp_camera_fb_return(framebuffer);
398
409
  }
399
410
  }
400
411
 
401
- ESP32Camera *global_esp32_camera; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
402
-
403
- /* ---------------- CameraImageReader class ---------------- */
404
- void CameraImageReader::set_image(std::shared_ptr<CameraImage> image) {
405
- this->image_ = std::move(image);
412
+ /* ---------------- ESP32CameraImageReader class ----------- */
413
+ void ESP32CameraImageReader::set_image(std::shared_ptr<camera::CameraImage> image) {
414
+ this->image_ = std::static_pointer_cast<ESP32CameraImage>(image);
406
415
  this->offset_ = 0;
407
416
  }
408
- size_t CameraImageReader::available() const {
417
+ size_t ESP32CameraImageReader::available() const {
409
418
  if (!this->image_)
410
419
  return 0;
411
420
 
412
421
  return this->image_->get_data_length() - this->offset_;
413
422
  }
414
- void CameraImageReader::return_image() { this->image_.reset(); }
415
- void CameraImageReader::consume_data(size_t consumed) { this->offset_ += consumed; }
416
- uint8_t *CameraImageReader::peek_data_buffer() { return this->image_->get_data_buffer() + this->offset_; }
417
-
418
- /* ---------------- CameraImage class ---------------- */
419
- CameraImage::CameraImage(camera_fb_t *buffer, uint8_t requesters) : buffer_(buffer), requesters_(requesters) {}
420
-
421
- camera_fb_t *CameraImage::get_raw_buffer() { return this->buffer_; }
422
- uint8_t *CameraImage::get_data_buffer() { return this->buffer_->buf; }
423
- size_t CameraImage::get_data_length() { return this->buffer_->len; }
424
- bool CameraImage::was_requested_by(CameraRequester requester) const {
423
+ void ESP32CameraImageReader::return_image() { this->image_.reset(); }
424
+ void ESP32CameraImageReader::consume_data(size_t consumed) { this->offset_ += consumed; }
425
+ uint8_t *ESP32CameraImageReader::peek_data_buffer() { return this->image_->get_data_buffer() + this->offset_; }
426
+
427
+ /* ---------------- ESP32CameraImage class ----------- */
428
+ ESP32CameraImage::ESP32CameraImage(camera_fb_t *buffer, uint8_t requesters)
429
+ : buffer_(buffer), requesters_(requesters) {}
430
+
431
+ camera_fb_t *ESP32CameraImage::get_raw_buffer() { return this->buffer_; }
432
+ uint8_t *ESP32CameraImage::get_data_buffer() { return this->buffer_->buf; }
433
+ size_t ESP32CameraImage::get_data_length() { return this->buffer_->len; }
434
+ bool ESP32CameraImage::was_requested_by(camera::CameraRequester requester) const {
425
435
  return (this->requesters_ & (1 << requester)) != 0;
426
436
  }
427
437