To be sure to understand well the problem, you want to report multiple uptime from same physical device (which doesn’t have much sense) or from differents ESPs ? If from different ESPs they’ll show up as different variables for sure in HA so not sure what’s your problem there
Thanks for this! I’m much happier having my ESP do the work instead of making more sensors in HA. I also learned I can control the number of decimal places:
- platform: uptime
name: "Sensor Uptime"
filters:
- lambda: return x / 3600.0;
unit_of_measurement: "hours"
accuracy_decimals: 2
yes I love esphome because so many things can be done without touching configuration of HASS.
My next goal is to put most of the automation inside ESPhome too.
Is there a reason why you put 3600.0 and not 3600?
No, actually at first I wondered if putting 3600.0 would make it add the decimal place, but then I figured out it didn’t make any difference - I needed the accuracy_decimals
statement. But I forgot to change it back to just 3600
I’m learning new things every day!
Me tto, these are also some nice additions
switch:
- platform: restart
name: "power plug restart"
binary_sensor:
- platform: status
name: "power plug status"
sensor:
- platform: wifi_signal
name: "POW WiFi Signal"
update_interval: 60s
Like the OP here, I wanted the Uptime Sensor in ESPHome to do the formatting and not have to have Home Assistant do the work. So, I offer this code snippet to @Klagio (and everyone else).
esphome code:
sensor:
- platform: uptime
name: "Uptime"
id: uptime_s
update_interval: 15s
text_sensor:
- 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
Any idea why I am getting below error?
src\main.cpp:562:21: error: could not convert ‘{buffer}’ from ‘’ to ‘esphome::optional’
return {buffer};
^
src\main.cpp:563:3: warning: control reaches end of non-void function [-Wreturn-type]
});
^
*** [.pioenvs\bw_shp6_powerplug_02\src\main.cpp.o] Error 1
Fantastic, works great
hi all,
i was just looking thorough to find a method to do just this and after reading the above worked out that i can do this …
Copy to clipboard
- platform: uptime
name: "Emergency Light uptime"
filters:
- lambda: return (x/60)/60;
unit_of_measurement: "Hrs"
to get a readout in hours… eg… 1 hrs. or 1.5hrs
hope it helps
Found myself. I put everything under sensor and not text_sensor:(
That would do it. I’m glad you figured it out.
One more snippet for the crowd:
sensor:
- platform: uptime
name: "Uptime"
id: uptime_sec
- platform: template
name: "Uptime Days"
lambda: |-
return (id(uptime_sec).state/60)/60/24;
icon: mdi:clock-start
unit_of_measurement: days
I wanted to have the uptime still in seconds and have another one breaking it down in days
And…here is another version to show a more human readable uptime in days, hours, minutes, seconds:
sensor:
- platform: uptime
id: uptime_sec
text_sensor:
- platform: template
name: ${upper_devicename} Uptime
lambda: |-
int seconds = (id(uptime_sec).state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
icon: mdi:clock-start
update_interval: 113s
Result:
Great stuff guys! Here’s a version I did that only shows variables if they are positive. (i.e. doesn’t state “days” until it has been up for at least 1 day.)
sensor:
- platform: uptime
id: uptime_seconds
text_sensor:
- platform: template
name: ${friendly_name} - Uptime
update_interval: 42s
icon: mdi:clock-start
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 ) {
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() };
}
-J
This works like a charm, thanks!
Guys, I’m really liking the human readable uptime strings but have you noticed that just after you program the thing it gives a value that is MASSIVE? For example:
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.
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
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
Is this good according to the new template style too? Working fine on my end, but still want to check.