Seite 1 von 1

Türkontaktöffner zu bestimmten Zeiten aktivieren

Verfasst: 29. Sep 2021 08:57
von christian1312
Hallo,

ich habe bei mir im Haus eine Treppenbeleuchtung installiert.
Gesteuert wird diese über einen Shelly 1 mit Zeitsteuerung.
Wenn die Sonne untergeht, dann geht das Licht an und um 22:30 Uhr geht das Licht aus.

Nun habe ich zusätzlich einen Türkontaktöffner installiert und möchte dass das Licht an geht, wenn die Tür zwischen 22:30 und 5:59 geöffnet wird.
Dazu habe ich folgende Regel erstellt.

Habe ich irgendwo einen Fehler gemacht? - Vielen Dank!

Code: Alles auswählen

// Haustuer

rule "Licht An - 1 Minute warten - Licht Aus"
when
    Item eg_flur_haustuer changed to OPEN
then
    tTuer?.cancel
    if(eg_flur_licht_treppe.state != ON && now.getMinuteOfDay >= 22*60+30 && now.getMinuteOfDay <= 23*60+59) // von 22:30 Uhr - 23:59 Uhr
        sendCommand(eg_flur_licht_treppe, ON)
        tTuer = createTimer(now.plusMinutes(1), [
		eg_flur_licht_treppe.sendCommand(OFF)
        ])
    if(eg_flur_licht_treppe.state != ON && now.getMinuteOfDay >= 00*60+00 && now.getMinuteOfDay <= 05*60+59) // von 00:00 bis 05:59
        sendCommand(eg_flur_licht_treppe, ON)
        tTuer = createTimer(now.plusMinutes(1), [
		eg_flur_licht_treppe.sendCommand(OFF)
        ])
end

Re: Türkontaktöffner zu bestimmten Zeiten aktivieren

Verfasst: 29. Sep 2021 12:47
von peter-pan
Hallo Christian,
ich bin zwar kein Spezialist, aber was mir als erstes auffällt, dass die global Variable "tTuer" vor der Regel fehlt. Dann bin ich mir unschlüssig, warum du die erste IF-Bedingung brauchst. Du schreibst ja, dass diese Steuerung durch deinen Shelly (ich nehme an in einer anderen Regel) vorgenommen wird.

Somit könnte die "einzige" If-Bedingung doch lauten:

Code: Alles auswählen

    if(eg_flur_licht_treppe.state != ON && now.getMinuteOfDay >= 22*60+30 && now.getMinuteOfDay <= 05*60+59) // von 22:30 bis 05:59
        sendCommand(eg_flur_licht_treppe, ON)
        tTuer = createTimer(now.plusMinutes(1), [
		eg_flur_licht_treppe.sendCommand(OFF)
        ])
Ich bin mir aber nicht sicher, ob deine Und-Verknüpfungen passen. Evtl. könntest du mal probieren die Zeit-Werte zu klammern und als Oder-Bedingung zu behandeln.

Code: Alles auswählen

    if(eg_flur_licht_treppe.state != ON && (now.getMinuteOfDay >= 22*60+30 || now.getMinuteOfDay <= 05*60+59)) // von 22:30 bis 05:59
        sendCommand(eg_flur_licht_treppe, ON)
        tTuer = createTimer(now.plusMinutes(1), [
		eg_flur_licht_treppe.sendCommand(OFF)
        ])
Hab's aber nicht getestet.

Re: Türkontaktöffner zu bestimmten Zeiten aktivieren

Verfasst: 29. Sep 2021 15:18
von udo1toni
Also, es gibt ja immer viele Wege, die nach Rom führen... Aber man sollte beim Programmieren immer versuchen, den einfachsten Weg zu gehen.

Code: Alles auswählen

var Timer tTuer = null

rule "Licht An - 1 Minute warten - Licht Aus" // Haustuer
when
    Item eg_flur_haustuer changed to OPEN
