esphome 2025.6.2__py3-none-any.whl → 2025.7.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) 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 +42 -20
  22. esphome/components/api/api_connection.cpp +318 -391
  23. esphome/components/api/api_connection.h +206 -126
  24. esphome/components/api/api_frame_helper.cpp +89 -124
  25. esphome/components/api/api_frame_helper.h +57 -45
  26. esphome/components/api/api_pb2.cpp +414 -4350
  27. esphome/components/api/api_pb2.h +287 -198
  28. esphome/components/api/api_pb2_dump.cpp +4333 -0
  29. esphome/components/api/api_pb2_service.cpp +180 -425
  30. esphome/components/api/api_pb2_service.h +7 -6
  31. esphome/components/api/api_pb2_size.h +2 -4
  32. esphome/components/api/api_server.cpp +138 -167
  33. esphome/components/api/api_server.h +66 -12
  34. esphome/components/api/client.py +10 -4
  35. esphome/components/api/list_entities.cpp +36 -105
  36. esphome/components/api/list_entities.h +31 -23
  37. esphome/components/api/proto.h +26 -3
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/as5600/as5600.h +0 -1
  41. esphome/components/async_tcp/__init__.py +14 -5
  42. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  43. esphome/components/atm90e32/atm90e32.cpp +2 -1
  44. esphome/components/audio/audio_decoder.cpp +1 -1
  45. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  46. esphome/components/b_parasite/b_parasite.h +0 -1
  47. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  48. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  49. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  50. esphome/components/bh1750/bh1750.cpp +5 -5
  51. esphome/components/binary_sensor/__init__.py +82 -5
  52. esphome/components/binary_sensor/automation.h +19 -1
  53. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  54. esphome/components/binary_sensor/binary_sensor.h +11 -25
  55. esphome/components/binary_sensor/filter.cpp +29 -24
  56. esphome/components/binary_sensor/filter.h +20 -10
  57. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  58. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  59. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  60. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  61. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  62. esphome/components/ble_client/switch/ble_switch.h +0 -1
  63. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  64. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  65. esphome/components/ble_presence/ble_presence_device.h +0 -1
  66. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  67. esphome/components/ble_scanner/ble_scanner.h +0 -1
  68. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  69. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  70. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  71. esphome/components/bme680/sensor.py +1 -1
  72. esphome/components/bmp581/bmp581.h +0 -2
  73. esphome/components/button/__init__.py +5 -2
  74. esphome/components/camera/__init__.py +1 -0
  75. esphome/components/camera/camera.cpp +22 -0
  76. esphome/components/camera/camera.h +80 -0
  77. esphome/components/canbus/__init__.py +1 -0
  78. esphome/components/cap1188/cap1188.h +0 -1
  79. esphome/components/captive_portal/__init__.py +12 -2
  80. esphome/components/captive_portal/captive_portal.cpp +12 -2
  81. esphome/components/captive_portal/captive_portal.h +5 -2
  82. esphome/components/ccs811/ccs811.h +0 -2
  83. esphome/components/climate/__init__.py +5 -2
  84. esphome/components/cm1106/sensor.py +2 -2
  85. esphome/components/const/__init__.py +2 -0
  86. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  87. esphome/components/copy/button/copy_button.h +0 -1
  88. esphome/components/copy/cover/copy_cover.h +0 -1
  89. esphome/components/copy/fan/copy_fan.h +0 -1
  90. esphome/components/copy/lock/copy_lock.h +0 -1
  91. esphome/components/copy/number/copy_number.h +0 -1
  92. esphome/components/copy/select/copy_select.h +0 -1
  93. esphome/components/copy/sensor/copy_sensor.h +0 -1
  94. esphome/components/copy/switch/copy_switch.h +0 -1
  95. esphome/components/copy/text/copy_text.h +0 -1
  96. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  97. esphome/components/cover/__init__.py +5 -2
  98. esphome/components/cs5460a/cs5460a.h +0 -1
  99. esphome/components/datetime/__init__.py +4 -2
  100. esphome/components/debug/__init__.py +20 -0
  101. esphome/components/deep_sleep/__init__.py +43 -9
  102. esphome/components/demo/__init__.py +2 -2
  103. esphome/components/display/display.cpp +4 -3
  104. esphome/components/display/display.h +0 -2
  105. esphome/components/display/display_buffer.cpp +1 -1
  106. esphome/components/ds2484/__init__.py +1 -0
  107. esphome/components/ds2484/ds2484.cpp +209 -0
  108. esphome/components/ds2484/ds2484.h +43 -0
  109. esphome/components/ds2484/one_wire.py +37 -0
  110. esphome/components/duty_time/duty_time_sensor.h +0 -1
  111. esphome/components/ens160_base/ens160_base.h +0 -1
  112. esphome/components/es7210/es7210.h +0 -1
  113. esphome/components/es7243e/es7243e.h +0 -1
  114. esphome/components/es8156/es8156.h +0 -1
  115. esphome/components/es8311/es8311.h +0 -1
  116. esphome/components/es8388/es8388.h +0 -1
  117. esphome/components/esp32/__init__.py +102 -135
  118. esphome/components/esp32/core.cpp +0 -4
  119. esphome/components/esp32/gpio.h +1 -1
  120. esphome/components/esp32/helpers.cpp +69 -0
  121. esphome/components/esp32_ble/ble.cpp +5 -6
  122. esphome/components/esp32_ble/ble.h +29 -14
  123. esphome/components/esp32_ble/ble_event.h +6 -6
  124. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  125. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  126. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  127. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  128. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  129. esphome/components/esp32_camera/__init__.py +111 -97
  130. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  131. esphome/components/esp32_camera/esp32_camera.h +35 -30
  132. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  133. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  134. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  135. esphome/components/esp32_hall/sensor.py +2 -21
  136. esphome/components/esp32_hosted/__init__.py +101 -0
  137. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  138. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  139. esphome/components/esp32_rmt/__init__.py +0 -58
  140. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  141. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  142. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  143. esphome/components/esp32_touch/esp32_touch.h +174 -28
  144. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  145. esphome/components/esp32_touch/esp32_touch_v1.cpp +238 -0
  146. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  147. esphome/components/esp8266/__init__.py +1 -0
  148. esphome/components/esp8266/gpio.cpp +10 -10
  149. esphome/components/esp8266/helpers.cpp +31 -0
  150. esphome/components/esphome/ota/__init__.py +1 -0
  151. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  152. esphome/components/ethernet/__init__.py +42 -23
  153. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  154. esphome/components/ethernet/ethernet_component.cpp +69 -29
  155. esphome/components/ethernet/ethernet_component.h +18 -10
  156. esphome/components/event/__init__.py +5 -2
  157. esphome/components/ezo/ezo.h +0 -1
  158. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  159. esphome/components/fan/__init__.py +5 -2
  160. esphome/components/feedback/feedback_cover.h +0 -1
  161. esphome/components/font/__init__.py +92 -82
  162. esphome/components/font/font.cpp +9 -2
  163. esphome/components/font/font.h +20 -5
  164. esphome/components/fs3000/fs3000.h +0 -1
  165. esphome/components/gcja5/gcja5.h +0 -1
  166. esphome/components/gl_r01_i2c/__init__.py +0 -0
  167. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  168. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  169. esphome/components/gl_r01_i2c/sensor.py +36 -0
  170. esphome/components/gp8403/gp8403.h +0 -1
  171. esphome/components/gpio/binary_sensor/__init__.py +17 -0
  172. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  173. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  174. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  175. esphome/components/he60r/he60r.h +0 -1
  176. esphome/components/heatpumpir/climate.py +2 -1
  177. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  178. esphome/components/heatpumpir/heatpumpir.h +1 -0
  179. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  180. esphome/components/host/__init__.py +2 -1
  181. esphome/components/host/helpers.cpp +57 -0
  182. esphome/components/http_request/__init__.py +19 -1
  183. esphome/components/http_request/http_request.h +1 -1
  184. esphome/components/http_request/http_request_arduino.cpp +0 -1
  185. esphome/components/http_request/http_request_arduino.h +1 -0
  186. esphome/components/http_request/http_request_idf.cpp +0 -1
  187. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  188. esphome/components/http_request/update/http_request_update.cpp +28 -9
  189. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  190. esphome/components/hydreon_rgxx/sensor.py +1 -1
  191. esphome/components/i2c/__init__.py +23 -11
  192. esphome/components/i2c/i2c_bus.h +8 -1
  193. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  194. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  195. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  196. esphome/components/i2c_device/i2c_device.h +0 -1
  197. esphome/components/i2s_audio/__init__.py +2 -10
  198. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  199. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  200. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  201. esphome/components/iaqcore/iaqcore.h +0 -2
  202. esphome/components/image/__init__.py +123 -24
  203. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  204. esphome/components/ina219/ina219.cpp +7 -0
  205. esphome/components/ina219/ina219.h +1 -0
  206. esphome/components/ina260/ina260.h +0 -2
  207. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  208. esphome/components/inkplate6/display.py +15 -0
  209. esphome/components/inkplate6/inkplate.cpp +2 -2
  210. esphome/components/integration/integration_sensor.h +0 -1
  211. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  212. esphome/components/internal_temperature/sensor.py +0 -26
  213. esphome/components/interval/interval.h +0 -2
  214. esphome/components/ld2410/button/__init__.py +3 -3
  215. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  216. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  217. esphome/components/ld2410/ld2410.cpp +430 -261
  218. esphome/components/ld2410/ld2410.h +44 -146
  219. esphome/components/ld2410/number/__init__.py +2 -2
  220. esphome/components/ld2410/sensor.py +1 -1
  221. esphome/components/ld2410/switch/__init__.py +1 -1
  222. esphome/components/ld2420/ld2420.cpp +196 -100
  223. esphome/components/ld2420/ld2420.h +46 -118
  224. esphome/components/ld2420/number/__init__.py +2 -2
  225. esphome/components/ld2420/sensor/__init__.py +6 -2
  226. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  227. esphome/components/ld2450/button/__init__.py +3 -3
  228. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  229. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  230. esphome/components/ld2450/ld2450.cpp +384 -232
  231. esphome/components/ld2450/ld2450.h +60 -69
  232. esphome/components/ld2450/switch/__init__.py +1 -1
  233. esphome/components/ledc/ledc_output.cpp +1 -63
  234. esphome/components/libretiny/__init__.py +4 -3
  235. esphome/components/libretiny/const.py +5 -0
  236. esphome/components/libretiny/generate_components.py +1 -0
  237. esphome/components/libretiny/helpers.cpp +35 -0
  238. esphome/components/libretiny/lt_component.cpp +5 -3
  239. esphome/components/light/__init__.py +4 -2
  240. esphome/components/light/addressable_light.h +3 -3
  241. esphome/components/light/light_call.cpp +180 -243
  242. esphome/components/light/light_call.h +72 -20
  243. esphome/components/light/light_color_values.h +14 -14
  244. esphome/components/light/light_state.h +15 -13
  245. esphome/components/light/transformers.h +2 -2
  246. esphome/components/ln882x/__init__.py +52 -0
  247. esphome/components/ln882x/boards.py +285 -0
  248. esphome/components/lock/__init__.py +5 -2
  249. esphome/components/logger/__init__.py +40 -3
  250. esphome/components/logger/logger.cpp +47 -12
  251. esphome/components/logger/logger.h +80 -49
  252. esphome/components/logger/logger_esp32.cpp +3 -3
  253. esphome/components/lps22/__init__.py +0 -0
  254. esphome/components/lps22/lps22.cpp +75 -0
  255. esphome/components/lps22/lps22.h +27 -0
  256. esphome/components/lps22/sensor.py +58 -0
  257. esphome/components/ltr390/ltr390.h +0 -1
  258. esphome/components/ltr501/ltr501.h +0 -1
  259. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  260. esphome/components/lvgl/__init__.py +1 -1
  261. esphome/components/lvgl/schemas.py +66 -6
  262. esphome/components/lvgl/styles.py +24 -16
  263. esphome/components/lvgl/widgets/__init__.py +12 -2
  264. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  265. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  266. esphome/components/max9611/max9611.h +0 -1
  267. esphome/components/mcp23016/__init__.py +1 -1
  268. esphome/components/mcp23xxx_base/__init__.py +1 -1
  269. esphome/components/mcp4461/__init__.py +1 -1
  270. esphome/components/mcp4461/output/__init__.py +3 -2
  271. esphome/components/mcp9600/mcp9600.h +0 -2
  272. esphome/components/md5/md5.cpp +3 -3
  273. esphome/components/md5/md5.h +1 -6
  274. esphome/components/mdns/__init__.py +22 -11
  275. esphome/components/media_player/__init__.py +4 -3
  276. esphome/components/micro_wake_word/__init__.py +1 -5
  277. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  278. esphome/components/microphone/microphone.cpp +7 -9
  279. esphome/components/microphone/microphone.h +0 -2
  280. esphome/components/mipi_spi/display.py +1 -0
  281. esphome/components/mmc5603/mmc5603.cpp +1 -1
  282. esphome/components/modbus/modbus.cpp +33 -15
  283. esphome/components/modbus/modbus.h +9 -0
  284. esphome/components/modbus_controller/__init__.py +42 -10
  285. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  286. esphome/components/modbus_controller/modbus_controller.h +61 -7
  287. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  288. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  289. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  290. esphome/components/mqtt/__init__.py +16 -0
  291. esphome/components/mqtt/mqtt_backend.h +2 -1
  292. esphome/components/mqtt/mqtt_backend_esp32.cpp +126 -45
  293. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  294. esphome/components/mqtt/mqtt_client.cpp +15 -9
  295. esphome/components/mqtt/mqtt_client.h +8 -3
  296. esphome/components/ms8607/ms8607.h +0 -1
  297. esphome/components/neopixelbus/light.py +4 -1
  298. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  299. esphome/components/network/__init__.py +4 -1
  300. esphome/components/network/ip_address.h +1 -0
  301. esphome/components/nextion/__init__.py +16 -0
  302. esphome/components/nextion/base_component.py +1 -0
  303. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  304. esphome/components/nextion/display.py +14 -4
  305. esphome/components/nextion/nextion.cpp +166 -101
  306. esphome/components/nextion/nextion.h +84 -53
  307. esphome/components/nextion/nextion_commands.cpp +11 -10
  308. esphome/components/nextion/nextion_component.cpp +28 -28
  309. esphome/components/nextion/nextion_component.h +53 -18
  310. esphome/components/nextion/nextion_component_base.h +3 -0
  311. esphome/components/nextion/nextion_upload.cpp +36 -0
  312. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  313. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  314. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  315. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  316. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  317. esphome/components/nfc/nfc.cpp +3 -22
  318. esphome/components/nfc/nfc.h +3 -3
  319. esphome/components/number/__init__.py +5 -2
  320. esphome/components/online_image/__init__.py +5 -0
  321. esphome/components/online_image/online_image.cpp +6 -2
  322. esphome/components/online_image/online_image.h +4 -1
  323. esphome/components/opentherm/opentherm.cpp +7 -12
  324. esphome/components/openthread/__init__.py +47 -40
  325. esphome/components/openthread/const.py +1 -0
  326. esphome/components/openthread/openthread_esp.cpp +27 -5
  327. esphome/components/opt3001/__init__.py +0 -0
  328. esphome/components/opt3001/opt3001.cpp +122 -0
  329. esphome/components/opt3001/opt3001.h +27 -0
  330. esphome/components/opt3001/sensor.py +35 -0
  331. esphome/components/ota/__init__.py +17 -0
  332. esphome/components/ota/ota_backend.h +27 -1
  333. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  334. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  335. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  336. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  337. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  338. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  339. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  340. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  341. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  342. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  343. esphome/components/packages/__init__.py +5 -2
  344. esphome/components/packet_transport/binary_sensor.py +61 -4
  345. esphome/components/packet_transport/packet_transport.cpp +31 -1
  346. esphome/components/packet_transport/packet_transport.h +11 -5
  347. esphome/components/pcf8574/__init__.py +1 -1
  348. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  349. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  350. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  351. esphome/components/pmsa003i/pmsa003i.h +0 -1
  352. esphome/components/pmsx003/pmsx003.h +0 -1
  353. esphome/components/pn7150/pn7150.cpp +7 -7
  354. esphome/components/pn7150/pn7150.h +0 -1
  355. esphome/components/pn7160/pn7160.cpp +7 -7
  356. esphome/components/pn7160/pn7160.h +0 -1
  357. esphome/components/preferences/syncer.h +2 -0
  358. esphome/components/prometheus/prometheus_handler.h +1 -1
  359. esphome/components/psram/psram.cpp +0 -20
  360. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  361. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  362. esphome/components/pulse_width/pulse_width.h +0 -1
  363. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  364. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  365. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  366. esphome/components/qr_code/__init__.py +13 -10
  367. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  368. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  369. esphome/components/rc522/rc522.h +0 -1
  370. esphome/components/rdm6300/rdm6300.h +0 -2
  371. esphome/components/remote_base/__init__.py +7 -5
  372. esphome/components/remote_base/remote_base.cpp +24 -21
  373. esphome/components/remote_base/remote_base.h +3 -26
  374. esphome/components/remote_receiver/__init__.py +40 -46
  375. esphome/components/remote_receiver/remote_receiver.h +4 -18
  376. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  377. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  378. esphome/components/remote_transmitter/__init__.py +42 -43
  379. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  380. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  381. esphome/components/resistance/resistance_sensor.h +0 -1
  382. esphome/components/rp2040/__init__.py +1 -0
  383. esphome/components/rp2040/helpers.cpp +55 -0
  384. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  385. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  386. esphome/components/rtttl/__init__.py +4 -4
  387. esphome/components/rtttl/rtttl.cpp +10 -1
  388. esphome/components/ruuvitag/ruuvitag.h +0 -1
  389. esphome/components/safe_mode/safe_mode.cpp +2 -0
  390. esphome/components/safe_mode/safe_mode.h +4 -1
  391. esphome/components/scd30/scd30.h +0 -1
  392. esphome/components/scd30/sensor.py +2 -2
  393. esphome/components/scd4x/scd4x.cpp +61 -54
  394. esphome/components/scd4x/scd4x.h +17 -15
  395. esphome/components/scd4x/sensor.py +4 -4
  396. esphome/components/script/script.h +0 -2
  397. esphome/components/sdp3x/sensor.py +1 -1
  398. esphome/components/select/__init__.py +5 -2
  399. esphome/components/sen5x/sen5x.h +0 -1
  400. esphome/components/senseair/senseair.h +0 -1
  401. esphome/components/sensor/__init__.py +4 -2
  402. esphome/components/sensor/filter.cpp +1 -1
  403. esphome/components/sensor/sensor.cpp +12 -6
  404. esphome/components/sensor/sensor.h +13 -5
  405. esphome/components/servo/servo.h +0 -1
  406. esphome/components/sfa30/sfa30.h +0 -1
  407. esphome/components/sgp30/sgp30.h +0 -1
  408. esphome/components/sgp4x/sgp4x.h +0 -1
  409. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  410. esphome/components/sht4x/sht4x.h +0 -1
  411. esphome/components/sm300d2/sm300d2.h +0 -2
  412. esphome/components/smt100/sensor.py +8 -4
  413. esphome/components/smt100/smt100.cpp +5 -5
  414. esphome/components/smt100/smt100.h +3 -3
  415. esphome/components/sn74hc595/__init__.py +1 -1
  416. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  417. esphome/components/sntp/sntp_component.cpp +9 -3
  418. esphome/components/sntp/time.py +2 -0
  419. esphome/components/socket/__init__.py +17 -0
  420. esphome/components/spi/__init__.py +27 -6
  421. esphome/components/spi/spi.cpp +3 -2
  422. esphome/components/spi/spi.h +9 -3
  423. esphome/components/spi/spi_arduino.cpp +3 -5
  424. esphome/components/spi/spi_esp_idf.cpp +40 -21
  425. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  426. esphome/components/sps30/sps30.h +0 -1
  427. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  428. esphome/components/st7701s/st7701s.cpp +0 -4
  429. esphome/components/status/status_binary_sensor.h +0 -2
  430. esphome/components/substitutions/__init__.py +76 -19
  431. esphome/components/substitutions/jinja.py +99 -0
  432. esphome/components/sun/sun.cpp +3 -4
  433. esphome/components/switch/__init__.py +5 -2
  434. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  435. esphome/components/sx126x/__init__.py +317 -0
  436. esphome/components/sx126x/automation.h +62 -0
  437. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  438. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  439. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  440. esphome/components/sx126x/sx126x.cpp +523 -0
  441. esphome/components/sx126x/sx126x.h +140 -0
  442. esphome/components/sx126x/sx126x_reg.h +163 -0
  443. esphome/components/sx127x/__init__.py +325 -0
  444. esphome/components/sx127x/automation.h +62 -0
  445. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  446. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  447. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  448. esphome/components/sx127x/sx127x.cpp +498 -0
  449. esphome/components/sx127x/sx127x.h +128 -0
  450. esphome/components/sx127x/sx127x_reg.h +295 -0
  451. esphome/components/syslog/esphome_syslog.cpp +5 -3
  452. esphome/components/syslog/esphome_syslog.h +1 -1
  453. esphome/components/tca9555/__init__.py +1 -1
  454. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  455. esphome/components/text/__init__.py +5 -2
  456. esphome/components/text_sensor/__init__.py +5 -2
  457. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  458. esphome/components/thermostat/thermostat_climate.h +43 -39
  459. esphome/components/time/__init__.py +16 -2
  460. esphome/components/time/real_time_clock.cpp +4 -0
  461. esphome/components/time/real_time_clock.h +5 -1
  462. esphome/components/tlc5971/tlc5971.cpp +4 -1
  463. esphome/components/tmp1075/tmp1075.h +0 -2
  464. esphome/components/tof10120/tof10120_sensor.h +0 -1
  465. esphome/components/tormatic/tormatic_cover.h +0 -1
  466. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  467. esphome/components/tsl2591/tsl2591.cpp +1 -1
  468. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  469. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  470. esphome/components/tx20/tx20.cpp +2 -2
  471. esphome/components/uart/__init__.py +18 -0
  472. esphome/components/uart/uart_component_esp_idf.cpp +1 -5
  473. esphome/components/update/__init__.py +5 -2
  474. esphome/components/update/update_entity.h +8 -0
  475. esphome/components/usb_host/__init__.py +5 -2
  476. esphome/components/valve/__init__.py +5 -2
  477. esphome/components/vbus/vbus.h +0 -1
  478. esphome/components/veml3235/veml3235.h +0 -1
  479. esphome/components/veml7700/veml7700.h +0 -1
  480. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  481. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  482. esphome/components/watchdog/watchdog.cpp +0 -4
  483. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  484. esphome/components/web_server/__init__.py +34 -19
  485. esphome/components/web_server/ota/__init__.py +32 -0
  486. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  487. esphome/components/web_server/ota/ota_web_server.h +26 -0
  488. esphome/components/web_server/web_server.cpp +311 -430
  489. esphome/components/web_server/web_server.h +33 -23
  490. esphome/components/web_server/web_server_v1.cpp +4 -5
  491. esphome/components/web_server_base/__init__.py +5 -2
  492. esphome/components/web_server_base/web_server_base.cpp +2 -94
  493. esphome/components/web_server_base/web_server_base.h +5 -25
  494. esphome/components/web_server_idf/multipart.cpp +254 -0
  495. esphome/components/web_server_idf/multipart.h +86 -0
  496. esphome/components/web_server_idf/utils.cpp +32 -0
  497. esphome/components/web_server_idf/utils.h +10 -0
  498. esphome/components/web_server_idf/web_server_idf.cpp +162 -16
  499. esphome/components/web_server_idf/web_server_idf.h +11 -10
  500. esphome/components/wiegand/wiegand.cpp +2 -2
  501. esphome/components/wifi/__init__.py +18 -0
  502. esphome/components/wifi/wifi_component.cpp +17 -22
  503. esphome/components/wifi/wifi_component.h +27 -23
  504. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  505. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  506. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  507. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  508. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  509. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  510. esphome/components/wireguard/__init__.py +2 -11
  511. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  512. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  513. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  514. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  515. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  516. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  517. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  518. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  519. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  520. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  521. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  522. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  523. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  524. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  525. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  526. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  527. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  528. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  529. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  530. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  531. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  532. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  533. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  534. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  535. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  536. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  537. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  538. esphome/components/zyaura/zyaura.h +0 -1
  539. esphome/config.py +88 -22
  540. esphome/config_helpers.py +74 -1
  541. esphome/config_validation.py +12 -1
  542. esphome/const.py +65 -10
  543. esphome/core/__init__.py +18 -2
  544. esphome/core/application.cpp +163 -10
  545. esphome/core/application.h +145 -165
  546. esphome/core/area.h +19 -0
  547. esphome/core/automation.h +58 -9
  548. esphome/core/color.cpp +3 -5
  549. esphome/core/color.h +16 -16
  550. esphome/core/component.cpp +151 -18
  551. esphome/core/component.h +98 -4
  552. esphome/core/component_iterator.cpp +7 -7
  553. esphome/core/component_iterator.h +9 -7
  554. esphome/core/config.py +155 -6
  555. esphome/core/controller.cpp +4 -2
  556. esphome/core/controller.h +1 -1
  557. esphome/core/datatypes.h +2 -2
  558. esphome/core/defines.h +17 -2
  559. esphome/core/device.h +20 -0
  560. esphome/core/entity_base.cpp +20 -15
  561. esphome/core/entity_base.h +76 -0
  562. esphome/core/entity_helpers.py +162 -1
  563. esphome/core/event_pool.h +81 -0
  564. esphome/core/helpers.cpp +75 -230
  565. esphome/core/helpers.h +164 -104
  566. esphome/core/lock_free_queue.h +151 -0
  567. esphome/core/log.cpp +2 -2
  568. esphome/core/log.h +2 -0
  569. esphome/core/optional.h +5 -0
  570. esphome/core/ring_buffer.cpp +2 -2
  571. esphome/core/scheduler.cpp +278 -103
  572. esphome/core/scheduler.h +157 -17
  573. esphome/core/time.cpp +5 -5
  574. esphome/core/time.h +5 -5
  575. esphome/cpp_generator.py +17 -0
  576. esphome/cpp_helpers.py +0 -22
  577. esphome/cpp_types.py +3 -1
  578. esphome/dashboard/entries.py +1 -1
  579. esphome/dashboard/util/text.py +5 -21
  580. esphome/dashboard/web_server.py +9 -1
  581. esphome/helpers.py +47 -0
  582. esphome/loader.py +15 -1
  583. esphome/pins.py +14 -8
  584. esphome/wizard.py +16 -3
  585. esphome/writer.py +21 -3
  586. esphome/yaml_util.py +0 -2
  587. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/METADATA +10 -9
  588. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/RECORD +593 -533
  589. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  590. esphome/components/esp32_ble/queue.h +0 -85
  591. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  592. esphome/components/esp32_hall/esp32_hall.h +0 -23
  593. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  594. esphome/components/ld2410/button/reset_button.cpp +0 -9
  595. esphome/components/ld2450/button/reset_button.cpp +0 -9
  596. esphome/components/openthread/tlv.py +0 -65
  597. /esphome/{dashboard/enum.py → enum.py} +0 -0
  598. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/WHEEL +0 -0
  599. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/entry_points.txt +0 -0
  600. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/licenses/LICENSE +0 -0
  601. {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/top_level.txt +0 -0
@@ -50,7 +50,6 @@ class ES8311 : public audio_dac::AudioDac, public Component, public i2c::I2CDevi
50
50
  /////////////////////////
51
51
 
52
52
  void setup() override;
53
- float get_setup_priority() const override { return setup_priority::DATA; }
54
53
  void dump_config() override;
55
54
 
56
55
  ////////////////////////
@@ -38,7 +38,6 @@ class ES8388 : public audio_dac::AudioDac, public Component, public i2c::I2CDevi
38
38
  /////////////////////////
39
39
 
40
40
  void setup() override;
41
- float get_setup_priority() const override { return setup_priority::DATA; }
42
41
  void dump_config() override;
43
42
 
44
43
  ////////////////////////
@@ -4,7 +4,7 @@ import logging
4
4
  import os
5
5
  from pathlib import Path
6
6
 
7
- from esphome import git
7
+ from esphome import yaml_util
8
8
  import esphome.codegen as cg
9
9
  import esphome.config_validation as cv
10
10
  from esphome.const import (
@@ -23,7 +23,6 @@ from esphome.const import (
23
23
  CONF_REFRESH,
24
24
  CONF_SOURCE,
25
25
  CONF_TYPE,
26
- CONF_URL,
27
26
  CONF_VARIANT,
28
27
  CONF_VERSION,
29
28
  KEY_CORE,
@@ -32,14 +31,13 @@ from esphome.const import (
32
31
  KEY_TARGET_FRAMEWORK,
33
32
  KEY_TARGET_PLATFORM,
34
33
  PLATFORM_ESP32,
35
- TYPE_GIT,
36
- TYPE_LOCAL,
37
34
  __version__,
38
35
  )
39
36
  from esphome.core import CORE, HexInt, TimePeriod
40
37
  from esphome.cpp_generator import RawExpression
41
38
  import esphome.final_validate as fv
42
39
  from esphome.helpers import copy_file_if_changed, mkdir_p, write_file_if_changed
40
+ from esphome.types import ConfigType
43
41
 
44
42
  from .boards import BOARDS
45
43
  from .const import ( # noqa
@@ -49,10 +47,8 @@ from .const import ( # noqa
49
47
  KEY_EXTRA_BUILD_FILES,
50
48
  KEY_PATH,
51
49
  KEY_REF,
52
- KEY_REFRESH,
53
50
  KEY_REPO,
54
51
  KEY_SDKCONFIG_OPTIONS,
55
- KEY_SUBMODULES,
56
52
  KEY_VARIANT,
57
53
  VARIANT_ESP32,
58
54
  VARIANT_ESP32C2,
@@ -132,6 +128,8 @@ def set_core_data(config):
132
128
  choices = CPU_FREQUENCIES[variant]
133
129
  if "160MHZ" in choices:
134
130
  cpu_frequency = "160MHZ"
131
+ elif "360MHZ" in choices:
132
+ cpu_frequency = "360MHZ"
135
133
  else:
136
134
  cpu_frequency = choices[-1]
137
135
  config[CONF_CPU_FREQUENCY] = cpu_frequency
@@ -191,7 +189,7 @@ def get_download_types(storage_json):
191
189
  ]
192
190
 
193
191
 
194
- def only_on_variant(*, supported=None, unsupported=None):
192
+ def only_on_variant(*, supported=None, unsupported=None, msg_prefix="This feature"):
195
193
  """Config validator for features only available on some ESP32 variants."""
196
194
  if supported is not None and not isinstance(supported, list):
197
195
  supported = [supported]
@@ -202,11 +200,11 @@ def only_on_variant(*, supported=None, unsupported=None):
202
200
  variant = get_esp32_variant()
203
201
  if supported is not None and variant not in supported:
204
202
  raise cv.Invalid(
205
- f"This feature is only available on {', '.join(supported)}"
203
+ f"{msg_prefix} is only available on {', '.join(supported)}"
206
204
  )
207
205
  if unsupported is not None and variant in unsupported:
208
206
  raise cv.Invalid(
209
- f"This feature is not available on {', '.join(unsupported)}"
207
+ f"{msg_prefix} is not available on {', '.join(unsupported)}"
210
208
  )
211
209
  return obj
212
210
 
@@ -233,7 +231,7 @@ def add_idf_sdkconfig_option(name: str, value: SdkconfigValueType):
233
231
  def add_idf_component(
234
232
  *,
235
233
  name: str,
236
- repo: str,
234
+ repo: str = None,
237
235
  ref: str = None,
238
236
  path: str = None,
239
237
  refresh: TimePeriod = None,
@@ -243,30 +241,27 @@ def add_idf_component(
243
241
  """Add an esp-idf component to the project."""
244
242
  if not CORE.using_esp_idf:
245
243
  raise ValueError("Not an esp-idf project")
246
- if components is None:
247
- components = []
248
- if name not in CORE.data[KEY_ESP32][KEY_COMPONENTS]:
244
+ if not repo and not ref and not path:
245
+ raise ValueError("Requires at least one of repo, ref or path")
246
+ if refresh or submodules or components:
247
+ _LOGGER.warning(
248
+ "The refresh, components and submodules parameters in add_idf_component() are "
249
+ "deprecated and will be removed in ESPHome 2026.1. If you are seeing this, report "
250
+ "an issue to the external_component author and ask them to update it."
251
+ )
252
+ if components:
253
+ for comp in components:
254
+ CORE.data[KEY_ESP32][KEY_COMPONENTS][comp] = {
255
+ KEY_REPO: repo,
256
+ KEY_REF: ref,
257
+ KEY_PATH: f"{path}/{comp}" if path else comp,
258
+ }
259
+ else:
249
260
  CORE.data[KEY_ESP32][KEY_COMPONENTS][name] = {
250
261
  KEY_REPO: repo,
251
262
  KEY_REF: ref,
252
263
  KEY_PATH: path,
253
- KEY_REFRESH: refresh,
254
- KEY_COMPONENTS: components,
255
- KEY_SUBMODULES: submodules,
256
264
  }
257
- else:
258
- component_config = CORE.data[KEY_ESP32][KEY_COMPONENTS][name]
259
- if components is not None:
260
- component_config[KEY_COMPONENTS] = list(
261
- set(component_config[KEY_COMPONENTS] + components)
262
- )
263
- if submodules is not None:
264
- if component_config[KEY_SUBMODULES] is None:
265
- component_config[KEY_SUBMODULES] = submodules
266
- else:
267
- component_config[KEY_SUBMODULES] = list(
268
- set(component_config[KEY_SUBMODULES] + submodules)
269
- )
270
265
 
271
266
 
272
267
  def add_extra_script(stage: str, filename: str, path: str):
@@ -289,11 +284,8 @@ def add_extra_build_file(filename: str, path: str) -> bool:
289
284
 
290
285
  def _format_framework_arduino_version(ver: cv.Version) -> str:
291
286
  # format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to
292
- # a PIO platformio/framework-arduinoespressif32 value
293
- # List of package versions: https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
294
- if ver <= cv.Version(1, 0, 3):
295
- return f"~2.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
296
- return f"~3.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
287
+ # a PIO pioarduino/framework-arduinoespressif32 value
288
+ return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{str(ver)}/esp32-{str(ver)}.zip"
297
289
 
298
290
 
299
291
  def _format_framework_espidf_version(
@@ -317,12 +309,10 @@ def _format_framework_espidf_version(
317
309
 
318
310
  # The default/recommended arduino framework version
319
311
  # - https://github.com/espressif/arduino-esp32/releases
320
- # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
321
- RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(2, 0, 5)
322
- # The platformio/espressif32 version to use for arduino frameworks
323
- # - https://github.com/platformio/platform-espressif32/releases
324
- # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
325
- ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
312
+ RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 1, 3)
313
+ # The platform-espressif32 version to use for arduino frameworks
314
+ # - https://github.com/pioarduino/platform-espressif32/releases
315
+ ARDUINO_PLATFORM_VERSION = cv.Version(53, 3, 13)
326
316
 
327
317
  # The default/recommended esp-idf framework version
328
318
  # - https://github.com/espressif/esp-idf/releases
@@ -351,6 +341,7 @@ SUPPORTED_PLATFORMIO_ESP_IDF_5X = [
351
341
  # List based on https://github.com/pioarduino/esp-idf/releases
352
342
  SUPPORTED_PIOARDUINO_ESP_IDF_5X = [
353
343
  cv.Version(5, 5, 0),
344
+ cv.Version(5, 4, 2),
354
345
  cv.Version(5, 4, 1),
355
346
  cv.Version(5, 4, 0),
356
347
  cv.Version(5, 3, 3),
@@ -365,8 +356,8 @@ SUPPORTED_PIOARDUINO_ESP_IDF_5X = [
365
356
  def _arduino_check_versions(value):
366
357
  value = value.copy()
367
358
  lookups = {
368
- "dev": (cv.Version(2, 1, 0), "https://github.com/espressif/arduino-esp32.git"),
369
- "latest": (cv.Version(2, 0, 9), None),
359
+ "dev": (cv.Version(3, 1, 3), "https://github.com/espressif/arduino-esp32.git"),
360
+ "latest": (cv.Version(3, 1, 3), None),
370
361
  "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
371
362
  }
372
363
 
@@ -388,6 +379,10 @@ def _arduino_check_versions(value):
388
379
  CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
389
380
  )
390
381
 
382
+ if value[CONF_SOURCE].startswith("http"):
383
+ # prefix is necessary or platformio will complain with a cryptic error
384
+ value[CONF_SOURCE] = f"framework-arduinoespressif32@{value[CONF_SOURCE]}"
385
+
391
386
  if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION:
392
387
  _LOGGER.warning(
393
388
  "The selected Arduino framework version is not the recommended one. "
@@ -416,8 +411,8 @@ def _esp_idf_check_versions(value):
416
411
  version = cv.Version.parse(cv.version_number(value[CONF_VERSION]))
417
412
  source = value.get(CONF_SOURCE, None)
418
413
 
419
- if version < cv.Version(4, 0, 0):
420
- raise cv.Invalid("Only ESP-IDF 4.0+ is supported.")
414
+ if version < cv.Version(5, 0, 0):
415
+ raise cv.Invalid("Only ESP-IDF 5.0+ is supported.")
421
416
 
422
417
  # flag this for later *before* we set value[CONF_PLATFORM_VERSION] below
423
418
  has_platform_ver = CONF_PLATFORM_VERSION in value
@@ -427,20 +422,15 @@ def _esp_idf_check_versions(value):
427
422
  )
428
423
 
429
424
  if (
430
- (is_platformio := _platform_is_platformio(value[CONF_PLATFORM_VERSION]))
431
- and version.major >= 5
432
- and version not in SUPPORTED_PLATFORMIO_ESP_IDF_5X
433
- ):
425
+ is_platformio := _platform_is_platformio(value[CONF_PLATFORM_VERSION])
426
+ ) and version not in SUPPORTED_PLATFORMIO_ESP_IDF_5X:
434
427
  raise cv.Invalid(
435
428
  f"ESP-IDF {str(version)} not supported by platformio/espressif32"
436
429
  )
437
430
 
438
431
  if (
439
- version.major < 5
440
- or (
441
- version in SUPPORTED_PLATFORMIO_ESP_IDF_5X
442
- and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X
443
- )
432
+ version in SUPPORTED_PLATFORMIO_ESP_IDF_5X
433
+ and version not in SUPPORTED_PIOARDUINO_ESP_IDF_5X
444
434
  ) and not has_platform_ver:
445
435
  raise cv.Invalid(
446
436
  f"ESP-IDF {value[CONF_VERSION]} may be supported by platformio/espressif32; please specify '{CONF_PLATFORM_VERSION}'"
@@ -574,6 +564,17 @@ CONF_ENABLE_LWIP_DHCP_SERVER = "enable_lwip_dhcp_server"
574
564
  CONF_ENABLE_LWIP_MDNS_QUERIES = "enable_lwip_mdns_queries"
575
565
  CONF_ENABLE_LWIP_BRIDGE_INTERFACE = "enable_lwip_bridge_interface"
576
566
 
567
+
568
+ def _validate_idf_component(config: ConfigType) -> ConfigType:
569
+ """Validate IDF component config and warn about deprecated options."""
570
+ if CONF_REFRESH in config:
571
+ _LOGGER.warning(
572
+ "The 'refresh' option for IDF components is deprecated and has no effect. "
573
+ "It will be removed in ESPHome 2026.1. Please remove it from your configuration."
574
+ )
575
+ return config
576
+
577
+
577
578
  ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
578
579
  cv.Schema(
579
580
  {
@@ -613,15 +614,19 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
613
614
  }
614
615
  ),
615
616
  cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
616
- cv.Schema(
617
- {
618
- cv.Required(CONF_NAME): cv.string_strict,
619
- cv.Required(CONF_SOURCE): cv.SOURCE_SCHEMA,
620
- cv.Optional(CONF_PATH): cv.string,
621
- cv.Optional(CONF_REFRESH, default="1d"): cv.All(
622
- cv.string, cv.source_refresh
623
- ),
624
- }
617
+ cv.All(
618
+ cv.Schema(
619
+ {
620
+ cv.Required(CONF_NAME): cv.string_strict,
621
+ cv.Optional(CONF_SOURCE): cv.git_ref,
622
+ cv.Optional(CONF_REF): cv.string,
623
+ cv.Optional(CONF_PATH): cv.string,
624
+ cv.Optional(CONF_REFRESH): cv.All(
625
+ cv.string, cv.source_refresh
626
+ ),
627
+ }
628
+ ),
629
+ _validate_idf_component,
625
630
  )
626
631
  ),
627
632
  }
@@ -695,6 +700,7 @@ FINAL_VALIDATE_SCHEMA = cv.Schema(final_validate)
695
700
  async def to_code(config):
696
701
  cg.add_platformio_option("board", config[CONF_BOARD])
697
702
  cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE])
703
+ cg.set_cpp_standard("gnu++20")
698
704
  cg.add_build_flag("-DUSE_ESP32")
699
705
  cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
700
706
  cg.add_build_flag(f"-DUSE_ESP32_VARIANT_{config[CONF_VARIANT]}")
@@ -748,6 +754,9 @@ async def to_code(config):
748
754
  add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False)
749
755
  add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False)
750
756
 
757
+ # Disable dynamic log level control to save memory
758
+ add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False)
759
+
751
760
  # Set default CPU frequency
752
761
  add_idf_sdkconfig_option(f"CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_{freq}", True)
753
762
 
@@ -787,14 +796,9 @@ async def to_code(config):
787
796
 
788
797
  if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC):
789
798
  add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True)
790
- if (framework_ver.major, framework_ver.minor) >= (4, 4):
791
- add_idf_sdkconfig_option(
792
- "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False
793
- )
794
- else:
795
- add_idf_sdkconfig_option(
796
- "CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE", False
797
- )
799
+ add_idf_sdkconfig_option(
800
+ "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False
801
+ )
798
802
  if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES):
