Taupunkt / Dewpoint Berechnung

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Hallo zusammen,

nachdem mein OH3 nun scheinbar zuverlässig läuft, möchte ich mich tiefer in die Bedienung und Programmierung einarbeiten.
Ich habe ein laufendes Home Assistant System laufen, welches durch OH3 (hoffentlich) vollständig abgelöst werden soll.

Eine der bestehenden Funktionen ist eine einfache Entfeuchtung unseres Wäschekellers basierend auf der Taupunktberechnung.
liegt der Taupunkt in der Waschküche 3Grad über dem Taupunkt auusen und die Luftfeuchtigkeit innen über 73%, schaltet ein Decken und Wandventilator. Der Wandventilator muss nur getriggert werden und läuft dann 35min. Ich würde daher die Routine alle 30min prüfen lassen.
Der Deckenventilator läuft soll solange laufen wie die Bedingung WAHR ist.

Im englischen Forum habe ich eine entsprechenden Eintrag gefunden. Ich möchte das aber nicht einfach übernehmen, sondern Schritt für Schritt verstehen, wie ich das aufbaue. Irgendwann kann ich das dann hoffentlich komplett alleine.
https://community.openhab.org/t/dewpoin ... tion/42344

Ich würde gerne mit zwei ITEMS beginnen, die mir den jeweiligen Taupunkt für AUSSEN und INNEN anzeigen.
Für den Anfang würde mir diese simple Formel ausreichen:
dewPoint = temperature - ((100 - humidity) / 5)

Als Sensoren habe ich je einen Aussen und Innensensor von Homematic eingebunden. Beide liefern mir die Temperatur und Luftfeuchte.

Kann mich hierbei jemand unterstützen ?

Beste Grüße
Dominik

Jojo
Beiträge: 207
Registriert: 5. Mär 2019 21:13
Answers: 2
Wohnort: Ingolstadt

Re: Taupunkt / Dewpoint Berechnung

Beitrag von Jojo »

Servus,
ist zwar nicht direkt dein Thema, aber DHT11 / DHT22 Sensoren liefern den Taupunkt direkt als Wert.
Ich bin nicht fit genug um dir deine Routine zu schreiben, aber wenn ich dich richtig verstehe ist das ja auch gar nicht dein Ziel.
Deshalb:
Wenn ich das richtig weiß kannst du über einen CRON-Job regelmäßig Skripte ausführen lassen.
Der Rest ist eine Abfolge von IF Then Schleifen.
Also Wenn dewpoint1 > dewpoint2+3 und HumInnen <73 then starte Ventilatoren.

Frage ist, wie hängt der Deckenventilator am Strom ?

Ich hoffe das hilft dir ein wenig ?
--

Gruß

Jojo

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Hallo,
mir geht es in erster Linie darum zu verstehen wie ich sowas angehe. Mit Hilfe dieser Formel kann ich leicht einen Wert errechnen. Bisher brauchte ich immer mal wieder Berechnungen, daher möchte ich verstehen wie das in OH funktioniert.
Der Ventilator hängt an einer Tasmota Steckdose und wird per MQTT geschaltet

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Ich war dann heute mal fleissig und habe die Geschichte auf meine Bedürfnisse umgebastelt
Das sind meine ITEMS:

Code: Alles auswählen

Switch Keller_Ventilation_Trigger

// Berechnete Taupunktwerte (siehe Taupunktberechnung.rules)
Number In_THSensor_Dew "Innen Taupunkt [%.2f°C]"       (Weather, Temperature)
Number Out_THSensor_Dew "Aussen Taupunkt [%.2f°C]" (Weather, Temperature)
Number Taupunkt_Differenz "Taupunktdifferenz [%.2f°C]"  (Weather, Temperature)
Das ist die Rule zur Taupunktberechnung:

Code: Alles auswählen

val org.eclipse.xtext.xbase.lib.Functions$Function2<Double, Double, Double> getDewPoint = [
	
	Double Temperature, 
	Double Humidity 
	
	|

	var Double a
	var Double b
	var Double SDD
	var Double DD
	var Double v
	var Double t = Temperature
	var Double h = Humidity
	
	if (t >= 0.0){ // T >= 0 °C
		a = 7.5
		b = 237.3
	} else { // T < 0 °C über Wasser
		a = 7.6
		b = 240.7
	}
	SDD=(6.1078 * Math::pow(10.0, ((a*t)/(b+t))))
	DD = (h/100.0*SDD)
	v = Math::log10((DD/6.107))
	return ((b*v)/(a-v))

]

