Group rule triggered twice - why?

Hi there,

I have a simple test setup for a rule which is supposed to be triggered after a click on a switch.

The SiteMap

Frame label="myTest" {
    Switch item=mySwitch1 label="Switch 1"
    Switch item=mySwitch2 label="Switch 2"
    Switch item=mySwitch3 label="Switch 3"
}

The Items

Group myTest (All)
Switch mySwitch1 “Test1” (myTest)
Switch mySwitch2 “Test2” (myTest)
Switch mySwitch3 “Test3” (myTest)

The code

rule “myTest-Buttons V1”
when
Item myTest received update
then
println("Rule triggered: " + myTest.toString())
end

After clicking on one of the switches I get the following output:

2015-08-16 22:46:28.545 [INFO ] [runtime.busevents ] - mySwitch1 received command OFF
Rule triggered: myMansion (Type=GroupItem, Members=3, State=Undefined)
Rule triggered: myMansion (Type=GroupItem, Members=3, State=Undefined)
2015-08-16 22:46:29.184 [INFO ] [runtime.busevents ] - mySwitch1 received command ON
Rule triggered: myMansion (Type=GroupItem, Members=3, State=Undefined)
Rule triggered: myMansion (Type=GroupItem, Members=3, State=Undefined)

Why is this rule triggered twice?? It has definitly something to do with the group. This error doesnt happen when I bind the rule to a specific switch. Can anybody please help me?

EDIT: looks like it’s only displayed twice… but how can this be?

I just ran into this behavior myself, only it looks like it is called three or four times. Are you sure the rule is not being triggered multiple times? I just added a counter to my rule and confirmed that it is being triggered multiple times.

So far I haven’t found any explanation for it yet but at the moment the fact that the rule executes multiple times is a mere annoyance for me and not a problem. I’d love to know why though.

If you use

Group:Switch:OR(OFF,ON) myTest (All)

in place of

Group myTest (All)

does that affect how the rule is triggered?

I’m afraid not. It still gets triggered three times for me even when I add the Switch to the group. It is kind of odd.

Rich

I agree it’s odd, but there is no guarantee that the number of updates on the event bus for an item will be the same as the number of state changes. There could be many more updates potentially. Instead of

Item myTest received update

Use

Item myTest changed

and it ought to run the rule only when myTest’s state has changed.

1 Like

Very strange indeed. Maybe a bug?
I’ve changed it to “Item myTest changed” now, this works (only one call per time)

Thanks very much.

It’s probably not a bug, just a side effect of how the Group’s state is calculated. In most cases I can think of, rule are more interested in being triggered when the state it’s watching has changed, not when the state is updated. (This is one reason I set the log level that appends to events.log to WARN, because otherwise that file contains a long list of uninteresting updates. I would rather just have a 0-length events.log file than a huge file of updates.)

I tried using “Item gLights changed” at first but it doesn’t exhibit the behavior I want.

In my case I have three lights that are members of a group. I want the rule to trigger any time any of the items in the group changes its state. However, not every change of an item’s state causes the group’s state to change. For example, if all three lights are OFF and one turns ON, the group will change state to ON. So far so good. However, when the second and third lights turn ON the group doesn’t change state because it is already ON and the rule does not get triggered.

The multiple updates on the group for one Item’s change is odd but at least in my case it isn’t actually causing a problem. It is just slightly annoying. However, it is keeping me from applying a rule design pattern I’m experimenting with to other areas of my system.

Rich

I had the same problem, the rule’trigger works (twice) only with “received update” (even though with not every group I’ve tried). I think this is a bug for the groups’ trigger…

1 Like

Same here and I’m afraid this is not the only bug.

I switched to “myGroup received update” because “myGroup changed” does not work reliable. So i believe in group change trigger there is something wrong too.

“myGroup received update” is fired three times in my case. Does it have something to do with the number of items in this group? Will check this…

OK, here is the full story on using groups as triggers to rules.

The state of a Group is an aggregate of the Items that are members of the group. You can control how the Item states are aggregated in the Group definition (see the itemtype section of the Items wiki page).

By default the state of the Group use OR. So for a Group of switches the Group will be ON if any of the members are ON. But this means that once one Item turns on the Group’s state gets set so each subsequent Item that turns on will not trigger “myGroup changed” because the Group isn’t changing.

This is not a bug, it is the expected and designed behavior. Because the group state is an aggregate, every change in the Item members does not necessarily result in a change to the Group’s state.

