Blockly execution stops if a contextual info is undefined

In OH4 some blocks of contextual info (command, newState, oldState) now have a toString already included.
While this is mostly useful it causes a rule to fail with type-errors if the specific contextual info is undefined.

The (I think pretty common) use case is when a rule has different triggers like commands, changeEvents.

I guess this question mainly goes to the marvelous @stefan.hoehn (who put a lot of work to turn blockly in such a great tool for openhab :pray:): Would it be possible to change the contextual blocks so that they don’t fail if evaluated to undefined?

It can be reproduced by a rule with only a contextual block which is triggered manually:

Then the log says

Aww, how nice of you (applause feeds the hunger of the artist ;-)This :heart:)

Did you notice that you have this block?

image

This is how I use it:

yes, I know that one.
But it doesn’t help if a rule is triggered by change and command events because event available is true in both cases.
So I didn’t find a clean solution to evaluate the command and newState values.
My current workaround is to directly search within the ctx-context.


…but admittedly not really beautiful

Based on my experiments, you should be able to use the “contextual info [event type]” to tell the difference between a command and changed trigger. When triggered by a command that will be “ItemCommandEvent” and when triggered by a change it will be “ItemStateChangedEvent”. Depending on the event, there might be more information in ‘get context attribute “event”’. The full list of ways the rule is triggered and the values of the event type include:

Trigger event type attribute event
received command ItemCommandEvent undefined
received update ItemStateUpdatedEvent undefined
changed ItemStateChangedEvent undefined
Time TimerEvent undefined
System event (e.g. runlevel) undefined undefined
Manually run ExecutionEvent Execution triggered by manual
Run from another rule ExecutionEvent Execution triggered by runRuleAction

Further information is available in ‘get context attribute “event”’

This isn’t arguing for or against anything proposed on this thread. I just wanted to make sure that all were aware that you can see what sort of event triggered the rule and then take different actions as necessary.

oh yes, you’re right. I cannot tell why I missed that.

Maybe (as my excuse) failing with a stacktrace if one uses the contextual info block too carelessly might not be very beautiful.
But of course checking the type before using the state or the command is fine and works as a solution. many thanks

Hi Rich,

not directly related to this post, but if you trigger a rule from another rule by JS directly (not by blockly) there is no context available. Both

  console.log(ctx["event"].toString());
  console.log(ctx["event"].type);

is undefined.
Am I doing something wrong or is it a bug?

No, that’s Blockly only I think. I didn’t try it in JS Scripting. I’m not sure ctx even exists outside of Blockly. I’m pretty certain it doesn’t in file based JS Scripting rules for sure.

Just FYI, I also tried

  console.log(this.event.toString());
  console.log(this.event.type);

and

  console.log(event.toString());
  console.log(event.type);

with the same result on GUI-based rules. Doesn‘t seem to be consistent if rule based triggers have no context.
Sure, as a workaround one might pass a variable to the rule and check for existence by

if (typeof myVariable !== 'undefined') {}

ctx does provide results in JS scripting for other events though.

What version of OH are you testing with? There have been some changes in what gets populated in event since 4.0 release I think.

In my experiments, the called rule always has event.type defined and it’s always ExecutionEvent. I tested using Blockly above and JS Scripting just now.

I am on 4.1.0.M3
I double checked with

utils.dumpObject(this.event);

This also results in

Dumping object
-   typeof obj = undefined
-   Java.isJavaObject(obj) = false
-   Java.isType(obj) = false
-   value = undefined

How do you call the rule? My command is

rules.runRule('e9449541f0');

That might be the difference. I just use the “Run Rule” action in the UI, not a script.