Repeat in rule (loop)

Hi,

I have TCP binding for TCP/RS485 converter, where the serial device is relay board for lights. I have to ask with commnad and then have a reply with status. I am creating a rule, to ask all coils in relay sheduled with cron. It works, but I think it should be done by better way. There is my rule:

when

 Time cron "*/15 * * * * ?"

then
sendCommand(svdot01, “ON”)
Thread::sleep(1000)
svoblus.postUpdate(if(svdot01.state == ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot02, “ON”)
svobbod.postUpdate(if(svdot02.state == ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot03, “ON”)
svobled.postUpdate(if(svdot03.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot04, “ON”)
svsch.postUpdate(if(svdot04.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot05, “ON”)
svvch.postUpdate(if(svdot05.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot06, “ON”)
svloz.postUpdate(if(svdot06.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot07, “ON”)
svpolus.postUpdate(if(svdot07.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot08, “ON”)
svpohve.postUpdate(if(svdot08.state==ON) ON else OFF)

end

Is possible in openhab, before end somethink like “repeat” or go to some line? I mean something like:

when

System started
//line 03
then
sendCommand(svdot01, “ON”)
Thread::sleep(1000)
svoblus.postUpdate(if(svdot01.state == ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot02, “ON”)
svobbod.postUpdate(if(svdot02.state == ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot03, “ON”)
svobled.postUpdate(if(svdot03.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot04, “ON”)
svsch.postUpdate(if(svdot04.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot05, “ON”)
svvch.postUpdate(if(svdot05.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot06, “ON”)
svloz.postUpdate(if(svdot06.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot07, “ON”)
svpolus.postUpdate(if(svdot07.state==ON) ON else OFF)

then
Thread::sleep(1000)
sendCommand(svdot08, “ON”)
svpohve.postUpdate(if(svdot08.state==ON) ON else OFF)

GOTO line 03

end

Any ideas? Thank you.

It really helps with reading and understanding code to use code fences in forum postings. This will add some syntax highlighting and preserve your indentation.

```
your code goes here
```

Some comments and questions:

  • Does this rule actually work as written? I didn’t know that you could have more than one then clause for a single rule. The docs imply that this should be invalid and I’ve never see an example like this. Typically there is only one then clause per rule. If it works, does it execute each then at the same time or does it execute them one after the other? If it is one after the other then the then clauses add nothing except to make the rule more difficult to read. Or are you showing all of the then clauses as a shorthand for a bunch of different rules.

  • If I understand correctly correctly the flow of information is 1) send a message to an Item, wait for a short period of time, then send the new state to a different Item. Does the serial device send anything back in the meantime?

Yes, you can use a while loop or for loop. However, this will result in a rule that essentially runs forever without ever exiting. This is a bad design pattern in openHAB because it will permanently tie up a thread in the execution thread pool. So your cron triggered rule is actually the correct way to execute this rule periodically.

Now there are a ton of things that can be done to make this rule simpler.

  • If the relay board send information back after you send the command, post the update in response to that command rather than just waiting. If not, then the wait is good.
  • Do you need to send all of the commands at the same time or do you need to send them in serial. Not having ever seen this multiple then clause syntax I don’t know how this runs. Assuming that they run in sequence you can make this much simpler using a couple of Groups and a different naming scheme.
  • You can just send the Item’s state in the post update. postUpdate(svdot01.state) is equivalent to postUpdate(if(svdot01.state==ON) ON else OFF)

So

  1. Put all your svdot0x Items into a group. I’ll call it “gGroup1”. Put all your Items that you postUpdate to into another Group which I’ll call “gGroup2”
  2. Rename the Items in gGroup2 such that you can recreate their name from the matching Item in gGroup1. For example, rename svoblus to scdot01_update.
  3. Keep the cron triggered rule
  4. Use a forEach loop through the members of gGroup1 to send the commands, wait, and post update.

This collapses the rule to:

when
    Time cron "*/15 * * * * ?"
then
    gGroup1.members.forEach[ i |
        i.sendCommand("ON")
        Thread::sleep(1000)
        gGroup2.members.filter[u|u.name == i.name+"_update"].head.postUpdate(i.state)
    ]
end
1 Like

Hi,

thank you very much for your long post (and your time of course). First, please excuse my grammar, becouse I`m not english native, but trying my best. Ok, higlihting code - I will try to remeber this rule, thank you.

Yes, this rule is working as is writen, but I know, its not in the right form. Im very new to OpenHAB so I`m learning the code right now. My programming skills are weak, I know, I know … :frowning:

I`d like to introduce my serial device behaviour, what is worknig and what I want from it - for better understanding:

1, My device is this relay unit, actually I have few of them. This device can be controlled via RS485 and I have TCP/RS485 converter as i described before. The protocol to control and ask device i quite easy, if someone is interested, is described here.

2, to control device I`m using this command in items (example to control one coil in relay board)

Switch light1 "Living room light 1" (All) {tcp=">[ON:192.168.88.238:13000:'MAP(lroom.map)'], >[OFF:192.168.88.238:13000:'MAP(lroom.map)']"}

My map file looks like this:

ON=d@0010000000000000000000000000000000
OFF=d@0000000000000000001000000000000000

With this I can control lights, but the device doesnt send anyhing back. So, if Im controlling lights by pushbuttons on walls I dont have switch buttons updated on OpenHAB site. I have to ask device. Fot this, I create new items (for example I`m renaming names form my language shortcuts to some english ones) and rules.

Item file:

Switch light1question "Question for light 1" (All) {tcp=">[ON:192.168.88.238:13000:'MAP(LroomQ.map)'], >[OFF:192.168.88.238:13000:'MAP(LroomQ.map)']"}

Map file:

ON=?d01000001
!d0012@Q=ON

And rule file shown before. From this you can see, that i send thru TCP converter to device question ?d01000001 (mapped as ON command fort TCP binding) and if the answer is !d0012@Q it means, that the coil in relay board is ON. What I want as result, is periodically send questions, receive answers and postupdate buttons.

I will try to colapse rule with the grouping. Good point to learn grouping finally :slight_smile: If you will have some idea, how to do it better, easier or somehow I`ll appreciate it very much. I hope, that this reply is now better and more understandable than my fist without highlihgting.

Thank you.

Based on your description of what you are trying to do, I think the Grouping approach is the best approach. One minor change I might make to keep it from calling postUpdate to Items that have not changed would be to change to the following (NOTE: I split it up into separate lines and added comments so you can see a little better what it is doing)


    gGroup1.members.forEach[ lightQuery |
        lightQuery.sendCommand("ON") // issue the request to the device to report its current status
        Thread::sleep(1000) // wait for update, presumably lightQuery gets updated with the light's current state
        val lightSwitch = gGroup2.members.filter[lightSwitch|lightSwitch.name == lightQuery.name+"_switch"].head // get the corresponding light switch
        if(lightSwitch.state != lightQuery.state) lightSwitch.postUpdate(lightQuery.state) // only postUpdate if the state is different
    ]

Hi,

thank you very much for your code. I was trying yesterday to implement the code, btw grouping is very easy. This is the result:

Option 1:

when
    Time cron "*/12 * * * * ?"
then
 
gGroup1.members.forEach[ lightQuery |
    lightQuery.sendCommand("ON") // issue the request to the device to report its current status
    Thread::sleep(500) // wait for update, presumably lightQuery gets updated with the light's current state
    val lightSwitch = gGroup2.members.filter[lightSwitch|lightSwitch.name == lightQuery.name+"_switch"].head
    if(lightSwitch.state != lightQuery.state) lightSwitch.postUpdate(lightQuery.state)
]
end

I have this errors:

java.lang.IllegalStateException: Could not invoke method: org.openhab.model.script.lib.NumberExtensions.operator_notEquals(org.openhab.core.types.Type,java.lang.Number) on instance: null
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:738) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:713) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor44.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateIfExpression(XbaseInterpreter.java:327) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor53.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:28) ~[na:na]
        at com.sun.proxy.$Proxy79.apply(Unknown Source) ~[na:na]
        at org.eclipse.xtext.xbase.lib.IterableExtensions.forEach(IterableExtensions.java:395) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:729) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:713) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateMemberFeatureCall(XbaseInterpreter.java:549) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
        at org.openhab.model.script.internal.engine.ScriptImpl.execute(ScriptImpl.java:59) ~[na:na]
        at org.openhab.model.rule.internal.engine.ExecuteRuleJob.execute(ExecuteRuleJob.java:55) ~[na:na]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [quartz-all-2.1.7.jar:na]
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) [quartz-all-2.1.7.jar:na]
Caused by: java.lang.IllegalArgumentException: argument type mismatch
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:729) ~[na:na]
        ... 56 common frames omitted

Option 2:

when
    Time cron "*/12 * * * * ?"
then
 
gGroup1.members.forEach[ lightQuery |
    lightQuery.sendCommand("ON") // issue the request to the device to report its current status
    Thread::sleep(500) // wait for update, presumably lightQuery gets updated with the light's current state
    val lightSwitch = gGroup2.members.filter[lightSwitch|lightSwitch.name == lightQuery.name+"_switch"].head
    if(lightSwitch.state != lightQuery.state) lightSwitch.postUpdate (if(lightQuery.state != OFF) ON else OFF)
	]
end

I have this errors:


java.lang.IllegalStateException: Could not invoke method: org.openhab.model.script.lib.NumberExtensions.operator_notEquals(org.openhab.core.types.Type,java.lang.Number) on instance: null
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:738) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:713) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor44.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateIfExpression(XbaseInterpreter.java:327) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor53.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:28) ~[na:na]
        at com.sun.proxy.$Proxy79.apply(Unknown Source) ~[na:na]
        at org.eclipse.xtext.xbase.lib.IterableExtensions.forEach(IterableExtensions.java:395) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:729) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:713) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateMemberFeatureCall(XbaseInterpreter.java:549) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
        at org.openhab.model.script.internal.engine.ScriptImpl.execute(ScriptImpl.java:59) ~[na:na]
        at org.openhab.model.rule.internal.engine.ExecuteRuleJob.execute(ExecuteRuleJob.java:55) ~[na:na]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [quartz-all-2.1.7.jar:na]
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) [quartz-all-2.1.7.jar:na]
Caused by: java.lang.IllegalArgumentException: argument type mismatch
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:729) ~[na:na]
        ... 56 common frames omitted

