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
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.
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
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.
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
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.