Automatischer Dimmer (sunrise)

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

atk69
Beiträge: 98
Registriert: 15. Jan 2019 19:07
Answers: 1
Wohnort: Weil am Rhein

Automatischer Dimmer (sunrise)

Beitrag von atk69 »

Hallo zusammen

Ich hänge wieder an einem "kleinen" Problem bei OH3:
folgende rule soll mir zu einer bestimmten Uhrzeit eine Lampe langsam hochfahren.

Code: Alles auswählen

triggers:
  - id: "1"
    configuration:
      time: 11:03
    type: timer.TimeOfDayTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        var Timer tSunset = null


        rule "Sunrise"

        when
            GZL_switch.state == OFF
        then
            tSunset?.cancel
            tSunset = createTimer (now.plusSeconds(1),[|
                if((GZL_Helligkeit.state as Number) > 0) {
                    GZL_Helligkeit.sendCommand((GZL_Helligkeit.state as Number) + 1)
                    tSunset.reschedule(now.plusSeconds(5))
                }
            ])
        end
    type: script.ScriptAction
Zentraler Teil ist ja rule "sunrise". Ich bekommefolgende Fehlermeldung(en) im log:

Code: Alles auswählen

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '3e80ba289e' failed: var Timer tSunset = null

rule "Sunrise"
when
    GZL_switch.state == OFF
then
    tSunset?.cancel
    tSunset = createTimer (now.plusSeconds(1),[|
        if((GZL_Helligkeit.state as Number) > 0) {
            GZL_Helligkeit.sendCommand((GZL_Helligkeit.state as Number) + 1)
            tSunset.reschedule(now.plusSeconds(5))
        }
    ])
end
   1. The method or field rule is undefined; line 3, column 26, length 4
   2. The method or field when is undefined; line 4, column 41, length 4
   3. The method or field then is undefined; line 6, column 74, length 4
   4. The method or field end is undefined; line 14, column 344, length 3
   5. Cannot refer to the non-final variable tSunset inside a lambda expression; line 11, column 288, length 7
   6. This expression is not allowed in this context, since it doesn't cause any side effects.; line 3, column 31, length 9
Damit kann ich nicht viel anfangen.
Kann mir jemand auf die Sprünge helfen ?

Gruss
atk69
von udo1toni » 16. Jun 2021 23:34
Das Problem ist hier ein grundsätzliches Missverständnis :)

Du kannst createTimer mit einer globalen Variablen nur in einer "echten" DSL Rule verwenden (das heißt, Du musst die Rule zwingend über eine *.rules Datei anlegen, nicht über die UI)

Bei DSL Rules, die über die UI angelegt werden, gibt es außerdem keinen when-Teil ,und niemals gibt es im when-Teil ein == ;)

Die korrekte Rule sollte also so aussehen:

Code: Alles auswählen

var Timer tSunset = null

rule "Sunrise"
when
    Time cron "0 3 11 * * ?"
then
    if(GZL_switch.state == ON) return;
    tSunset?.cancel
    tSunset = createTimer(now.plusSeconds(1), [|
        var nBright = GZL_Helligkeit.state as Number
        if(nBright < 100) {
            GZL_Helligkeit.sendCommand(nBright + 1)
            tSunset.reschedule(now.plusSeconds(5))
        }
   ])
end
Wie gesagt, NICHT über die UI, sondern über Datei...
Gehe zur vollständigen Antwort
and IT works ;)

Benutzeravatar
peter-pan
Beiträge: 2573
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Automatischer Dimmer (sunrise)

Beitrag von peter-pan »

Hast du den Timer initialisiert (am Dateianfang, vor der ersten Rule) mit "var Timer tSunset = null" ? Da scheinen aber noch ein paar andere Fehler drin zu sein. Wie hast du denn die Rule angelegt ? Über die MainUi ? Wenn ja, weiß ich nicht, ob das überhaupt geht ?
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.2 openhabian

atk69
Beiträge: 98
Registriert: 15. Jan 2019 19:07
Answers: 1
Wohnort: Weil am Rhein

Re: Automatischer Dimmer (sunrise)

Beitrag von atk69 »

Hallo peter-pan
Ja, der Timer wird initialisiert (direkt im script ) . Das wäre Zeile 13.
Der sunrise-teil ist ja ein seperates script. Zur Verdeutlichung:
test.png
Das Ganze ist nach vielem Suchen auch nur "geklaut". Ich habs einfach nicht so mit dem Syntax. Irgendwie habe ich hier eine Blockade.
Stell mir eine Firewall oder einen Windows/Linux -Server hin, da mach ich dir alles. Aber hier :oops:
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
and IT works ;)

Benutzeravatar
peter-pan
Beiträge: 2573
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Automatischer Dimmer (sunrise)