rule "Taupunktberechnung Außen" // calculation of outdoor dewpoint
when

	Item Out_THSensor_Temp received update or
	Item Out_THSensor_Hum received update or
	System started

then

	if ((Out_THSensor_Temp.state != NULL) && (Out_THSensor_Hum.state != NULL))
	{

		var t = (Out_THSensor_Temp.state as QuantityType<Number>).doubleValue
		var h = (Out_THSensor_Hum.state as QuantityType<Number>).doubleValue
		
		// OutsideThermometerCombined.sendCommand(String::format("%.1f°C / %.0f%%", t, h))
	
		Out_THSensor_Dew.postUpdate(getDewPoint.apply(t, h))
			
	}

end

rule "Taupunktberechnung Innen" // calculation of basement dewpoint
when

	Item In_THSensor_Temp received update or
	Item In_THSensor_Hum received update or
	System started

then

	if ((In_THSensor_Temp.state != NULL) && (In_THSensor_Hum.state != NULL))
	{

		var t = (In_THSensor_Temp.state as QuantityType<Number>).doubleValue
		var h = (In_THSensor_Hum.state as QuantityType<Number>).doubleValue
		
		// OutsideThermometerCombined.sendCommand(String::format("%.1f°C / %.0f%%", t, h))
	
		In_THSensor_Dew.postUpdate(getDewPoint.apply(t, h))
			
	}

end

rule "Taupunktdifferenz berechnen" // for statistics: dewpoint difference
when
	Item In_THSensor_Dew changed or
	Item Out_THSensor_Dew changed
then
	var dewpoint_keller = (In_THSensor_Dew.state as Number).doubleValue
	// var dewpoint_keller = In_THSensor_Dew.state
	var dewpoint_aussen = (Out_THSensor_Dew.state as Number).doubleValue
	// var dewpoint_aussen = Out_THSensor_Dew.state
	Taupunkt_Differenz.postUpdate(dewpoint_keller - dewpoint_aussen)
end
Und das ist die Rule zum Triggern der Ventilatoren:

Code: Alles auswählen

var Timer ventilation_timer = null

/* **********************************************************************
 * *      Einstellung obere untere Hysterese der Luftfeuchtigkeit       *
 * **********************************************************************
 * hier schaltet sich nur der Deckenventilator ein
  * 
 */
var Number dehumitification_bottom = 65
var Number dehumitification_top = 75

/* **********************************************************************
 * * Einstellung der Taupunktdifferenz (Kellertaupunkt - Außentaupunkt) *
 * *            2°C bis 9°C, 1°-Schritte, Standardwert 5°C              *
 * **********************************************************************
 * Eine Entfeuchtung erfolgt nach der eingestellten Taupunktdifferenz (effektive Feuchtigkeit).
 * Der Standardwert liegt bei ca. 5°C Taupunktdifferenz. Dies ist ein Erfahrungswert um eine Entfeuchtung
 * effektiv zu gewährleisten. Die Werten können zwischen 2°C und 9°C eingestellt werden. Wird die Differenz
 * verkleinert, also gegen 2 gehen gelassen, wird öfter gelüftet, jedoch wesentlich weniger entfeuchtet.
 * 
 */
var Number dewpoint_min_gap = 5

/* ************************************************************************************************
 * *             Einstellung des Lüftungsintervalls (alle 30min wird erneut geprüft)              *
  * ************************************************************************************************
 */
var Number ventilation_interval = 1

rule "Ventilation Decke" // this is to switch the dehumidificator when the inner humidity runs above a certain value
when
	Item In_THSensor_Hum changed
then
	var Number basement_humidity = In_THSensor_Hum.state as Number
	
	if(basement_humidity >= dehumitification_top) {
		sendCommand(Ventilator_Decke_switch, ON)
	}
	if(basement_humidity <= dehumitification_bottom) {
		sendCommand(Ventilator_Decke_switch, OFF)
	}
end

// this is the core ventilation rule. I checks the surrounding parameters an starts the ventilators for 5 minutes and waits a certain time period to let the "fresh" air collecting the humidity from the inside. 
rule "Ventilation"
when
	Item Out_THSensor_Dew changed or
	Item Out_THSensor_Temp changed or
	Item In_THSensor_Dew changed or
	Item Keller_Ventilation_Trigger changed or
then
	var Number outdoor_dewpoint = Out_THSensor_Dew.state as DecimalType
	var Number basement_dewpoint = In_THSensor_Dew.state as DecimalType

	if (basement_dewpoint - outdoor_dewpoint >= dewpoint_min_gap) {

		if (ventilation_timer === null) {
			if (Ventilator_Decke_switch.state === OFF) sendCommand(Ventilator_Decke_switch, ON)
			if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
			// 30 Minuten Lüften
			ventilation_timer = createTimer(now.plusMinutes(ventilation_interval)) [|
				sendCommand(Ventilator_Decke_switch, OFF)
				sendCommand(Ventilator_Wand_switch, OFF)
				ventilation_timer = null
			]
		}
	}
	
	// Wenn Taupunkt außen höher ist, als Taupunkt Keller, in jedem Fall ausschalten!
	else if (outdoor_dewpoint > basement_dewpoint) {
		sendCommand(Ventilator_Decke_switch, OFF)
		sendCommand(Ventilator_Wand_switch, OFF)
		ventilation_timer = null
	}
	// Wenn Keller_Ventilation_Trigger AN, dann für 30min belüften
	else if (Keller_Ventilation_Trigger.state === ON) {
		if (Ventilator_Decke_switch.state === OFF) sendCommand(Ventilator_Decke_switch, ON)
		if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
		ventilation_timer = createTimer(now.plusMinutes(ventilation_interval)) [|
				sendCommand(Ventilator_Decke_switch, OFF)
				sendCommand(Ventilator_Wand_switch, OFF)
				sendCommand(Keller_Ventilation_Trigger, OFF)
				ventilation_timer = null
			]
	}
end
Beim Intervall habe ich zunächst noch 1min stehen, weil ich sehen möchte, ob sich das Teil auch wieder abschaltet. Die Switches sind auf jeden Fall wieder OFF, nur sind die ITEMS in der PaperUI noch immer ON. Wie bekomme ich dann das aktualisiert?
Ich finde dazu nichts.

Vielleicht kann auch mal einer der Profis drüber schauen und eventuelle Fehler aufzeigen :D

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Ich habe meine Ventilatorsteuerung nochmal angepasst. Das funktionierte nicht so wie ich mir das vorstellte.
Ich hoffe jetzt passt es.

Code: Alles auswählen

var Timer ventilation_timer = null
var Number dehumitification_bottom = 65 // Einstellung unteren Hysterese der Luftfeuchtigkeit
var Number dehumitification_top = 75 // Einstellung oberen Hysterese der Luftfeuchtigkeit
var Number dewpoint_min_gap = 5 // Einstellung der Taupunktdifferenz Kellertaupunkt - Außentaupunkt
var Number ventilation_interval = 35 // Einstellung des Lüftungsintervalls (alle xx min wird erneut geprüft) 

rule "Kellerentfeuchtung"

when
	Item In_THSensor_Dew changed or
	Item In_THSensor_Hum changed
