Astro Rule vereinfachen / zusammenfassen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Astro Rule vereinfachen / zusammenfassen

Beitrag von domjo75 »

N'abend zusammen,

Ich bin noch immer fleißig dabei meine Klicki Bunti Regeln in .Rules zu packen.
Ob´s immer so sinnvoll ist, lass ich mal dahin gestellt, aber es macht Spass :)

Da ich viele Regeln redundant habe und aus verschiedenen Richtungen die gleichen Switches setze, habe ich auch dementsprechend viele Regeln.
So habe ich z.B. drei Regeln die, abhängig von der Helligkeit im Garten, meine Lichte, Rollo´s usw. steuern. Da schonmal unbemerkt mein Helligkeitssensor versagt hat (Batterie leer) und dadurch nix geschaltet wurde, habe ich parallel, noch Astro Regeln gebaut. Die Sonne und der Mond gehen ja immer ;)
Das jetzt in eine Rule zu bringen fällt mir schwer. Da ist meine Grenze erreicht und ich brauche Hilfe.
So sehen meine Regeln aus:

Code: Alles auswählen

rule "Sunrise / Sunset"
when
    Item Outdoor_Illuminance changed
then
    val minuteOfDay = now.toLocalTime.getHour * 60 + now.toLocalTime.getMinute
    if ( minuteOfDay >= 15 * 60 && minuteOfDay <= 22 * 60 ) {
        if(Outdoor_Illuminance.state <= 2 && isDark.state != ON) {
            logInfo("Sonnenuntergang", "isDark -> ON")
            isDark.sendCommand (ON)
        }
        if(Outdoor_Illuminance.state <= 25 && isDusk.state != ON) {
            logInfo("Sonnenuntergang", "isDusk -> ON")
            isDusk.sendCommand (ON)
        }
        if(Outdoor_Illuminance.state <= 150 && isNight.state != ON) {
            logInfo("Sonnenuntergang", "isNight -> ON")
            isNight.sendCommand (ON)
        }
    }

    if(Outdoor_Illuminance.state > 10 && isDark.state != OFF) {
        logInfo("Sonnenaufgang", "isDark -> OFF")
        isDark.sendCommand (OFF)
    }
    if(Outdoor_Illuminance.state > 35 && isDusk.state != OFF) {
        logInfo("Sonnenaufgang", "isDusk -> OFF")
        isDusk.sendCommand (OFF)
    }
    if(Outdoor_Illuminance.state > 170 && isNight.state != OFF) {
        logInfo("Sonnenaufgang", "isNight -> OFF")
        isNight.sendCommand (OFF)
    }
end
Die Astro-Rules sind ja geklickt, also dementsprechend so:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      thingUID: astro:sun:local
      event: START
      channelUID: astro:sun:local:set#event
    type: core.ChannelEventTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: isNight
      command: ON
    type: core.ItemCommandAction

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      thingUID: astro:sun:local
      event: START
      channelUID: astro:sun:later:set#event
    type: core.ChannelEventTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: isDark
      command: ON
    type: core.ItemCommandAction

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      thingUID: astro:sun:local
      event: START
      channelUID: astro:sun:earlier:set#event
    type: core.ChannelEventTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: isDusk
      command: ON
    type: core.ItemCommandAction
Den Trigger bekomme ich mit OR gerade noch verknüpft, allerdings muss ich ja dann im THEN auf das ASTRO Event reagieren und den richtigen Schalter setzen. kann ich EventTrigger so einfach mit IF abfragen ?

:)

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 243
Wohnort: Darmstadt

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von udo1toni »

Deine erste Rule kann eine lokale Konstante vertragen:

Code: Alles auswählen

rule "Sunrise / Sunset"
when
    Item Outdoor_Illuminance changed
then
    val minuteOfDay = now.toLocalTime.getHour * 60 + now.toLocalTime.getMinute
    val illluminance = Outdoor_Illuminance.state
    if ( minuteOfDay >= 15 * 60 && minuteOfDay <= 22 * 60 ) {
        if(illluminance <= 2 && isDark.state != ON) {
            logInfo("Sonnenuntergang", "isDark -> ON")
            isDark.postUpdate(ON)
        }
        if(illluminance <= 25 && isDusk.state != ON) {
            logInfo("Sonnenuntergang", "isDusk -> ON")
            isDusk.postUpdate(ON)
        }
        if(illluminance <= 150 && isNight.state != ON) {
            logInfo("Sonnenuntergang", "isNight -> ON")
            isNight.postUpdate(ON)
        }
    }
    if(illluminance > 10 && isDark.state != OFF) {
        logInfo("Sonnenaufgang", "isDark -> OFF")
        isDark.postUpdate(OFF)
    }
    if(illluminance > 35 && isDusk.state != OFF) {
        logInfo("Sonnenaufgang", "isDusk -> OFF")
        isDusk.postUpdate(OFF)
    }
    if(illluminance > 170 && isNight.state != OFF) {
        logInfo("Sonnenaufgang", "isNight -> OFF")
        isNight.postUpdate(OFF)
    }
