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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. esphome/__main__.py +36 -42
  2. esphome/components/absolute_humidity/absolute_humidity.cpp +3 -5
  3. esphome/components/adc/adc_sensor_esp32.cpp +29 -6
  4. esphome/components/ags10/ags10.cpp +3 -18
  5. esphome/components/ags10/ags10.h +2 -12
  6. esphome/components/aht10/aht10.cpp +3 -3
  7. esphome/components/airthings_ble/__init__.py +2 -2
  8. esphome/components/alarm_control_panel/__init__.py +2 -2
  9. esphome/components/am2315c/am2315c.cpp +1 -17
  10. esphome/components/am2315c/am2315c.h +2 -3
  11. esphome/components/api/__init__.py +2 -2
  12. esphome/components/api/api_connection.cpp +34 -23
  13. esphome/components/api/api_connection.h +20 -39
  14. esphome/components/api/api_frame_helper.cpp +25 -25
  15. esphome/components/api/api_frame_helper.h +3 -3
  16. esphome/components/api/api_frame_helper_noise.cpp +75 -40
  17. esphome/components/api/api_frame_helper_noise.h +3 -7
  18. esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
  19. esphome/components/api/api_frame_helper_plaintext.h +1 -4
  20. esphome/components/api/api_pb2.cpp +20 -2
  21. esphome/components/api/api_pb2.h +146 -141
  22. esphome/components/api/api_pb2_dump.cpp +12 -1
  23. esphome/components/api/proto.cpp +33 -37
  24. esphome/components/async_tcp/__init__.py +2 -2
  25. esphome/components/atm90e26/sensor.py +2 -0
  26. esphome/components/atm90e32/sensor.py +4 -2
  27. esphome/components/audio_adc/__init__.py +2 -2
  28. esphome/components/audio_dac/__init__.py +2 -2
  29. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
  30. esphome/components/bedjet/bedjet_hub.cpp +1 -1
  31. esphome/components/binary_sensor/__init__.py +2 -2
  32. esphome/components/binary_sensor/binary_sensor.cpp +13 -0
  33. esphome/components/binary_sensor/binary_sensor.h +4 -7
  34. esphome/components/bl0940/__init__.py +6 -1
  35. esphome/components/bl0940/bl0940.cpp +178 -41
  36. esphome/components/bl0940/bl0940.h +121 -76
  37. esphome/components/bl0940/button/__init__.py +27 -0
  38. esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
  39. esphome/components/bl0940/button/calibration_reset_button.h +19 -0
  40. esphome/components/bl0940/number/__init__.py +94 -0
  41. esphome/components/bl0940/number/calibration_number.cpp +29 -0
  42. esphome/components/bl0940/number/calibration_number.h +26 -0
  43. esphome/components/bl0940/sensor.py +151 -2
  44. esphome/components/bl0942/bl0942.cpp +1 -1
  45. esphome/components/ble_client/output/__init__.py +4 -4
  46. esphome/components/bluetooth_proxy/__init__.py +1 -1
  47. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
  48. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
  49. esphome/components/bluetooth_proxy/bluetooth_proxy.h +3 -2
  50. esphome/components/button/__init__.py +2 -2
  51. esphome/components/button/button.cpp +13 -0
  52. esphome/components/button/button.h +4 -7
  53. esphome/components/camera/buffer.h +18 -0
  54. esphome/components/camera/buffer_impl.cpp +20 -0
  55. esphome/components/camera/buffer_impl.h +26 -0
  56. esphome/components/camera/camera.h +43 -0
  57. esphome/components/camera/encoder.h +69 -0
  58. esphome/components/camera_encoder/__init__.py +62 -0
  59. esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
  60. esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
  61. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
  62. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
  63. esphome/components/captive_portal/__init__.py +2 -2
  64. esphome/components/captive_portal/captive_portal.cpp +35 -12
  65. esphome/components/captive_portal/captive_portal.h +3 -3
  66. esphome/components/ccs811/ccs811.cpp +3 -3
  67. esphome/components/climate/__init__.py +2 -2
  68. esphome/components/climate/climate.cpp +1 -1
  69. esphome/components/cover/__init__.py +5 -5
  70. esphome/components/cover/cover.cpp +1 -1
  71. esphome/components/cover/cover.h +2 -2
  72. esphome/components/dallas_temp/dallas_temp.cpp +2 -2
  73. esphome/components/datetime/__init__.py +2 -2
  74. esphome/components/datetime/date_entity.h +2 -2
  75. esphome/components/datetime/datetime_entity.h +2 -2
  76. esphome/components/datetime/time_entity.h +2 -2
  77. esphome/components/debug/debug_esp32.cpp +1 -1
  78. esphome/components/display/__init__.py +4 -4
  79. esphome/components/duty_time/duty_time_sensor.cpp +1 -1
  80. esphome/components/esp32/__init__.py +0 -5
  81. esphome/components/esp32/gpio.cpp +27 -23
  82. esphome/components/esp32/gpio.h +26 -11
  83. esphome/components/esp32/preferences.cpp +8 -4
  84. esphome/components/esp32_ble/__init__.py +7 -2
  85. esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
  86. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  87. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +9 -44
  88. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
  89. esphome/components/esp8266/__init__.py +2 -2
  90. esphome/components/esp8266/core.cpp +2 -2
  91. esphome/components/esp8266/gpio.py +4 -4
  92. esphome/components/esp8266/preferences.cpp +30 -28
  93. esphome/components/esphome/ota/__init__.py +2 -2
  94. esphome/components/esphome/ota/ota_esphome.cpp +21 -19
  95. esphome/components/esphome/ota/ota_esphome.h +6 -5
  96. esphome/components/ethernet/__init__.py +7 -2
  97. esphome/components/ethernet/ethernet_component.cpp +1 -1
  98. esphome/components/event/__init__.py +2 -2
  99. esphome/components/event/event.h +4 -4
  100. esphome/components/fan/__init__.py +2 -2
  101. esphome/components/fan/fan.cpp +2 -1
  102. esphome/components/gdk101/gdk101.cpp +4 -4
  103. esphome/components/globals/__init__.py +2 -2
  104. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
  105. esphome/components/gpio_expander/cached_gpio.h +36 -16
  106. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
  107. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  108. esphome/components/haier/haier_base.cpp +1 -1
  109. esphome/components/haier/hon_climate.cpp +1 -1
  110. esphome/components/hlw8012/hlw8012.cpp +5 -5
  111. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
  112. esphome/components/host/preferences.h +3 -2
  113. esphome/components/hte501/hte501.cpp +3 -21
  114. esphome/components/hte501/hte501.h +2 -3
  115. esphome/components/http_request/ota/__init__.py +2 -2
  116. esphome/components/i2c/__init__.py +2 -2
  117. esphome/components/i2c/i2c.cpp +13 -9
  118. esphome/components/i2c/i2c_bus.h +36 -6
  119. esphome/components/i2s_audio/__init__.py +8 -2
  120. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  121. esphome/components/i2s_audio/microphone/__init__.py +1 -1
  122. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  123. esphome/components/inkplate/__init__.py +1 -0
  124. esphome/components/inkplate/const.py +105 -0
  125. esphome/components/inkplate/display.py +238 -0
  126. esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
  127. esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
  128. esphome/components/inkplate6/__init__.py +0 -1
  129. esphome/components/inkplate6/display.py +2 -211
  130. esphome/components/integration/integration_sensor.cpp +1 -1
  131. esphome/components/json/__init__.py +2 -2
  132. esphome/components/lc709203f/lc709203f.cpp +4 -17
  133. esphome/components/lc709203f/lc709203f.h +2 -3
  134. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  135. esphome/components/ld2450/ld2450.cpp +1 -1
  136. esphome/components/libretiny/preferences.cpp +13 -5
  137. esphome/components/light/__init__.py +2 -2
  138. esphome/components/light/addressable_light_effect.h +7 -0
  139. esphome/components/light/base_light_effects.h +8 -0
  140. esphome/components/light/light_call.cpp +22 -20
  141. esphome/components/light/light_effect.cpp +36 -0
  142. esphome/components/light/light_effect.h +14 -0
  143. esphome/components/light/light_json_schema.cpp +9 -1
  144. esphome/components/light/light_state.cpp +2 -2
  145. esphome/components/light/light_state.h +38 -0
  146. esphome/components/lock/__init__.py +2 -2
  147. esphome/components/lock/lock.h +2 -2
  148. esphome/components/logger/__init__.py +2 -2
  149. esphome/components/logger/logger.cpp +25 -4
  150. esphome/components/logger/logger.h +1 -1
  151. esphome/components/logger/logger_esp32.cpp +16 -8
  152. esphome/components/logger/logger_esp8266.cpp +11 -3
  153. esphome/components/logger/logger_libretiny.cpp +13 -3
  154. esphome/components/logger/logger_rp2040.cpp +14 -3
  155. esphome/components/logger/logger_zephyr.cpp +15 -4
  156. esphome/components/lvgl/defines.py +1 -0
  157. esphome/components/lvgl/hello_world.py +96 -33
  158. esphome/components/lvgl/number/lvgl_number.h +1 -1
  159. esphome/components/lvgl/select/lvgl_select.h +1 -1
  160. esphome/components/lvgl/widgets/__init__.py +0 -1
  161. esphome/components/lvgl/widgets/spinbox.py +20 -11
  162. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  163. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  164. esphome/components/mapping/__init__.py +13 -5
  165. esphome/components/mapping/mapping.h +69 -0
  166. esphome/components/max17043/max17043.cpp +2 -2
  167. esphome/components/mcp23016/__init__.py +1 -0
  168. esphome/components/mcp23016/mcp23016.cpp +20 -5
  169. esphome/components/mcp23016/mcp23016.h +10 -4
  170. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  171. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  172. esphome/components/mdns/__init__.py +2 -2
  173. esphome/components/mdns/mdns_component.cpp +145 -54
  174. esphome/components/media_player/__init__.py +2 -2
  175. esphome/components/micro_wake_word/__init__.py +2 -2
  176. esphome/components/microphone/__init__.py +2 -2
  177. esphome/components/mipi/__init__.py +77 -33
  178. esphome/components/mipi_rgb/__init__.py +2 -0
  179. esphome/components/mipi_rgb/display.py +321 -0
  180. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  181. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  182. esphome/components/mipi_rgb/models/guition.py +24 -0
  183. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  184. esphome/components/mipi_rgb/models/rpi.py +9 -0
  185. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  186. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  187. esphome/components/mipi_spi/models/jc.py +229 -0
  188. esphome/components/mlx90614/mlx90614.cpp +1 -16
  189. esphome/components/mlx90614/mlx90614.h +0 -1
  190. esphome/components/mqtt/__init__.py +2 -2
  191. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  192. esphome/components/ms5611/ms5611.cpp +7 -6
  193. esphome/components/network/__init__.py +2 -2
  194. esphome/components/nextion/nextion_upload.cpp +4 -1
  195. esphome/components/nrf52/__init__.py +49 -6
  196. esphome/components/nrf52/const.py +1 -0
  197. esphome/components/nrf52/dfu.cpp +51 -0
  198. esphome/components/nrf52/dfu.h +24 -0
  199. esphome/components/ntc/ntc.cpp +1 -1
  200. esphome/components/number/__init__.py +2 -2
  201. esphome/components/number/automation.cpp +1 -1
  202. esphome/components/number/number.cpp +21 -0
  203. esphome/components/number/number.h +4 -13
  204. esphome/components/opentherm/hub.h +6 -6
  205. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  206. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  207. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  208. esphome/components/ota/__init__.py +2 -2
  209. esphome/components/pca6416a/__init__.py +1 -0
  210. esphome/components/pca6416a/pca6416a.cpp +20 -5
  211. esphome/components/pca6416a/pca6416a.h +12 -5
  212. esphome/components/pca9554/__init__.py +2 -1
  213. esphome/components/pca9554/pca9554.cpp +12 -18
  214. esphome/components/pca9554/pca9554.h +10 -9
  215. esphome/components/pcf8574/__init__.py +1 -0
  216. esphome/components/pcf8574/pcf8574.cpp +14 -5
  217. esphome/components/pcf8574/pcf8574.h +13 -6
  218. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  219. esphome/components/pipsolar/__init__.py +3 -3
  220. esphome/components/pipsolar/output/__init__.py +4 -4
  221. esphome/components/pulse_width/pulse_width.cpp +2 -2
  222. esphome/components/qmp6988/qmp6988.cpp +81 -126
  223. esphome/components/qmp6988/qmp6988.h +31 -37
  224. esphome/components/radon_eye_ble/__init__.py +2 -2
  225. esphome/components/remote_base/__init__.py +6 -8
  226. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  227. esphome/components/rp2040/__init__.py +2 -2
  228. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  229. esphome/components/runtime_stats/runtime_stats.h +4 -10
  230. esphome/components/safe_mode/__init__.py +2 -2
  231. esphome/components/safe_mode/safe_mode.cpp +33 -31
  232. esphome/components/script/script.cpp +6 -0
  233. esphome/components/script/script.h +19 -5
  234. esphome/components/sdm_meter/sensor.py +3 -1
  235. esphome/components/select/__init__.py +2 -2
  236. esphome/components/select/select.h +2 -2
  237. esphome/components/sen5x/sen5x.cpp +57 -55
  238. esphome/components/sen5x/sen5x.h +21 -15
  239. esphome/components/sen5x/sensor.py +67 -44
  240. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  241. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  242. esphome/components/sensor/__init__.py +2 -2
  243. esphome/components/sensor/automation.h +1 -1
  244. esphome/components/sensor/sensor.cpp +34 -6
  245. esphome/components/sensor/sensor.h +4 -21
  246. esphome/components/sgp30/sgp30.cpp +34 -35
  247. esphome/components/sgp30/sgp30.h +11 -10
  248. esphome/components/sgp4x/sgp4x.cpp +2 -2
  249. esphome/components/shelly_dimmer/light.py +7 -7
  250. esphome/components/sht4x/sht4x.cpp +1 -1
  251. esphome/components/sntp/sntp_component.cpp +36 -9
  252. esphome/components/sntp/sntp_component.h +7 -0
  253. esphome/components/sound_level/sound_level.cpp +1 -1
  254. esphome/components/speaker/__init__.py +2 -2
  255. esphome/components/speaker/media_player/__init__.py +2 -2
  256. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  257. esphome/components/spi/__init__.py +2 -2
  258. esphome/components/sprinkler/sprinkler.cpp +1 -1
  259. esphome/components/sps30/sps30.cpp +18 -23
  260. esphome/components/sps30/sps30.h +3 -3
  261. esphome/components/status_led/__init__.py +2 -2
  262. esphome/components/stepper/__init__.py +2 -2
  263. esphome/components/switch/__init__.py +2 -2
  264. esphome/components/switch/switch.cpp +5 -5
  265. esphome/components/sx1509/__init__.py +1 -1
  266. esphome/components/sx1509/sx1509.cpp +12 -7
  267. esphome/components/sx1509/sx1509.h +11 -4
  268. esphome/components/tca9555/tca9555.cpp +5 -5
  269. esphome/components/tee501/tee501.cpp +2 -21
  270. esphome/components/tee501/tee501.h +2 -4
  271. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  272. esphome/components/template/datetime/template_date.cpp +1 -1
  273. esphome/components/template/datetime/template_datetime.cpp +2 -2
  274. esphome/components/template/datetime/template_time.cpp +1 -1
  275. esphome/components/template/number/template_number.cpp +1 -1
  276. esphome/components/template/select/template_select.cpp +1 -1
  277. esphome/components/template/text/template_text.cpp +1 -1
  278. esphome/components/text/__init__.py +2 -2
  279. esphome/components/text/text.h +2 -2
  280. esphome/components/text_sensor/__init__.py +2 -2
  281. esphome/components/text_sensor/text_sensor.h +4 -4
  282. esphome/components/thermostat/climate.py +11 -7
  283. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  284. esphome/components/thermostat/thermostat_climate.h +52 -41
  285. esphome/components/time/__init__.py +2 -2
  286. esphome/components/tmp1075/tmp1075.cpp +1 -1
  287. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  288. esphome/components/touchscreen/__init__.py +2 -2
  289. esphome/components/tuya/number/tuya_number.cpp +1 -1
  290. esphome/components/udp/udp_component.cpp +3 -3
  291. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  292. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  293. esphome/components/update/__init__.py +2 -2
  294. esphome/components/usb_uart/usb_uart.cpp +1 -1
  295. esphome/components/valve/__init__.py +5 -5
  296. esphome/components/valve/valve.cpp +1 -1
  297. esphome/components/valve/valve.h +2 -2
  298. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  299. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  300. esphome/components/web_server/__init__.py +2 -2
  301. esphome/components/web_server/ota/__init__.py +2 -2
  302. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  303. esphome/components/web_server/web_server.cpp +58 -12
  304. esphome/components/web_server_base/__init__.py +2 -2
  305. esphome/components/wifi/__init__.py +5 -5
  306. esphome/components/wifi/wifi_component.cpp +3 -3
  307. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  308. esphome/config_validation.py +2 -2
  309. esphome/const.py +2 -1
  310. esphome/core/__init__.py +1 -0
  311. esphome/core/application.cpp +89 -51
  312. esphome/core/application.h +1 -0
  313. esphome/core/component.cpp +41 -19
  314. esphome/core/component.h +17 -13
  315. esphome/core/config.py +7 -7
  316. esphome/core/defines.h +4 -0
  317. esphome/core/entity_base.cpp +22 -8
  318. esphome/core/entity_base.h +43 -0
  319. esphome/core/helpers.cpp +26 -13
  320. esphome/core/helpers.h +4 -3
  321. esphome/core/ring_buffer.cpp +6 -2
  322. esphome/core/ring_buffer.h +2 -1
  323. esphome/core/scheduler.cpp +175 -94
  324. esphome/core/scheduler.h +66 -35
  325. esphome/core/time.cpp +6 -20
  326. esphome/coroutine.py +80 -3
  327. esphome/cpp_generator.py +13 -0
  328. esphome/cpp_helpers.py +2 -2
  329. esphome/dashboard/web_server.py +67 -10
  330. esphome/espota2.py +13 -6
  331. esphome/helpers.py +68 -83
  332. esphome/resolver.py +67 -0
  333. esphome/util.py +9 -6
  334. esphome/wizard.py +39 -26
  335. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/METADATA +9 -9
  336. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/RECORD +344 -313
  337. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  338. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  339. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  340. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  341. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/WHEEL +0 -0
  342. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/entry_points.txt +0 -0
  343. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/licenses/LICENSE +0 -0
  344. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/top_level.txt +0 -0
