Es scheint als hättest Du beim Anlegen zu irgendeinem Zeitpunkt etwas kaputt gemacht
Benenne erst mal die Datei mit den Rules um (insbesondere sollten im Dateinamen keine Leerzeichen vorkommen, aber zu diesem Zeitpunkt ändere auch die Endung von .rules z.B. auf .rules.old ab. Nun sollten eigentlich alle Rules verschwunden sein. Ist das nicht der Fall, starte openHAB bitte einmal neu. Spätestens dann sollten die überzähligen Rules weg sein.
Ansonsten könnte es natürlich noch sein, dass Du im Verzeichnis $OPENHAB_CONF/rules/ noch weitere Dateien liegen hast, die da aber nicht sein sollten

insbesondere keine Dateien, die keine aktiven Rules enthalten, deren Endung aber .rules lautet (auch nicht in Unterverzeichnissen, die außerdem nicht in der Verzeichnisstruktur erlaubt sind)
Tatsächlich wird keine der Rules von oben große Probleme bereiten, im Grunde sollte alle (bis auf die mit getHourOfDay) einwandfrei funktionieren. Da die Rules bei Dir doppelt auftauchen, hast Du ein anderes Problem, welches vermutlich jeglichen Betrieb von openHAB stört.
Trotzdem hier mal die überarbeiteten Rules:
Code: Alles auswählen
// globale Variablen
var Number Bad = 1
var Timer tKueche = null
var Timer tFlur = null
// Initialisieren Systemstart
rule "Init virtual Items"
when
System started
then
Bewegungsmelder_Kueche_MotionOffTimer.sendCommand(10) // NULL Standard Wert
Bewegungsmelder_Flur_MotionOffTimer.sendCommand(10) // NULL Standard Wert
Bewegungsmelder_Wohnzimmer_MotionOffTimer.sendCommand(15) // NULL Standard Wert
if(!(TemperaturBad.state instanceof Number)) // Badtemperatur
TemperaturBad.postUpdate(16.5)
if(!(Badtemperatur_Soll_Setpoint.state instanceof Number))
Badtemperatur_Soll_Setpoint.sendCommand(16)
if(!(TemperaturWon.state instanceof Number)) // Wohnzimmertemperatur
TemperaturWon.postUpdate(16.5)
if(!(Wontemperatur_Soll_Setpoint.state instanceof Number))
Wontemperatur_Soll_Setpoint.sendCommand(16)
if(!(TemperaturSchl.state instanceof Number)) // Schlafzimmertemperatur
TemperaturSchl.postUpdate(16.5)
if(!(Schltemperatur_Soll_Setpoint.state instanceof Number))
Schltemperatur_Soll_Setpoint.sendCommand(16)
end
// Regeln Badezimmer
rule "Temperatur Ist mit Soll vergleichen im Bad"
when
Item TemperaturBad changed or
Item Badtemperatur_Soll_Setpoint changed
then
if(!(TemperaturBad.state instanceof Number)) {
logWarn("temp","Temperatur Bad liefert ungültigen Wert {}",TemperaturBad.state)
return;
}
val fIst = (TemperaturBad.state as Number).floatValue
var fSoll = 16.0
if(Badtemperatur_Soll_Setpoint.state instanceof Number)
fSoll = (Badtemperatur_Soll_Setpoint.state as Number).floatValue
var soll = OFF
if(fSoll > fIst)
soll = ON
if(Heizung_Switch_Ba.state != soll)
Heizung_Switch_Ba.sendCommand(soll.toString)
end
rule "Badfenster"
when
Item Bad_Fenster_1_OpenStatus changed or
Item Bad_Fenster_2_OpenStatus changed
then
var soll = 3
if(Bad_Fenster_1_OpenStatus.state == CLOSED && Bad_Fenster_2_OpenStatus.state == CLOSED)
soll = 17
if(Badtemperatur_Soll_Setpoint.state != soll)
Badtemperatur_Soll_Setpoint.sendCommand(soll)
end
// Regeln Wohnzimmerheizung
rule "Temperatur Ist mit Soll vergleichen"
when
Item TemperaturWon changed or
Item Wontemperatur_Soll_Setpoint changed
then
if(!(TemperaturWon.state instanceof Number)) {
logWarn("temp","Temperatur Wohnzimmer liefert ungültigen Wert {}",TemperaturWon.state)
return;
}
val fIst = (TemperaturWon.state as Number).floatValue
var fSoll = 16.0
if(Wontemperatur_Soll_Setpoint.state instanceof Number)
fSoll = (Wontemperatur_Soll_Setpoint.state as Number).floatValue
var soll = OFF
if(fSoll > fIst)
soll = ON
if(Heizung_Switch_Won1.state != soll)
Heizung_Switch_Won1.sendCommand(soll.toString)
if(Heizung_Switch_Won2.state != soll)
Heizung_Switch_Won2.sendCommand(soll.toString)
end
rule "Wohnzimmer Tablet einschalten"
when
Item Bewegungsmelder_Wohnzimmer_MotionStatus received update ON
then
sendHttpGetRequest("http://192.168.178.91:8080/TabletWohnzimmerEin")
end
// Regeln Flur
rule "Taster im Flur"
when
Item Touch_G1_Flur_Lampe received update ON
then
Touch_G1_Flur_Lampe.sendCommand(OFF)
end
rule "Flur Nachtlicht"
when
Item Bewegungsmelder_Flur_MotionStatus received update ON
then
if(now.getHour > 7 && now.getHour < 17) // zwischen 8 Uhr und 17 Uhr kein Nachtlicht
return;
tFlur?.cancel
if(XiaomiMiSmartHomeGateway_Brightness.state != ON)
XiaomiMiSmartHomeGateway_Brightness.sendCommand(ON)
tFlur = createTimer(now.plusSeconds(130), [ |
XiaomiMiSmartHomeGateway_Brightness.sendCommand(OFF)
])
end
// Regeln Schlafzimmer
rule "Temperatur Ist mit Soll vergleichen im Schlafzimmer"
when
Item TemperaturSchl changed or
Item Schltemperatur_Soll_Setpoint changed
then
if(!(TemperaturSchl.state instanceof Number)) {
logWarn("temp","Temperatur Schlafzimmer liefert ungültigen Wert {}",TemperaturSchl.state)
return;
}
val fIst = (TemperaturSchl.state as Number).floatValue
var fSoll = 16.0
if(Schltemperatur_Soll_Setpoint.state instanceof Number)
fSoll = (Schltemperatur_Soll_Setpoint.state as Number).floatValue
var soll = OFF
if(fSoll > fIst)
soll = ON
if(Heizung_Switch_Schl.state != soll)
Heizung_Switch_Schl.sendCommand(soll.toString)
end
rule "Schlafzimmerfenster"
when
Item Schlaf_Fenster_1_OpenStatus changed or
Item Schlaf_Fenster_2_OpenStatus changed
then
var soll = 3
if(Schlaf_Fenster_1_OpenStatus.state == CLOSED && Schlaf_Fenster_2_OpenStatus.state == CLOSED ) {
soll = 18
if(Schltemperatur_Soll_Setpoint.state != soll)
Schltemperatur_Soll_Setpoint.sendCommand(soll)
end
// Regeln Küche
rule "Küche Bewegungsmelder"
when Item Bewegungsmelder_Kueche_MotionStatus changed
then
if(now.getHour > 8 && now.getHour < 17) // kein Licht zwischen 8 Uhr und 17 Uhr
return;
tKueche?.cancel() // cancel existing timer
if(newState == ON) {
if(Touch_G1_Kueche_Lampe.state != ON)
Touch_G1_Kueche_Lampe.sendCommand(ON) //turn on light
if(S20_48_LED_Leiste_Kueche_Power.state != ON)
S20_48_LED_Leiste_Kueche_Power.sendCommand(ON)
} else
tKueche = createTimer(now.plusSeconds(180), [|
Touch_G1_Kueche_Lampe.sendCommand(OFF)
S20_48_LED_Leiste_Kueche_Power.sendCommand(OFF)
])
end
//
rule "Gesamte Automatisierung"
when
Time cron "0 59 23 * * ?" // täglich um 23:59 Uhr wird die Temperatur eingestellt
then
// Wonautomatik_Hz_ein_aus.sendCommand(1)
// Badautomatik_Hz_ein_aus.sendCommand(1)
Badtemperatur_Soll_Setpoint.sendCommand(17)
Wontemperatur_Soll_Setpoint.sendCommand(17)
Schltemperatur_Soll_Setpoint.sendCommand(18)
end
rule "Schlafen gehen/ Out of House"
when
Item Out_of_House received command ON
then
Touch_G2_Won_Lampe_1_1.sendCommand(OFF)
Touch_G2_Won_Lampe_1_2.sendCommand(OFF)
Touch_G2_Won_Lampe_2_1.sendCommand(OFF)
Touch_G2_Won_Lampe_2_2.sendCommand(OFF)
Touch_G1_Schlaf_Lampe.sendCommand(OFF)
Touch_G2_Bad_Lampe_1_1.sendCommand(OFF)
S20_Stehlampe.sendCommand(OFF)
Badtemperatur_Soll_Setpoint.sendCommand(17)
Wontemperatur_Soll_Setpoint.sendCommand(17)
Schltemperatur_Soll_Setpoint.sendCommand(18)
Out_of_House.sendCommand(OFF)
XiaomiMiSmartHomeGateway_Brightness.sendCommand(OFF)
Touch_G1_Kueche_Lampe.sendCommand(OFF)
Touch_G1_Flur_Lampe.sendCommand(OFF)
end
rule "Ich bin wieder zu Hause"
when
Item bin_wieder_da received command ON
then
Badtemperatur_Soll_Setpoint.sendCommand(20)
Wontemperatur_Soll_Setpoint.sendCommand(22)
Schltemperatur_Soll_Setpoint.sendCommand(18)
bin_wieder_da.sendCommand(OFF)
if(now.getHour > 7 && now.getHour < 17) // Licht an zwischen 8:00Uhr und 17:00Uhr
return;
Touch_G2_Won_Lampe_1_1.sendCommand(ON)
Touch_G2_Won_Lampe_1_2.sendCommand(ON)
Touch_G2_Won_Lampe_2_1.sendCommand(ON)
end
// Automatisierung
rule "Cron Heizung Automatisierung Bad 1"
when
Time cron "0 30 5 ? * MON-FRI" // 5:30 Uhr Aufheizperiode Bad EIN (Mo-Fr)
then
Badtemperatur_Soll_Setpoint.sendCommand(19)
end
rule "Cron Heizung Automatisierung Bad 2"
when
Time cron "0 30 7 ? * MON-FRI" // 8:00 Uhr Abschaltung Bad AUS (Mo-Fr)
then
Heizung_Switch_Ba.sendCommand(OFF)
Badtemperatur_Soll_Setpoint.sendCommand(17)
end
rule "Cron Heizung Automatisierung Wohnzimmer 1"
when
Time cron "0 30 15 ? * MON-FRI" // 15:30 Uhr Aufheizperiode Wohnzimmer EIN (Mo-Fr)
then
Wontemperatur_Soll_Setpoint.postUpdate(20)
end
Wie gesagt, im Grunde muss da nichts weiter geändert werden.
Ich habe dennoch ein paar Dinge anders gelöst. Im Einzelnen: einen Wert
Uninitialized gibt und gab es nie. Wenn überhaupt, gäbe es
UNINITIALIZED als Wert, der aber vermutlich eher
NULL wäre, oder alternativ gäbe es bei String Items auch einen Wert
"Uninitialized" (man beachte die Anführungszeichen)
Besser ist aber ohnehin die Prüfung auf einen gültigen Zahlenwert
instanceof Number, das ist eher zielführend.
Du hast kommentiert
postUpdate ist nur für Aktualisierungen innerhalb von openHAB (sendCommand gibt diese auch auf den Bus)
Ja, aber.
Der Punkt ist:
.postUpdate() setzt den Status eines Items, während
.sendCommand() einen Befehl an das Item sendet, nicht mehr und nicht weniger.
Das default Verhalten von openHAB ist dabei: ein empfangener Befehl wird an alle verknüpften Bindings weitergeleitet. Außerdem wird der Trigger
Item received command ausgelöst. Weiterhin bestimmt openHAB anhand des gesendeten Befehls den mutmaßlichen neuen Status des Items und führt ein postUpdate für das Item aus. Dieses Verhalten kann mit dem Parameter
autoupdate=false unterbunden werden.
Du sendest in der ersten Rule Werte an Sensoren, was vollkommen sinnlos erscheint, denn ein Sensor sollte nicht auf Befehle von außen reagieren. An dieser Stelle wäre also ein .postUpdate() wesentlich sinnvoller. Ich gehe davon aus, dass Du ab Systemstart schon einen Zahlenwert im Item stehen haben willst, selbst wenn dieser Wert nicht dem realen Messwert entspricht.
Und wie sieht es mit den Setpoints aus? Da Du die Werte ja selbst per Rule auswertest um damit die Heizung zu steuern, befürchte ich, dass auch diese gar nicht an externe Hardware gehen, sondern ausschließlich in openHAB selbst Verwendung finden, kann das sein? In diesem Fall wären auch diese Items besser mit .postUpdate() zu setzen (und zwar in allen Rules)
Nun zu den ganzen Temperaturvergleichen...
Es wäre sinnvoller, die Items geschickt zu benennen und eine Gruppe zu definieren, so:
Code: Alles auswählen
Group gHeat "Heizung"
Number Bad_Soll "Bad Soll" (gHeat)
Number Bad_Ist "Bad Ist" (gHeat)
Switch Bad_Heat "Bad heizen" (gHeat)
Number Wohnzimmer_Soll "Wohnzimmer Soll" (gHeat)
Number Wohnzimmer_Ist "Wohnzimmer Ist" (gHeat)
Switch Wohnzimmer_1_Heat "Wohnzimmer 1 heizen" (gHeat)
Switch Wohnzimmer_2_Heat "Wohnzimmer 2 heizen" (gHeat)
Number Schlafzimmer_Soll "Schlafzimmer Soll" (gHeat)
Number Schlafzimmer_Ist "Schlafzimmer Ist" (gHeat)
Switch Schlafzimmer_Heat "Schlafzimmer heizen" (gHeat)
Nun reicht eine Rule...
Code: Alles auswählen
rule "Heizung schalten"
when
Member of gHeat changed
then
if(triggeringItem.name.endsWith("Heat")) Änderung des Heizvorgangs interessiert uns nicht
return;
val strHK = triggeringItem.name.split("_").get(0)
val iIst = gHeat.members.filter[i|i.name.startsWith(strHK) && i.name.endsWith("Ist")].head
val iSoll = gHeat.members.filter[i|i.name.startsWith(strHK) && i.name.endsWith("Soll")].head
val iHeat = gHeat.members.filter[i|i.name.startsWith(strHK) && i.name.endsWith("Heat")]
if(!(iIst.state instanceof Number)) {
logWarn("temp","Temperatur {} liefert ungültigen Wert {}", strHK, iIst.state)
return;
}
val fIst = (iIst.state as Number).floatValue
var fSoll = 16.0
if(iSoll.state instanceof Number)
fSoll = (iSoll.state as Number).floatValue
var soll = OFF
if(fSoll > fIst)
soll = ON
iHeat.forEach[i|
if(i.state != soll)
i.sendCommand(soll.toString)
]
end
die sich um alle drei Heizkreise kümmert, und ja, sie berücksichtigt auch, dass es im Wohnzimmer mehr als einen Heizkörper gibt.
Ähnliiches kann man auch für die Überwachung der Fensterstatus machen, wenn die Namen der Items besser gewählt werden.
Aber auch da siehst Du schon von vornherein eine Optimierung, denn warum sollte man hier zwei Rules verwenden, wenn man doch ohnehin beide Status überwachen muss. Ich gehe davon aus, dass es sich bei den Kontakten um eine Meldung "geöffnet" und eine Meldung "gekippt" handelt, es wäre sinnvoll, diese Items zu einem Item zusammenzuführen. Wenn Du ein String Item dafür hernimmst, kannst Du als Texte hier CLOSED, OPEN und AJAR setzen, dann wird ein verlinktes window-Icon den Zustand auch korrekt anzeigen. Leider geht das nur über ein Proxy Item, sähe dann z.B. so aus:
Code: Alles auswählen
Group gWindows "Fenster"
Contact Bad_Open "Badfenster geöffnet" (gWindows)
Contact Bad_Ajar "Badfenster gekippt" (gWindows)
String Bad_Window "Badfenster" (gWindows)
Contact Schlafzimmer_Open "Schlafzimmerfenster geöffnet" (gWindows)
Contact Schlafzimmer_Ajar "Schlafzimmerfenster gekippt" (gWindows)
String Schlafzimmer_Window "Schlafzimmerfenster" (gWindows)
rule "Fensterzustand"
when
Member of gWindows changed
then
val strRoom = triggeringItem.name.split("_").get(0)
if(triggeringItem.name.endsWith("Window")) {
if(newState != "CLOSED") {
gHeat.members.filter[i|i.name.startsWith(strRoom) && i.name.endsWith("Soll")].head.postUpdate(3)
} else {
var soll = 17
if(strRoom == "Schlafzimmer")
soll = 18
gHeat.members.filter[i|i.name.startsWith(strRoom) && i.name.endsWith("Soll")].head.postUpdate(soll)
}
} else {
gWindows.members.filter[i|i.name.startsWith(strRoom) && i.name.endsWith("Window")].head.postUpdate(
if(gWindows.members.filter[i|i.name.startsWith(strRoom) && i.name.endsWith("Open")].head.state != CLOSED)
"OPEN"
else if(gWindows.members.filter[i|i.name.startsWith(strRoom) && i.name.endsWith("Ajar")].head.state != CLOSED)
"AJAR"
else
"CLOSED"
)
}
end
Eine Rule für beide Fenster, es wird sogar berücksichtigt, dass die Solltemperatur im Schlafzimmer bei geschlossenem Fenster ein wenig höher sein soll als im Bad. Die Rule triggert sich im Übrigen selbst, weil ja alle Items in der gleichen Gruppe liegen, das macht es etwas weniger intuitiv, zu verstehen, was da passiert, aber die Grundidee sollte klar werden.
Eine "Warnung" am Rande: Ich habe die Rules nicht ausprobiert, es kann also gut sein, dass da noch Fehler lauern oder ich irgendwo einen Denkfehler gemacht habe

aber wie ich oben ja schon erwähnt habe: im Grunde sollten Deine Rules funktionieren, abgesehen vom
now.getHourOfDay, welches nun
now.getHour heißt, ansonsten gibt es keine Fallen. Die Stellen im Code führen nur dazu, dass die von Dir verwendete Variable nicht korrekt initialisiert wird, ansonsten sollte der Code dennoch durchlaufen, Dein Problem liegt also erst mal darin begründet, dass Du es irgendwie geschafft hast, die Rules doppelt anzulegen, und das musst Du zuerst fixen.