Have you actually seen this happen? It’s not supposed to and deserves an issue if you’ve seen it happen before. Each runlevel only occurs once per startup.
Note, the code as written is Nashorn style JS, not GraalVM style JS with the helper library.
Written with the newer JS style the code would be something like
// Don't import stuff from Java, you don't need to, use the helper library instead
if(items.OH_SystemLevel.state != "ok") { // .state is already a String
setTimeout( () => items.OH_SystemLevel.postUpdate("ok"), time.toZDT('PT2M').getMillisFromNow()); // you throw away the handle to the timer anyway so just use a timeout
}
Though I’d move the test of OH_SystemLevel.state to be a rule Condition and avoid scheduling a new Timer if there is one already scheduled.
configuration: {}
triggers:
- id: "1"
configuration:
startlevel: 70
type: core.SystemStartlevelTrigger
conditions:
- inputs: {}
id: "2"
configuration:
itemName: OH_Systemlevel.state
state: ok
operator: !=
type: core.ItemStateCondition
actions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >-
var timer = cache.private.get('timer');
if(timer === null) {
cache.private.put(actions.scriptExecution.createTimer(time.toZDT('PT2M'), () => {
items.OH_Systemlevel.postUpdate('ok');
});
}
else {
timer.reschedule(time.toZDT('PT2M'));
}
type: script.ScriptAction
But when you look at the second rule, you trigger it based on the Item changing. If runlevel 70 occurred twice for some reason, even without all the logic above the Item would only change the one time (that’s why your current implementation works even though if runlevel 70 were reached twice before your 2 minute timer goes off you end up with two timers and the Item gets update to “ok” twice). So throw out all the checks and stuff and it becomes a couple lines of code.
configuration: {}
triggers:
- id: "1"
configuration:
startlevel: 70
type: core.SystemStartlevelTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >-
var timer = cache.private.get('timer');
if(timer === null) {
cache.private.put(actions.scriptExecution.createTimer(time.toZDT('PT2M'), () => {
items.OH_Systemlevel.postUpdate('ok');
});
}
type: script.ScriptAction
You need to exclude OH_Systemlevel
from restoreOnStartup to achieve this.
Why not a Switch or Contact? It’s used as a binary flag after all.
You already know that runlevel 70 passed at least two minutes ago, so why do you need to to test for this again here? Also, what if it’s runlevel100? Do you not need to update that Item in that case?