@@ -6,24 +6,25 @@
6
6
  #include "esphome/components/climate/climate.h"
7
7
  #include "esphome/components/sensor/sensor.h"
8
8
 
9
+ #include <array>
9
10
  #include <cinttypes>
10
11
  #include <map>
11
- #include <vector>
12
12
 
13
13
  namespace esphome {
14
14
  namespace thermostat {
15
15
 
16
16
  enum ThermostatClimateTimerIndex : uint8_t {
17
- TIMER_COOLING_MAX_RUN_TIME = 0,
18
- TIMER_COOLING_OFF = 1,
19
- TIMER_COOLING_ON = 2,
20
- TIMER_FAN_MODE = 3,
21
- TIMER_FANNING_OFF = 4,
22
- TIMER_FANNING_ON = 5,
23
- TIMER_HEATING_MAX_RUN_TIME = 6,
24
- TIMER_HEATING_OFF = 7,
25
- TIMER_HEATING_ON = 8,
26
- TIMER_IDLE_ON = 9,
17
+ THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME = 0,
18
+ THERMOSTAT_TIMER_COOLING_OFF = 1,
19
+ THERMOSTAT_TIMER_COOLING_ON = 2,
20
+ THERMOSTAT_TIMER_FAN_MODE = 3,
21
+ THERMOSTAT_TIMER_FANNING_OFF = 4,
22
+ THERMOSTAT_TIMER_FANNING_ON = 5,
23
+ THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME = 6,
24
+ THERMOSTAT_TIMER_HEATING_OFF = 7,
25
+ THERMOSTAT_TIMER_HEATING_ON = 8,
26
+ THERMOSTAT_TIMER_IDLE_ON = 9,
27
+ THERMOSTAT_TIMER_COUNT = 10,
27
28
  };
28
29
 
29
30
  enum OnBootRestoreFrom : uint8_t {
@@ -131,6 +132,7 @@ class ThermostatClimate : public climate::Climate, public Component {
131
132
  Trigger<> *get_dry_mode_trigger() const;
132
133
  Trigger<> *get_fan_only_mode_trigger() const;
133
134
  Trigger<> *get_heat_mode_trigger() const;
135
+ Trigger<> *get_heat_cool_mode_trigger() const;
134
136
  Trigger<> *get_off_mode_trigger() const;
135
137
  Trigger<> *get_fan_mode_on_trigger() const;
136
138
  Trigger<> *get_fan_mode_off_trigger() const;
@@ -163,9 +165,10 @@ class ThermostatClimate : public climate::Climate, public Component {
163
165
  /// Returns the fan mode that is locked in (check fan_mode_change_delayed(), first!)
164
166
  climate::ClimateFanMode locked_fan_mode();
165
167
  /// Set point and hysteresis validation
166
- bool hysteresis_valid(); // returns true if valid
168
+ bool hysteresis_valid(); // returns true if valid
169
+ bool limit_setpoints_for_heat_cool(); // returns true if set points should be further limited within visual range
167
170
  void validate_target_temperature();
168
- void validate_target_temperatures();
171
+ void validate_target_temperatures(bool pin_target_temperature_high);
169
172
  void validate_target_temperature_low();
170
173
  void validate_target_temperature_high();
171
174
 
@@ -241,12 +244,28 @@ class ThermostatClimate : public climate::Climate, public Component {
241
244
  bool supplemental_cooling_required_();
242
245
  bool supplemental_heating_required_();
243
246
 
244
- void dump_preset_config_(const char *preset_name, const ThermostatClimateTargetTempConfig &config,
245
- bool is_default_preset);
247
+ void dump_preset_config_(const char *preset_name, const ThermostatClimateTargetTempConfig &config);
246
248
 
247
249
  /// Minimum allowable duration in seconds for action timers
248
250
  const uint8_t min_timer_duration_{1};
249
251
 
252
+ /// Store previously-known states
253
+ ///
254
+ /// These are used to determine when a trigger/action needs to be called
255
+ climate::ClimateFanMode prev_fan_mode_{climate::CLIMATE_FAN_ON};
256
+ climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF};
257
+ climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF};
258
+
259
+ /// The current supplemental action
260
+ climate::ClimateAction supplemental_action_{climate::CLIMATE_ACTION_OFF};
261
+
262
+ /// Default standard preset to use on start up
263
+ climate::ClimatePreset default_preset_{};
264
+
265
+ /// If set to DEFAULT_PRESET then the default preset is always used. When MEMORY prior
266
+ /// state will attempt to be restored if possible
267
+ OnBootRestoreFrom on_boot_restore_from_{OnBootRestoreFrom::MEMORY};
268
+
250
269
  /// Whether the controller supports auto/cooling/drying/fanning/heating.
251
270
  ///
252
271
  /// A false value for any given attribute means that the controller has no such action
@@ -362,9 +381,15 @@ class ThermostatClimate : public climate::Climate, public Component {
362
381
  Trigger<> *supplemental_heat_action_trigger_{nullptr};
363
382
  Trigger<> *heat_mode_trigger_{nullptr};
364
383
 
384
+ /// The trigger to call when the controller should switch to heat/cool mode.
385
+ ///
386
+ /// In heat/cool mode, the controller will enable heating/cooling as necessary and switch
387
+ /// to idle when the temperature is within the thresholds/set points.
388
+ Trigger<> *heat_cool_mode_trigger_{nullptr};
389
+
365
390
  /// The trigger to call when the controller should switch to auto mode.
366
391
  ///
367
- /// In auto mode, the controller will enable heating/cooling as necessary and switch
392
+ /// In auto mode, the controller will enable heating/cooling as supported/necessary and switch
368
393
  /// to idle when the temperature is within the thresholds/set points.
369
394
  Trigger<> *auto_mode_trigger_{nullptr};
370
395
 
@@ -438,35 +463,21 @@ class ThermostatClimate : public climate::Climate, public Component {
438
463
  Trigger<> *prev_mode_trigger_{nullptr};
439
464
  Trigger<> *prev_swing_mode_trigger_{nullptr};
440
465
 
441
- /// If set to DEFAULT_PRESET then the default preset is always used. When MEMORY prior
442
- /// state will attempt to be restored if possible
443
- OnBootRestoreFrom on_boot_restore_from_{OnBootRestoreFrom::MEMORY};
444
-
445
- /// Store previously-known states
446
- ///
447
- /// These are used to determine when a trigger/action needs to be called
448
- climate::ClimateAction supplemental_action_{climate::CLIMATE_ACTION_OFF};
449
- climate::ClimateFanMode prev_fan_mode_{climate::CLIMATE_FAN_ON};
450
- climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF};
451
- climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF};
452
-
453
- /// Default standard preset to use on start up
454
- climate::ClimatePreset default_preset_{};
455
466
  /// Default custom preset to use on start up
456
467
  std::string default_custom_preset_{};
457
468
 
458
469
  /// Climate action timers
459
- std::vector<ThermostatClimateTimer> timer_{
460
- {false, 0, 0, std::bind(&ThermostatClimate::cooling_max_run_time_timer_callback_, this)},
461
- {false, 0, 0, std::bind(&ThermostatClimate::cooling_off_timer_callback_, this)},
462
- {false, 0, 0, std::bind(&ThermostatClimate::cooling_on_timer_callback_, this)},
463
- {false, 0, 0, std::bind(&ThermostatClimate::fan_mode_timer_callback_, this)},
464
- {false, 0, 0, std::bind(&ThermostatClimate::fanning_off_timer_callback_, this)},
465
- {false, 0, 0, std::bind(&ThermostatClimate::fanning_on_timer_callback_, this)},
466
- {false, 0, 0, std::bind(&ThermostatClimate::heating_max_run_time_timer_callback_, this)},
467
- {false, 0, 0, std::bind(&ThermostatClimate::heating_off_timer_callback_, this)},
468
- {false, 0, 0, std::bind(&ThermostatClimate::heating_on_timer_callback_, this)},
469
- {false, 0, 0, std::bind(&ThermostatClimate::idle_on_timer_callback_, this)},
470
+ std::array<ThermostatClimateTimer, THERMOSTAT_TIMER_COUNT> timer_{
471
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::cooling_max_run_time_timer_callback_, this)),
472
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::cooling_off_timer_callback_, this)),
473
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::cooling_on_timer_callback_, this)),
474
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::fan_mode_timer_callback_, this)),
475
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::fanning_off_timer_callback_, this)),
476
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::fanning_on_timer_callback_, this)),
477
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::heating_max_run_time_timer_callback_, this)),
478
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::heating_off_timer_callback_, this)),
479
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::heating_on_timer_callback_, this)),
480
+ ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::idle_on_timer_callback_, this)),
470
481
  };
471
482
 
472
483
  /// The set of standard preset configurations this thermostat supports (Eg. AWAY, ECO, etc)
@@ -26,7 +26,7 @@ from esphome.const import (
26
26
  CONF_TIMEZONE,
27
27
  CONF_TRIGGER_ID,
28
28
  )
29
- from esphome.core import CORE, coroutine_with_priority
29
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
30
30
 
31
31
  _LOGGER = logging.getLogger(__name__)
32
32
 
@@ -340,7 +340,7 @@ async def register_time(time_var, config):
340
340
  await setup_time_core_(time_var, config)
341
341
 
342
342
 
343
- @coroutine_with_priority(100.0)
343
+ @coroutine_with_priority(CoroPriority.CORE)
344
344
  async def to_code(config):
345
345
  if CORE.using_zephyr:
346
346
  zephyr_add_prj_conf("POSIX_CLOCK", True)
@@ -32,7 +32,7 @@ void TMP1075Sensor::update() {
32
32
  uint16_t regvalue;
33
33
  if (!read_byte_16(REG_TEMP, &regvalue)) {
34
34
  ESP_LOGW(TAG, "'%s' - unable to read temperature register", this->name_.c_str());
35
- this->status_set_warning("can't read");
35
+ this->status_set_warning(LOG_STR("can't read"));
36
36
  return;
37
37
  }
38
38
  this->status_clear_warning();
@@ -10,7 +10,7 @@ void TotalDailyEnergy::setup() {
10
10
  float initial_value = 0;
11
11
 
12
12
  if (this->restore_) {
13
- this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
13
+ this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
14
14
  this->pref_.load(&initial_value);
15
15
  }
16
16
  this->publish_state_and_save(initial_value);
@@ -13,7 +13,7 @@ from esphome.const import (
13
13
  CONF_SWAP_XY,
14
14
  CONF_TRANSFORM,
15
15
  )
16
- from esphome.core import coroutine_with_priority
16
+ from esphome.core import CoroPriority, coroutine_with_priority
17
17
 
18
18
  CODEOWNERS = ["@jesserockz", "@nielsnl68"]
19
19
  DEPENDENCIES = ["display"]
@@ -152,7 +152,7 @@ async def register_touchscreen(var, config):
152
152
  )
153
153
 
154
154
 
155
- @coroutine_with_priority(100.0)
155
+ @coroutine_with_priority(CoroPriority.CORE)
156
156
  async def to_code(config):
157
157
  cg.add_global(touchscreen_ns.using)
158
158
  cg.add_define("USE_TOUCHSCREEN")
@@ -8,7 +8,7 @@ static const char *const TAG = "tuya.number";
8
8
 
9
9
  void TuyaNumber::setup() {
10
10
  if (this->restore_value_) {
11
- this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
11
+ this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
12
12
  }
13
13
 
14
14
  this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
@@ -28,12 +28,12 @@ void UDPComponent::setup() {
28
28
  int enable = 1;
29
29
  auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
30
30
  if (err != 0) {
31
- this->status_set_warning("Socket unable to set reuseaddr");
31
+ this->status_set_warning(LOG_STR("Socket unable to set reuseaddr"));
32
32
  // we can still continue
33
33
  }
34
34
  err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
35
35
  if (err != 0) {
36
- this->status_set_warning("Socket unable to set broadcast");
36
+ this->status_set_warning(LOG_STR("Socket unable to set broadcast"));
37
37
  }
38
38
  }
39
39
  // create listening socket if we either want to subscribe to providers, or need to listen
@@ -55,7 +55,7 @@ void UDPComponent::setup() {
55
55
  int enable = 1;
56
56
  err = this->listen_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
57
57
  if (err != 0) {
58
- this->status_set_warning("Socket unable to set reuseaddr");
58
+ this->status_set_warning(LOG_STR("Socket unable to set reuseaddr"));
59
59
  // we can still continue
60
60
  }
61
61
  struct sockaddr_in server {};
@@ -104,10 +104,10 @@ void UFireECComponent::write_data_(uint8_t reg, float data) {
104
104
  void UFireECComponent::dump_config() {
105
105
  ESP_LOGCONFIG(TAG, "uFire-EC");
106
106
  LOG_I2C_DEVICE(this)
107
- LOG_UPDATE_INTERVAL(this)
108
- LOG_SENSOR(" ", "EC Sensor", this->ec_sensor_)
109
- LOG_SENSOR(" ", "Temperature Sensor", this->temperature_sensor_)
110
- LOG_SENSOR(" ", "Temperature Sensor external", this->temperature_sensor_external_)
107
+ LOG_UPDATE_INTERVAL(this);
108
+ LOG_SENSOR(" ", "EC Sensor", this->ec_sensor_);
109
+ LOG_SENSOR(" ", "Temperature Sensor", this->temperature_sensor_);
110
+ LOG_SENSOR(" ", "Temperature Sensor external", this->temperature_sensor_external_);
111
111
  ESP_LOGCONFIG(TAG,
112
112
  " Temperature Compensation: %f\n"
113
113
  " Temperature Coefficient: %f",
@@ -141,10 +141,10 @@ void UFireISEComponent::write_data_(uint8_t reg, float data) {
141
141
  void UFireISEComponent::dump_config() {
142
142
  ESP_LOGCONFIG(TAG, "uFire-ISE");
143
143
  LOG_I2C_DEVICE(this)
144
- LOG_UPDATE_INTERVAL(this)
145
- LOG_SENSOR(" ", "PH Sensor", this->ph_sensor_)
146
- LOG_SENSOR(" ", "Temperature Sensor", this->temperature_sensor_)
147
- LOG_SENSOR(" ", "Temperature Sensor external", this->temperature_sensor_external_)
144
+ LOG_UPDATE_INTERVAL(this);
145
+ LOG_SENSOR(" ", "PH Sensor", this->ph_sensor_);
146
+ LOG_SENSOR(" ", "Temperature Sensor", this->temperature_sensor_);
147
+ LOG_SENSOR(" ", "Temperature Sensor external", this->temperature_sensor_external_);
148
148
  }
149
149
 
150
150
  } // namespace ufire_ise
@@ -14,7 +14,7 @@ from esphome.const import (
14
14
  DEVICE_CLASS_FIRMWARE,
15
15
  ENTITY_CATEGORY_CONFIG,
16
16
  )
17
- from esphome.core import CORE, coroutine_with_priority
17
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
18
18
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
19
19
  from esphome.cpp_generator import MockObjClass
20
20
 
@@ -124,7 +124,7 @@ async def new_update(config):
124
124
  return var
125
125
 
126
126
 
127
- @coroutine_with_priority(100.0)
127
+ @coroutine_with_priority(CoroPriority.CORE)
128
128
  async def to_code(config):
129
129
  cg.add_global(update_ns.using)
130
130
 
@@ -266,7 +266,7 @@ void USBUartTypeCdcAcm::on_connected() {
266
266
  for (auto *channel : this->channels_) {
267
267
  if (i == cdc_devs.size()) {
268
268
  ESP_LOGE(TAG, "No configuration found for channel %d", channel->index_);
269
- this->status_set_warning("No configuration found for channel");
269
+ this->status_set_warning(LOG_STR("No configuration found for channel"));
270
270
  break;
271
271
  }
272
272
  channel->cdc_dev_ = cdc_devs[i++];
@@ -21,7 +21,7 @@ from esphome.const import (
21
21
  DEVICE_CLASS_GAS,
22
22
  DEVICE_CLASS_WATER,
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
 
@@ -202,9 +202,9 @@ async def valve_stop_to_code(config, action_id, template_arg, args):
202
202
 
203
203
 
204
204
  @automation.register_action("valve.toggle", ToggleAction, VALVE_ACTION_SCHEMA)
205
- def valve_toggle_to_code(config, action_id, template_arg, args):
206
- paren = yield cg.get_variable(config[CONF_ID])
207
- yield cg.new_Pvariable(action_id, template_arg, paren)
205
+ async def valve_toggle_to_code(config, action_id, template_arg, args):
206
+ paren = await cg.get_variable(config[CONF_ID])
207
+ return cg.new_Pvariable(action_id, template_arg, paren)
208
208
 
209
209
 
210
210
  VALVE_CONTROL_ACTION_SCHEMA = cv.Schema(
@@ -233,6 +233,6 @@ async def valve_control_to_code(config, action_id, template_arg, args):
233
233
  return var
234
234
 
235
235
 
236
- @coroutine_with_priority(100.0)
236
+ @coroutine_with_priority(CoroPriority.CORE)
237
237
  async def to_code(config):
238
238
  cg.add_global(valve_ns.using)
@@ -155,7 +155,7 @@ void Valve::publish_state(bool save) {
155
155
  }
156
156
  }
157
157
  optional<ValveRestoreState> Valve::restore_state_() {
158
- this->rtc_ = global_preferences->make_preference<ValveRestoreState>(this->get_object_id_hash());
158
+ this->rtc_ = global_preferences->make_preference<ValveRestoreState>(this->get_preference_hash());
159
159
  ValveRestoreState recovered{};
160
160
  if (!this->rtc_.load(&recovered))
161
161
  return {};
@@ -19,8 +19,8 @@ const extern float VALVE_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
 
@@ -74,12 +74,12 @@ void WakeOnLanButton::setup() {
74
74
  int enable = 1;
75
75
  auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
76
76
  if (err != 0) {
77
- this->status_set_warning("Socket unable to set reuseaddr");
77
+ this->status_set_warning(LOG_STR("Socket unable to set reuseaddr"));
78
78
  // we can still continue
79
79
  }
80
80
  err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
81
81
  if (err != 0) {
82
- this->status_set_warning("Socket unable to set broadcast");
82
+ this->status_set_warning(LOG_STR("Socket unable to set broadcast"));
83
83
  }
84
84
  #endif
85
85
  }
@@ -181,7 +181,7 @@ void WaveshareEPaper2P13InV3::dump_config() {
181
181
  LOG_PIN(" Reset Pin: ", this->reset_pin_)
182
182
  LOG_PIN(" DC Pin: ", this->dc_pin_)
183
183
  LOG_PIN(" Busy Pin: ", this->busy_pin_)
184
- LOG_UPDATE_INTERVAL(this)
184
+ LOG_UPDATE_INTERVAL(this);
185
185
  }
186
186
 
187
187
  void WaveshareEPaper2P13InV3::set_full_update_every(uint32_t full_update_every) {
@@ -31,7 +31,7 @@ from esphome.const import (
31
31
  PLATFORM_LN882X,
32
32
  PLATFORM_RTL87XX,
33
33
  )
34
- from esphome.core import CORE, coroutine_with_priority
34
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
35
35
  import esphome.final_validate as fv
36
36
  from esphome.types import ConfigType
37
37
 
@@ -269,7 +269,7 @@ def add_resource_as_progmem(
269
269
  cg.add_global(cg.RawExpression(size_t))
270
270
 
271
271
 
272
- @coroutine_with_priority(40.0)
272
+ @coroutine_with_priority(CoroPriority.WEB)
273
273
  async def to_code(config):
274
274
  paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID])
275
275
 
@@ -3,7 +3,7 @@ from esphome.components.esp32 import add_idf_component
3
3
  from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code
4
4
  import esphome.config_validation as cv
5
5
  from esphome.const import CONF_ID
6
- from esphome.core import CORE, coroutine_with_priority
6
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
7
7
 
8
8
  CODEOWNERS = ["@esphome/core"]
9
9
  DEPENDENCIES = ["network", "web_server_base"]
@@ -22,7 +22,7 @@ CONFIG_SCHEMA = (
22
22
  )
23
23
 
24
24
 
25
- @coroutine_with_priority(52.0)
25
+ @coroutine_with_priority(CoroPriority.COMMUNICATION)
26
26
  async def to_code(config):
27
27
  var = cg.new_Pvariable(config[CONF_ID])
28
28
  await ota_to_code(var, config)
@@ -198,9 +198,20 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
198
198
  void OTARequestHandler::handleRequest(AsyncWebServerRequest *request) {
199
199
  AsyncWebServerResponse *response;
200
200
  // Use the ota_success_ flag to determine the actual result
201
+ #ifdef USE_ESP8266
202
+ static const char UPDATE_SUCCESS[] PROGMEM = "Update Successful!";
203
+ static const char UPDATE_FAILED[] PROGMEM = "Update Failed!";
204
+ static const char TEXT_PLAIN[] PROGMEM = "text/plain";
205
+ static const char CONNECTION_STR[] PROGMEM = "Connection";
206
+ static const char CLOSE_STR[] PROGMEM = "close";
207
+ const char *msg = this->ota_success_ ? UPDATE_SUCCESS : UPDATE_FAILED;
208
+ response = request->beginResponse_P(200, TEXT_PLAIN, msg);
209
+ response->addHeader(CONNECTION_STR, CLOSE_STR);
210
+ #else
201
211
  const char *msg = this->ota_success_ ? "Update Successful!" : "Update Failed!";
202
212
  response = request->beginResponse(200, "text/plain", msg);
203
213
  response->addHeader("Connection", "close");
214
+ #endif
204
215
  request->send(response);
205
216
  }
206
217
 
@@ -507,14 +507,37 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
507
507
  auto detail = get_request_detail(request);
508
508
  std::string data = this->switch_json(obj, obj->state, detail);
509
509
  request->send(200, "application/json", data.c_str());
510
- } else if (match.method_equals("toggle")) {
511
- this->defer([obj]() { obj->toggle(); });
512
- request->send(200);
510
+ return;
511
+ }
512
+
513
+ // Handle action methods with single defer and response
514
+ enum SwitchAction { NONE, TOGGLE, TURN_ON, TURN_OFF };
515
+ SwitchAction action = NONE;
516
+
517
+ if (match.method_equals("toggle")) {
518
+ action = TOGGLE;
513
519
  } else if (match.method_equals("turn_on")) {
514
- this->defer([obj]() { obj->turn_on(); });
515
- request->send(200);
520
+ action = TURN_ON;
516
521
  } else if (match.method_equals("turn_off")) {
517
- this->defer([obj]() { obj->turn_off(); });
522
+ action = TURN_OFF;
523
+ }
524
+
525
+ if (action != NONE) {
526
+ this->defer([obj, action]() {
527
+ switch (action) {
528
+ case TOGGLE:
529
+ obj->toggle();
530
+ break;
531
+ case TURN_ON:
532
+ obj->turn_on();
533
+ break;
534
+ case TURN_OFF:
535
+ obj->turn_off();
536
+ break;
537
+ default:
538
+ break;
539
+ }
540
+ });
518
541
  request->send(200);
519
542
  } else {
520
543
  request->send(404);
@@ -1332,14 +1355,37 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
1332
1355
  auto detail = get_request_detail(request);
1333
1356
  std::string data = this->lock_json(obj, obj->state, detail);
1334
1357
  request->send(200, "application/json", data.c_str());
1335
- } else if (match.method_equals("lock")) {
1336
- this->defer([obj]() { obj->lock(); });
1337
- request->send(200);
1358
+ return;
1359
+ }
1360
+
1361
+ // Handle action methods with single defer and response
1362
+ enum LockAction { NONE, LOCK, UNLOCK, OPEN };
1363
+ LockAction action = NONE;
1364
+
1365
+ if (match.method_equals("lock")) {
1366
+ action = LOCK;
1338
1367
  } else if (match.method_equals("unlock")) {
1339
- this->defer([obj]() { obj->unlock(); });
1340
- request->send(200);
1368
+ action = UNLOCK;
1341
1369
  } else if (match.method_equals("open")) {
1342
- this->defer([obj]() { obj->open(); });
1370
+ action = OPEN;
1371
+ }
1372
+
1373
+ if (action != NONE) {
1374
+ this->defer([obj, action]() {
1375
+ switch (action) {
1376
+ case LOCK:
1377
+ obj->lock();
1378
+ break;
1379
+ case UNLOCK:
1380
+ obj->unlock();
1381
+ break;
1382
+ case OPEN:
1383
+ obj->open();
1384
+ break;
1385
+ default:
1386
+ break;
1387
+ }
1388
+ });
1343
1389
  request->send(200);
1344
1390
  } else {
1345
1391
  request->send(404);
@@ -1,7 +1,7 @@
1
1
  import esphome.codegen as cg
2
2
  import esphome.config_validation as cv
3
3
  from esphome.const import CONF_ID
4
- from esphome.core import CORE, coroutine_with_priority
4
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
5
5
 
6
6
  CODEOWNERS = ["@esphome/core"]
7
7
  DEPENDENCIES = ["network"]
@@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.Schema(
26
26
  )
27
27
 
28
28
 
29
- @coroutine_with_priority(65.0)
29
+ @coroutine_with_priority(CoroPriority.COMMUNICATION)
30
30
  async def to_code(config):
31
31
  var = cg.new_Pvariable(config[CONF_ID])
32
32
  await cg.register_component(var, config)
@@ -44,14 +44,14 @@ from esphome.const import (
44
44
  CONF_USERNAME,
45
45
  PlatformFramework,
46
46
  )
47
- from esphome.core import CORE, HexInt, coroutine_with_priority
47
+ from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority
48
48
  import esphome.final_validate as fv
49
49
 
50
50
  from . import wpa2_eap
51
51
 
52
52
  AUTO_LOAD = ["network"]
53
53
 
54
- NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2]
54
+ NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
55
55
  CONF_SAVE = "save"
56
56
 
57
57
  wifi_ns = cg.esphome_ns.namespace("wifi")
@@ -179,8 +179,8 @@ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend(
179
179
  def validate_variant(_):
180
180
  if CORE.is_esp32:
181
181
  variant = get_esp32_variant()
182
- if variant in NO_WIFI_VARIANTS:
183
- raise cv.Invalid(f"{variant} does not support WiFi")
182
+ if variant in NO_WIFI_VARIANTS and "esp32_hosted" not in fv.full_config.get():
183
+ raise cv.Invalid(f"WiFi requires component esp32_hosted on {variant}")
184
184
 
185
185
 
186
186
  def final_validate(config):
@@ -370,7 +370,7 @@ def wifi_network(config, ap, static_ip):
370
370
  return ap
371
371
 
372
372
 
373
- @coroutine_with_priority(60.0)
373
+ @coroutine_with_priority(CoroPriority.COMMUNICATION)
374
374
  async def to_code(config):
375
375
  var = cg.new_Pvariable(config[CONF_ID])
376
376
  cg.add(var.set_use_address(config[CONF_USE_ADDRESS]))
@@ -148,7 +148,7 @@ void WiFiComponent::loop() {
148
148
 
149
149
  switch (this->state_) {
150
150
  case WIFI_COMPONENT_STATE_COOLDOWN: {
151
- this->status_set_warning("waiting to reconnect");
151
+ this->status_set_warning(LOG_STR("waiting to reconnect"));
152
152
  if (millis() - this->action_started_ > 5000) {
153
153
  if (this->fast_connect_ || this->retry_hidden_) {
154
154
  if (!this->selected_ap_.get_bssid().has_value())
@@ -161,13 +161,13 @@ void WiFiComponent::loop() {
161
161
  break;
162
162
  }
163
163
  case WIFI_COMPONENT_STATE_STA_SCANNING: {
164
- this->status_set_warning("scanning for networks");
164
+ this->status_set_warning(LOG_STR("scanning for networks"));
165
165
  this->check_scanning_finished();
166
166
  break;
167
167
  }
168
168
  case WIFI_COMPONENT_STATE_STA_CONNECTING:
169
169
  case WIFI_COMPONENT_STATE_STA_CONNECTING_2: {
170
- this->status_set_warning("associating to network");
170
+ this->status_set_warning(LOG_STR("associating to network"));
171
171
  this->check_connecting_finished();
172
172
  break;
173
173
  }
@@ -654,12 +654,14 @@ const char *get_disconnect_reason_str(uint8_t reason) {
654
654
  return "Association comeback time too long";
655
655
  case WIFI_REASON_SA_QUERY_TIMEOUT:
656
656
  return "SA query timeout";
657
+ #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 2)
657
658
  case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY:
658
659
  return "No AP found with compatible security";
659
660
  case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD:
660
661
  return "No AP found in auth mode threshold";
661
662
  case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD:
662
663
  return "No AP found in RSSI threshold";
664
+ #endif
663
665
  case WIFI_REASON_UNSPECIFIED:
664
666
  default:
665
667
  return "Unspecified";
@@ -1112,8 +1112,8 @@ voltage = float_with_unit("voltage", "(v|V|volt|Volts)?")
1112
1112
  distance = float_with_unit("distance", "(m)")
1113
1113
  framerate = float_with_unit("framerate", "(FPS|fps|Fps|FpS|Hz)")
1114
1114
  angle = float_with_unit("angle", "(°|deg)", optional_unit=True)
1115
- _temperature_c = float_with_unit("temperature", "(°C|° C|°|C)?")
1116
- _temperature_k = float_with_unit("temperature", "(° K|° K|K)?")
1115
+ _temperature_c = float_with_unit("temperature", "(°C|° C|C)?")
1116
+ _temperature_k = float_with_unit("temperature", "(°K|° K|K)?")
1117
1117
  _temperature_f = float_with_unit("temperature", "(°F|° F|F)?")
1118
1118
  decibel = float_with_unit("decibel", "(dB|dBm|db|dbm)", optional_unit=True)
1119
1119
  pressure = float_with_unit("pressure", "(bar|Bar)", optional_unit=True)