esphome 2025.8.4__py3-none-any.whl → 2025.9.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. esphome/__main__.py +177 -105
  2. esphome/components/absolute_humidity/absolute_humidity.cpp +3 -5
  3. esphome/components/adc/__init__.py +1 -26
  4. esphome/components/adc/adc_sensor_esp32.cpp +29 -6
  5. esphome/components/adc/sensor.py +20 -0
  6. esphome/components/ags10/ags10.cpp +3 -18
  7. esphome/components/ags10/ags10.h +2 -12
  8. esphome/components/aht10/aht10.cpp +3 -3
  9. esphome/components/airthings_ble/__init__.py +2 -2
  10. esphome/components/alarm_control_panel/__init__.py +2 -2
  11. esphome/components/am2315c/am2315c.cpp +1 -17
  12. esphome/components/am2315c/am2315c.h +2 -3
  13. esphome/components/api/__init__.py +2 -2
  14. esphome/components/api/api_connection.cpp +38 -34
  15. esphome/components/api/api_connection.h +20 -40
  16. esphome/components/api/api_frame_helper.cpp +25 -25
  17. esphome/components/api/api_frame_helper.h +3 -3
  18. esphome/components/api/api_frame_helper_noise.cpp +75 -40
  19. esphome/components/api/api_frame_helper_noise.h +3 -7
  20. esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
  21. esphome/components/api/api_frame_helper_plaintext.h +1 -4
  22. esphome/components/api/api_pb2.cpp +12 -2
  23. esphome/components/api/api_pb2.h +144 -143
  24. esphome/components/api/api_pb2_dump.cpp +6 -1
  25. esphome/components/api/api_pb2_service.cpp +0 -14
  26. esphome/components/api/api_pb2_service.h +1 -3
  27. esphome/components/api/client.py +5 -3
  28. esphome/components/api/proto.cpp +33 -37
  29. esphome/components/async_tcp/__init__.py +2 -2
  30. esphome/components/atm90e26/sensor.py +2 -0
  31. esphome/components/atm90e32/sensor.py +4 -2
  32. esphome/components/audio_adc/__init__.py +2 -2
  33. esphome/components/audio_dac/__init__.py +2 -2
  34. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
  35. esphome/components/bedjet/bedjet_hub.cpp +1 -1
  36. esphome/components/binary_sensor/__init__.py +2 -2
  37. esphome/components/binary_sensor/binary_sensor.cpp +13 -0
  38. esphome/components/binary_sensor/binary_sensor.h +4 -7
  39. esphome/components/bl0940/__init__.py +6 -1
  40. esphome/components/bl0940/bl0940.cpp +178 -41
  41. esphome/components/bl0940/bl0940.h +121 -76
  42. esphome/components/bl0940/button/__init__.py +27 -0
  43. esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
  44. esphome/components/bl0940/button/calibration_reset_button.h +19 -0
  45. esphome/components/bl0940/number/__init__.py +94 -0
  46. esphome/components/bl0940/number/calibration_number.cpp +29 -0
  47. esphome/components/bl0940/number/calibration_number.h +26 -0
  48. esphome/components/bl0940/sensor.py +151 -2
  49. esphome/components/bl0942/bl0942.cpp +1 -1
  50. esphome/components/ble_client/output/__init__.py +4 -4
  51. esphome/components/bluetooth_proxy/__init__.py +1 -1
  52. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
  54. esphome/components/bluetooth_proxy/bluetooth_proxy.h +6 -3
  55. esphome/components/button/__init__.py +2 -2
  56. esphome/components/button/button.cpp +13 -0
  57. esphome/components/button/button.h +4 -7
  58. esphome/components/camera/buffer.h +18 -0
  59. esphome/components/camera/buffer_impl.cpp +20 -0
  60. esphome/components/camera/buffer_impl.h +26 -0
  61. esphome/components/camera/camera.h +43 -0
  62. esphome/components/camera/encoder.h +69 -0
  63. esphome/components/camera_encoder/__init__.py +62 -0
  64. esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
  65. esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
  66. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
  67. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
  68. esphome/components/captive_portal/__init__.py +2 -2
  69. esphome/components/captive_portal/captive_index.h +77 -97
  70. esphome/components/captive_portal/captive_portal.cpp +35 -12
  71. esphome/components/captive_portal/captive_portal.h +3 -3
  72. esphome/components/ccs811/ccs811.cpp +3 -3
  73. esphome/components/climate/__init__.py +2 -2
  74. esphome/components/climate/climate.cpp +1 -1
  75. esphome/components/cover/__init__.py +5 -5
  76. esphome/components/cover/cover.cpp +1 -1
  77. esphome/components/cover/cover.h +2 -2
  78. esphome/components/dallas_temp/dallas_temp.cpp +2 -2
  79. esphome/components/datetime/__init__.py +2 -2
  80. esphome/components/datetime/date_entity.h +2 -2
  81. esphome/components/datetime/datetime_entity.h +2 -2
  82. esphome/components/datetime/time_entity.h +2 -2
  83. esphome/components/debug/debug_esp32.cpp +1 -1
  84. esphome/components/display/__init__.py +4 -4
  85. esphome/components/duty_time/duty_time_sensor.cpp +1 -1
  86. esphome/components/esp32/__init__.py +0 -5
  87. esphome/components/esp32/gpio.cpp +27 -23
  88. esphome/components/esp32/gpio.h +26 -11
  89. esphome/components/esp32/preferences.cpp +8 -4
  90. esphome/components/esp32_ble/__init__.py +7 -2
  91. esphome/components/esp32_ble/ble_uuid.cpp +30 -9
  92. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +4 -3
  93. esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
  94. esphome/components/esp32_ble_client/ble_client_base.h +8 -5
  95. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  96. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +11 -47
  97. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
  98. esphome/components/esp8266/__init__.py +2 -2
  99. esphome/components/esp8266/core.cpp +2 -2
  100. esphome/components/esp8266/gpio.py +4 -4
  101. esphome/components/esp8266/preferences.cpp +30 -28
  102. esphome/components/esphome/ota/__init__.py +2 -2
  103. esphome/components/esphome/ota/ota_esphome.cpp +21 -19
  104. esphome/components/esphome/ota/ota_esphome.h +6 -5
  105. esphome/components/ethernet/__init__.py +7 -2
  106. esphome/components/ethernet/ethernet_component.cpp +49 -3
  107. esphome/components/ethernet/ethernet_component.h +2 -0
  108. esphome/components/event/__init__.py +2 -2
  109. esphome/components/event/event.h +4 -4
  110. esphome/components/factory_reset/button/factory_reset_button.cpp +18 -1
  111. esphome/components/factory_reset/button/factory_reset_button.h +6 -1
  112. esphome/components/factory_reset/switch/factory_reset_switch.cpp +18 -1
  113. esphome/components/factory_reset/switch/factory_reset_switch.h +5 -1
  114. esphome/components/fan/__init__.py +2 -2
  115. esphome/components/fan/fan.cpp +2 -1
  116. esphome/components/gdk101/gdk101.cpp +4 -4
  117. esphome/components/globals/__init__.py +2 -2
  118. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
  119. esphome/components/gpio_expander/cached_gpio.h +36 -16
  120. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
  121. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  122. esphome/components/haier/haier_base.cpp +1 -1
  123. esphome/components/haier/hon_climate.cpp +1 -1
  124. esphome/components/hlw8012/hlw8012.cpp +5 -5
  125. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
  126. esphome/components/host/preferences.h +3 -2
  127. esphome/components/hte501/hte501.cpp +3 -21
  128. esphome/components/hte501/hte501.h +2 -3
  129. esphome/components/http_request/ota/__init__.py +2 -2
  130. esphome/components/i2c/__init__.py +2 -2
  131. esphome/components/i2c/i2c.cpp +13 -9
  132. esphome/components/i2c/i2c_bus.h +36 -6
  133. esphome/components/i2s_audio/__init__.py +8 -2
  134. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  135. esphome/components/i2s_audio/microphone/__init__.py +1 -1
  136. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  137. esphome/components/ina2xx_base/__init__.py +4 -2
  138. esphome/components/inkplate/__init__.py +1 -0
  139. esphome/components/inkplate/const.py +105 -0
  140. esphome/components/inkplate/display.py +238 -0
  141. esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
  142. esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
  143. esphome/components/inkplate6/__init__.py +0 -1
  144. esphome/components/inkplate6/display.py +2 -211
  145. esphome/components/integration/integration_sensor.cpp +1 -1
  146. esphome/components/json/__init__.py +2 -2
  147. esphome/components/lc709203f/lc709203f.cpp +4 -17
  148. esphome/components/lc709203f/lc709203f.h +2 -3
  149. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  150. esphome/components/ld2450/ld2450.cpp +1 -1
  151. esphome/components/libretiny/preferences.cpp +13 -5
  152. esphome/components/light/__init__.py +2 -2
  153. esphome/components/light/addressable_light_effect.h +7 -0
  154. esphome/components/light/base_light_effects.h +8 -0
  155. esphome/components/light/light_call.cpp +22 -20
  156. esphome/components/light/light_effect.cpp +36 -0
  157. esphome/components/light/light_effect.h +14 -0
  158. esphome/components/light/light_json_schema.cpp +9 -1
  159. esphome/components/light/light_state.cpp +2 -2
  160. esphome/components/light/light_state.h +38 -0
  161. esphome/components/lock/__init__.py +2 -2
  162. esphome/components/lock/lock.h +2 -2
  163. esphome/components/logger/__init__.py +2 -2
  164. esphome/components/logger/logger.cpp +25 -4
  165. esphome/components/logger/logger.h +1 -1
  166. esphome/components/logger/logger_esp32.cpp +16 -8
  167. esphome/components/logger/logger_esp8266.cpp +11 -3
  168. esphome/components/logger/logger_libretiny.cpp +13 -3
  169. esphome/components/logger/logger_rp2040.cpp +14 -3
  170. esphome/components/logger/logger_zephyr.cpp +15 -4
  171. esphome/components/lvgl/defines.py +1 -0
  172. esphome/components/lvgl/hello_world.py +96 -33
  173. esphome/components/lvgl/number/lvgl_number.h +1 -1
  174. esphome/components/lvgl/select/lvgl_select.h +1 -1
  175. esphome/components/lvgl/widgets/__init__.py +0 -1
  176. esphome/components/lvgl/widgets/spinbox.py +20 -11
  177. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  178. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  179. esphome/components/mapping/__init__.py +13 -5
  180. esphome/components/mapping/mapping.h +69 -0
  181. esphome/components/max17043/max17043.cpp +2 -2
  182. esphome/components/mcp23016/__init__.py +1 -0
  183. esphome/components/mcp23016/mcp23016.cpp +20 -5
  184. esphome/components/mcp23016/mcp23016.h +10 -4
  185. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  186. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  187. esphome/components/md5/md5.cpp +3 -2
  188. esphome/components/mdns/__init__.py +2 -2
  189. esphome/components/mdns/mdns_component.cpp +145 -54
  190. esphome/components/media_player/__init__.py +2 -2
  191. esphome/components/micro_wake_word/__init__.py +2 -2
  192. esphome/components/microphone/__init__.py +2 -2
  193. esphome/components/mipi/__init__.py +77 -33
  194. esphome/components/mipi_rgb/__init__.py +2 -0
  195. esphome/components/mipi_rgb/display.py +321 -0
  196. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  197. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  198. esphome/components/mipi_rgb/models/guition.py +24 -0
  199. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  200. esphome/components/mipi_rgb/models/rpi.py +9 -0
  201. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  202. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  203. esphome/components/mipi_spi/models/jc.py +229 -0
  204. esphome/components/mlx90614/mlx90614.cpp +1 -16
  205. esphome/components/mlx90614/mlx90614.h +0 -1
  206. esphome/components/mqtt/__init__.py +2 -2
  207. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  208. esphome/components/ms5611/ms5611.cpp +7 -6
  209. esphome/components/network/__init__.py +2 -2
  210. esphome/components/nextion/nextion_upload.cpp +4 -1
  211. esphome/components/nrf52/__init__.py +49 -6
  212. esphome/components/nrf52/const.py +1 -0
  213. esphome/components/nrf52/dfu.cpp +51 -0
  214. esphome/components/nrf52/dfu.h +24 -0
  215. esphome/components/ntc/ntc.cpp +1 -1
  216. esphome/components/number/__init__.py +2 -2
  217. esphome/components/number/automation.cpp +1 -1
  218. esphome/components/number/number.cpp +21 -0
  219. esphome/components/number/number.h +4 -13
  220. esphome/components/opentherm/hub.h +6 -6
  221. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  222. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  223. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  224. esphome/components/openthread/openthread.cpp +41 -7
  225. esphome/components/openthread/openthread.h +11 -0
  226. esphome/components/ota/__init__.py +2 -2
  227. esphome/components/pca6416a/__init__.py +1 -0
  228. esphome/components/pca6416a/pca6416a.cpp +20 -5
  229. esphome/components/pca6416a/pca6416a.h +12 -5
  230. esphome/components/pca9554/__init__.py +2 -1
  231. esphome/components/pca9554/pca9554.cpp +12 -18
  232. esphome/components/pca9554/pca9554.h +10 -9
  233. esphome/components/pcf8574/__init__.py +1 -0
  234. esphome/components/pcf8574/pcf8574.cpp +14 -5
  235. esphome/components/pcf8574/pcf8574.h +13 -6
  236. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  237. esphome/components/pipsolar/__init__.py +3 -3
  238. esphome/components/pipsolar/output/__init__.py +4 -4
  239. esphome/components/pulse_width/pulse_width.cpp +2 -2
  240. esphome/components/qmp6988/qmp6988.cpp +81 -126
  241. esphome/components/qmp6988/qmp6988.h +31 -37
  242. esphome/components/radon_eye_ble/__init__.py +2 -2
  243. esphome/components/remote_base/__init__.py +6 -8
  244. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  245. esphome/components/rp2040/__init__.py +2 -2
  246. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  247. esphome/components/runtime_stats/runtime_stats.h +4 -10
  248. esphome/components/safe_mode/__init__.py +2 -2
  249. esphome/components/safe_mode/safe_mode.cpp +33 -31
  250. esphome/components/script/script.cpp +6 -0
  251. esphome/components/script/script.h +19 -5
  252. esphome/components/sdm_meter/sensor.py +3 -1
  253. esphome/components/select/__init__.py +2 -2
  254. esphome/components/select/select.h +2 -2
  255. esphome/components/sen5x/sen5x.cpp +57 -55
  256. esphome/components/sen5x/sen5x.h +21 -15
  257. esphome/components/sen5x/sensor.py +67 -44
  258. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  259. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  260. esphome/components/sensor/__init__.py +2 -2
  261. esphome/components/sensor/automation.h +1 -1
  262. esphome/components/sensor/sensor.cpp +34 -6
  263. esphome/components/sensor/sensor.h +4 -21
  264. esphome/components/sgp30/sgp30.cpp +34 -35
  265. esphome/components/sgp30/sgp30.h +11 -10
  266. esphome/components/sgp4x/sgp4x.cpp +2 -2
  267. esphome/components/shelly_dimmer/light.py +7 -7
  268. esphome/components/sht4x/sht4x.cpp +1 -1
  269. esphome/components/sntp/sntp_component.cpp +36 -9
  270. esphome/components/sntp/sntp_component.h +7 -0
  271. esphome/components/sound_level/sound_level.cpp +1 -1
  272. esphome/components/speaker/__init__.py +2 -2
  273. esphome/components/speaker/media_player/__init__.py +2 -2
  274. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  275. esphome/components/spi/__init__.py +2 -2
  276. esphome/components/sprinkler/sprinkler.cpp +1 -1
  277. esphome/components/sps30/sps30.cpp +18 -23
  278. esphome/components/sps30/sps30.h +3 -3
  279. esphome/components/status_led/__init__.py +2 -2
  280. esphome/components/stepper/__init__.py +2 -2
  281. esphome/components/switch/__init__.py +2 -2
  282. esphome/components/switch/switch.cpp +5 -5
  283. esphome/components/sx1509/__init__.py +1 -1
  284. esphome/components/sx1509/sx1509.cpp +12 -7
  285. esphome/components/sx1509/sx1509.h +11 -4
  286. esphome/components/tca9555/tca9555.cpp +5 -5
  287. esphome/components/tee501/tee501.cpp +2 -21
  288. esphome/components/tee501/tee501.h +2 -4
  289. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  290. esphome/components/template/datetime/template_date.cpp +1 -1
  291. esphome/components/template/datetime/template_datetime.cpp +2 -2
  292. esphome/components/template/datetime/template_time.cpp +1 -1
  293. esphome/components/template/number/template_number.cpp +1 -1
  294. esphome/components/template/select/template_select.cpp +1 -1
  295. esphome/components/template/text/template_text.cpp +1 -1
  296. esphome/components/text/__init__.py +2 -2
  297. esphome/components/text/text.h +2 -2
  298. esphome/components/text_sensor/__init__.py +2 -2
  299. esphome/components/text_sensor/text_sensor.h +4 -4
  300. esphome/components/thermostat/climate.py +11 -7
  301. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  302. esphome/components/thermostat/thermostat_climate.h +52 -41
  303. esphome/components/time/__init__.py +2 -2
  304. esphome/components/tmp1075/tmp1075.cpp +1 -1
  305. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  306. esphome/components/touchscreen/__init__.py +2 -2
  307. esphome/components/tuya/number/tuya_number.cpp +1 -1
  308. esphome/components/udp/udp_component.cpp +3 -3
  309. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  310. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  311. esphome/components/update/__init__.py +2 -2
  312. esphome/components/usb_uart/usb_uart.cpp +1 -1
  313. esphome/components/valve/__init__.py +5 -5
  314. esphome/components/valve/valve.cpp +1 -1
  315. esphome/components/valve/valve.h +2 -2
  316. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  317. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  318. esphome/components/web_server/__init__.py +2 -2
  319. esphome/components/web_server/ota/__init__.py +2 -2
  320. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  321. esphome/components/web_server/server_index_v2.h +149 -149
  322. esphome/components/web_server/web_server.cpp +58 -12
  323. esphome/components/web_server_base/__init__.py +2 -2
  324. esphome/components/wifi/__init__.py +5 -5
  325. esphome/components/wifi/wifi_component.cpp +4 -4
  326. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  327. esphome/components/wifi_info/wifi_info_text_sensor.h +3 -2
  328. esphome/config_validation.py +2 -2
  329. esphome/const.py +3 -1
  330. esphome/core/__init__.py +1 -0
  331. esphome/core/application.cpp +89 -51
  332. esphome/core/application.h +1 -0
  333. esphome/core/component.cpp +41 -19
  334. esphome/core/component.h +17 -13
  335. esphome/core/config.py +7 -7
  336. esphome/core/defines.h +4 -0
  337. esphome/core/entity_base.cpp +22 -8
  338. esphome/core/entity_base.h +43 -0
  339. esphome/core/helpers.cpp +34 -20
  340. esphome/core/helpers.h +33 -3
  341. esphome/core/ring_buffer.cpp +6 -2
  342. esphome/core/ring_buffer.h +2 -1
  343. esphome/core/scheduler.cpp +178 -97
  344. esphome/core/scheduler.h +67 -36
  345. esphome/core/time.cpp +6 -20
  346. esphome/coroutine.py +80 -3
  347. esphome/cpp_generator.py +13 -0
  348. esphome/cpp_helpers.py +2 -2
  349. esphome/dashboard/web_server.py +67 -10
  350. esphome/espota2.py +13 -6
  351. esphome/helpers.py +68 -83
  352. esphome/resolver.py +67 -0
  353. esphome/util.py +9 -6
  354. esphome/wizard.py +39 -26
  355. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/METADATA +9 -9
  356. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/RECORD +364 -333
  357. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  358. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  359. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  360. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  361. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/WHEEL +0 -0
  362. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/entry_points.txt +0 -0
  363. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/licenses/LICENSE +0 -0
  364. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/top_level.txt +0 -0
