Problem with rules if startup-trigger is used?

I discovered strange behavior (bug?) with UI-rules that have a startup-trigger.
I first wanted to discuss it here before raising an issue.

Rules with a startup trigger are (unlike all other rules) executed if they are saved (During this run they get a strange context (“start level=40”, no event-object…)

This can be easily reproduced with this simple rule:

configuration: {}
triggers:
  - id: "1"
    configuration:
      startlevel: 100
    type: core.SystemStartlevelTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: |-
        console.info(ctx);
        console.info((event !== undefined));
    type: script.ScriptAction

This throws the following errors immediately when the rule is saved.

2024-02-24 07:36:14.148 [INFO ] [g.openhab.automation.script.ui.0Test] - {startlevel=40, ruleUID=0Test}
2024-02-24 07:36:14.149 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: ReferenceError: "event" is not defined
	at <js>.:program(<eval>:2) ~[?:?]

...   [ then long java stack-trace ] 

I thought the expected behavior is that it is not executed at all while being saved (like all other rules).
This can confuse many users because every Blockly rule that gets triggered during startup can throw those errors although the rule is completely correct.

event wasn’t passed to the startup triggers until recent 4.2 snapshots
So to get the start level, simply use startlevel in your rule, at least in dsl and jruby. Not sure how it’s done in jsscripting.

AFAIK, this is the expected behaviour (i.e. startup trigger gets executed upon saving). There have been a few discussions about this which I haven’t been following closely.

thank you. So event handling is possible with 4.2. That’s good news.

In JavaScript you can return the startlevel with console.info(ctx[‘startlevel’]).

Btw: It returns 40 when you save a rule. Lower than the startlevel of 100 after a complete system startup.

This is how it’s done in the core code. Primarily because you may have multiple triggers, and rather than running the rule multiple times, it just runs it once and you’ll always get startlevel 40 whenever your script is activated / loaded well after the startlevel had been reached.

You can use this to your advantage and detect such case in your script.

pseudocode (untested):

// rule with startlevel triggers > 40, e.g.:
rule "xxx" 
when
  system reached startlevel 100
then
  switch(startlevel) {
    case 40: // our script just got reloaded, but openhab has been running for a while
      break
    case 100: // openhab just started
  }
end

I’m not sure if this is an officially documented behaviour though, so perhaps don’t rely on that :slight_smile: