Shut down Roller based on Position of the sun

Hello everybody,
I am sitting in the home office - as many of you are at the moment. In this respect, it is time to optimize the “office environment” :man_office_worker: :houses:.

My office is full east side with window to the east; I look at a wall in the south. It is now the case that the sun is currently appearing in the window at around 4 p.m. and is permanently “dazzling” until around 6 p.m.
My goal would be a rule (based on the Astro Binding?) That “adjusts” the roller shutter in 2-3 steps when the sun is shining (openweathermap :sun_with_face: :sunglasses:) - i.e. at 16:00 to 30% and at 16:30 to 50% puts.
Does anyone have something like that in use?
Thank you and best regards
Tom

I have made a rule for shutters that react on clouds and azimuth and height of the sun.

These are the items used to check the weather, clouds sun-height and azimuth.

String CurrentCondition "[%s]"                             {channel="openweathermap:weather-and-forecast:xxxxxxx:local:current#condition" }
String HuidigWeer 
Number CurrentCloudiness "Bewolking percentage [%.0f %%]" <day_clouds> {channel="openweathermap:weather-and-forecast:xxxxxxxx:local:current#cloudiness"}
Number CurrentUvindex "UV index [%s]"  <sun_radiation>   {channel="openweathermap:uvindex:xxxxxxx:local:current#uvindex"}
Number:Angle ZonPositieHoogte "Hoogte zon [%.2f %unit%] " <incline>     {channel="astro:sun:home:position#elevation"}
Number:Angle ZonPositieAzimuth "Kompasrichting zon [%.3f %unit%]" <sun> {channel="astro:sun:home:position#azimuth"}


Using two different rollershutters.
RolTuindeurControl
RolWoonkamerControl

rule "graden van zonnestand als zon boven horizon"

when 
   Item ZonPositieAzimuth changed 
then 
      var MustClose = false;
   if ((ZonPositieHoogte.state as Number).intValue > 0){
      // CurrentUvindex is not reliable
      // Cloudiness has slow update rate
      // check the condition for clouds
      if (CurrentCondition.state=="licht bewolkt" || 
         CurrentCondition.state=="zon" ||
         CurrentCondition.state=="half bewolkt" ||
         CurrentCondition.state=="helder" ||
         CurrentCondition.state=="onbewolkt" ||
         (CurrentCloudiness.state as Number) < 80){
         MustClose = true
      }
      if (MustClose){
     
         if ((ZonPositieAzimuth.state as Number).intValue > 228 &&
            (ZonPositieAzimuth.state as Number).intValue < 250 &&
            (ZonPositieHoogte.state as Number).intValue < 14 &&
            (ZonPositieHoogte.state as Number).intValue > 4.9 &&
            (RolTuindeurControl.state as Number).intValue < 10 && 
            (TuindeurZon.state == 0 || TuindeurZon.state == NULL) ){
            RolTuindeurControl.sendCommand(44)
            TuindeurZon.postUpdate(1)
         }
         var NewSetting = 55
         if ((ZonPositieHoogte.state as Number).intValue < 20){
            NewSetting = 35 + 20 -(ZonPositieHoogte.state as Number).intValue
         }

         if ((ZonPositieAzimuth.state as Number).intValue > 245 && 
            (ZonPositieHoogte.state as Number).intValue < 20  &&
            (ZonPositieHoogte.state as Number).intValue > 4.9) {
                  if ((RolWoonkamerControl.state as Number).intValue != NewSetting
                  && (RolWoonkamerControl.state as Number).intValue < NewSetting ){
                     RolWoonkamerControl.sendCommand(NewSetting)
                  }
              
         }
      }
      
      val currentMin = new DateTime().getMinuteOfDay 
      val zononder = (SunsetMinute.state as Number).intValue
      if ((ZonPositieHoogte.state as Number).intValue <= 4.9 &&
         (RolWoonkamerControl.state as Number).intValue > 20 &&
         (RolWoonkamerControl.state as Number).intValue < 65 &&
         currentMin < zononder - 15 && 
         currentMin > 960){
         RolWoonkamerControl.sendCommand(UP)
      }
   }
end 

I spent some time to figure out at what height the sun in too bright in the room.
Now it is perfect. Also as soon as the sun is so low it doesn’t matter the Rollershutters go UP again.

Hi there,
I’ve created a approach with 6 different day-times (morning, forenoon, noon, afternoon, evening, night). A rule that triggers every minute gets sun elevation/azimuth from Astro-binding and sets a “global” variable called shutter_status.

Another rule triggers on shutter_status change and drives the rollershutters based on an array-index.

Example:
rule 1 calculates shutter_status = 3 (“noon”)
rule 2 sees a change in shutter_status (2->3) and drives each shutter on a predefined array-index.

I described that approach here.

Something like this would be easy to implement using…

… and…

1 Like