@@ -11,17 +11,35 @@ namespace captive_portal {
11
11
  static const char *const TAG = "captive_portal";
12
12
 
13
13
  void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
14
- AsyncResponseStream *stream = request->beginResponseStream("application/json");
15
- stream->addHeader("cache-control", "public, max-age=0, must-revalidate");
14
+ AsyncResponseStream *stream = request->beginResponseStream(F("application/json"));
15
+ stream->addHeader(F("cache-control"), F("public, max-age=0, must-revalidate"));
16
+ #ifdef USE_ESP8266
17
+ stream->print(F("{\"mac\":\""));
18
+ stream->print(get_mac_address_pretty().c_str());
19
+ stream->print(F("\",\"name\":\""));
20
+ stream->print(App.get_name().c_str());
21
+ stream->print(F("\",\"aps\":[{}"));
22
+ #else
16
23
  stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str());
24
+ #endif
17
25
 
18
26
  for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
19
27
  if (scan.get_is_hidden())
20
28
  continue;
21
29
 
22
- // Assumes no " in ssid, possible unicode isses?
30
+ // Assumes no " in ssid, possible unicode isses?
31
+ #ifdef USE_ESP8266
32
+ stream->print(F(",{\"ssid\":\""));
33
+ stream->print(scan.get_ssid().c_str());
34
+ stream->print(F("\",\"rssi\":"));
35
+ stream->print(scan.get_rssi());
36
+ stream->print(F(",\"lock\":"));
37
+ stream->print(scan.get_with_auth());
38
+ stream->print(F("}"));
39
+ #else
23
40
  stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
