Implement delay in x.members.forEach, exec binding+rcswitch

Hi everyone, my first post in the forum. Great software!

I´m running OpenHab on a raspberry pi3 hooked up to a TX433 chip.
Im using exec binding and rc-switch library.
Switching individual lights on or off works like a charm.

But:
If i try to switch a group nothing happens. My suspicion is that the exec command is too fast
and somehow flooding the TX433 when trying to switch of 10 lights at once.
If I switch a group with only one member it works, as soon as I add another one nothing happens.

After some research i tried using an empty switch and a rule instead:

rule “All off”
when
Item All_lights_off received command
then
lights.members.forEach[sw|sw.sendCommand(toString)]
end

Looking at the output this seems to work (openHab successfully executes the command for switch)
Despite this nothing happens. Like a said I think the execution is too fast for rc-switch/TX433 chip to process everything.

Question:
Is there a way to implement a short delay between the sendCommand(“ON”) execution of each member in my group lights? A dirty fix would be to hardcode each switch in the rule but it would be nice if I could just refer to the group.

Thanks / M

1 Like
rule "All off"
    when
        Item All_lights_off received command
    then
        lights?.members.forEach[sw|         //keep the question mark in mind
            sw.sendCommand(receivedCommand) //send a state, not a string
            Thread::sleep(200)              //time to sleep in msec
        ]
end

:slight_smile:

Thank you! Works great, although I had to increase to over 500ms in order
for it to be 100% reliable.

Hello, I am new to openhab and tried this rule with rollershutter items, which resulted in an indefinitive loop of commands (probably because the item status does not change). Is there a way to stop the loop once the command has been sent to all members of the group?

Many thanks in advance,
Jonas

No, the only way to get an infinite loop would be, if the trigger item belongs to the group, so please ensure that the item(s) between when and then are not members of the group

You are right. Thanks. Sometimes the answer is so obvious.
There remains, however, the following issue: the script results in the execution of both “UP” and “DOWN” commands.

2016-10-03 10:03:53.074 [INFO ] [ab.binding.exec.internal.ExecBinding] - executed commandLine ‘sh /etc/openhab2/scripts/Velux/KidsShutterWest_close.sh’
2016-10-03 10:03:53.089 [INFO ] [ab.binding.exec.internal.ExecBinding] - executed commandLine ‘sh /etc/openhab2/scripts/Velux/KidsShutterWest_open.sh’

Rule:
> rule “Open all Shutters”
when
Item Shutters_All received command [UP]
then
Shutters.members.forEach[Rollershutter|
sendCommand(Rollershutter, UP)
Thread::sleep(2000)
]
end
rule “Close all Shutters”
when
Item Shutters_All received command [DOWN]
then
Shutters.members.forEach[Rollershutter|
sendCommand(Rollershutter, DOWN)
Thread::sleep(2000)
]
end

And here one example for a rollershutter item:

Rollershutter Shutter_FF_Kids_West “Kids West” (FF_Kids, Shutters) {exec=“UP:sh /etc/openhab2/scripts/Velux/KidsShutterWest_open.sh, DOWN:sh /etc/openhab2/scripts/Velux/KidsShutterWest_close.sh”}

Any help would be appreciated.

I don’t think the UP and DOWN parts are formatted correctly. There is not an example in the wiki for a multiple command item like a switch or roller, but see this post

where > and get used as separators.
There is also the use of @@ instead of spaces.

You may need to tell us the version you use for more help

Be aware that there is a difference between action and method, so please try

Shutters.members.forEach[Rollershutter| 
        Rollershutter.sendCommand(DOWN)  //or UP
        Thread::sleep(2000) 
    ]

instead.
The method item.sendCommand(value) has knowledge about the correct type to transmit to the item, where the action sendCommand(item,value [as string]) has not, and therefore the action will always send a string, even if this is wrong.

Did you try if the rollershutters work as expected, if using one item through UI?
It’s always a good idea to do it step-by-step… :wink:

Thanks for the quick reply. I tried your suggestion but unfortunately it results in the same behavior.
Of course I tried the individual rollershutters first. They work flawlessly.

Ahhh.

A second issue would be the trigger, this has to be

    Item Shutters_All received command UP // or DOWN, don't use brackets around

and this would be more effective:

rule "control all Shutters"
when
    Item Shutters_All received command
then
    if (receivedCommand != STOP) // to avoid stop-command
        Shutters.members.forEach[r| 
            r.sendCommand(receivedCommand) 
            Thread::sleep(2000) 
        ]
end

only one rule :wink:

Very nice and elegant. Thanks so much. Works flawlessly.
Have a great day!

sorry for bumping here.

what is the difference between

lights?.members.forEach[sw| //keep the question mark in mind

lights.members.forEach[sw|

For what is the “?” used to?

As far as I know, the ? would supress errors in your log if the list is empty.

I’m not a big fan of Thread.sleep() because it suspends the entire thread. I prefer to set up timers. This is how I do it in one of my rules. ‘Lights_Kitchen’ is a group of 3 lights and Light_Kitchen_All is a physical switch that turns all three on or off at once. This is all Z-Wave (two Fibaro FGS221 Double Relay Switches).

rule "All Kitchen Lights off or on"
when
    Item Light_Kitchen_All changed
then
    var newState = Light_Kitchen_All.state as OnOffType
    logDebug("rule", "All Kitchen Lights switching {}", newState)
    Lights_Kitchen?.members.forEach(item,i|createTimer(now.plusMillis(i*50)) [|item.sendCommand(newState)])
end

Quite a satisfying clack of relays when that triggers!