esphome 2025.8.3__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 (345) 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/kmeteriso/kmeteriso.cpp +1 -1
  133. esphome/components/lc709203f/lc709203f.cpp +4 -17
  134. esphome/components/lc709203f/lc709203f.h +2 -3
  135. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  136. esphome/components/ld2450/ld2450.cpp +1 -1
  137. esphome/components/libretiny/preferences.cpp +13 -5
  138. esphome/components/light/__init__.py +2 -2
  139. esphome/components/light/addressable_light_effect.h +7 -0
  140. esphome/components/light/base_light_effects.h +8 -0
  141. esphome/components/light/light_call.cpp +22 -20
  142. esphome/components/light/light_effect.cpp +36 -0
  143. esphome/components/light/light_effect.h +14 -0
  144. esphome/components/light/light_json_schema.cpp +9 -1
  145. esphome/components/light/light_state.cpp +2 -2
  146. esphome/components/light/light_state.h +39 -0
  147. esphome/components/lock/__init__.py +2 -2
  148. esphome/components/lock/lock.h +2 -2
  149. esphome/components/logger/__init__.py +2 -2
  150. esphome/components/logger/logger.cpp +25 -4
  151. esphome/components/logger/logger.h +1 -1
  152. esphome/components/logger/logger_esp32.cpp +16 -8
  153. esphome/components/logger/logger_esp8266.cpp +11 -3
  154. esphome/components/logger/logger_libretiny.cpp +13 -3
  155. esphome/components/logger/logger_rp2040.cpp +14 -3
  156. esphome/components/logger/logger_zephyr.cpp +15 -4
  157. esphome/components/lvgl/defines.py +1 -0
  158. esphome/components/lvgl/hello_world.py +96 -33
  159. esphome/components/lvgl/number/lvgl_number.h +1 -1
  160. esphome/components/lvgl/select/lvgl_select.h +1 -1
  161. esphome/components/lvgl/widgets/__init__.py +0 -1
  162. esphome/components/lvgl/widgets/spinbox.py +20 -11
  163. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  164. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  165. esphome/components/mapping/__init__.py +13 -5
  166. esphome/components/mapping/mapping.h +69 -0
  167. esphome/components/max17043/max17043.cpp +2 -2
  168. esphome/components/mcp23016/__init__.py +1 -0
  169. esphome/components/mcp23016/mcp23016.cpp +20 -5
  170. esphome/components/mcp23016/mcp23016.h +10 -4
  171. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  172. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  173. esphome/components/mdns/__init__.py +2 -2
  174. esphome/components/mdns/mdns_component.cpp +145 -54
  175. esphome/components/media_player/__init__.py +2 -2
  176. esphome/components/micro_wake_word/__init__.py +2 -2
  177. esphome/components/microphone/__init__.py +2 -2
  178. esphome/components/mipi/__init__.py +77 -33
  179. esphome/components/mipi_rgb/__init__.py +2 -0
  180. esphome/components/mipi_rgb/display.py +321 -0
  181. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  182. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  183. esphome/components/mipi_rgb/models/guition.py +24 -0
  184. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  185. esphome/components/mipi_rgb/models/rpi.py +9 -0
  186. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  187. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  188. esphome/components/mipi_spi/models/jc.py +229 -0
  189. esphome/components/mlx90614/mlx90614.cpp +1 -16
  190. esphome/components/mlx90614/mlx90614.h +0 -1
  191. esphome/components/mqtt/__init__.py +2 -2
  192. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  193. esphome/components/ms5611/ms5611.cpp +7 -6
  194. esphome/components/network/__init__.py +2 -2
  195. esphome/components/nextion/nextion_upload.cpp +4 -1
  196. esphome/components/nrf52/__init__.py +49 -6
  197. esphome/components/nrf52/const.py +1 -0
  198. esphome/components/nrf52/dfu.cpp +51 -0
  199. esphome/components/nrf52/dfu.h +24 -0
  200. esphome/components/ntc/ntc.cpp +1 -1
  201. esphome/components/number/__init__.py +2 -2
  202. esphome/components/number/automation.cpp +1 -1
  203. esphome/components/number/number.cpp +21 -0
  204. esphome/components/number/number.h +4 -13
  205. esphome/components/opentherm/hub.h +6 -6
  206. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  207. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  208. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  209. esphome/components/ota/__init__.py +2 -2
  210. esphome/components/pca6416a/__init__.py +1 -0
  211. esphome/components/pca6416a/pca6416a.cpp +20 -5
  212. esphome/components/pca6416a/pca6416a.h +12 -5
  213. esphome/components/pca9554/__init__.py +2 -1
  214. esphome/components/pca9554/pca9554.cpp +12 -18
  215. esphome/components/pca9554/pca9554.h +10 -9
  216. esphome/components/pcf8574/__init__.py +1 -0
  217. esphome/components/pcf8574/pcf8574.cpp +14 -5
  218. esphome/components/pcf8574/pcf8574.h +13 -6
  219. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  220. esphome/components/pipsolar/__init__.py +3 -3
  221. esphome/components/pipsolar/output/__init__.py +4 -4
  222. esphome/components/pulse_width/pulse_width.cpp +2 -2
  223. esphome/components/qmp6988/qmp6988.cpp +81 -126
  224. esphome/components/qmp6988/qmp6988.h +31 -37
  225. esphome/components/radon_eye_ble/__init__.py +2 -2
  226. esphome/components/remote_base/__init__.py +6 -8
  227. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  228. esphome/components/rp2040/__init__.py +2 -2
  229. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  230. esphome/components/runtime_stats/runtime_stats.h +4 -10
  231. esphome/components/safe_mode/__init__.py +2 -2
  232. esphome/components/safe_mode/safe_mode.cpp +33 -31
  233. esphome/components/script/script.cpp +6 -0
  234. esphome/components/script/script.h +19 -5
  235. esphome/components/sdm_meter/sensor.py +3 -1
  236. esphome/components/select/__init__.py +2 -2
  237. esphome/components/select/select.h +2 -2
  238. esphome/components/sen5x/sen5x.cpp +58 -55
  239. esphome/components/sen5x/sen5x.h +21 -15
  240. esphome/components/sen5x/sensor.py +67 -44
  241. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  242. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  243. esphome/components/sensor/__init__.py +2 -2
  244. esphome/components/sensor/automation.h +1 -1
  245. esphome/components/sensor/sensor.cpp +34 -6
  246. esphome/components/sensor/sensor.h +4 -21
  247. esphome/components/sgp30/sgp30.cpp +34 -35
  248. esphome/components/sgp30/sgp30.h +11 -10
  249. esphome/components/sgp4x/sgp4x.cpp +2 -2
  250. esphome/components/shelly_dimmer/light.py +7 -7
  251. esphome/components/sht4x/sht4x.cpp +1 -1
  252. esphome/components/sntp/sntp_component.cpp +36 -9
  253. esphome/components/sntp/sntp_component.h +7 -0
  254. esphome/components/sound_level/sound_level.cpp +1 -1
  255. esphome/components/speaker/__init__.py +2 -2
  256. esphome/components/speaker/media_player/__init__.py +2 -2
  257. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  258. esphome/components/spi/__init__.py +2 -2
  259. esphome/components/sprinkler/sprinkler.cpp +1 -1
  260. esphome/components/sps30/sps30.cpp +18 -23
  261. esphome/components/sps30/sps30.h +3 -3
  262. esphome/components/status_led/__init__.py +2 -2
  263. esphome/components/stepper/__init__.py +2 -2
  264. esphome/components/switch/__init__.py +2 -2
  265. esphome/components/switch/switch.cpp +5 -5
  266. esphome/components/sx1509/__init__.py +1 -1
  267. esphome/components/sx1509/sx1509.cpp +12 -7
  268. esphome/components/sx1509/sx1509.h +11 -4
  269. esphome/components/tca9555/tca9555.cpp +5 -5
  270. esphome/components/tee501/tee501.cpp +2 -21
  271. esphome/components/tee501/tee501.h +2 -4
  272. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  273. esphome/components/template/datetime/template_date.cpp +1 -1
  274. esphome/components/template/datetime/template_datetime.cpp +2 -2
  275. esphome/components/template/datetime/template_time.cpp +1 -1
  276. esphome/components/template/number/template_number.cpp +1 -1
  277. esphome/components/template/select/template_select.cpp +1 -1
  278. esphome/components/template/text/template_text.cpp +1 -1
  279. esphome/components/text/__init__.py +2 -2
  280. esphome/components/text/text.h +2 -2
  281. esphome/components/text_sensor/__init__.py +2 -2
  282. esphome/components/text_sensor/text_sensor.h +4 -4
  283. esphome/components/thermostat/climate.py +11 -7
  284. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  285. esphome/components/thermostat/thermostat_climate.h +52 -41
  286. esphome/components/time/__init__.py +2 -2
  287. esphome/components/tmp1075/tmp1075.cpp +1 -1
  288. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  289. esphome/components/touchscreen/__init__.py +2 -2
  290. esphome/components/tuya/number/tuya_number.cpp +1 -1
  291. esphome/components/udp/udp_component.cpp +3 -3
  292. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  293. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  294. esphome/components/update/__init__.py +2 -2
  295. esphome/components/usb_uart/usb_uart.cpp +1 -1
  296. esphome/components/valve/__init__.py +5 -5
  297. esphome/components/valve/valve.cpp +1 -1
  298. esphome/components/valve/valve.h +2 -2
  299. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  300. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  301. esphome/components/web_server/__init__.py +2 -2
  302. esphome/components/web_server/ota/__init__.py +2 -2
  303. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  304. esphome/components/web_server/web_server.cpp +58 -12
  305. esphome/components/web_server_base/__init__.py +2 -2
  306. esphome/components/wifi/__init__.py +5 -5
  307. esphome/components/wifi/wifi_component.cpp +3 -3
  308. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  309. esphome/config_validation.py +2 -2
  310. esphome/const.py +2 -1
  311. esphome/core/__init__.py +1 -0
  312. esphome/core/application.cpp +89 -51
  313. esphome/core/application.h +1 -0
  314. esphome/core/component.cpp +41 -19
  315. esphome/core/component.h +17 -13
  316. esphome/core/config.py +7 -7
  317. esphome/core/defines.h +4 -0
  318. esphome/core/entity_base.cpp +22 -8
  319. esphome/core/entity_base.h +43 -0
  320. esphome/core/helpers.cpp +26 -13
  321. esphome/core/helpers.h +4 -3
  322. esphome/core/ring_buffer.cpp +6 -2
  323. esphome/core/ring_buffer.h +2 -1
  324. esphome/core/scheduler.cpp +175 -94
  325. esphome/core/scheduler.h +66 -35
  326. esphome/core/time.cpp +6 -20
  327. esphome/coroutine.py +80 -3
  328. esphome/cpp_generator.py +13 -0
  329. esphome/cpp_helpers.py +2 -2
  330. esphome/dashboard/web_server.py +67 -10
  331. esphome/espota2.py +13 -6
  332. esphome/helpers.py +68 -83
  333. esphome/resolver.py +67 -0
  334. esphome/util.py +9 -6
  335. esphome/wizard.py +39 -26
  336. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/METADATA +9 -9
  337. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/RECORD +345 -314
  338. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  339. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  340. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  341. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  342. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/WHEEL +0 -0
  343. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/entry_points.txt +0 -0
  344. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/licenses/LICENSE +0 -0
  345. {esphome-2025.8.3.dist-info → esphome-2025.9.0b1.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ from esphome.const import (
21
21
  DEVICE_CLASS_OUTLET,
22
22
  DEVICE_CLASS_SWITCH,
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
 
@@ -230,6 +230,6 @@ async def switch_is_off_to_code(config, condition_id, template_arg, args):
230
230
  return cg.new_Pvariable(condition_id, template_arg, paren, False)
231
231
 
232
232
 
233
- @coroutine_with_priority(100.0)
233
+ @coroutine_with_priority(CoroPriority.CORE)
234
234
  async def to_code(config):
235
235
  cg.add_global(switch_ns.using)
@@ -32,7 +32,7 @@ optional<bool> Switch::get_initial_state() {
32
32
  if (!(restore_mode & RESTORE_MODE_PERSISTENT_MASK))
33
33
  return {};
34
34
 
35
- this->rtc_ = global_preferences->make_preference<bool>(this->get_object_id_hash());
35
+ this->rtc_ = global_preferences->make_preference<bool>(this->get_preference_hash());
36
36
  bool initial_state;
37
37
  if (!this->rtc_.load(&initial_state))
38
38
  return {};
@@ -91,8 +91,8 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o
91
91
  LOG_STR_ARG(onoff));
92
92
 
93
93
  // Add optional fields separately
94
- if (!obj->get_icon().empty()) {
95
- ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon().c_str());
94
+ if (!obj->get_icon_ref().empty()) {
95
+ ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str());
96
96
  }
97
97
  if (obj->assumed_state()) {
98
98
  ESP_LOGCONFIG(tag, "%s Assumed State: YES", prefix);
@@ -100,8 +100,8 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o
100
100
  if (obj->is_inverted()) {
101
101
  ESP_LOGCONFIG(tag, "%s Inverted: YES", prefix);
102
102
  }
103
- if (!obj->get_device_class().empty()) {
104
- ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class().c_str());
103
+ if (!obj->get_device_class_ref().empty()) {
104
+ ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str());
105
105
  }
106
106
  }
107
107
  }
@@ -25,7 +25,7 @@ CONF_SCAN_TIME = "scan_time"
25
25
  CONF_DEBOUNCE_TIME = "debounce_time"
26
26
  CONF_SX1509_ID = "sx1509_id"
27
27
 
28
- AUTO_LOAD = ["key_provider"]
28
+ AUTO_LOAD = ["key_provider", "gpio_expander"]
29
29
  DEPENDENCIES = ["i2c"]
30
30
  MULTI_CONF = True
31
31
 
@@ -39,6 +39,9 @@ void SX1509Component::dump_config() {
39
39
  }
40
40
 
41
41
  void SX1509Component::loop() {
42
+ // Reset cache at the start of each loop
43
+ this->reset_pin_cache_();
44
+
42
45
  if (this->has_keypad_) {
43
46
  if (millis() - this->last_loop_timestamp_ < min_loop_period_)
44
47
  return;
@@ -73,18 +76,20 @@ void SX1509Component::loop() {
73
76
  }
74
77
  }
75
78
 
76
- bool SX1509Component::digital_read(uint8_t pin) {
79
+ bool SX1509Component::digital_read_hw(uint8_t pin) {
80
+ // Always read all pins when any input pin is accessed
81
+ return this->read_byte_16(REG_DATA_B, &this->input_mask_);
82
+ }
83
+
84
+ bool SX1509Component::digital_read_cache(uint8_t pin) {
85
+ // Return cached value for input pins, false for output pins
77
86
  if (this->ddr_mask_ & (1 << pin)) {
78
- uint16_t temp_reg_data;
79
- if (!this->read_byte_16(REG_DATA_B, &temp_reg_data))
80
- return false;
81
- if (temp_reg_data & (1 << pin))
82
- return true;
87
+ return (this->input_mask_ & (1 << pin)) != 0;
83
88
  }
84
89
  return false;
85
90
  }
86
91
 
87
- void SX1509Component::digital_write(uint8_t pin, bool bit_value) {
92
+ void SX1509Component::digital_write_hw(uint8_t pin, bool bit_value) {
88
93
  if ((~this->ddr_mask_) & (1 << pin)) {
89
94
  // If the pin is an output, write high/low
90
95
  uint16_t temp_reg_data = 0;
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "esphome/components/i2c/i2c.h"
4
4
  #include "esphome/components/key_provider/key_provider.h"
5
+ #include "esphome/components/gpio_expander/cached_gpio.h"
5
6
  #include "esphome/core/component.h"
6
7
  #include "esphome/core/hal.h"
7
8
  #include "sx1509_gpio_pin.h"
@@ -30,7 +31,10 @@ class SX1509Processor {
30
31
 
31
32
  class SX1509KeyTrigger : public Trigger<uint8_t> {};
32
33
 
33
- class SX1509Component : public Component, public i2c::I2CDevice, public key_provider::KeyProvider {
34
+ class SX1509Component : public Component,
35
+ public i2c::I2CDevice,
36
+ public gpio_expander::CachedGpioExpander<uint16_t, 16>,
37
+ public key_provider::KeyProvider {
34
38
  public:
35
39
  SX1509Component() = default;
36
40
 
@@ -39,11 +43,9 @@ class SX1509Component : public Component, public i2c::I2CDevice, public key_prov
39
43
  float get_setup_priority() const override { return setup_priority::HARDWARE; }
40
44
  void loop() override;
41
45
 
42
- bool digital_read(uint8_t pin);
43
46
  uint16_t read_key_data();
44
47
  void set_pin_value(uint8_t pin, uint8_t i_on) { this->write_byte(REG_I_ON[pin], i_on); };
45
48
  void pin_mode(uint8_t pin, gpio::Flags flags);
46
- void digital_write(uint8_t pin, bool bit_value);
47
49
  uint32_t get_clock() { return this->clk_x_; };
48
50
  void set_rows_cols(uint8_t rows, uint8_t cols) {
49
51
  this->rows_ = rows;
@@ -61,10 +63,15 @@ class SX1509Component : public Component, public i2c::I2CDevice, public key_prov
61
63
  void setup_led_driver(uint8_t pin);
62
64
 
63
65
  protected:
66
+ // Virtual methods from CachedGpioExpander
67
+ bool digital_read_hw(uint8_t pin) override;
68
+ bool digital_read_cache(uint8_t pin) override;
69
+ void digital_write_hw(uint8_t pin, bool value) override;
70
+
64
71
  uint32_t clk_x_ = 2000000;
65
72
  uint8_t frequency_ = 0;
66
73
  uint16_t ddr_mask_ = 0x00;
67
- uint16_t input_mask_ = 0x00;
74
+ uint16_t input_mask_ = 0x00; // Cache for input values (16-bit for all pins)
68
75
  uint16_t port_mask_ = 0x00;
69
76
  uint16_t output_state_ = 0x00;
70
77
  bool has_keypad_ = false;
@@ -50,7 +50,7 @@ bool TCA9555Component::read_gpio_outputs_() {
50
50
  return false;
51
51
  uint8_t data[2];
52
52
  if (!this->read_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
53
- this->status_set_warning("Failed to read output register");
53
+ this->status_set_warning(LOG_STR("Failed to read output register"));
54
54
  return false;
55
55
  }
56
56
  this->output_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
@@ -64,7 +64,7 @@ bool TCA9555Component::read_gpio_modes_() {
64
64
  uint8_t data[2];
65
65
  bool success = this->read_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2);
66
66
  if (!success) {
67
- this->status_set_warning("Failed to read mode register");
67
+ this->status_set_warning(LOG_STR("Failed to read mode register"));
68
68
  return false;
69
69
  }
70
70
  this->mode_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
@@ -79,7 +79,7 @@ bool TCA9555Component::digital_read_hw(uint8_t pin) {
79
79
  uint8_t bank_number = pin < 8 ? 0 : 1;
80
80
  uint8_t register_to_read = bank_number ? TCA9555_INPUT_PORT_REGISTER_1 : TCA9555_INPUT_PORT_REGISTER_0;
81
81
  if (!this->read_bytes(register_to_read, &data, 1)) {
82
- this->status_set_warning("Failed to read input register");
82
+ this->status_set_warning(LOG_STR("Failed to read input register"));
83
83
  return false;
84
84
  }
85
85
  uint8_t second_half = this->input_mask_ >> 8;
@@ -108,7 +108,7 @@ void TCA9555Component::digital_write_hw(uint8_t pin, bool value) {
108
108
  data[0] = this->output_mask_;
109
109
  data[1] = this->output_mask_ >> 8;
110
110
  if (!this->write_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
111
- this->status_set_warning("Failed to write output register");
111
+ this->status_set_warning(LOG_STR("Failed to write output register"));
112
112
  return;
113
113
  }
114
114
 
@@ -123,7 +123,7 @@ bool TCA9555Component::write_gpio_modes_() {
123
123
  data[0] = this->mode_mask_;
124
124
  data[1] = this->mode_mask_ >> 8;
125
125
  if (!this->write_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2)) {
126
- this->status_set_warning("Failed to write mode register");
126
+ this->status_set_warning(LOG_STR("Failed to write mode register"));
127
127
  return false;
128
128
  }
129
129
  this->status_clear_warning();
@@ -12,7 +12,7 @@ void TEE501Component::setup() {
12
12
  uint8_t identification[9];
13
13
  this->read(identification, 9);
14
14
  this->write_read(address, sizeof address, identification, sizeof identification);
15
- if (identification[8] != calc_crc8_(identification, 0, 7)) {
15
+ if (identification[8] != crc8(identification, 8, 0xFF, 0x31, true)) {
16
16
  this->error_code_ = CRC_CHECK_FAILED;
17
17
  this->mark_failed();
18
18
  return;
@@ -45,7 +45,7 @@ void TEE501Component::update() {
45
45
  this->set_timeout(50, [this]() {
46
46
  uint8_t i2c_response[3];
47
47
  this->read(i2c_response, 3);
48
- if (i2c_response[2] != calc_crc8_(i2c_response, 0, 1)) {
48
+ if (i2c_response[2] != crc8(i2c_response, 2, 0xFF, 0x31, true)) {
49
49
  this->error_code_ = CRC_CHECK_FAILED;
50
50
  this->status_set_warning();
51
51
  return;
@@ -62,24 +62,5 @@ void TEE501Component::update() {
62
62
  });
63
63
  }
64
64
 
65
- unsigned char TEE501Component::calc_crc8_(const unsigned char buf[], unsigned char from, unsigned char to) {
66
- unsigned char crc_val = 0xFF;
67
- unsigned char i = 0;
68
- unsigned char j = 0;
69
- for (i = from; i <= to; i++) {
70
- int cur_val = buf[i];
71
- for (j = 0; j < 8; j++) {
72
- if (((crc_val ^ cur_val) & 0x80) != 0) // If MSBs are not equal
73
- {
74
- crc_val = ((crc_val << 1) ^ 0x31);
75
- } else {
76
- crc_val = (crc_val << 1);
77
- }
78
- cur_val = cur_val << 1;
79
- }
80
- }
81
- return crc_val;
82
- }
83
-
84
65
  } // namespace tee501
85
66
  } // namespace esphome
@@ -1,8 +1,8 @@
1
1
  #pragma once
2
2
 
3
- #include "esphome/core/component.h"
4
- #include "esphome/components/sensor/sensor.h"
5
3
  #include "esphome/components/i2c/i2c.h"
4
+ #include "esphome/components/sensor/sensor.h"
5
+ #include "esphome/core/component.h"
6
6
 
7
7
  namespace esphome {
8
8
  namespace tee501 {
@@ -16,8 +16,6 @@ class TEE501Component : public sensor::Sensor, public PollingComponent, public i
16
16
  void update() override;
17
17
 
18
18
  protected:
19
- unsigned char calc_crc8_(const unsigned char buf[], unsigned char from, unsigned char to);
20
-
21
19
  enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, CRC_CHECK_FAILED } error_code_{NONE};
22
20
  };
23
21
 
@@ -86,7 +86,7 @@ void TemplateAlarmControlPanel::setup() {
86
86
  break;
87
87
  case ALARM_CONTROL_PANEL_RESTORE_DEFAULT_DISARMED: {
88
88
  uint8_t value;
89
- this->pref_ = global_preferences->make_preference<uint8_t>(this->get_object_id_hash());
89
+ this->pref_ = global_preferences->make_preference<uint8_t>(this->get_preference_hash());
90
90
  if (this->pref_.load(&value)) {
91
91
  this->current_state_ = static_cast<alarm_control_panel::AlarmControlPanelState>(value);
92
92
  } else {
@@ -20,7 +20,7 @@ void TemplateDate::setup() {
20
20
  } else {
21
21
  datetime::DateEntityRestoreState temp;
22
22
  this->pref_ =
23
- global_preferences->make_preference<datetime::DateEntityRestoreState>(194434030U ^ this->get_object_id_hash());
23
+ global_preferences->make_preference<datetime::DateEntityRestoreState>(194434030U ^ this->get_preference_hash());
24
24
  if (this->pref_.load(&temp)) {
25
25
  temp.apply(this);
26
26
  return;
@@ -19,8 +19,8 @@ void TemplateDateTime::setup() {
19
19
  state = this->initial_value_;
20
20
  } else {
21
21
  datetime::DateTimeEntityRestoreState temp;
22
- this->pref_ = global_preferences->make_preference<datetime::DateTimeEntityRestoreState>(194434090U ^
23
- this->get_object_id_hash());
22
+ this->pref_ = global_preferences->make_preference<datetime::DateTimeEntityRestoreState>(
23
+ 194434090U ^ this->get_preference_hash());
24
24
  if (this->pref_.load(&temp)) {
25
25
  temp.apply(this);
26
26
  return;
@@ -20,7 +20,7 @@ void TemplateTime::setup() {
20
20
  } else {
21
21
  datetime::TimeEntityRestoreState temp;
22
22
  this->pref_ =
23
- global_preferences->make_preference<datetime::TimeEntityRestoreState>(194434060U ^ this->get_object_id_hash());
23
+ global_preferences->make_preference<datetime::TimeEntityRestoreState>(194434060U ^ this->get_preference_hash());
24
24
  if (this->pref_.load(&temp)) {
25
25
  temp.apply(this);
26
26
  return;
@@ -14,7 +14,7 @@ void TemplateNumber::setup() {
14
14
  if (!this->restore_value_) {
15
15
  value = this->initial_value_;
16
16
  } else {
17
- this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
17
+ this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
18
18
  if (!this->pref_.load(&value)) {
19
19
  if (!std::isnan(this->initial_value_)) {
20
20
  value = this->initial_value_;
@@ -16,7 +16,7 @@ void TemplateSelect::setup() {
16
16
  ESP_LOGD(TAG, "State from initial: %s", value.c_str());
17
17
  } else {
18
18
  size_t index;
19
- this->pref_ = global_preferences->make_preference<size_t>(this->get_object_id_hash());
19
+ this->pref_ = global_preferences->make_preference<size_t>(this->get_preference_hash());
20
20
  if (!this->pref_.load(&index)) {
21
21
  value = this->initial_option_;
22
22
  ESP_LOGD(TAG, "State from initial (could not load stored index): %s", value.c_str());
@@ -15,7 +15,7 @@ void TemplateText::setup() {
15
15
  if (!this->pref_) {
16
16
  ESP_LOGD(TAG, "State from initial: %s", value.c_str());
17
17
  } else {
18
- uint32_t key = this->get_object_id_hash();
18
+ uint32_t key = this->get_preference_hash();
19
19
  key += this->traits.get_min_length() << 2;
20
20
  key += this->traits.get_max_length() << 4;
21
21
  key += fnv1_hash(this->traits.get_pattern()) << 6;
@@ -13,7 +13,7 @@ from esphome.const import (
13
13
  CONF_VALUE,
14
14
  CONF_WEB_SERVER,
15
15
  )
16
- from esphome.core import CORE, coroutine_with_priority
16
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
17
17
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
18
18
  from esphome.cpp_generator import MockObjClass
19
19
 
@@ -149,7 +149,7 @@ async def new_text(
149
149
  return var
150
150
 
151
151
 
152
- @coroutine_with_priority(100.0)
152
+ @coroutine_with_priority(CoroPriority.CORE)
153
153
  async def to_code(config):
154
154
  cg.add_global(text_ns.using)
155
155
 
@@ -12,8 +12,8 @@ namespace text {
12
12
  #define LOG_TEXT(prefix, type, obj) \
13
13
  if ((obj) != nullptr) { \
14
14
  ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
15
- if (!(obj)->get_icon().empty()) { \
16
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
15
+ if (!(obj)->get_icon_ref().empty()) { \
16
+ ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
17
17
  } \
18
18
  }
19
19
 
@@ -20,7 +20,7 @@ from esphome.const import (
20
20
  DEVICE_CLASS_EMPTY,
21
21
  DEVICE_CLASS_TIMESTAMP,
22
22
  )
23
- from esphome.core import CORE, coroutine_with_priority
23
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
24
24
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
25
25
  from esphome.cpp_generator import MockObjClass
26
26
  from esphome.util import Registry
@@ -230,7 +230,7 @@ async def new_text_sensor(config, *args):
230
230
  return var
231
231
 
232
232
 
233
- @coroutine_with_priority(100.0)
233
+ @coroutine_with_priority(CoroPriority.CORE)
234
234
  async def to_code(config):
235
235
  cg.add_global(text_sensor_ns.using)
236
236
 
@@ -14,11 +14,11 @@ namespace text_sensor {
14
14
  #define LOG_TEXT_SENSOR(prefix, type, obj) \
15
15
  if ((obj) != nullptr) { \
16
16
  ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
17
- if (!(obj)->get_device_class().empty()) { \
18
- ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \
17
+ if (!(obj)->get_device_class_ref().empty()) { \
18
+ ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \
19
19
  } \
20
- if (!(obj)->get_icon().empty()) { \
21
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
20
+ if (!(obj)->get_icon_ref().empty()) { \
21
+ ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
22
22
  } \
23
23
  }
24
24
 
@@ -32,6 +32,7 @@ from esphome.const import (
32
32
  CONF_FAN_WITH_COOLING,
33
33
  CONF_FAN_WITH_HEATING,
34
34
  CONF_HEAT_ACTION,
35
+ CONF_HEAT_COOL_MODE,
35
36
  CONF_HEAT_DEADBAND,
36
37
  CONF_HEAT_MODE,
37
38
  CONF_HEAT_OVERRUN,
@@ -150,7 +151,7 @@ def generate_comparable_preset(config, name):
150
151
  def validate_thermostat(config):
151
152
  # verify corresponding action(s) exist(s) for any defined climate mode or action
152
153
  requirements = {
153
- CONF_AUTO_MODE: [
154
+ CONF_HEAT_COOL_MODE: [
154
155
  CONF_COOL_ACTION,
155
156
  CONF_HEAT_ACTION,
156
157
  CONF_MIN_COOLING_OFF_TIME,
@@ -540,6 +541,9 @@ CONFIG_SCHEMA = cv.All(
540
541
  cv.Optional(CONF_FAN_ONLY_MODE): automation.validate_automation(
541
542
  single=True
542
543
  ),
544
+ cv.Optional(CONF_HEAT_COOL_MODE): automation.validate_automation(
545
+ single=True
546
+ ),
543
547
  cv.Optional(CONF_HEAT_MODE): automation.validate_automation(single=True),
544
548
  cv.Optional(CONF_OFF_MODE): automation.validate_automation(single=True),
545
549
  cv.Optional(CONF_FAN_MODE_ON_ACTION): automation.validate_automation(
@@ -644,7 +648,6 @@ async def to_code(config):
644
648
  var = await climate.new_climate(config)
645
649
  await cg.register_component(var, config)
646
650
 
647
- heat_cool_mode_available = CONF_HEAT_ACTION in config and CONF_COOL_ACTION in config
648
651
  two_points_available = CONF_HEAT_ACTION in config and (
649
652
  CONF_COOL_ACTION in config
650
653
  or (config[CONF_FAN_ONLY_COOLING] and CONF_FAN_ONLY_ACTION in config)
@@ -739,11 +742,6 @@ async def to_code(config):
739
742
  var.get_idle_action_trigger(), [], config[CONF_IDLE_ACTION]
740
743
  )
741
744
 
742
- if heat_cool_mode_available is True:
743
- cg.add(var.set_supports_heat_cool(True))
744
- else:
745
- cg.add(var.set_supports_heat_cool(False))
746
-
747
745
  if CONF_COOL_ACTION in config:
748
746
  await automation.build_automation(
749
747
  var.get_cool_action_trigger(), [], config[CONF_COOL_ACTION]
@@ -780,6 +778,7 @@ async def to_code(config):
780
778
  await automation.build_automation(
781
779
  var.get_auto_mode_trigger(), [], config[CONF_AUTO_MODE]
782
780
  )
781
+ cg.add(var.set_supports_auto(True))
783
782
  if CONF_COOL_MODE in config:
784
783
  await automation.build_automation(
785
784
  var.get_cool_mode_trigger(), [], config[CONF_COOL_MODE]
@@ -800,6 +799,11 @@ async def to_code(config):
800
799
  var.get_heat_mode_trigger(), [], config[CONF_HEAT_MODE]
801
800
  )
802
801
  cg.add(var.set_supports_heat(True))
802
+ if CONF_HEAT_COOL_MODE in config:
803
+ await automation.build_automation(
804
+ var.get_heat_cool_mode_trigger(), [], config[CONF_HEAT_COOL_MODE]
805
+ )
806
+ cg.add(var.set_supports_heat_cool(True))
803
807
  if CONF_OFF_MODE in config:
804
808
  await automation.build_automation(
805
809
  var.get_off_mode_trigger(), [], config[CONF_OFF_MODE]