OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Lux73
Beiträge: 71
Registriert: 26. Dez 2019 12:32
Answers: 0
Wohnort: Bielefeld

OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von Lux73 »

Hallo,

ich habe dieses WE von OH3.x auf OH4.0.3 upgedatet - bisher konnte ich ein paar Kleinigkeiten alleine beheben, allerdings beiße ich mir noch an einer Rule die Zähne aus.

Diese Rule liest ein Item aus meiner InfluxDB aus und schreibt die daraus generierten differenzierten Zeitwerte in Dummy Items welche ich dann in meiner Sitemap darstelle:

Code: Alles auswählen

//#####################################
rule "Aussentemp min-/max"
when
	Item Sensor_Aussen_Temperatur changed or
	Time cron "0 0/5 * 1/1 * ? *"
then
	if (!(Sensor_Aussen_Temperatur.state instanceof Number)) return;
	val aussen_temp_heute_min = (Sensor_Aussen_Temperatur.minimumSince(now.with(LocalTime.of(0,0,0,0)), "influxdb").state as Number)
	val aussen_temp_heute_max = (Sensor_Aussen_Temperatur.maximumSince(now.with(LocalTime.of(0,0,0,0)), "influxdb").state as Number)
	val aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusWeeks(1), "influxdb").state as Number)
	val aussen_temp_1W_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusWeeks(1), "influxdb").state as Number)
	val aussen_temp_1M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(1), "influxdb").state as Number)
	val aussen_temp_1M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(1), "influxdb").state as Number)
	val aussen_temp_6M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(6), "influxdb").state as Number)
	val aussen_temp_6M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(6), "influxdb").state as Number)
	val aussen_temp_1Y_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusYears(1), "influxdb").state as Number)
	val aussen_temp_1Y_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusYears(1), "influxdb").state as Number)
	if (aussen_temp_heute_min != NULL && aussen_temp_heute_max != NULL) {
		Sensor_Aussen_Temp_heute_min.postUpdate(aussen_temp_heute_min)
		Sensor_Aussen_Temp_heute_max.postUpdate(aussen_temp_heute_max)
	}
	if (aussen_temp_1W_min != NULL && aussen_temp_1W_max != NULL) {
		Sensor_Aussen_Temp_1W_min.postUpdate(aussen_temp_1W_min)
		Sensor_Aussen_Temp_1W_max.postUpdate(aussen_temp_1W_max)
	}
	if (aussen_temp_1M_min != NULL && aussen_temp_1M_max != NULL) {
		Sensor_Aussen_Temp_1M_min.postUpdate(aussen_temp_1M_min)
		Sensor_Aussen_Temp_1M_max.postUpdate(aussen_temp_1M_max)
	}
	if (aussen_temp_6M_min != NULL && aussen_temp_6M_max != NULL) {
		Sensor_Aussen_Temp_6M_min.postUpdate(aussen_temp_6M_min)
		Sensor_Aussen_Temp_6M_max.postUpdate(aussen_temp_6M_max)
	}
	if (aussen_temp_1Y_min != NULL && aussen_temp_1Y_max != NULL) {
		Sensor_Aussen_Temp_1Y_min.postUpdate(aussen_temp_1Y_min)
		Sensor_Aussen_Temp_1Y_max.postUpdate(aussen_temp_1Y_max)
	}
end
Dummy Items:

Code: Alles auswählen

Number:Temperature	Sensor_Aussen_Temp_heute_min		<temperature_cold>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_heute_max		<temperature_hot>		{unit="°C"}
Number:Temperature 	Sensor_Aussen_Temp_1W_min		<temperature_cold>		{unit="°C"}
Number:Temperature	 Sensor_Aussen_Temp_1W_max		<temperature_hot>		{unit="°C"}
Number:Temperature 	Sensor_Aussen_Temp_1M_min		<temperature_cold>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_1M_max		<temperature_hot>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_6M_min		<temperature_cold>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_6M_max		<temperature_hot>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_1Y_min		<temperature_cold>		{unit="°C"}
Number:Temperature	Sensor_Aussen_Temp_1Y_max		<temperature_hot>		{unit="°C"}
Temperatur Item:

Code: Alles auswählen

