From d71f296313123303c159729eda781a267df469a4 Mon Sep 17 00:00:00 2001 From: Darsey Litzenberger Date: Tue, 14 Oct 2025 00:15:02 -0600 Subject: [PATCH] app_status: Initial commit --- components/app_status/README.md | 27 +++++++++++++ components/app_status/__init__.py | 0 components/app_status/app_status.cpp | 40 +++++++++++++++++++ components/app_status/app_status.h | 32 +++++++++++++++ components/app_status/binary_sensor.py | 32 +++++++++++++++ .../color_status_led/color_status_led.h | 2 +- 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 components/app_status/README.md create mode 100644 components/app_status/__init__.py create mode 100644 components/app_status/app_status.cpp create mode 100644 components/app_status/app_status.h create mode 100644 components/app_status/binary_sensor.py diff --git a/components/app_status/README.md b/components/app_status/README.md new file mode 100644 index 0000000..de0e7bf --- /dev/null +++ b/components/app_status/README.md @@ -0,0 +1,27 @@ +This should simply return app status. + +```yaml +# example configuration: + +binary_sensor: + - platform: app_status + name: App warning state + detect_status: warning + + - platform: app_status + name: App error state + detect_status: error + + - platform: app_status + name: App error or warning state + detect_status: + - warning + - error + + - platform: app_status + name: App ok + detect_status: + - warning + - error + inverted: true +``` diff --git a/components/app_status/__init__.py b/components/app_status/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/components/app_status/app_status.cpp b/components/app_status/app_status.cpp new file mode 100644 index 0000000..be9db1c --- /dev/null +++ b/components/app_status/app_status.cpp @@ -0,0 +1,40 @@ +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "app_status.h" + +namespace esphome { +namespace app_status { + +static const char *TAG = "app_status.binary_sensor"; + +void AppStatus::setup() { + +} + +void AppStatus::update() { + ESP_LOGV(TAG, "update() called; inverted = %s", TRUEFALSE(this->inverted_)); + bool result = false; + auto app_state = App.get_app_state() & STATUS_LED_MASK; + if (this->include_errors_ && (app_state & STATUS_LED_ERROR)) { + result = true; + } + if (this->include_warnings_ && (app_state & STATUS_LED_WARNING)) { + result = true; + } + if (this->inverted_) { + result = !result; + } + this->publish_state(result); +} + +void AppStatus::dump_config() { + ESP_LOGCONFIG(TAG, "App status binary sensor"); + ESP_LOGCONFIG(TAG, " inverted = %s", TRUEFALSE(this->inverted_)); + ESP_LOGCONFIG(TAG, " include warnings = %s", TRUEFALSE(this->include_warnings_)); + ESP_LOGCONFIG(TAG, " include errors = %s", TRUEFALSE(this->include_errors_)); +} + +} // namespace app_status +} // namespace esphome + +// vim:set sw=2: diff --git a/components/app_status/app_status.h b/components/app_status/app_status.h new file mode 100644 index 0000000..098bc87 --- /dev/null +++ b/components/app_status/app_status.h @@ -0,0 +1,32 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/binary_sensor/binary_sensor.h" + +namespace esphome { +namespace app_status { + +class AppStatus : public binary_sensor::BinarySensor, public PollingComponent { + public: + //void loop() override; + void setup() override; + void update() override; + void dump_config() override; + + //float get_loop_priority() const override { return 50.0f; } + + void set_inverted(bool value) { this->inverted_ = value; } + void set_include_errors(bool allow) { this->include_errors_ = allow; } + void set_include_warnings(bool allow) { this->include_warnings_ = allow; } + + protected: + //uint8_t last_app_state_(0xFF); + bool inverted_{false}; + bool include_warnings_{true}; + bool include_errors_{true}; +}; + +} // namespace app_status +} // namespace esphome + +// vim:set sw=2: diff --git a/components/app_status/binary_sensor.py b/components/app_status/binary_sensor.py new file mode 100644 index 0000000..543075f --- /dev/null +++ b/components/app_status/binary_sensor.py @@ -0,0 +1,32 @@ +# dlitz 2025 +# Ref: https://github.com/esphome/starter-components/blob/main/components/empty_binary_sensor/binary_sensor.py +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor +from esphome.const import CONF_ID, CONF_INVERTED + +CONF_DETECT_STATUS = "detect_status" +CONF_WARNING = "warning" +CONF_ERROR = "error" + +DETECT_STATUS_ENUM = { + CONF_WARNING: 1, + CONF_ERROR: 2, +} + +app_status_ns = cg.esphome_ns.namespace("app_status") +AppStatus = app_status_ns.class_("AppStatus", binary_sensor.BinarySensor, cg.PollingComponent) + +#CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(AppStatus).extend({cv.GenerateID(): cv.declare_id(AppStatus)}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(AppStatus).extend({ + cv.GenerateID(): cv.declare_id(AppStatus), + cv.Optional(CONF_DETECT_STATUS, default=[CONF_WARNING, CONF_ERROR]): cv.ensure_list(cv.enum(DETECT_STATUS_ENUM)), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, +}).extend(cv.polling_component_schema(default_update_interval="1s")) + +async def to_code(config): + var = await binary_sensor.new_binary_sensor(config) + await cg.register_component(var, config) + cg.add(var.set_inverted(config[CONF_INVERTED])) + cg.add(var.set_include_warnings(CONF_WARNING in config[CONF_DETECT_STATUS])) + cg.add(var.set_include_errors(CONF_ERROR in config[CONF_DETECT_STATUS])) diff --git a/components/color_status_led/color_status_led.h b/components/color_status_led/color_status_led.h index 94c2a15..52e26c8 100644 --- a/components/color_status_led/color_status_led.h +++ b/components/color_status_led/color_status_led.h @@ -15,7 +15,7 @@ class ColorStatusLED : public switch_::Switch, public Component { float get_loop_priority() const override { return 50.0f; } protected: - uint8_t last_app_state_(0xFF); + uint8_t last_app_state_{0xFF}; }; } // namespace color_status_led