Arrays and For Loop

Hi all,

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:

items = ["Rear_Garage_Door_Sensor", "Kitchen_Door_Sensor"]

Then:

for (i = 0; i < items.length; i++) {
   item += myObj.cars[i].changed;
}

I hope the above makes some sort of sense of what I’m trying to achieve.

Many thanks,

Jeevs

Helpful hint… you used quotes instead of code fences.

So, your question is how to iterate over an array of Items names? How about putting the Items in a group and iterating over the members?

https://openhab-scripters.github.io/openhab-helper-libraries/Guides/But%20How%20Do%20I.html#iterate-over-members-of-a-group

1 Like

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.

@5iver Thanks for the heads up, I’ve changed them to code fences now :slight_smile:

@rossko57 Thanks for this information :slight_smile:

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?

Many thanks,

It’s entirely up to you. You can have quite different groups for display purposes and for control purposes, Items can be members of multiple groups.

2 Likes

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]

Seems like I could also use the above…

Many thanks :slight_smile:

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.

Apologies @rossko57 I didn’t realise I could use more than one language in the rules.

I’m using the above from here. I also noticed that the post you included had similar lines…

Any help would be greatly appreciated.

Many thanks :slight_smile:

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.

1 Like

@rossko57 - Thanks for the clarification, its most helpful :slight_smile:

I’ll give the DSL Rule a go and feedback. Just so I know, how are other languages stored/loaded such as Python?

Many thanks,

No idea, I don’t use them. Have you tried the docs?

Thanks for that @rossko57, your help is most appreciated :slight_smile:

Hi @rossko57,

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?

Many thanks as always,

Don’t know, maybe a Stringbuilder object doesn’t have a .toString method.

Bit puzzled by expecting door.state might be OPEN or “NIGHT”, these are different types

1 Like

Okay no worries, will test and get back to you!

Yes, I noticed this mistake after posting - silly mistake on my part and has alraedy been updated :slight_smile:

Thanks once again :slight_smile: