Automatic Shading with Astro, OpenWeather and MqTT (for Shelly 2.5)

Hello OpenHABers,

here i want to share my Project to have a automatic shading with
OpenHab, Astro, OpenWeather and MqTT.

First of all: The author of the Rule is Florian Schießl. I would also like to thank him for allowing me to publish my project here. His origin project can be found here:
https://www.forwardme.de/2018/03/12/elektrischen-rolladen-abhaengig-von-sonnenstand-und-wetter-steuern-lassen-mit-openhab2/

What is needed?
Software:
OpenHab 2.4
MQTT
Weather binding installed
Astro Binding installed
OpenHab Cloud Connector

Hardware:
RaspBerry 3
Shelly 2.5 shutter actuator

What is the whole thing doing?
Depending on the position of the sun, temperature and clouds, the rule can shade a room via an electric shutter.
In addition, a push message is sent at the beginning and end of the shading.

How it behaves with sun direction and sun altitude, you will find here:
https://www.sunearthtools.com

The whole thing is of course individually configurable.
And works like this:

It should be a circuit depending on sun angle and altitude.
Of course, this should take effect but only from a certain outside temperature, because in winter we are then rather happy about the light and if rain or even clouds are in the sky, a shading is not necessary. If the shutter is already closed when it is to be closed, nothing should happen.
Likewise, nothing should happen, the shutter in trying to open it has now changed state.

Here first the corresponding item file: (Exemplary for the west side of our house)

Group gruppeRolladen_West
// Konfiguration Rollo-Automatik West
Switch Rolloautomatik "Rollo-Automatik aus/an"
Switch Rolloautomatik_oeffnen "Rolladen öffnen aus/an"
Number Rolloautomatik_zielwert "Schließen auf [%d Prozent]"
Number Rolloautomatik_temp_min "Temperatur größer [%d °C]"
Number Rolloautomatik_wolken_max "Bewölkung weniger als [%d Prozent]"
Number Rolloautomatik_azimuth_start "Sonnenrichtung größer gleich [%d °]"
Number Rolloautomatik_elevation_ende "Sonnenhöhe kleiner gleich [%d °]"
DateTime Rolloautomatik_start_last "Letzte Ausführung (Rollo ab)"
DateTime Rolloautomatik_ende_last "Letzte Ausführung (Rollo hoch)"

