[Rule] Heizung steuern bei Änderung des Fenstersensors

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von udo1toni »

mapdb ist für den Zeitstempel ok, nicht aber für die Temperatur. mapdb liefert IMMER den letzten Wert des Items (im laufenden Betrieb also den AKTUELLEN Status). Du willst aber den Status vor dem aktuellen Status haben, besser den Status zu einem bestimmten Zeitpunkt (der vom Zeitstempel vorgegeben ist).

Zu den Fehlermeldungen: die erste (cannot convert from HistoricItem to Command):
Eventuell muss noch ein .state hinter die erste schließende Klammer, es könnte sogar sein, dass noch ein .toString dran muss. Also so:

Code: Alles auswählen

AZ_Heizung_SetTemp.sendCommand(AZ_Heizung_SetTemp.historicState(AZ_Zeitstempel.state as DateTimeType).state) 
oder

Code: Alles auswählen

AZ_Heizung_SetTemp.sendCommand(AZ_Heizung_SetTemp.historicState(AZ_Zeitstempel.state as DateTimeType).state.toString) 
Die Zeile wirft aber noch einen zweiten Fehler (cannot convert from DateTimeType to AbstractInstant).
Das wird die härtere Nuss werden... eventuell reicht aber schon ein .getZonedDateTime(), so dass die Zeile dann so aussieht:

Code: Alles auswählen

AZ_Heizung_SetTemp.sendCommand(AZ_Heizung_SetTemp.historicState((AZ_Zeitstempel.state as DateTimeType).getZonedDateTime()).state.toString) 
Das ist aber nur eine Vermutung.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von Eleven »

Ich habe Deine Änderungen mal ausprobiert. Also die Fehlermeldung:

Code: Alles auswählen

Type mismatch: cannot convert from DateTimeType to AbstractInstant
ist immer noch vorhanden. Leider hat das .getZonedDateTime() nicht den nötigen Erfolg gebracht.

Die Fehlermeldung bezieht sich auf den folgenden Teil: AZ_Zeitstempel.state as DateTimeType

Aktuell habe ich diese Zeile so gesetzt:

Code: Alles auswählen

AZ_Heizung_SetTemp.sendCommand(AZ_Heizung_SetTemp.historicState(AZ_Zeitstempel.state as DateTimeType).state.toString)
Hast Du noch eine Idee?
Was für eine persistence sollte die Solltemperatur den geschrieben werden? rrd4j?

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

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von udo1toni »

Ja, rrd4j sollte funktionieren.

Probiere bitte mal diese Variante:

Code: Alles auswählen