And finally option 3:

You can see, that i only reverse if(lightSwitch.state != lightQuery.state) to if(lightQuery.state != lightSwitch.state) and it works. To be honest, I dont understand it, but its working.

when
    Time cron "*/12 * * * * ?"
then
 
gGroup1.members.forEach[ lightQuery |
    lightQuery.sendCommand("ON") // issue the request to the device to report its current status
    Thread::sleep(500) // wait for update, presumably lightQuery gets updated with the light's current state
    val lightSwitch = gGroup2.members.filter[lightSwitch|lightSwitch.name == lightQuery.name+"_switch"].head
    if(lightQuery.state != lightSwitch.state) lightSwitch.postUpdate (if(lightQuery.state != OFF) ON else OFF)
	]
end

Woking! :slight_smile:

2016-08-05 10:16:14.836 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'svetla.rules'
2016-08-05 10:16:24.396 [INFO ] [runtime.busevents             ] - svoblus received command ON
2016-08-05 10:16:24.872 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0012@P from the remote end Channel [item=svoblus, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:25.041 [INFO ] [runtime.busevents             ] - svoblus state updated to OFF
2016-08-05 10:16:25.631 [INFO ] [runtime.busevents             ] - svobbod received command ON
2016-08-05 10:16:26.205 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0032@P from the remote end Channel [item=svobbod, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:26.373 [INFO ] [runtime.busevents             ] - svobbod state updated to OFF
2016-08-05 10:16:26.892 [INFO ] [runtime.busevents             ] - svobled received command ON
2016-08-05 10:16:27.489 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0022@P from the remote end Channel [item=svobled, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:27.648 [INFO ] [runtime.busevents             ] - svobled state updated to OFF
2016-08-05 10:16:28.166 [INFO ] [runtime.busevents             ] - svsch received command ON
2016-08-05 10:16:28.619 [INFO ] [runtime.busevents             ] - lampa state updated to 4
2016-08-05 10:16:28.666 [INFO ] [runtime.busevents             ] - slamp state updated to OFF
2016-08-05 10:16:28.718 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0042@P from the remote end Channel [item=svsch, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:28.734 [INFO ] [runtime.busevents             ] - ppower state updated to OFF
2016-08-05 10:16:28.996 [INFO ] [runtime.busevents             ] - svsch state updated to OFF
2016-08-05 10:16:29.435 [INFO ] [runtime.busevents             ] - svvch received command ON
2016-08-05 10:16:30.001 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0052@P from the remote end Channel [item=svvch, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:30.166 [INFO ] [runtime.busevents             ] - svvch state updated to OFF
2016-08-05 10:16:30.681 [INFO ] [runtime.busevents             ] - svloz received command ON
2016-08-05 10:16:31.036 [INFO ] [t.protocol.internal.TCPBinding] - Received !d0062@P from the remote end Channel [item=svloz, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:31.232 [INFO ] [runtime.busevents             ] - svloz state updated to OFF
2016-08-05 10:16:31.522 [INFO ] [runtime.busevents             ] - stav state updated to 7
2016-08-05 10:16:31.754 [INFO ] [runtime.busevents             ] - svpolus received command ON
2016-08-05 10:16:32.302 [INFO ] [t.protocol.internal.TCPBinding] - Received !d1012@P from the remote end Channel [item=svpolus, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:32.469 [INFO ] [runtime.busevents             ] - svpolus state updated to OFF
2016-08-05 10:16:32.975 [INFO ] [runtime.busevents             ] - svpohve received command ON
2016-08-05 10:16:33.329 [INFO ] [t.protocol.internal.TCPBinding] - Received !d1022@P from the remote end Channel [item=svpohve, command=ON, direction=OUT, remote=/192.168.88.238:13000, buffer=, isBlocking=false, isReconnecting=false, channel=/192.168.88.250:52587::/192.168.88.238:13000, host=192.168.88.238, port=13000]
2016-08-05 10:16:33.519 [INFO ] [runtime.busevents             ] - svpohve state updated to OFF

The error for option 1 and option 2 are the same error.

I think what is happening is that the Rules engine was not able to figure out what type of Item lightSwitch is. When you pull it out of gGroup2 it comes out as the lowest type of Item (GenericItem). Consequently it can’t figure out how to convert its state to an OnOffState to do the comparison (i.e. the !=). However when you reverse the order it has more to work with and can figure the right casting out.

All of this is probably low level programming gobbledygook but it might make sense to someone somewhere.

Anyway, if I’m correct, the following probably would have worked:

val SwitchItem lightSwitch = gGroup2.members.filter[lightSwitch|lightSwitch.name == lightQuery.name+"_switch"].head as SwitchItem
if(lightSwitch.state != lightQuery.state) lightSwitch.postUpdate(lightQuery.state)

Working! Thank you very much!