I was hoping the community could help me; essentially I’m attempting to clean up my rules so that I’m not repeating code…(DRY).
I have several rules that are purely for notifications i.e. a door has been open or to switch items on based on the time, I’ve given two examples below of each.
Notification:
rule "Garage Door Open/Close"
when
Item Rear_Garage_Door_Sensor changed // Run when sensor state changes
then
val garageLog = "Garage Door"
if (Rear_Garage_Door_Sensor.state == OPEN) {
sendBroadcastNotification(garageLog + " Opened")
logInfo(garageLog, garageLog + " Opened")
} else {
sendBroadcastNotification(garageLog + " Closed")
logInfo(garageLog, garageLog + " Closed")
}
end
Time-based trigger:
rule "Outdoor Front Lights On/Off"
when
Item vTimeOfDay received command
then
val outdoorFrontLightLog = "Front Lights"
if (vTimeOfDay.state == "SUNSET") {
Outdoor_Front_Lights.sendCommand(ON)
logInfo(outdoorFrontLightLog, outdoorFrontLightLog + " On")
} else if (vTimeOfDay.state == "BED") {
Outdoor_Front_Lights.sendCommand(OFF)
logInfo(outdoorFrontLightLog, outdoorFrontLightLog + " Off")
}
end
Now, I was thinking to create an array of items to begin and a for loop to run through each item to check which one has triggered the rule? For example:
But you cannot trigger a rule from an array of Item names.
You should definitely look at Groups, with associated Member of rule triggering, and triggeringItem implicit variable.
So it seems i need to use Groups which is fine. However, at the moment I’m using location based groups. For instance:
Group Rear_Garage (Ground_Floor)
Group Kitchen (Ground_Floor)
Should I introduce a new set of groups in addition to the above? With regards to what I’m trying to achieve, what would you say is best for me? The DP @rossko57 has recommended or can I simply use a group and for loop?
I have now created a new Group called ‘Contacts’ and assigned them in my .items file.
I’m now looking at the rule itself, no matter where I put the below in a rule i get an error:
for item in ir.getItem("Contacts").members:
Can @5iver or @rossko57 shed any light how the above should be incorporated into a rule?
Also, what is the difference between the below two:
listOfMembers = filter(lambda item: item.state == ON, ir.getItem("gTest").members)
listOfMembers = [item for item in ir.getItem("gTest").members if item.state == ON]
You should clarify what rule language you are writing in. You cannot mix them within the same rule. (Your first post showed an example in “original” Rules DSL)
That doesn’t mean much without knowing what ir is, or if it should have a getItem method.
The tab that says python? There is a different tab for DSL rules.
We’d probably best start over. openHAB supports a number of different languages for scripting rules.
The “native” language inherited from OH1 is called Rules DSL, and lives in xxx.rules files.
There are other choices, loaded in different ways.
Rather like a spoken language, it doesn’t work properly if you mix languages in rules or files.
Finally after understanding the differences in rules/languages you can use I’ve managed to use the DP.
I’m getting one error on the final error from the example shown:
rule "A Door Sensor Changed"
when
Member of Contacts changed
then
val door = triggeringItem
// Alert
val StringBuilder msg = new StringBuilder
msg.append(transform("MAP", "entry.map", door.name)) // note a map and transform can convert from Item name to human friendly words
if(door.state == OPEN) msg.append(" was opened") else msg.append(" was closed")
var alert = false
if(door.state == "NIGHT" || vTimeOfDay.state == "BED"){
alert = true
msg.append(" and it is night")
}
if(alert){
msg.append("!")
**aAlerts.sendCommand(msg.toString)**
}
logInfo("Entry", msg.toString)
end
The aAlerts denoted by ** any idea what this could be? VSCode is saying the method or field is undefined, which i agree with. I think i should be able to remove it, do i even need it? as in the logInfo its being converted to string anyway?