diff --git a/esphome/components/power_supply/power_supply.cpp b/esphome/components/power_supply/power_supply.cpp index 4da73e76ae..f094f6e2e9 100644 --- a/esphome/components/power_supply/power_supply.cpp +++ b/esphome/components/power_supply/power_supply.cpp @@ -21,7 +21,11 @@ void PowerSupply::dump_config() { LOG_PIN(" Pin: ", this->pin_); } -float PowerSupply::get_setup_priority() const { return setup_priority::IO; } +float PowerSupply::get_setup_priority() const { + if (this->pin_->is_internal() && this->enable_on_boot_) + return setup_priority::POWER; + return setup_priority::IO; +} bool PowerSupply::is_enabled() const { return this->active_requests_ != 0; } diff --git a/esphome/core/component.h b/esphome/core/component.h index 1ae70371a1..70a051ca0b 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -33,6 +33,8 @@ class RuntimeStatsCollector; */ namespace setup_priority { +/// For power supply components that must be on before buses like i2c can work. +inline constexpr float POWER = 1200.0f; /// For communication buses like i2c/spi inline constexpr float BUS = 1000.0f; /// For components that represent GPIO pins like PCF8573 diff --git a/tests/components/power_supply/test_setup_priority.cpp b/tests/components/power_supply/test_setup_priority.cpp new file mode 100644 index 0000000000..401fc72654 --- /dev/null +++ b/tests/components/power_supply/test_setup_priority.cpp @@ -0,0 +1,47 @@ +#include + +#include "esphome/components/power_supply/power_supply.h" +#include "esphome/core/gpio.h" +#include "esphome/core/component.h" + +namespace esphome::power_supply::testing { + +// Minimal dummy internal GPIO pin implementation for testing +class DummyInternalPin : public InternalGPIOPin { + public: + DummyInternalPin() = default; + void setup() override {} + void pin_mode(esphome::gpio::Flags) override {} + esphome::gpio::Flags get_flags() const override { return esphome::gpio::FLAG_NONE; } + bool digital_read() override { return false; } + void digital_write(bool) override {} + void detach_interrupt() const override {} + ISRInternalGPIOPin to_isr() const override { return ISRInternalGPIOPin(); } + uint8_t get_pin() const override { return 0; } + bool is_inverted() const override { return false; } + + protected: + // Implement protected attach_interrupt required by InternalGPIOPin + void attach_interrupt(void (*func)(void *), void *arg, esphome::gpio::InterruptType type) const override {} +}; + +TEST(PowerSupply, HasHigherPriorityThanBusWhenInternalAndEnableOnBoot) { + power_supply::PowerSupply ps; + DummyInternalPin pin; + ps.set_pin(&pin); + ps.set_enable_on_boot(true); + + // POWER priority should be greater than BUS priority + EXPECT_GT(ps.get_setup_priority(), setup_priority::BUS); +} + +TEST(PowerSupply, FallsBackToIOWhenNotEnableOnBoot) { + power_supply::PowerSupply ps; + DummyInternalPin pin; + ps.set_pin(&pin); + ps.set_enable_on_boot(false); + + EXPECT_EQ(ps.get_setup_priority(), setup_priority::IO); +} + +} // namespace esphome::power_supply::testing