Number:Temperature	Sensor_Aussen_Temperatur		"Sensor Aussen Temperatur"	<temperature>	(gAussen,gInfluxDB,gRRD4J,gChartTemperatur)		{channel="mqtt:topic:sensor_temp_aussen:temperature", unit="°C"}
Diese Rule hat unter OH3 problemlos funktioniert - unter OH bleibt die Rule jetzt scheinbar hängen und produziert dauerhaft 100% Last auf einem Core ohne irgendwelche Dummy Items zu füllen...

Ich kann dies nur durch deaktivieren der Rule beheben - nach Deaktivierung dauert es teilweise 1 Minute bis folgender Fehler ausgeworfen wird und die 100% Last wieder abgeworfen wird:

Code: Alles auswählen

2023-10-22 16:13:22.409 [WARN ] [rnal.influx1.InfluxDB1RepositoryImpl] - Failed to execute query 'FilterCriteria [itemName=Sensor_Aussen_Temperatur, beginDate=null, endDate=2023-04-22T16:12:23.250613897+02:00[Europe/Berlin], pageNumber=0, pageSize=1, operator=EQ, ordering=DESCENDING, state=null]': java.io.InterruptedIOException: interrupted

2023-10-22 16:13:23.001 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'min_max_temp-1' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.emf.ecore.resource.Resource.getResourceSet()" because "context" is null in min_max_temp
wahrscheinlich gab es mit dem Switch von Java11 zu Java17 wieder irgendwelche Java DateTime änderungen, ich komme aber nicht dahinter ^^

wenn jemand einen Tip hat in welche Richtung ich schauen muss, gerne her damit ;)
von udo1toni » 23. Okt 2023 10:55
Die Rule war schon immer falsch :) nur ist es offensichtlich nie zu einem Fehlverhalten gekommen.
Warum es jetzt nicht mehr funktioniert, musst Du aber durch etwas Logging eingrenzen:

Code: Alles auswählen

//#####################################
rule "Aussentemp min-/max"
when
    Item Sensor_Aussen_Temperatur changed or
    Time cron "0 0/5 * * * ?"
then
    if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;

    logInfo("tempCalc","berechne heute")
    val aussen_temp_heute_min = (Sensor_Aussen_Temperatur.minimumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
    val aussen_temp_heute_max = (Sensor_Aussen_Temperatur.maximumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Woche")
    val aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue
    val aussen_temp_1W_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Monat (1)")
    val aussen_temp_1M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
    val aussen_temp_1M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Monat (6)")
    val aussen_temp_6M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
    val aussen_temp_6M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Jahr")
    val aussen_temp_1Y_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusYears(1), "influxdb").state as Number).floatValue
    val aussen_temp_1Y_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusYears(1), "influxdb").state as Number).floatValue

    if(aussen_temp_heute_min !== null && aussen_temp_heute_max !== null) {
        Sensor_Aussen_Temp_heute_min.postUpdate(aussen_temp_heute_min)
        Sensor_Aussen_Temp_heute_max.postUpdate(aussen_temp_heute_max)
    }
    if (aussen_temp_1W_min !== null && aussen_temp_1W_max !== null) {
        Sensor_Aussen_Temp_1W_min.postUpdate(aussen_temp_1W_min)
        Sensor_Aussen_Temp_1W_max.postUpdate(aussen_temp_1W_max)
    }
    if (aussen_temp_1M_min !== null && aussen_temp_1M_max !== null) {
        Sensor_Aussen_Temp_1M_min.postUpdate(aussen_temp_1M_min)
        Sensor_Aussen_Temp_1M_max.postUpdate(aussen_temp_1M_max)
    }
    if (aussen_temp_6M_min !== null && aussen_temp_6M_max !== null) {
        Sensor_Aussen_Temp_6M_min.postUpdate(aussen_temp_6M_min)
        Sensor_Aussen_Temp_6M_max.postUpdate(aussen_temp_6M_max)
    }
    if (aussen_temp_1Y_min !== null && aussen_temp_1Y_max !== null) {
        Sensor_Aussen_Temp_1Y_min.postUpdate(aussen_temp_1Y_min)
        Sensor_Aussen_Temp_1Y_max.postUpdate(aussen_temp_1Y_max)
    }
end
Die Rule gibt nun also vor jeder Berechnung aus, was sie gerade berechnet.
Bei der Kontrolle des Werts in der lokalen Konstanten musst Du immer auf nicht identisch zu null prüfen, nicht auf ist ungleich NULL, denn NULL ist kein Teil von Number, damit kann der Vergleich niemals nicht erfüllt sein (keine der beiden Konstanten kann jemals NULL sein).
Das !== bedeutet "nicht identisch", hierbei wird der Verweis auf die Speicherzelle im RAM geprüft, nicht deren Inhalt.

Das .floatValue soll sicherstellen, dass eine reine Zahl geladen wird (sollte nicht notwendig sein, aber zumindest vorläufig...
Mal schauen, wie weit die Rule kommt.

Ach so... LocalTime.MIDNIGHT berücksichtigt auch die Zeitumstellung :), außerdem funktioniert das bei mir :mrgreen:
Und der Time cron Trigger kann ebenfalls einfacher geschrieben werden...
Gehe zur vollständigen Antwort
APU2c4|Debian12.11|OpenHAB4.3.5@Zulu21|mosquitto|hostapd|dnsmasq|zigbee2mqtt / Huawei MediaPad T5|FullyKioskBrowser
Zigbee:CC2652RB|1xCC2530.ROUTER|15xHue|4xIlluminize 5110.40|Danfoss:4xAlly+4xRoomSensor
Aqara:5xMCCGQ11LM/6xWSDCGQ11LM/6xGZCGQ01LM/4xRTCGQ11LM/2xRTCGQ13LM/2xRTCGQ14LM/1xDJT11LM/1xRTCZCGQ11LM/2x WXKG02LM
TuYa:2xTS011F/3xTS0601/1xTS0001|MOES:1xUFO-R11|HEIMAN:1xHS2WD-E
MQTT:Tasmota13.4.0|6xDelock 11826|3xShelly1|3xBlitzwolf SHP8|1xGosund SP112

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

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von udo1toni »

Die Rule war schon immer falsch :) nur ist es offensichtlich nie zu einem Fehlverhalten gekommen.
Warum es jetzt nicht mehr funktioniert, musst Du aber durch etwas Logging eingrenzen:

Code: Alles auswählen

//#####################################
rule "Aussentemp min-/max"
when
    Item Sensor_Aussen_Temperatur changed or
    Time cron "0 0/5 * * * ?"
then
    if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;

    logInfo("tempCalc","berechne heute")
    val aussen_temp_heute_min = (Sensor_Aussen_Temperatur.minimumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
    val aussen_temp_heute_max = (Sensor_Aussen_Temperatur.maximumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Woche")
    val aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue
    val aussen_temp_1W_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Monat (1)")
    val aussen_temp_1M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
    val aussen_temp_1M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Monat (6)")
    val aussen_temp_6M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
    val aussen_temp_6M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
    logInfo("tempCalc","berechne Jahr")
    val aussen_temp_1Y_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusYears(1), "influxdb").state as Number).floatValue
    val aussen_temp_1Y_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusYears(1), "influxdb").state as Number).floatValue

    if(aussen_temp_heute_min !== null && aussen_temp_heute_max !== null) {
        Sensor_Aussen_Temp_heute_min.postUpdate(aussen_temp_heute_min)
        Sensor_Aussen_Temp_heute_max.postUpdate(aussen_temp_heute_max)
    }
    if (aussen_temp_1W_min !== null && aussen_temp_1W_max !== null) {
        Sensor_Aussen_Temp_1W_min.postUpdate(aussen_temp_1W_min)
        Sensor_Aussen_Temp_1W_max.postUpdate(aussen_temp_1W_max)
    }
    if (aussen_temp_1M_min !== null && aussen_temp_1M_max !== null) {
        Sensor_Aussen_Temp_1M_min.postUpdate(aussen_temp_1M_min)
        Sensor_Aussen_Temp_1M_max.postUpdate(aussen_temp_1M_max)
    }
    if (aussen_temp_6M_min !== null && aussen_temp_6M_max !== null) {
        Sensor_Aussen_Temp_6M_min.postUpdate(aussen_temp_6M_min)
        Sensor_Aussen_Temp_6M_max.postUpdate(aussen_temp_6M_max)
    }
    if (aussen_temp_1Y_min !== null && aussen_temp_1Y_max !== null) {
        Sensor_Aussen_Temp_1Y_min.postUpdate(aussen_temp_1Y_min)
        Sensor_Aussen_Temp_1Y_max.postUpdate(aussen_temp_1Y_max)
    }
end
Die Rule gibt nun also vor jeder Berechnung aus, was sie gerade berechnet.
Bei der Kontrolle des Werts in der lokalen Konstanten musst Du immer auf nicht identisch zu null prüfen, nicht auf ist ungleich NULL, denn NULL ist kein Teil von Number, damit kann der Vergleich niemals nicht erfüllt sein (keine der beiden Konstanten kann jemals NULL sein).
Das !== bedeutet "nicht identisch", hierbei wird der Verweis auf die Speicherzelle im RAM geprüft, nicht deren Inhalt.

Das .floatValue soll sicherstellen, dass eine reine Zahl geladen wird (sollte nicht notwendig sein, aber zumindest vorläufig...
Mal schauen, wie weit die Rule kommt.

Ach so... LocalTime.MIDNIGHT berücksichtigt auch die Zeitumstellung :), außerdem funktioniert das bei mir :mrgreen:
Und der Time cron Trigger kann ebenfalls einfacher geschrieben werden...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Lux73
Beiträge: 71
Registriert: 26. Dez 2019 12:32
Answers: 0
Wohnort: Bielefeld

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von Lux73 »

Hallo udo1toni,

vielen Dank für deinen Input - ich habe das ganze jetzt mal etwas beobachtet. Beim Laden deiner Rule kommen zunächst "Validation Issues":

Code: Alles auswählen

2023-10-23 16:27:10.229 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'min_max_temp.rules'

2023-10-23 16:27:11.589 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'min_max_temp.rules', using it anyway:
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
The operator '!==' is undefined for the argument types float and null
die Rule als solches läuft aber. Wenn gleich auch ein Core wieder länger ausgelastet wird während die Rule triggert.

Code: Alles auswählen

023-10-23 16:15:02.084 [INFO ] [g.openhab.core.model.script.tempCalc] - berechne heute
2023-10-23 16:15:02.419 [INFO ] [g.openhab.core.model.script.tempCalc] - berechne Woche
2023-10-23 16:15:05.559 [INFO ] [g.openhab.core.model.script.tempCalc] - berechne Monat (1)
2023-10-23 16:15:19.868 [INFO ] [g.openhab.core.model.script.tempCalc] - berechne Monat (6)
2023-10-23 16:17:10.706 [INFO ] [g.openhab.core.model.script.tempCalc] - berechne Jahr
ich befürchte das die Berechnung - also das zusammensuchen der Daten innerhalb der influxdb - ziemlich viel Zeit in Anspruch nimmt.

Meine InfluxDB läuft auf einem anderen physischen Host als es das OpenHAB tut - aus historischen Gründen liegt die Datenbank nämlich als Jail innerhalb meines FreeBSD Servers. Die Dauer der Auslastung des Core bei berechnung korreliert mit der ansteigenden Historiendauer.

als Sofortmassnahme lasse ich jetzt nur die "berechnung heute/Woche" alle 5 min durchführen. Die restlichen drei "(1) Monat/(6) Monat/Jahr" habe ich erstmal per seperaten cron auf einmal kurz nach Mitternacht gelegt

Ob mir das nur vorher nicht aufgefallen ist kann ich jetzt nicht zu 100% sagen - aber wahrscheinlich hatte ich "htop" vorher nicht lange genug auf und hatte auch keinen expliziten Augenmerk auf die Auslastung... :|

die Rule sieht aktuell wie folgt aus:

Code: Alles auswählen

//#####################################
rule "Aussentemp min-/max kurz"
when
	Item Sensor_Aussen_Temperatur changed or
	Time cron "0 0/5 * * * ?"
then
	if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;

	logInfo("tempCalc","berechne heute")
	val aussen_temp_heute_min = (Sensor_Aussen_Temperatur.minimumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
	val aussen_temp_heute_max = (Sensor_Aussen_Temperatur.maximumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number).floatValue
	logInfo("tempCalc","berechne Woche")
	val aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue
	val aussen_temp_1W_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusWeeks(1), "influxdb").state as Number).floatValue

	if(aussen_temp_heute_min !== null && aussen_temp_heute_max !== null) {
		Sensor_Aussen_Temp_heute_min.postUpdate(aussen_temp_heute_min)
		Sensor_Aussen_Temp_heute_max.postUpdate(aussen_temp_heute_max)
	}
	if (aussen_temp_1W_min !== null && aussen_temp_1W_max !== null) {
		Sensor_Aussen_Temp_1W_min.postUpdate(aussen_temp_1W_min)
		Sensor_Aussen_Temp_1W_max.postUpdate(aussen_temp_1W_max)
	}
end
//#####################################
rule "Aussentemp min-/max lang"
when
	Time cron "0 15 1 * * ?"