then
	var Number outdoor_dewpoint = Out_THSensor_Dew.state as DecimalType
	var Number basement_dewpoint = In_THSensor_Dew.state as DecimalType
	var Number basement_humidity = (In_THSensor_Hum.state as Number).floatValue
	var Numer dewpoint_gab = (basement_dewpoint - outdoor_dewpoint)
	logInfo("Kellerentfeuchtung", "Luftfeuchte im Keller {}% <= min Luftfeuchte {}%", basement_humidity, dehumitification_bottom)
	logInfo("Kellerentfeuchtung", "Luftfeuchte im Keller {}% >= max Luftfeuchte {}%", basement_humidity, dehumitification_top)
	logInfo("Kellerentfeuchtung", "TaupunktIN {} - TaupunktOUT {} = TaupunktDIFF {} >= TaupunktMinDIFF {}", basement_dewpoint, outdoor_dewpoint, dewpoint_gab, dewpoint_min_gap)
	
	if(basement_humidity >= dehumitification_top) { // wenn die Luftfeuchte im Keller über dem Maximum steht, schalte den Deckenventilator ein
		logInfo("Kellerentfeuchtung", "Ventilation Decke switch ON -- Luftfeuchte im Keller über dem Maximum")
		sendCommand(Ventilator_Decke_switch, ON)

		if(basement_dewpoint - outdoor_dewpoint >= dewpoint_min_gap) {
			logInfo("Kellerentfeuchtung", "Ventilation Wand switch ON -- Taupunkt-Differenz über dem Maximum")
			if (ventilation_timer === null) {
				if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
				// 30 Minuten Lüften
				ventilation_timer = createTimer(now.plusMinutes(ventilation_interval)) [|
					sendCommand(Ventilator_Wand_switch, OFF)
					ventilation_timer = null
				]
			}
		}
		if(basement_dewpoint - outdoor_dewpoint <= dewpoint_min_gap) {
			logInfo("Kellerentfeuchtung", "Ventilation Wand switch OFF -- Taupunkt-Differenz OK")
			sendCommand(Ventilator_Wand_switch, OFF)
		}
	}
	if(basement_humidity < dehumitification_bottom) { // wenn die Luftfeuchte im Keller unter dem Minimum steht, schalte den Deckenventilator aus
		logInfo("Kellerentfeuchtung", "Ventilation Decke und Wand switch OFF -- Luftfeuchte im Keller unter dem Minimum")
		sendCommand(Ventilator_Decke_switch, OFF)
		sendCommand(Ventilator_Wand_switch, OFF)
	}
	
	if(basement_humidity < dehumitification_top) {
		if(basement_humidity >= dehumitification_bottom) {
			logInfo("Kellerentfeuchtung", "Ventilation Decke unverändert -- Luftfeuchte im Regelbereich")
		}
	}

	else if (Keller_Ventilation_Trigger.state === ON) { // Wenn Keller_Ventilation_Trigger AN, dann für 35min belüften
		logInfo("Ventilation Trigger", "Ventilation Trigger started -- Ventilation Decke und Wand switch ON")
		if (Ventilator_Decke_switch.state === OFF) sendCommand(Ventilator_Decke_switch, ON)
		if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
		ventilation_timer = createTimer(now.plusMinutes(ventilation_interval)) [|
			logInfo("Ventilation Trigger", "Ventilation Timer 0 -- Ventilation Decke und Wand switch OFF")
			sendCommand(Ventilator_Decke_switch, OFF)
			sendCommand(Ventilator_Wand_switch, OFF)
			sendCommand(Keller_Ventilation_Trigger, OFF)
			events.postUpdate(Keller_Ventilation_Trigger, OFF)
			ventilation_timer = null
		]
	}
end

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

Re: Taupunkt / Dewpoint Berechnung

Beitrag von udo1toni »

Ich glaube nicht, dass die Rule so funktioniert. Zum einen ist da ein Tippfehler (Numer statt Number in der 4. Zeile nach dem then). Allerdings verwendest Du die Variable garnicht. Dann hast Du aber auch mehrere Vergleiche des Status und verwendest dort === als Operator, das ist nicht zulässig.
Weiterhin prüfst Du teilweise den Status und schaltest dann, dabei prüfst Du aber auf OFF und schaltest dann auf ON. Ein Switch Item kann aber außer OFF und ON noch den Zustand NULL einnehmen.
Du nutzt im letzten Teil ein Item Keller_Ventilation_Trigger. der Teil der Rule wird allerdings nur abgearbeitet, (des else wegen) wenn die vorherige Bedingung if(basement_humidity < dehumitification_top) nicht erfüllt war. Diese Bedingung ist allerdings schon im ersten Teil abgehandelt und schaltet dort bereits automatisch mindestens den einen Ventilator (und je nach Zustand Timer und Taupunktdifferenz auch den anderen Ventilator) ein. Im Extremfall (Obergrenze überschritten und Taupunktdifferent groß genug) laufen anschließend zwei Timer, von denen der eine nicht mehr steuerbar ist.

Du verwendest die Action sendCommand(Itemname als String,Kommando als String), was zwar zulässig, aber nicht gut ist. Hier geht das, aber Du solltest Dir besser angewöhnen, die Methode Itemname.sendCommand(Kommando) zu verwenden. Gleiches gilt für das postUpdate.
Und die Schreibweise für createTimer ist ebenfalls nicht empfohlen, auch wenn sie zulässig ist. Besser (wegen der Lesbarkeit des Codes) ist es, das Lambda als Teil des Funktionsaufrufs zu verwenden.

Die Benennung der Variablen ventilation_interval legt nahe, dass Du einem Irrtum unterliegst ;) denn es erfolgt kiene Prüfung nach xx Minuten, stattdessen wird der Lüfter (bzw. die Lüfter) nach xx Minuten abgeschaltet. Eine Prüfung erfolgt ausschließlich wenn sich die Werte ändern (denn das ist der Trigger für die Rule).

Die logInfos sind hier auch eher nicht besonders hilfreich, zumal durch die langen Variablennamen ohnehin keine gute Übersichtlichkeit herrscht.
Hier mal "meine" Variante Deines Codes:

Code: Alles auswählen

var Timer tVent = null

val Number dehum_min        = 65 // unterer Grenzwert Luftfeuchtigkeit
val Number dehum_max        = 75 // oberer  Grenzwert Luftfeuchtigkeit
val Number dewpoint_min_gap =  5 // minimale Taupunktdifferenz Keller - Außen
val Number vent_dur         = 35 // Lüftungsdauer (nach xx min wird abgeschaltet) 

rule "Kellerentfeuchtung"
when
    Item In_THSensor_Dew changed or
    Item In_THSensor_Hum changed or
    Item Keller_Ventilation_Trigger changed to ON
then
    val basement_hum = (In_THSensor_Hum.state as Number).floatValue
    val dewpoint_gap = (In_THSensor_Dew.state as Number) - (Out_THSensor_Dew.state as Number)

    var sollDecke = OFF                                                                         // Default Soll
    var sollWand  = OFF                                                                         // Default Soll

    if(newState == ON) {                                                                        // Keller_Ventilation_Trigger AN
        sollDecke = ON                                                                          // Soll ändern
        sollWand  = ON                                                                          // Soll ändern
        tVent?.cancel                                                                           // laufenden Timer löschen
        tVent = createTimer(now.plusMinutes(vent_dur), [|                                       // Timer anlegen
            Ventilator_Decke_switch.sendCommand(OFF)
            Ventilator_Wand_switch.sendCommand(OFF)
            Keller_Ventilation_Trigger.postUpdate(OFF)
            tVent = null
        ])
    } else {                                                                                    // Rule nicht durch Taster getriggert
        if(basement_hum > dehum_max) {                                                          // Luftfeuchte Keller über Maximum
            sollDecke = ON                                                                      // Soll ändern
            if(dewpoint_gap > dewpoint_min_gap) {                                               // Taupunktdifferenz ok
                if(tVent === null) {                                                            // Falls kein Timer läuft
                    sollWand = ON                                                               // Soll ändern
                    tVent = createTimer(now.plusMinutes(vent_dur), [|                           // Timer anlegen
                        Ventilator_Wand_switch.sendCommand(OFF)
                        tVent = null
                    ])
                }
            }
        } else if(basement_hum >= dehum_min) {                                                  // Werte innerhalb der Hysterese; kein Aktion
            return;
        }
    }
    if(Ventilator_Decke_switch.state != sollDecke)                                              // Falls Abweichung vom Soll, schalten
        Ventilator_Decke_switch.sendCommand(sollDecke.toString)
    if(Ventilator_Wand_switch.state  != sollWand)                                               // Falls Abweichung vom Soll, schalten
        Ventilator_Wand_switch.sendCommand(sollWand.toString)
end
Die Rule arbeitet etwas anders. Zunächst habe ich Konstanten als val definiert. Der Unterschied ist, dass diese Werte nicht mehr änderbar sind, dafür wird aber auch weniger Code erzeugt.
Dann gibt es den zusätzlichen Trigger um die Lüfter manuell zu starten. Es gibt zwei Variablen sollName, in denen der Sollzustand der beiden Ventilatoren gespeichert wird. Dadurch habe ich zwei Vorteile: Zum Einen kann ich bestimmte Prüfungen einfach auslassen (nämlich die, welche zum Zustand OFF für beide Ventilatoren führen). Zum Zweiten habe ich nur noch eine Stelle im Code, in dem ich den eigentlichen Steuerbefehl absetze (zwei Zeilen vs. sieben Zeilen). Eine Variablenzuweisung ist wesentlich effizienter als ein Funktionsaufruf, das heißt, das entstehende Kompilat ist kompakter und läuft schneller. Das macht in der einzelnen Rule nicht viel aus, in der Summe kann das aber Auswirkungen haben.

Weiter geht's im Code. Es gibt einen übergeordneten Trigger zum manuellen Starten der Ventilatoren, dieser muss also auch mit höherer Priorität verarbeitet werden, also als erstes. Ich nutze hier die Tatsache, dass die implizite Variable newState nur ON oder eine Zahl enthalten kann, wobei ON nur dann drin steht, wenn der Trigger das extra Item war. Wird also der Trigger ausgelöst, so wird der Sollzustand der Ventilatoren auf ON geändert und der Timer zum Abschalten erzeugt - wobei ein eventuell bereits laufender Timer vorher entfernt wird - tVent?.cancel ist gleichbedeutend mit if(tVent !== null) tVent.cancel.
Falls der Trigger nicht das extra Item war, wird auf Überschreiten des oberen Grenzwertes geprüft. Ist das der Fall, greift der gleiche Code wie bei Dir, nur dass ich wieder lediglich die Sollzustände setze. Ist der obere Grenzwert nicht überschritten, so kann es sein, dass der untere Grenzwert überschritten ist. In diesem Fall (wir erinnern uns - kein extra Trigger!) ist nichts zu tun und die Rule wird unverzüglich beendet.
Der letzte Fall - unterer Grenzwert unterschritten - ist bereits der Default unserer Sollzustände, muss also nicht überprüft werden.

Abschließend ist jetzt also nur noch der Sollzustand für beide Ventilatoren herzustellen, was in den letzten Codezeilen passiert.
Man könnte noch überlegen, ob man innerhalb der Timer prüft, ob der Sollzustand abweicht.

Ach so... Hysterese ist der Abstand zwischen oberem und unterem Grenzwert. Du definierst die beiden Grenzwerte und damit indirekt die Hysterese.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Hallo Udo,

danke, dass Du drüber geschaut hast.
Du hast Recht, da war ein Tippfehler. Ich nutze die Variable nur in der LOGausgabe. Eigentlich kann die weg.
Die Sache mit dem dreifachen = finde ich auch komisch und ich hatte zunächst nur == , hab dann aber diese Meldung im LOG bekommen.

Code: Alles auswählen

The operator '==' should be replaced by '===' when null is one of the arguments.

Code: Alles auswählen

if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
Was ist, wenn ich hier das IF State OFF weglasse? Im Grunde ist es doch wurscht was er gerade tut. Er soll ja nur angehen.

Macht es mehr Sinn eine weiter Rule für den Trigger zu bauen? Das mit den doppelten Timern vertehe ich nicht :)

Aus den sendCommand(Ventilator_Decke_switch, ON) mache ich also besser Ventilator_Decke_switch.sendCommand(ON) ?
Das kommt mir auch bekannter vor, wenn ich mich an Powershell erinnere.

Beim CreateTimer hast Du mich komplett abgehängt. Hast Du ein Beispiel ?

Grüße

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

Re: Taupunkt / Dewpoint Berechnung

Beitrag von udo1toni »

domjo75 hat geschrieben: 4. Feb 2021 15:02 Die Sache mit dem dreifachen = finde ich auch komisch und ich hatte zunächst nur == , hab dann aber diese Meldung im LOG bekommen.

Code: Alles auswählen

The operator '==' should be replaced by '===' when null is one of the arguments.
Ja, aber das bezieht sich auf exakt eine Zeile in Deinem Code, nämlich die Prüfung auf null im Zusammenhang mit der Timer Variablen.
Und die Meldung ist ja nun auch klar genug: der Operator == sollte mit === ersetzt werden, falls (und nur falls) eines der beiden Argumente null ist.

