Java Runtime Environment: openjdk version “1.8.0_152”
openHAB version: openHAB 2.2.0-1 (Release Build)
I have installed the GPIO binding using PaperUI and some rules written for my Switch items, which worked quite well - all in the form
MyItem.sendCommand(OtherItem.state)
Yesterday I installed Network binding using PaperUI, and suddenly GPIO binding got uninstalled automatically. I re-installed it, and everything was fine, rules using GPIO and Network Switch items worked.
Today I restarted my OpenHAB computer, and all my rules stopped working with this error message:
Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.Number) on instance: null
The benefit of using Objects over primitives is apparent through the following type conversions that are automatically invoked by Object as the context requires. Using the method MyTimes.sendCommand() that is owned by MyItem will use the sendCommand method that is suitable to make the necessary type conversions.
@rlkoshak
Hm, I don’t use it on both, I will keep that in mind for startup problems. My problem also happens when both items are not NULL - I added some debug code to the rule and here you go:
rule "Example Rule"
when
Item OtherItem changed or
Item VT_DebugTrigger changed to ON
then
logInfo("debug.rules", "MyItem.state = " + MyItem.state)
logInfo("debug.rules", "OtherItem.state = " + OtherItem.state)
MyItem.sendCommand(OtherItem.state)
end
Log output:
==> /var/log/openhab2/events.log <==
2018-02-10 19:24:46.284 [ome.event.ItemCommandEvent] - Item 'VT_DebugTrigger' received command ON
2018-02-10 19:24:46.303 [vent.ItemStateChangedEvent] - VT_DebugTrigger changed from OFF to ON
==> /var/log/openhab2/openhab.log <==
2018-02-10 19:24:46.709 [INFO ] [smarthome.model.script.debug.rules] - MyItem.state = ON
2018-02-10 19:24:46.718 [INFO ] [smarthome.model.script.debug.rules] - OtherItem.state = ON
2018-02-10 19:24:46.723 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Example Rule': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.Number) on instance: null
I just stumbled across the same problem. And I’m sure it has nothing to do with items that aren’t initialized. Simple example:
rule "PIR Actions"
when
Item Tasmota_PIR received update
then
Tasmota_Display.sendCommand(ON) // works
Tasmota_Display.sendCommand(Tasmota_PIR.state) // does not work
Tasmota_Display.sendCommand(Tasmota_PIR.state.toString) // works
end
Tasmota_Display is initialized because the first sendCommand() works. Tasmota_PIR must be initialized because it just received an update.
The second sendCommand() throws this error:
Rule 'PIR Actions': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.String) on instance: null
rule "PIR Actions"
when
Item Tasmota_PIR received update
then
logInfo("debug", "before")
if (Tasmota_PIR.state == NULL) {
logInfo("debug", "Tasmota_PIR.state is NULL")
} else {
logInfo("debug", "Tasmota_PIR.state is not NULL")
}
logInfo("debug", "Tasmota_PIR.toString is " + Tasmota_PIR.state.toString)
if (Tasmota_Power.state == NULL) {
logInfo("debug", "Tasmota_Power.state is NULL")
} else {
logInfo("debug", "Tasmota_Power.state is not NULL")
}
logInfo("debug", "Tasmota_Power.toString is " + Tasmota_Power.state.toString)
Tasmota_Power.sendCommand(Tasmota_PIR.state.toString) // does not work without .toString
logInfo("debug", "after")
if (Tasmota_PIR.state == NULL) {
logInfo("debug", "Tasmota_PIR.state is NULL")
} else {
logInfo("debug", "Tasmota_PIR.state is not NULL")
}
logInfo("debug", "Tasmota_PIR.toString is " + Tasmota_PIR.state.toString)
if (Tasmota_Power.state == NULL) {
logInfo("debug", "Tasmota_Power.state is NULL")
} else {
logInfo("debug", "Tasmota_Power.state is not NULL")
}
logInfo("debug", "Tasmota_Power.toString is " + Tasmota_Power.state.toString)
end
The output in the log:
2019-04-02 20:25:17.191 [INFO ] [eclipse.smarthome.model.script.debug] - before
2019-04-02 20:25:17.195 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.state is not NULL
2019-04-02 20:25:17.199 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.toString is ON
2019-04-02 20:25:17.202 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.state is not NULL
2019-04-02 20:25:17.205 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.toString is OFF
2019-04-02 20:25:17.209 [INFO ] [eclipse.smarthome.model.script.debug] - after
2019-04-02 20:25:17.214 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.state is not NULL
2019-04-02 20:25:17.219 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.toString is ON
2019-04-02 20:25:17.224 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.state is not NULL
2019-04-02 20:25:17.236 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.toString is ON
2019-04-02 20:25:20.230 [INFO ] [eclipse.smarthome.model.script.debug] - before
2019-04-02 20:25:20.237 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.state is not NULL
2019-04-02 20:25:20.245 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.toString is OFF
2019-04-02 20:25:20.251 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.state is not NULL
2019-04-02 20:25:20.258 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.toString is ON
2019-04-02 20:25:20.266 [INFO ] [eclipse.smarthome.model.script.debug] - after
2019-04-02 20:25:20.274 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.state is not NULL
2019-04-02 20:25:20.287 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_PIR.toString is OFF
2019-04-02 20:25:20.295 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.state is not NULL
2019-04-02 20:25:20.302 [INFO ] [eclipse.smarthome.model.script.debug] - Tasmota_Power.toString is OFF
And finally when I remove the “.toString”:
2019-04-02 20:29:04.141 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'PIR Actions': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.String) on instance: null
At this point we can do the easy thing or the hard thing. The easy thing is to just continue to use .toString. You know that works and when type errors like this occur, using .toString is usually the most expedient solution.
The hard thing is to start to figure out why it isn’t able to convert the State to an OnOffType automatically the way it is supposed to. The first thing try would be to cast the state to an OnOffType.
Tasmota_Power.sendCommand(Tasmota_PIR.state as OnOffType)
What I just remembered: I had the same problem with two items of type “String”. Using .toString solved that, too. So it looks like it’s a general problem to copy the contents of one item to another item of the same type.
It’s a problem from the underlying language that the Rules DSL is built upon. It’s a loosely typed language (i.e. the types of Objects are not determined until runtime instead of compile time) but it’s not all that good at figuring out the type in some cases without additional hints. Supplying the as OnOffType gave it the hint it needed to treat the state properly.
When you use .toString, you are using a different code path that parses the String passed to it instead of trying to use the Object as is. This is why .toString will almost always solve this error in a postUpdate or sendCommand.
I usually see this error more with Numbers. I think this is the first I’ve seen it from an enum type like OnOffType.
Another place you will see this error is when trying to log it. For example:
logInfo("Test", Tasmota_PIR.state)
will probably generate a similar error. The language isn’t smart enough to know you want the state to be a String.
logInfo("Test", "State = " + Tasmota_PIR.state)
will work because we gave the language the hint that we want the state as a String so it will call .toString for you.