Storen nach x-Sekunden stoppen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

So, hat mir jetzt keine Ruhe gelassen...

Ich habe herausgefunden, wie man nativ Millisekunden verwenden kann :) das macht die Werte beim Debuggen etwas besser lesbar... Außerdem ist die Berechnung nun "ordentlich".
Weiterhin habe ich nun auch folgende Fälle abgefangen:
1. Aufwärts/Abwärts Fahrt, die nicht von Hand gestoppt wird -> openHAB sendet nach der gesetzten Maximalzeit iStoreUp bzw. iStoreDown einen Stop Befehl und setzt den Status auf 0 bzw. 100 %. Auf diese Weise sollte man nun den Store jederzeit "synchronisieren" können, einfach die Endlage anfahren lassen und warten.
2. Stop aus Stop -> Es darf keine Berechnung erfolgen, wird durch gezieltes Leeren der Startzeit erreicht.

Code: Alles auswählen

// 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 Proxy_Store_Essen received command
then
    logDebug("store","Rule gestartet mit Befehl {}",receivedCommand)

    var Integer iPos = 0                                                                               // Defaultwert 0, falls kein Wert vorhanden
    if(Proxy_Store_Essen.state instanceof Number)                                                      // falls gültiger Wert
        iPos = (Proxy_Store_Essen.state as Number).intValue                                            // setze Ist-Position
    logDebug("store","Aktuelle Position {}",iPos)

    switch(receivedCommand) {                                                                          // abhängig vom empfangenen Befehl
        case UP   : {                                                                                  // Aufwärts:
            Store_WohnenEssen.sendCommand(UP)                                                          // sende UP
            bStoreDir = false                                                                          // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                                                   // Merke Startzeit
            logDebug("store","UP erkannt, Starte Messung ({})",lStoreStart)
            tStore?.cancel                                                                             // lösche Timer, falls vorhanden
            tStore = createTimer(now.plus(iStoreUp,MILLIS),[                                           // Starte Timer für Stopp-Befehl
                Store_WohnenEssen.sendCommand(STOP)                                                    // Stoppe Fahrt
                Proxy_Store_Essen.postUpdate(0)                                                        // setze neue Position
                lStoreStart = null                                                                     // Startzeitpunkt leeren
            ])
        }
        case DOWN : {                                                                                  // Abwärts:
            Store_WohnenEssen.sendCommand(DOWN)                                                        // sende DOWN
            bStoreDir = true                                                                           // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                                                   // Merke Startzeit
            logDebug("store","DOWN erkannt, Starte Messung ({})",lStoreStart)
            tStore?.cancel                                                                             // lösche Timer, falls vorhanden
            tStore = createTimer(now.plus(iStoreDown,MILLIS),[                                         // Starte Timer für Stopp-Befehl
                Store_WohnenEssen.sendCommand(STOP)                                                    // Stoppe Fahrt
                Proxy_Store_Essen.postUpdate(100)                                                      // setze neue Position
                lStoreStart = null                                                                     // Startzeitpunkt leeren
            ])
        }
        case STOP : {                                                                                  // Stopp:
            tStore?.cancel                                                                             // lösche Timer, falls vorhanden
            logDebug("store","STOP erkannt, Berechne {} - {}",now.toInstant.toEpochMilli, lStoreStart)
            Store_WohnenEssen.sendCommand(STOP)                                                        // sende STOP
            if(lStoreStart === null)                                                                   // falls keine Startzeit
                return;                                                                                // Abbruch, da keine BErechnung möglich
            val Long lDiff = now.toInstant.toEpochMilli - lStoreStart                                  // Errechne Fahrtzeit
            var Integer iPosNew
            if(bStoreDir) {                                                                            // Abhängig von der Fahrtrichtung
                iPosNew = iPos + (lDiff/iStoreUp*100).intValue                                         // Bestimme neue Position
            } else {
                iPosNew = iPos - (lDiff/iStoreDown*100).intValue                                       // Bestimme neue Position
            }
            logDebug("store","Diff ohne Begrenzung: {} Pos: {} Pos neu: {}", lDiff, iPos, iPosNew)
            if(iPosNew < 0)   iPosNew = 0                                                              // Bei unterschreiten auf 0 begrenzen
            if(iPosNew > 100) iPosNew = 100                                                            // Bei überschreiten auf 100 begrenzen
            logDebug("store","Diff: {} Pos: {} Pos neu: {}", lDiff, iPos, iPosNew)
            Proxy_Store_Essen.postUpdate(iPosNew)                                                      // Schreibe neue Position
            lStoreStart = null                                                                         // Startzeitpunkt leeren
        }
        default   : {                                                                                  // Befehl ist eine Zahl
            iSoll = (receivedCommand as Number).intValue                                               // Bestimme Sollposition
            logDebug("store","Positionsfahrt erkannt ({} %)", iSoll)
            val Integer iMove = (iSoll - iPos).intValue                                                // Bestimme Teilstrecke
            var Long iTime = 0                                                                         // Initialisiere Variable
            logDebug("store","aktuelle Position {} %, Fahrt {}", iPos, iMove)
            if(iMove < 0) {                                                                            // Teilstrecke negativ -> Aufwärts
                iTime = -(iStoreUp * iMove / 100).intValue                                             // Errechne Fahrtdauer
                logDebug("store","Aufwärts Fahrt {}", iTime)
                Store_WohnenEssen.sendCommand(UP)                                                      // Starte Fahrt
            } else if(iMove > 0) {                                                                     // Teilstrecke positiv -> Abwärts
                iTime = (iStoreDown * iMove / 100).intValue                                            // Errechne Fahrtdauer
                logDebug("store","Abwärts Fahrt {}", iTime)
                Store_WohnenEssen.sendCommand(DOWN)                                                    // Starte Fahrt
            }
            logDebug("store","Strecke von {} % nach {} % = {} % ({} mSec)", iPos, iSoll, iMove, iTime)
            tStore?.cancel                                                                             // lösche Timer, falls vorhanden
            tStore = createTimer(now.plus(iTime,MILLIS),[                                              // Starte Timer für Stopp-Befehl
                Store_WohnenEssen.sendCommand(STOP)                                                    // Stoppe Fahrt
                Proxy_Store_Essen.postUpdate(iSoll)                                                    // setze neue Position
            ])
        }
    }
