From 1d91bf5759a615273348ed722aa3983488bce1c1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 4 Sep 2025 11:02:17 -0500 Subject: [PATCH] [pcf8574] Add lazy input caching to reduce I2C bus usage --- esphome/components/pcf8574/pcf8574.cpp | 10 +++++++++- esphome/components/pcf8574/pcf8574.h | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index 848fbed484..5da6f92aae 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -16,6 +16,11 @@ void PCF8574Component::setup() { this->write_gpio_(); this->read_gpio_(); } +void PCF8574Component::loop() { + // Invalidate the cache at the start of each loop. + // The actual read will happen on demand in digital_read() + this->cache_valid_ = false; +} void PCF8574Component::dump_config() { ESP_LOGCONFIG(TAG, "PCF8574:"); LOG_I2C_DEVICE(this) @@ -25,7 +30,10 @@ void PCF8574Component::dump_config() { } } bool PCF8574Component::digital_read(uint8_t pin) { - this->read_gpio_(); + // Read the inputs once per loop on demand and cache the result + if (!this->cache_valid_ && this->read_gpio_()) { + this->cache_valid_ = true; + } return this->input_mask_ & (1 << pin); } void PCF8574Component::digital_write(uint8_t pin, bool value) { diff --git a/esphome/components/pcf8574/pcf8574.h b/esphome/components/pcf8574/pcf8574.h index 6edc67fc96..fdeee1800d 100644 --- a/esphome/components/pcf8574/pcf8574.h +++ b/esphome/components/pcf8574/pcf8574.h @@ -15,6 +15,8 @@ class PCF8574Component : public Component, public i2c::I2CDevice { /// Check i2c availability and setup masks void setup() override; + /// Invalidate cache at start of each loop + void loop() override; /// Helper function to read the value of a pin. bool digital_read(uint8_t pin); /// Helper function to write the value of a pin. @@ -37,6 +39,8 @@ class PCF8574Component : public Component, public i2c::I2CDevice { uint16_t output_mask_{0x00}; /// The state read in read_gpio_ - 1 means HIGH, 0 means LOW uint16_t input_mask_{0x00}; + /// Cache validity flag - true if we've read inputs this loop cycle + bool cache_valid_{false}; bool pcf8575_; ///< TRUE->16-channel PCF8575, FALSE->8-channel PCF8574 };