then
	if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;

	logInfo("tempCalc","berechne Monat (1)")
	val aussen_temp_1M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
	val aussen_temp_1M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(1), "influxdb").state as Number).floatValue
	logInfo("tempCalc","berechne Monat (6)")
	val aussen_temp_6M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
	val aussen_temp_6M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(6), "influxdb").state as Number).floatValue
	logInfo("tempCalc","berechne Jahr")
	val aussen_temp_1Y_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusYears(1), "influxdb").state as Number).floatValue
	val aussen_temp_1Y_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusYears(1), "influxdb").state as Number).floatValue

	if (aussen_temp_1M_min !== null && aussen_temp_1M_max !== null) {
		Sensor_Aussen_Temp_1M_min.postUpdate(aussen_temp_1M_min)
		Sensor_Aussen_Temp_1M_max.postUpdate(aussen_temp_1M_max)
	}
	if (aussen_temp_6M_min !== null && aussen_temp_6M_max !== null) {
		Sensor_Aussen_Temp_6M_min.postUpdate(aussen_temp_6M_min)
	Sensor_Aussen_Temp_6M_max.postUpdate(aussen_temp_6M_max)
	}
	if (aussen_temp_1Y_min !== null && aussen_temp_1Y_max !== null) {
		Sensor_Aussen_Temp_1Y_min.postUpdate(aussen_temp_1Y_min)
		Sensor_Aussen_Temp_1Y_max.postUpdate(aussen_temp_1Y_max)
	}
end
das geht bestimmt auch wesentlich "hübscher" - gerade mit deinen programmier Skills :mrgreen:
APU2c4|Debian12.11|OpenHAB4.3.5@Zulu21|mosquitto|hostapd|dnsmasq|zigbee2mqtt / Huawei MediaPad T5|FullyKioskBrowser
Zigbee:CC2652RB|1xCC2530.ROUTER|15xHue|4xIlluminize 5110.40|Danfoss:4xAlly+4xRoomSensor
Aqara:5xMCCGQ11LM/6xWSDCGQ11LM/6xGZCGQ01LM/4xRTCGQ11LM/2xRTCGQ13LM/2xRTCGQ14LM/1xDJT11LM/1xRTCZCGQ11LM/2x WXKG02LM
TuYa:2xTS011F/3xTS0601/1xTS0001|MOES:1xUFO-R11|HEIMAN:1xHS2WD-E
MQTT:Tasmota13.4.0|6xDelock 11826|3xShelly1|3xBlitzwolf SHP8|1xGosund SP112

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

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von udo1toni »

Ja, grundsätzlich muss InfluxDB ja alle Werte durch schauen, je länger Du in die Vergangenheit schaust, umso mehr Werte müssen ausgewertet werden. Allerdings hätte ich ein Optimierung seitens InfluxDB erwartet... Kommt natürlich auch drauf an, wie oft ein Wert in die Datenbank geschrieben wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Lux73
Beiträge: 71
Registriert: 26. Dez 2019 12:32
Answers: 0
Wohnort: Bielefeld

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von Lux73 »

Moin Udo,

ich habe die Rule noch etwas angepasst - pauschal alle 5min auch ohne entsprechende Temperaturänderung erschien mir nicht sonderlich sinnvoll :oops:

Code: Alles auswählen

//#####################################
var Timer tBlocker = null
var Boolean bBlocker = false
//#####################################
rule "Aussentemp min-/max kurz"
when
	Item Sensor_Aussen_Temperatur changed
then
	if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;
	
	if (tBlocker === null && bBlocker == false) {
//		logInfo("tempCalc","setze bBlocker (true)")
		bBlocker = true

		logInfo("tempCalc","Sensor_Aussen_Temperatur berechne heute")
		val aussen_temp_heute_min = (Sensor_Aussen_Temperatur.minimumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number)
		val aussen_temp_heute_max = (Sensor_Aussen_Temperatur.maximumSince(now.with(LocalTime.MIDNIGHT), "influxdb").state as Number)
		
		logInfo("tempCalc","Sensor_Aussen_Temperatur berechne Woche")
		val aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusWeeks(1), "influxdb").state as Number)
		val aussen_temp_1W_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusWeeks(1), "influxdb").state as Number)

		if(aussen_temp_heute_min !== null && aussen_temp_heute_max !== null) {
//			logInfo("tempCalc","postUpdate heute min/max")
			Sensor_Aussen_Temp_heute_min.postUpdate(aussen_temp_heute_min)
			Sensor_Aussen_Temp_heute_max.postUpdate(aussen_temp_heute_max)
		}
		
		if (aussen_temp_1W_min !== null && aussen_temp_1W_max !== null) {
//			logInfo("tempCalc","postUpdate 1 Woche min/max")
			Sensor_Aussen_Temp_1W_min.postUpdate(aussen_temp_1W_min)
			Sensor_Aussen_Temp_1W_max.postUpdate(aussen_temp_1W_max)
		}
		