end
Der Unterschied wird nicht wesentlich sein, aber eine lokale Konstante liegt im Zweifel direkt im Stack oder ist innerhalb 10 Taktzyklen abgefragt, während ein getState hunderte, wenn nicht sogar tausende Taktzyklen braucht, weil dazu ja jede Menge Code ausgeführt wird, um die Item Registry abzufragen.


Channel:
Immer daran denken: Rules sind Event-gesteuert. Events haben aber keinen Zustand. Du brauchst einfach weitere Rules:

Code: Alles auswählen

rule "astro sunset"
when
    Channel 'astro:sun:local:set#event' triggered START
then
    isNight.postUpdate(ON)
end

rule "astro sunset later"
when
    Channel 'astro:sun:later:set#event' triggered START
then
    isDark.postUpdate(ON)
end

rule "astro sunset earlier"
when
    Channel 'astro:sun:earlier:set#event' triggered START
then
    isDusk.postUpdate(ON)
end
Warum Du dafür allerdings drei Things nutzt, erschließt sich mir nicht vollständig. Gewöhnlich wird man für drei unterschiedliche Items auch drei voneinander unabhängige Trigger verwenden, also z.B. Sonnenuntergang, Bürgerliche Dämmerung und Nautische Dämmerung. (entsprechend 0°, -6° und -12° Höhenwinkel) das geht dann mit einem Thing, und man kann die Punkte individuell mit Offsets und Grenzwerten versehen.

Ich sehe allerdings auch nicht, was es für Vorteile bringen soll, einen unzuverlässigen Sensor überhaupt die Arbeit machen zu lassen, wenn man dann zusätzlich noch über Astro steuert. Lass den Sensor ruhig drin um die aktuelle Helligkeit abzulesen, aber verwende ihn nicht zu Steuerung.
Dass die erste Rule die Items nur innerhalb eines Zeitraums aktiviert, sie aber jederzeit wieder deaktiviert, ist Absicht?
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von domjo75 »

Hallo Udo,
es freut mich, dass ich wieder was dazu lernen konnte. Ich werde in all meinen Rules die getStates ersetzen.

Schade, dass es keine Möglichkeit gibt das Ganze in nur eine Rule zu legen. Ich finde zu viele Rules unübersichtlich. Aber gut, so ist das dann eben.
Ich hatte ja geschrieben, dass mir mein Helligkeitssensor irgendwann mal ausgestiegen ist und daraufhin meine Trigger nicht mehr gesetzt wurden. Wenn die Frau im Dunklen sitzt muss ein Fallback her. Und das sind eben die Astros.

Die Astro Things habe ich zu Beginn meiner OH3 Erfahrung erstellt. Da war ich noch froh, dass überhaupt was geht :) Das könnte ich natürlich mal anpassen.

Danke für die Hilfe

Benutzeravatar
rfu
Beiträge: 24
Registriert: 8. Okt 2021 15:41
Answers: 0

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von rfu »

Hi,

ich weiß nicht genau was Du am Ende damit anfangen willst, aber für mich war es sehr viel einfacher, ein item an den "Sonnenphase" channel zu binden... In meinen Rules reagiere ich dann auf Änderung dieses einen items:

Code: Alles auswählen

rule "Dämmerung"
when
    Item LokaleSonnendaten_Sonnenphase changed
then
    if (LokaleSonnendaten_Sonnenphase.state == "CIVIL_DAWN") {
        // aussensteckdose früher aus...
        Aussensteckdose_AussenSteckdose.sendCommand(OFF)
    } else if (LokaleSonnendaten_Sonnenphase.state == "SUN_RISE") {
        Aussenlicht_Switch.sendCommand(OFF)
    } else if (LokaleSonnendaten_Sonnenphase.state == "CIVIL_DUSK") {
        Aussenlicht_Switch.sendCommand(ON)
        Aussensteckdose_AussenSteckdose.sendCommand(ON)
    }
