Also die Totzeit solltest Du weg lassen, falls sich nicht herausstellt, dass Du sie unbedingt brauchst (wie erwähnt gibt es Bewegungsmelder, die plötzliche Lichtänderung fälschlicherweise als Bewegung erkennen... die sollte man aber eher durch was sinnvolleres ersetzen, als das in einer Rule abzufangen)
Items:
Code: Alles auswählen
Group gMelder
Group gSwitches
Group gLichter
Group gLichtFlur (gLichter)
Group gLichtTreppe (gLichter)
Switch Flur_Melder1 (gMelder)
Switch Flur_Melder2 (gMelder)
Switch Treppe_Melder1 (gMelder)
Switch Treppe _Melder2 (gMelder)
Switch Flur_Switch (gSwitches)
Switch Treppe_Switch (gSwitches)
Dimmer Flur_LichtNacht (gLichtFlur)
Dimmer Flur_Licht2 (gLichtFlur)
Dimmer Flur_Licht3 (gLichtFlur)
Dimmer Flur_Licht4 (gLichtFlur)
Dimmer Flur_Licht5 (gLichtFlur)
Dimmer Flur_Licht6 (gLichtFlur)
Dimmer Treppe_Licht1 (gLichtTreppe)
Dimmer Treppe_Licht2 (gLichtTreppe)
rules:
Code: Alles auswählen
var Timer tFlur = null
var Timer tTreppe = null
val Integer iZeit = 45
rule "Bewegung erkennen"
when
Member of gMelder received update ON
then
val licht = triggeringItem.name.split("_").get(0) // "Flur" oder "Treppe"
val Licht = gLichter.members.filter[i|i.name.contains(licht)].head // gLichtFlur oder gLichtTreppe
if(Licht.state != 100) { // Licht nicht in Dauerbetrieb
if(licht == "Treppe") { // falls Treppe, Treppentimer
gLichtTreppe.sendCommand(60) // entsprechendes Licht auf 60%
tTreppe?.cancel // Timer abbrechen
tTreppe = createTimer(now.plusSeconds(iZeit),[| // Timer anlegen
gLichtTreppe.sendCommand(0) // Licht aus
])
} else if(dunkel.state == ON) { // falls nicht Treppe und dunkel
gLichtFlur.sendCommand(60) // entsprechendes Licht auf 60%
tFlur?.cancel // Timer abbrechen
tFlur = createTimer(now.plusSeconds(iZeit),[| // Timer anlegen
gLichtFlur.members.forEach[i| // Für jedes Licht
i.sendCommand(if( // Sende Befehl
i.name.contains("1") && // Falls der Name "1" enthält
(now.getHourOfDay > 14 || now.getHourOfDay < 1) // und Zeitbedingung erfüllt
)30 else 0) // 30, ansonsten 0
]
])
}
}
end
rule "Dauerbetrieb"
when
Member of gSwitches changed
then
val licht = triggeringItem.name.split("_")get(0)
val Licht = gLichter.members.filter[i|i.name.contains(licht)].head
if(licht == "Flur") tFlur?.cancel
if(licht == "Treppe") tTreppe?.cancel
Licht.sendCommand(triggeringItem.state)
if((now.getHourOfDay < 1 || now.getHourOfDay > 14) && triggeringItem.state == OFF && licht = "Flur")
Flur_LichtNacht.sendCommand(30)
end
rule "Nachtlicht an"
when
Time cron "0 0 15 * * ?"
then
if(Flur_Licht1.state == 0) Flur_Licht1.sendCommand(30)
end
rule "Nachtlicht an"
when
Time cron "0 0 1 * * ?"
then
if(Flur_LichtNacht.state == 30) Flur_LichtNacht.sendCommand(0)
end
Die erste Rule ist etwas komplizierter. Der Punkt ist aber, dass diese 4 Rules
alles erschlagen sollten. Es ist unerheblich, wie viele Leuchten gesteuert werden, es ist unerheblich, wie viele Bewegungsmelder oder Schalter verwendet werden.
Ich gehe die Rules von hinten nach vorne durch
Die letzte Rule schaltet die Lampe Flur_Licht1 aus, falls sie gerade auf 30% ist.
Die dritte Rule schaltet die Lampe Flur_Licht1 auf 30%, falls sie gerade aus ist (dabei wird nicht auf Helligkeit geachtet).
Die zweite Rule kümmert sich darum, das Licht auf 100% oder auf 0% zu schalten. Wird das Licht angeschaltet, so muss der passende Timer abgebrochen werden, damit das Licht nicht ausgeschaltet wird.
Beim Ausschalten muss noch berücksichtigt werden, dass zwischen 15 Uhr und 1 Uhr die Leuchte Flur_Licht1 auf 30% geschaltet werden muss, falls gerade ausgeschaltet wird. Man könnte das (so wie beim Flur-Timer, siehe erste Rule) beim Ausschalten erledigen. Ich bin hier etwas faul und schalte das Licht wieder an, falls es gerade ausgeschaltet wurde.
Nun zur wichtigsten Rule.
Löst einer der Bewegungsmelder aus, so wird anhand des Itemnamens bestimmt, welcher der Bereiche beleuchtet werden soll (der erste Teil des Itemnamens, vor dem _).
Entsprechend wird die zu schaltende Gruppe herausgesucht. Nun wird geprüft, ob die Gruppe auf 100% ist. Ist das der Fall, ist der entsprechende Lichtkreis gerade dauerhaft ON.
Falls nicht, müssen zwei unterschiedliche Timer verwendet werden, die sich auch noch unterschiedlich verhalten. Nun wird also abhängig vom Kreis entweder die Gruppe gLichtTreppe auf 60% geschaltet und der entsprechende Timer angelegt, oder das Ganze passiert für gLichtFlur, dort allerdings nur, falls das Item dunkel den Status ON hat. Zusätzlich muss hier noch beim Ausschalten der Fall berücksichtigt werden, dass das Licht Flur_Licht1 auf 30% geschaltet wird.
Wie gesagt, reichen diese 4 Rules für beide Lichtkreise und alle Bedingungen. Durch die zusätzlichen Bedingungen ist ein Teil des Codes für die Kreise unterschiedlich, was sich aber fast ausschließlich in der ersten Rule niederschlägt.
Sollten weitere bewegungsgesteuerte Kreise dazu kommen, muss nur dieses Teilstück ergänzt werden, und das streng genommen auch nur, weil es das unterschiedliche Verhalten für das Nachtlicht zu berücksichtigen gilt. Die unterschiedlichen Timer könnte man auch über eine HashMap erstellen, aber hier, bei den unterschiedlichen Bedingungen, ist das eher kontraproduktiv. Man kann beliebig viele Lampen bzw. beliebig viele Melder oder auch Switches hinzufügen, solange die Namenskonvention eingehalten wird.
Über iZeit wird die Zeitspanne gesetzt, falls diese für die beiden Kreise unterschiedlich sein soll, kann man hier natürlich auch unterschiedliche Werte nutzen.
Das Item Dunkel hab ich hier mal außen vor gelassen und einfach als Schalter definiert. Den Zustand ob zwischen 15 und 1 Uhr oder zwischen 1 und 15 Uhr könnte man ebenfalls über ein Item lösen, oder auch über eine Variable (die definiert man global und setzt sie in der entsprechenden Time cron Rule)