AZ_Heizung_SetTemp.sendCommand(AZ_Heizung_SetTemp.historicState((AZ_Zeitstempel.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).state.toString)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von Eleven »

Funktioniert leider nicht.
Fehlermeldung ist etwas anders:

Code: Alles auswählen

Type mismatch: cannot convert from long to AbstractInstant
Edit: Hat vielleicht noch jemand eine Idee oder eine vergleichbar funktionierende Konfiguration?

Grüße Eleven

Sigi
Beiträge: 15
Registriert: 4. Jan 2020 23:50
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von Sigi »

Hallo und guten Abend,

da ich im Augenblick mit einem ähnlichen Problem beschäfigt bin, schließe ich mich hier mal an.

Folgende Situation:
Ich hab openHAB 3 auf einem Raspberry Pi 4 am laufen und möchte meine E-Heizungen mittels Shelly HT und Plug S steuern.

Ich hab also folgende Items:

Code: Alles auswählen

Shelly_VE_HT_Tem 
Shelly_VE_PS_Bet
für die Hardware und folgende:

Code: Alles auswählen

HeizVE
gHeizHaus
als Setpoint-Dummies zur Steuerung, wobei HeizVE Teil der Gruppe gHeizHaus ist.

Die Items hab ich im UI angelegt und mit den Things verlinkt. Für jedes Zimmer gibt es eigene Items, bei denen jeweils die Kennung anders ist; hier bei Veranda ist es VE, im Bad dann entsprechend BA.

Mittels Rules möchte ist jetzt die Soll-Temperaturen einstellen. Und zwar einerseits zentral für das ganze Haus mittels gHeizHaus und andererseits jeden Raum einzeln mittels HeizVE.
Hierfür habe ich für jedes Zimmer folgende Rules angelegt, die sich jeweils in ihrer Zimmer-Kennung unterscheiden:

Code: Alles auswählen

rule "Heizung Veranda"
when
    Item Shelly_VE_HT_Tem changed or                                            // Istwert Temp Veranda
    Item HeizVE changed or                                                      // Sollwert Heizung Vernada
    Item gHeizHaus changed                                                      // Sollwert Heizung Haus
then
    val Number vets = (HeizVE.state as Number).doubleValue                      // Temperatur Soll Veranda 
    val Number veti = (Shelly_VE_HT_Tem.state as Number).doubleValue            // Temperatur Ist Veranda
    
    if (vets > veti)                                                            // Vergleich Soll > Ist
        Shelly_VE_PS_Bet.sendCommand(if ( Shelly_VE_PS_Bet.state == OFF ) ON )  // Heizung geht - wenn sie aus ist - an wenn Soll > Ist
    else                                                                        
        Shelly_VE_PS_Bet.sendCommand(if ( Shelly_VE_PS_Bet.state == ON ) OFF)   // Heizung geht - wenn sie an ist - aus wenn Soll <= Ist
end
Ich fürchte, irgendwas stimmt mit den Rules nicht.
Sobald ich diese aktiviere, wird openHAB innerhalb weniger Minuten quasi nicht mehr nutzbar.
Es wird extrem langsam, die UIs reagieren super zäh bis gar nicht mehr, auf myopenhab.org ist das System nicht mehr erreichbar.
Bis jetzt hat nur ein Neustart von openHAB geholfen, wobei es bei weiterhin aktiven Heizungs-Rules immer wieder sehr schnell sehr zäh wird. Wenn ich die Rules deaktiviere, ist nach einem Neustart alles wieder wie gewohnt schnell.

Vielleicht könnt Ihr mir Helfen.
Vielen Dank jedenfalls schon mal im Voraus.

Schönen Abend,
Sigi

Sigi
Beiträge: 15
Registriert: 4. Jan 2020 23:50
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von Sigi »

Guten Morgen,

bin gerade darauf gekommen, dass ich

Code: Alles auswählen

val Number ...
geschrieben habe und es eigentlich

Code: Alles auswählen

var Number ...
heissen sollte.

Hoffe das war der einzige Fehler... :D

Schönen Tag,
Sigi

habuser1
Beiträge: 21
Registriert: 1. Nov 2021 13:08
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von habuser1 »

Hallo! ich möchte das gleiche erreichen... bin aber mit dem Code überfordert... kann man das auch mit den YAML GUI Rules bauen?

Bisher habe ich es so, dass die Heizung auf Energy schaltet, wenn das Fenster offen ist.
Aber die Heizung soll nur wieder angehen, wenn sie davor auch im Heat-Modus war. Wenn Sie davor eh aus war, soll sie natürlich nicht wieder angehen.

Kann man das auch in mit UI Regeln realisieren? Wenn ja, wie?

Danke und Grüße!

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

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von udo1toni »

Ja, grundsätzlich ist das kein Problem. Ich habe jetzt oben nicht geschaut, wie es dort gelöst ist, nur so viel: Wenn Du eine Rule über die UI anlegst (egal welcher Typ) gibt es eine Einschränkung gegenüber den Rules aus den *.rules Dateien, und das sind die globalen Variablen. Nur *.rules Dateien stellen auf Wunsch globale Variablen zur Verfügung. Das heißt, Du musst den "alten" Status anders sichern.

Grundsätzlich gibt es dazu zwei Optionen, zum einen über ein ungebundenes Item. Du speicherst bei jedem Betriebsartenwechsel (außer dem auf Energy) die neue Betriebsart in diesem Item. Wenn das Fenster geschlossen wird, setzt Du die aktuelle Betriebsart auf den Status des Items.
Die andere Option wäre Persistence. Dazu persistierst Du Betriebsart und Fensterkontakt. Beim Schließen des Fensters prüfst Du den Zeitpunkt ab, zu dem das Fenster zuletzt geschlossen war. Diesen Zeitpunkt nutzt Du dann, um in der Persistence die Betriebsart nachzuschauen, die zu dem Zeitpunkt aktiv war.
Die zweite Variante ist wesentlich eleganter und man kann diese auf jeden Fall auch über eine UI-Rule programmieren (allerdings nicht ohne Code, in welcher Sprache auch immer). Sie ist aber anspruchsvoller in der Umsetzung.
Die erste Variante lässt sich mit zwei Rules erledigen. Rule 1 brauchst Du ohnehin (Fenster wird geöffnet). Dort speicherst Du halt die aktuelle Betriebsart, bevor Du diese änderst.
Achtung: openHAB arbeitet asynchron. Es gibt keine Garantie, dass ein itemA.postUpdate(itemB.state) tatsächlich ausgeführt wird, bevor itemB.sendCommand("Energy") ausgeführt wurde. Es ist in einem solchen Fall also sinnvoll, eine kleine Pause einzulegen.
In der 2. Rule schreibst Du einfach den gesicherten Status wieder zurück.
Diese Variante ist also sehr leicht umzusetzen, auch über UI-Rules (die Reihenfolge der Befehle muss aber eingehalten werden), dafür benötigt sie aber pro Steuerung ein zusätzliches Item.
Falls die Pausen nicht eingehalten werden, kannst Du auch eine dritte Rule nutzen. Diese Rule löst jedes Mal aus, wenn sich die Betriebsart ändert. Sie schreibt umgehend die aktuelle Betriebsart in das Hilfsitem, aber nur, wenn der Zustand nicht "Energy" ist. (but only if) So musst Du in der "ersten" Rule (also die, die bei Fenster auf triggert) Dich nicht um den aktuellen Status kümmern, der wurde ja schon notiert.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27
Answers: 0

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von Eleven »

udo1toni hat geschrieben: 11. Jan 2021 00:16 Es gibt dafür verschiedene Möglichkeiten. Die "billige" Variante: Du legst einfach eine globale Variable (pro Temperaturwert, der gemerkt werden soll) an und rettest den Temperaturwert in diesem Zwischenspeicher. Nachteil: Wenn openHAB bei geöffnetem Fenster neu gestartet wird, weiß openHAB nicht mehr, welche Temperatur beim Öffnen eingestellt war, denn die Variable wird neu initialisiert. Leider wird die globale Variable auch beim erneuten Einlesen der Datei initialisiert, sogar, wenn Du nur den Zeitstempel der Datei änderst, aber auch wenn Du nur etwas an einer Rule änderst.
Trotzdem als Beispiel:

Code: Alles auswählen

var Timer fenstertimer = null    
val Number tempComfort = 23.0
val Number tempOff = 8.0
var Number tempBDU = 23.0               // Nur ein Default Wert. Beim Öffnen des Fensters wird der Wert überschrieben.

rule "Heizung Bad unten"
when
    Item BDU_Fenster_Status changed                             // Triggere wenn der Fensterkontakt geschaltet hat
then
    if(BDU_Fenster_Status.state != CLOSED) {                    // Fenster offen oder nicht initialisiert?
        tempBDU = BDU_Heizung_SetTemp.state as Number    // Temperatur retten
        BDU_Heizung_SetTemp.sendCommand(tempOff)  
        logInfo("Heizung", "Fenster im Bad unten geöffnet und Heizkörper abgedreht")
        fenstertimer = createTimer(now.plusMinutes(10), [|      // Starte Timer für Meldung
            sendPushoverMessage(pushoverBuilder("Info, Fenster Bad unten 10 Min. geöffnet").withDevice("iPhoneXR"))
        ])                                                      // Lambda in die Funktion verschoben, Lesbarkeit des Codes
    } else {                                                    // Fenster ist geschlossen!
        BDU_Heizung_SetTemp.sendCommand(tempBDU)          // geretteten Wert zurückschreiben.
        logInfo("Heizung", "Fenster im Bad unten geschlossen und Heizkörper aufgedreht")
        fenstertimer?.cancel                                 // Timer abbrechen, falls aktiv
    }
end
Es ist nicht notwendig, kompliziert nach === null zu prüfen, der ? Operator erledigt das wesentlich eleganter.

Die bessere Alternative führt über die Persistence. Weil ich jetzt Feierabend habe, bleibe ich ein konkretes Codebeispiel schuldig, aber ich erkläre es zumindest. Du brauchst für jede Temperatur eine Persistence. Zusätzlich brauchst Du ein DateTime Item pro Temperatur, die wiederhergestellt werden soll. Auch dieses Item muss persistiert werden, und zwar mit mapDB (oder einer anderen Persistence, welche DateTime nativ unterstützt).

Wenn die Temperatur abgesenkt wird, merkst Du Dir im zugehörigen Item den Zeitpunkt (unbedingt bevor die Temperatur abgesenkt wird!). Wenn nun openHAB zwischendurch neu gestartet wird, stellt die Persistence Strategy restoreOnStartup den aktuellen Wert dieses Datetime Items wieder her. Damit ist der große Fehler oben Geschichte.
Wird das Fenster geschlossen, lässt Du per temperaturItem.sendCommand(temperaturItem.historicState(DateTimeItem.state as DateTimeType)) den alten Wert wiederherstellen. Kann gut sein, dass der Aufruf leicht anders ist, aber so ungefähr sollte es funktionieren.
Ich möchte dieses Thema nochmals aufgreifen, da ich es damals nicht geschafft habe zu realisieren und ich dann irgendwann die Lust verloren hatte. Nun möchte ich mich nochmals diesem Thema widmen, da die Heizperiode in absehbarer Zeit wieder anfängt. Mein Ziel ist es die Variante mit der Persistence umzusetzen. Kannst Du mir evtl. nochmal anhand eines Beispiels erklären wie man vorgehen sollte?

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

Re: [Rule] Heizung steuern bei Änderung des Fenstersensors

Beitrag von udo1toni »

Na ja, nehmen wir an, wir haben drei Items,
sollTemperatur,
fensterKontakt und
offenZeit (hier merken wir uns die Zeit, wenn das Fenster geöffnet oder geschlossen wird)

Dann sähe eine passende Rule ungefähr so aus:

Code: Alles auswählen

rule "fenster Kontakt"
when
    Item fensterKontakt changed
then
    if(newState == OPEN) {
        offenZeit.postUpdate(new DateTimeType(now.minusSeconds(1)))
        sollTemperatur.sendCommand(7)
    } else {
        sollTemperatur.sendCommand(sollTemperatur.historicState((offenZeit.state as DateTimeType).getZonedDateTime()))
        offenZeit.postUpdate(new DateTimeType(now.plusSeconds(1)))
    }
end
Ob der Code so funktioniert, kann ich allerdings nicht sicher sagen. Aber die Theorie dahinter: Wenn der Zustand des Fensters sich ändert, startet die Rule.
Es wird geprüft, ob das Fenster geschlossen oder geöffnet wurde. In letzterem Fall wird ein Zeitspempel vor einer Sekunde gerettet und die Solltemperatur auf 7 gesetzt. In ersterem Fall wird die sollTemperatur von dem gespeicherten Zeitpunkt ausgelesen und gesetzt, außerdem wird als Zeitpunkt der eine Sekunde in der Zukunft gespeichert.

So ist sichergestellt, dass immer die zum Zeitpunkt des Öffnens eingestellte Soll-Temperatur wiederhergestellt wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten