I would like to share my setup for tracking uptime, adapted from the posts here and extended using java specific functionality.
I am using the following for tracking PC uptime (“CPU uptime”) and openHAB uptime. The solution uses java’s ManagementFactory
to access the uptime of the openHAB java process, and systeminfo
addon to access PC uptime (“cpu uptime”). The rules are setup such that they do not rely on persistence, and the values are restored even if items are re-created, e.g. when modifying the items file.
import java.lang.management.ManagementFactory
import java.time.ZonedDateTime
import java.time.Instant
import java.time.ZoneOffset
val formatDurationToText = [ Number millis |
// http://stackoverflow.com/questions/13018550/time-since-ago-library-for-android-java
val Number SECOND_MILLIS = 1000;
val Number MINUTE_MILLIS = 60 * SECOND_MILLIS;
val Number HOUR_MILLIS = 60 * MINUTE_MILLIS;
val Number DAY_MILLIS = 24 * HOUR_MILLIS;
var String tmp;
if (millis < MINUTE_MILLIS) {
tmp = "less than a minute";
} else if (millis < 2 * MINUTE_MILLIS) {
tmp = "couple of minutes";
} else if (millis < 50 * MINUTE_MILLIS) {
tmp = String::format("%.2f", millis / MINUTE_MILLIS) + " minutes";
} else if (millis < 90 * MINUTE_MILLIS) {
tmp = "an hour ago";
} else if (millis < 24 * HOUR_MILLIS) {
tmp = String::format("%.2f", millis / HOUR_MILLIS) + " hours";
} else if (millis < 48 * HOUR_MILLIS) {
tmp = "since yesterday";
} else {
tmp = String::format("%.1f", millis / DAY_MILLIS) + " days";
}
return tmp
]
rule "Openhab Uptime"
when
Time cron "0/10 * * * * ?"
then
val runtime = ManagementFactory::getRuntimeMXBean();
val long startedMillis = runtime.getStartTime()
if(Openhab_Started.state == NULL || Openhab_Started.state == UNDEF) {
Openhab_Started.postUpdate(new DateTimeType(ZonedDateTime.ofInstant(Instant.ofEpochMilli(startedMillis), ZoneOffset.UTC)))
}
var uptimeAsText = formatDurationToText.apply(now.millis - startedMillis)
postUpdate(Openhab_Uptime, uptimeAsText)
end
rule "CPU Uptime readable"
when
Item CPU_Uptime changed or
Time cron "0/10 * * * * ?"
then
if(CPU_Uptime.state != NULL && CPU_Uptime.state != UNDEF) {
// CPU_Uptime is in minutes, convert it to millis
var cpuUptimeMillis = (CPU_Uptime.state as Number).longValue * 60 * 1000
var uptimeAsText = formatDurationToText.apply(cpuUptimeMillis)
postUpdate(CPU_Uptime_Text, uptimeAsText)
} else {
postUpdate(CPU_Uptime_Text, "-")
}
end
items:
DateTime Openhab_Started "openHAB started [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <status>
String Openhab_Uptime "openHAB uptime [%s]" <status>
String CPU_Uptime_Text "Raspi uptime [%s]" <status>
Number CPU_Uptime { channel="systeminfo:computer:systemdata:cpu#uptime" }
EDIT 2023-11-12: I noticed that runtime.getStartTime()
can return the time in local epoch milli… I worked around these issues using uptime:
// We calculate JVM start time using uptime
// runtime.startTime epoch milli can be in UTC millis or local millis, making
// it less convenient
var Instant = Java.type("java.time.Instant");
var startedZoned = ZonedDateTime.ofInstant(
Instant.now().minusMillis(runtime.getUptime()),
ZoneId.systemDefault())
Openhab_Started.postUpdate(new DateTimeType(startedZoned )