Skip to content

Commit 807df83

Browse files
committed
Merge branch 'pr3/time-based-actuator-base' into pr5/time-based-valve
2 parents f29257c + 1a4daf5 commit 807df83

9 files changed

Lines changed: 45 additions & 16 deletions

File tree

esphome/components/actuator/iactuator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <cstdint>
3+
#include "esphome/core/optional.h"
34

45
namespace esphome::actuator {
56

@@ -14,6 +15,10 @@ class IActuator {
1415
virtual ActuatorOperation get_operation() const = 0;
1516
virtual void set_operation(ActuatorOperation op) = 0;
1617
virtual void do_publish_state(bool save) = 0;
18+
/// Restore previously saved state and return restored position, or empty if no saved state.
19+
virtual optional<float> do_restore_state() = 0;
20+
/// Return the name of the entity (for logging).
21+
virtual const char *get_entity_name() const = 0;
1722
};
1823

1924
} // namespace esphome::actuator

esphome/components/cover/cover.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,23 @@ void Cover::publish_state(bool save) {
167167
}
168168
}
169169

170+
optional<CoverRestoreState> Cover::restore_state_() {
171+
this->rtc_ = this->make_entity_preference<CoverRestoreState>();
172+
CoverRestoreState recovered{};
173+
if (!this->rtc_.load(&recovered))
174+
return {};
175+
return recovered;
176+
}
177+
178+
optional<float> Cover::do_restore_state() {
179+
auto restore = this->restore_state_();
180+
if (!restore.has_value())
181+
return {};
182+
restore->apply(this);
183+
float pos = restore->position; // copy to avoid packed-field reference
184+
return pos;
185+
}
186+
170187
bool Cover::is_fully_open() const { return this->position == COVER_OPEN; }
171188
bool Cover::is_fully_closed() const { return this->position == COVER_CLOSED; }
172189

esphome/components/cover/cover.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ class Cover : public actuator::ActuatorBase, public actuator::IActuator {
127127
actuator::ActuatorOperation get_operation() const override { return this->current_operation; }
128128
void set_operation(actuator::ActuatorOperation op) override { this->current_operation = op; }
129129
void do_publish_state(bool save) override { this->publish_state(save); }
130+
optional<float> do_restore_state() override;
131+
const char *get_entity_name() const override { return this->get_name().c_str(); }
130132

131133
protected:
132134
friend CoverCall;
@@ -136,7 +138,7 @@ class Cover : public actuator::ActuatorBase, public actuator::IActuator {
136138
// Bridge from ActuatorBase — safe cast because Cover::make_call() always constructs a CoverCall
137139
void control(const actuator::ActuatorCallBase &call) final { this->control(static_cast<const CoverCall &>(call)); }
138140

139-
optional<CoverRestoreState> restore_state_() { return ActuatorBase::restore_state_<CoverRestoreState>(); }
141+
optional<CoverRestoreState> restore_state_();
140142
};
141143

142144
} // namespace esphome::cover

esphome/components/time_based/time_based_actuator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void TimeBasedActuatorBase::loop() {
3434
}
3535
}
3636

37-
void TimeBasedActuatorBase::control(const ActuatorCallBase &call) {
37+
void TimeBasedActuatorBase::control_(const ActuatorCallBase &call) {
3838
if (call.get_stop()) {
3939
this->start_direction_(ACTUATOR_OPERATION_IDLE);
4040
this->actuator_->do_publish_state(true);

esphome/components/time_based/time_based_actuator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class TimeBasedActuatorBase : public Component {
2424
bool get_assumed_state() const { return this->assumed_state_; }
2525

2626
protected:
27-
void control(const actuator::ActuatorCallBase &call);
27+
void control_(const actuator::ActuatorCallBase &call);
2828
void stop_prev_trigger_();
2929
bool is_at_target_() const;
3030
void start_direction_(actuator::ActuatorOperation dir);

esphome/components/time_based/time_based_cover.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class TimeBasedCover : public TimeBasedActuatorBase, public cover::Cover {
1515
void dump_config() override;
1616

1717
protected:
18-
void control(const cover::CoverCall &call) override { TimeBasedActuatorBase::control(call); }
18+
void control(const cover::CoverCall &call) override { TimeBasedActuatorBase::control_(call); }
1919
};
2020

2121
} // namespace esphome::time_based

esphome/components/valve/valve.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ void Valve::publish_state(bool save) {
141141
bool Valve::is_fully_open() const { return this->position == VALVE_OPEN; }
142142
bool Valve::is_fully_closed() const { return this->position == VALVE_CLOSED; }
143143

144+
optional<float> Valve::do_restore_state() {
145+
auto restore = this->restore_state_();
146+
if (!restore.has_value())
147+
return {};
148+
restore->apply(this);
149+
float pos = restore->position; // copy to avoid packed-field reference
150+
return pos;
151+
}
152+
144153
ValveCall ValveRestoreState::to_call(Valve *valve) {
145154
auto call = valve->make_call();
146155
call.set_position(this->position);

esphome/components/valve/valve.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class Valve : public actuator::ActuatorBase, public actuator::IActuator {
118118
actuator::ActuatorOperation get_operation() const override { return this->current_operation; }
119119
void set_operation(actuator::ActuatorOperation op) override { this->current_operation = op; }
120120
void do_publish_state(bool save) override { this->publish_state(save); }
121+
optional<float> do_restore_state() override;
122+
const char *get_entity_name() const override { return this->get_name().c_str(); }
121123

122124
protected:
123125
friend ValveCall;
Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
1-
"""Unit tests for the TimeBasedActuatorBase component.
2-
3-
Phases:
4-
Phase 8: Tests must FAIL (cpp stub not yet populated, class not exported)
5-
Phase 9: Import tests pass (TimeBasedActuatorBase exported, cpp implemented)
6-
Phase 10: Inheritance test passes (TimeBasedCover inherits TimeBasedActuatorBase)
7-
"""
1+
"""Unit tests for the TimeBasedActuatorBase component."""
82

93

104
def test_time_based_actuator_importable():
115
# pylint: disable-next=unused-import
12-
from esphome.components.actuator import TimeBasedActuatorBase # noqa: F401
6+
from esphome.components.time_based import TimeBasedActuatorBase # noqa: F401
137

148

159
def test_time_based_cover_inherits_actuator_base():
16-
"""After Phase 10, TimeBasedCover must inherit TimeBasedActuatorBase."""
17-
from esphome.components.actuator import TimeBasedActuatorBase
10+
"""Verify TimeBasedCover inherits TimeBasedActuatorBase."""
1811
from esphome.components.cover import Cover
12+
from esphome.components.time_based import TimeBasedActuatorBase
1913
from esphome.components.time_based.cover import TimeBasedCover
2014

2115
# MockObjClass does not support Python's issubclass(); use inherits_from() instead
@@ -26,6 +20,6 @@ def test_time_based_cover_inherits_actuator_base():
2620

2721

2822
def test_time_based_actuator_class_exported():
29-
import esphome.components.actuator as actuator_mod
23+
import esphome.components.time_based as time_based_mod
3024

31-
assert hasattr(actuator_mod, "TimeBasedActuatorBase")
25+
assert hasattr(time_based_mod, "TimeBasedActuatorBase")

0 commit comments

Comments
 (0)