You are switching devices and want the operating hours of these devices counted? This tutorial gets you covered.
You will get:
- a precise operating hours counter
- a live running counter when device is turned on
You need:
- a persistence service set up (script will get exact times from there)
Limits:
- not so suitable for switch on times < 1 minute as those might be missed
Granularity in minutes can be changed. Make sure to change granularity variable and cron period, both have to match! (e.g. to "0 0/5 * * * ? *"
for 5 minutes granularity)
Tested with openHAB 3.4
items/uptime_demo.items
:
Group GP_Persist_Change
Group GP_Persist_Restore // this is optional, configure if you want your item state to be restored after restart
Switch Item1_Switch "Fan" <fan> (GP_Persist_Change) { expire="3h,command=OFF" }
Switch Item2_Online "Computer [%s]" (GP_Persist_Change) { channel="network:pingdevice:computer:online" }
Number:Time Item1_Hours "Operating Hours [%.1f s]" (GP_Persist_Restore)
Number:Time Item2_Hours "Operating Hours [%.1f s]" (GP_Persist_Restore)
persistence/influxdb.persist
:
Strategies {
default = everyChange
}
Items {
GP_Persist_Change* : strategy = everyChange
}
persistence/mapdb.persist
: (optional)
Strategies {
default = everyChange
}
Items {
GP_Persist_Restore* : strategy = everyChange, restoreOnStartup
}
rules/uptime.rules
:
import java.util.ArrayList // openHAB does not import ArrayList.get() it by default
import org.openhab.core.types.UnDefType // openHAB does not import it by default
val granularity = 1 // minutes; change cron period when you change this value!
rule "Calculate uptime of items"
when
Time cron "0 0/1 * * * ? *"
then
val uptime_items = newArrayList(
newArrayList(Item1_Switch, Item1_Hours)
, newArrayList(Item2_Online, Item2_Hours)
)
val now = ZonedDateTime.now()
for (ArrayList<GenericItem> current_item : uptime_items) {
var item = current_item.get(0)
var target = current_item.get(1)
var uptime = if (target.state instanceof UnDefType) 0 else (target.state as QuantityType<Number>).doubleValue
val uptime_old = uptime
if(item.changedSince(now.minusMinutes(granularity))) {
var item_old = item.previousState()
var duration = Duration.ZERO
if(item.state == ON) {
// item was switched on, take time from last persisted state (= switch on time) to now
duration = Duration.between(item_old.getTimestamp, now)
}
if(item.state == OFF) {
// item was switched off, take time from last cron call to last persisted state (= switch off time)
duration = Duration.between(now.minusMinutes(granularity), item_old.getTimestamp)
}
uptime += duration.getSeconds()
uptime += duration.getNano() / 1.0E9
} else if(item.state == ON) {
uptime += granularity * 60
}
if(uptime_old != uptime) {
target.postUpdate(uptime.doubleValue)
}
}
end