for this I use a generic function:
import java.util.HashMap
var Timer tAlarmanlageStartTimer = null
var Timer tSireneTimer = null
var Timer tshadowTimer = null
var Timer tProxyTimer = null
var HashMap<String, Timer> tRandomTimers = newHashMap()
var HashMap<String, Timer> tTimersWithCancel = newHashMap()
var HashMap<String, Timer> tEscalationTimer = newHashMap()
var HashMap<String, Integer> iEscalationTimer = newHashMap()
var HashMap<String, String> stEscalationTimer = newHashMap()
// this function is used to wait for a random interval and then set the item to given state
// GenericItem = item
// Hashmap of the Timer
// Numberitem with the maximum of delay
// String with new state after interval is reached
val Procedures$Procedure4<GenericItem, HashMap<String, Timer>, NumberItem, String> startRandomTimerWithAction= [ relatedItem, tRandomTimers, nuRandomTimerTime, newitemstate |
var int randomTime
// if the times still exists, delete it first, no reschedule implemented
if(tRandomTimers.get(relatedItem.name) !== null)
{
tRandomTimers.get(relatedItem.name).cancel()
tRandomTimers.put(relatedItem.name, null)
tRandomTimers.remove(relatedItem.name)
}
// if no timer in needed because interval <= 30
if((nuRandomTimerTime.state as Number).intValue <= 30)
{
logInfo("Logger", "RandomTimer for Item " + relatedItem.label + " not needed. Action " + newitemstate.toString + " executed.")
relatedItem.sendCommand(newitemstate)
return;
}
// ensure that random value is greater then 0
randomTime = (new java.util.Random).nextInt((nuRandomTimerTime.state as Number).intValue) + 5
// wait a little bit, if two timers end on the same time not all of them are execute the commands
Thread::sleep(100)
// create the timer and do the action at the end of the timer
logInfo("Logger", "RandomTimer for Item " + relatedItem.label + " started with " + randomTime + " sec.")
tRandomTimers.put(relatedItem.name, createTimer(now.plusSeconds(randomTime))
[ |
tRandomTimers.get(relatedItem.name).cancel()
tRandomTimers.put(relatedItem.name, null)
tRandomTimers.remove(relatedItem.name)
logInfo("Logger", "RandomTimer for Item " + relatedItem.label + " reached end. Action " + newitemstate.toString + " executed.")
relatedItem.sendCommand(newitemstate)
])
]
A rollershutter item (RolloRuntergefahren) is triggered by the astro binding, that know the rollershutter should go up or down.
In addition for every rollershutter there is a switch to exclude from automatic up or down (SW_RollerShutter_01_AutoMode, …)
tRandomTimers is a number item for the maximum delay for the random in sec.
RS_RollerShutter_0 is the rollershutter item itself.
rule "RolloRuntergefahren"
when
Item RolloRuntergefahren changed from OFF to ON
then
if(SW_RollerShutter_01_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_01, tRandomTimers, nuRandomValueRollerShutter, "25")}
if(SW_RollerShutter_02_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_02, tRandomTimers, nuRandomValueRollerShutter, "30")}
if(SW_RollerShutter_03_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_03, tRandomTimers, nuRandomValueRollerShutter, "25")}
if(SW_RollerShutter_04_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_04, tRandomTimers, nuRandomValueRollerShutter, "0")}
if(SW_RollerShutter_05_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_05, tRandomTimers, nuRandomValueRollerShutter, "0")}
if(SW_RollerShutter_06_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_06, tRandomTimers, nuRandomValueRollerShutter, "25")}
if(SW_RollerShutter_07_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_07, tRandomTimers, nuRandomValueRollerShutter, "25")}
if(SW_RollerShutter_08_AutoMode.state == ON){startRandomTimerWithAction.apply(RS_RollerShutter_08, tRandomTimers, nuRandomValueRollerShutter, "25")}
end
The function is generic and can be used for every random need.