Same rule for different rooms

Hello!
At this moment my rollershutters work like this:

rule "Schatten Auto Azimuth"
when
	Item Astro_Azimuth changed
then
    val int az_foyer_mitte_up = 168

    val int az_gang_mitte_up = 207

    val int az_kueche_up = 202

    val int az_wz_front_up = 207
        
    val int az_foyer_rechts_dn = 185
    val int az_foyer_rechts_up = 251

    val int az_gang_rechts_dn = 177
    val int az_gang_rechts_up = 251 // noch genau zu definieren

    val int az_buero_dn = 139
    val int az_buero_up = 272


    if ((Astro_Azimuth.state > az_foyer_rechts_dn) && (Astro_Azimuth.state < az_foyer_rechts_up) && (rs_foyer_rechts_auto.state == ON)) {
        if (rs_foyer_rechts.state < 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist. Ansonsten werden die Raffstore bei der Änderung Azimuth gestellt!
        sendCommand(rs_foyer_rechts, 100)
        }
        if (rs_foyer_rechts_lm.state != 0) {
        sendCommand(rs_foyer_rechts_lm, 0)
        }
        logInfo("Beschattung","Fassade Dorf EG Beschattung ein")
    }
    
    if ((Astro_Azimuth.state > az_gang_rechts_dn) && (Astro_Azimuth.state < az_gang_rechts_up) && (rs_gang_rechts_auto.state == ON)) {
        if (rs_gang_rechts.state < 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist. Ansonsten werden die Raffstore bei der Änderung Azimuth gestellt!
        sendCommand(rs_gang_rechts, 100)
        }
        if (rs_gang_rechts_lm.state != 0) {
        sendCommand(rs_gang_rechts_lm, 0)
        }
        logInfo("Beschattung","Fassade Dorf OG Beschattung ein")
    }


    if ((Astro_Azimuth.state > az_buero_dn) && (Astro_Azimuth.state < az_buero_up) && (rs_buero_auto.state == ON)) {
        if (rs_buero.state < 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist. Ansonsten werden die Raffstore bei der Änderung Azimuth gestellt!
        sendCommand(rs_buero, 100)
        }
        if (rs_buero_lm.state != 0) {
        sendCommand(rs_buero_lm, 0)
        }
        logInfo("Beschattung","Raffstore Buero wird automatisch gestellt")
    }

    if ((Astro_Azimuth.state > az_buero_dn) && (Astro_Azimuth.state < az_buero_up) && (rs_kino_auto.state == ON)) {
        if (rs_kino.state < 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist. Ansonsten werden die Raffstore bei der Änderung Azimuth gestellt!
        sendCommand(rs_kino, 100)
        }
        if (rs_kino_lm.state != 0) {
        sendCommand(rs_kino_lm, 0)
        }
        logInfo("Beschattung","Raffstore Kino wird automatisch gestellt")
    }
}

(and there are more lines with even more items…)

basically the rule should to this for every item “x”:

    if ((Astro_Azimuth.state > az_X_dn) && (Astro_Azimuth.state < az_X_up) && (rs_X_auto.state == ON)) {
        if (rs_X.state < 90) {
        sendCommand(rs_X, 100)
        }
        if (rs_X_lm.state != 0) {
        sendCommand(rs_X_lm, 0)
        }
        logInfo("Beschattung","Fassade X Beschattung ein")
    }

i’m pretty shure i read something familiar in another topic but i can’t find the topic anymore :frowning:

i’d appreciate any input!

That’s a good start: Design Pattern: DRY, How Not to Repeat Yourself in Rules DSL

Yes, please see the DRY DP to help reduce the lines of code a bit.

But I have another comment. Avoid the use of primitives unless absolutely necessary. Even on a powerful machine, you can see .rules parsing and loading times in the minutes instead of single digit seconds caused only bu the use of primitives. And you don’t even need to use these as ints here. Just get rid of the “int” and the Rules DSL will know to make them into Numbers.

Just a hint, for topics you may want to reference at a later time, use bookmarks. Click the three dots located in bottom right of post then select the bookmark symbol. Not sure what the bookmark max is but I have a bunch and they help tons. Both for personal issues and helping others.:smiley:

1 Like

yeah… i was sure the topic was bookmarked but probably it’s a browser bookmark on some device :slight_smile:

hmm okay. i tried this page and subpages but i don’t even have an idea which approach i should try to understand. most examples have even more code so this probably would even more complex…

Start with Design Pattern: How to Structure a Rule

i should probably find something helpful in the 1-2-3 section, right?
1 - i could check if Astro_Azimuth.state is bigger than 168 (smallest trigger value) and maybe check of some of the rs_auto items are “ON”?
2 - i still have to determine for every item what has to be done (don’t i?)
3 - send all the commands???

or have i misunderstood your “hint”?

  1. Check to see if the role needs to run at all. If not return.

  2. Determine which items need which commands.

  3. Since your if statements to send the commands are all the same with the only difference being the item checked and the item commanded put that at the end just once instead of repeating it over and over again.

if Astro_Azimuth.state < 168 OR all items of group rs_auto = OFF
then return
???
all other conditions are checked in the if statements (which i should put at the end)

that’s the first part of my if statements… (which i should put at the end)

as described in the opening post i have no idea how to do just that.

Thanks for yout patience, but i’m totally lost with all this new information :confused:

i think i found a way to write the if statements to send the commands just once. (will post later, probably way to complex…)
but i’d also like to work on this 1-2-3 approach. how can i know if there’s any item in my group that matches the condition “ON”? i tried the RULES DSL and i even got results that make sense, but in the end i couldn’t figure out how to know “if any item of group xx == ON then”…

val numON = MyGroup.members.filter[itm | itm.state == ON].size
if(size > 0){
    // then
}

If you want to do something for all members of the Group that are ON

MyGroup.members.filter[itm | itm.state == ON].forEach[itm |
    // then
]

I didn’t notice before that the original is a series of if statements, not if else. But I think you are on the right track. Put the Items into a Group and loop through the members of the Group checking each room one by one. Use Design Pattern: Associated Items.

Hello again!
after some pretty intensive weeks with no time for openHAB now i’m sitting at my PC again and i’m wondering how to proceed with my raffstore :slight_smile:
Thanks to the help here i know how to do it in different rooms, but i’m not sure how the logical approach should be…

there are some rooms where raffstore just should go UP when Azimuth > x - this seems easy even to me:

    if ((Astro_Azimuth.state > az_kueche_up) && (rs_kueche_auto.state == ON)) {
        sendCommand(rs_kueche_auto, OFF)
        if (rs_kueche.state > 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist.
        sendCommand(rs_kueche, 0)
        }
        logInfo("Beschattung","Raffstore Küche nach oben")
    }

but there are rooms there are also rooms where there’s more to do:
Part A:

    if ((Astro_Azimuth.state > az_buero_dn) && (Astro_Azimuth.state < az_buero_up) && (rs_buero_auto.state == ON)) {
        if (rs_buero.state < 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist. Ansonsten werden die Raffstore bei der Änderung Azimuth gestellt!
        sendCommand(rs_buero, 100)
        }
        if (rs_buero_lm.state != 0) {
        sendCommand(rs_buero_lm, 0)
        }
        logInfo("Beschattung","Raffstore Buero wird automatisch gestellt")
    }

PART B:

    if ((Astro_Azimuth.state > az_buero_up) && (rs_buero_auto.state == ON)) {
        sendCommand(rs_buero_auto, OFF)
        if (rs_buero.state > 90) { // KNX stellt den Wert nicht genau auf 100, daher wird hier geprüft, ob der Wert nahe 100 ist.
        sendCommand(rs_buero, 0)
        }
        logInfo("Beschattung","Raffstore Büro nach oben")
    }

all this works for now but as i’m rewriting the whole rule with Design Patterns i’m wondering if there’s no better way to combine Part A & B…

my idea at the moment:

if (*_auto.state == ON)
    if (Astro_Azimuth.state > *_up) then do things in Part B
    if ((Astro_Azimuth.state > *_dn) && (Astro_Azimuth.state < *_up)) the do things in Part A

or i leave it like it is at the moment:

if ((*_auto.state == ON) && (Astro_Azimuth.state > *_up)) then do things in Part B
if ((*_auto.state == ON) && ((Astro_Azimuth.state > *_dn) && (Astro_Azimuth.state < *_up)) the do things in Part A

which approach makes more sense (and why?)?

new year, new hope!
any help would be appreciated! time to finish this rule :slight_smile:

Hello (again)!
I’m still trying to figure this out :frowning:
atm i have this:

items:

Group JalouAutoUpOnly

Rollershutter rs_foyer_mitte "Foyer mitte" (Jalou, JalouAutoUpOnly, Garten_RS, sNacht, Fassade1) { knx="2/2/16,2/2/15,2/2/17+<2/2/106" }
Rollershutter rs_foyer_mitte_lm "Foyer mitte LM" (Jalou_LM, Garten_LM, Fassade1_lm) { knx="2/2/15,2/2/15,2/2/18+<2/2/107" }
Switch rs_foyer_mitte_auto (rs_auto)

Rollershutter rs_gang_mitte "Gang mitte" (Jalou, JalouAutoUpOnly, sNacht, Fassade2) { knx="3/2/26,3/2/25,3/2/27+<3/2/109" }
Rollershutter rs_gang_mitte_lm "Gang mitte LM" (Jalou_LM, Fassade2_lm) { knx="3/2/25,3/2/25,3/2/28+<3/2/110" }
Switch rs_gang_mitte_auto (rs_auto)

rule:

rule "Test"
when
	Item Test_Button received command ON
then
	// ok rs_auto.members.filter [ i | i.state == ON ].forEach[i | logInfo("Steuerung", i.name + " ist ON!")]
	// rs_auto.members.findFirst [ i | i.state == ON ].sendCommand(OFF)

    val rs_foyer_mitte_up = 168
    val rs_gang_mitte_up = 207

	if (TagNacht.state == "Nacht") {
	//	logInfo("Raffstore Steuerung:", "Es ist Nacht, hier gibts nichts zu tun.")
		return;
	}

	// up_Only
	JalouAutoUpOnly.members.forEach( i | {
		val i_auto = ScriptServiceUtil.getItemRegistry.getItem(i.name + "_auto")
		val i_lm = ScriptServiceUtil.getItemRegistry.getItem(i.name + "_lm")
		val i_up = val(i.name + "_up")

		if ((Astro_Azimuth.state > i_up) && (i_auto.state == ON)) {
        sendCommand(i_auto, OFF)
        if (i.state > 90) {
        sendCommand(i, 0)
        }
        logInfo("Beschattung","Raffstore Garten OG nach oben")
    }

		
	})
end

how am supposed to use the val “i_up” for each item?
*_up is NOT an item but is a val defined in my rule…