Working with design pattern in rule, refer to specific item

Hello,

https://community.openhab.org/t/design-pattern-working-with-groups-in-rules/20512 lists various examples how to work with groups of items in rules. I’m succesfully using

MyGroup.members.forEach[ i | <code> ]

As part of the code I would like to query whether the actual item i corresponds to item with real name “abcde”. So in the example of the above mentioned link we have items defined as

Group:Switch:OR(ON, OFF) gDoorsTimers
Switch vGarageOpener1_Timer (gDoorsTimers)
Switch vGarageOpener2_Timer (gDoorsTimers)
Switch vGarageOpener3_Timer (gDoorsTimers)

I would like to check during execution of a rule running over all group members whether the actual group member is “vGarageOpener2_Timer”:

Group.members.forEach[ i | 
   if i == "vGarageOpener2_Timer" { do something} ] 

Is that possible?

Thanks,
Meschmesch

You’d want to look at the name property of the Item? i.name

Yes, so in the above example it would need to be coded as:

roup.members.forEach[ i | 
   if i.name == "vGarageOpener2_Timer" { do something} ] 

correct?

You could try it, I suppose.

There are several examples of using the .name property in that design pattern thread.

The syntax is wrong but the concept is correct. You need to use the name of the Group, not “Group”. The condition requires parenthesis around it.

gDoorTimers.members.forEach[ i | if (i.name == "vGarageOpener2_Timer") { do something } ]

But if the only thing you are doing is looking for that one Item it’s better to use findFirst.

var timer = gDoorTimers.members.findFirst[ i | i.name == "vGarageOpener2_Timer" ]
do soemthing

@rlkoshak sure. I’m using the group name. Thank you, it’s working.

…and another question. From within the “forEach…” I would like to execute commands. Normally I would simply code this as follows:

myGroupname.members.forEach[ i | 
   if i == "vGarageOpener2_Timer" { 
       Thread::sleep(20000)     
       do_something_more... 
   }
  else {
      Thread::sleep(10000) 
      do_something_else...
  }
 ] 

What would you recommend to do in order to avoid the Thread::sleep? I would like to use a timer if possible. But the timer would only cause a cascade of “do something more” or “do something else” without waiting for completion of the respective do someting stuff.

You put the “do_something_more…” inside the lambda you pass to the Timer.

… Which will then only delay the do_something_more but execute immediately the if else block for the next member of myGroupname. However the prerequisite is that the next member is not used until the previous timer ended or terminated.

Consider it like a cascade of lights, each light being assigned a switch of myGroupname. 1st light is turned on and after a timer of 10 seconds turned off. Only thereafter the 2nd light is turned on, timer 10secs, turn off. And so on.

Given the long delays, you probably want a state machine sequencing.