Seite 2 von 6

Re: Storen nach x-Sekunden stoppen

Verfasst: 22. Jun 2023 06:51
von Norick
Danke für den Hinweis für das Widget, das kann ich zusätzlich auch sehr gut verwenden. Ich denke meine Frage war schon korrekt, da ich aus einer Rule heraus die Position x anfahren möchte. Das heisst die Rule triggert zum Beispiel bei Sonneneinstrahlung oder bei einer Temperatur und fähr dann die Store auf eine neue Position.

Muss ich in diesem Fall deine Rule noch bzw. WIE kann diese dann in der neuen Rule verwenden?




Wenn ich jetzt eine neue Rule über das UI anlege kann ich als Item eine Store auswählen. Danach sehe ich unter "Then" das "send a command to" resp. weiter unter stehen dann die drei Commands zur Auswahl (UP, DOWN, STOP). Hier gibt es jedoch auch noch das Feld "Command to send" welches leer ist.

Frage:
Wie kann ich jetzt in dieser Rule der Store sagen sie soll auf 60 % fahren?

Re: Storen nach x-Sekunden stoppen

Verfasst: 22. Jun 2023 21:27
von udo1toni
Na, Du schreibst einfach die 60 in das leere Feld rein. Für Rollershutter Items stehen die Befehle UP/DOWN/STOP und 0 - 100 zur Verfügung, als Status werden die Werte 0 - 100 gemeldet. Die Auswahl der möglichen Befehle über die Radiobuttons ist halt auf die drei allgemeinen beschränkt, man müsste sonst ein Kombinationsfeld bauen oder eine Liste mit 104 Werten zur Auswahl. Stattdessen gibt es halt den zu sendenen Befehl als leeres Feld, in welches über die Radiobuttons drei Werte automatisiert eingetragen werden können. Die anderen Werte muss man aber per Hand eintragen.

Re: Storen nach x-Sekunden stoppen

Verfasst: 23. Jun 2023 07:00
von Norick
habe ich eigentlich auch so verstanden. Wenn ich nun deine Rule mit dem Trigger verbinde bekomme ich eine Fehlermeldung angezeigt. Hier die Rule:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Wetterstation_Dach_Aussentemperatur
    type: core.ItemStateUpdateTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: Wetterstation_Dach_Aussentemperatur
      state: 20 °C
      operator: ">"
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "3"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        /Globale Variablen und Konstanten immer vor der ersten Rule definieren!

        val Integer iStoreUp    = 29500 // 29,5 Sekunden aufwärts

        val Integer iStoreDown  = 27300 // 27,3 Sekunden  abwärts

        var Timer   tStore      = null  // Timer für Positionsfahrt

        var Long    lStoreStart = null  // Startzeit für UP/DOWN Fahrt

        var Boolean bStoreDir   = false // Richtung (false = UP)

        var Integer iSoll       = null  // Sollposition

        Rule "drive store"

        when
            Item KNX_Device_Storen_Essen_Wohnen_Essen received command
        then
            val Integer iPos = (KNX_Device_Storen_Essen_Wohnen_Essen.state as Number).intValue                  // Ermittle Ist-Position
            switch(receivedCommand) {
                case UP   : {
                    StoreControl.sendCommand(UP)                                     // Bei Aufwärts-Befehl sende UP
                    bStoreDir = false                                                // Merke Fahrtrichtung
                    lStoreStart = now.toInstant.toEpochMilli                         // Merke Startzeit
                }
                case DOWN : {
                    StoreControl.sendCommand(DOWN)                                   // Bei Abwärts-Befehl sende DOWN
                    bStoreDir = true                                                 // Merke Fahrtrichtung
                    lStoreStart = now.toInstant.toEpochMilli                         // Merke Startzeit
                }
                case STOP : {
                    StoreControl.sendCommand(STOP)                                   // Bei Stopp-Befehl sende STOP
                    val Long lDiff = lStoreStart - now.toInstant.toEpochMilli        // Errechne Fahrtzeit
                    val Integer iPosNew = if(bStoreDir) {                            // Abhängig von der Fahrtrichtung
                                              iPos - (lDiff/iStoreUp*100).intValue   // Bestimme neue Position
                                          } else {
                                              iPos + (lDiff/iStoreDown*100).intValue // Bestimme neue Position
                                          }
                    KNX_Device_Storen_Essen_Wohnen_Essen.postUpdate(iPosNew)                                    // Schreibe neue Position
                }
                default   : {                                                        // Befehl ist eine Zahl
                                iSoll = (receivedCommand as Number).intValue         // Bestimme Sollposition
                    val Integer iMove = iSoll - iPos                                 // Bestimme Teilstrecke
                    var Integer iTime = 0                                            // Initialisiere Variable
                    if(iMove < 0) {                                                  // Aufwärts
                        iTime = -(iStoreUp * iMove)                                  // Errechne Fahrtdauer
                        StoreControl.sendCommand(UP)                                 // Starte Fahrt
                    } else if(iMove > 0) {                                           // Abwärts
                        iTime = iStoreDown * iMove                                   // Errechne Fahrtdauer
                        StoreControl.sendCommand(DOWN)                               // Starte Fahrt
                    }
                    tStore?.cancel                                                   // lösche Timer, falls vorhanden
                    tStore = createTimer(now.plusNanos(iTime*10000),[                // Starte Timer für Stopp-Befehl
                        StoreControl.sendCommand(STOP)                               // Stoppe Fahrt
                        KNX_Device_Storen_Essen_Wohnen_Essen.postUpdate(iSoll)                                  // setze neue Position
                    ])
                }
            }
        end
    type: script.ScriptAction
  - inputs: {}
    id: "4"
    configuration:
      itemName: KNX_Device_Storen_Essen_Wohnen_Essen
      command: "50"
    type: core.ItemCommandAction