//		logInfo("tempCalc","Timer gestartet 5min")
		tBlocker = createTimer(now.plusMinutes(5), [|
//			logInfo("tempCalc","Timer abgelaufen, reset bBlocker (false)")
			bBlocker = false
			tBlocker?.cancel
			tBlocker = null
		])
	}
end
//#####################################
rule "Aussentemp min-/max lang"
when
	Time cron "0 17 1 * * ?"
then
	if(!(Sensor_Aussen_Temperatur.state instanceof Number)) return;

	logInfo("tempCalc","Sensor_Aussen_Temperatur berechne Monat (1)")
	val aussen_temp_1M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(1), "influxdb").state as Number)
	val aussen_temp_1M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(1), "influxdb").state as Number)
	logInfo("tempCalc","Sensor_Aussen_Temperatur berechne Monat (6)")
	val aussen_temp_6M_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusMonths(6), "influxdb").state as Number)
	val aussen_temp_6M_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusMonths(6), "influxdb").state as Number)
	logInfo("tempCalc","Sensor_Aussen_Temperatur berechne Jahr")
	val aussen_temp_1Y_min = (Sensor_Aussen_Temperatur.minimumSince(now.minusYears(1), "influxdb").state as Number)
	val aussen_temp_1Y_max = (Sensor_Aussen_Temperatur.maximumSince(now.minusYears(1), "influxdb").state as Number)

	if (aussen_temp_1M_min !== null && aussen_temp_1M_max !== null) {
		Sensor_Aussen_Temp_1M_min.postUpdate(aussen_temp_1M_min)
		Sensor_Aussen_Temp_1M_max.postUpdate(aussen_temp_1M_max)
	}
	if (aussen_temp_6M_min !== null && aussen_temp_6M_max !== null) {
		Sensor_Aussen_Temp_6M_min.postUpdate(aussen_temp_6M_min)
	Sensor_Aussen_Temp_6M_max.postUpdate(aussen_temp_6M_max)
	}
	if (aussen_temp_1Y_min !== null && aussen_temp_1Y_max !== null) {
		Sensor_Aussen_Temp_1Y_min.postUpdate(aussen_temp_1Y_min)
		Sensor_Aussen_Temp_1Y_max.postUpdate(aussen_temp_1Y_max)
	}
end
ich arbeite jetzt mit einem Blocker welcher nach einer Temperaturänderung erstmal 5 Minuten lang weitere berechnungen blockiert falls in der Zeit nochma ein änderung eintritt - somit komme ich auf Intervalle zwischen 7min und 1h 8-)

Hast du noch eine Idee wie ich das Datum und die Uhrzeit für die Tage mit ausgeben kann? Also für "heute" reicht selbstverständlich die Uhrzeit. Für alle anderen berechnungen wären Datum und Uhrzeit ziemlich cool. Weitere Dummy Items wäre mein Weg

Die Daten müssten ja vorliegen weil die "berechnungen" ja schon durchgeührt wurden?!

Ein Vorschlag für z.B. "Woche" reicht vollkommen aus, den Rest kann ich mir dann sicherlich herleiten :)

Mit jeder Rule lernt man(n) ja auch ;)

...ach und nach entfernen der .floatValue sind bei reload der Rule auch die Validation Issues verschwunden...
APU2c4|Debian12.11|OpenHAB4.3.5@Zulu21|mosquitto|hostapd|dnsmasq|zigbee2mqtt / Huawei MediaPad T5|FullyKioskBrowser
Zigbee:CC2652RB|1xCC2530.ROUTER|15xHue|4xIlluminize 5110.40|Danfoss:4xAlly+4xRoomSensor
Aqara:5xMCCGQ11LM/6xWSDCGQ11LM/6xGZCGQ01LM/4xRTCGQ11LM/2xRTCGQ13LM/2xRTCGQ14LM/1xDJT11LM/1xRTCZCGQ11LM/2x WXKG02LM
TuYa:2xTS011F/3xTS0601/1xTS0001|MOES:1xUFO-R11|HEIMAN:1xHS2WD-E
MQTT:Tasmota13.4.0|6xDelock 11826|3xShelly1|3xBlitzwolf SHP8|1xGosund SP112

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

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von udo1toni »