24
41
  scan.get_with_auth());
42
+ #endif
25
43
  }
26
44
  stream->print(F("]}"));
27
45
  request->send(stream);
@@ -34,7 +52,7 @@ void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
34
52
  ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
35
53
  wifi::global_wifi_component->save_wifi_sta(ssid, psk);
36
54
  wifi::global_wifi_component->start_scanning();
37
- request->redirect("/?save");
55
+ request->redirect(F("/?save"));
38
56
  }
39
57
 
40
58
  void CaptivePortal::setup() {
@@ -53,18 +71,23 @@ void CaptivePortal::start() {
53
71
  this->dns_server_ = make_unique<DNSServer>();
54
72
  this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
55
73
  network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip();
56
- this->dns_server_->start(53, "*", ip);
74
+ this->dns_server_->start(53, F("*"), ip);
57
75
  // Re-enable loop() when DNS server is started
58
76
  this->enable_loop();
59
77
  #endif
60
78
 
61
79
  this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
62
80
  if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
63
- req->send(404, "text/html", "File not found");
81
+ req->send(404, F("text/html"), F("File not found"));
64
82
  return;
65
83
  }
66
84
 
85
+ #ifdef USE_ESP8266
86
+ String url = F("http://");
87
+ url += wifi::global_wifi_component->wifi_soft_ap_ip().str().c_str();
88
+ #else
67
89
  auto url = "http://" + wifi::global_wifi_component->wifi_soft_ap_ip().str();
90
+ #endif
68
91
  req->redirect(url.c_str());
69
92
  });
