It is a side effect in how the state of the Group is calculated. And a recent change (as of 2.1) makes it so a Group that isn’t given a type (e.g. Group:Number) no longer receive any updates at all. This is why Udo recommends the need to add that to your Group definition.
So I do something similar. First, let’s break the problem down a little bit. I recommend separating the alerting code from your detection code. See the Separation of Behaviors Design Pattern for how I do this. The tl;dr is create an Alert Item and an Info Item and use Alet.sendCommand(“message”) to send an alert and the same with Info. Then implement the code that actually sends the alert messages out using pushover, email, what ever in a rule that triggers on Alert received command
.
The nice thing about this approach is you can add in some complicated logic that will apply everywhere at once without requiring you to make changes everywhere. For example, during the day I send Infos using NotifyMyAndroid and for Alerts I use Cloud Connector’s Broadcast. At night my wife really really doesn’t want to be woken up by these sorts of alerts so I shift to send the alerts via NotifyMyAndroid at night.
Also, notice the use of the Time of Day Design Pattern.
Now for code to determine what alerts to make.
Assuming you fix your Group definitions so they all have the appropriate Type and Function:
Group:Number:MAX TemperatureRooms
Group:Number:MAX CO2Rooms
Number WaterLevelOfPlant // I'm assuming this is just one sensor, not a Group
Switch Doorbell // again, just one Switch, not a Group
you have two choices.
- Write your rule so it only triggers once per Item change
- Write your rule so it doesn’t matter that the Rule triggers more than once for each change to one of its members.
Solution 1 is Udo’s approach. You need to add each Item individually as a trigger. You can still loop through the Group and use Persistence tricks to figure out what Item triggered the rule or you can not care and just construct an alert that includes all the Items that are warning or alerting.
This would look like, if you implement Time of Day and Separation of Behaviors:
rule "warnings and alerts for temperature"
when
Item Temp1 changed or
Item Temp2 changed or
Item Temp3 changed or
Item Temp4 changed or
Item Temp5 changed
then
val message = new StringBuilder
TemperatureRooms.members.filter[temp|temp.state as Number > 25].forEach[temp |
message.append(temp.name + " is " + temp.state + "!\n")
]
if(TemperatureRooms.state as Number > 30) aAlert.sendCommand(message.toString)
if(TemperatureRooms.state as Number > 25 && vTimeOfDay.state.toString == "DAY") aInfo.sendCommand(message.toString)
end
One neat trick is to use a MAP transform to convert the Item’s name into a friendly name. Create a map file and change the message.append to:
message.append(transform("MAP", "alert.map", temp.name) + " is " + temp.state + "!\n")
Solution 2 is to write the rule such that you don’t care if it gets triggered multiple times per change to TemperatureRooms’s members. There are lots of ways to go about this and which is best depends on a lot of personal requirements. In the case of TemperatureRoom’s we can take advantage of the use of the MAX function for the Group definition. We don’t need to trigger the rule every time one of the room’s changes temperature, we only need to trigger the rule when the maximum temperature of all the rooms changes so we can trigger the rule on changes to the Group rather than updates.
rule "Temperature"
when
Item TemperatureRooms changed
then
val message = new StringBuilder
TemperatureRooms.members.filter[temp|temp.state as Number > 25].forEach[temp |
message.append(transform("MAP", "alert.map", temp.name) + " is " +transform("MAP", "alert.map", temp.state) + "!\n")
]
if(TemperatureRooms.state as Number > 30) aAlert.sendCommand(message.toString)
if(TemperatureRooms.state as Number > 25 && vTimeOfDay.state.toString == "DAY") aInfo.sendCommand(message.toString)
end
However, this is not always the case. For example, if you have multiple DoorBells and DoorBell is a Group then we can’t really rely on the aggregation function so we would need a way to filter out the multiple rule triggers. I just posted a new Design Pattern showing how to do this here: