[uptime] Cosmetic improvements for uptime text_sensor (#8101)

This commit is contained in:
Clyde Stubbs 2025-01-21 13:43:50 +11:00 committed by GitHub
parent 576dbd6f0c
commit 0f4e274e52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 24 deletions

View File

@ -11,7 +11,7 @@ CONFIG_SCHEMA = text_sensor.text_sensor_schema(
UptimeTextSensor,
icon=ICON_TIMER,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
).extend(cv.polling_component_schema("60s"))
).extend(cv.polling_component_schema("30s"))
async def to_code(config):

View File

@ -9,34 +9,51 @@ namespace uptime {
static const char *const TAG = "uptime.sensor";
void UptimeTextSensor::setup() { this->last_ms_ = millis(); }
void UptimeTextSensor::setup() {
this->last_ms_ = millis();
if (this->last_ms_ < 60 * 1000)
this->last_ms_ = 0;
this->update();
}
void UptimeTextSensor::update() {
const auto now = millis();
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);
uint32_t delta = now - this->last_ms_;
this->last_ms_ = now - delta % 1000; // save remainder for next update
delta /= 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));
unsigned interval = this->get_update_interval() / 1000;
std::string buffer{};
// display from the largest unit that corresponds to the update interval, drop larger units that are zero.
while (true) { // enable use of break for early exit
unsigned remainder = uptime % 60;
uptime /= 60;
if (interval < 30) {
buffer.insert(0, str_sprintf("%us", remainder));
if (uptime == 0)
break;
}
remainder = uptime % 60;
uptime /= 60;
if (interval < 1800) {
buffer.insert(0, str_sprintf("%um", remainder));
if (uptime == 0)
break;
}
remainder = uptime % 24;
uptime /= 24;
if (interval < 12 * 3600) {
buffer.insert(0, str_sprintf("%uh", remainder));
if (uptime == 0)
break;
}
buffer.insert(0, str_sprintf("%ud", (unsigned) uptime));
break;
}
this->publish_state(buffer);
}
float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; }

View File

@ -17,8 +17,8 @@ class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent
float get_setup_priority() const override;
protected:
uint64_t uptime_{0};
uint64_t last_ms_{0};
uint32_t uptime_{0}; // uptime in seconds, will overflow after 136 years
uint32_t last_ms_{0};
};
} // namespace uptime