From dfc7cd7f5d35426c8bb07af0f0312e0298772e02 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 15 Mar 2023 15:21:35 -0700 Subject: [PATCH] allow using a binary output for the status led (#4532) * allow using a binary output for the status led * lint * output status as well * simplify --------- Co-authored-by: Samuel Sieb --- .../components/status_led/light/__init__.py | 29 ++++++++++++------- .../status_led/light/status_led_light.cpp | 28 +++++++++++------- .../status_led/light/status_led_light.h | 6 +++- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/esphome/components/status_led/light/__init__.py b/esphome/components/status_led/light/__init__.py index 8896046998..d6a4a245e6 100644 --- a/esphome/components/status_led/light/__init__.py +++ b/esphome/components/status_led/light/__init__.py @@ -1,26 +1,35 @@ from esphome import pins import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import light -from esphome.const import CONF_OUTPUT_ID, CONF_PIN +from esphome.components import light, output +from esphome.const import CONF_OUTPUT, CONF_OUTPUT_ID, CONF_PIN from .. import status_led_ns +AUTO_LOAD = ["output"] + StatusLEDLightOutput = status_led_ns.class_( "StatusLEDLightOutput", light.LightOutput, cg.Component ) -CONFIG_SCHEMA = light.BINARY_LIGHT_SCHEMA.extend( - { - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(StatusLEDLightOutput), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - } +CONFIG_SCHEMA = cv.All( + light.BINARY_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(StatusLEDLightOutput), + cv.Optional(CONF_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_OUTPUT): cv.use_id(output.BinaryOutput), + } + ), + cv.has_at_least_one_key(CONF_PIN, CONF_OUTPUT), ) async def to_code(config): var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) - pin = await cg.gpio_pin_expression(config[CONF_PIN]) - cg.add(var.set_pin(pin)) + if CONF_PIN in config: + pin = await cg.gpio_pin_expression(config[CONF_PIN]) + cg.add(var.set_pin(pin)) + if CONF_OUTPUT in config: + out = await cg.get_variable(config[CONF_OUTPUT]) + cg.add(var.set_output(out)) await cg.register_component(var, config) - # cg.add(cg.App.register_component(var)) await light.register_light(var, config) diff --git a/esphome/components/status_led/light/status_led_light.cpp b/esphome/components/status_led/light/status_led_light.cpp index 760c89f972..b47d1f5bd0 100644 --- a/esphome/components/status_led/light/status_led_light.cpp +++ b/esphome/components/status_led/light/status_led_light.cpp @@ -15,10 +15,10 @@ void StatusLEDLightOutput::loop() { } if ((new_state & STATUS_LED_ERROR) != 0u) { - this->pin_->digital_write(millis() % 250u < 150u); + this->output_state_(millis() % 250u < 150u); this->last_app_state_ = new_state; } else if ((new_state & STATUS_LED_WARNING) != 0u) { - this->pin_->digital_write(millis() % 1500u < 250u); + this->output_state_(millis() % 1500u < 250u); this->last_app_state_ = new_state; } else if (new_state != this->last_app_state_) { // if no error/warning -> restore light state or turn off @@ -26,17 +26,16 @@ void StatusLEDLightOutput::loop() { if (lightstate_) lightstate_->current_values_as_binary(&state); - - this->pin_->digital_write(state); - this->last_app_state_ = new_state; - ESP_LOGD(TAG, "Restoring light state %s", ONOFF(state)); + + this->output_state_(state); + this->last_app_state_ = new_state; } } void StatusLEDLightOutput::setup_state(light::LightState *state) { lightstate_ = state; - ESP_LOGD(TAG, "'%s': Setting initital state", state->get_name().c_str()); + ESP_LOGD(TAG, "'%s': Setting initial state", state->get_name().c_str()); this->write_state(state); } @@ -47,16 +46,18 @@ void StatusLEDLightOutput::write_state(light::LightState *state) { // if in warning/error, don't overwrite the status_led // once it is back to OK, the loop will restore the state if ((App.get_app_state() & (STATUS_LED_ERROR | STATUS_LED_WARNING)) == 0u) { - this->pin_->digital_write(binary); ESP_LOGD(TAG, "'%s': Setting state %s", state->get_name().c_str(), ONOFF(binary)); + this->output_state_(binary); } } void StatusLEDLightOutput::setup() { ESP_LOGCONFIG(TAG, "Setting up Status LED..."); - this->pin_->setup(); - this->pin_->digital_write(false); + if (this->pin_ != nullptr) { + this->pin_->setup(); + this->pin_->digital_write(false); + } } void StatusLEDLightOutput::dump_config() { @@ -64,5 +65,12 @@ void StatusLEDLightOutput::dump_config() { LOG_PIN(" Pin: ", this->pin_); } +void StatusLEDLightOutput::output_state_(bool state) { + if (this->pin_ != nullptr) + this->pin_->digital_write(state); + if (this->output_ != nullptr) + this->output_->set_state(state); +} + } // namespace status_led } // namespace esphome diff --git a/esphome/components/status_led/light/status_led_light.h b/esphome/components/status_led/light/status_led_light.h index e90d381e3c..e711a2e749 100644 --- a/esphome/components/status_led/light/status_led_light.h +++ b/esphome/components/status_led/light/status_led_light.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" #include "esphome/components/light/light_output.h" +#include "esphome/components/output/binary_output.h" namespace esphome { namespace status_led { @@ -10,6 +11,7 @@ namespace status_led { class StatusLEDLightOutput : public light::LightOutput, public Component { public: void set_pin(GPIOPin *pin) { pin_ = pin; } + void set_output(output::BinaryOutput *output) { output_ = output; } light::LightTraits get_traits() override { auto traits = light::LightTraits(); @@ -31,9 +33,11 @@ class StatusLEDLightOutput : public light::LightOutput, public Component { float get_loop_priority() const override { return 50.0f; } protected: - GPIOPin *pin_; + GPIOPin *pin_{nullptr}; + output::BinaryOutput *output_{nullptr}; light::LightState *lightstate_{}; uint32_t last_app_state_{0xFFFF}; + void output_state_(bool state); }; } // namespace status_led