The behavior of a “myGroup received update” isn’t necessarily a bug either. I’m speculating here a little bit (haven’t had time to set up the IDE so I can trace through the code so I’m going based on my experiences) but I believe what is happening is the following:

  • when an Item changes it triggers an event that causes the Group’s state to be recalculated
  • during the recalculation it iterates over all of its members and applies the aggregation function
  • it does the calculation step by step, first just updating the Group’s state with the state of the first Item, then applying the aggregation function between the Group and each individual item, calling postUpdate on each calculation

So the “problem” is that each time postUpdate is called it triggers any “myGroup received update” rule. Thus each of these rules get triggered multiple times.

1 Like

Its because the parent group with multiple children states “Undefined” when an item is active. If the parent group only has one child then it states properly they way it should. I have the same issue.

SO now when you run a rule against it and you see two logs or emails its because it checks against the"Undefined" then a change.

SO SO,

The question is, How do we get this to properly show what the group has… If all items in the group show CLOSED then the parent should show closed. If any one of the children are OPEN the the parent should show as well.

<item><type>GroupItem</type>
<name>gMotionSensors</name>

<state>Undefined</state>

<link>http://10.1.100.23:10005/rest/items/gMotionSensors</link>
<members>
<type>ContactItem</type>
<name>kMotion</name>

<state>CLOSED</state>

<link>http://10.1.100.23:10005/rest/items/kMotion</link>
</members><members>
<type>ContactItem</type>
<name>lMotion</name>

<state>OPEN</state>

<link>http://10.1.100.23:10005/rest/items/lMotion</link>
</members></item>

This is working for me,

Group:Contact:OR(OPEN,CLOSED) gMotionSensors (All)

I have the same problem with “Item {group} changed” is there a solution to the rule firing more then once? I have tried locks, but that does not seam to work.

Please post an example. I expect Item {group} received update to trigger a rule more than once but would not expect it to with Item {group} changed.

Are you seeing more than one event in events.log showing the Group’s state changing more than once?

I suppose, if the Group’s state is a SUM, MAX, MIN, etc the Group might change more than once. For example, for MAX, it iterates through the members and sets the Group to the first Item’s value, then if the second one is larger than the first it updates the state again and the Group’s state changes, and so on. I don’t know for sure that is how it works, I’m just guessing based on how received update works.

Sorry I should have been more clear, I was trying to say that I have the same problem with “Item {group} changed” as you were so I am trying to find a solution for received update. With received update, I am seeing the rule fire twice at the same millisecond so locks are not even working.

That is surprising as no matter what you shouldn’t be able to have more than one thread acquire a lock at the same time, even if the two threads attempt within nanoseconds of each other. That is the purpose of locks.

Am I doing something wrong?

import java.util.concurrent.locks.ReentrantLock

var ReentrantLock lock = new ReentrantLock()

rule "Alarm Triggered"
when
  Item Alarms received update 
then
  logInfo("Testing", "Lock: " + lock.isLocked)
  if (!lock.isLocked) {
    lock.lock()
    try {
      Thread::sleep(200) 
      logInfo("Testing", "Alarms received update")
      val alarm = Alarms.members.filter[s|s.lastUpdate("mapdb") != null].sortBy[lastUpdate("mapdb")].last
      if (alarm.state == OPEN) {
        logInfo("Testing", "Test: " + alarm)
      }
    } 
    finally {
      lock.unlock()
    }
  } else {
    logInfo("Testing", "locked, update ignored")
 }
end

I don’t think so; as per your other thread your hardware is potent enough to beat the ©lock, generating group updates and kicking off two rules essentially simultaneously.

The issue is not that the lock is acquired twice, it is that the second rule gets past the “abandon if already locked” if (before the first rule has actually grabbed the lock) - and then queues for the lock. The rule gets run twice in neat sucession, when the intent is to use the lock to abort the second run.

Restating this made me think, is there a ReentrantLock method that doesn’t queue? Seems .tryLock may fit the bill here?
Example
https://groups.google.com/forum/#!topic/openhab/V5r-JgvwK18

Nothing that would explain your behavior. But what I do notice:

  • the is no catch so if an exception occurs. In the past I’ve had finally but work when an exception occurs. I’ve not verified this is still the case with oh 2.
  • the rule did be skipped if another instance has the lock. I suppose the could be something weird going on there. I don’t know if the isLocked method is synchronized (it should be).

What do you see in your logs?

How many Items are members of Alarms?