[fan] Fix preset_mode not restored on boot (#14002)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jonathan Swoboda
2026-02-15 12:11:50 -05:00
committed by Jesse Hills
parent f6362aa8da
commit df29cdbf17
5 changed files with 23 additions and 15 deletions

View File

@@ -221,12 +221,17 @@ void Fan::publish_state() {
}
// Random 32-bit value, change this every time the layout of the FanRestoreState struct changes.
constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABA;
constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABB;
optional<FanRestoreState> Fan::restore_state_() {
FanRestoreState recovered{};
this->rtc_ = this->make_entity_preference<FanRestoreState>(RESTORE_STATE_VERSION);
bool restored = this->rtc_.load(&recovered);
if (!restored) {
// No valid saved data; ensure preset_mode sentinel is set
recovered.preset_mode = FanRestoreState::NO_PRESET;
}
switch (this->restore_mode_) {
case FanRestoreMode::NO_RESTORE:
return {};
@@ -264,6 +269,7 @@ void Fan::save_state_() {
state.oscillating = this->oscillating;
state.speed = this->speed;
state.direction = this->direction;
state.preset_mode = FanRestoreState::NO_PRESET;
if (this->has_preset_mode()) {
const auto &preset_modes = traits.supported_preset_modes();

View File

@@ -91,11 +91,13 @@ class FanCall {
};
struct FanRestoreState {
static constexpr uint8_t NO_PRESET = UINT8_MAX;
bool state;
int speed;
bool oscillating;
FanDirection direction;
uint8_t preset_mode;
uint8_t preset_mode{NO_PRESET};
/// Convert this struct to a fan call that can be performed.
FanCall to_call(Fan &fan);

View File

@@ -28,15 +28,15 @@ fan::FanCall HBridgeFan::brake() {
}
void HBridgeFan::setup() {
// Construct traits before restore so preset modes can be looked up by index
this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(*this);
this->write_state_();
}
// Construct traits
this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
}
void HBridgeFan::dump_config() {

View File

@@ -7,15 +7,15 @@ namespace speed {
static const char *const TAG = "speed.fan";
void SpeedFan::setup() {
// Construct traits before restore so preset modes can be looked up by index
this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(*this);
this->write_state_();
}
// Construct traits
this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
}
void SpeedFan::dump_config() { LOG_FAN("", "Speed Fan", this); }

View File

@@ -6,15 +6,15 @@ namespace esphome::template_ {
static const char *const TAG = "template.fan";
void TemplateFan::setup() {
// Construct traits before restore so preset modes can be looked up by index
this->traits_ =
fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(*this);
}
// Construct traits
this->traits_ =
fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_);
this->traits_.set_supported_preset_modes(this->preset_modes_);
}
void TemplateFan::dump_config() { LOG_FAN("", "Template Fan", this); }