then
    if(now.getMinuteOfDay < 22*60+30 && now.getMinuteOfDay >= 6*60) // Tagsüber nicht
        return;
    if(eg_flur_licht_treppe.state == ON)                            // Falls Licht schon an, nichts tun
        return;

    tTuer?.cancel
    eg_flur_licht_treppe.sendCommand(ON)
    tTuer = createTimer(now.plusMinutes(1), [
        eg_flur_licht_treppe.sendCommand(OFF)
    ])
end
Die Definition der globalen Variable hat peter-pan ja schon erwähnt. Die ist vielleicht auch vorhanden, aber da sie in der Rules Datei noch vor der ersten Rule erfolgen muss, wird sie gerne beim Code Kopieren vergessen :)

Du möchtest den Timer nur zwischen 22:30 und 6:00 Uhr ausführen. Entsprechend ist es sinnvoll, dies als Abbruchbedingung zu definieren- Dabei ist die Schreibweise 6*60 statt 360 prima, weil gut nachvollziehbar. + 00 hingegen ist nicht sinnvoll, es erhöht die Lesbarkeit nicht sondern stört nur.
Durch die Umkehr der Logik (statt den Code auszuführen, falls die Bedingung erfüllt ist, wird die Rule abgebrochen, falls die Bedingung erfüllt ist) ergeben sich natürlich Abweichungen bei den Grenzen. Das Maximum <= 23:60+59 und das Minimum >= 0*60+0 ist hingegen zu jeder Zeit wahr, es gibt also keinen Grund, dies in irgendeiner Weise zu berücksichtigen, also weg damit.
Es ist auch nicht sinnvoll, die Bedingungen zu vermischen, auch das trägt nicht zur Lesbarkeit bei, also besser für den Schaltzustand eine weitere Abfrage spendieren. Durch die Negierung könnte die Rule sogar jeweils darüber informieren, warum der Abbruch erfolgte (man muss dann natürlich noch geschweifte Klammern ergänzen).

Erst jetzt - es ist sicher, dass der Timer auch gestartet wird - wird ein eventuell laufender Timer gestoppt.
Anschließend wird das Licht eingeschaltet und ein Timer zum Ausschalten angelegt. Dabei wird für beide Befehle die Methode verwendet.

Ich dränge immer darauf, die Action nur zu nutzen, wenn sich dies nicht vermeiden lässt. Das wäre der Fall, wenn man den Itemnamen durch eine Formel errechnen muss und keine Möglichkeit hat, das entsprechende Item anderweitig als echtes Item zur Verfügung zu stellen. Dann muss man auf die Action zurückgreifen, denn hier wird kein Item übergeben, sondern ein String.
Es ist außerdem sehr schlechter Stil, einmal die Action und das andere Mal die Methode zu nutzen...
Nebenbei ist es natürlich nicht sinnvoll, Code unnötig doppelt in einer Rule zu integrieren. Warum sollte man den identischen Code für die Zeit vor Mitternacht und die Zeit nach Mitternacht getrennt nutzen? Selbst wenn man z.B. unterschiedliche Einschaltzeiten nutzen will, wäre es sinnvoller, dies über eine Variable vorher zu errechnen und anschließend diese Variable beim Anlegen des Timers zu verwenden.

Re: Türkontaktöffner zu bestimmten Zeiten aktivieren

Verfasst: 29. Sep 2021 16:37
von BOP
Ich drehe bei mir die Multiplikation immer rum. Dann stehen Stunden und Minuten hintereinander. Ich finde das lässt sich dann noch besser lesen.
Und ich schreibe dann tatsächlich sogar '00'.
Beispiel von 7:00 Uhr bis 22:59 Uhr:
(now.getHour*60+now.getMinute)>=(60*7+00) && (now.getHour*60+now.getMinute)<=(60*22+59)

Manchmal definiere ich mir in der Rule dann noch eine Boolsche Variable, um im eigentlichen Code es etwas kürzer und lesbarer zu gestalten.

Code: Alles auswählen

val Boolean einschaltzeit  = (now.getHour*60+now.getMinute)>=(60*7+00) && (now.getHour*60+now.getMinute)<=(60*22+59)