Storen nach x-Sekunden stoppen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Ja das macht Sinn wenn die iPos noch nicht gesetzt wurde. Ich habe dies noch geändert und nochmals probiert mit folgendem Ergebnis im Log-File:

Code: Alles auswählen

 [DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl 40
[DEBUG] [org.openhab.core.model.script.store ] - Positionsfahrt erkannt (40 %)
[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ProxyStoreEssen-1' failed: An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_lessThan(int,int) on instance: null in ProxyStoreEssen

Irgendwie will er noch nicht :roll:

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Ergänze bitte mal einen Lotgbefehl:

Code: Alles auswählen

            logDebug("store","aktuelle Position {} %, Fahrt {}", iPos, iMove)
Und zwar nach der Definition von iMove:

Code: Alles auswählen

            val Integer iMove = iSoll - iPos                                    // Bestimme Teilstrecke
Hast Du denn schon mal die normalen Befehl Up, DOWN und STOP ausprobiert?
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

So, ich habe mit die Rule noch mal bei mir angeschaut, und es gibt ein paar Stellen, an denen offensichtlich die Typkonvertierung schief geht - warum auch immer. Ich kann nicht nachvollziehen, warum openHAB da so mäkelig ist. Aber es ist ja nicht so, dass man da machtlos wäre...
Also hier eine neue Version... :)

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
    if(Proxy_Store_Essen.state instanceof Number)
        (Proxy_Store_Essen.state as Number).intValue                            // Ermittle Ist-Position
    switch(receivedCommand) {
        case UP   : {
            Store_WohnenEssen.sendCommand(UP)                                   // Bei Aufwärts-Befehl sende UP
            bStoreDir = false                                                   // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                            // Merke Startzeit
            logDebug("store","UP erkannt, Starte Messung ({})",lStoreStart)   
        }   
        case DOWN : {
            Store_WohnenEssen.sendCommand(DOWN)                                    // Bei Abwärts-Befehl sende DOWN
            bStoreDir = true                                                       // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                               // Merke Startzeit
            logDebug("store","DOWN erkannt, Starte Messung ({})",lStoreStart)
        }
        case STOP : {
            logDebug("store","STOP erkannt, Berechne {} - {}",now, lStoreStart)
            Store_WohnenEssen.sendCommand(STOP)                                    // Bei Stopp-Befehl sende STOP
            val Long lDiff = now.toInstant.toEpochMilli - lStoreStart              // Errechne Fahrtzeit
            var 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
                                  }
            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
        }
        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 Integer iTime = 0                                                  // Initialisiere Variable
            logDebug("store","aktuelle Position {} %, Fahrt {}", iPos, iMove)
            if(iMove < 0) {                                                        // Aufwärts
                iTime = -(iStoreUp * iMove).intValue                               // Errechne Fahrtdauer
                Store_WohnenEssen.sendCommand(UP)                                  // Starte Fahrt
            } else if(iMove > 0) {                                                 // Abwärts
                iTime = (iStoreDown * iMove).intValue                              // Errechne Fahrtdauer
                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.plusNanos(iTime*10000),[                      // Starte Timer für Stopp-Befehl
                Store_WohnenEssen.sendCommand(STOP)                                // Stoppe Fahrt
                Proxy_Store_Essen.postUpdate(iSoll)                                // setze neue Position
            ])
        }
    }
end
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Ja Danke, ich habe die neue Version jetzt eingespielt. Ich habe die Store zuerst komplett geschlossen und dann nochmals komplett geöffnet. Wenn diese offen ist und die Rule starte bekomme ich folgenden Log:

Code: Alles auswählen

[DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl 40
2023-08-09 06:38:38.655 [DEBUG] [org.openhab.core.model.script.store ] - Positionsfahrt erkannt (40 %)
2023-08-09 06:38:38.655 [DEBUG] [org.openhab.core.model.script.store ] - aktuelle Position 0 %, Fahrt 40
2023-08-09 06:38:38.656 [DEBUG] [org.openhab.core.model.script.store ] - Strecke von 0 % nach 40 % = 40 % (1092000 mSec)

Die Zeit welche mit 1092000ms angegeben ist würde so zu gross sein. Die Store bewegt sich nur ganz kurz (ca. 1ms) nach unten und stoppt dann gleich. Die Richtung stimmt schon einmal nur die Dauer resp. Position (40%) stimmt noch nicht ganz :shock:

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Hm. Frage: Welche Werte hast Du in iStoreUp und iStoreDown eingesetzt?

Norick hat geschrieben: 9. Aug 2023 06:44 Die Zeit welche mit 1092000ms angegeben ist würde so zu gross sein.
Ja, Rechenfehler, der aber nur die Anzeige betrifft. Der Wert ist um den Faktor 100 zu groß angegeben.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Hier habe ich folgende eingetragen:

Code: Alles auswählen

val Integer iStoreUp    = 29500 // 29,5 Sekunden aufwärts
val Integer iStoreDown  = 27300 // 27,3 Sekunden  abwärts
Was mir noch aufgefallen ist ist folgendes: Wenn die neue Storenposition einen kleinen Wert hat (zum Bsp. 8) dann fährt die Store etwas länger runter ca. 0.5s. Wenn die neue Position gross ist zum Bsp. 70 dann fährt die Store nur ca. 0.1s runter.

Kann es nicht sein dass es hier noch einen Umrechnunsfehler gibt zwischen ms und s?

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

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Code: Alles auswählen

[DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl 88
[DEBUG] [org.openhab.core.model.script.store ] - Positionsfahrt erkannt (88 %)
[DEBUG] [org.openhab.core.model.script.store ] - aktuelle Position 0 %, Fahrt 88
[DEBUG] [org.openhab.core.model.script.store ] - Strecke von 0 % nach 88 % = 88 % (2402400 mSec)
[DEBUG] [org.openhab.core.model.script.store ] - Rule gestartet mit Befehl 7
[DEBUG] [org.openhab.core.model.script.store ] - Positionsfahrt erkannt (7 %)
[DEBUG] [org.openhab.core.model.script.store ] - aktuelle Position 0 %, Fahrt 7
[DEBUG] [org.openhab.core.model.script.store ] - Strecke von 0 % nach 7 % = 7 % (191100 mSec)

Abgesehen vom Faktor 100 würde die Zeit in etwa stimmen für diese beiden Positionen. Die Store erreicht anscheinend die Endposition jedoch schon viel früher als der berechnete Wert.

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Hast Du die Fahrtzeiten auch korrekt ausgemessen? Einmal auf eine der Endlagen fahren, dann eine komplette Fahrt auf die andere Endlage und dabei die Zeit messen und nochmal in die Gegenrichtung, wieder die Zeit messen. Das sind die beiden Zeiten.
Die beiden momentan eingetragenen Zeiten sind von mir eingesetzte Beispiele, die keinesfalls richtig sein können (das wäre schon spooky)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

Re: Storen nach x-Sekunden stoppen

Beitrag von Norick »

Die sind (jetzt) korrekt eingemessen und habe dies auch mehrmals gemacht. Der Unterschied sind ein paar Sekunden. Aber der Fehler der sich zeigt hat leider nichts mit der Dauer zu tun. Wie gesagt die Zeit die für die Fahrt auf zum Beispiel 60% berechnet wird und im Log angezeigt wird stimmt. Aber die Dauer oder die Zeit welche die Store dann tatsächlich macht stimmt überhaupt nicht. Diese ist immer extrem kurz und <1s wenn die gewählte Position einen hohen Wert hat (z.B. 80%). Bei einem kleinen Wert (z.B. 10%) ist die Fahrzeit vielleicht 1s. Diese Fahrzeiten haben darum nichts mit den Fahrzeiten zu tun welche die Store von 0-100% benötigt.

Irgendwo muss der Fehler noch in der Dauer liegen, bzw. diese entgültige Dauer ist in Wahrheit viel kürzer als ausgegeben wird.

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

Re: Storen nach x-Sekunden stoppen

Beitrag von udo1toni »

Ja, kann ich bestätigen... Ich bin da auch gleich einen ganzen Haufen Fallen getreten...
Angefangen mit einer vergessenen Zuordnung, über ein falsches Vorzeichen bis hin zu einem Problem mit einer Variablen, die unbedingt als Long definiert sein muss, weil die angegebenen Zeiten sonst (dank Zahlenraum...) innerhalb der Berechnung zu Nanosekunden negativ werden...
Egal...

Hier die nächste Version :) aber es gibt noch etwas zu beachten, und zwar muss beim Item Proxy_Store_Essen unbedingt über die Metadaten des Items autoupdate=false gesetzt werden (sonst wird der Status des Items durch den jeweiligen Befehl gesetzt, das darf keinesfalls sein...)

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 
    if(Proxy_Store_Essen.state instanceof Number)
        iPos = (Proxy_Store_Essen.state as Number).intValue                        // Ermittle Ist-Position
   
    logDebug("store","Aktuelle Position {}",iPos)   
   
    switch(receivedCommand) {   
        case UP   : {   
            Store_WohnenEssen.sendCommand(UP)                                      // Bei Aufwärts-Befehl sende UP
            bStoreDir = false                                                      // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                               // Merke Startzeit
            logDebug("store","UP erkannt, Starte Messung ({})",lStoreStart)   
        }   
        case DOWN : {
            Store_WohnenEssen.sendCommand(DOWN)                                    // Bei Abwärts-Befehl sende DOWN
            bStoreDir = true                                                       // Merke Fahrtrichtung
            lStoreStart = now.toInstant.toEpochMilli                               // Merke Startzeit
            logDebug("store","DOWN erkannt, Starte Messung ({})",lStoreStart)
        }
        case STOP : {
            logDebug("store","STOP erkannt, Berechne {} - {}",now.toInstant.toEpochMilli, lStoreStart)
            Store_WohnenEssen.sendCommand(STOP)                                    // Bei Stopp-Befehl sende STOP
            if(lStoreStart === null)
                return;
            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
        }
        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) {                                                        // Aufwärts
                iTime = -(iStoreUp * iMove).intValue                               // Errechne Fahrtdauer
                logDebug("store","Aufwärts Fahrt {}", iTime)
                Store_WohnenEssen.sendCommand(UP)                                  // Starte Fahrt
            } else if(iMove > 0) {                                                 // Abwärts
                iTime = (iStoreDown * iMove).intValue                              // Errechne Fahrtdauer
                logDebug("store","Abwärts Fahrt {}", iTime)
                Store_WohnenEssen.sendCommand(DOWN)                                // Starte Fahrt
            }
            logDebug("store","Strecke von {} % nach {} % = {} % ({} nSec)", iPos, iSoll, iMove, iTime*10000)
            tStore?.cancel                                                         // lösche Timer, falls vorhanden
            tStore = createTimer(now.plusNanos(iTime*10000),[                      // Starte Timer für Stopp-Befehl
                Store_WohnenEssen.sendCommand(STOP)                                // Stoppe Fahrt
                Proxy_Store_Essen.postUpdate(iSoll)                                // setze neue Position
            ])
        }
    }
end
Es gibt noch einen weiteren Knackpunkt... Bekommst Du über das Binding mit, wenn der Motor abschaltet? Das wäre ganz interessant, wenn man die Fahrt über UP/DOWN startet aber nicht selbst stoppt. Könnte man aber auch noch integrieren...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten