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
@@ -484,7 +484,7 @@ bool I2SAudioSpeaker::send_esp_err_to_event_group_(esp_err_t err) {
484
484
  esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) {
485
485
  if (this->data_buffer_ == nullptr) {
486
486
  // Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus
487
- ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
487
+ RAMAllocator<uint8_t> allocator;
488
488
  this->data_buffer_ = allocator.allocate(data_buffer_size);
489
489
  }
490
490
 
@@ -698,7 +698,7 @@ void I2SAudioSpeaker::delete_task_(size_t buffer_size) {
698
698
  this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
699
699
 
700
700
  if (this->data_buffer_ != nullptr) {
701
- ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
701
+ RAMAllocator<uint8_t> allocator;
702
702
  allocator.deallocate(this->data_buffer_, buffer_size);
703
703
  this->data_buffer_ = nullptr;
704
704
  }
@@ -16,8 +16,6 @@ class IAQCore : public PollingComponent, public i2c::I2CDevice {
16
16
  void update() override;
17
17
  void dump_config() override;
18
18
 
19
- float get_setup_priority() const override { return setup_priority::DATA; }
20
-
21
19
  protected:
22
20
  sensor::Sensor *co2_{nullptr};
23
21
  sensor::Sensor *tvoc_{nullptr};
@@ -10,8 +10,10 @@ from PIL import Image, UnidentifiedImageError
10
10
 
11
11
  from esphome import core, external_files
12
12
  import esphome.codegen as cg
13
+ from esphome.components.const import CONF_BYTE_ORDER
13
14
  import esphome.config_validation as cv
14
15
  from esphome.const import (
16
+ CONF_DEFAULTS,
15
17
  CONF_DITHER,
16
18
  CONF_FILE,
17
19
  CONF_ICON,
@@ -38,6 +40,7 @@ CONF_OPAQUE = "opaque"
38
40
  CONF_CHROMA_KEY = "chroma_key"
39
41
  CONF_ALPHA_CHANNEL = "alpha_channel"
40
42
  CONF_INVERT_ALPHA = "invert_alpha"
43
+ CONF_IMAGES = "images"
41
44
 
42
45
  TRANSPARENCY_TYPES = (
43
46
  CONF_OPAQUE,
@@ -188,6 +191,10 @@ class ImageRGB565(ImageEncoder):
188
191
  dither,
189
192
  invert_alpha,
190
193
  )
194
+ self.big_endian = True
195
+
196
+ def set_big_endian(self, big_endian: bool) -> None:
197
+ self.big_endian = big_endian
191
198
 
192
199
  def convert(self, image, path):
193
200
  return image.convert("RGBA")
@@ -205,10 +212,16 @@ class ImageRGB565(ImageEncoder):
205
212
  g = 1
206
213
  b = 0
207
214
  rgb = (r << 11) | (g << 5) | b
208
- self.data[self.index] = rgb >> 8
209
- self.index += 1
210
- self.data[self.index] = rgb & 0xFF
211
- self.index += 1
215
+ if self.big_endian:
216
+ self.data[self.index] = rgb >> 8
217
+ self.index += 1
218
+ self.data[self.index] = rgb & 0xFF
219
+ self.index += 1
220
+ else:
221
+ self.data[self.index] = rgb & 0xFF
222
+ self.index += 1
223
+ self.data[self.index] = rgb >> 8
224
+ self.index += 1
212
225
  if self.transparency == CONF_ALPHA_CHANNEL:
213
226
  if self.invert_alpha:
214
227
  a ^= 0xFF
@@ -364,7 +377,7 @@ def validate_file_shorthand(value):
364
377
  value = cv.string_strict(value)
365
378
  parts = value.strip().split(":")
366
379
  if len(parts) == 2 and parts[0] in MDI_SOURCES:
367
- match = re.match(r"[a-zA-Z0-9\-]+", parts[1])
380
+ match = re.match(r"^[a-zA-Z0-9\-]+$", parts[1])
368
381
  if match is None:
369
382
  raise cv.Invalid(f"Could not parse mdi icon name from '{value}'.")
370
383
  return download_gh_svg(parts[1], parts[0])
@@ -434,20 +447,29 @@ def validate_type(image_types):
434
447
 
435
448
 
436
449
  def validate_settings(value):
437
- type = value[CONF_TYPE]
450
+ """
451
+ Validate the settings for a single image configuration.
452
+ """
453
+ conf_type = value[CONF_TYPE]
454
+ type_class = IMAGE_TYPE[conf_type]
438
455
  transparency = value[CONF_TRANSPARENCY].lower()
439
- allow_config = IMAGE_TYPE[type].allow_config
440
- if transparency not in allow_config:
456
+ if transparency not in type_class.allow_config:
441
457
  raise cv.Invalid(
442
- f"Image format '{type}' cannot have transparency: {transparency}"
458
+ f"Image format '{conf_type}' cannot have transparency: {transparency}"
443
459
  )
444
460
  invert_alpha = value.get(CONF_INVERT_ALPHA, False)
445
461
  if (
446
462
  invert_alpha
447
463
  and transparency != CONF_ALPHA_CHANNEL
448
- and CONF_INVERT_ALPHA not in allow_config
464
+ and CONF_INVERT_ALPHA not in type_class.allow_config
449
465
  ):
450
466
  raise cv.Invalid("No alpha channel to invert")
467
+ if value.get(CONF_BYTE_ORDER) is not None and not callable(
468
+ getattr(type_class, "set_big_endian", None)
469
+ ):
470
+ raise cv.Invalid(
471
+ f"Image format '{conf_type}' does not support byte order configuration"
472
+ )
451
473
  if file := value.get(CONF_FILE):
452
474
  file = Path(file)
453
475
  if is_svg_file(file):
@@ -456,31 +478,82 @@ def validate_settings(value):
456
478
  try:
457
479
  Image.open(file)
458
480
  except UnidentifiedImageError as exc:
459
- raise cv.Invalid(f"File can't be opened as image: {file}") from exc
481
+ raise cv.Invalid(
482
+ f"File can't be opened as image: {file.absolute()}"
483
+ ) from exc
460
484
  return value
461
485
 
462
486
 
487
+ IMAGE_ID_SCHEMA = {
488
+ cv.Required(CONF_ID): cv.declare_id(Image_),
489
+ cv.Required(CONF_FILE): cv.Any(validate_file_shorthand, TYPED_FILE_SCHEMA),
490
+ cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
491
+ }
492
+
493
+
494
+ OPTIONS_SCHEMA = {
495
+ cv.Optional(CONF_RESIZE): cv.dimensions,
496
+ cv.Optional(CONF_DITHER, default="NONE"): cv.one_of(
497
+ "NONE", "FLOYDSTEINBERG", upper=True
498
+ ),
499
+ cv.Optional(CONF_INVERT_ALPHA, default=False): cv.boolean,
500
+ cv.Optional(CONF_BYTE_ORDER): cv.one_of("BIG_ENDIAN", "LITTLE_ENDIAN", upper=True),
501
+ cv.Optional(CONF_TRANSPARENCY, default=CONF_OPAQUE): validate_transparency(),
502
+ cv.Optional(CONF_TYPE): validate_type(IMAGE_TYPE),
503
+ }
504
+
505
+ OPTIONS = [key.schema for key in OPTIONS_SCHEMA]
506
+
507
+ # image schema with no defaults, used with `CONF_IMAGES` in the config
508
+ IMAGE_SCHEMA_NO_DEFAULTS = {
509
+ **IMAGE_ID_SCHEMA,
510
+ **{cv.Optional(key): OPTIONS_SCHEMA[key] for key in OPTIONS},
511
+ }
512
+
463
513
  BASE_SCHEMA = cv.Schema(
464
514
  {
465
- cv.Required(CONF_ID): cv.declare_id(Image_),
466
- cv.Required(CONF_FILE): cv.Any(validate_file_shorthand, TYPED_FILE_SCHEMA),
467
- cv.Optional(CONF_RESIZE): cv.dimensions,
468
- cv.Optional(CONF_DITHER, default="NONE"): cv.one_of(
469
- "NONE", "FLOYDSTEINBERG", upper=True
470
- ),
471
- cv.Optional(CONF_INVERT_ALPHA, default=False): cv.boolean,
472
- cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
515
+ **IMAGE_ID_SCHEMA,
516
+ **OPTIONS_SCHEMA,
473
517
  }
474
518
  ).add_extra(validate_settings)
475
519
 
476
520
  IMAGE_SCHEMA = BASE_SCHEMA.extend(
477
521
  {
478
522
  cv.Required(CONF_TYPE): validate_type(IMAGE_TYPE),
479
- cv.Optional(CONF_TRANSPARENCY, default=CONF_OPAQUE): validate_transparency(),
480
523
  }
481
524
  )
482
525
 
483
526
 
527
+ def validate_defaults(value):
528
+ """
529
+ Validate the options for images with defaults
530
+ """
531
+ defaults = value[CONF_DEFAULTS]
532
+ result = []
533
+ for index, image in enumerate(value[CONF_IMAGES]):
534
+ type = image.get(CONF_TYPE, defaults.get(CONF_TYPE))
535
+ if type is None:
536
+ raise cv.Invalid(
537
+ "Type is required either in the image config or in the defaults",
538
+ path=[CONF_IMAGES, index],
539
+ )
540
+ type_class = IMAGE_TYPE[type]
541
+ # A default byte order should be simply ignored if the type does not support it
542
+ available_options = [*OPTIONS]
543
+ if (
544
+ not callable(getattr(type_class, "set_big_endian", None))
545
+ and CONF_BYTE_ORDER not in image
546
+ ):
547
+ available_options.remove(CONF_BYTE_ORDER)
548
+ config = {
549
+ **{key: image.get(key, defaults.get(key)) for key in available_options},
550
+ **{key.schema: image[key.schema] for key in IMAGE_ID_SCHEMA},
551
+ }
552
+ validate_settings(config)
553
+ result.append(config)
554
+ return result
555
+
556
+
484
557
  def typed_image_schema(image_type):
485
558
  """
486
559
  Construct a schema for a specific image type, allowing transparency options
@@ -523,10 +596,33 @@ def typed_image_schema(image_type):
523
596
 
524
597
  # The config schema can be a (possibly empty) single list of images,
525
598
  # or a dictionary of image types each with a list of images
526
- CONFIG_SCHEMA = cv.Any(
527
- cv.Schema({cv.Optional(t.lower()): typed_image_schema(t) for t in IMAGE_TYPE}),
528
- cv.ensure_list(IMAGE_SCHEMA),
529
- )
599
+ # or a dictionary with keys `defaults:` and `images:`
600
+
601
+
602
+ def _config_schema(config):
603
+ if isinstance(config, list):
604
+ return cv.Schema([IMAGE_SCHEMA])(config)
605
+ if not isinstance(config, dict):
606
+ raise cv.Invalid(
607
+ "Badly formed image configuration, expected a list or a dictionary"
608
+ )
609
+ if CONF_DEFAULTS in config or CONF_IMAGES in config:
610
+ return validate_defaults(
611
+ cv.Schema(
612
+ {
613
+ cv.Required(CONF_DEFAULTS): OPTIONS_SCHEMA,
614
+ cv.Required(CONF_IMAGES): cv.ensure_list(IMAGE_SCHEMA_NO_DEFAULTS),
615
+ }
616
+ )(config)
617
+ )
618
+ if CONF_ID in config or CONF_FILE in config:
619
+ return cv.ensure_list(IMAGE_SCHEMA)([config])
620
+ return cv.Schema(
621
+ {cv.Optional(t.lower()): typed_image_schema(t) for t in IMAGE_TYPE}
622
+ )(config)
623
+
624
+
625
+ CONFIG_SCHEMA = _config_schema
530
626
 
531
627
 
532
628
  async def write_image(config, all_frames=False):
@@ -585,6 +681,9 @@ async def write_image(config, all_frames=False):
585
681
 
586
682
  total_rows = height * frame_count
587
683
  encoder = IMAGE_TYPE[type](width, total_rows, transparency, dither, invert_alpha)
684
+ if byte_order := config.get(CONF_BYTE_ORDER):
685
+ # Check for valid type has already been done in validate_settings
686
+ encoder.set_big_endian(byte_order == "BIG_ENDIAN")
588
687
  for frame_index in range(frame_count):
589
688
  image.seek(frame_index)
590
689
  pixels = encoder.convert(image.resize((width, height)), path).getdata()
@@ -59,11 +59,7 @@ optional<uint8_t> ImprovSerialComponent::read_byte_() {
59
59
  break;
60
60
  #if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
61
61
  case logger::UART_SELECTION_USB_CDC:
62
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
63
62
  if (esp_usb_console_available_for_read()) {
64
- #else
65
- if (esp_usb_console_read_available()) {
66
- #endif
67
63
  esp_usb_console_read_buf((char *) &data, 1);
68
64
  byte = data;
69
65
  }
@@ -129,6 +129,13 @@ void INA219Component::setup() {
129
129
  }
130
130
  }
131
131
 
132
+ void INA219Component::on_powerdown() {
133
+ // Mode = 0 -> power down
134
+ if (!this->write_byte_16(INA219_REGISTER_CONFIG, 0)) {
135
+ ESP_LOGE(TAG, "powerdown error");
136
+ }
137
+ }
138
+
132
139
  void INA219Component::dump_config() {
133
140
  ESP_LOGCONFIG(TAG, "INA219:");
134
141
  LOG_I2C_DEVICE(this);
@@ -15,6 +15,7 @@ class INA219Component : public PollingComponent, public i2c::I2CDevice {
15
15
  void dump_config() override;
16
16
  float get_setup_priority() const override;
17
17
  void update() override;
18
+ void on_powerdown() override;
18
19
 
19
20
  void set_shunt_resistance_ohm(float shunt_resistance_ohm) { shunt_resistance_ohm_ = shunt_resistance_ohm; }
20
21
  void set_max_current_a(float max_current_a) { max_current_a_ = max_current_a; }
@@ -13,8 +13,6 @@ class INA260Component : public PollingComponent, public i2c::I2CDevice {
13
13
  void dump_config() override;
14
14
  void update() override;
15
15
 
16
- float get_setup_priority() const override { return setup_priority::DATA; }
17
-
18
16
  void set_bus_voltage_sensor(sensor::Sensor *bus_voltage_sensor) { this->bus_voltage_sensor_ = bus_voltage_sensor; }
19
17
  void set_current_sensor(sensor::Sensor *current_sensor) { this->current_sensor_ = current_sensor; }
20
18
  void set_power_sensor(sensor::Sensor *power_sensor) { this->power_sensor_ = power_sensor; }
@@ -16,7 +16,6 @@ class InkbirdIbstH1Mini : public Component, public esp32_ble_tracker::ESPBTDevic
16
16
  bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
17
17
 
18
18
  void dump_config() override;
19
- float get_setup_priority() const override { return setup_priority::DATA; }
20
19
  void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
21
20
  void set_external_temperature(sensor::Sensor *external_temperature) { external_temperature_ = external_temperature; }
22
21
  void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
@@ -1,6 +1,7 @@
1
1
  from esphome import pins
2
2
  import esphome.codegen as cg
3
3
  from esphome.components import display, i2c
4
+ from esphome.components.esp32 import CONF_CPU_FREQUENCY
4
5
  import esphome.config_validation as cv
5
6
  from esphome.const import (
6
7
  CONF_FULL_UPDATE_EVERY,
@@ -13,7 +14,9 @@ from esphome.const import (
13
14
  CONF_PAGES,
14
15
  CONF_TRANSFORM,
15
16
  CONF_WAKEUP_PIN,
17
+ PLATFORM_ESP32,
16
18
  )
19
+ import esphome.final_validate as fv
17
20
 
18
21
  DEPENDENCIES = ["i2c", "esp32"]
19
22
  AUTO_LOAD = ["psram"]
@@ -120,6 +123,18 @@ CONFIG_SCHEMA = cv.All(
120
123
  )
121
124
 
122
125
 
126
+ def _validate_cpu_frequency(config):
127
+ esp32_config = fv.full_config.get()[PLATFORM_ESP32]
128
+ if esp32_config[CONF_CPU_FREQUENCY] != "240MHZ":
129
+ raise cv.Invalid(
130
+ "Inkplate requires 240MHz CPU frequency (set in esp32 component)"
131
+ )
132
+ return config
133
+
134
+
135
+ FINAL_VALIDATE_SCHEMA = _validate_cpu_frequency
136
+
137
+
123
138
  async def to_code(config):
124
139
  var = cg.new_Pvariable(config[CONF_ID])
125
140
 
@@ -57,8 +57,8 @@ void Inkplate6::setup() {
57
57
  * Allocate buffers. May be called after setup to re-initialise if e.g. greyscale is changed.
58
58
  */
59
59
  void Inkplate6::initialize_() {
60
- ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
61
- ExternalRAMAllocator<uint32_t> allocator32(ExternalRAMAllocator<uint32_t>::ALLOW_FAILURE);
60
+ RAMAllocator<uint8_t> allocator;
61
+ RAMAllocator<uint32_t> allocator32;
62
62
  uint32_t buffer_size = this->get_buffer_length_();
63
63
  if (buffer_size == 0)
64
64
  return;
@@ -27,7 +27,6 @@ class IntegrationSensor : public sensor::Sensor, public Component {
27
27
  public:
28
28
  void setup() override;
29
29
  void dump_config() override;
30
- float get_setup_priority() const override { return setup_priority::DATA; }
31
30
  void set_sensor(Sensor *sensor) { sensor_ = sensor; }
32
31
  void set_time(IntegrationSensorTime time) { time_ = time; }
33
32
  void set_method(IntegrationMethod method) { method_ = method; }
@@ -10,11 +10,7 @@ uint8_t temprature_sens_read();
10
10
  #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \
11
11
  defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || \
12
12
  defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32P4)
13
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
14
- #include "driver/temp_sensor.h"
15
- #else
16
13
  #include "driver/temperature_sensor.h"
17
- #endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
18
14
  #endif // USE_ESP32_VARIANT
19
15
  #endif // USE_ESP32
20
16
  #ifdef USE_RP2040
@@ -31,12 +27,11 @@ namespace internal_temperature {
31
27
 
32
28
  static const char *const TAG = "internal_temperature";
33
29
  #ifdef USE_ESP32
34
- #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \
35
- (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \
36
- defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \
37
- defined(USE_ESP32_VARIANT_ESP32P4))
30
+ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \
31
+ defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \
32
+ defined(USE_ESP32_VARIANT_ESP32P4)
38
33
  static temperature_sensor_handle_t tsensNew = NULL;
39
- #endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT
34
+ #endif // USE_ESP32_VARIANT
40
35
  #endif // USE_ESP32
41
36
 
42
37
  void InternalTemperatureSensor::update() {
@@ -51,24 +46,11 @@ void InternalTemperatureSensor::update() {
51
46
  #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \
52
47
  defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || \
53
48
  defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32P4)
54
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
55
- temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT();
56
- temp_sensor_set_config(tsens);
57
- temp_sensor_start();
58
- #if defined(USE_ESP32_VARIANT_ESP32S3) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 3))
59
- #error \
60
- "ESP32-S3 internal temperature sensor requires ESP IDF V4.4.3 or higher. See https://github.com/esphome/issues/issues/4271"
61
- #endif
62
- esp_err_t result = temp_sensor_read_celsius(&temperature);
63
- temp_sensor_stop();
64
- success = (result == ESP_OK);
65
- #else
66
49
  esp_err_t result = temperature_sensor_get_celsius(tsensNew, &temperature);
67
50
  success = (result == ESP_OK);
68
51
  if (!success) {
69
52
  ESP_LOGE(TAG, "Reading failed (%d)", result);
70
53
  }
71
- #endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
72
54
  #endif // USE_ESP32_VARIANT
73
55
  #endif // USE_ESP32
74
56
  #ifdef USE_RP2040
@@ -99,10 +81,9 @@ void InternalTemperatureSensor::update() {
99
81
 
100
82
  void InternalTemperatureSensor::setup() {
101
83
  #ifdef USE_ESP32
102
- #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \
103
- (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \
104
- defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \
105
- defined(USE_ESP32_VARIANT_ESP32P4))
84
+ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \
85
+ defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2) || \
86
+ defined(USE_ESP32_VARIANT_ESP32P4)
106
87
  ESP_LOGCONFIG(TAG, "Running setup");
107
88
 
108
89
  temperature_sensor_config_t tsens_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
@@ -120,7 +101,7 @@ void InternalTemperatureSensor::setup() {
120
101
  this->mark_failed();
121
102
  return;
122
103
  }
123
- #endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT
104
+ #endif // USE_ESP32_VARIANT
124
105
  #endif // USE_ESP32
125
106
  }
126
107
 
@@ -1,46 +1,21 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import sensor
3
- from esphome.components.esp32 import get_esp32_variant
4
- from esphome.components.esp32.const import VARIANT_ESP32S3
5
3
  import esphome.config_validation as cv
6
4
  from esphome.const import (
7
5
  DEVICE_CLASS_TEMPERATURE,
8
6
  ENTITY_CATEGORY_DIAGNOSTIC,
9
- KEY_CORE,
10
- KEY_FRAMEWORK_VERSION,
11
7
  PLATFORM_BK72XX,
12
8
  PLATFORM_ESP32,
13
9
  PLATFORM_RP2040,
14
10
  STATE_CLASS_MEASUREMENT,
15
11
  UNIT_CELSIUS,
16
12
  )
17
- from esphome.core import CORE
18
13
 
19
14
  internal_temperature_ns = cg.esphome_ns.namespace("internal_temperature")
20
15
  InternalTemperatureSensor = internal_temperature_ns.class_(
21
16
  "InternalTemperatureSensor", sensor.Sensor, cg.PollingComponent
22
17
  )
23
18
 
24
-
25
- def validate_config(config):
26
- if CORE.is_esp32:
27
- variant = get_esp32_variant()
28
- if variant == VARIANT_ESP32S3:
29
- if CORE.using_arduino and CORE.data[KEY_CORE][
30
- KEY_FRAMEWORK_VERSION
31
- ] < cv.Version(2, 0, 6):
32
- raise cv.Invalid(
33
- "ESP32-S3 Internal Temperature Sensor requires framework version 2.0.6 or higher. See <https://github.com/esphome/issues/issues/4271>."
34
- )
35
- if CORE.using_esp_idf and CORE.data[KEY_CORE][
36
- KEY_FRAMEWORK_VERSION
37
- ] < cv.Version(4, 4, 3):
38
- raise cv.Invalid(
39
- "ESP32-S3 Internal Temperature Sensor requires framework version 4.4.3 or higher. See <https://github.com/esphome/issues/issues/4271>."
40
- )
41
- return config
42
-
43
-
44
19
  CONFIG_SCHEMA = cv.All(
45
20
  sensor.sensor_schema(
46
21
  InternalTemperatureSensor,
@@ -51,7 +26,6 @@ CONFIG_SCHEMA = cv.All(
51
26
  entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
52
27
  ).extend(cv.polling_component_schema("60s")),
53
28
  cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX]),
54
- validate_config,
55
29
  )
56
30
 
57
31
 
@@ -23,8 +23,6 @@ class IntervalTrigger : public Trigger<>, public PollingComponent {
23
23
 
24
24
  void set_startup_delay(const uint32_t startup_delay) { this->startup_delay_ = startup_delay; }
25
25
 
26
- float get_setup_priority() const override { return setup_priority::DATA; }
27
-
28
26
  protected:
29
27
  uint32_t startup_delay_{0};
30
28
  bool started_{false};
@@ -12,6 +12,6 @@ CONFIG_SCHEMA = cv.All(
12
12
 
13
13
  @coroutine_with_priority(1.0)
14
14
  async def to_code(config):
15
- cg.add_library("bblanchon/ArduinoJson", "6.18.5")
15
+ cg.add_library("bblanchon/ArduinoJson", "7.4.2")
16
16
  cg.add_define("USE_JSON")
17
17
  cg.add_global(json_ns.using)
@@ -1,83 +1,76 @@
1
1
  #include "json_util.h"
2
2
  #include "esphome/core/log.h"
3
3
 
4
+ // ArduinoJson::Allocator is included via ArduinoJson.h in json_util.h
5
+
4
6
  namespace esphome {
5
7
  namespace json {
6
8
 
7
9
  static const char *const TAG = "json";
8
10
 
9
- static std::vector<char> global_json_build_buffer; // NOLINT
10
- static const auto ALLOCATOR = RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::ALLOC_INTERNAL);
11
+ // Build an allocator for the JSON Library using the RAMAllocator class
12
+ struct SpiRamAllocator : ArduinoJson::Allocator {
13
+ void *allocate(size_t size) override { return this->allocator_.allocate(size); }
14
+
15
+ void deallocate(void *pointer) override {
16
+ // ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate.
17
+ // RAMAllocator::deallocate() requires the size, which we don't have access to here.
18
+ // RAMAllocator::deallocate implementation just calls free() regardless of whether
19
+ // the memory was allocated with heap_caps_malloc or malloc.
20
+ // This is safe because ESP-IDF's heap implementation internally tracks the memory region
21
+ // and routes free() to the appropriate heap.
22
+ free(pointer); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
23
+ }
24
+
25
+ void *reallocate(void *ptr, size_t new_size) override {
26
+ return this->allocator_.reallocate(static_cast<uint8_t *>(ptr), new_size);
27
+ }
28
+
29
+ protected:
30
+ RAMAllocator<uint8_t> allocator_{RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::NONE)};
31
+ };
11
32
 
12
33
  std::string build_json(const json_build_t &f) {
13
- // Here we are allocating up to 5kb of memory,
14
- // with the heap size minus 2kb to be safe if less than 5kb
15
- // as we can not have a true dynamic sized document.
16
- // The excess memory is freed below with `shrinkToFit()`
17
- auto free_heap = ALLOCATOR.get_max_free_block_size();
18
- size_t request_size = std::min(free_heap, (size_t) 512);
19
- while (true) {
20
- ESP_LOGV(TAG, "Attempting to allocate %zu bytes for JSON serialization", request_size);
21
- DynamicJsonDocument json_document(request_size);
22
- if (json_document.capacity() == 0) {
23
- ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, largest free heap block: %zu bytes",
24
- request_size, free_heap);
25
- return "{}";
26
- }
27
- JsonObject root = json_document.to<JsonObject>();
28
- f(root);
29
- if (json_document.overflowed()) {
30
- if (request_size == free_heap) {
31
- ESP_LOGE(TAG, "Could not allocate memory for document! Overflowed largest free heap block: %zu bytes",
32
- free_heap);
33
- return "{}";
34
- }
35
- request_size = std::min(request_size * 2, free_heap);
36
- continue;
37
- }
38
- json_document.shrinkToFit();
39
- ESP_LOGV(TAG, "Size after shrink %zu bytes", json_document.capacity());
40
- std::string output;
41
- serializeJson(json_document, output);
42
- return output;
34
+ // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
35
+ auto doc_allocator = SpiRamAllocator();
36
+ JsonDocument json_document(&doc_allocator);
37
+ if (json_document.overflowed()) {
38
+ ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
39
+ return "{}";
40
+ }
41
+ JsonObject root = json_document.to<JsonObject>();
42
+ f(root);
43
+ if (json_document.overflowed()) {
44
+ ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
45
+ return "{}";
43
46
  }
47
+ std::string output;
48
+ serializeJson(json_document, output);
49
+ return output;
50
+ // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
44
51
  }
45
52
 
46
53
  bool parse_json(const std::string &data, const json_parse_t &f) {
47
- // Here we are allocating 1.5 times the data size,
48
- // with the heap size minus 2kb to be safe if less than that
49
- // as we can not have a true dynamic sized document.
50
- // The excess memory is freed below with `shrinkToFit()`
51
- auto free_heap = ALLOCATOR.get_max_free_block_size();
52
- size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5));
53
- while (true) {
54
- DynamicJsonDocument json_document(request_size);
55
- if (json_document.capacity() == 0) {
56
- ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, free heap: %zu", request_size,
57
- free_heap);
58
- return false;
59
- }
60
- DeserializationError err = deserializeJson(json_document, data);
61
- json_document.shrinkToFit();
54
+ // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
55
+ auto doc_allocator = SpiRamAllocator();
56
+ JsonDocument json_document(&doc_allocator);
57
+ if (json_document.overflowed()) {
58
+ ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
59
+ return false;
60
+ }
61
+ DeserializationError err = deserializeJson(json_document, data);
62
62
 
63
- JsonObject root = json_document.as<JsonObject>();
63
+ JsonObject root = json_document.as<JsonObject>();
64
64
 
65
- if (err == DeserializationError::Ok) {
66
- return f(root);
67
- } else if (err == DeserializationError::NoMemory) {
68
- if (request_size * 2 >= free_heap) {
69
- ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller");
70
- return false;
71
- }
72
- ESP_LOGV(TAG, "Increasing memory allocation.");
73
- request_size *= 2;
74
- continue;
75
- } else {
76
- ESP_LOGE(TAG, "Parse error: %s", err.c_str());
77
- return false;
78
- }
79
- };
65
+ if (err == DeserializationError::Ok) {
66
+ return f(root);
67
+ } else if (err == DeserializationError::NoMemory) {
68
+ ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller");
69
+ return false;
70
+ }
71
+ ESP_LOGE(TAG, "Parse error: %s", err.c_str());
80
72
  return false;
73
+ // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
81
74
  }
82
75
 
83
76
  } // namespace json