Beitrag von peter-pan »

Ich bin mir nicht sicher, ob das über die MainUI überhaupt geht. Ich denke da kommt es zu Problemen mit globalen Variablen. @udo1toni weiss dass bestimmt genau.

M.E. kannst du das ganze aber als DSL-Rule im Rules-Ordner anlegen und dann sollte es einschl. der globalen Variablen funktionieren.

Die DSL-Rule sieht dann so aus:

Code: Alles auswählen

var Timer tSunset = null

rule "Sunrise"
when
    GZL_switch.state == OFF
then
    tSunset?.cancel
    tSunset = createTimer (now.plusSeconds(1),[|
        if((GZL_Helligkeit.state as Number) > 0) {
            GZL_Helligkeit.sendCommand((GZL_Helligkeit.state as Number) + 1)
            tSunset.reschedule(now.plusSeconds(5))
        }
    ])
end
Ich habe jetzt nicht auf die Logik geschaut, aber dann sollten eigentlich keine Fehlermeldungen mehr auftauchen.
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.2 openhabian

atk69
Beiträge: 98
Registriert: 15. Jan 2019 19:07
Answers: 1
Wohnort: Weil am Rhein

Re: Automatischer Dimmer (sunrise)

Beitrag von atk69 »

Habe es jetzt als reine DSL-rule angelegt. mit "GZL_switch.state == OFF" hat er Probleme. Fehlte auch "Item" davor ;-(
Einfach zum testen mit einem anderen Schalter verknüpft: "Item sonoff0001ASwitch_state changed to OFF"
Jetzt kommt kein Fehler mehr. Allerdings passiert auch nix. Komischerweise wird "var Timer tSunset = null" anscheinend ignoriert.

Code: Alles auswählen

// Triggers:
// - When sonoff0001ASwitch_state changed to OFF

// context: sunrise-1
tSunset?.cancel
	
tSunset = createTimer (now.plusSeconds(1),[|
    if((GZL_Helligkeit.state as Number) > 0) {
        GZL_Helligkeit.sendCommand((GZL_Helligkeit.state as Number) + 1)
        tSunset.reschedule(now.plusSeconds(5))
    }
])
Der code stammt aus dem Designer. Die Orginal rule im rules-ordner hat den Eintrag "var Timer tSunset = null". Gleich zu Beginn.
and IT works ;)

Benutzeravatar
peter-pan
Beiträge: 2573
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Automatischer Dimmer (sunrise)

Beitrag von peter-pan »

...sorry, hab nicht so genau hingeguckt, sondern einfach deinen Code genommen und die globale Variable ergänzt.

Natürlich muss der Trigger (when)

Code: Alles auswählen

Item GZL_switch changed to OFF 
heissen.

Die globale Variable wird nicht ignoriert, sondern nur nicht angezeigt. Vermutlich hat der Code-Editor hier Probleme mit der Darstellung denn eigentlich gibt es diese Variablen nicht (mehr) im Designer (NGRE).
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.2 openhabian

atk69
Beiträge: 98
Registriert: 15. Jan 2019 19:07
Answers: 1
Wohnort: Weil am Rhein

Re: Automatischer Dimmer (sunrise)

Beitrag von atk69 »

peter-pan hat geschrieben: 16. Jun 2021 18:01 ...sorry, hab nicht so genau hingeguckt......
Das ist wohl egal ;)
Hauptsache du hast dich überhaupt damit befasst. Vielen Dank.
Eventuell meldet sich udo1toni noch dazu.
Da war doch noch was mit LogInfo, weiss aber nicht mehr wie ich das einsetzen kann. Offenbar bleibt er ja bei timer hängen.
and IT works ;)

Benutzeravatar
peter-pan
Beiträge: 2573
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Automatischer Dimmer (sunrise)

Beitrag von peter-pan »

atk69 hat geschrieben: 16. Jun 2021 20:00 Da war doch noch was mit LogInfo
...hier die Rule mit logInfo-Erweiterung.

Code: Alles auswählen

var Timer tSunset = null

rule "Sunrise"
when
    Item Dummy_4 changed to ON     // anstelle von GZL_switch
then
    tSunset?.cancel
    tSunset = createTimer (now.plusSeconds(1),[|
    logInfo("Sunrise", "Timer wurde gestartet")
        if((Dummy_2.state as Number) > 0 ) {
            logInfo("Sunrise", "If-Anweisung erfüllt")
            Dummy_2.sendCommand((Dummy_2.state as Number) + 1)  //          anstelle von GZL_Helligkeit
            logInfo("Sunrise", "Status GZL-Helligkeit {}", Dummy_2.state) //     ""   ""  "" 
            tSunset.reschedule(now.plusSeconds(5))
        }
    ])
end
Ich hab das mal getestet mit einem Dummy-Switch-Item und einem Dummy-Dimmer-Item. Grundsätzlich läuft die Regel, aber .....unendlich. Hier ein Auszug aus dem Log:

Code: Alles auswählen

2021-06-16 22:56:51.569 [INFO ] [rg.openhab.core.model.script.Sunrise] - Timer wurde gestartet
2021-06-16 22:56:51.574 [INFO ] [rg.openhab.core.model.script.Sunrise] - If-Anweisung erfüllt
2021-06-16 22:56:51.581 [INFO ] [rg.openhab.core.model.script.Sunrise] - Status GZL-Helligkeit 15
2021-06-16 22:56:56.586 [INFO ] [rg.openhab.core.model.script.Sunrise] - Timer wurde gestartet
2021-06-16 22:56:56.591 [INFO ] [rg.openhab.core.model.script.Sunrise] - If-Anweisung erfüllt
2021-06-16 22:56:56.597 [INFO ] [rg.openhab.core.model.script.Sunrise] - Status GZL-Helligkeit 16
.......... usw.
2021-06-16 22:57:01.603 [INFO ] [rg.openhab.core.model.script.Sunrise] - Timer wurde gestartet
2021-06-16 23:03:53.002 [INFO ] [rg.openhab.core.model.script.Sunrise] - If-Anweisung erfüllt
2021-06-16 23:03:53.008 [INFO ] [rg.openhab.core.model.script.Sunrise] - Status GZL-Helligkeit 99
2021-06-16 23:03:58.013 [INFO ] [rg.openhab.core.model.script.Sunrise] - Timer wurde gestartet
2021-06-16 23:03:58.019 [INFO ] [rg.openhab.core.model.script.Sunrise] - If-Anweisung erfüllt
2021-06-16 23:03:58.028 [WARN ] [b.core.model.script.actions.BusEvent] - Cannot convert '101' to a command type which item 'Dummy_2' accepts: [PercentType, OnOffType, IncreaseDecreaseType, RefreshType].
2021-06-16 23:03:58.033 [INFO ] [rg.openhab.core.model.script.Sunrise] - Status GZL-Helligkeit 100
2021-06-16 23:04:03.038 [INFO ] [rg.openhab.core.model.script.Sunrise] - Timer wurde gestartet
2021-06-16 23:04:03.043 [INFO ] [rg.openhab.core.model.script.Sunrise] - If-Anweisung erfüllt
......  usw.
Irgendwo muss der Timer bzw. die Regel aber beendet werden, spätestens wenn der Dimmer auf 100% ist. Ich könnte mir vorstellen, dass das in einer zweiten If-Anweisung geschehen könnte, in der auch der Rescheduler beinhaltet ist. Da habe ich aber zu wenig Erfahrung, da ich selbst noch nie mit Dimmer-Items "gespielt habe.
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.2 openhabian

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

Re: Automatischer Dimmer (sunrise)

Beitrag von udo1toni »

Das Problem ist hier ein grundsätzliches Missverständnis :)

Du kannst createTimer mit einer globalen Variablen nur in einer "echten" DSL Rule verwenden (das heißt, Du musst die Rule zwingend über eine *.rules Datei anlegen, nicht über die UI)

Bei DSL Rules, die über die UI angelegt werden, gibt es außerdem keinen when-Teil ,und niemals gibt es im when-Teil ein == ;)

Die korrekte Rule sollte also so aussehen:

Code: Alles auswählen

var Timer tSunset = null

rule "Sunrise"
when
    Time cron "0 3 11 * * ?"
then
    if(GZL_switch.state == ON) return;
    tSunset?.cancel
    tSunset = createTimer(now.plusSeconds(1), [|
        var nBright = GZL_Helligkeit.state as Number
        if(nBright < 100) {
            GZL_Helligkeit.sendCommand(nBright + 1)
            tSunset.reschedule(now.plusSeconds(5))
        }
   ])
end
Wie gesagt, NICHT über die UI, sondern über Datei...
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

atk69
Beiträge: 98
Registriert: 15. Jan 2019 19:07
Answers: 1
Wohnort: Weil am Rhein

Re: Automatischer Dimmer (sunrise)

Beitrag von atk69 »

Hallo udo1toni
getestet und für sehr gut befunden :D
lässt sich sehr einfach (selbst für mich) anpassen für sunrise /sunset , diverse Auslöser, max. bright, usw.
Ich dachte eben, dass sich das im Zuge von OH3 als DSL-Baustein einbauen lässt.
D.h. das script nur für den Bereich "then" zu verwenden und den Rest via GUI. Mal wieder falsch gedacht.
Aber das ist ok so, hauptsache es funktioniert ;)

Nochmals vielen Dank für euer beider Einsatz :P

Gruss
Andreas
and IT works ;)

Antworten