Also, wenn Du es ganz ordentlich machen willst, testest Du, ob die Persistence einen Number Wert liefert, bevor Du den Wert in die Variable schreibst. Falls die Persistence keinen gültigen Wert liefert, wird es ansonsten auch zu einer NullPointer Exception kommen.
Allerdings wird das dann zu einer doppelten Abfrage führen (wobei die Datenbank den Vorgang eventuell im Cache hat)

Du brauchst keine Boolean Variable zum Blocken, so reicht völlig:

Code: Alles auswählen

var Timer tBlock = null

rule "Block Test"
when
    Time cron "5 * * * * ?"
then
    if(tBlock !== null) {
        logInfo("block","Rule geblockt!")
        return;
    }
    
    tBlock = createTimer(now.plusMinutes(5),[tBlock = null])
end
Natürlich kann das logInfo() auch entfallen, hier nur als Nachweis der Funktion.

Die Rule wird einmal pro Minute ausgelöst.
Ist der Zeiger nicht null, so wird die Rule beendet.
Ist der Zeiger null, so wird der Timer erzeugt.
Läuft der Timer ab, so wird der Zeiger auf null gesetzt.

Bezüglich der Zeitangabe: Es gibt hier zwei verschiedene Möglichkeiten :) Zum einen kannst Du den Startzeitpunkt des Zeitraums in einer Variablen speichern, z.B.

Code: Alles auswählen

val minus7 = now.minusWeeks(1)
Zeitstempel7.postUpdate(new DateTimeType(minus7))
aussen_temp_1W_min = (Sensor_Aussen_Temperatur.minimumSince(minus7, "influxdb").state as Number)
...
Damit bekommst Du den Beginn des Beobachtungszeitraums angezeigt.
Vielleicht möchtest Du aber noch lieber wissen, wann das Maximum/Minimum erreicht wurde...

Code: Alles auswählen

ZeitMin7 = Sensor_Aussen_Temperatur.minimumSince(minus7, "influxdb").timestamp
liefert den Zeitpunkt, zu dem der Minimumwert aufgetreten ist. Wenn ich mich richtig erinnere, wird der erste Zeitpunkt genommen, falls es mehrere identische Messwerte gibt.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Lux73
Beiträge: 71
Registriert: 26. Dez 2019 12:32
Answers: 0
Wohnort: Bielefeld

Re: OH4 Upgrade Min-/Max Temperatur Rule verursacht 100% Kernauslastung

Beitrag von Lux73 »

Moin Udo,

danke für den vereinfachten Timer - funktionert tadellos. Wieder ein paar Zeilen Code gespart, wenn mann - dank deiner Hilfe - im Bilde ist wie :mrgreen:

Die Zeitangabe baue ich heute ein - und deine zweite annahme war völlig korrekt. Ich würde mit gerne anzeigen lassen wann der entsprechende Wert aufgetreten ist, also werde ich deine genannte ".timestamp" Funktion einbauen ;)

p.s. die Prüfung ob ein gültiger Number Wert in der Persistence vorhanden ist werde ich selbstverständlich auch noch einbauen

Grüße Michael
APU2c4|Debian12.11|OpenHAB4.3.5@Zulu21|mosquitto|hostapd|dnsmasq|zigbee2mqtt / Huawei MediaPad T5|FullyKioskBrowser
Zigbee:CC2652RB|1xCC2530.ROUTER|15xHue|4xIlluminize 5110.40|Danfoss:4xAlly+4xRoomSensor
Aqara:5xMCCGQ11LM/6xWSDCGQ11LM/6xGZCGQ01LM/4xRTCGQ11LM/2xRTCGQ13LM/2xRTCGQ14LM/1xDJT11LM/1xRTCZCGQ11LM/2x WXKG02LM
TuYa:2xTS011F/3xTS0601/1xTS0001|MOES:1xUFO-R11|HEIMAN:1xHS2WD-E
MQTT:Tasmota13.4.0|6xDelock 11826|3xShelly1|3xBlitzwolf SHP8|1xGosund SP112

Antworten