end
Der Code kann eventuell noch verbessert werden, gibt es doch viele Doppelungen. Da es aber in der DSL keine Sprunganweisungen gibt, bliebe nur, Teile des Codes als Lambda abzubilden, was gewöhnlich eher komplexer als einfacher wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Norick
Beiträge: 250
Registriert: 31. Jan 2022 06:35
Answers: 0

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Danke für das neue Skript. Nun ich habe das letzte genommen bzw. die Metadaten angepasst. Beim ersten Mal ist das Skript wie vorher schon nicht gelaufen weil die iPos nicht stimmte. Diese war immer gleich gross :roll:

Ich habe den Fehler aber gefunden und hier angepasst:

Code: Alles auswählen

var Integer iPos = 0                                                                               // Defaultwert 0, falls kein Wert vorhanden
    if(Store_WohnenEssen.state instanceof Number)                                                      // falls gültiger Wert
        iPos = (Store_WohnenEssen.state as Number).intValue                                            // setze Ist-Position

Hier war fälschlicherweise noch die "Proxy Store" drinnen...

Jetzt funktioniert es aber super! Hier das Log:

Code: Alles auswählen

[DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl 20
 [DEBUG] [org.openhab.core.model.script.store ] - Aktuelle Position 0
 [DEBUG] [org.openhab.core.model.script.store ] - Positionsfahrt erkannt (20 %)
 [DEBUG] [org.openhab.core.model.script.store ] - aktuelle Position 0 %, Fahrt 20
 [DEBUG] [org.openhab.core.model.script.store ] - Abw rts Fahrt 5460
 [DEBUG] [org.openhab.core.model.script.store ] - Strecke von 0 % nach 20 % = 20 % (5460 mSec)
 [DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl UP
 [DEBUG] [org.openhab.core.model.script.store ] - Aktuelle Position 11
 [DEBUG] [org.openhab.core.model.script.store ] - UP erkannt, Starte Messung (1691819932899)

Wenn ich den UP Befehl sende stoppt der Motor auch wenn er ganz oben ist.

Ich denke das wars dann mit dieser Store :D
Vielen Dank von meiner Seite für die Unterstützung und das Skript!!!

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Nein. Mit Verlaub, Diese Änderung bewirkt im Gegenteil, dass das Script keinesfalls korrekt funktioniert!

Offensichtlich hast Du ein Konfigurationsproblem mit Deinem Store Aktor, der sehr wohl direkte Positionsfahrten unterstützt - denn sonst könnte das von Dir verwendete Item niemals korrekte Positionsdaten liefern.

Die Rule von oben ist ausdrücklich ausschließlich zu dem Zweck, einem Aktor Positionsfahrten beizubringen, die dieser selbst nicht beherrscht, das heißt, der Aktor kennt ausschließlich die Befehle UP/DOWN/STOP, aber nicht 0 - 100 und er liefert auch nicht die Werte 0 - 100 als Antwort auf Steuerbefehle, sondern allenfalls ein ON/OFF (welches dann "letzte Fahrt ging nach UNTEN/OBEN" bedeutet).

Ich habe deutlich darauf hingewiesen, dass das Proxy Item den Status hält (das heißt, die Position). Damit das korrekt funktioniert, muss autoupdate="false" gesetzt sein.

Es ging darum, ein Item MIT Positionsfunktion zu nutzen, um einen Aktor OHNE Positionsfunktion zu steuern, nicht, einen Aktor MIT Positionsfunktion zu steuern, bei dem man nur irgendwie nicht in der Lage ist, Positionsbefehle zu senden.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Norick
Beiträge: 250
Registriert: 31. Jan 2022 06:35
Answers: 0

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Nun ich benutze den Hager TXA 228 welche meines Wissens folgendes kann:

- Auf / Ab / Stop
- Positionsanzeige in %

- Lamellenwinkelanzeige in %
- Lamellenwinkel


das heisst für mich, dass ich die Store ja nur Auf/Ab und stoppen kann aber eben NICHT eine Position aus OH direkt setzen kann. Für die Lamellenwinkel müsste es wahrscheinlich aber gehen da ich hier nebst der Lamellenwinkelanzeige auch einen Lamellenwinkel angeben kann. Oder sehe ich das falsch?

Und genau aus diesem Grund wollte ich ja das Skript von dir verwenden um die Position aus OH zu sezten.

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Es gibt zwei verschiedene Modelle dieses Aktors, TXA228 (Appl. TXA228A V1.0) und TXA228-a2 (Appl. TXA228B V3.0). Beide sollten direkte Positionsfahrten unterstützen. Allerdings scheinen die gewählten Namen der KO etwas unglücklich, aber hier mal die Gegenüberstellung nach KO sortiert (Nur Ausgang 1, für alle anderen entsprechend):

Code: Alles auswählen

V Nummer  Objektfunktion            Länge  K L S Ü    V  Nummer Objektfunktion             Länge   K L S Ü
A 0       AUF / AB                  1 bit  K L S -    B  0      AUF / AB                   1 bit   K L S -
A 1       Lamelle/Stopp             1 bit  K L S -    B  1      Lamellenwinkel / Stopp     1 bit   K L S -
A 2       Zwangssteuerung           2 bit  K L S -    B  2      Zwangssteuerung            2 bit   K L S -
A 3       Wind Alarm                1 bit  K L S -    B  3      Alarm Priorität 2          1 bit   K L S -
A 4       Regen Alarm               1 bit  K L S -    B  4      Alarm Priorität 1          1 bit   K L S -
A 5       Szene                     1 byte K L S -    B  5      Szene                      1 byte  K L S -
A 6       Zustand (1 bit)           1 bit  K L - Ü 
A 58      Zustand blockieren        1 bit  K L S -    B  58     Blockierung                1 bit   K L S -
A 60      Position anfahren         1 byte K L S -    B  60     Standort                   1 byte  K L S -
A 61      Lamellenwinkel einstellen 1 byte K L S -    B  61     Lamellenwinkel / Stopp     1 byte  K L S -
A 62      Zustand                   1 byte K L - Ü    B  62     Zustandsanzeige (1 byte)   1 byte  K L - Ü
A 63      Positionsanzeige in %     1 byte K L - Ü    B  63     Positionsanzeige in %      1 byte  K L - Ü
                                                      B  64     Lamellenwinkelanzeige in % 1 byte  K L - Ü
                                                      B  65     Zustandsanzeige (1 Bit)    1 bit   K L - Ü
Die Version A hat also eine Zustandsanzeige als 1 Bit auf KO 6, während dies bei Version B auf KO 65 stattfindet, außerdem gibt es bei der B-Version zusätzlich noch die Anzeige des Lamellenwinkels.
Was Du aber in dieser Gegenüberstellung gut sehen kannst: Es gibt bei der B-Version ein Objekt "Standort", das ist zum direkten Anfahren einer Position gedacht. Hager hat schon immer "überraschende" Bezeichnungen für die diversen KO verwendet.
Die Doppelung "Lamellenwinkel/Stopp" wäre auch so eine Sache... Über die Länge ist aber klar, dass es sich bei KO 1 um MOVE/STOP handelt, während KO 61 die direkte Steuerung des Lamellenwinkels ist.

Sorry, so viel Aufriss für eine simple Lösung :), hätte ich mal zu Beginn genauer nachgefragt...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Norick
Beiträge: 250
Registriert: 31. Jan 2022 06:35
Answers: 0

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Ja jetzt kommen wir (du vor allem) der Sache schon näher. Also ich benutze die "a2" Version. Und natürlich ist der "Standort" bei mir nicht benutzt, was ergo dazu führt dass eben die Position nicht übermittelt wird. Da wäre ich auch nicht drauf gekommen dass Hager als "Position" den Begriff "Standort" benutzt - ist wirklich schlecht gewählt. Und ja, es ist mir auch aufgefallen dass Hager diese Doppelnamen verwendet was noch unlogischer ist aus meiner Sicht.

Nun gut, ich werde dies mal bereinigen und melde mich ob es jetzt geklappt hat mit meiner Store!

Danke!

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

:) Gerne!
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Norick
Beiträge: 250
Registriert: 31. Jan 2022 06:35
Answers: 0

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

