Compare commits

...
4 changed files with 63 additions and 0 deletions
+2
View File
@@ -446,6 +446,8 @@ file does, and it is the authority when they disagree. The most useful starting
switches = switch.sub_switches(config, parent=hub)
await switches(CONF_BLUETOOTH, None, apply="set_bluetooth(state)", publish="after")
```
Restore an owned or standalone switch in `setup()` with `sw->restore_state()`, or
`restore_state(default)` to still drive a state when the restore mode is disabled.
- **Other codegen helpers:** `uart.new_uart_component(config, *ctor_args)` (and `i2c.new_i2c_component`,
`spi.new_spi_component`, `modbus.new_modbus_client_component`, `ble_client.new_ble_node_component`)
+7
View File
@@ -53,6 +53,13 @@ optional<bool> Switch::get_initial_state_with_restore_mode() {
}
return initial_state;
}
void Switch::restore_state() {
if (auto initial = this->get_initial_state_with_restore_mode())
this->control(*initial);
}
void Switch::restore_state(bool when_disabled) {
this->control(this->get_initial_state_with_restore_mode().value_or(when_disabled));
}
void Switch::publish_state(bool state) {
if (!this->publish_dedup_.next(state))
return;
+5
View File
@@ -110,6 +110,11 @@ class Switch : public EntityBase {
*/
optional<bool> get_initial_state_with_restore_mode();
/// Drive the switch to the state its restore mode yields, through control(), so inversion and
/// write_state() apply; a disabled restore mode drives `when_disabled`, or nothing without one.
void restore_state();
void restore_state(bool when_disabled);
/** Return whether this switch uses an assumed state - i.e. if both the ON/OFF actions should be displayed in Home
* Assistant because the real state is unknown.
*
@@ -0,0 +1,49 @@
#include <gtest/gtest.h>
#include <vector>
#include "esphome/components/switch/switch.h"
namespace esphome::switch_::testing {
class RecordingSwitch : public Switch {
public:
std::vector<bool> writes;
protected:
void write_state(bool state) override {
this->writes.push_back(state);
this->publish_state(state);
}
};
TEST(RestoreState, DrivesTheRestoreModeStateThroughInversion) {
RecordingSwitch on, off, inverted;
on.set_restore_mode(SWITCH_ALWAYS_ON);
off.set_restore_mode(SWITCH_ALWAYS_OFF);
inverted.set_restore_mode(SWITCH_ALWAYS_ON);
inverted.set_inverted(true);
on.restore_state();
off.restore_state();
inverted.restore_state();
EXPECT_EQ(on.writes, std::vector<bool>{true});
EXPECT_EQ(off.writes, std::vector<bool>{false});
EXPECT_EQ(inverted.writes, std::vector<bool>{false}); // the hardware level
EXPECT_TRUE(on.state);
EXPECT_FALSE(off.state);
EXPECT_TRUE(inverted.state);
}
TEST(RestoreState, DefaultAppliesOnlyWhenTheModeIsDisabled) {
RecordingSwitch disabled, on;
disabled.set_restore_mode(SWITCH_RESTORE_DISABLED);
on.set_restore_mode(SWITCH_ALWAYS_ON);
disabled.restore_state();
EXPECT_TRUE(disabled.writes.empty());
disabled.restore_state(true);
on.restore_state(false);
EXPECT_EQ(disabled.writes, std::vector<bool>{true});
EXPECT_EQ(on.writes, std::vector<bool>{true});
}
} // namespace esphome::switch_::testing