799
803
  _LOGGER.warning(
800
804
  "Using experimental features in ESP-IDF may result in unexpected failures."
@@ -812,26 +816,17 @@ async def to_code(config):
812
816
  add_idf_sdkconfig_option(name, RawSdkconfigValue(value))
813
817
 
814
818
  for component in conf[CONF_COMPONENTS]:
815
- source = component[CONF_SOURCE]
816
- if source[CONF_TYPE] == TYPE_GIT:
817
- add_idf_component(
818
- name=component[CONF_NAME],
819
- repo=source[CONF_URL],
820
- ref=source.get(CONF_REF),
821
- path=component.get(CONF_PATH),
822
- refresh=component[CONF_REFRESH],
823
- )
824
- elif source[CONF_TYPE] == TYPE_LOCAL:
825
- _LOGGER.warning("Local components are not implemented yet.")
826
-
819
+ add_idf_component(
820
+ name=component[CONF_NAME],
821
+ repo=component.get(CONF_SOURCE),
822
+ ref=component.get(CONF_REF),
823
+ path=component.get(CONF_PATH),
824
+ )
827
825
  elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
828
826
  cg.add_platformio_option("framework", "arduino")
829
827
  cg.add_build_flag("-DUSE_ARDUINO")
830
828
  cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO")
831
- cg.add_platformio_option(
832
- "platform_packages",
833
- [f"platformio/framework-arduinoespressif32@{conf[CONF_SOURCE]}"],
834
- )
829
+ cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
835
830
 
836
831
  if CONF_PARTITIONS in config:
837
832
  cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
@@ -925,6 +920,26 @@ def _write_sdkconfig():
925
920
  write_file_if_changed(sdk_path, contents)
926
921
 
927
922
 
923
+ def _write_idf_component_yml():
924
+ yml_path = Path(CORE.relative_build_path("src/idf_component.yml"))
925
+ if CORE.data[KEY_ESP32][KEY_COMPONENTS]:
926
+ components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS]
927
+ dependencies = {}
928
+ for name, component in components.items():
929
+ dependency = {}
930
+ if component[KEY_REF]:
931
+ dependency["version"] = component[KEY_REF]
932
+ if component[KEY_REPO]:
933
+ dependency["git"] = component[KEY_REPO]
934
+ if component[KEY_PATH]:
935
+ dependency["path"] = component[KEY_PATH]
936
+ dependencies[name] = dependency
937
+ contents = yaml_util.dump({"dependencies": dependencies})
938
+ else:
939
+ contents = ""
940
+ write_file_if_changed(yml_path, contents)
941
+
942
+
928
943
  # Called by writer.py
