It gets more complicated but you could use a Design Pattern: Looping Timers to calculate the time ON instead of persistence.
rule "MySwitch turned ON"
when
Item MySwitch changed to ON
then
// Do nothing if this happens. It means the switch was turned OFF and then ON again
// in less than a second.
if(sharedCache.get('MySwitchTimer') !== null) {
logDebug('MySwitch', 'Timer already exists! Ignoring as the timer is already running.')
return;
}
privateCache.put('MySwitch_timer', createTimer(now.plusSeconds(1), [ |
val state = MySwitch_OnTime.state as QuantityType
// Initialize the count Item if it's NULL or UNDEF
if(state == NULL || state == UNDEF) {
MySwitch_OnTime.postUpdate('1 s')
}
// Add one second to the total time
else {
MySwitch_OnTime.postUpdate(state.plus('1 s'))
}
// Reschedule if it's still ON, exit the timer if not
if(state == ON) {
privateCache.get('MySwitch_timer').reschedule(now.plusSeconds(1)
}
else {
privateCache.put('MySwitch_timer', null)
}
]))
end
This will be accurate to within a second. Additional book keeping and an another rule would be required to track to the millisecond or nanosecond. You’ll need to use the sharedCache for the second rule to see the Timer though.
Instead of using a global variable, this uses the privateCache which will cancel the timer for us when the rule is unloaded instead of leaving it orphaned to create an exception in the logs later. We create a timer for one second from now which adds one to the Time Item and if the Switch is still ON it reschedules the timer for another second. Once the Switch is no longer ON the loop will exit.