end
rfu
openHAB 3.3.0 im docker

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von domjo75 »

rfu hat geschrieben: 17. Mär 2022 18:10 Hi,

ich weiß nicht genau was Du am Ende damit anfangen willst, aber für mich war es sehr viel einfacher, ein item an den "Sonnenphase" channel zu binden... In meinen Rules reagiere ich dann auf Änderung dieses einen items:

Code: Alles auswählen

rule "Dämmerung"
when
    Item LokaleSonnendaten_Sonnenphase changed
then
    if (LokaleSonnendaten_Sonnenphase.state == "CIVIL_DAWN") {
        // aussensteckdose früher aus...
        Aussensteckdose_AussenSteckdose.sendCommand(OFF)
    } else if (LokaleSonnendaten_Sonnenphase.state == "SUN_RISE") {
        Aussenlicht_Switch.sendCommand(OFF)
    } else if (LokaleSonnendaten_Sonnenphase.state == "CIVIL_DUSK") {
        Aussenlicht_Switch.sendCommand(ON)
        Aussensteckdose_AussenSteckdose.sendCommand(ON)
    }
end
rfu
Das sieht interessant aus. Muss ich mal beobachten wann welche Phase eintritt.

Was ich erreichen will ist schnell erklärt. Ich habe 3 Switches isNight, isDusk, isDark.
isNight schaltet die Ambiente Beleuchtung an
isDusk fährt die Rollos auf 25%
isDark schliesst bestimmte Rollos

Alle 3 Switches werden via Helligkeitssensor und Astro (nur falls der Helligkeitss. nicht geht) getriggert.
Für die Helligkeit brauche ich nur eine Rule.
Für die Astro-Werte sechs. Ich möchte das einfach gerne in einer Rule haben. Das ist alles. :)

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 243
Wohnort: Darmstadt

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von udo1toni »

Vergiss das mal mit "nur eine Rule", das ist nicht zielführend. Das hat auch nichts mit unübersichtlich zu tun, unübersichtlich wird es höchstens, wenn Du viele Rules durcheinander würfelst.
Wenn Du hingegen alle Rules, die sich um einen bestimmten Aspekt Deiner Steuerung kümmern zusammen hältst (und natürlich auch vernünftig mit Kommentaren versiehst), sollte es auch mit viel mehr Rules nicht unübersichtlich werden.

Ich habe momentan etwa 1150 Zeilen Code für Rules, aufgeteilt in zwei Dateien, die eine kümmert sich exklusiv um meine zwei Hoftore (jeweils zweiflügelig, die Rules versuchen, jeweils den Öffnungsgrad für beide Torflügel zu errechnen), diese Rules sind ein einziger Sauhaufen, weil ich sie vor etwa 10 Jahren geschrieben, und seitdem nicht mehr angefasst habe (aus Gründen... ;) ).
In der anderen Datei sind alle anderen Rules, die sich vor allem um Beschattung, Lüfternachlauf und Musiksteuerung im ganzen Haus kümmern, aber z.B. auch um alle Heizungsthermostate:

Code: Alles auswählen

rule "Betriebsart RTR"
 when
    Member of GHeat_Mode changed
 then
    var Integer newMode 
    val mode = (triggeringItem.state as DecimalType).toBigDecimal.toBigInteger
    val iName = triggeringItem.name.split("_").get(0).toString
    logDebug("rtr","Name is: {}, Mode is: {}",iName,mode)
    switch (mode) {
        case mode.testBit(0) : newMode = 1
        case mode.testBit(2) : newMode = 3
        case mode.testBit(3) : newMode = 4
        default : newMode = 2
    }
    var myItem = GHeat_Set.members.filter[ f | f.name.startsWith(iName) ].head
    var Integer oldMode = 0
    if(myItem.state instanceof Number) oldMode = (myItem.state as Number).intValue
    if(oldMode != newMode) {
        logDebug("rtr","Name is: {}, oldMode is: {}, newMode is: {}",myItem.name,oldMode,newMode)
        myItem.postUpdate(newMode)
    }
end
Das ist ein Beispiel, wie man mit einer Rule beliebig viele gleichartige Items betreuen kann.
Es geht hier darum, einen Wert aus einem Item in einen anderen Wert umzurechnen und diesen in ein zweites Item zu schreiben. Dabei ist der genaue Name der beteiligten Items nicht bekannt, sondern wird zur Laufzeit der Rule bestimmt.
Die Items liegen jeweils in den Group Items GHeat_Mode und GHeat_Set, die Namen der Items lassen sich voneinander ableiten, das ist schon der ganze Trick. Eine Rule, sie alle zu finden, ins Dunkel zu ziehen und ewig zu binden...