Re: Storen nach x-Sekunden stoppen

Verfasst: 23. Jun 2023 14:03
von udo1toni
Vergiss bitte meine Rule, die bezog sich ja darauf, dass Du einen Aktor OHNE direkte Positionsfahrt hast.

Re: Storen nach x-Sekunden stoppen

Verfasst: 2. Jul 2023 08:34
von Norick
vielen Dank für die Erklärungen. Die Storen ohne Positionsfahrten funktionieren jetzt, wobei doch noch eine Store keine Positionsfahrt unterstützt :(
Das heisst ich kann (muss) doch noch deine Rule verwenden. Dies habe ich dann so wie oben beschrieben gemacht aber es funktioniert so nicht ganz. Das stimmt so, dass ich die Rule lokal speichern muss UND zusätzlich in meiner Rule wo ich die Store dann triggere nochmals deine Rule verwenden muss mit dem Storenitem jeweils?

Danke

Re: Storen nach x-Sekunden stoppen

Verfasst: 2. Jul 2023 13:41
von udo1toni
Bei den Aktoren, die keine Positionsfahrt unterstützen, brauchst Du wie beschrieben ein Proxy Item - also eines, welches gegenüber dem Anwender als Stellvertreter verwendet wird.
Das Proxy Item unterstützt die Positionsfahrt mithilfe der Rule. Die Steuerung erfolgt dann ausschließlich mit dem Proxy Item, d.h. wenn Du über eine Automation den Store zur Hälfte schließen willst, sendest Du den Befehl 50 an das Proxy Item. Das Proxy Item triggert die Rule, welche anhand der aktuellen Position, der Sollposition und der Laufzeiten errechnet, wie lange der Store in welche Richtung gefahren werden muss. Die Rule startet dann den Store über das "echte" Item, welches keine Positionsfahrt unterstützt (aber sehr wohl die Befehle UP/DOWN/STOP).
Wenn Du in der UI auf den Store zugreifen willst, geschieht das ebenfalls über das Proxy Item, so dass Du als Anwender einfach nur die gewünschte Position wählst, die Rule kümmert sich um den Rest.

Re: Storen nach x-Sekunden stoppen

Verfasst: 11. Jul 2023 06:46
von Norick
Verstehe was du meinst. Zum Punkt mit dem "Proxy Item" noch folgende Fragen: In diesem Fall kann ich einfach unter "Items" ein "New Item" anlegen und zwar für jeden einzelnen Storen separat welche keine Positionsfahrten untesrstützen?

Unter "Group Membership" wähle ich dann die entsprechende Store dann aus um das Proxy Item dann anzulegen und mit der Rule zu verknüpfen?

Danke

Re: Storen nach x-Sekunden stoppen

Verfasst: 11. Jul 2023 10:27
von udo1toni
Ja, genau.

Re: Storen nach x-Sekunden stoppen

Verfasst: 18. Jul 2023 06:40
von Norick
so jetzt habe ich es geschafft eine"Proxy STore" anzulegen welche verlinkt ist mit der richtigen Store welche keine Positionsfahrten unterstützt. Danach habe ich eine Rule angelegt welche bei >20°C diese Store auf eine Position x fahren soll. Dazu habe ich dann einfach die DSL Rule welche du mir gegeben hast ausgewählt (unter THEN).
In dieser DSL, welche ich auf lokal abgelegt habe, ist jeweils die "Proxy Store" eingetragen. Stimmt das so, oder muss im Skript dann doch die "richtige" Store rein?

Die zweite Frage bezieht sich auf die Position x die ich anfahren möchte. Wo gebe ich dies in der Rule (UI) ein? Muss dies direkt in der DSL Rule eingegeben werden oder wo kann ich dies setzten?

Hier meine Rule:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Wetterstation_Dach_Aussentemperatur
    type: core.ItemStateUpdateTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: Wetterstation_Dach_Aussentemperatur
      state: 20 °C
      operator: ">"
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "3"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        /Globale Variablen und Konstanten immer vor der ersten Rule definieren!

        val Integer iStoreUp    = 29500 // 29,5 Sekunden aufwärts

        val Integer iStoreDown  = 27300 // 27,3 Sekunden  abwärts

        var Timer   tStore      = null  // Timer für Positionsfahrt

        var Long    lStoreStart = null  // Startzeit für UP/DOWN Fahrt

        var Boolean bStoreDir   = false // Richtung (false = UP)

        var Integer iSoll       = null  // Sollposition

        Rule "drive store"

        when
            Item ProxyStore_Wohnung_Essen received command
        then
            val Integer iPos = (ProxyStore_Wohnung_Essen.state as Number).intValue                  // Ermittle Ist-Position
            switch(receivedCommand) {
                case UP   : {
                    StoreControl.sendCommand(UP)                                     // Bei Aufwärts-Befehl sende UP
                    bStoreDir = false                                                // Merke Fahrtrichtung
                    lStoreStart = now.toInstant.toEpochMilli                         // Merke Startzeit
                }
                case DOWN : {
                    StoreControl.sendCommand(DOWN)                                   // Bei Abwärts-Befehl sende DOWN
                    bStoreDir = true                                                 // Merke Fahrtrichtung
                    lStoreStart = now.toInstant.toEpochMilli                         // Merke Startzeit
                }
                case STOP : {
                    StoreControl.sendCommand(STOP)                                   // Bei Stopp-Befehl sende STOP
                    val Long lDiff = lStoreStart - now.toInstant.toEpochMilli        // Errechne Fahrtzeit
                    val Integer iPosNew = if(bStoreDir) {                            // Abhängig von der Fahrtrichtung
                                              iPos - (lDiff/iStoreUp*100).intValue   // Bestimme neue Position
                                          } else {
                                              iPos + (lDiff/iStoreDown*100).intValue // Bestimme neue Position
                                          }
                    ProxyStore_Wohnung_Essen.postUpdate(iPosNew)                                    // Schreibe neue Position
                }
                default   : {                                                        // Befehl ist eine Zahl
                                iSoll = (receivedCommand as Number).intValue         // Bestimme Sollposition
                    val Integer iMove = iSoll - iPos                                 // Bestimme Teilstrecke
                    var Integer iTime = 0                                            // Initialisiere Variable
                    if(iMove < 0) {                                                  // Aufwärts
                        iTime = -(iStoreUp * iMove)                                  // Errechne Fahrtdauer
                        StoreControl.sendCommand(UP)                                 // Starte Fahrt
                    } else if(iMove > 0) {                                           // Abwärts
                        iTime = iStoreDown * iMove                                   // Errechne Fahrtdauer
                        StoreControl.sendCommand(DOWN)                               // Starte Fahrt
                    }
                    tStore?.cancel                                                   // lösche Timer, falls vorhanden
                    tStore = createTimer(now.plusNanos(iTime*10000),[                // Starte Timer für Stopp-Befehl
                        StoreControl.sendCommand(STOP)                               // Stoppe Fahrt
                        ProxyStore_Wohnung_Essen.postUpdate(iSoll)                                  // setze neue Position
                    ])
                }
            }
        end
    type: script.ScriptAction

Re: Storen nach x-Sekunden stoppen

Verfasst: 18. Jul 2023 18:17
von udo1toni
Nein, das ist so nicht das, was ich beschrieben habe. :)

Punkt 1: Das Proxy Item wird nicht verlinkt. Überhaupt nicht. (Ein Link ist immer die Verbindung zu einem Channel, den es in diesem Fall nicht gibt)
Punkt 2: Du legst eine Rule an, welche über das Proxy Item getriggert wird, per received command.
Diese Rule errechnet anhand der vorher gemessenen Laufzeiten (getrennt für beide Richtungen, kann aber sein, dass bei horizontaler Bewegung beide Richtungen gleich lang sind, dann kannst Du natürlich auch mit nur einer Zeit arbeiten, aber bitte ausmessen) und der von der vorherigen Fahrt bekannten (gleich...) Position: bei den verschiedenen Befehlen verschiedene Dinge erledigt:
  • Bei UP/DOWN den Startzeitpunkt speichern, so dass bei STOP die Dauer gemessen werden kann, außerdem wird der empfangene Befehl 1:1 an das "echte" Item geschickt.
  • Bei STOP aus der vergangenen Fahrtdauer die neue Position berechnen und im Proxy Item speichern (per postUpdate). Außerdem wird an das "echte" Item der Befehl STOP gesendet.
  • Bei einer Positionsangabe errechnen, wie viele Sekunden die Soll-Position von der Ist-Position entfernt ist und in welche Richtung der Antrieb laufen muss, den Antrieb starten und einen Timer starten, der den Antrieb nach der errechneten Zeit stoppt. Außerdem kann dieser Teil der Rule gleich die neue Ist-Position per postUpdate im Proxy Item speichern.
