[SOLVED] "triggeringItem" null for system started

How do I detect which trigger fired the rule below? When System started fires, triggeringItem is null and the triggeringItem.name (getName()) raises an exception.

rule "Set myVisibility"
when
    System started or
    Item plug_reachable changed
then
    if (triggeringItem.name == "plug_reachable")
        myVisibility.postUpdate(triggeringItem.state)
end

Not sure I understand what you want to achieve.
When the system starts your item is null, so why would you need to trigger your rule when the system starts. What exactly is the rule supposed to do then.
But in case I do not get it, would it help if you add:

then
    if (triggeringItem !== null && triggeringItem.name == "plug_reachable")

DSL will exit the if clause when your item is null and not even look at the second clause (EDIT: this statement may not be true, see below post #6). So when the system starts your rule will simply not do anything, hence see above.

EDIT: post edited as per #8 (read: != and needs to read !==), my thanks to @vzorglub

This is what I needed. I had tried the null check as the second item (so of course the rule was still blowing up). It did not occur to me to swap the clauses. So close!

Thanks.

Mike

P.S. The logic I put in the post was simplified and not my actual rule. I just wanted to put a core of what I was trying to do for explanation purposes.

I tried it with the null check first - it still fails. It looks like I have to split the clause into two separate if statements.

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Set myVisibility': cannot invoke method public abstract java.lang.String org.eclipse.smarthome.core.items.Item.getName() on null

Mmmhh, sorry not sure, although I have to admit that I am always getting confused between NULL and null, maybe try the other one

NULL, null, ==, !==, 
 null checking always gets me too.

I even tried parentheses pairing to see if it was confused. Nothing but splitting it worked. Using lowercase null in a separate IF clause worked. Not as pretty, but works :wink:

2 Likes

I believe rules DSL should do the “lazy evaluation” thing, i.e. not evaluate the second part of an AND if the first part is not true.
Maybe that doesn’t always apply - I seemed to get some results in OH1 where null==test would work and test==null would not, but that has changed for OH2 Im sure.

NULL is an item state specific to the rule DSL
null is java for a variable or object that is not instanciated

You check for NULL then same as you check others states == or !=
You check for null with === or !==

1 Like

I would have expected the same. Clearly that isn’t the case. It’s good to know.

Absolutely not. Just because we (most of us) read from left to right doesn’t mean any logic will do the same. Never ever expect any parts of an expression to be not evaluated because of other parts of the expression.

You never know how any optimizer mixes the expression when it is evaluated.

Feature request? Have a means to programmatically detect what triggered a rule when things like System or Time are the trigger.

I don’t think that makes much sense. Better separate your logic and use separate rules. You do not need logic concerning a triggering item in system started or a cron rule.

Maybe I’m being dense here, but it seems to me that the following test should be sufficient unless there is a bug in the framework that results in triggeringItem being set to any value other than null when a change of plug_reachable's state was not the reason your rule was triggered, i.e., when the System started event triggered your rule.

if (triggeringItem !== null)
    myVisibility.postUpdate(triggeringItem.state)

What rossko57 describes is the standard behavior of many programming languages (most? see the Short Circuit column here Short-circuit evaluation - Wikipedia), including Java. Since Rules DSL runs on top of Java it is a reasonable assumption that it would use Short Circuit evaluation as well. The fact that it doesn’t means that the people who created Xtend went out of their way to change how boolean expressions are evaluated and given that every major language I can think of uses short circuit evaluation I would agree, Xtend should as well.

And Java has a definite order of operations and both && and || are left-associative, meaning that the left operand is evaluated first. The optimizer should not be changing this. Again, this is standard for most languages and it is reasonable to assume that Xtend behave the same as well. If it doesn’t then this is another place where the Xtend developers went out of their way to make it work differently.

But I will admit, it has been a long time since I’ve done a deep dive of this sort into Java and unfortunately Xtend does not document this. Plus I don’t know what ESH/OH has changed in the language that might impact this behavior as well. So thinks may have changed. But that would be unfortunately if it has changed because, as Java at least is currently documented, we CAN rely on the operations taking place left to right and as soon as the an operand is evaluated that proves the expression to be false it stops evaluating operands.

That should work and I was about to write that. The problem with the order of evaluating the operands goes away if you only have the one. :smiley:

OK. But in this case the equality operator is analyzed before the and operator. So, the exception happens before the rule engine even knows, it could use this lazy stuff.

Scott,

I simplified my rule for posting the question. I actually have more than one Item besides the System started clause in my when section of the rule. Thus, the key was that if it wasn’t null, then it had to be one of my items and I could then test triggeringItem. I’d tried to put the triggeringItem and the null check in the same IF clause
 but I ended up having to break the check into separate IF statements.

Mike

Michael,

That makes sense. So, essentially you first check if the source of the trigger was the System start event or one of the item triggers, then with the information that System start was not the source of the trigger, you can safely check the name of the triggering source.

I would like to note that this is a good example of there never being too much information you can provide when asking a question here.

Glad you solved your issue. I think the ensuing discussion was good.

1 Like

That’s a pretty definitive statement. You are saying that one ought to have two separate rules for Time or System start. And, if the restart occurs during the “cron” time window, it’s OK to have each rule fire separately? And if the desired effect is to ensure that only one event is processed, then the rule ought to have the logic in it to prevent the two from executing separately.

Or, you have an ‘OR’ in the when of ONE rule for either situation (and you can test for which of the two, if needed). I’m always looking at this from a lay person’s point of view (i.e., me) wanting to implement a HOME automation hub
 even if one doesn’t have a CS degree or a certificate in xTend coding (i.e., me). Having a “simple” test for what triggered a rule would simplify things.

Mike

I agree. It’s just that I try to make my inquiries succinct to avoid wasting everyone’s time (yet I end up doing the opposite!). I try to be as unambiguous in the post as possible. Sometimes I’m more successful than others :wink:

Cheers!

Mike

Is this thread solved?