929
944
  def copy_files():
930
945
  if CORE.using_arduino:
@@ -937,6 +952,7 @@ def copy_files():
937
952
  )
938
953
  if CORE.using_esp_idf:
939
954
  _write_sdkconfig()
955
+ _write_idf_component_yml()
940
956
  if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]:
941
957
  write_file_if_changed(
942
958
  CORE.relative_build_path("partitions.csv"),
@@ -953,55 +969,6 @@ def copy_files():
953
969
  __version__,
954
970
  )
955
971
 
956
- import shutil
957
-
958
- shutil.rmtree(CORE.relative_build_path("components"), ignore_errors=True)
959
-
960
- if CORE.data[KEY_ESP32][KEY_COMPONENTS]:
961
- components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS]
962
-
963
- for name, component in components.items():
964
- repo_dir, _ = git.clone_or_update(
965
- url=component[KEY_REPO],
966
- ref=component[KEY_REF],
967
- refresh=component[KEY_REFRESH],
968
- domain="idf_components",
969
- submodules=component[KEY_SUBMODULES],
970
- )
971
- mkdir_p(CORE.relative_build_path("components"))
972
- component_dir = repo_dir
973
- if component[KEY_PATH] is not None:
974
- component_dir = component_dir / component[KEY_PATH]
975
-
976
- if component[KEY_COMPONENTS] == ["*"]:
977
- shutil.copytree(
978
- component_dir,
979
- CORE.relative_build_path("components"),
980
- dirs_exist_ok=True,
981
- ignore=shutil.ignore_patterns(".git*"),
982
- symlinks=True,
983
- ignore_dangling_symlinks=True,
984
- )
985
- elif len(component[KEY_COMPONENTS]) > 0:
986
- for comp in component[KEY_COMPONENTS]:
987
- shutil.copytree(
988
- component_dir / comp,
989
- CORE.relative_build_path(f"components/{comp}"),
990
- dirs_exist_ok=True,
991
- ignore=shutil.ignore_patterns(".git*"),
992
- symlinks=True,
993
- ignore_dangling_symlinks=True,
994
- )
995
- else:
996
- shutil.copytree(
997
- component_dir,
998
- CORE.relative_build_path(f"components/{name}"),
999
- dirs_exist_ok=True,
1000
- ignore=shutil.ignore_patterns(".git*"),
1001
- symlinks=True,
1002
- ignore_dangling_symlinks=True,
1003
- )
1004
-
1005
972
  for _, file in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES].items():
1006
973
  if file[KEY_PATH].startswith("http"):
1007
974
  import requests
@@ -56,11 +56,7 @@ void arch_init() {
56
56
  void IRAM_ATTR HOT arch_feed_wdt() { esp_task_wdt_reset(); }
57
57
 
58
58
  uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
59
- #if ESP_IDF_VERSION_MAJOR >= 5
60
59
  uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); }
61
- #else
62
- uint32_t arch_get_cpu_cycle_count() { return cpu_hal_get_cycle_count(); }
63
- #endif
64
60
  uint32_t arch_get_cpu_freq_hz() {
65
61
  uint32_t freq = 0;
66
62
  #ifdef USE_ESP_IDF
@@ -29,9 +29,9 @@ class ESP32InternalGPIOPin : public InternalGPIOPin {
29
29
  void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
30
30
 
31
31
  gpio_num_t pin_;
32
- bool inverted_;
33
32
  gpio_drive_cap_t drive_strength_;
34
33
  gpio::Flags flags_;
34
+ bool inverted_;
35
35
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
36
36
  static bool isr_service_installed;
37
37
  };
@@ -0,0 +1,69 @@
1
+ #include "esphome/core/helpers.h"
2
+
3
+ #ifdef USE_ESP32
4
+
5
+ #include "esp_efuse.h"
6
+ #include "esp_efuse_table.h"
7
+ #include "esp_mac.h"
8
+
9
+ #include <freertos/FreeRTOS.h>
10
+ #include <freertos/portmacro.h>
11
+ #include "esp_random.h"
12
+ #include "esp_system.h"
13
+
14
+ namespace esphome {
15
+
16
+ uint32_t random_uint32() { return esp_random(); }
17
+ bool random_bytes(uint8_t *data, size_t len) {
18
+ esp_fill_random(data, len);
19
+ return true;
20
+ }
21
+
22
+ Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); }
23
+ Mutex::~Mutex() {}
24
+ void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); }
25
+ bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; }
26
+ void Mutex::unlock() { xSemaphoreGive(this->handle_); }
27
+
28
+ // only affects the executing core
29
+ // so should not be used as a mutex lock, only to get accurate timing
30
+ IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); }
31
+ IRAM_ATTR InterruptLock::~InterruptLock() { portENABLE_INTERRUPTS(); }
32
+
33
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
34
+ #if defined(CONFIG_SOC_IEEE802154_SUPPORTED)
35
+ // When CONFIG_SOC_IEEE802154_SUPPORTED is defined, esp_efuse_mac_get_default
36
+ // returns the 802.15.4 EUI-64 address, so we read directly from eFuse instead.
37
+ if (has_custom_mac_address()) {
38
+ esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48);
39
+ } else {
40
+ esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48);
41
+ }
42
+ #else
43
+ if (has_custom_mac_address()) {
44
+ esp_efuse_mac_get_custom(mac);
45
+ } else {
46
+ esp_efuse_mac_get_default(mac);
47
+ }
48
+ #endif
49
+ }
50
+
51
+ void set_mac_address(uint8_t *mac) { esp_base_mac_addr_set(mac); }
52
+
53
+ bool has_custom_mac_address() {
54
+ #if !defined(USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC)
55
+ uint8_t mac[6];
56
+ // do not use 'esp_efuse_mac_get_custom(mac)' because it drops an error in the logs whenever it fails
57
+ #ifndef USE_ESP32_VARIANT_ESP32
58
+ return (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac);
59
+ #else
60
+ return (esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac);
61
+ #endif
62
+ #else
63
+ return false;
64
+ #endif
65
+ }
66
+
67
+ } // namespace esphome
68
+
69
+ #endif // USE_ESP32
@@ -1,9 +1,9 @@
1
1
  #ifdef USE_ESP32
