From fc2b15e307833359f079aec46ceffd30b9398abe Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:27:47 +1100 Subject: [PATCH] [uptime] Add text_sensor (#8028) --- .../uptime/{sensor.py => sensor/__init__.py} | 6 +-- .../{ => sensor}/uptime_seconds_sensor.cpp | 0 .../{ => sensor}/uptime_seconds_sensor.h | 0 .../{ => sensor}/uptime_timestamp_sensor.cpp | 0 .../{ => sensor}/uptime_timestamp_sensor.h | 0 .../components/uptime/text_sensor/__init__.py | 19 ++++++++ .../uptime/text_sensor/uptime_text_sensor.cpp | 46 +++++++++++++++++++ .../uptime/text_sensor/uptime_text_sensor.h | 25 ++++++++++ tests/components/uptime/common.yaml | 4 ++ 9 files changed, 97 insertions(+), 3 deletions(-) rename esphome/components/uptime/{sensor.py => sensor/__init__.py} (100%) rename esphome/components/uptime/{ => sensor}/uptime_seconds_sensor.cpp (100%) rename esphome/components/uptime/{ => sensor}/uptime_seconds_sensor.h (100%) rename esphome/components/uptime/{ => sensor}/uptime_timestamp_sensor.cpp (100%) rename esphome/components/uptime/{ => sensor}/uptime_timestamp_sensor.h (100%) create mode 100644 esphome/components/uptime/text_sensor/__init__.py create mode 100644 esphome/components/uptime/text_sensor/uptime_text_sensor.cpp create mode 100644 esphome/components/uptime/text_sensor/uptime_text_sensor.h diff --git a/esphome/components/uptime/sensor.py b/esphome/components/uptime/sensor/__init__.py similarity index 100% rename from esphome/components/uptime/sensor.py rename to esphome/components/uptime/sensor/__init__.py index 30220751b6..e2a7aee1a2 100644 --- a/esphome/components/uptime/sensor.py +++ b/esphome/components/uptime/sensor/__init__.py @@ -1,14 +1,14 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import sensor, time +import esphome.config_validation as cv from esphome.const import ( CONF_TIME_ID, + DEVICE_CLASS_DURATION, DEVICE_CLASS_TIMESTAMP, ENTITY_CATEGORY_DIAGNOSTIC, + ICON_TIMER, STATE_CLASS_TOTAL_INCREASING, UNIT_SECOND, - ICON_TIMER, - DEVICE_CLASS_DURATION, ) uptime_ns = cg.esphome_ns.namespace("uptime") diff --git a/esphome/components/uptime/uptime_seconds_sensor.cpp b/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp similarity index 100% rename from esphome/components/uptime/uptime_seconds_sensor.cpp rename to esphome/components/uptime/sensor/uptime_seconds_sensor.cpp diff --git a/esphome/components/uptime/uptime_seconds_sensor.h b/esphome/components/uptime/sensor/uptime_seconds_sensor.h similarity index 100% rename from esphome/components/uptime/uptime_seconds_sensor.h rename to esphome/components/uptime/sensor/uptime_seconds_sensor.h diff --git a/esphome/components/uptime/uptime_timestamp_sensor.cpp b/esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp similarity index 100% rename from esphome/components/uptime/uptime_timestamp_sensor.cpp rename to esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp diff --git a/esphome/components/uptime/uptime_timestamp_sensor.h b/esphome/components/uptime/sensor/uptime_timestamp_sensor.h similarity index 100% rename from esphome/components/uptime/uptime_timestamp_sensor.h rename to esphome/components/uptime/sensor/uptime_timestamp_sensor.h diff --git a/esphome/components/uptime/text_sensor/__init__.py b/esphome/components/uptime/text_sensor/__init__.py new file mode 100644 index 0000000000..996d983e71 --- /dev/null +++ b/esphome/components/uptime/text_sensor/__init__.py @@ -0,0 +1,19 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import ENTITY_CATEGORY_DIAGNOSTIC, ICON_TIMER + +uptime_ns = cg.esphome_ns.namespace("uptime") +UptimeTextSensor = uptime_ns.class_( + "UptimeTextSensor", text_sensor.TextSensor, cg.PollingComponent +) +CONFIG_SCHEMA = text_sensor.text_sensor_schema( + UptimeTextSensor, + icon=ICON_TIMER, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, +).extend(cv.polling_component_schema("60s")) + + +async def to_code(config): + var = await text_sensor.new_text_sensor(config) + await cg.register_component(var, config) diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp new file mode 100644 index 0000000000..0fa5e199f3 --- /dev/null +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -0,0 +1,46 @@ +#include "uptime_text_sensor.h" + +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace uptime { + +static const char *const TAG = "uptime.sensor"; + +void UptimeTextSensor::setup() { this->last_ms_ = millis(); } + +void UptimeTextSensor::update() { + const auto now = millis(); + // get whole seconds since last update. Note that even if the millis count has overflowed between updates, + // the difference will still be correct due to the way twos-complement arithmetic works. + const uint32_t delta = (now - this->last_ms_) / 1000; + if (delta == 0) + return; + // set last_ms_ to the last second boundary + this->last_ms_ = now - (now % 1000); + this->uptime_ += delta; + auto uptime = this->uptime_; + unsigned days = uptime / (24 * 3600); + unsigned seconds = uptime % (24 * 3600); + unsigned hours = seconds / 3600; + seconds %= 3600; + unsigned minutes = seconds / 60; + seconds %= 60; + if (days != 0) { + this->publish_state(str_sprintf("%dd%dh%dm%ds", days, hours, minutes, seconds)); + } else if (hours != 0) { + this->publish_state(str_sprintf("%dh%dm%ds", hours, minutes, seconds)); + } else if (minutes != 0) { + this->publish_state(str_sprintf("%dm%ds", minutes, seconds)); + } else { + this->publish_state(str_sprintf("%ds", seconds)); + } +} + +float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; } +void UptimeTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Uptime Text Sensor", this); } + +} // namespace uptime +} // namespace esphome diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.h b/esphome/components/uptime/text_sensor/uptime_text_sensor.h new file mode 100644 index 0000000000..4baf1039b6 --- /dev/null +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.h @@ -0,0 +1,25 @@ +#pragma once + +#include "esphome/core/defines.h" + +#include "esphome/components/text_sensor/text_sensor.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace uptime { + +class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent { + public: + void update() override; + void dump_config() override; + void setup() override; + + float get_setup_priority() const override; + + protected: + uint64_t uptime_{0}; + uint64_t last_ms_{0}; +}; + +} // namespace uptime +} // namespace esphome diff --git a/tests/components/uptime/common.yaml b/tests/components/uptime/common.yaml index f63f80b050..d78ef8eca9 100644 --- a/tests/components/uptime/common.yaml +++ b/tests/components/uptime/common.yaml @@ -13,3 +13,7 @@ sensor: - platform: uptime name: Uptime Sensor Timestamp type: timestamp + +text_sensor: + - platform: uptime + name: Uptime Text