Hi,
many thanks for the help. Maybe a few more understanding questions (I’m unfortunately not a programmer):

  • is it correct that everything between"var Newsetting" and “val currentMin” affects the second roller shutter (RolWoonkamer) - if I only have one roller shutter can I remove this part of the coding?
  • is it right, that only the RolWoonkamer-shutter goes up again at the end? “RolTuindeurControl” keeps closed/down…?
  • TuindeurZon is not described in more detail … what’s going on here?

thanks in advance
Tom

@vooodooo1974

is it correct that everything between"var Newsetting" and “val currentMin” affects the second roller shutter (RolWoonkamer) - if I only have one roller shutter can I remove this part of the coding?

This part controls the main shutter. If the sun comes lower the more the shutter is closed. The two shutters react both different.(they are both in the livingroom)

The RolTuindeur actually works on different elevation and azimuth values. This shutter is actually only moving in early and late season.

TuindeurZon is not described in more detail … what’s going on here?

This is an item that stores that the shutter has been lowered to prevent multiple command to send down.

Number TuindeurZon "If sun in range set to 1"

It goes (very) slowly with the conding adaptation to my environment … but maybe one more question: How did you determine the official names of the weather conditions? Did you wait until the corresponding name (in your language) appeared in the log? So it’s about this part:

I stored all the different conditions in a mariaDB database and did a GROUP BY selection and found all different conditions in Dutch. bewolkt = cloudy in english

Mmh, it still doesn’t work … With my adjustments it looks like this:

rule "Büro2: Rolladen runter bei Sonne"

when 
Item LocalSun_Position_Azimuth changed 
then 
if ((LocalSun_Position_Elevation.state as Number).intValue > 0) {logInfo(Rolladen_Buero_BlindsControl, "2.Versucht: RolladenBüroXX")
  {
          var NewSetting = 55
     if ((LocalSun_Position_Elevation.state as Number).intValue < 50)
     { NewSetting = 35 + 20 -(LocalSun_Position_Elevation.state as Number).intValue }

     if ((LocalSun_Position_Azimuth.state as Number).intValue > 245 && 
        (LocalSun_Position_Elevation.state as Number).intValue < 50  && 
        (LocalSun_Position_Elevation.state as Number).intValue > 4.9)
         {
              if ((Rolladen_Buero_BlindsControl.state as Number).intValue != NewSetting
              && (Rolladen_Buero_BlindsControl.state as Number).intValue < NewSetting )
              { Rolladen_Buero_BlindsControl.sendCommand(NewSetting) }
         }
    }
}
end

I get this error:

:face_with_symbols_over_mouth: :rage: :face_with_symbols_over_mouth: :rage:

openHAB doesn’t like the above. I’m not certain, but I think Rolladen_Buero_BlindsControl has to be in quotes: "Rolladen_Buero_BlindsControl"

logInfo expects a string. https://www.openhab.org/docs/administration/logging.html#create-log-entries-in-rules

1 Like

@hafniumzinc

Rules like to be proper a simple quote makes the difference

Thank you, concrete problem solved … unfortunately the core of the rule, i.e. the roller shutter does not move at all … :sob:. let’s see …

Try to get some info why it is not moving

....
if ((LocalSun_Position_Elevation.state as Number).intValue < 50)
     { NewSetting = 35 + 20 -(LocalSun_Position_Elevation.state as Number).intValue }
logInfo("Variables sun", "NewSetting: " + NewSetting + " Azimuth: " + (LocalSun_Position_Azimuth.state as Number).intValue + " Elevation: " + (LocalSun_Position_Elevation.state as Number).intValue)
     if  .....

This will show the values that come out of the calculation and the azimuth and elevation
And I would trigger the rule by the Elevation as well, just to see

Item LocalSun_Position_Azimuth changed  or
Item LocalSun_Position_Elevation changed

Hi, and sorry for the late, late reply (… family business needs its time in Corona ages :woozy_face:).

I first simplified the original Charley rule - e.g. there is now only one roller shutter for me (Rolladen_Wohnzimmer_BlindsControl).
Up until now I have left the “clouds” outside … But my wife doesn’t find it funny that the shutters go down when it rains.
I’m sure my mistake is somehow with the variable “MustClose” or the associated call of the actual logic instead … can someone correct that?
here the rule and below the error message from the log:

rule "Rolladen Wohnzimmer runter wenn Sonne scheint"

when
   Item LocalSun_Position_Azimuth changed
then
   var MustClose = false;
if ((LocalSun_Position_Elevation.state as Number).intValue > 0){
   if (Wetterdaten_Wolken_AIT_Openweathermap.state as Number) < 80){
   MustClose = true
   }
   if (MustClose)
          var NewSetting = 55
     if ((LocalSun_Position_Elevation.state as Number).intValue < 54)
     { NewSetting =  100 - (LocalSun_Position_Elevation.state as Number).intValue }

logInfo("Variables sun", "NewSetting: " + NewSetting + " Azimuth: " + (LocalSun_Position_Azimuth.state as Number).intValue + "Elevation:" + (LocalSun_Position_Elevation.state))

     if ((LocalSun_Position_Azimuth.state as Number).intValue > 216 &&
        (LocalSun_Position_Elevation.state as Number).intValue < 60  &&
        (LocalSun_Position_Elevation.state as Number).intValue > 4.9)
         {
              if ((Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue != NewSetting
              && (Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue > NewSetting )
              { Rolladen_Wohnzimmer_BlindsControl.sendCommand(NewSetting) }
logInfo("RolladenWohnzimmer", "Status Wohnzimmer Rolladen: " + (Rolladen_Wohnzimmer_BlindsControl.state as Number))
         }
    }

end

the log says:

 2020-07-08 23:05:05.756 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'Rolladen_Wohnzimmer_Sonne-wolke.rules' has errors, therefore ignoring it: [8,69]: no viable alternative at input '80'
[12,15]: no viable alternative at input 'var'

You are missing a paren at the beginning of this line.

when
   Item LocalSun_Position_Azimuth changed
then
   var MustClose = false;
if ((LocalSun_Position_Elevation.state as Number).intValue > 0){
   if ((Wetterdaten_Wolken_AIT_Openweathermap.state as Number) < 80){
   MustClose = true
   }
.....

:skull_and_crossbones: :boom: :bomb: … it will not work!

Am I’m blind? Same error in another “if”-loop; and i can’t find a probably missing bracket:

rule "Rolladen Wohnzimmer runter wenn Sonne scheint"

when
  Item LocalSun_Position_Azimuth changed
then
   var MustClose = false;
  if ((LocalSun_Position_Elevation.state as Number).intValue > 0)
{
  if ((Wetterdaten_Wolken_AIT_Openweathermap.state as Number) < 80)
  { MustClose = true }

  if (MustClose)
     var NewSetting = 55;
     if ((LocalSun_Position_Elevation.state as Number).intValue < 54)
     { NewSetting = 100 - (LocalSun_Position_Elevation.state as Number).intValue }

 logInfo("Variables sun", "NewSetting: " + NewSetting + " Azimuth: " + (LocalSun_Position_Azimuth.state as Number).intValue + "Elevation:" + (LocalSun_Position_Elevation.state))

     if ((LocalSun_Position_Azimuth.state as Number).intValue > 216 &&
        (LocalSun_Position_Elevation.state as Number).intValue < 60  &&
        (LocalSun_Position_Elevation.state as Number).intValue > 4.9)
         {
              if ((Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue != NewSetting
              && (Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue > NewSetting )
              { Rolladen_Wohnzimmer_BlindsControl.sendCommand(NewSetting) }
logInfo("RolladenWohnzimmer", "Status Wohnzimmer Rolladen: " + (Rolladen_Wohnzimmer_BlindsControl.state as Number))
         }
}

end

and still this error:
2020-07-15 16:17:46.046 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'Rolladen_Wohnzimmer_Sonne-wolke.rules' has errors, therefore ignoring it: [13,10]: no viable alternative at input 'var'

not sure what that is meant to do, but I always use the { } curly braces with if{} so that I can read it myself.
The rules parse will let you omit them, but there are consequences to just leaving them out. It becomes a strictly one-line if()

I have added the missing curly braces. @rossko57 is right
if you use an if statement that has a single line it is OK to omit the braces. However it is always easier to read if you use then.

Here is your code I did some proper indenting (in Visual Studio use SHIFT-ALT-F to do the automatic.

rule "Rolladen Wohnzimmer runter wenn Sonne scheint"

when
  Item LocalSun_Position_Azimuth changed
then
  var MustClose = false;
  if ((LocalSun_Position_Elevation.state as Number).intValue > 0){
    if ((Wetterdaten_Wolken_AIT_Openweathermap.state as Number) < 80) { 
       MustClose = true 
    }
    if (MustClose) {
      var NewSetting = 55;
      if ((LocalSun_Position_Elevation.state as Number).intValue < 54){ 
	      NewSetting = 100 - (LocalSun_Position_Elevation.state as Number).intValue 
      }   
      logInfo("Variables sun", "NewSetting: " + NewSetting + " Azimuth: " + (LocalSun_Position_Azimuth.state as Number).intValue + "Elevation:" + (LocalSun_Position_Elevation.state))

     if ((LocalSun_Position_Azimuth.state as Number).intValue > 216 &&
         (LocalSun_Position_Elevation.state as Number).intValue < 60  &&
         (LocalSun_Position_Elevation.state as Number).intValue > 4.9) {
		    if ((Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue != NewSetting
                 && (Rolladen_Wohnzimmer_BlindsControl.state as Number).intValue > NewSetting ){

				    Rolladen_Wohnzimmer_BlindsControl.sendCommand(NewSetting) 
			}
            logInfo("RolladenWohnzimmer", "Status Wohnzimmer Rolladen: " + (Rolladen_Wohnzimmer_BlindsControl.state as Number))
     }
	} 
  }

end