I am scratching my head for this. Here’s an excerpt of the rule:
val baseName = "Hallway" // Simplified for this excerpt
var itemColor = null
try {
itemColor = ScriptServiceUtil.getItemRegistry.getItem(baseName + "_Light_Color")
} catch (Throwable t) {} // is there a better way?
if (itemColor !== null) {
itemColor.sendCommand("03030303") // <<=== This is where the error occurred
}
The above code when executed, will trigger this error message:
16:02:13.876 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Night Light PIR': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(java.lang.String,java.lang.String) on instance: null
Why is the instance null when it passed the if (itemColor !== null) ?
A separate question: Is there a way to check for the existence of an item without resorting to try / except to catch the exception?
As Crispin indicated, if you initialize a variable to null, you have to provide the type because they’re has nothing to tell the rules engine what type it is.
You need to provide more context but I suspect the answer in Rules DSL is no. But I don’t know what ScriptServiceUtil.getItemRegistry.getItem(itemName) returns when the item by that name doesn’t exist. Maybe it just returns null. See Design Pattern: Associated Items for details.
There is a alternative to “find Item by name string”. Before ScriptServiceUtil, we used to put Items in Groups and search Group by name. If there is no such member, you get a tidy null result and no error, and can deal with that in code
I still use this method where some Item may or may not have a “helper” or “associated” companion Item
EDIT - knew there was a previous, found it
I do not think that is a sensible thing to send to a Color Item, shouldn’t there be commas? It will fail with null components when it tries to parse the string?
It would throw an exception. That’s why I enclosed it in a try/catch
What would be the type for a String Item?
The “Color” item is actually just a String type item. It expects a tring in the form of 8 hexadecimal digits, e.g. FFFFFFFF for RGBW values. This is the Thing definition for it:
Is there a better way to represent this particular color item?
Thanks to @rossko57 and @CDriver, I think the solution, for now, is using the group find method, although to me it feels a bit dodgy. It would be nicer to have another function, maybe ScriptServiceUtil.getItemRegistry.findItem() ?
It’s perfectly reliable. It does depend on you assigning things to the correct Group(s) as part of your design.
EDIT - I’ve never compared performance, it might be interesting; getItemRegistry must rummage through all Items, though there may be speed-up hashing in bowels of system
Group findFirst in theory need only look through a smaller set of Items, but likely less optimized.
I think for now, I’m happy with just using try/catch and if the variable needed to be outside the try/catch block, I’d give it an explicit type. If it is only needed inside the try/catch then just create/assign it inside the block.
Knowing getItems() and the group findFirst would come in handy though, thanks!