zinnik hat geschrieben: ↑28. Mai 2023 23:29Ich habe den log nochmal angehängt und Farbig markiert,
Sicher?
zinnik hat geschrieben: ↑28. Mai 2023 23:29
Der Logfehler Script execution of rule with UID 'Badheizkoerper_an_Ueberschuss1' failed ist kein Fehler.
Aber doch:
Code: Alles auswählen
==> /logs/openhab.log <==
2023-05-28 19:14:17.767 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Badheizkoerper_an_Ueberschuss1' failed:
// Globale Timer zu Beginn der Datei definieren!
var Timer tHeatStart = null
if(!(Aktuell_Live_Export.state instanceof Number)) // gültige Zahl? Falls nicht
return; // Rule abbrechen
val Number nPower = (Aktuell_Live_Export.state as Number).floatValue // Messwert als Zahl ohne Einheit
if(nPower < 1.10) { // Leistung unter 1.1kw
tHeatStart?.cancel // stoppe Timer, falls vorhanden
tHeatStart = null // entferne Timer
}
if(nPower < 0.1 && Badheizkoerper_Betrieb.state != OFF) // Leistung unter 0.1kw und Heizung an
Badheizkoerper_Betrieb.sendCommand(OFF) // Beende Heizen
if(nPower > 1.10 && Badheizkoerper_Betrieb.state != ON && tHeatStart === null) // Leistung über 1.1kw, Heizung aus und Timer läuft nicht
tHeatStart = createTimer(now.plusMinutes(1), [| // Erzeuge Timer (Ausfühung in einer Minute)
Badheizkoerper_Betrieb.sendCommand(ON) // Schalte Heizung ein
tHeatStart = null
])
Cannot refer to the non-final variable tHeatStart inside a lambda expression; line 21, column 1359, length 10
Achte bitte auf den Beginn der Logzeile (beginnt mit dem Zeitpunkt des Logeintrags): Da steht ERROR.
Und in der letzten Zeile wird auch erklärt, was schief geht:
Cannot refer to the non-final variable tHeatStart inside a lambda expression
Du kannst die Variable tHeatStart nicht innerhalb des Lambdas benutzen (das Lambda enthält den Code, der ausgeführt wird, wenn der Timer abläuft).
Der Grund hierfür ist, dass die Variable nicht final definiert ist, das heißt, sie ist in einem Kontext definiert, der nicht gültig ist, wenn der Code ausgeführt wird.
Und wenn Du die ersten Codezeilen betrachtest, wird das bestätigt. Du definierst die Variable lokal innerhalb der Rule, dabei steht sogar im Kommentar darüber, dass die Variable
zu Beginn der Datei definiert werden muss, das heißt, außerhalb der Rules. Alle globalen Variablen müssen definiert werden, bevor die erste Rule definiert wird.
zinnik hat geschrieben: ↑28. Mai 2023 23:29
das letzte Sternchen steht doch für Jahr oder ? und das erste für Sekunde
Code: Alles auswählen
Time cron "0 0 9 * * ? *"
^ ^ ^ ^ ^ ^ ^
| | | | | | |
| | | | | | Jahr (kann entfallen)
| | | | | Wochentag (Mon - Sun, 1 - 7, L, #)
| | | | Monat (Jan - Dec, 1 - 12)
| | | Tag im Monat (1 - 31, L, W)
| | Stunde (0 - 23)
| Minute (0 - 59)
Sekunde (0 - 59)
* bedeutet jeder beliebige Wert,
0/5 bedeutet jeder fünfte Wert, beginnend mit 0 (entsprechend 7/13 jeder 13. Wert, beginnend mit 7)
4-9,13,17 bedeutet Die Werte 4 bis 9, 13 und 17. Da das Leerzeichen zwei Felder trennt, müssen alle Ausdrücke pro Feld ohne Leerzeichen geschrieben werden.
Es muss im cron-Ausdruck exakt ein Fragezeichen stehen, entweder beim Wochentag oder beim Tag im Monat. Man kann also keinen cron-Ausdruck formulieren, der nur am Freitag dem 13. auslöst.
Steht beim Tag im Monat ein W mit Zahl (z.B. 15W), so wird der Trigger am nächstgelegenen Werktag triggern (Montag - Freitag), also z.B. am 14, wenn der 15. ein Samstag ist, aber am 16., wenn der 15. ein Sonntag ist.
Beim Tag im Monat steht das L für den letzten Tag im Monat, also "1 1 1 L * ?" triggert immer am Monatsletzten, am 31. Januar, am 28. (im Schaltjahr 29.) Februar, am 31. März, am 30. April usw.
L-4 wäre der viertletzte Tag im Monat...
Im Wochentag funktioniert das L ähnlich... 1L ist der letzte Montag im Monat. 4#2 wäre der zweite Donnerstag im Monat.
zinnik hat geschrieben: ↑28. Mai 2023 22:36
wenn ich eine Rule über den Log verfolgen will wird mir aber immer nur der Dateiname als Rule angezeigt.
Rules erzeugen nur dann Logeinträge, wenn man mit einem logX() Befehl eine Ausgabe erzeugt. Dabei steht das X für Debug, Info, Warn oder Error, also z.B. logInfo("loggername","Meldung"). Über den Loggernamen kann man von der Karaf Konsole aus während openHAB läuft steuern, welche Meldungen ausgegeben werden. Z.B. die beiden Bewässerungsrules, mit Logging angereichert:
Code: Alles auswählen
rule "Bewässerung"
when
Time cron "0 0 9 * * ?" // täglich um 09:00:00 Uhr
then
logDebug("watering","Cron-Job für Bewässerung gestartet")
if(BodenfeuchtesensorBeet_Bodenfeuchtigkeit.state instanceof Number) { // enthält das Item einen gültigen Zahlenwert?
logInfo("watering","Item Bodenfeuchte liefert {}",BodenfeuchtesensorBeet_Bodenfeuchtigkeit.state as Number)
if((BodenfeuchtesensorBeet_Bodenfeuchtigkeit.state as Number).floatValue >= 45) { // größer oder gleich 45?
logWarn("watering","Bodenfeuchtewert über 44, Abbruch")
return; // dann Rule abbrechen
}
}
if(BodenfeuchtesensorBeet_Bodentemperatur.state instanceof Number) { // enthält das Item einen gültigen Zahlenwert?
logInfo("watering","Item Bodentemperatur liefert {}",BodenfeuchtesensorBeet_Bodentemperatur.state.state as Number)
if((BodenfeuchtesensorBeet_Bodentemperatur.state as Number).floatValue <= 1) { // kleiner oder gleich 1?
logWarn("watering","Temperatur unter 1, zu kalt, Abbruch")
return; // dann Rule abbrechen
}
}
logInfo("watering","Ventil 1 einschalten und Timer starten")
Bewaesserung_1_STATE.sendCommand(ON) // Ventil einschalten
createTimer(now.plusSeconds(600), [| // Timer für Bewässerungsdauer
logInfo("watering","Ventil 1 mit Timer ausschalten")
Bewaesserung_1_STATE.sendCommand(OFF) // Ventil ausschalten
])
end
rule "Bewässerung Quelle"
when
Member of gVentile changed or // Ventil wurde geschaltet
Item Fuellstandssensor_Regenfass_Fuellstand changed // Wasserstand hat sich geändert
then
logDebug("watering","Bewässerungsquelle wählen")
var Integer iRegenfass = 0 // Initialwert Regentonne
var swHW = OFF // Initialwert Switch Hauswasser
var swRT = OFF // Initialwert Switch Regentonne
if(Fuellstandssensor_Regenfass_Fuellstand.state instanceof Number) // Falls Wasserstand gültig
iRegenfass = (Fuellstandssensor_Regenfass_Fuellstand.state as Number).intValue // setze Füllstand
logInfo("watering","Ermittelter Füllstand {}",iRegenfass)
if(gVentile.members.filter[v|v.state == ON].size > 0) { // Falls Bewässerung aktiv
logInfo("watering","Mindestens ein Ventil geöffnet")
if(iRegenfass > 20) // Falls Füllstand über 20 %
swRT = ON // Regentonne aktivieren
else // sonst
swHW = ON // Hauswasser aktivieren
}
logInfo("watering","Sollzustand Quellventil Hauswasser: {} Regenfass: {}",swHW,swRT)
if(shellyplugsWandprojektion192168180_Betrieb.state != swHW) { // Falls Soll von Ist abweicht
logInfo("watering","Schalte Quellventil Hauswasser auf {}",swHW)
shellyplugsWandprojektion192168180_Betrieb.sendCommand(swHW.toString) // sende Schaltbefehl
}
if(FRITZDECT210_Steckdose.state != swRT) {
logInfo("watering","Schalte Quellventil Regenfass auf {}",swRT)
FRITZDECT210_Steckdose.sendCommand(swRT.toString)
}
end
Nun kannst Du über die Karaf Konsole das Logging feingranular steuern:
lässt alle Logmeldungen ausgeben
läst die DEBUG-Meldungen aus
gibt nur die Warnmeldungen aus
unterdrückt alles, bis auf ERROR, haben wir hier nicht, also gibt es keine Log-Meldungen mehr (diese beiden Rules betreffend).
Man kann auch noch OFF, TRACE und DEFAULT angeben, Ersteres unterdrückt auch noch die ERROR Meldungen, Letzteres übernimmt die Einstellung des Parent-Elements (hier org.openhab.core.model.script).
TRACE gibt es nur beim Core und den Bindings, in Zusammenhang mit Rules ist das wirkungslos.
openHAB4.2.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.8, LXC), mit openHABian eingerichtet