Seite 1 von 1

[GELÖST] Kellerlüftung / State in var ablegen - Item Werte casten und umwandeln

Verfasst: 19. Nov 2022 12:08
von Selter
Hallo zusammen,

ich habe Rule zur Kellerlüftung an meine Bedürfnisse angepasst, allerdings funktioniert eine Sache offenbar nicht korrekt.

Es gibt eine Bedingung (// Auskühlung des Kellers verhindern), die das Auskühlen des Kellers verhindern soll, wenn die Außentemperatur unter 2°C liegt.
Das funktioniert aber nicht - die Lüftung läuft trotzdem, obwohl gerade draußen 1,5°C sind.

Ich vermute, es liegt an der Konvertierung des Temperaturwertes (

Code: Alles auswählen

OUT_s_xtemp2_Temperature
= "1.5 °C") in die Var

Code: Alles auswählen

outdoor_temperature
mit diesem Code:

Code: Alles auswählen

var Number outdoor_temperature = OUT_s_xtemp2_Temperature.state as QuantityType<Number>
Es gibt aber auch keine Fehlermeldung im Log.
(Wenn ich "OUT_s_xtemp2_Temperature.state as DecimalType" verwende, bekomme ich einen Error.)

Ich hoffe, Ihr könnt mir bei der Konvertierung helfen bzw. das Script korrigieren?

Code: Alles auswählen

rule "Ventilation"			
when
	Item Taupunkt_Differenz changed or
	Item Keller_Ventilation_Interval changed or
	Item Keller_Temperatur_Min changed or
	Item Keller_Ventilation_Steady changed or
	Item KE_x_pow2_switch changed
then
	var Number dewpoint_gap = Taupunkt_Differenz.state as DecimalType
	var Number dewpoint_min_gap = Keller_Dewpoint_Gap_Min.state as DecimalType
	var Number outdoor_temperature = OUT_s_xtemp2_Temperature.state as QuantityType<Number>

	ventilation_interval = 20 // set default value
    if(Keller_Ventilation_Interval.state instanceof Number)
        ventilation_interval = (Keller_Ventilation_Interval.state as Number).intValue

		logInfo("KELLERLUEFTUNG","Taupunktdifferenz (Keller minus Außen) ist " + dewpoint_gap + ". Mindestdifferenz ist (custom) " + dewpoint_min_gap + ". Außentaupunkt muss niedriger sein als Kellertaupunkt." )

	// Wenn Lüftung ständig an sein soll, dann Steckdose an!
	if (Keller_Ventilation_Steady.state == ON) {
		sendCommand(KE_x_pow2_switch, ON)
		logInfo("KELLERLUEFTUNG","Lüftung an, da Dauerlüftung eingeschaltet.")
		ventilation_timer = null
		interval_timer = null
	}
	// Auskühlung des Kellers verhindern
	else if (outdoor_temperature <= 2) {
		sendCommand(KE_x_pow2_switch, OFF)
		logInfo("KELLERLUEFTUNG","Lüftung aus, da Außentemperatur niedriger als 2°C. [" + outdoor_temperature + "°C]")
		ventilation_timer = null
		interval_timer = null
	}
	// Wenn Taupunkt außen höher ist, als Taupunkt Keller, in jedem Fall ausschalten!
	else if (dewpoint_gap <= 0) {
		sendCommand(KE_x_pow2_switch, OFF)
		logInfo("KELLERLUEFTUNG","Lüftung aus, da Außentaupunkt [" + Aussenbereich_Taupunkt + "] höher als Kellertaupunkt [" + Keller_Taupunkt + "].")
		ventilation_timer = null
		interval_timer = null
	}
	// Lüftungsprogramm abfragen
	else if (dewpoint_gap >= dewpoint_min_gap) {

		if (ventilation_interval > 0 && ventilation_timer === null && interval_timer === null) {

			if (KE_x_pow2_switch.state == OFF && KE_x_pow1_switch.state == OFF) sendCommand(KE_x_pow2_switch, ON)		// if (KE_x_pow2_switch.state == OFF) sendCommand(KE_x_pow2_switch, ON) -> erweitert um Luftentfeuchter muss aus sein

			// nach 5 Minuten Lüften ausschalten
			ventilation_timer = createTimer(now.plusMinutes(5), [|
				sendCommand(KE_x_pow2_switch, OFF)
				ventilation_timer = null
				logInfo("KELLERLUEFTUNG","Lüftung aus, da 5 Minuten gelüftet.")
				// Pause gem. Keller_Ventilation_Interval
				interval_timer = createTimer(now.plusMinutes(ventilation_interval), [|
					sendCommand(KE_x_pow2_switch, ON)
					interval_timer = null
					logInfo("KELLERLUEFTUNG","Lüftung an, weil custom " + ventilation_interval + " Minuten Pausen-Intervall vorbei.")
				])
				logInfo("KELLERLUEFTUNG", ventilation_interval + "-Minuten-Timer (custom) für Pausen-Intervall gesetzt.")
			])
			logInfo("KELLERLUEFTUNG","Lüftung gestartet / 5 Minuten-Timer für Lüftung gesetzt / Aktuelle Werte: " + KE_s_XiaomiTemperatursensorC_Humidity.state +" / " + KE_s_XiaomiTemperatursensorC_Temperature.state)
			Thread::sleep(300)
		} else if (ventilation_interval == 0) {
			if (KE_x_pow2_switch.state == OFF) sendCommand(KE_x_pow2_switch, ON)
		}

	} else if (ventilation_timer === null && interval_timer === null) {

		if (KE_x_pow2_switch.state == ON) {
			if (KE_x_pow2_switch.state == ON) sendCommand(KE_x_pow2_switch, OFF)
			logInfo("KELLERLUEFTUNG","Lüftung pauschal aus.")
		}

	}
	
	if (KE_x_pow2_switch.state == ON) {
		logInfo("KELLERLUEFTUNG","Lüftung läuft.")
		    // sendPushoverMessage(pushoverBuilder("Lüftung läuft").withSound("mechanical"))
    		// Thread::sleep(100)
	}
	else logInfo("KELLERLUEFTUNG","Lüftung ist aus. Aktuelle Werte: " + KE_s_XiaomiTemperatursensorC_Humidity.state + " / " + KE_s_XiaomiTemperatursensorC_Temperature.state)

end

Re: Kellerlüftung / State in var ablegen

Verfasst: 20. Nov 2022 03:56
von udo1toni
Die Rule hat einige Schwachpunkte. Der Fehler rührt daher, dass QuantityType<Number> keinesfalls die Einheit entfernt, falls eine solche mit dem Item mitgeliefert wird. Stattdessen muss lediglich nach Number gecastet werden und der Zahlenwert anschließend nach float gewandelt werden:

Code: Alles auswählen

var Number outdoor_temperature = (OUT_s_xtemp2_Temperature.state as Number).floatValue
Aber wie erwähnt gibt es da noch einige weitere Probleme. Beispielsweise führt das Löschen des Zeigers auf einen Timer nicht dazu, dass der Timer abgebrochen wird. Stattdessen verliert man die Kontrolle über den Timer. Du musst also vor jedem ventilation_timer = null noch ein

Code: Alles auswählen

ventilation_timer?.cancel
einfügen. Wahlweise kannst Du es auch ausschreiben:

Code: Alles auswählen

if(ventilation_timer !== null) ventilation_timer.cancel
Nur innerhalb des Timer Codes ist das nicht nötig.
Das Gleiche gilt sinngemäß auch für den zweiten Timer.

Das ist auch eine unnötige Komplexität, einfacher wäre es, im ersten Timer den Zustand von KE_x_pow2_switch zu prüfen. Falls er gerade an ist, schaltet der Code dann aus und startet den Timer erneut (mit dem Wert von ventilation_interval), ansonsten schaltet er an und setzt den Zeiger auf null.
Auf diese Weise spart man einige Zeilen Code ein, da nur noch ein Timer zu steuern ist.

Allgemein ist es besser, die Methode KE_x_pow2_switch.sendCommand([ON|OFF]) zu verwenden, statt der Action sendCommand(KE_x_pow2_switch, [ON|OFF])
In den Logbefehlen kann man mit Substitution arbeiten.

Code: Alles auswählen

var strWort = "eine"
logInfo("logger","Dies ist " + strWort + " Meldung.")
kann man auch so schreiben:

Code: Alles auswählen

var strWort = "eine"
logInfo("logger","Dies ist {}  Meldung.",strWort)
Durch die Substitution wird das N-te Klammerpaar durch den N-ten zusätzlichen Parameter ersetzt. Das Schöne daran: bei der Substitution werden sämtliche Typumwandlungen automatisch ausgeführt. Außerdem lässt sich der Meldungstext im Code leichter sinnerfassend lesen.

Re: Kellerlüftung / State in var ablegen

Verfasst: 20. Nov 2022 12:39
von Selter
Vielen Dank, Udo - das hat mir sehr geholfen.
Und ich habe wieder viel dazugelernt :)