Here is the rule:

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 (AussenTemp.state > Integer::parseInt(Rolloautomatik_temp_min.state.toString())) {
                    if (LocalWeatherAndForecast_Current_Cloudiness.state  <= Integer::parseInt(Rolloautomatik_wolken_max.state.toString())) { if (Elevation.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 (' + Elevation.state.toString() + ')')
                        }
                    } else {
                        if (log) logInfo('rules', logPrefix + 'Mindestbewoelkung (' + Rolloautomatik_wolken_max.state.toString() + ') wurde unterschritten (' + LocalWeatherAndForecast_Current_Cloudiness.state.toString() + ')')
                    }
                } else {
                    if (log) logInfo('rules', logPrefix + 'Mindest-Temperatur (' + Rolloautomatik_temp_min.state.toString() + ') wurde nicht erreicht durch aktuelle Temperatur (' + AussenTemp.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 Elevation 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 (Elevation.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 (' + Elevation.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

The rule asks whether the automatic system has generally been running, possibly already running, whether the temperature, cloudiness and current status of the blinds are suitable and if so they will be driven down.

Important: All blinds must be assigned to group groupRolladen_West.

If a shutter is in a different state than it should have been when it was shut down at the calculated time of going back up, it will not automatically open.

And here the relevant part from the sitemap:

Text label="Konfiguration Verschattung West" icon="rollershutter" {
        Frame label="Aktivieren der Automatik" {
        Switch item=Rolloautomatik
        Setpoint item=Rolloautomatik_zielwert minValue=0 maxValue=100 step=1
        }
        Frame label="Rollo ab, wenn..." {
        Setpoint item=Rolloautomatik_temp_min minValue=0 maxValue=35 step=1
        Text item=AussenTemp label="Temperatur Aussen [%.1f °C]" icon="temperature" valuecolor=[>27="red",>20="orange",>10="purple",>5="green",<=5="blue"]
        Setpoint item=Rolloautomatik_wolken_max minValue=0 maxValue=100 step=1
        Text item=LocalWeatherAndForecast_Current_Cloudiness icon="sun_clouds" label="Bewölkung [%.0f %%]"
        Setpoint item=Rolloautomatik_azimuth_start minValue=0 maxValue=360 step=1
        Default item=Azimuth icon="niveau" label="Azimuth"
        }
        Frame label="Rollo hoch, wenn..." {
        Switch item=Rolloautomatik_oeffnen
        Setpoint item=Rolloautomatik_elevation_ende minValue=-20 maxValue=60 step=1
        Default item=Elevation label="Elevation"

It look like this in the sitemap:

Have Fun!

13 Likes

Hi, great script.

How do you manage for the other directions (i.e. south & east)? Do you run this script for each direction?

1 Like

Hi Dominik,

yes at the moment I use it for two directions.
Two rules for each.

Nice work! Currently planning something similar, so I’ll be taking this one as a good example =)
Additionally I’ll close the shutters in case the window is open and it starts raining.

Hi,

I love the script, but I have to issue with it.

Without knowing why, it happend to me already twice, that the rules start to be active at 0:00. As they then already run at 0:00 they do not start again. What I don’t get, the Azimut at this time should be far away from excecution value.

Does someone else have the same issue?

Further I am interested, how to reset the behaviour, that the rule is blocked for further execution? As I understood, the rule runs only if timeNow is not timeLast. But, how to reset timeLast?

Any helpful guess would be appreciated.

Hi Dominik,

Maybe you can reset the timeLast with the RestApi or restart OpenHab.

Br Peter

Thanks, but restart OpenHab is not an option.
My idea would be to have a switch, which would reset the value via postUpdate command.

After analysing the logs, it is clear to me, why the rule run after midnight.

TimeNow !=TimeLast and the azimuth is still above the given value: 2019-06-20 00:00:30.491 [vent.ItemStateChangedEvent] - Azimuth changed from 337.4839890387086 ° to 337.6765460913182 °

I added if (now.isBefore((Sunset_Time.state as DateTimeType).zonedDateTime.toInstant().toEpochMilli) ||now.isAfter((Sunrise_Time.state as DateTimeType).zonedDateTime.toInstant().toEpochMilli)) which should help to execute the script only during daytime.

Maybe interesting for someone else as well.

is it possible to have an english version? i’m not sure this script works for me so i would like to have a look at logs to find where the problem is…

thanks!

ps. really interested in this, i was looking for this for a long time!

1 Like

hi ruben,

there is no english version availiable.
But if you have any problems you can post it here and probably we can help you.

BR

Peter

ok thanks for your fast answer! i’ve tried to copy/paste all files from the first post and i’m checking…
because i’m on a test environment, i thought instead using a real rollershutter i can use dimmer item like this:

Dimmer Light1 “Light 1” (gruppeRolladen_West)

then i’ve placed this dummy dimmer to sitemap so i can “see” if the rule “move” the intensity of the dimmer to the percentage selected. but it doesn’t.
do you thing because i’m using the dimmer item, the rule doesn’t work?
also, “Cloudness” the setpoint means “don’t use the rule when the cloudness is ABOVE the value?”
so if the weather cloudness is 30% and i set 40% in setpoint, it means the rule is skipped till the weather reach 40%?

hi Ruben,

regarding to your question about the function of the in you test environment i cant give you an answer
because i always run the rule on a real environment.

The “Cloudiness” setpoint means: if you set 40% und the cloudiness is 50% = no shading
But if you set 40% and the Cloudiness is 30% then you can have the shading

thanks! other question:

these 2 log entries, what they mean?

2019-08-30 09:20:24.288 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West hoch) - Beende, da Elevation (26.628859751736055 °) nicht kleiner der eingestellten Elevation (1) war
2019-08-30 09:20:24.289 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West ab) - Azimuth (104.93162810920226 °) hat noch nicht Schwellwert (rolloautomatik_azimuth_start.state.toString()) erreicht

they means the rule has been executed correctly or not? i lways get these errors…also if i increase or decrease elevation and azimuth…

hi,

i guess the rule is working.
the “Elevation” thing is for OPEN the shutters.
the “Azimuth” thing is for CLOSE the shutters.
So the rule wont not OPEN before it have CLOSED the shutters.

Rolloautomatik (Rollo West hoch) - Beende, da Elevation (26.628859751736055 °) nicht kleiner der eingestellten Elevation (1) war

Your setpoint for Open must be higher than 26

Rolloautomatik (Rollo West ab) - Azimuth (104.93162810920226 °) hat noch nicht Schwellwert (rolloautomatik_azimuth_start.state.toString()) erreicht

Your setpoint for CLOSE, i guess is also higher than 104

For Example:
My Setpoints for the Westside of the House:
Closing: AZ 220, Opening: EL 12

BR

thanks! so with this settings, should work in this scenario?

hi,

dont know… give a try, keep your eye in the log an report here :slight_smile:
This is actually here… a short moment after closing the shutters on the west side:

I’ve finally copied everything on “live” environment but it wont work :sweat:
Don’t understand why…maybe because the azimuth here is increasing from afternoon to evening,could be why?

hi Ruben,

the show us your log.
an please use the codefences when you paste the “code”

BR

voilà!

2019-08-31 14:49:30.933 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West hoch) - Regel wurde gestartet
2019-08-31 14:49:30.949 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West ab) - Regel wurde gestartet
2019-08-31 14:49:30.951 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West hoch) - Erstmalige Ausführung am 
System, Belegung mit Initialwert
2019-08-31 14:49:30.965 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West hoch) - Erstmalige Ausführung am 
System, Belegung mit Initialwert
2019-08-31 14:49:30.967 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West ab) - Erstmalige Ausführung am 
System, Belegung mit Initialwert
2019-08-31 14:49:31.011 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West hoch) - Beende, da Elevation 
(48.75948943723178) nicht kleiner der eingestellten 
Elevation (20) war
2019-08-31 14:49:31.032 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West ab) - Mindestbewoelkung (15) 
wurde unterschritten (59.00)

no way to make the rule work. both open and close doesn’t work :frowning:
thanks…

hi Ruben,

don´t know atm what the problem is…
The rule wont accept setpoint values like Azimuth 180.5
The Rule only accept setpoint values like Azimuth 180 the same with the Elevation Cloudiness and Temperature setpoints.
Maybe there is the problem.

1 Like