Hintergrund: == bedeutet "ist gleich". === bedeutet "ist identisch". Der Unterschied wird klar, wenn man versteht, wie Daten gespeichert werden. Die Daten liegen in Speicherzellen. Die Variablen oder Konstanten sind Zeiger, die auf diese Speicherzellen verweisen. Wenn man nun einer Variablen den Wert null zuweist, so wird der Zeiger in der Variablen auf eine ganz bestimmte Speicherzelle gesetzt. === vergleicht nun also nicht den Inhalt der Speicherzelle, sondern, ob der Zeiger auf diese Speicherzelle zeigt, der Wert also der selbe (und nicht der gleiche!) ist.
domjo75 hat geschrieben: 4. Feb 2021 15:02

Code: Alles auswählen

if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
Was ist, wenn ich hier das IF State OFF weglasse? Im Grunde ist es doch wurscht was er gerade tut. Er soll ja nur angehen.
Nun ja, der Unterschied besteht darin, dass Du ständig Einschaltbefehle senden wirst, auch wenn der Ventilator bereits läuft, und zwar so lange, bis der obere Grenzwert unterschritten ist. Das gleiche gillt dann sinngemäß bei unterschreiten des unteren Grenzwertes. Du willst nicht sinnlos Schaltbefehle senden, das müllt nur Deinen Bus zu (selbst wenn nur alle paar Minuten eine Änderung des Messwertes rein kommt).
domjo75 hat geschrieben: 4. Feb 2021 15:02 Macht es mehr Sinn eine weiter Rule für den Trigger zu bauen?
Nein, eigentlich ist das ganz gut in der Rule aufgehoben, es muss aber korrekt umgesetzt sein...
domjo75 hat geschrieben: 4. Feb 2021 15:02 Das mit den doppelten Timern vertehe ich nicht :)
Na, nehmen wir an, der obere Grenzwert wurde überschritten und der Taupunkt passt, dann wird oben ein Timer angelegt, der ventilation_interval Minuten läuft. Ein Zeiger auf diesen Timer wird in ventilation_timer gespeichert.
Weiter unten wird der Timer wieder gesetzt (falls Keller_Ventilation_Trigger ON ist). Dabei wird der Zeiger auf den ersten Timer einfach überschrieben. Das passiert übrigens so lange, bis der obere Grenzwert unterschritten wird, das kann also auch noch mehrere Minuten nach dem Anlegen des ersten Timers passieren. Du verwendest immer die selbe Variable, prüft aber nicht, ob diese auch null ist. Du überschreibst den Wert einfach. In der Folge werden immer wieder Timer angelegt, die bestehenden Timer existieren aber weiter, sie wurden ja nicht entfernt. Wenn es dumm läuft, schalten diverse Timer hintereinander Deine Items immer wieder aus, obwohl die Rule die Items gerade erst eingeschaltet hat, und Du suchst verzweifelt nach dem Grund...
domjo75 hat geschrieben: 4. Feb 2021 15:02 Aus den sendCommand(Ventilator_Decke_switch, ON) mache ich also besser Ventilator_Decke_switch.sendCommand(ON) ?
genau.
domjo75 hat geschrieben: 4. Feb 2021 15:02 Beim CreateTimer hast Du mich komplett abgehängt. Hast Du ein Beispiel ?
Ja. Du schreibst (generalisiert):

Code: Alles auswählen

tTimer = createTimer(now.plusX()) [|
    // code
]
ich schreibe

Code: Alles auswählen

tTimer = createTimer(now.plusX(), [|
    // code
])
Die schließende Klammer wandert also hinter das Ende des Lambda, dafür steht vor dem Lambda ein Komma. Das Lambda ist damit ein Argument der Funktion createTimer().
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

domjo75
Beiträge: 159
Registriert: 22. Jan 2019 11:10
Answers: 0

Re: Taupunkt / Dewpoint Berechnung

Beitrag von domjo75 »

Hallo,

ich suche immer noch den "Hutzieh" -Smiley :)
Das ist schon erstaunlich wie schnell Du mein Script verbessert hat. Ich verstehe schon grundsätzlich was Du da machst, aber im Detail komme ich da nicht mit. Und selber ein Script in dieser Qualität zu bauen, traue ich mir nicht zu.
Ich habe es übernommen, nutze es als "Vorlage" und freu mich, dass es funktioniert.

Nochmals vielen Dank für die Unterstützung.

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

Re: Taupunkt / Dewpoint Berechnung

Beitrag von udo1toni »

:) gerne.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten