From 644aec791ee5b6d84142033298a277f42a393a93 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 20 Oct 2019 18:10:14 +0200 Subject: [PATCH] Add GPIO Switch interlock wait time (#777) * Add interlock wait time to gpio switch Fixes https://github.com/esphome/issues/issues/753 * Format * Fix --- esphome/components/gpio/switch/__init__.py | 3 +++ esphome/components/gpio/switch/gpio_switch.cpp | 18 +++++++++++++++++- esphome/components/gpio/switch/gpio_switch.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/esphome/components/gpio/switch/__init__.py b/esphome/components/gpio/switch/__init__.py index 7b383cb8a9..f75bc71009 100644 --- a/esphome/components/gpio/switch/__init__.py +++ b/esphome/components/gpio/switch/__init__.py @@ -15,12 +15,14 @@ RESTORE_MODES = { 'ALWAYS_ON': GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_ON, } +CONF_INTERLOCK_WAIT_TIME = 'interlock_wait_time' CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(GPIOSwitch), cv.Required(CONF_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_RESTORE_MODE, default='RESTORE_DEFAULT_OFF'): cv.enum(RESTORE_MODES, upper=True, space='_'), cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)), + cv.Optional(CONF_INTERLOCK_WAIT_TIME, default='0ms'): cv.positive_time_period_milliseconds, }).extend(cv.COMPONENT_SCHEMA) @@ -40,3 +42,4 @@ def to_code(config): lock = yield cg.get_variable(it) interlock.append(lock) cg.add(var.set_interlock(interlock)) + cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME])) diff --git a/esphome/components/gpio/switch/gpio_switch.cpp b/esphome/components/gpio/switch/gpio_switch.cpp index d22a74847e..d87e5a61e6 100644 --- a/esphome/components/gpio/switch/gpio_switch.cpp +++ b/esphome/components/gpio/switch/gpio_switch.cpp @@ -69,13 +69,29 @@ void GPIOSwitch::dump_config() { void GPIOSwitch::write_state(bool state) { if (state != this->inverted_) { // Turning ON, check interlocking + + bool found = false; for (auto *lock : this->interlock_) { if (lock == this) continue; - if (lock->state) + if (lock->state) { lock->turn_off(); + found = true; + } } + if (found && this->interlock_wait_time_ != 0) { + this->set_timeout("interlock", this->interlock_wait_time_, [this, state] { + // Don't write directly, call the function again + // (some other switch may have changed state while we were waiting) + this->write_state(state); + }); + return; + } + } else if (this->interlock_wait_time_ != 0) { + // If we are switched off during the interlock wait time, cancel any pending + // re-activations + this->cancel_timeout("interlock"); } this->pin_->digital_write(state); diff --git a/esphome/components/gpio/switch/gpio_switch.h b/esphome/components/gpio/switch/gpio_switch.h index ceace477b2..dc0dd9bc95 100644 --- a/esphome/components/gpio/switch/gpio_switch.h +++ b/esphome/components/gpio/switch/gpio_switch.h @@ -26,6 +26,7 @@ class GPIOSwitch : public switch_::Switch, public Component { void setup() override; void dump_config() override; void set_interlock(const std::vector &interlock); + void set_interlock_wait_time(uint32_t interlock_wait_time) { interlock_wait_time_ = interlock_wait_time; } protected: void write_state(bool state) override; @@ -33,6 +34,7 @@ class GPIOSwitch : public switch_::Switch, public Component { GPIOPin *pin_; GPIOSwitchRestoreMode restore_mode_{GPIO_SWITCH_RESTORE_DEFAULT_OFF}; std::vector interlock_; + uint32_t interlock_wait_time_{0}; }; } // namespace gpio