Ähm... geht gleich wieder... ;)

Bevor es die Möglichkeit gab, über die implizite Variable triggeringItem herauszufinden, welches Item die Rule gestartet hat, musste ich die Rule (leicht vereinfacht, weil ja der Name nicht bestimmt werden muss) neun mal pflegen, DAS war unübersichtlich.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von domjo75 »

Wenn das zu viel Aufwand, am Zweck gemessen, ist, werde ich das sein lassen. Ist ja auch etwas Spielerei um was zu lernen.

Benutzeravatar
rfu
Beiträge: 24
Registriert: 8. Okt 2021 15:41
Answers: 0

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von rfu »

Hi,
Das sieht interessant aus. Muss ich mal beobachten wann welche Phase eintritt.
Die Phasen sind

Code: Alles auswählen

SUN_RISE, ASTRO_DAWN, NAUTIC_DAWN, CIVIL_DAWN, CIVIL_DUSK, NAUTIC_DUSK, ASTRO_DUSK, SUN_SET, DAYLIGHT, NIGHT
siehe https://www.openhab.org/addons/bindings/astro/.

rfu
openHAB 3.3.0 im docker

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 243
Wohnort: Darmstadt

Re: Astro Rule vereinfachen / zusammenfassen

Beitrag von udo1toni »

domjo75 hat geschrieben: 18. Mär 2022 08:53 Wenn das zu viel Aufwand, am Zweck gemessen, ist, werde ich das sein lassen. Ist ja auch etwas Spielerei um was zu lernen.
Du meinst, alles in eine Rule zu quetschen? Der Punkt ist, dass es nicht möglich ist. Vielleicht habe ich das oben vergessen zu erwähnen...

Rules sind immer ereignisgesteuert. Die Range Event Channel im astro Binding generieren Events zu den Zeitpunkten, an denen das betreffende Ereignis eintritt. Man kann sie aber nicht abfragen, denn diese Channel haben keinen Zustand.
Du könntest die betreffenden Zeitpunkte erfragen, indem Du die jeweiligen DateTime Channel auswertest.
Du kannst auch den Sonnenphasen Channel verwenden, wobei der im Gegensatz zu den Range Event Channels keinen Offset erlaubt. Dafür kannst Du aber eine Rule auf Item Sonnenphase changed triggern lassen, denn die Änderung ist ja wieder ein Ereignis. Innerhalb der Rule kannst Du dann nach Zustand unterscheiden, mit diversen if() else if() Anweisungen, oder (sieht hübscher aus) einem switch case:

Code: Alles auswählen

...
then
switch(newState.toString) {
    case "SUN_RISE"    : {...}
    case "ASTRO_DAWN"  : {...}
    case "NAUTIC_DAWN" : {...}
    case "CIVIL_DAWN"  : {...}
    case "CIVIL_DUSK"  : {...}
    case "NAUTIC_DUSK" : {...}
    case "ASTRO_DUSK"  : {...}
    case "SUN_SET"     : {...}
    case "DAYLIGHT"    : {...}
    case "NIGHT"       : {...}
})
Eventuell
Damit hast Du maximale Flexibilität. Auf der anderen Seite kannst Du Dir dann den Helligkeitssensor getrost sparen und innerhalb der Rules, in denen Du den jeweiligen Zustand brauchst direkt das Item Sonnenphase abfragen, wobei es natürlich unpraktisch ist, wenn Du wissen willst, ob es nach Sonnenuntergang und vor Sonnenaufgang ist, denn Du musst dann mindestens drei Fälle negativ abfragen (!= "DAYLIGHT" && != "SUN_RISE" && != "SUN_SET") oder sieben verschiedene Fälle positiv (== "ASTRO_DAWN" || == "ASTRO_DUSK" || ...)
Es läuft dann also darauf hinaus, dass Du doch wieder eine Rule (immerhin nur eine) verwendest, um ungebundene Switch Items in ihren Zustand zu bringen, wenn der entsprechende Zeitpunkt erreicht ist.

Man könnte allerdings ein Number Item nehmen und z.B. Nacht = 0 und Tag = 5 annehmen, die Zwischenstufen 1 - 4 sind dann die verschiedenen Phasen (definiert nach Höhenbereich in dem sich die Sonne befindet. Dann kann man auf < oder > prüfen, je nach Bedarf, alles über ein Item.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten