SpikeyGG
(Greg G.)
November 29, 2020, 3:18pm
28
Thanks for sharing this @JayElDubya , I used it and added the “Starting up” to take care of the huge negative number right after flashing.
lambda: |-
int seconds = (id(${node_name}_uptime_raw).state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
if ( days > 3650 ) {
return { "Starting up" };
} else if ( days ) {
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( hours ) {
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( minutes ) {
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else {
return { (String(seconds) +"s").c_str() };
}
icon: mdi:clock-start
I also determined that the huge negative number was causing a boot loop on the ESP32 so now I have used this code to reflash all my ESPHome devices so they come up with more readable and accurate values.
6 Likes
nice find. Will update my nodes.I have had random reboots on several devices that eventually sort themselves out. I wonder if there’s some variation as to what order things are initialized upon boot. Hopefully this stops the overflow. For what it’s worth, I’ve noticed high values on HA sensor values as well before it actually connects to HA and refreshes the value. Is there a way, maybe with a clever filter, to have an initial value (like 0) for a sensor to have before the data comes in?
-Josh
fredrike
(Fredrik Erlandsson)
January 7, 2021, 10:44am
30
I’m not super found of limits (although I highly doubt my nodes will reach close to 10 years uptime).
This works even better:
text_sensor:
- platform: template
name: ${friendly_name} Uptime
id: ${node_name}_uptime
icon: mdi:clock-start
sensor:
- platform: uptime
name: "${friendly_name} Uptime Sensor"
id: ${node_name}_uptime_raw
update_interval: 60s
on_raw_value:
then:
- logger.log:
format: "Raw Value of Uptime sensor: %f"
args: ['id(${node_name}_uptime_raw).raw_state']
level: INFO
- text_sensor.template.publish:
id: ${node_name}_uptime
state: !lambda |-
int seconds = round(id(${node_name}_uptime_raw).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
if ( days ) {
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( hours ) {
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( minutes ) {
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else {
return { (String(seconds) +"s").c_str() };
}
Edit: I’ve added this as an example to the esphome doc: https://esphome.io/components/sensor/uptime.html#human-readable-sensor
3 Likes
yousaf465
(Yousaf465)
August 5, 2022, 6:10am
31
Is this good according to the new template style too? Working fine on my end, but still want to check.
Hm, that was 3 years ago, and I have completely changed my approach. That code is probably still going to work fine - I haven’t heard about deprecating the old template format.
What I am doing nowadays is to have a time
entity on the ESP device, then have a text_sensor
that exposes that value, and then set the device class to timestamp
inside Home Assistant. The major advantage of this approach is that the entity only updates once (as opposed to every 60 seconds) and thus reduces the load on the database, and it uses the built-in way to display a human-readable uptime like “2 days ago” or “Last month”.
text_sensor:
- platform: template
name: "${display_devicename} Last Restart Time"
id: last_restart_time
icon: mdi:clock
entity_category: diagnostic
# device_class: timestamp
time:
- platform: homeassistant
id: homeassistant_time
on_time_sync:
then:
# Update last restart time, but only once.
- if:
condition:
lambda: 'return id(last_restart_time).state == "";'
then:
- text_sensor.template.publish:
id: last_restart_time
state: !lambda 'return id(homeassistant_time).utcnow().strftime("%Y-%m-%dT%H:%M:%S.000000+00:00");'
2 Likes
makai
August 5, 2022, 6:56am
33
I’m using this code (original code from Frenck):
time:
- platform: homeassistant
id: current_time
on_time_sync:
- component.update: uptime_timestamp
sensor:
- platform: uptime
id: uptime_sec
- platform: template
id: uptime_timestamp
name: "$devicename Uptime"
device_class: timestamp
entity_category: diagnostic
accuracy_decimals: 0
update_interval: never
lambda: |-
static float timestamp = (
id(current_time).utcnow().timestamp - id(uptime_sec).state
);
return timestamp;
3 Likes
TheFes
(The Fes)
August 5, 2022, 7:25am
34
I use the same, but I’ve set the first sensor to internal only, so it won’t end up in HA.
1 Like
makai
August 5, 2022, 7:28am
35
It’s internal by default if it has no name:
TheFes
(The Fes)
August 5, 2022, 7:29am
36
ah, didn’t know that, thanks
yousaf465
(Yousaf465)
August 5, 2022, 7:36am
37
modified it to comply with new guidelines
template:
- sensor:
- name: "Huawei Modem uptime"
state: >
{% set uptime = states.sensor.huawei_igd_uptime.state | int %}
{% set days = (uptime / 86400) | int %}
{%- if days > 0 -%}
{{ days }} days, {{ (uptime - (days * 86400)) | int | timestamp_custom('%H:%M:%S', false) }}
{%- else -%}
{{ uptime | int | timestamp_custom('%H:%M:%S', false) }}
{%- endif -%}
Edit: removed unit, bcz it is self explanatory.
1 Like
yousaf465
(Yousaf465)
August 5, 2022, 5:32pm
38
Thanks a lot for explanations!
device_class: duration
can be used but what difference it makes is still not known in uptime.
umbex
January 7, 2023, 12:11pm
39
GarSys:
- platform: template
name: "Uptime (formatted)"
lambda: |-
uint32_t dur = id(uptime_s).state;
int dys = 0;
int hrs = 0;
int mnts = 0;
if (dur > 86399) {
dys = trunc(dur / 86400);
dur = dur - (dys * 86400);
}
if (dur > 3599) {
hrs = trunc(dur / 3600);
dur = dur - (hrs * 3600);
}
if (dur > 59) {
mnts = trunc(dur / 60);
dur = dur - (mnts * 60);
}
char buffer[17];
sprintf(buffer, "%ud %02uh %02um %02us", dys, hrs, mnts, dur);
return {buffer};
icon: mdi:clock-start
update_interval: 15s
Great! it works.
It gives warning in compilation but it works. thank!
1 Like
raidnet-ms
(Raidnet Ms)
March 22, 2023, 11:01am
40
Hi guys,
why not using copy integration as suggested for wifi signal component to show rssi data in percentage?
Seems to be the new guideline, am I wrong?
jbhobson
(Justin H.)
April 4, 2023, 6:06am
41
This code ends up sending the device_last_restart to HA every 60 seconds, even if update_internval = 6h or a filter for delta 0.01 is added… it keeps sending the same last restart data every minute.
??
That should actually work. I am currently on ESPHome version 2023.3.2 and can confirm that setting a longer update interval for the template text sensor works.
The other thing to remember is (at least that’s my understanding) that even if the last restart time is sent every minute, because the value has not changed this should not be registered as an update in HA and thus not write an entry into the database.
Compare that with an actual uptime sensor that changes its value every single time, this would result in a state change and a new entry in the database.
Yamaha0014
(Yamaha0014)
November 15, 2023, 6:58pm
43
Is it possible to make such a change so that there is no error when compiling?
sign
(Sign)
December 21, 2023, 8:35pm
44
Came up with this solution (dd:hh:mm:ss
format):
text_sensor:
- platform: template
name: Uptime
update_interval: 1s
lambda: |-
auto s = millis() / 1000;
return str_snprintf("%02d:%02d:%02d:%02d", 11, s / 86400, s / 3600 % 24, s / 60 % 60, s % 60);
jbhobson
(Justin H.)
December 22, 2023, 1:50pm
45
There’s also this version:
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
- platform: template
name: "Device Uptime"
entity_category: diagnostic
lambda: |-
int seconds = (id(uptime_seconds).state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
if ( days > 3650 ) {
return { "Starting up" };
} else if ( days ) {
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( hours ) {
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else if ( minutes ) {
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
} else {
return { (String(seconds) +"s").c_str() };
}
icon: mdi:clock-start
2 Likes
bubi
January 16, 2024, 9:30am
47
This might be a silly question but how I can use this code?
I copy/paste it into configuration.yaml, but what next? Thanks
You take it out again and instead put it where it belongs