2
2
 
3
3
  #include "ble.h"
4
- #include "ble_event_pool.h"
5
4
 
6
5
  #include "esphome/core/application.h"
6
+ #include "esphome/core/helpers.h"
7
7
  #include "esphome/core/log.h"
8
8
 
9
9
  #include <esp_bt.h>
@@ -516,13 +516,12 @@ void ESP32BLE::dump_config() {
516
516
  break;
517
517
  }
518
518
  ESP_LOGCONFIG(TAG,
519
- "ESP32 BLE:\n"
520
- " MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n"
519
+ "BLE:\n"
520
+ " MAC address: %s\n"
521
521
  " IO Capability: %s",
522
- mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5],
523
- io_capability_s);
522
+ format_mac_address_pretty(mac_address).c_str(), io_capability_s);
524
523
  } else {
525
- ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
524
+ ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
526
525
  }
527
526
  }
528
527
 
@@ -12,8 +12,8 @@
12
12
  #include "esphome/core/helpers.h"
13
13
 
14
14
  #include "ble_event.h"
15
- #include "ble_event_pool.h"
16
- #include "queue.h"
15
+ #include "esphome/core/lock_free_queue.h"
16
+ #include "esphome/core/event_pool.h"
17
17
 
18
18
  #ifdef USE_ESP32
