New Rule: Having a moment of what am I doing wrong?

Hello all,

I am trying to write a rule that will change the state of some switches. (Below the full reason if interested.)

Here is the code I am using to debug my rule:

rule "dummyrule"
when
Item Dummy1 changed 
then
logInfo("Logme", "message")
sendCommand(Dummy11.state)
if(Dummy11.state == ON) logError("loggerName", "on")

end

From reading the docs, I believed this should work. I read the help on send command, but I still don’t have my answer. Pretty sure I am just missing one parameter, but not finding it.

Error:

2018-07-20 14:53:15.890 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'dummyrule': 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

PS: Reason for this is power outage. I am trying to write rules that will sync the state of openhabs persistence with some of the devices I have. This is because, after a power outag what happens is that the device is off, but openhab thinks it should be on based on persistence. I am trying to resend the command to the device so it will all be in sync.

What are you sending the command to?

???.sendCommand(Dummy11.state)

That is easy enough. First and foremost you need to have persistence set up with restoreOnStartup on all the relevant Items. Then I recommend putting all the Items you want to synchronize with the previous state in the same Group. I’ll call that Group “Restore”.

rule "Restore Devices to previous states"
when
    System started
then
    // You may need a small Thread::sleep here to make sure persistence is done restoring the states of the Items
    Restore.forEach[ i | i.sendCommand( i.previousState) ]
end

I will try the loop with a group as you stated. Yes, I have mapdb setup and it functions. I noticed this problem when I powercycled just one switch the other day.

On another note, I tried Dummy11.sendCommand(Dummy11.state) and I got an error also. This is what led me to ask the question. It seemed that no matter which way I tried it never worked.

I used an if statement and verified that Dummy11.state had a state and it was on when on and off when off. I will try it with previous state in your loop and give you feedback.

Oh wait, that’s right, you don’t need previousState because the Item has been restored.

Restore.forEach[ i | i.sendCommand( i.state) ]

You can’t sendCommand with NULL so I’d bet that Dummy11 had not yet been restoreOnStartup’d. That is why I added the comment about the Thread::sleep. Unless you checked that the state was ON before the call to sendCommand you are not guaranteed that it wasn’t NULL when you called sendCommand.

Often you can solve a lot of problems like these by calling toString on the state. There may be a problem converting the State object to something the Item expects.

There have also been reports of weird errors at startup time where sometimes OH complains about stuff that clearly exists as not existing. Experiment with a Thread::sleep or better yet a Timer before running the loop to restore the devices to give everything a chance to get loaded and settle down.

1 Like

Rich,

Got it working. I started with your post here: Resend MQTT command to nodemcu(or ESP 8266) after power failure . Thanks this was a great help. Everything worked, until the error popped up!

The error appeared to be due to the sendcommand needing a “toString” on the end. As you stated above sometimes openhab can be picky about the “toString”.

when
    System started
then 
var count = 0
while (Lamp3.state == NULL && count < 20) {
    Thread::sleep(1000)
    count = count + 1
    logInfo("InWhile", "Loop!")
}

if(Lamp3.state == NULL) logInfo("PersistRule", "Waiting for Pesistence to restoreonstartup! (ex:Restore last know values)")
    else 
    {
    //Must Resend command to Insteon switches as they don't stay in last state after power cycle.
    Lamp3.sendCommand(Lamp3.state.toString) //Currently need the .toString or else this command throws and error!
    Lamp4.sendCommand(Lamp4.state.toString) //Currently need the .toString or else this command throws and error!
    logInfo("PersistRule", "Done! Restored Item States after reboot!")
    }
logInfo("PersistRule", "Done!")
end

Still tweaking the rule, I am thinking the if statement should be in the while loop. It does work though for now thats what counts.

To avoid a long Thread::sleep(), it would be better to use a timer instead:

var tSystemStart = null                                       //timer for scheduled restore of devices based on last known state
var count = 0                                                 //counter for schedule (just to be nice)

rule "reload or system start"
when
    System started                                            //will also trigger when rule file is reloaded
then
    if(tSystemStart !== null) tSystemStart.cancel             //if there is already a timer, cancel it
    tSystemStart = createTimer(now.plusSeconds(1), [ |        //create the timer
        if (Lamp3.state != NULL) {                            //is the state not NULL?
            Lamp3.sendCommand(Lamp3.state.toString)           //then restore devices
            Lamp4.sendCommand(Lamp4.state.toString)
            logInfo("systemStart", "Restored Devices!")
            tSystemStart = null
        }
        else {                                                //items aren't restored yet, so
            logInfo("systemStart", "Items not restored yet!")
            count = count + 1                                 //count up
            if (count < 21) {                                 //only try for 20 seconds
                logInfo("systemStart", "Loop! No. {}",count)
                tSystemStart.reschedule(now.plusSeconds(1))  //reschedule the timer
            }
            else {
                logInfo("systemStart", "Waiting for 20 Seconds! Give up now.")
                tSystemStart = null
                count = 0
            }
        }
    ])
end

You could omit the counter, because the timer should not harm the system, in contrast
to while () [ Thread::sleep() }, see

@Udo_Hartmann Thanks!

@Udo_Hartmann I am getting the following error when executing the rule code you posted. I starting reading the timer manual and some examples from the forum. Something (a bracket) might be out of place, I just can’t put my finger on what.

2018-08-05 10:27:55.333 [ERROR] [org.quartz.core.JobRunShell         ] - Job DEFAULT.2018-08-05T10:27:55.259-05:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
  org.eclipse.xtext.xbase.impl.XIfExpressionImpl@5ec44b
} ] threw an unhandled Exception: 
java.lang.reflect.UndeclaredThrowableException: null
	at com.sun.proxy.$Proxy143.apply(Unknown Source) [?:?]
	at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:49) [137:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
Caused by: org.eclipse.smarthome.model.script.engine.ScriptExecutionException: 'reschedule' is not a
 member of 'org.eclipse.smarthome.model.script.internal.actions.TimerImpl';
 line 35, column 17, length 43
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:125) ~[?:?]

The line it is complaing about is this one: tSystemStart.reschedule(now.plusSeconds(1)) //reschedule the timer

I also only get an error if I clear the cache. A normal restart works like a champ.

During system startup there is a known bug that is causing globals and Items to not be recognized. I think it is a timing issue. I’ve seen some errors on my setup complaining about NULL or ON not existing.

Does this error happen every time?

Yes it appears that it happens every restart.

I did not see it when I created the file and the rule executed.

Try touching the rules file a couple of times and see if the error pops up. If not then I’ll bet it is caused by the issue I referred to.

Yes appears to be. I saved the file so it would execute. No errors!

Must be related to the issue you spoke of. Hopefully 2.4 addresses it.