Taupunkt / Dewpoint Berechnung
-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Taupunkt / Dewpoint Berechnung
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
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
-
- Beiträge: 207
- Registriert: 5. Mär 2019 21:13
- Wohnort: Ingolstadt
Re: Taupunkt / Dewpoint Berechnung
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 ?
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
Gruß
Jojo
-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Re: Taupunkt / Dewpoint Berechnung
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
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
-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Re: Taupunkt / Dewpoint Berechnung
Ich war dann heute mal fleissig und habe die Geschichte auf meine Bedürfnisse umgebastelt
Das sind meine ITEMS:
Das ist die Rule zur Taupunktberechnung:
Und das ist die Rule zum Triggern der Ventilatoren:
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
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)
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
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
Ich finde dazu nichts.
Vielleicht kann auch mal einer der Profis drüber schauen und eventuelle Fehler aufzeigen

-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Re: Taupunkt / Dewpoint Berechnung
Ich habe meine Ventilatorsteuerung nochmal angepasst. Das funktionierte nicht so wie ich mir das vorstellte.
Ich hoffe jetzt passt es.
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
- udo1toni
- Beiträge: 15247
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Taupunkt / Dewpoint Berechnung
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:
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.
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

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
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
-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Re: Taupunkt / Dewpoint Berechnung
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.
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
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)
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
- udo1toni
- Beiträge: 15247
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Taupunkt / Dewpoint Berechnung
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.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.
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.
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:02Was ist, wenn ich hier das IF State OFF weglasse? Im Grunde ist es doch wurscht was er gerade tut. Er soll ja nur angehen.Code: Alles auswählen
if (Ventilator_Wand_switch.state === OFF) sendCommand(Ventilator_Wand_switch, ON)
Nein, eigentlich ist das ganz gut in der Rule aufgehoben, es muss aber korrekt umgesetzt sein...
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...
genau.
Ja. Du schreibst (generalisiert):
Code: Alles auswählen
tTimer = createTimer(now.plusX()) [|
// code
]
Code: Alles auswählen
tTimer = createTimer(now.plusX(), [|
// code
])
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet
-
- Beiträge: 159
- Registriert: 22. Jan 2019 11:10
Re: Taupunkt / Dewpoint Berechnung
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.
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.
- udo1toni
- Beiträge: 15247
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Taupunkt / Dewpoint Berechnung

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