So jetzt bin ich dazugekommen. Nun der Lamellenwinkel wird in OH angezeigt - das funktioniert. Aber was nicht geht ist folgendes, evtl. habe ich das anderes verstanden als gedacht.

Kann ich den Lamellenwinkel auch über drei Tasten (auf,ab, stop) nun steuern von 0-100% ohne dass sich die Store nach unten oder oben bewegt? Das funktioniert so leider noch nicht, zumindest mit folgender Implementation.

Code: Alles auswählen

 - id: Chn3_1
    channelTypeUID: knx:rollershutter
    label: Store Lamellenwinkel Essen
    description: null
    configuration:
      upDown: 1/1/5
      stopMove: 1/1/5
      lamellenwinkel: 1/1/22+<1/1/9

bzw. in der ETS:
lamellen.PNG
Danke!
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Es gibt keinen Parameter lamellenWinkel :)
Außerdem gibt es beim LamellenWinkel für die relative Steuerung (UP/DOWN) keine Funktion Stop. Die Definition des Channels muss entsprechend eher so aussehen:

Code: Alles auswählen

 - id: Chn3_1
    channelTypeUID: knx:rollershutter
    label: Store Lamellenwinkel Essen
    description: null
    configuration:
      upDown: 1/1/5
      position: 1/1/22+<1/1/9
