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