19
19
 
@@ -25,10 +25,15 @@ namespace esphome {
25
25
  namespace esp32_ble {
26
26
 
27
27
  // Maximum number of BLE scan results to buffer
28
+ // Sized to handle bursts of advertisements while allowing for processing delays
29
+ // With 16 advertisements per batch and some safety margin:
30
+ // - Without PSRAM: 24 entries (1.5× batch size)
31
+ // - With PSRAM: 36 entries (2.25× batch size)
32
+ // The reduced structure size (~80 bytes vs ~400 bytes) allows for larger buffers
28
33
  #ifdef USE_PSRAM
29
- static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 32;
34
+ static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 36;
30
35
  #else
31
- static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 20;
36
+ static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 24;
32
37
  #endif
33
38
 
34
39
  // Maximum size of the BLE event queue - must be power of 2 for lock-free queue
@@ -51,7 +56,7 @@ enum IoCapability {
51
56
  IO_CAP_KBDISP = ESP_IO_CAP_KBDISP,
52
57
  };
53
58
 
54
- enum BLEComponentState {
59
+ enum BLEComponentState : uint8_t {
55
60
  /** Nothing has been initialized yet. */
56
61
  BLE_COMPONENT_STATE_OFF = 0,
57
62
  /** BLE should be disabled on next loop. */
@@ -141,21 +146,31 @@ class ESP32BLE : public Component {
141
146
  private:
142
147
  template<typename... Args> friend void enqueue_ble_event(Args... args);
143
148
 
149
+ // Vectors (12 bytes each on 32-bit, naturally aligned to 4 bytes)
144
150
  std::vector<GAPEventHandler *> gap_event_handlers_;
145
151
  std::vector<GAPScanEventHandler *> gap_scan_event_handlers_;
146
152
  std::vector<GATTcEventHandler *> gattc_event_handlers_;
147
153
  std::vector<GATTsEventHandler *> gatts_event_handlers_;
148
154
  std::vector<BLEStatusEventHandler *> ble_status_event_handlers_;
149
- BLEComponentState state_{BLE_COMPONENT_STATE_OFF};
150
-
151
- LockFreeQueue<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_events_;
152
- BLEEventPool<MAX_BLE_QUEUE_SIZE> ble_event_pool_;
153
- BLEAdvertising *advertising_{};
154
- esp_ble_io_cap_t io_cap_{ESP_IO_CAP_NONE};
155
- uint32_t advertising_cycle_time_{};
156
- bool enable_on_boot_{};
155
+
156
+ // Large objects (size depends on template parameters, but typically aligned to 4 bytes)
157
+ esphome::LockFreeQueue<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_events_;
158
+ esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_event_pool_;
159
+
160
+ // optional<string> (typically 16+ bytes on 32-bit, aligned to 4 bytes)
157
161
  optional<std::string> name_;
158
- uint16_t appearance_{0};
162
+
163
+ // 4-byte aligned members
164
+ BLEAdvertising *advertising_{}; // 4 bytes (pointer)
165
+ esp_ble_io_cap_t io_cap_{ESP_IO_CAP_NONE}; // 4 bytes (enum)
166
+ uint32_t advertising_cycle_time_{}; // 4 bytes
167
+
168
+ // 2-byte aligned members
169
+ uint16_t appearance_{0}; // 2 bytes
170
+
171
+ // 1-byte aligned members (grouped together to minimize padding)
172
+ BLEComponentState state_{BLE_COMPONENT_STATE_OFF}; // 1 byte (uint8_t enum)
173
+ bool enable_on_boot_{}; // 1 byte
159
174
  };
160
175
 
161
176
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)