Wenn die Behanghöhe sich beim Verstellen des Lamellenwinkels ändert, dann stimmen die im Aktor hinterlegten Zeiten für den Kurz-Betrieb nicht.

Es wird nur ein Motor angesteuert, der über eine Mechanik sowohl die Behanghöhe als auch den Lamellenwinkel steuert.
Läuft der Motor in die eine Richtung, so werden die Lamellen zunächst in eine Richtung gedreht und anschließend hebt sich die Jalousie. Läuft der Motor in die Gegenrichtung, so werden die Lamellen zunächst in die andere Richtung gedreht und anschließend senkt sich die Jalousie.
Deshalb gibt es auch kein "echtes" Stopp-Kommando, sondern lediglich die Unterscheidung zwischen lang und kurz und hier jeweils UP/DOWN. STOP wird durch ein "UP/DOWN kurz" erreicht.
Im Aktor werden entsprechend mehrere Zeiten hinterlegt, zum einen wie lange der Motor braucht, um die Jalousie von "komplett geöffnet" bis "komplett geschlossen" zu verfahren (und noch getrennt für die Gegenrichtung, weil der Motor beim Heben langsamer läuft), zum anderen wie lange der Motor braucht, um die Lamellen aus dem Extremwinkel 1 auf den Extremwinkel 2 zu verfahren (kommt etwas auf den Aktor an, wie das definiert wird) Im Zweifel muss die minimale Kurzzeit aber auch lang genug sein, dass der Motor auch eine echte Bewegung ausführen kann. Der Lamellenwinkel muss immer entgegen der letzten Auf-/Abwärtsbewegung ausgeführt werden, ansonsten wird der Motor ja wegen der Extremstellung des Winkels einfach die Jalousie weiter in die letzte Richtung verfahren, wenn auch nur in kurzen Schritten.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Norick
Beiträge: 250
Registriert: 31. Jan 2022 06:35
Answers: 0

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Ok so funktioniert es schon (fast) perfekt :) Nun ich habe in der ETS noch die Lamellenzeiten hinterlegt sodass diese nun auch stimmen. In OH habe ich als "Type" nur den Rollershutter auswählen können der aber nicht so richtig passt um den Lamellenwinkel einzustellen.

Das heisst, wenn ich nun den Rollershutter "Up" drücke gehen die Lamellen komplett auf bzw. komplett zu bei "Down". Soweit so gut, aber schön wäre wenn:

- der "Type" nur einen "up" und einen "down" Knopf hätte (ohne Stop). Gibt es sowas oder wie kann man sich einen "neuen Typ" selber machen?
- eigentlich möchte ich dass sich die Lamellen nur bewegen solange man auf den Knopf drückt. Wenn man diesen loslässt sollen die Lamellen dort stoppen wo diese gerade sind. Geht dies mit dem "Rollershutter" Type oder was empfiehlst du hier?


Wäre es dann möglich mit einem eigenen Widget ein paar Buttons zu definieren wie 30%, 50% etc. sodass die Lamellen dann auf diesen Lamellenwinkel öffnen? Das wäre meine Wunschvorstellung.

Antworten