70
93
 
@@ -73,19 +96,19 @@ void CaptivePortal::start() {
73
96
  }
74
97
 
75
98
  void CaptivePortal::handleRequest(AsyncWebServerRequest *req) {
76
- if (req->url() == "/") {
99
+ if (req->url() == F("/")) {
77
100
  #ifndef USE_ESP8266
78
- auto *response = req->beginResponse(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
101
+ auto *response = req->beginResponse(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
79
102
  #else
80
- auto *response = req->beginResponse_P(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
103
+ auto *response = req->beginResponse_P(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
81
104
  #endif
82
- response->addHeader("Content-Encoding", "gzip");
105
+ response->addHeader(F("Content-Encoding"), F("gzip"));
83
106
  req->send(response);
84
107
  return;
85
- } else if (req->url() == "/config.json") {
108
+ } else if (req->url() == F("/config.json")) {
86
109
  this->handle_config(req);
87
110
  return;
88
- } else if (req->url() == "/wifisave") {
111
+ } else if (req->url() == F("/wifisave")) {
89
112
  this->handle_wifisave(req);
90
113
  return;
91
114
  }
@@ -45,11 +45,11 @@ class CaptivePortal : public AsyncWebHandler, public Component {
45
45
  return false;
46
46
 
47
47
  if (request->method() == HTTP_GET) {
48
- if (request->url() == "/")
48
+ if (request->url() == F("/"))
49
49
  return true;
50
- if (request->url() == "/config.json")
50
+ if (request->url() == F("/config.json"))
51
51
  return true;
52
- if (request->url() == "/wifisave")
52
+ if (request->url() == F("/wifisave"))
53
53
  return true;
54
54
  }
55
55
 
@@ -152,9 +152,9 @@ void CCS811Component::send_env_data_() {
152
152
  void CCS811Component::dump_config() {
153
153
  ESP_LOGCONFIG(TAG, "CCS811");
154
154
  LOG_I2C_DEVICE(this)
155
- LOG_UPDATE_INTERVAL(this)
156
- LOG_SENSOR(" ", "CO2 Sensor", this->co2_)
157
- LOG_SENSOR(" ", "TVOC Sensor", this->tvoc_)
155
+ LOG_UPDATE_INTERVAL(this);
156
+ LOG_SENSOR(" ", "CO2 Sensor", this->co2_);
157
+ LOG_SENSOR(" ", "TVOC Sensor", this->tvoc_);
158
158
  LOG_TEXT_SENSOR(" ", "Firmware Version Sensor", this->version_)
159
159
  if (this->baseline_) {
160
160
  ESP_LOGCONFIG(TAG, " Baseline: %04X", *this->baseline_);
@@ -47,7 +47,7 @@ from esphome.const import (
47
47
  CONF_VISUAL,
48
48
  CONF_WEB_SERVER,
49
49
  )
50
- from esphome.core import CORE, coroutine_with_priority
50
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
51
51
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
52
52
  from esphome.cpp_generator import MockObjClass
53
53
 
@@ -517,6 +517,6 @@ async def climate_control_to_code(config, action_id, template_arg, args):
517
517
  return var
518
518
 
519
519
 
520
- @coroutine_with_priority(100.0)
520
+ @coroutine_with_priority(CoroPriority.CORE)
521
521
  async def to_code(config):
522
522
  cg.add_global(climate_ns.using)
@@ -327,7 +327,7 @@ void Climate::add_on_control_callback(std::function<void(ClimateCall &)> &&callb
327
327
  static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
328
328
 
329
329
  optional<ClimateDeviceRestoreState> Climate::restore_state_() {
330
- this->rtc_ = global_preferences->make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash() ^
330
+ this->rtc_ = global_preferences->make_preference<ClimateDeviceRestoreState>(this->get_preference_hash() ^
331
331
  RESTORE_STATE_VERSION);
332
332
  ClimateDeviceRestoreState recovered{};
333
333
  if (!this->rtc_.load(&recovered))
@@ -32,7 +32,7 @@ from esphome.const import (
32
32
  DEVICE_CLASS_SHUTTER,
33
33
  DEVICE_CLASS_WINDOW,
34
34
  )
35
- from esphome.core import CORE, coroutine_with_priority
35
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
36
36
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
37
37
  from esphome.cpp_generator import MockObjClass
38
38
 
@@ -228,9 +228,9 @@ async def cover_stop_to_code(config, action_id, template_arg, args):
228
228
 
229
229
 
230
230
  @automation.register_action("cover.toggle", ToggleAction, COVER_ACTION_SCHEMA)
231
- def cover_toggle_to_code(config, action_id, template_arg, args):
232
- paren = yield cg.get_variable(config[CONF_ID])
233
- yield cg.new_Pvariable(action_id, template_arg, paren)
231
+ async def cover_toggle_to_code(config, action_id, template_arg, args):
232
+ paren = await cg.get_variable(config[CONF_ID])
233
+ return cg.new_Pvariable(action_id, template_arg, paren)
234
234
 
235
235
 
236
236
  COVER_CONTROL_ACTION_SCHEMA = cv.Schema(
@@ -263,6 +263,6 @@ async def cover_control_to_code(config, action_id, template_arg, args):
263
263
  return var
264
264
 
265
265
 
266
- @coroutine_with_priority(100.0)
266
+ @coroutine_with_priority(CoroPriority.CORE)
267
267
  async def to_code(config):
268
268
  cg.add_global(cover_ns.using)
@@ -194,7 +194,7 @@ void Cover::publish_state(bool save) {
194
194
  }
195
195
  }
196
196
  optional<CoverRestoreState> Cover::restore_state_() {
197
- this->rtc_ = global_preferences->make_preference<CoverRestoreState>(this->get_object_id_hash());
197
+ this->rtc_ = global_preferences->make_preference<CoverRestoreState>(this->get_preference_hash());
198
198
  CoverRestoreState recovered{};
199
199
  if (!this->rtc_.load(&recovered))
200
200
  return {};
@@ -19,8 +19,8 @@ const extern float COVER_CLOSED;
19
19
  if (traits_.get_is_assumed_state()) { \
20
20
  ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
21
21
  } \
22
- if (!(obj)->get_device_class().empty()) { \
23
- ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \
22
+ if (!(obj)->get_device_class_ref().empty()) { \
23
+ ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \
24
24
  } \
25
25
  }
26
26
 
@@ -64,7 +64,7 @@ bool DallasTemperatureSensor::read_scratch_pad_() {
64
64
  }
65
65
  } else {
66
66
  ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str());
67
- this->status_set_warning("bus reset failed");
67
+ this->status_set_warning(LOG_STR("bus reset failed"));
68
68
  }
69
69
  return success;
70
70
  }
@@ -124,7 +124,7 @@ bool DallasTemperatureSensor::check_scratch_pad_() {
124
124
  crc8(this->scratch_pad_, 8));
125
125
  #endif
126
126
  if (!chksum_validity) {
127
- this->status_set_warning("scratch pad checksum invalid");
127
+ this->status_set_warning(LOG_STR("scratch pad checksum invalid"));
128
128
  ESP_LOGD(TAG, "Scratch pad: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X (%02X)", this->scratch_pad_[0],
129
129
  this->scratch_pad_[1], this->scratch_pad_[2], this->scratch_pad_[3], this->scratch_pad_[4],
130
130
  this->scratch_pad_[5], this->scratch_pad_[6], this->scratch_pad_[7], this->scratch_pad_[8],
@@ -21,7 +21,7 @@ from esphome.const import (
21
21
  CONF_WEB_SERVER,
22
22
  CONF_YEAR,
23
23
  )
24
- from esphome.core import CORE, coroutine_with_priority
24
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
25
25
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
26
26
  from esphome.cpp_generator import MockObjClass
27
27
 
@@ -172,7 +172,7 @@ async def new_datetime(config, *args):
172
172
  return var
173
173
 
174
174
 
175
- @coroutine_with_priority(100.0)
175
+ @coroutine_with_priority(CoroPriority.CORE)
176
176
  async def to_code(config):
177
177
  cg.add_global(datetime_ns.using)
178
178
 
@@ -16,8 +16,8 @@ namespace datetime {
16
16
  #define LOG_DATETIME_DATE(prefix, type, obj) \
17
17
  if ((obj) != nullptr) { \
18
18
  ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
19
- if (!(obj)->get_icon().empty()) { \
20
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
19
+ if (!(obj)->get_icon_ref().empty()) { \
20
+ ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
21
21
  } \
22
22
  }
23
23
 
@@ -16,8 +16,8 @@ namespace datetime {
16
16
  #define LOG_DATETIME_DATETIME(prefix, type, obj) \
17
17
  if ((obj) != nullptr) { \
18
18
  ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
19
- if (!(obj)->get_icon().empty()) { \
20
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
19
+ if (!(obj)->get_icon_ref().empty()) { \
20
+ ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
21
21
  } \
22
22
  }
23
23
 
@@ -16,8 +16,8 @@ namespace datetime {
16
16
  #define LOG_DATETIME_TIME(prefix, type, obj) \
17
17
  if ((obj) != nullptr) { \
18
18
  ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
19
- if (!(obj)->get_icon().empty()) { \
20
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
19
+ if (!(obj)->get_icon_ref().empty()) { \
20
+ ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
21
21
  } \
22
22
  }
23
23
 
@@ -52,7 +52,7 @@ void DebugComponent::on_shutdown() {
52
52
  char buffer[REBOOT_MAX_LEN]{};
53
53
  auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name()));
54
54
  if (component != nullptr) {
55
- strncpy(buffer, component->get_component_source(), REBOOT_MAX_LEN - 1);
55
+ strncpy(buffer, LOG_STR_ARG(component->get_component_log_str()), REBOOT_MAX_LEN - 1);
56
56
  buffer[REBOOT_MAX_LEN - 1] = '\0';
57
57
  }
58
58
  ESP_LOGD(TAG, "Storing reboot source: %s", buffer);
@@ -15,7 +15,7 @@ from esphome.const import (
15
15
  CONF_UPDATE_INTERVAL,
16
16
  SCHEDULER_DONT_RUN,
17
17
  )
18
- from esphome.core import coroutine_with_priority
18
+ from esphome.core import CoroPriority, coroutine_with_priority
19
19
 
20
20
  IS_PLATFORM_COMPONENT = True
21
21
 
@@ -176,7 +176,7 @@ async def display_page_show_to_code(config, action_id, template_arg, args):
176
176
  DisplayPageShowNextAction,
177
177
  maybe_simple_id(
178
178
  {
179
- cv.Required(CONF_ID): cv.templatable(cv.use_id(Display)),
179
+ cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)),
180
180
  }
181
181
  ),
182
182
  )
@@ -190,7 +190,7 @@ async def display_page_show_next_to_code(config, action_id, template_arg, args):
190
190
  DisplayPageShowPrevAction,
191
191
  maybe_simple_id(
192
192
  {
193
- cv.Required(CONF_ID): cv.templatable(cv.use_id(Display)),
193
+ cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)),
194
194
  }
195
195
  ),
196
196
  )
@@ -218,7 +218,7 @@ async def display_is_displaying_page_to_code(config, condition_id, template_arg,
218
218
  return var
219
219
 
220
220
 
221
- @coroutine_with_priority(100.0)
221
+ @coroutine_with_priority(CoroPriority.CORE)
222
222
  async def to_code(config):
223
223
  cg.add_global(display_ns.using)
224
224
  cg.add_define("USE_DISPLAY")
@@ -41,7 +41,7 @@ void DutyTimeSensor::setup() {
41
41
  uint32_t seconds = 0;
42
42
 
43
43
  if (this->restore_) {
44
- this->pref_ = global_preferences->make_preference<uint32_t>(this->get_object_id_hash());
44
+ this->pref_ = global_preferences->make_preference<uint32_t>(this->get_preference_hash());
45
45
  this->pref_.load(&seconds);
46
46
  }
47
47
 
@@ -859,11 +859,6 @@ async def to_code(config):
859
859
 
860
860
  cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
861
861
 
862
- # platformio/toolchain-esp32ulp does not support linux_aarch64 yet and has not been updated for over 2 years
863
- # This is espressif's own published version which is more up to date.
864
- cg.add_platformio_option(
865
- "platform_packages", ["espressif/toolchain-esp32ulp@2.35.0-20220830"]
866
- )
867
862
  add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True)
868
863
  add_idf_sdkconfig_option(
869
864
  f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True
@@ -54,13 +54,13 @@ struct ISRPinArg {
54
54
 
55
55
  ISRInternalGPIOPin ESP32InternalGPIOPin::to_isr() const {
56
56
  auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
57
- arg->pin = this->pin_;
57
+ arg->pin = this->get_pin_num();
58
58
  arg->flags = gpio::FLAG_NONE;
59
- arg->inverted = inverted_;
59
+ arg->inverted = this->pin_flags_.inverted;
60
60
  #if defined(USE_ESP32_VARIANT_ESP32)
61
- arg->use_rtc = rtc_gpio_is_valid_gpio(this->pin_);
61
+ arg->use_rtc = rtc_gpio_is_valid_gpio(this->get_pin_num());
62
62
  if (arg->use_rtc)
63
- arg->rtc_pin = rtc_io_number_get(this->pin_);
63
+ arg->rtc_pin = rtc_io_number_get(this->get_pin_num());
64
64
  #endif
65
65
  return ISRInternalGPIOPin((void *) arg);
66
66
  }
@@ -69,23 +69,23 @@ void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpi
69
69
  gpio_int_type_t idf_type = GPIO_INTR_ANYEDGE;
70
70
  switch (type) {
71
71
  case gpio::INTERRUPT_RISING_EDGE:
72
- idf_type = inverted_ ? GPIO_INTR_NEGEDGE : GPIO_INTR_POSEDGE;
72
+ idf_type = this->pin_flags_.inverted ? GPIO_INTR_NEGEDGE : GPIO_INTR_POSEDGE;
73
73
  break;
74
74
  case gpio::INTERRUPT_FALLING_EDGE:
75
- idf_type = inverted_ ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE;
75
+ idf_type = this->pin_flags_.inverted ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE;
76
76
  break;
77
77
  case gpio::INTERRUPT_ANY_EDGE:
78
78
  idf_type = GPIO_INTR_ANYEDGE;
79
79
  break;
80
80
  case gpio::INTERRUPT_LOW_LEVEL:
81
- idf_type = inverted_ ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL;
81
+ idf_type = this->pin_flags_.inverted ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL;
82
82
  break;
83
83
  case gpio::INTERRUPT_HIGH_LEVEL:
84
- idf_type = inverted_ ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL;
84
+ idf_type = this->pin_flags_.inverted ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL;
85
85
  break;
86
86
  }
87
- gpio_set_intr_type(pin_, idf_type);
88
- gpio_intr_enable(pin_);
87
+ gpio_set_intr_type(this->get_pin_num(), idf_type);
88
+ gpio_intr_enable(this->get_pin_num());
89
89
  if (!isr_service_installed) {
90
90
  auto res = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
91
91
  if (res != ESP_OK) {
@@ -94,31 +94,31 @@ void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpi
94
94
  }
95
95
  isr_service_installed = true;
96
96
  }
97
- gpio_isr_handler_add(pin_, func, arg);
97
+ gpio_isr_handler_add(this->get_pin_num(), func, arg);
98
98
  }
99
99
 
100
100
  std::string ESP32InternalGPIOPin::dump_summary() const {
101
101
  char buffer[32];
102
- snprintf(buffer, sizeof(buffer), "GPIO%" PRIu32, static_cast<uint32_t>(pin_));
102
+ snprintf(buffer, sizeof(buffer), "GPIO%" PRIu32, static_cast<uint32_t>(this->pin_));
103
103
  return buffer;
104
104
  }
105
105
 
106
106
  void ESP32InternalGPIOPin::setup() {
107
107
  gpio_config_t conf{};
108
- conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(pin_);
109
- conf.mode = flags_to_mode(flags_);
110
- conf.pull_up_en = flags_ & gpio::FLAG_PULLUP ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
111
- conf.pull_down_en = flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
108
+ conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(this->pin_);
109
+ conf.mode = flags_to_mode(this->flags_);
110
+ conf.pull_up_en = this->flags_ & gpio::FLAG_PULLUP ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
111
+ conf.pull_down_en = this->flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
112
112
  conf.intr_type = GPIO_INTR_DISABLE;
113
113
  gpio_config(&conf);
114
- if (flags_ & gpio::FLAG_OUTPUT) {
115
- gpio_set_drive_capability(pin_, drive_strength_);
114
+ if (this->flags_ & gpio::FLAG_OUTPUT) {
115
+ gpio_set_drive_capability(this->get_pin_num(), this->get_drive_strength());
116
116
  }
117
117
  }
118
118
 
119
119
  void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
120
120
  // can't call gpio_config here because that logs in esp-idf which may cause issues
121
- gpio_set_direction(pin_, flags_to_mode(flags));
121
+ gpio_set_direction(this->get_pin_num(), flags_to_mode(flags));
122
122
  gpio_pull_mode_t pull_mode = GPIO_FLOATING;
123
123
  if ((flags & gpio::FLAG_PULLUP) && (flags & gpio::FLAG_PULLDOWN)) {
124
124
  pull_mode = GPIO_PULLUP_PULLDOWN;
@@ -127,12 +127,16 @@ void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
127
127
  } else if (flags & gpio::FLAG_PULLDOWN) {
128
128
  pull_mode = GPIO_PULLDOWN_ONLY;
129
129
  }
130
- gpio_set_pull_mode(pin_, pull_mode);
130
+ gpio_set_pull_mode(this->get_pin_num(), pull_mode);
131
131
  }
132
132
 
133
- bool ESP32InternalGPIOPin::digital_read() { return bool(gpio_get_level(pin_)) != inverted_; }
134
- void ESP32InternalGPIOPin::digital_write(bool value) { gpio_set_level(pin_, value != inverted_ ? 1 : 0); }
135
- void ESP32InternalGPIOPin::detach_interrupt() const { gpio_intr_disable(pin_); }
133
+ bool ESP32InternalGPIOPin::digital_read() {
134
+ return bool(gpio_get_level(this->get_pin_num())) != this->pin_flags_.inverted;
135
+ }
136
+ void ESP32InternalGPIOPin::digital_write(bool value) {
137
+ gpio_set_level(this->get_pin_num(), value != this->pin_flags_.inverted ? 1 : 0);
138
+ }
139
+ void ESP32InternalGPIOPin::detach_interrupt() const { gpio_intr_disable(this->get_pin_num()); }
136
140
 
137
141
  } // namespace esp32
138
142
 
@@ -7,12 +7,18 @@
7
7
  namespace esphome {
8
8
  namespace esp32 {
9
9
 
10
+ // Static assertions to ensure our bit-packed fields can hold the enum values
11
+ static_assert(GPIO_NUM_MAX <= 256, "gpio_num_t has too many values for uint8_t");
12
+ static_assert(GPIO_DRIVE_CAP_MAX <= 4, "gpio_drive_cap_t has too many values for 2-bit field");
13
+
10
14
  class ESP32InternalGPIOPin : public InternalGPIOPin {
11
15
  public:
12
- void set_pin(gpio_num_t pin) { pin_ = pin; }
13
- void set_inverted(bool inverted) { inverted_ = inverted; }
14
- void set_drive_strength(gpio_drive_cap_t drive_strength) { drive_strength_ = drive_strength; }
15
- void set_flags(gpio::Flags flags) { flags_ = flags; }
16
+ void set_pin(gpio_num_t pin) { this->pin_ = static_cast<uint8_t>(pin); }
17
+ void set_inverted(bool inverted) { this->pin_flags_.inverted = inverted; }
18
+ void set_drive_strength(gpio_drive_cap_t drive_strength) {
19
+ this->pin_flags_.drive_strength = static_cast<uint8_t>(drive_strength);
20
+ }
21
+ void set_flags(gpio::Flags flags) { this->flags_ = flags; }
16
22
 
17
23
  void setup() override;
18
24
  void pin_mode(gpio::Flags flags) override;
@@ -21,17 +27,26 @@ class ESP32InternalGPIOPin : public InternalGPIOPin {
21
27
  std::string dump_summary() const override;
22
28
  void detach_interrupt() const override;
23
29
  ISRInternalGPIOPin to_isr() const override;
24
- uint8_t get_pin() const override { return (uint8_t) pin_; }
25
- gpio::Flags get_flags() const override { return flags_; }
26
- bool is_inverted() const override { return inverted_; }
30
+ uint8_t get_pin() const override { return this->pin_; }
31
+ gpio::Flags get_flags() const override { return this->flags_; }
32
+ bool is_inverted() const override { return this->pin_flags_.inverted; }
33
+ gpio_num_t get_pin_num() const { return static_cast<gpio_num_t>(this->pin_); }
34
+ gpio_drive_cap_t get_drive_strength() const { return static_cast<gpio_drive_cap_t>(this->pin_flags_.drive_strength); }
27
35
 
28
36
  protected:
29
37
  void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
30
38
 
31
- gpio_num_t pin_;
32
- gpio_drive_cap_t drive_strength_;
33
- gpio::Flags flags_;
34
- bool inverted_;
39
+ // Memory layout: 8 bytes total on 32-bit systems
40
+ // - 3 bytes for members below
41
+ // - 1 byte padding for alignment
42
+ // - 4 bytes for vtable pointer
43
+ uint8_t pin_; // GPIO pin number (0-255, actual max ~54 on ESP32)
44
+ gpio::Flags flags_; // GPIO flags (1 byte)
45
+ struct PinFlags {
46
+ uint8_t inverted : 1; // Invert pin logic (1 bit)
47
+ uint8_t drive_strength : 2; // Drive strength 0-3 (2 bits)
48
+ uint8_t reserved : 5; // Reserved for future use (5 bits)
49
+ } pin_flags_; // Total: 1 byte
35
50
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
36
51
  static bool isr_service_installed;
37
52
  };
@@ -8,6 +8,7 @@
8
8
  #include <cinttypes>
9
9
  #include <vector>
10
10
  #include <string>
11
+ #include <memory>
11
12
 
12
13
  namespace esphome {
13
14
  namespace esp32 {
@@ -156,20 +157,23 @@ class ESP32Preferences : public ESPPreferences {
156
157
  return failed == 0;
157
158
  }
158
159
  bool is_changed(const uint32_t nvs_handle, const NVSData &to_save) {
159
- NVSData stored_data{};
160
160
  size_t actual_len;
161
161
  esp_err_t err = nvs_get_blob(nvs_handle, to_save.key.c_str(), nullptr, &actual_len);
162
162
  if (err != 0) {
163
163
  ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", to_save.key.c_str(), esp_err_to_name(err));
164
164
  return true;
165
165
  }
166
- stored_data.data.resize(actual_len);
167
- err = nvs_get_blob(nvs_handle, to_save.key.c_str(), stored_data.data.data(), &actual_len);
166
+ // Check size first before allocating memory
167
+ if (actual_len != to_save.data.size()) {
168
+ return true;
169
+ }
170
+ auto stored_data = std::make_unique<uint8_t[]>(actual_len);
171
+ err = nvs_get_blob(nvs_handle, to_save.key.c_str(), stored_data.get(), &actual_len);
168
172
  if (err != 0) {
169
173
  ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", to_save.key.c_str(), esp_err_to_name(err));
170
174
  return true;
171
175
  }
172
- return to_save.data != stored_data.data;
176
+ return memcmp(to_save.data.data(), stored_data.get(), to_save.data.size()) != 0;
173
177
  }
174
178
 
175
179
  bool reset() override {
@@ -5,9 +5,14 @@ from esphome import automation
5
5
  import esphome.codegen as cg
6
6
  from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
7
7
  import esphome.config_validation as cv
8
- from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ESPHOME, CONF_ID, CONF_NAME
8
+ from esphome.const import (
9
+ CONF_ENABLE_ON_BOOT,
10
+ CONF_ESPHOME,
11
+ CONF_ID,
12
+ CONF_NAME,
13
+ CONF_NAME_ADD_MAC_SUFFIX,
14
+ )
9
15
  from esphome.core import CORE, TimePeriod
10
- from esphome.core.config import CONF_NAME_ADD_MAC_SUFFIX
11
16
  import esphome.final_validate as fv
12
17
 
13
18
  DEPENDENCIES = ["esp32"]
@@ -7,6 +7,7 @@
7
7
  #include <cstdio>
8
8
  #include <cinttypes>
9
9
  #include "esphome/core/log.h"
10
+ #include "esphome/core/helpers.h"
10
11
 
11
12
  namespace esphome::esp32_ble {
12
13
 
@@ -169,22 +170,42 @@ bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const {
169
170
  }
170
171
  esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; }
171
172
  std::string ESPBTUUID::to_string() const {
173
+ char buf[40]; // Enough for 128-bit UUID with dashes
174
+ char *pos = buf;
175
+
172
176
  switch (this->uuid_.len) {
173
177
  case ESP_UUID_LEN_16:
174
- return str_snprintf("0x%02X%02X", 6, this->uuid_.uuid.uuid16 >> 8, this->uuid_.uuid.uuid16 & 0xff);
178
+ *pos++ = '0';
179
+ *pos++ = 'x';
180
+ *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 >> 12);
181
+ *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 8) & 0x0F);
182
+ *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 4) & 0x0F);
183
+ *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 & 0x0F);
184
+ *pos = '\0';
185
+ return std::string(buf);
186
+
175
187
  case ESP_UUID_LEN_32:
176
- return str_snprintf("0x%02" PRIX32 "%02" PRIX32 "%02" PRIX32 "%02" PRIX32, 10, (this->uuid_.uuid.uuid32 >> 24),
177
- (this->uuid_.uuid.uuid32 >> 16 & 0xff), (this->uuid_.uuid.uuid32 >> 8 & 0xff),
178
- this->uuid_.uuid.uuid32 & 0xff);
188
+ *pos++ = '0';
189
+ *pos++ = 'x';
190
+ for (int shift = 28; shift >= 0; shift -= 4) {
191
+ *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid32 >> shift) & 0x0F);
192
+ }
193
+ *pos = '\0';
194
+ return std::string(buf);
195
+
179
196
  default:
180
197
  case ESP_UUID_LEN_128:
181
- std::string buf;
198
+ // Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
182
199
  for (int8_t i = 15; i >= 0; i--) {
183
- buf += str_snprintf("%02X", 2, this->uuid_.uuid.uuid128[i]);
184
- if (i == 6 || i == 8 || i == 10 || i == 12)
185
- buf += "-";
200
+ uint8_t byte = this->uuid_.uuid.uuid128[i];
201
+ *pos++ = format_hex_pretty_char(byte >> 4);
202
+ *pos++ = format_hex_pretty_char(byte & 0x0F);
203
+ if (i == 12 || i == 10 || i == 8 || i == 6) {
204
+ *pos++ = '-';
205
+ }
186
206
  }
187
- return buf;
207
+ *pos = '\0';
208
+ return std::string(buf);
188
209
  }
189
210
  return "";
190
211
  }