All das erledigt die weiter oben gezeigte Rule.

Wenn Du nun bei > 20 °C den Store in Position X fahren willst, schreibst Du eine Rule, welche bei Temperatur changed triggert.
Über but only if legst Du fest, dass der Rule Code nur ausgeführt werden soll, wenn die Temperatur größer 20 °C ist.
Außerdem soll die Rule nur ausgeführt werden, wenn das Proxy Item (nicht das "echte") von der angegebenen Position abweicht. Wobei es vermutlich sinnvoll ist, sich hier für einen Bereich zu entscheiden, also z.B. Store soll zu 80 % geschlossen werden -> Alles was über 75 % ist, wird als "Store steht schon auf Sollposition" gewertet, also ProxyItem <= 75.
In der Rule wird als Action nur ein einziger Befehl ausgeführt, nämlich ProxyItem.sendCommand(80).

Das heißt, Du legst zwei Rules an, die eine kümmert sich ausschließlich um die Positionsfahrt als solche, die andere gibt ausschließlich einen Steuerbefehl.
In der UI wird ausschließlich das Proxy Item sichtbar gemacht. Du bedienst den Store - soweit es openHAB betrifft - ausschließlich über das Proxy Item.
Proxy -> Stellvertreter. Das Proxy Item nimmt die Position des "echten" Items stellvertretend ein. Über die Rule im Hintergrund hat es zusätzliche Fähigkeiten, das ist der ganze Sinn der Aktion, es wird das Verhalten eines Aktors mit eingebauter Positionsfahrt emuliert.

Da Laufzeiten niemals auf die Millisekunde gleich sein werden (selbst für exakt gleiche Strecken in der gleichen Richtung) muss man mit gewissen Toleranzen leben. Das ist aber erfahrungsgemäß kein echtes Problem, da - z.B. in diesem Fall - ein Store oft immer mal wieder in eine der beiden Endstellungen gefahren wird (über UP oder DOWN, ohne selbst ein STOP zu senden). Man kann also nun die STOP-Meldung vom Aktor registrieren und mit in die Steuerung einbeziehen.
Eine weitere Möglichkeit besteht darin, bei UP/DOWN einen Timer zu starten, der nach tMax (also der maximal möglichen Laufzeit) zusätzlich ein STOP an das Proxy Item sendet, womit die Rule getriggert wird. Da im Zweifel mehr als die maximal mögliche Zeit vergangen ist, kommt bei der Berechnung der Position entweder ein negativer Wert heraus -> neue Position 0, oder es kommt ein Wert über 100 raus -> neue Position 100.

Ich hab jetzt gerade keine Lust, zu prüfen, ob ich das oben schon eingebaut habe, falls nicht, ist es jedenfalls keine große Sache, das nachzurüsten.