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
@@ -1,4 +1,4 @@
1
- #include "number.h"
1
+ #include "opentherm_number.h"
2
2
 
3
3
  namespace esphome {
4
4
  namespace opentherm {
@@ -17,7 +17,7 @@ void OpenthermNumber::setup() {
17
17
  if (!this->restore_value_) {
18
18
  value = this->initial_value_;
19
19
  } else {
20
- this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
20
+ this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
21
21
  if (!this->pref_.load(&value)) {
22
22
  if (!std::isnan(this->initial_value_)) {
23
23
  value = this->initial_value_;
@@ -1,5 +1,5 @@
1
1
  #include "esphome/core/helpers.h" // for clamp() and lerp()
2
- #include "output.h"
2
+ #include "opentherm_output.h"
3
3
 
4
4
  namespace esphome {
5
5
  namespace opentherm {
@@ -1,4 +1,4 @@
1
- #include "switch.h"
1
+ #include "opentherm_switch.h"
2
2
 
3
3
  namespace esphome {
4
4
  namespace opentherm {
@@ -10,7 +10,7 @@ from esphome.const import (
10
10
  CONF_TRIGGER_ID,
11
11
  PlatformFramework,
12
12
  )
13
- from esphome.core import CORE, coroutine_with_priority
13
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
14
14
 
15
15
  CODEOWNERS = ["@esphome/core"]
16
16
  AUTO_LOAD = ["md5", "safe_mode"]
@@ -82,7 +82,7 @@ BASE_OTA_SCHEMA = cv.Schema(
82
82
  )
83
83
 
84
84
 
85
- @coroutine_with_priority(54.0)
85
+ @coroutine_with_priority(CoroPriority.COMMUNICATION)
86
86
  async def to_code(config):
87
87
  cg.add_define("USE_OTA")
88
88
 
@@ -14,6 +14,7 @@ from esphome.const import (
14
14
 
15
15
  CODEOWNERS = ["@Mat931"]
16
16
  DEPENDENCIES = ["i2c"]
17
+ AUTO_LOAD = ["gpio_expander"]
17
18
  MULTI_CONF = True
18
19
  pca6416a_ns = cg.esphome_ns.namespace("pca6416a")
19
20
 
@@ -51,6 +51,11 @@ void PCA6416AComponent::setup() {
51
51
  this->status_has_error());
52
52
  }
53
53
 
54
+ void PCA6416AComponent::loop() {
55
+ // Invalidate cache at the start of each loop
56
+ this->reset_pin_cache_();
57
+ }
58
+
54
59
  void PCA6416AComponent::dump_config() {
55
60
  if (this->has_pullup_) {
56
61
  ESP_LOGCONFIG(TAG, "PCAL6416A:");
@@ -63,15 +68,25 @@ void PCA6416AComponent::dump_config() {
63
68
  }
64
69
  }
65
70
 
66
- bool PCA6416AComponent::digital_read(uint8_t pin) {
67
- uint8_t bit = pin % 8;
71
+ bool PCA6416AComponent::digital_read_hw(uint8_t pin) {
68
72
  uint8_t reg_addr = pin < 8 ? PCA6416A_INPUT0 : PCA6416A_INPUT1;
69
73
  uint8_t value = 0;
70
- this->read_register_(reg_addr, &value);
71
- return value & (1 << bit);
74
+ if (!this->read_register_(reg_addr, &value)) {
75
+ return false;
76
+ }
77
+
78
+ // Update the appropriate part of input_mask_
79
+ if (pin < 8) {
80
+ this->input_mask_ = (this->input_mask_ & 0xFF00) | value;
81
+ } else {
82
+ this->input_mask_ = (this->input_mask_ & 0x00FF) | (uint16_t(value) << 8);
83
+ }
84
+ return true;
72
85
  }
73
86
 
74
- void PCA6416AComponent::digital_write(uint8_t pin, bool value) {
87
+ bool PCA6416AComponent::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
88
+
89
+ void PCA6416AComponent::digital_write_hw(uint8_t pin, bool value) {
75
90
  uint8_t reg_addr = pin < 8 ? PCA6416A_OUTPUT0 : PCA6416A_OUTPUT1;
76
91
  this->update_register_(pin, value, reg_addr);
77
92
  }
@@ -3,20 +3,20 @@
3
3
  #include "esphome/core/component.h"
4
4
  #include "esphome/core/hal.h"
5
5
  #include "esphome/components/i2c/i2c.h"
6
+ #include "esphome/components/gpio_expander/cached_gpio.h"
6
7
 
7
8
  namespace esphome {
8
9
  namespace pca6416a {
9
10
 
10
- class PCA6416AComponent : public Component, public i2c::I2CDevice {
11
+ class PCA6416AComponent : public Component,
12
+ public i2c::I2CDevice,
13
+ public gpio_expander::CachedGpioExpander<uint8_t, 16> {
11
14
  public:
12
15
  PCA6416AComponent() = default;
13
16
 
14
17
  /// Check i2c availability and setup masks
15
18
  void setup() override;
16
- /// Helper function to read the value of a pin.
17
- bool digital_read(uint8_t pin);
18
- /// Helper function to write the value of a pin.
19
- void digital_write(uint8_t pin, bool value);
19
+ void loop() override;
20
20
  /// Helper function to set the pin mode of a pin.
21
21
  void pin_mode(uint8_t pin, gpio::Flags flags);
22
22
 
@@ -25,6 +25,11 @@ class PCA6416AComponent : public Component, public i2c::I2CDevice {
25
25
  void dump_config() override;
26
26
 
27
27
  protected:
28
+ // Virtual methods from CachedGpioExpander
29
+ bool digital_read_hw(uint8_t pin) override;
30
+ bool digital_read_cache(uint8_t pin) override;
31
+ void digital_write_hw(uint8_t pin, bool value) override;
32
+
28
33
  bool read_register_(uint8_t reg, uint8_t *value);
29
34
  bool write_register_(uint8_t reg, uint8_t value);
30
35
  void update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr);
@@ -32,6 +37,8 @@ class PCA6416AComponent : public Component, public i2c::I2CDevice {
32
37
  /// The mask to write as output state - 1 means HIGH, 0 means LOW
33
38
  uint8_t output_0_{0x00};
34
39
  uint8_t output_1_{0x00};
40
+ /// Cache for input values (16-bit combined for both banks)
41
+ uint16_t input_mask_{0x00};
35
42
  /// Storage for last I2C error seen
36
43
  esphome::i2c::ErrorCode last_error_;
37
44
  /// Only the PCAL6416A has pull-up resistors
@@ -11,7 +11,8 @@ from esphome.const import (
11
11
  CONF_OUTPUT,
12
12
  )
13
13
 
14
- CODEOWNERS = ["@hwstar", "@clydebarrow"]
14
+ CODEOWNERS = ["@hwstar", "@clydebarrow", "@bdraco"]
15
+ AUTO_LOAD = ["gpio_expander"]
15
16
  DEPENDENCIES = ["i2c"]
16
17
  MULTI_CONF = True
17
18
  CONF_PIN_COUNT = "pin_count"
@@ -37,10 +37,9 @@ void PCA9554Component::setup() {
37
37
  }
38
38
 
39
39
  void PCA9554Component::loop() {
40
- // The read_inputs_() method will cache the input values from the chip.
41
- this->read_inputs_();
42
- // Clear all the previously read flags.
43
- this->was_previously_read_ = 0x00;
40
+ // Invalidate the cache at the start of each loop.
41
+ // The actual read will happen on demand when digital_read() is called
42
+ this->reset_pin_cache_();
44
43
  }
45
44
 
46
45
  void PCA9554Component::dump_config() {
@@ -54,21 +53,17 @@ void PCA9554Component::dump_config() {
54
53
  }
55
54
  }
56
55
 
57
- bool PCA9554Component::digital_read(uint8_t pin) {
58
- // Note: We want to try and avoid doing any I2C bus read transactions here
59
- // to conserve I2C bus bandwidth. So what we do is check to see if we
60
- // have seen a read during the time esphome is running this loop. If we have,
61
- // we do an I2C bus transaction to get the latest value. If we haven't
62
- // we return a cached value which was read at the time loop() was called.
63
- if (this->was_previously_read_ & (1 << pin))
64
- this->read_inputs_(); // Force a read of a new value
65
- // Indicate we saw a read request for this pin in case a
66
- // read happens later in the same loop.
67
- this->was_previously_read_ |= (1 << pin);
56
+ bool PCA9554Component::digital_read_hw(uint8_t pin) {
57
+ // Read all pins from hardware into input_mask_
58
+ return this->read_inputs_(); // Return true if I2C read succeeded, false on error
59
+ }
60
+
61
+ bool PCA9554Component::digital_read_cache(uint8_t pin) {
62
+ // Return the cached pin state from input_mask_
68
63
  return this->input_mask_ & (1 << pin);
69
64
  }
70
65
 
71
- void PCA9554Component::digital_write(uint8_t pin, bool value) {
66
+ void PCA9554Component::digital_write_hw(uint8_t pin, bool value) {
72
67
  if (value) {
73
68
  this->output_mask_ |= (1 << pin);
74
69
  } else {
@@ -127,8 +122,7 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) {
127
122
 
128
123
  float PCA9554Component::get_setup_priority() const { return setup_priority::IO; }
129
124
 
130
- // Run our loop() method very early in the loop, so that we cache read values before
131
- // before other components call our digital_read() method.
125
+ // Run our loop() method early to invalidate cache before any other components access the pins
132
126
  float PCA9554Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
133
127
 
134
128
  void PCA9554GPIOPin::setup() { pin_mode(flags_); }
@@ -3,22 +3,21 @@
3
3
  #include "esphome/core/component.h"
4
4
  #include "esphome/core/hal.h"
5
5
  #include "esphome/components/i2c/i2c.h"
6
+ #include "esphome/components/gpio_expander/cached_gpio.h"
6
7
 
7
8
  namespace esphome {
8
9
  namespace pca9554 {
9
10
 
10
- class PCA9554Component : public Component, public i2c::I2CDevice {
11
+ class PCA9554Component : public Component,
12
+ public i2c::I2CDevice,
13
+ public gpio_expander::CachedGpioExpander<uint16_t, 16> {
11
14
  public:
12
15
  PCA9554Component() = default;
13
16
 
14
17
  /// Check i2c availability and setup masks
15
18
  void setup() override;
16
- /// Poll for input changes periodically
19
+ /// Invalidate cache at start of each loop
17
20
  void loop() override;
18
- /// Helper function to read the value of a pin.
19
- bool digital_read(uint8_t pin);
20
- /// Helper function to write the value of a pin.
21
- void digital_write(uint8_t pin, bool value);
22
21
  /// Helper function to set the pin mode of a pin.
23
22
  void pin_mode(uint8_t pin, gpio::Flags flags);
24
23
 
@@ -32,9 +31,13 @@ class PCA9554Component : public Component, public i2c::I2CDevice {
32
31
 
33
32
  protected:
34
33
  bool read_inputs_();
35
-
36
34
  bool write_register_(uint8_t reg, uint16_t value);
37
35
 
36
+ // Virtual methods from CachedGpioExpander
37
+ bool digital_read_hw(uint8_t pin) override;
38
+ bool digital_read_cache(uint8_t pin) override;
39
+ void digital_write_hw(uint8_t pin, bool value) override;
40
+
38
41
  /// number of bits the expander has
39
42
  size_t pin_count_{8};
40
43
  /// width of registers
@@ -45,8 +48,6 @@ class PCA9554Component : public Component, public i2c::I2CDevice {
45
48
  uint16_t output_mask_{0x00};
46
49
  /// The state of the actual input pin states - 1 means HIGH, 0 means LOW
47
50
  uint16_t input_mask_{0x00};
48
- /// Flags to check if read previously during this loop
49
- uint16_t was_previously_read_ = {0x00};
50
51
  /// Storage for last I2C error seen
51
52
  esphome::i2c::ErrorCode last_error_;
52
53
  };
@@ -11,6 +11,7 @@ from esphome.const import (
11
11
  CONF_OUTPUT,
12
12
  )
13
13
 
14
+ AUTO_LOAD = ["gpio_expander"]
14
15
  DEPENDENCIES = ["i2c"]
15
16
  MULTI_CONF = True
16
17
 
@@ -16,6 +16,10 @@ void PCF8574Component::setup() {
16
16
  this->write_gpio_();
17
17
  this->read_gpio_();
18
18
  }
19
+ void PCF8574Component::loop() {
20
+ // Invalidate the cache at the start of each loop
21
+ this->reset_pin_cache_();
22
+ }
19
23
  void PCF8574Component::dump_config() {
20
24
  ESP_LOGCONFIG(TAG, "PCF8574:");
21
25
  LOG_I2C_DEVICE(this)
@@ -24,17 +28,19 @@ void PCF8574Component::dump_config() {
24
28
  ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
25
29
  }
26
30
  }
27
- bool PCF8574Component::digital_read(uint8_t pin) {
28
- this->read_gpio_();
29
- return this->input_mask_ & (1 << pin);
31
+ bool PCF8574Component::digital_read_hw(uint8_t pin) {
32
+ // Read all pins from hardware into input_mask_
33
+ return this->read_gpio_(); // Return true if I2C read succeeded, false on error
30
34
  }
31
- void PCF8574Component::digital_write(uint8_t pin, bool value) {
35
+
36
+ bool PCF8574Component::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
37
+
38
+ void PCF8574Component::digital_write_hw(uint8_t pin, bool value) {
32
39
  if (value) {
33
40
  this->output_mask_ |= (1 << pin);
34
41
  } else {
35
42
  this->output_mask_ &= ~(1 << pin);
36
43
  }
37
-
38
44
  this->write_gpio_();
39
45
  }
40
46
  void PCF8574Component::pin_mode(uint8_t pin, gpio::Flags flags) {
@@ -91,6 +97,9 @@ bool PCF8574Component::write_gpio_() {
91
97
  }
92
98
  float PCF8574Component::get_setup_priority() const { return setup_priority::IO; }
93
99
 
100
+ // Run our loop() method early to invalidate cache before any other components access the pins
101
+ float PCF8574Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
102
+
94
103
  void PCF8574GPIOPin::setup() { pin_mode(flags_); }
95
104
  void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
96
105
  bool PCF8574GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
@@ -3,11 +3,16 @@
3
3
  #include "esphome/core/component.h"
4
4
  #include "esphome/core/hal.h"
5
5
  #include "esphome/components/i2c/i2c.h"
6
+ #include "esphome/components/gpio_expander/cached_gpio.h"
6
7
 
7
8
  namespace esphome {
8
9
  namespace pcf8574 {
9
10
 
10
- class PCF8574Component : public Component, public i2c::I2CDevice {
11
+ // PCF8574(8 pins)/PCF8575(16 pins) always read/write all pins in a single I2C transaction
12
+ // so we use uint16_t as bank type to ensure all pins are in one bank and cached together
13
+ class PCF8574Component : public Component,
14
+ public i2c::I2CDevice,
15
+ public gpio_expander::CachedGpioExpander<uint16_t, 16> {
11
16
  public:
12
17
  PCF8574Component() = default;
13
18
 
@@ -15,20 +20,22 @@ class PCF8574Component : public Component, public i2c::I2CDevice {
15
20
 
16
21
  /// Check i2c availability and setup masks
17
22
  void setup() override;
18
- /// Helper function to read the value of a pin.
19
- bool digital_read(uint8_t pin);
20
- /// Helper function to write the value of a pin.
21
- void digital_write(uint8_t pin, bool value);
23
+ /// Invalidate cache at start of each loop
24
+ void loop() override;
22
25
  /// Helper function to set the pin mode of a pin.
23
26
  void pin_mode(uint8_t pin, gpio::Flags flags);
24
27
 
25
28
  float get_setup_priority() const override;
29
+ float get_loop_priority() const override;
26
30
 
27
31
  void dump_config() override;
28
32
 
29
33
  protected:
30
- bool read_gpio_();
34
+ bool digital_read_hw(uint8_t pin) override;
35
+ bool digital_read_cache(uint8_t pin) override;
36
+ void digital_write_hw(uint8_t pin, bool value) override;
31
37
 
38
+ bool read_gpio_();
32
39
  bool write_gpio_();
33
40
 
34
41
  /// Mask for the pin mode - 1 means output, 0 means input
@@ -68,7 +68,7 @@ bool PI4IOE5V6408Component::read_gpio_outputs_() {
68
68
 
69
69
  uint8_t data;
70
70
  if (!this->read_byte(PI4IOE5V6408_REGISTER_OUT_SET, &data)) {
71
- this->status_set_warning("Failed to read output register");
71
+ this->status_set_warning(LOG_STR("Failed to read output register"));
72
72
  return false;
73
73
  }
74
74
  this->output_mask_ = data;
@@ -82,7 +82,7 @@ bool PI4IOE5V6408Component::read_gpio_modes_() {
82
82
 
83
83
  uint8_t data;
84
84
  if (!this->read_byte(PI4IOE5V6408_REGISTER_IO_DIR, &data)) {
85
- this->status_set_warning("Failed to read GPIO modes");
85
+ this->status_set_warning(LOG_STR("Failed to read GPIO modes"));
86
86
  return false;
87
87
  }
88
88
  #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
@@ -99,7 +99,7 @@ bool PI4IOE5V6408Component::digital_read_hw(uint8_t pin) {
99
99
 
100
100
  uint8_t data;
101
101
  if (!this->read_byte(PI4IOE5V6408_REGISTER_IN_STATE, &data)) {
102
- this->status_set_warning("Failed to read GPIO state");
102
+ this->status_set_warning(LOG_STR("Failed to read GPIO state"));
103
103
  return false;
104
104
  }
105
105
  this->input_mask_ = data;
@@ -117,7 +117,7 @@ void PI4IOE5V6408Component::digital_write_hw(uint8_t pin, bool value) {
117
117
  this->output_mask_ &= ~(1 << pin);
118
118
  }
119
119
  if (!this->write_byte(PI4IOE5V6408_REGISTER_OUT_SET, this->output_mask_)) {
120
- this->status_set_warning("Failed to write output register");
120
+ this->status_set_warning(LOG_STR("Failed to write output register"));
121
121
  return;
122
122
  }
123
123
  #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
@@ -131,15 +131,15 @@ bool PI4IOE5V6408Component::write_gpio_modes_() {
131
131
  return false;
132
132
 
133
133
  if (!this->write_byte(PI4IOE5V6408_REGISTER_IO_DIR, this->mode_mask_)) {
134
- this->status_set_warning("Failed to write GPIO modes");
134
+ this->status_set_warning(LOG_STR("Failed to write GPIO modes"));
135
135
  return false;
136
136
  }
137
137
  if (!this->write_byte(PI4IOE5V6408_REGISTER_PULL_SELECT, this->pull_up_down_mask_)) {
138
- this->status_set_warning("Failed to write GPIO pullup/pulldown");
138
+ this->status_set_warning(LOG_STR("Failed to write GPIO pullup/pulldown"));
139
139
  return false;
140
140
  }
141
141
  if (!this->write_byte(PI4IOE5V6408_REGISTER_PULL_ENABLE, this->pull_enable_mask_)) {
142
- this->status_set_warning("Failed to write GPIO pull enable");
142
+ this->status_set_warning(LOG_STR("Failed to write GPIO pull enable"));
143
143
  return false;
144
144
  }
145
145
  #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
@@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.All(
26
26
  )
27
27
 
28
28
 
29
- def to_code(config):
29
+ async def to_code(config):
30
30
  var = cg.new_Pvariable(config[CONF_ID])
31
- yield cg.register_component(var, config)
32
- yield uart.register_uart_device(var, config)
31
+ await cg.register_component(var, config)
32
+ await uart.register_uart_device(var, config)
@@ -99,9 +99,9 @@ async def to_code(config):
99
99
  }
100
100
  ),
101
101
  )
102
- def output_pipsolar_set_level_to_code(config, action_id, template_arg, args):
103
- paren = yield cg.get_variable(config[CONF_ID])
102
+ async def output_pipsolar_set_level_to_code(config, action_id, template_arg, args):
103
+ paren = await cg.get_variable(config[CONF_ID])
104
104
  var = cg.new_Pvariable(action_id, template_arg, paren)
105
- template_ = yield cg.templatable(config[CONF_VALUE], args, float)
105
+ template_ = await cg.templatable(config[CONF_VALUE], args, float)
106
106
  cg.add(var.set_level(template_))
107
- yield var
107
+ return var
@@ -17,8 +17,8 @@ void IRAM_ATTR PulseWidthSensorStore::gpio_intr(PulseWidthSensorStore *arg) {
17
17
  }
18
18
 
19
19
  void PulseWidthSensor::dump_config() {
20
- LOG_SENSOR("", "Pulse Width", this)
21
- LOG_UPDATE_INTERVAL(this)
20
+ LOG_SENSOR("", "Pulse Width", this);
21
+ LOG_UPDATE_INTERVAL(this);
22
22
  LOG_PIN(" Pin: ", this->pin_);
23
23
  }
24
24
  void PulseWidthSensor::update() {