openHAB 2.4.0~M4-1 - Could not invoke method: org.eclipse.smarthome.core.library.items.NumberItem.setState(org.eclipse.smarthome.core.types.State) on instance

Hardware:

  • Raspberry Pi 3 Model B version 1.2 (ARMv8, with 1GB RAM, and 64 GB microSD card)
  • ZMEUUZB - ZWave.Me USB Z-Wave dongle
  • ZOOZ ZEN15 Power Switch
  • Insteon 2413U PLM
  • Many Insteon switches

OS: Raspbian 9 (Stretch)
Java Runtime Environment: java version “1.8.0_181”, Java™ SE Runtime Environment (build 1.8.0_181-b13), Java HotSpot™ Client VM (build 25.181-b13, mixed mode)
openHAB version: 2.4.0~M4-1 with openhab2-addons 2.4.0~M4-1

Hello Community,

I’m receiving the following error in my openhab.log file. What’s causing it, and how do I fix it?

2018-10-19 23:26:00.417 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Washing Machine State': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.library.items.NumberItem.setState(org.eclipse.smarthome.core.types.State) on instance: zwave_washing_machine_meter_watts (Type=NumberItem, State=130.893, Label=Electric Power Consumption, Category=Energy)

Events.log shows this for the above time.

2018-10-19 23:26:00.411 [vent.ItemStateChangedEvent] - zwave_washing_machine_meter_watts changed from 137.796 to 130.893

``

My items file is as follows


```csv
Number Washing_Machine_State "Washing Machine State [%d]"

My rules file is as follows

mport java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

var org.joda.time.DateTime whenStarted = null
var Lock lock = new ReentrantLock()

val Number WASHING_MACHINE_STATE_OFF = 0
val Number WASHING_MACHINE_STATE_ON = 1

rule "Washing Machine State"
when
    Item zwave_washing_machine_meter_watts changed
then
    if (zwave_washing_machine_meter_watts.state = 0) Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_OFF)
    if (zwave_washing_machine_meter_watts.state > 0) Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_ON)
end

Regards,
Burzin

then
    if (zwave_washing_machine_meter_watts.state == 0) Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_OFF)
    if (zwave_washing_machine_meter_watts.state > 0) Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_ON)
end

You need to use == to compare equality, = tries to assign a value to zwave_washing_machine_meter_watts.state.

Thanks @pacive.

That was indeed the problem. I am however running into another blocker.

Basically, I’m trying to write a rule to notify me when the washing machine is done. What I want to do is set var Washing_Machine_Time_Start once. Instead, the every time the rule fires, it increments var Washing_Machine_Time_Start. Is there a way around this or do I need to use persistence. I’ve read: Washing Machine State Machine. However, I can’t use the bouncy workaround as the washing machine is too bouncy.

var org.joda.time.DateTime Washing_Machine_Time_Start = null
val Number WASHING_MACHINE_STATE_OFF = 0
val Number WASHING_MACHINE_STATE_ON = 1

rule "Washing Machine State"
when
    Item zwave_washing_machine_meter_watts changed
then
    if (zwave_washing_machine_meter_watts.state == 0) {
        Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_OFF)
    }
    if (zwave_washing_machine_meter_watts.state > 0) {
        Washing_Machine_State.postUpdate(WASHING_MACHINE_STATE_ON)
    }
end


rule "Check Washing Machine and Increment Runtime"
when
    Time cron "0 * * ? * *"  // Every minute
then
    logInfo("Testing", "Check Washing Machine and Increment Runtime")
    // Check if washing machine is running
    if (Washing_Machine_State.state == WASHING_MACHINE_STATE_ON && Washing_Machine_Time_Start === null) {
        var Washing_Machine_Time_Start = now().getMillis()
        logInfo("Testing", "Check Washing Machine and Increment Runtime - Washing Machine Started & fresh start " + Washing_Machine_Time_Start.toString())
    }
    // Increment Runtimes
    while (Washing_Machine_State.state == WASHING_MACHINE_STATE_ON && Washing_Machine_Time_Start !== null) {
        var Washing_Machine_Time_Now = now().getMillis()
        var Washing_Machine_Runtime_MSec = Washing_Machine_Time_Now - Washing_Machine_Time_Start
        var double Washing_Machine_Runtime_Minutes = Washing_Machine_Runtime_MSec/60000
        Washing_Machine_Runtime_Minutes.postUpdate(Washing_Machine_Runtime_Minutes)
    }
end

Regards,
Burzin

Don’t declare another new Washing_Machine_Time_Start inside the rule with var.

Also, you are running a rule every minute, that starts a while-loop which runs until the washing machine is finished. You will run out of execution threads very fast. It’s really bad practice to use while-loops in rules, but since the rule runs every minute anyway, you should be able to change the while to if.

Hi @pacive,

You’ve pre-empted my next question. Although I have some clean up and testing to do, I noticed that a logging statement in the body of the while loop, logged on a millisecond basis, instead of once a minute as I expected. Why is this?

logInfo(“Testing”, “Check Washing Machine and Increment Runtime - Total time now - " + Washing_Machine_Runtime_Minutes.toString() + " minutes”)

rule "Check Washing Machine and Increment Runtime"
when
    Time cron "0 * * ? * *"  // Every minute
then
    logInfo("Testing", "Check Washing Machine and Increment Runtime")
    // Check if washing machine is running
    if (Washing_Machine_State.state == WASHING_MACHINE_STATE_ON && Washing_Machine_Time_Start == 0) {
        Washing_Machine_Time_Start = now().getMillis()
        // logInfo("Testing", "Check Washing Machine and Increment Runtime - Washing Machine Started & fresh start " + Washing_Machine_Time_Start.toString())
    }
    // Increment Runtimes
    while (Washing_Machine_State.state == WASHING_MACHINE_STATE_ON && Washing_Machine_Time_Start > 0) {
        Washing_Machine_Time_Now = now().getMillis()
        Washing_Machine_Runtime_Msec = Washing_Machine_Time_Now - Washing_Machine_Time_Start
        Washing_Machine_Runtime_Minutes = Washing_Machine_Runtime_Msec/60000
        // Washing_Machine_Runtime_Minutes.postUpdate(Washing_Machine_Runtime_Minutes)
        // logInfo("Testing", "Check Washing Machine and Increment Runtime - Total time now - " + Washing_Machine_Runtime_Minutes.toString() + " minutes")
    }
end

Regards,
Burzin

Because a while loop just runs over and over again as long as the condition is still true. Change it to an if-statement and it will only run once every time the rule runs.