Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
- PeterA
- Beiträge: 1074
- Registriert: 8. Feb 2019 12:12
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo zusammen,
zwischenzeitlich ist auch hier ein Balkonkraftwerk "eingezogen"
Leider sind die Wolkenmengen die übers Wetterbinding reinkommen nicht immer passend für meinen Standort.
Anstelle der Wolkenmenge verwende ich nun die Einstrahlung auf die Panels.
Das funktioniert viel besser als die Wolkenmenge vom Wetterbinding.
Gruß
Peter
zwischenzeitlich ist auch hier ein Balkonkraftwerk "eingezogen"
Leider sind die Wolkenmengen die übers Wetterbinding reinkommen nicht immer passend für meinen Standort.
Anstelle der Wolkenmenge verwende ich nun die Einstrahlung auf die Panels.
Das funktioniert viel besser als die Wolkenmenge vom Wetterbinding.
Gruß
Peter
- OpenHab 2.4
#PWRUP
#PWRUP
-
- Beiträge: 81
- Registriert: 16. Jan 2022 13:30
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo,
zu erst: VIELEN DANK für die super Arbeit an der Rule zur automatischen Verschattung! Diese hat uns letzten Sommer echt ein kühles Zuhause ermöglicht.
Ich hatte noch einen kleinen Darstellungsfehler in der Sitemap, den ich ausbügeln wollte...
Ausgangslage: Der angezeigte Wert in der Sitemap stimmt nicht mit dem im Item hinterlegten Wert überein...
Im Item ist 65 eingestellt. Angezeigt wird allerdings 2.
Das Item ist als Nummer:Dimonsenless angelegt.
----------------------> Soweit so gut. In der Form funktioniert die Rule einwandfrei.
Sobald ich nun das Item auf den Typ Number umstelle, ist zwar die Anzeige in der Sitemap korrekt mit 65 % aber die Rule funktioniert dafür nicht mehr...
Im Log steht dann:
Jemand eine Idee, woran dieses Verhalten liegen könnte?
Grüße und vielen Dank für eure Ideen
zu erst: VIELEN DANK für die super Arbeit an der Rule zur automatischen Verschattung! Diese hat uns letzten Sommer echt ein kühles Zuhause ermöglicht.
Ich hatte noch einen kleinen Darstellungsfehler in der Sitemap, den ich ausbügeln wollte...
Ausgangslage: Der angezeigte Wert in der Sitemap stimmt nicht mit dem im Item hinterlegten Wert überein...
Im Item ist 65 eingestellt. Angezeigt wird allerdings 2.
Das Item ist als Nummer:Dimonsenless angelegt.
----------------------> Soweit so gut. In der Form funktioniert die Rule einwandfrei.
Sobald ich nun das Item auf den Typ Number umstelle, ist zwar die Anzeige in der Sitemap korrekt mit 65 % aber die Rule funktioniert dafür nicht mehr...
Im Log steht dann:
Ich vermute, dass in diesen Zeilen der Fehler versteckt ist:2023-05-21 14:34:59.541 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'auto_verschattung_sued_down-1' failed: For input string: "65.0" in auto_verschattung_sued_down
Code: Alles auswählen
group_Rollladen_Sued_hight.members.forEach[i|
if ((i.state as Number).floatValue <= (Rollladenautomatik_zielwert_sued.state as Number)) {
if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf ' + Rollladenautomatik_zielwert_sued.state.toString() + '%: ' + i.name)
i.sendCommand(Integer::parseInt(Rollladenautomatik_zielwert_sued.state.toString()))
} else {
if (log) logInfo('rules', logPrefix + 'Rolladen ist bereits weiter geschlossen (' + i.state.toString() + '%) als er geschlossen werden sollte und wird daher ignoriert')
}
]
Grüße und vielen Dank für eure Ideen
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
OpenHAB 4.3.0
in einem Docker-Container
auf einer Synology DS1515+
in einem Docker-Container
auf einer Synology DS1515+
- udo1toni
- Beiträge: 14829
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Der Codeschnipsel ist unnötig kompliziert. Probiere es mal so:
Der springende Punkt ist die Umwandlung nach Integer, aber es waren da noch einige andere Dinge, die ich angepasst habe.
BITTE nicht dieses schreckliche (und echt schlechte) if(log) logInfo() verwenden. Ich habe das (sehr viel) weiter oben erläutert. logInfo() ist mehr als ein Print-Befehl. Der erste Parameter ist der Loggername und sollte keinesfalls "rules" lauten. Auch ein dateiabhängiger String ist Quatsch. Stattdessen setzt man für logisch zusammenhängende Rule den identischen Loggernamen und kann so gezielt während openHAB läuft! das Logging auf verschiedenen Leveln ein- oder ausschalten. log:set WARN org.openhab.core.module.script.autoRoll schaltet z.B. die Info-Logs aus, lässt aber logWarn() und logError() durch. Mit log:set DEBUG org.openhab.core.module.script.autoRoll werden zusätzlich noch logDebug() Meldungen eingeschaltet. Das ist wesentlich besser als ein ungenaues if(log)
Die log Befehle beherrschen außerdem Substitution, das heißt, innerhalb einer Strings, der als zweiter Parameter angegeben wird (das ist die Meldung, die geloggt wird), werden diese Klammerpaare {} durch die zusätzlich übergebenen Parameter ersetzt, dabei werden die Parameter automatisch nach String gewandelt.
Code: Alles auswählen
val Integer iZiel = (Rollladenautomatik_zielwert_sued.state as Number).intValue
group_Rollladen_Sued_hight.members.forEach[i|
if((i.state as Number).intValue < iZiel) {
logInfo("autoRoll", "Fahre {} auf {} %",i.name,iZiel)
i.sendCommand(iZiel)
} else {
logInfo("autoRoll'" "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
}
]
BITTE nicht dieses schreckliche (und echt schlechte) if(log) logInfo() verwenden. Ich habe das (sehr viel) weiter oben erläutert. logInfo() ist mehr als ein Print-Befehl. Der erste Parameter ist der Loggername und sollte keinesfalls "rules" lauten. Auch ein dateiabhängiger String ist Quatsch. Stattdessen setzt man für logisch zusammenhängende Rule den identischen Loggernamen und kann so gezielt während openHAB läuft! das Logging auf verschiedenen Leveln ein- oder ausschalten. log:set WARN org.openhab.core.module.script.autoRoll schaltet z.B. die Info-Logs aus, lässt aber logWarn() und logError() durch. Mit log:set DEBUG org.openhab.core.module.script.autoRoll werden zusätzlich noch logDebug() Meldungen eingeschaltet. Das ist wesentlich besser als ein ungenaues if(log)
Die log Befehle beherrschen außerdem Substitution, das heißt, innerhalb einer Strings, der als zweiter Parameter angegeben wird (das ist die Meldung, die geloggt wird), werden diese Klammerpaare {} durch die zusätzlich übergebenen Parameter ersetzt, dabei werden die Parameter automatisch nach String gewandelt.
openHAB4.2.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.8, LXC), mit openHABian eingerichtet
-
- Beiträge: 81
- Registriert: 16. Jan 2022 13:30
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo @udo1toni,
wieder einmal DANKE für deine ausführliche Antwort.
Bei deiner verbesserten Variante bekomme ich ab dem Bereich des else mit der "logINFO" leider im OH Log mehrere Fehlermeldungen beim Laden der Rule...
Eine Idee, was hier los sein könnte?
Kann es sein, dass in der logINFO anstelle von " immer ' verwendet werden müsste?
Grüße
wieder einmal DANKE für deine ausführliche Antwort.
Bei deiner verbesserten Variante bekomme ich ab dem Bereich des else mit der "logINFO" leider im OH Log mehrere Fehlermeldungen beim Laden der Rule...
Code: Alles auswählen
2023-05-29 11:01:18.373 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'auto_verschattung_sued_down.rules' has errors, therefore ignoring it: [30,57]: missing ')' at '"null ist weiter geschlossen (null %) als er geschlossen werden sollte und wird daher ignoriert"'
[30,149]: mismatched input ',' expecting '}'
[30,156]: mismatched input ',' expecting ']'
[30,164]: extraneous input ')' expecting '}'
[32,33]: mismatched input ']' expecting '}'
[48,9]: mismatched input '}' expecting 'end'
2023-05-29 11:03:03.529 [INFO ] [el.core.internal.ModelRepositoryImpl] - Load
Kann es sein, dass in der logINFO anstelle von " immer ' verwendet werden müsste?
Grüße
OpenHAB 4.3.0
in einem Docker-Container
auf einer Synology DS1515+
in einem Docker-Container
auf einer Synology DS1515+
- udo1toni
- Beiträge: 14829
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Ja, da hat sich ein ' eingeschlichen.
das muss weg. Außerdem fehlt da noch ein Komma...
Code: Alles auswählen
logInfo("autoRoll'" "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
^ ^
Code: Alles auswählen
logInfo("autoRoll", "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
^ ^
openHAB4.2.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.8, LXC), mit openHABian eingerichtet
-
- Beiträge: 81
- Registriert: 16. Jan 2022 13:30
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Tadaaa
Vielen Dank - jetzt funktioniert die automatische Verschattung einwandfrei
Schöne Grüße
Vielen Dank - jetzt funktioniert die automatische Verschattung einwandfrei
Schöne Grüße
OpenHAB 4.3.0
in einem Docker-Container
auf einer Synology DS1515+
in einem Docker-Container
auf einer Synology DS1515+
-
- Beiträge: 34
- Registriert: 24. Feb 2018 09:11
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo Cyrelian,
könntest Du evtl. kurz einmal posten, wie Du das genau umgesetzt hast von der Programmierung her? Ich bin mit der Verwendung der Bewölkung von OWM auch nicht mehr zufrieden und würde gern auf den von Dir beschriebenen Ansatz schwenken.
Vielen Dank für die Unterstützung.
-
- Beiträge: 27
- Registriert: 16. Apr 2020 19:40
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo zusammen,
ich habe die Rule 1:1 (mit kleinen Anpassungen der Items) aus Post 1 kopiert und bekomme folgende Fehlermeldung:
Hier meine Rule:
Ich verwende Openhab 3.4.4 und komme einfach nicht drauf, woran es liegt.
Danke vorab für Eure Hilfe.
Viele Grüße
DJFlaxi
ich habe die Rule 1:1 (mit kleinen Anpassungen der Items) aus Post 1 kopiert und bekomme folgende Fehlermeldung:
Code: Alles auswählen
2023-06-11 14:32:07.571 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West ab) - Regel wurde gestartet
2023-06-11 14:32:07.572 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West hoch) - Regel wurde gestartet
2023-06-11 14:32:07.576 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Rollo-Sonnenstand-1' failed: For input string: "204.0" in Rollo-Sonnenstand
2023-06-11 14:32:07.579 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West hoch) - Beende, da Automatik generell nicht aktiv
Code: Alles auswählen
var boolean log = true
rule "Rollos West abfahren"
when Item Azimuth changed
then
val String logPrefix = 'Rolloautomatik (Rollo West ab) - '
if (log) logInfo('rules', logPrefix + 'Regel wurde gestartet')
var String timeLast = 'xxxx-xx-xx'
if (Rolloautomatik_start_last.state == NULL) {
if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
} else {
timeLast = Rolloautomatik_start_last.state.toString().substring(0,10)
}
var String timeNow = now.toString().substring(0,10)
if (Rolloautomatik.state == ON) {
if (timeNow != timeLast) {
if (Azimuth.state > Integer::parseInt(Rolloautomatik_azimuth_start.state.toString())) {
if (LocalWeatherAndForecastCurrentTemperature.state > Integer::parseInt(Rolloautomatik_temp_min.state.toString())) {
if (LocalWeatherAndForecastCurrentCloudiness.state <= Integer::parseInt(Rolloautomatik_wolken_max.state.toString())) { if (Sonnenstand.state > Integer::parseInt(Rolloautomatik_elevation_ende.state.toString())) {
// Rollos runterfahren
if (log) logInfo('rules', logPrefix + 'Rollos werden abgefahren')
gruppeRolladen_West.members.forEach[i|
if (i.state <= Integer::parseInt(Rolloautomatik_zielwert.state.toString())) {
if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf ' + Rolloautomatik_zielwert.state.toString() + '%: ' + i.name)
i.sendCommand(Integer::parseInt(Rolloautomatik_zielwert.state.toString()))
} else {
if (log) logInfo('rules', logPrefix + 'Rolladen ist bereits weiter geschlossen (' + i.state.toString() + '%) als er geschlossen werden sollte und wird daher ignoriert')
}
]
// Letzte Ausführung mit entsprechendem Zeitstempel belegen
sendBroadcastNotification("Verschattung Westseite aktiv") //Pushnachricht
Rolloautomatik_start_last.postUpdate(now.toString())
} else {
if (log) logInfo('rules', logPrefix + 'Elevation für wieder abfahren (' + Rolloautomatik_elevation_ende.state.toString() + ') ist groesser als aktuelle (' + Sonnenstand.state.toString() + ')')
}
} else {
if (log) logInfo('rules', logPrefix + 'Mindestbewoelkung (' + Rolloautomatik_wolken_max.state.toString() + ') wurde unterschritten (' + LocalWeatherAndForecastCurrentCloudiness.state.toString() + ')')
}
} else {
if (log) logInfo('rules', logPrefix + 'Mindest-Temperatur (' + Rolloautomatik_temp_min.state.toString() + ') wurde nicht erreicht durch aktuelle Temperatur (' + LocalWeatherAndForecastCurrentTemperature.state.toString() + ')')
}
} else {
if (log) logInfo('rules', logPrefix + 'Azimuth (' + Azimuth.state.toString() + ') hat noch nicht Schwellwert (rolloautomatik_azimuth_start.state.toString()) erreicht')
}
} else {
if (log) logInfo('rules', logPrefix + 'Automatik heute bereits einmal gelaufen, wird daher ignoriert')
}
} else {
if (log) logInfo('rules', logPrefix + 'Beende, da Automatik generell nicht aktiv')
}
end
rule "Rollo West wieder öffnen"
when Item Sonnenstand changed
then
val String logPrefix = 'Rolloautomatik (Rollo West hoch) - '
if (log) logInfo('rules', logPrefix + 'Regel wurde gestartet')
var String timeLastEnde = 'xxxx-xx-xx'
if (Rolloautomatik_ende_last.state == NULL) {
if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
} else {
timeLastEnde = Rolloautomatik_ende_last.state.toString().substring(0,10)
}
var String timeLastStart = 'yyyy-yy-yy'
if (Rolloautomatik_start_last.state == NULL) {
if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
} else {
timeLastStart = Rolloautomatik_start_last.state.toString().substring(0,10)
}
var String timeNow = now.toString().substring(0,10)
if (Rolloautomatik_oeffnen.state == ON) {
if (Sonnenstand.state <= Integer::parseInt(Rolloautomatik_elevation_ende.state.toString())) {
if (timeLastStart == timeNow) {
if (timeLastEnde != timeNow) {
// Rollos wieder hoch
if (log) logInfo('rules', logPrefix + 'Rollos werden hinaufgefahren')
gruppeRolladen_West.members.forEach[i|
if((Rolloautomatik_zielwert.state as Number).intValue <= (i.state as Number).intValue +5 && (Rolloautomatik_zielwert.state as Number).intValue >= (i.state as Number).intValue -5) {
if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf 0%: ' + i.name)
i.sendCommand(0)
} else {
if (log) logInfo('rules', logPrefix + 'Fahre Rolladen nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde: ' + i.name)
}
]
// Letzte Ausführung mit entsprechendem Zeitstempel belegen
sendBroadcastNotification("Verschattung Westseite beendet") //Pushnachricht
Rolloautomatik_ende_last.postUpdate(now.toString())
} else {
if (log) logInfo('rules', logPrefix + 'Beende, da heute bereits ein automatisches Wiederhochfahren stattfand')
}
} else {
if (log) logInfo('rules', logPrefix + 'Beende, da heute noch keine Ausführung stattfand. Demzufolge kann auch kein automatisches Öffnen gewollt sein')
}
} else {
if (log) logInfo('rules', logPrefix + 'Beende, da Elevation (' + Sonnenstand.state.toString() + ') nicht kleiner der eingestellten Elevation (' + Rolloautomatik_elevation_ende.state.toString()+ ') war')
}
} else {
if (log) logInfo('rules', logPrefix + 'Beende, da Automatik generell nicht aktiv')
}
end
Danke vorab für Eure Hilfe.
Viele Grüße
DJFlaxi
- udo1toni
- Beiträge: 14829
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Die Rules sind in dieser Form aus verschiedenen Gründen ned so dolle
Formal: logInfo() erzeugt Zeilen im zugehörigen log File (default ist das openhab.log). ABER: Man kann dieses Logging abschalten, und zwar über die Karaf Konsole im laufenden Betrieb. Das geht getrennt für jeden definierten Logger. Der Logger wird mit durch den ersten String definiert, in den Rules also "rules", was halt etwas sehr allgemein ist. Besser wäre z.B. "autoshutter", der entsprechende Logger hieße dann org.openhab.core.model.script.autoshutter (der Teil vor dem letzten Punkt ist für alle Logs aus Rules heraus identisch).
Mittelswerden also alle logInfo()-Zeilen spezifisch für diese beiden Rules unterdrückt. Deshalb scheint ein Konstrukt if(log) logInfo() nicht sehr elegant - zumal es mit einem Neustart der Rule Engine verbunden ist - die rules-Datei muss neu eingelesen werden...
Dann die Schachtelung der verschiedenen Bedingungen... es wäre sinnvoller, die Bedingungen in der Form abzuarbeiten, dass, wenn eine Bedingung für das Fahren nicht erfüllt ist, die Meldung geloggt wird und anschließend die Rule direkt beendet wird (dafür gibt es den Befehl return;)
Das Konstrukt, sich über einen Datumsstempel zu merken, ob die Rule am aktuellen Tag bereits ausgeführt wurde, ist auch... mäßig elegant. Einfacher, und genauso wirkungsvoll ist es, sich in einer globalen Variablen zu merken, wenn die Fahrt stattgefunden hat (wahlweise könnte man das auch über Items lösen, die können persistiert werden). Man benötigt lediglich eine Mini Rule, welche um 0 Uhr die Merker zurücksetzt - und falls man schon so eine Mitternachtsrule hat, kann man den Reset auch mit dort rein packen.
Beide Rules werden durch unterschiedliche Ereignisse des selben Bindings getriggert, beide Ereignisse treten immer (!) zeitgleich auf. Es werden also immer (!) beide Rules gestartet, unmittelbar. Es gibt keinen Grund, warum man immer zwei Rules gleichzeitig laufen lässt - eine reicht (allerdings hat das Konsequenzen für die Abbruchbedingungen...).
Es ist recht wichtig, die Status von Items immer auf einen sinnvollen Inhalt zu prüfen. Die beiden Items Azimuth und Sonnenstand enthalten zwei Winkel. in allen aktuellen openHAB Versionen wird also nach der Zahl ein ° stehen (und das ist für openHAB ein wichtiger Unterschied). Man muss das erst los werden, damit Vergleiche mit anderen Zahlen funktionieren. Ähnliches gilt auch für Temperatur (°C) und Bewölkung (%).
Ausnahme: z.B. ein Rollershutter Item liefert immer eine Zahl (genauso ein Dimmer Item) - eigentlich sollten die auch eine Prozentwert liefern, sind aber keine UoM Items (UoM -> Units of Measurement, die Einheit wird mit übergeben und auch berücksichtigt, z.B. 0°C == 32°F - das geht tatsächlich!)
Ich gehe anhand der Fehlermeldung davon aus, dass hier der eigentliche Fehler liegt (Wert wird nicht korrekt gewandelt) Könnte auch damit zusammenhängen, dass hier fälschlich ein intValue genutzt wird, die Winkel Azimuth und Sonnenstand (eigentlich Elevation) sind aber vom Typ Float.
Hier mal eine aktuell überarbeitete Variante unter Berücksichtigung aller obigen Punkte.
Zu beachten wäre noch, dass es diverse Grenzwerte gibt, die korrekt gesetzt wein müssen. Man könnte default Werte direkt in der Rule einpflegen (bei der Konstantendefinition hinter dem else des ternären Operators)
Ich habe in diesem Thread genau die angesprochenen Probleme schon mehrfach erläutert
Bei so langen Threads ist es oft keine gute Idee, den Inhalt des ersten Post zu nutzen (ja, das wird in anderen Foren gerne anders gehandhabt, da werden solche Posts immer mal wieder auf den neuesten Stand gebracht - hier aber eher nicht)
Formal: logInfo() erzeugt Zeilen im zugehörigen log File (default ist das openhab.log). ABER: Man kann dieses Logging abschalten, und zwar über die Karaf Konsole im laufenden Betrieb. Das geht getrennt für jeden definierten Logger. Der Logger wird mit durch den ersten String definiert, in den Rules also "rules", was halt etwas sehr allgemein ist. Besser wäre z.B. "autoshutter", der entsprechende Logger hieße dann org.openhab.core.model.script.autoshutter (der Teil vor dem letzten Punkt ist für alle Logs aus Rules heraus identisch).
Mittels
Code: Alles auswählen
log:set WARN org.openhab.core.model.script.autoshutter
Dann die Schachtelung der verschiedenen Bedingungen... es wäre sinnvoller, die Bedingungen in der Form abzuarbeiten, dass, wenn eine Bedingung für das Fahren nicht erfüllt ist, die Meldung geloggt wird und anschließend die Rule direkt beendet wird (dafür gibt es den Befehl return;)
Das Konstrukt, sich über einen Datumsstempel zu merken, ob die Rule am aktuellen Tag bereits ausgeführt wurde, ist auch... mäßig elegant. Einfacher, und genauso wirkungsvoll ist es, sich in einer globalen Variablen zu merken, wenn die Fahrt stattgefunden hat (wahlweise könnte man das auch über Items lösen, die können persistiert werden). Man benötigt lediglich eine Mini Rule, welche um 0 Uhr die Merker zurücksetzt - und falls man schon so eine Mitternachtsrule hat, kann man den Reset auch mit dort rein packen.
Beide Rules werden durch unterschiedliche Ereignisse des selben Bindings getriggert, beide Ereignisse treten immer (!) zeitgleich auf. Es werden also immer (!) beide Rules gestartet, unmittelbar. Es gibt keinen Grund, warum man immer zwei Rules gleichzeitig laufen lässt - eine reicht (allerdings hat das Konsequenzen für die Abbruchbedingungen...).
Es ist recht wichtig, die Status von Items immer auf einen sinnvollen Inhalt zu prüfen. Die beiden Items Azimuth und Sonnenstand enthalten zwei Winkel. in allen aktuellen openHAB Versionen wird also nach der Zahl ein ° stehen (und das ist für openHAB ein wichtiger Unterschied). Man muss das erst los werden, damit Vergleiche mit anderen Zahlen funktionieren. Ähnliches gilt auch für Temperatur (°C) und Bewölkung (%).
Ausnahme: z.B. ein Rollershutter Item liefert immer eine Zahl (genauso ein Dimmer Item) - eigentlich sollten die auch eine Prozentwert liefern, sind aber keine UoM Items (UoM -> Units of Measurement, die Einheit wird mit übergeben und auch berücksichtigt, z.B. 0°C == 32°F - das geht tatsächlich!)
Ich gehe anhand der Fehlermeldung davon aus, dass hier der eigentliche Fehler liegt (Wert wird nicht korrekt gewandelt) Könnte auch damit zusammenhängen, dass hier fälschlich ein intValue genutzt wird, die Winkel Azimuth und Sonnenstand (eigentlich Elevation) sind aber vom Typ Float.
Hier mal eine aktuell überarbeitete Variante unter Berücksichtigung aller obigen Punkte.
Zu beachten wäre noch, dass es diverse Grenzwerte gibt, die korrekt gesetzt wein müssen. Man könnte default Werte direkt in der Rule einpflegen (bei der Konstantendefinition hinter dem else des ternären Operators)
Code: Alles auswählen
// Globale Variablen müssen vor der ersten Rule definiert werden!
var Boolean bAutoZu = false
var Boolean bAutoAuf = false
rule "Rollos West abfahren"
when Item Azimuth changed
then
logInfo('autoshutter', 'Rolloautomatik (West) - Regel wurde gestartet')
if(bAutoAuf && bAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - Stoppe die Rule frühzeitig, da bereits beide Bewegungen stattfanden.')
return;
}
// lokale Variablen definieren
var Boolean bNoAutoZu = false
var Boolean bNoAutoAuf = false
// lokale Konstanten definieren
val fAzimuthIs = if(Rolloautomatik_azimuth_start.state instanceof Number) (Rolloautomatik_azimuth_start.state as Number).floatValue else 0.0
val fElevationIs = if(Sonnenstand.state instanceof Number) (Sonnenstand.state as Number).floatValue else 0.0
val fTempIs = if(LocalWeatherAndForecastCurrentTemperature.state instanceof Number) (LocalWeatherAndForecastCurrentTemperature.state as Number).floatValue else 0.0
val iCloudIs = if(LocalWeatherAndForecastCurrentCloudiness.state instanceof Number) (LocalWeatherAndForecastCurrentCloudiness.state as Number).intValue else 100
val fAzimuthMin = if(Azimuth.state instanceof Number) (Azimuth.state as Number).floatValue else 270.0
val fElevationMin = if(Rolloautomatik_elevation_ende.state instanceof Number) (Rolloautomatik_elevation_ende.state as Number).floatValue else 90.0
val fTempMin = if(Rolloautomatik_temp_min.state instanceof Number) (Rolloautomatik_temp_min.state as Number) else 23.0
val iCloudMax = if(Rolloautomatik_wolken_max.state instanceof Number) (Rolloautomatik_wolken_max.state as Number).intValue else 0
val iZiel = if(Rolloautomatik_zielwert.state instanceof Number) (Rolloautomatik_zielwert.state as Number).intValue else 0
// Prüfen der Bedingungen für ab
if(Rolloautomatik.state != ON) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, da Automatik generell nicht aktiv')
bNoAutoZu = true
}
if(bAutoZu && !bNoAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, da bereits ausgeführt')
bNoAutoZu = true
}
if(fAzimuthMin > fAzimuthIs && !bNoAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Azimuth ({}) hat noch nicht Schwellwert ({}) erreicht', fAzimuthIs, fAzimuthMin)
bNoAutoZu = true
}
if(fTempIs <= fTempMin && !bNoAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Mindest-Temperatur ({}°C) wurde nicht erreicht; aktuelle Temperatur: {}°C',fTempMin, fTempIs)
bNoAutoZu = true
}
if(iCloudIs > iCloudMax && !bNoAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Maximalbewölkung ({}%) wurde überschritten ({}%)', iCloudMax, iCloudIs)
bNoAutoZu = true
}
if(fElevationIs >= fElevationMin && !bNoAutoZu) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Elevation für abfahren ({}°) ist kleiner als aktuelle ({}°)', fElevationMin, fElevationIs)
bNoAutoZu = true
}
if(!bNoAutoZu) { // Rollos runterfahren
logInfo('autoshutter', 'Rolloautomatik (West ab) - Rollos werden abgefahren')
gruppeRolladen_West.members.forEach[i|
if((i.state as Number) <= iZiel) {
logInfo('autoshutter', 'Rolloautomatik (West ab) - Fahre Rollladen auf {}%: {}', Rolloautomatik_zielwert.state, i.name)
i.sendCommand(iZiel)
} else
logInfo('autoshutter', 'Rolloautomatik (West ab) - Rollladen ist bereits weiter geschlossen ({}%) als er geschlossen werden sollte und wird daher ignoriert', i.state)
]
sendBroadcastNotification("Verschattung Westseite aktiv") //Pushnachricht
bAutoZu = true
return;
}
// prüfen der Bedingungen für hoch
if(Rolloautomatik_oeffnen.state != ON) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da Automatik generell nicht aktiv')
bNoAutoAuf = true
}
if(fElevationIs > fElevationMin && !bNoAutoAuf) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da Elevation ({}°) nicht kleiner als eingestellte Elevation ({}°) war',fElevationIs,fElevationMin)
bNoAutoAuf = true
}
if(!bAutoZu && !bNoAutoAuf) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da heute noch kein Abwärts stattfand. Demzufolge kann auch kein automatisches Öffnen gewollt sein')
bNoAutoAuf = true
}
if(bAutoAuf && !bNoAutoAuf) {
logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da heute bereits ein automatisches Wiederhochfahren stattfand')
bNoAutoAuf = true
}
if(!bNoAutoAuf) { // Rollos wieder hoch
logInfo('autoshutter', 'Rolloautomatik (West hoch) - Rollos werden hochgefahren')
gruppeRolladen_West.members.forEach[i|
val iPosRel = Math.abs((i.state as Number).intValue - iZiel) // Abweichung des aktuellen Ladens von Zielwert
if(iPosRel <= 5) {
logInfo('autoshutter', 'Rolloautomatik (West hoch) - Fahre Rollladen {} auf 0%', i.name)
i.sendCommand(0)
} else
logInfo('autoshutter', 'Rolloautomatik (West hoch) - Fahre Rollladen {} nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde', i.name)
]
sendBroadcastNotification("Verschattung Westseite beendet") //Pushnachricht
bAutoAuf = true
}
end
rule "Reset globale Variablen"
when
Time cron "1 0 0 * * ?"
then
bAutoAuf = false
bAutoZu = false
end
Bei so langen Threads ist es oft keine gute Idee, den Inhalt des ersten Post zu nutzen (ja, das wird in anderen Foren gerne anders gehandhabt, da werden solche Posts immer mal wieder auf den neuesten Stand gebracht - hier aber eher nicht)
openHAB4.2.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.8, LXC), mit openHABian eingerichtet
-
- Beiträge: 7
- Registriert: 9. Mär 2021 01:25
Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen
Hallo zusammen,
ich habe mit großem Interesse das Projekt verfolgt und finde es echt klasse, was ihr hier auf die Beine gestellt habt!
Ich bin nun auch endlich dazu gekommen, die Rule bei mir zu implementieren und habe versucht aus den ganzen Beiträgen hier eine eigene Regel zu erstellen. Leider habe ich nur rudimentäre Kenntnisse im Programmieren und bin deshalb auf eure Hilfe angewiesen.
Im großen und ganzen funktioniert die Rule nun. Ich habe nun allerdings ein Problem bei Zeile 106 bis 114. Hier möchte ich die Gruppe variabel zuordnen, wie Udo das am 15.7.2020 vorgeschlagen hat.
Ich bekomme nun wie cupra6 3 Beiträge weiter, ebenfalls Fehler angezeigt: Auch im Log bekomme ich einen Fehler: Auch "allMembers" anstatt "members" funktionier leider nicht.
Wenn ich jedoch, wie von Udo vorgeschlagen die Gruppe der einzelnen Gruppen nehme, fahren immer alle Rollos.
Habt ihr vielleicht noch eine Idee, an was das liegt und wie ich das lösen könnte?
RULES-Datei:
Hinweis: das wieder auffahren geht aktuell nur für Osten, die anderen Himmelsrichtungen muss ich noch machen
ich habe mit großem Interesse das Projekt verfolgt und finde es echt klasse, was ihr hier auf die Beine gestellt habt!
Ich bin nun auch endlich dazu gekommen, die Rule bei mir zu implementieren und habe versucht aus den ganzen Beiträgen hier eine eigene Regel zu erstellen. Leider habe ich nur rudimentäre Kenntnisse im Programmieren und bin deshalb auf eure Hilfe angewiesen.
Im großen und ganzen funktioniert die Rule nun. Ich habe nun allerdings ein Problem bei Zeile 106 bis 114. Hier möchte ich die Gruppe variabel zuordnen, wie Udo das am 15.7.2020 vorgeschlagen hat.
Ich bekomme nun wie cupra6 3 Beiträge weiter, ebenfalls Fehler angezeigt: Auch im Log bekomme ich einen Fehler: Auch "allMembers" anstatt "members" funktionier leider nicht.
Wenn ich jedoch, wie von Udo vorgeschlagen die Gruppe der einzelnen Gruppen nehme, fahren immer alle Rollos.
Habt ihr vielleicht noch eine Idee, an was das liegt und wie ich das lösen könnte?
RULES-Datei:
Code: Alles auswählen
// Globale Variablen müssen vor der ersten Rule definiert werden!
import java.util.Map
var Number closingAzimuth_east = 300
var Number closingAzimuth_south = 120
var Number closingAzimuth_west = 210
var boolean isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false
val Map<String, Number> targetHights = newHashMap (
"R_OL3_01" -> 75,
"R_OL4_01" -> 75,
"R_OR3_01" -> 75,
"R_OL5_01" -> 75,
"R_OR2_01" -> 75,
"R_OR3_02" -> 75,
"R_OR4_01" -> 75,
"R_OR5_01" -> 75
)
var String strGroup = ""
rule "Rollos abfahren"
when Item LokaleSonnendaten_Azimut changed
then
logInfo('shading', 'Rolloautomatik ab - Regel wurde gestartet')
// lokale Variablen definieren
// lokale Konstanten definieren
val fAzimuthIs = if(LokaleSonnendaten_Azimut.state instanceof Number) (LokaleSonnendaten_Azimut.state as Number).floatValue else 0.0
val fElevationIs = if(LokaleSonnendaten_Hohenwinkel.state instanceof Number) (LokaleSonnendaten_Hohenwinkel.state as Number).floatValue else 0.0
val fTempIs = if(Wetterinformationen_Aussentemperatur.state instanceof Number) (Wetterinformationen_Aussentemperatur.state as Number).floatValue else 0.0
val iCloudIs = if(Wetterinformationen_Bewolkung.state instanceof Number) (Wetterinformationen_Bewolkung.state as Number).intValue else 100
val fAzimuthMin = if(v_rollo_azimuth_start.state instanceof Number) (v_rollo_azimuth_start.state as Number).floatValue else 270.0
val fElevationMin = 20//if(Rolloautomatik_elevation_ende.state instanceof Number) (Rolloautomatik_elevation_ende.state as Number).floatValue else 90.0
val fTempMin = if(v_rollo_temp_min.state instanceof Number) (v_rollo_temp_min.state as Number) else 23.0
val iCloudMax = if(v_rollo_wolken_max.state instanceof Number) (v_rollo_wolken_max.state as Number).intValue else 0
// Prüfen der Bedingungen für ab
if(v_rollo.state != ON) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, da Automatik generell nicht aktiv')
return;
}
if(sw_DayNight.state != ON) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, da Nacht')
return;
}
if(fAzimuthMin > fAzimuthIs) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, Azimuth ({}) hat noch nicht Schwellwert ({}) erreicht', fAzimuthIs, fAzimuthMin)
return;
}
if (v_rollo_start_letzter.state == NULL) {
logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (gestern)")
v_rollo_start_letzter.postUpdate(new DateTimeType(now.minusDays(1)))
}
if(fTempIs <= fTempMin) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, Mindest-Temperatur ({}°C) wurde nicht erreicht; aktuelle Temperatur: {}°C',fTempMin, fTempIs)
return;
}
if(iCloudIs > iCloudMax) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, Maximalbewölkung ({}%) wurde überschritten ({}%)', iCloudMax, iCloudIs)
return;
}
if(fElevationIs >= fElevationMin) {
logInfo('shading', 'Rolloautomatik - kein Abwärts, Elevation für abfahren ({}°) ist kleiner als aktuelle ({}°)', fElevationMin, fElevationIs)
return;
}
val nAz = (LokaleSonnendaten_Azimut.state as Number).floatValue
strGroup = ""
//Azimuth ist größer als 210° (West)
switch(true) { // erste zutreffende Bedingung wird exclusiv ausgeführt (alle nachfolgenden nicht, auch wenn sie zutreffen)
case nAz > closingAzimuth_west : {
if(!isActiveWest) {
logInfo ("shading", "Verschattung für Rollläden WEST")
strGroup = "g_R_OG_West"
isActiveWest = true
}
}
case nAz > closingAzimuth_south : {// hinreichend, da 1. Bedingung nicht zutrifft
if(!isActiveSouth) {
logInfo ("shading", "Verschattung für Rollläden SÜD")
strGroup = "g_R_OG_Sued"
isActiveSouth = true
}
}
case nAz > closingAzimuth_east : {// hinreichend, da 2. Bedingung nicht zutrifft
if(!isActiveEast){
logInfo ("shading", "Verschattung für Rollläden OST")
strGroup = "g_R_OG_Ost"
isActiveEast = true
}
}
}
if(strGroup == "") { // strGroup ist leer bzw. nicht definiert
logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
return;
}
val myGroup = g_R_OG_Group.members.filter[i|i.name == strGroup].head
myGroup.members.forEach[ blind |
if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {
logInfo ("shading", "Fahre Rollladen ({}) auf ({}) %",blind.name,targetHights.get(blind.name.toString()))
blind.sendCommand(targetHights.get(blind.name.toString()).intValue)
//sendTelegram("bot1","Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %")
} else {
logInfo ("shading", "Rollladen ({}) ist bereits weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",blind.name,blind.state)
}
]
v_rollo_start_letzter.postUpdate(new DateTimeType(now.toString()))
end
rule "Rollos auffahren"
when
Item LokaleSonnendaten_Azimut changed
then
logInfo('shading', 'Rolloautomatik hoch - Regel wurde gestartet')
// prüfen der Bedingungen für hoch
if (v_rollo_ende_letzter.state === NULL) {
logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
v_rollo_ende_letzter.postUpdate(new DateTimeType(now.minusDays(1)))
}
if(v_rollo.state != ON) {
logInfo('shading', 'Rolloautomatik - kein Aufwärts, da Automatik generell nicht aktiv')
return;
}
if(sw_DayNight.state != ON) {
logInfo('shading', 'Rolloautomatik - kein Aufwärts, da Nacht')
return;
}
if (!isActiveWest && !isActiveEast && !isActiveSouth) {
logInfo("shading", "Beende, da heute noch keine automatische Verschattung stattfand")
return;
}
if ((LokaleSonnendaten_Azimut.state as Number).floatValue > (v_rollo_azimuth_ende_ost.state as Number).floatValue && (LokaleSonnendaten_Azimut.state as Number).floatValue < (v_rollo_azimuth_ende_ost.state as Number).floatValue +5) {
logInfo("shading", "Verschattung für Rollläden OST beenden")
g_R_OG_Ost.members.forEach[ blind |
if ((blind.state as Number) -5 < targetHights.get(blind.name.toString()).intValue && (blind.state as Number) +5 > targetHights.get(blind.name.toString()).intValue) {
logInfo ("shading", "Fahre Rollladen ({}) auf 0%",blind.name)
blind.sendCommand(0)
//sendTelegram("bot1","Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %")
} else {
logInfo ("shading", "Fahre Rolladen {} nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde.",blind.name)
}
]
//shadingEnd.apply(g_R_OG_Ost)
return;
}
end
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.