How to calculate the time of a specific azimuth

Hi, I want to write a rule, that uses timers to control my roller shutters.
Now in the summer I want, that the roller shutters are closing if the sun is shining into the corresponding room.
My current rule doesn’t use fixed values and checks after every change of the azimuth if there are windows which are in the sunlight. But this creates many log entries and slows down the opehab server.

My new rule is using timers and a state machine to reduce the overhead.
But for the sun protection, I need the corresponding time of the azimuth to create a timer.

Know anyone a library to calculate the time of a specific azimuth?

Once you know it is working move your logInfos to logDebug in your rules to eliminate the logs from openhab.log. Don’t worry about events.log. It’s always going to be busy. If it’s a problem, just turn off events logging entirely.

Unless you are running on an underpowered machine like an RPi 1, running a rule once a minute is not going to slow down your openHAB unless this rule is doing stuff it shouldn’t like using Thread::sleeps.

I know if no way to calculate the time for a specific azimuth.

I have a simple rule which sets a virtual switch for every rollershutter when az positions correspond to the sun position for that window.
In the main rule, where the movement of the shutters take place, I use an if condition to only move the shutter when the switch is ON.
BTW, this was a recommendation from @rlkoshak a couple of openHAB years ago :+1:

Sorry for the offtopic

@rlkoshak
The rules have no logInfos anymore,
sorry for the wrong description of the problem,
but I get many errors on startup because the rule engine is very slow and not all items are initialized.
I have for every room one rule file, the system needs more than 30 mins to work nearly useable.
This is not the first time I have problems with it,
I moved from a pi1 to a pi3 and now it is running on my home server (AMD A4-5300 and 8GB RAM).
On the pi1 and pi3, it was unusable.

The rules don’t use sleeps or something like that.

Here a screenshot of htop after 40 mins uptime:

Here a list of threads --list from karaf

Here is one of the old rule files I’m using currently.

import java.util.Random
import java.util.Calendar

rule "Rollershutter Kueche Init"
when
	System started
then
	if(Rolladen_EG_Kueche_Hoch_Stunde_Montag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Montag.postUpdate(7);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Montag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Montag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Montag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Montag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Montag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Montag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Dienstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Dienstag.postUpdate(7);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Dienstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Dienstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Dienstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Dienstag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Dienstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Dienstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Mittwoch.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Mittwoch.postUpdate(7);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Mittwoch.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Mittwoch.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Mittwoch.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Mittwoch.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Mittwoch.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Mittwoch.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Donnerstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Donnerstag.postUpdate(7);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Donnerstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Donnerstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Donnerstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Donnerstag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Donnerstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Donnerstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Freitag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Freitag.postUpdate(7);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Freitag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Freitag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Freitag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Freitag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Freitag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Freitag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Samstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Samstag.postUpdate(9);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Samstag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Samstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Samstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Samstag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Samstag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Samstag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Hoch_Stunde_Sonntag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Stunde_Sonntag.postUpdate(9);
	}
	if(Rolladen_EG_Kueche_Hoch_Minute_Sonntag.state == NULL){
		Rolladen_EG_Kueche_Hoch_Minute_Sonntag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Runter_Stunde_Sonntag.state == NULL){
		Rolladen_EG_Kueche_Runter_Stunde_Sonntag.postUpdate(22);
	}
	if(Rolladen_EG_Kueche_Runter_Minute_Sonntag.state == NULL){
		Rolladen_EG_Kueche_Runter_Minute_Sonntag.postUpdate(0);
	}
	if(Rolladen_EG_Kueche_Nighttime_Mode.state == NULL){
		Rolladen_EG_Kueche_Nighttime_Mode.postUpdate("GLOBAL");
	}
	if(Rolladen_EG_Kueche_Sonnenschutz_Modus.state == NULL){
		Rolladen_EG_Kueche_Sonnenschutz_Modus.postUpdate(OFF);
	}
	if(Rolladen_EG_Kueche_Sonnenschutz_Stand.state == NULL){
		Rolladen_EG_Kueche_Sonnenschutz_Stand.postUpdate(40);
	}
	if(Rolladen_EG_Kueche_Sonnenschutz_WinkelLinks.state == NULL){
		Rolladen_EG_Kueche_Sonnenschutz_WinkelLinks.postUpdate(210);
	}
	if(Rolladen_EG_Kueche_Sonnenschutz_WinkelRechts.state == NULL){
		Rolladen_EG_Kueche_Sonnenschutz_WinkelRechts.postUpdate(280);
	}
	if(Rolladen_EG_Kueche_Stand_Nachts.state == NULL){
		Rolladen_EG_Kueche_Stand_Nachts.postUpdate(100);
	}
	if(Rolladen_EG_Kueche_Sonnenschutz_Wolken.state == NULL){
		Rolladen_EG_Kueche_Sonnenschutz_Wolken.postUpdate(40);
	}
	if(Rolladen_EG_Kueche_Stand_Tagsueber.state == NULL){
		Rolladen_EG_Kueche_Stand_Tagsueber.postUpdate(0);
	}
end

rule "Rollershutter Kueche Update"
when
	Item Rolladen_EG_Kueche changed
then
	var int upTime = 0
	var int downTime = 0

	var Nachtmodus = false

	if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "ASTRO"){
		upTime = (SunriseTime.state as DateTimeType).getCalendar.get(Calendar.HOUR_OF_DAY).intValue * 60 + (SunriseTime.state as DateTimeType).getCalendar.get(Calendar.MINUTE).intValue
		downTime = (SunsetTime.state as DateTimeType).getCalendar.get(Calendar.HOUR_OF_DAY).intValue * 60 + (SunsetTime.state as DateTimeType).getCalendar.get(Calendar.MINUTE).intValue
		Nachtmodus = true
	} else if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "GLOBAL"){
		if(0 < now.getDayOfWeek && now.getDayOfWeek < 6){
			upTime = (Rolladen_Hoch_Stunde_Werktags.state as Number).intValue * 60 + (Rolladen_Hoch_Minute_Werktags.state as Number).intValue
			downTime = (Rolladen_Runter_Stunde_Werktags.state as Number).intValue * 60 + (Rolladen_Runter_Minute_Werktags.state as Number).intValue
		} else if(5 < now.getDayOfWeek && now.getDayOfWeek < 8){
			upTime = (Rolladen_Hoch_Stunde_Wochenende.state as Number).intValue * 60 + (Rolladen_Hoch_Minute_Wochenende.state as Number).intValue
			downTime = (Rolladen_Runter_Stunde_Wochenende.state as Number).intValue * 60 + (Rolladen_Runter_Minute_Wochenende.state as Number).intValue
		}
		Nachtmodus = true
	} else if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "LOCAL"){
		if(now.getDayOfWeek == 1){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Montag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Montag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Montag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Montag.state as Number).intValue
		} else if(now.getDayOfWeek == 2){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Dienstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Dienstag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Dienstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Dienstag.state as Number).intValue
		} else if(now.getDayOfWeek == 3){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Mittwoch.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Mittwoch.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Mittwoch.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Mittwoch.state as Number).intValue
		} else if(now.getDayOfWeek == 4){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Donnerstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Donnerstag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Donnerstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Donnerstag.state as Number).intValue
		} else if(now.getDayOfWeek == 5){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Freitag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Freitag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Freitag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Freitag.state as Number).intValue
		} else if(now.getDayOfWeek == 6){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Samstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Samstag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Samstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Samstag.state as Number).intValue
		} else if(now.getDayOfWeek == 7){
			upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Sonntag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Sonntag.state as Number).intValue
			downTime = (Rolladen_EG_Kueche_Runter_Stunde_Sonntag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Sonntag.state as Number).intValue
		}
		Nachtmodus = true
	}
	
	val int currentTime = now.getHourOfDay * 60 + now.getMinuteOfHour
	val int azimuth = (SunAzimuth.state as Number).intValue
	val int left = (Rolladen_EG_Kueche_Sonnenschutz_WinkelLinks.state as Number).intValue
	val int right = (Rolladen_EG_Kueche_Sonnenschutz_WinkelRechts.state as Number).intValue
	val int actual = (Rolladen_EG_Kueche.state as Number).intValue
	
	if(upTime < downTime){
		if((currentTime > downTime || currentTime < upTime) && Nachtmodus == true){
			Rolladen_EG_Kueche_Stand_Nachts.postUpdate(actual)
		} else if((currentTime <= downTime && currentTime >= upTime) || Nachtmodus == false){
			if(left < right){
				if((azimuth > left && azimuth < right) && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
					Rolladen_EG_Kueche_Sonnenschutz_Stand.postUpdate(actual)
				} else {
					Rolladen_EG_Kueche_Stand_Tagsueber.postUpdate(actual)
				}
			} else {
				if((azimuth > left || azimuth < right) && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
					Rolladen_EG_Kueche_Sonnenschutz_Stand.postUpdate(actual)
				} else {
					Rolladen_EG_Kueche_Stand_Tagsueber.postUpdate(actual)
				}
			}
		}
	} else {
		if((currentTime > downTime && currentTime < upTime) && Nachtmodus == true){
			Rolladen_EG_Kueche_Stand_Nachts.postUpdate(actual)
		} else if((currentTime <= downTime || currentTime >= upTime) || Nachtmodus == false){
			if(left < right){
				if((azimuth > left && azimuth < right) && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
					Rolladen_EG_Kueche_Sonnenschutz_Stand.postUpdate(actual)
				} else {
					Rolladen_EG_Kueche_Stand_Tagsueber.postUpdate(actual)
				}
			} else {
				if((azimuth > left || azimuth < right) && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
					Rolladen_EG_Kueche_Sonnenschutz_Stand.postUpdate(actual)
				} else {
					Rolladen_EG_Kueche_Stand_Tagsueber.postUpdate(actual)
				}
			}
		}
	}
end

rule "Rollershutter Kueche Action"
when
	//Item SunAzimuth changed or
	Time cron "0 0/5 * * * ?" //or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Montag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Montag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Montag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Montag changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Dienstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Dienstag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Dienstag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Dienstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Mittwoch changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Mittwoch changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Mittwoch changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Mittwoch changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Donnerstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Donnerstag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Donnerstag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Donnerstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Freitag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Freitag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Freitag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Freitag changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Samstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Samstag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Samstag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Samstag changed or
	//Item Rolladen_EG_Kueche_Hoch_Stunde_Sonntag changed or
	//Item Rolladen_EG_Kueche_Hoch_Minute_Sonntag changed or
	//Item Rolladen_EG_Kueche_Runter_Stunde_Sonntag changed or
	//Item Rolladen_EG_Kueche_Runter_Minute_Sonntag changed or
	//Item Rolladen_EG_Kueche_Nighttime_Mode changed or
	//Item Rolladen_EG_Kueche_Sonnenschutz_Modus changed or
	//Item Rolladen_EG_Kueche_Sonnenschutz_Stand changed or
	//Item Rolladen_EG_Kueche_Sonnenschutz_WinkelLinks changed or
	//Item Rolladen_EG_Kueche_Sonnenschutz_WinkelRechts changed or
	//Item Rolladen_EG_Kueche_Sonnenschutz_Wolken changed or
	//Item OLDClouds changed
then
	//logInfo("Rolladen Kueche","start")
	
	if(Rolladen_EG_Kueche.state == NULL){
		logInfo("Rolladen Kueche","Homatic not ready")
	} else {

		var int upTime = 0
		var int downTime = 0
		
		var Nachtmodus = false


		if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "ASTRO"){
			//logInfo("Rolladen Kueche","astro start")
			upTime = (SunriseTime.state as DateTimeType).getCalendar.get(Calendar.HOUR_OF_DAY).intValue * 60 + (SunriseTime.state as DateTimeType).getCalendar.get(Calendar.MINUTE).intValue
			downTime = (SunsetTime.state as DateTimeType).getCalendar.get(Calendar.HOUR_OF_DAY).intValue * 60 + (SunsetTime.state as DateTimeType).getCalendar.get(Calendar.MINUTE).intValue
			Nachtmodus = true
			//logInfo("Rolladen Kueche","astro end")
		} else if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "GLOBAL"){
			//logInfo("Rolladen Kueche","global start")
			if(0 < now.getDayOfWeek && now.getDayOfWeek < 6){
				upTime = (Rolladen_Hoch_Stunde_Werktags.state as Number).intValue * 60 + (Rolladen_Hoch_Minute_Werktags.state as Number).intValue
				downTime = (Rolladen_Runter_Stunde_Werktags.state as Number).intValue * 60 + (Rolladen_Runter_Minute_Werktags.state as Number).intValue
			} else if(5 < now.getDayOfWeek && now.getDayOfWeek < 8){
				upTime = (Rolladen_Hoch_Stunde_Wochenende.state as Number).intValue * 60 + (Rolladen_Hoch_Minute_Wochenende.state as Number).intValue
				downTime = (Rolladen_Runter_Stunde_Wochenende.state as Number).intValue * 60 + (Rolladen_Runter_Minute_Wochenende.state as Number).intValue
			}
			Nachtmodus = true
			//logInfo("Rolladen Kueche","global end")
		} else if(Rolladen_EG_Kueche_Nighttime_Mode.state.toString == "LOCAL"){
			//logInfo("Rolladen Kueche","local start")
			if(now.getDayOfWeek == 1){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Montag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Montag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Montag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Montag.state as Number).intValue
			} else if(now.getDayOfWeek == 2){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Dienstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Dienstag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Dienstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Dienstag.state as Number).intValue
			} else if(now.getDayOfWeek == 3){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Mittwoch.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Mittwoch.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Mittwoch.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Mittwoch.state as Number).intValue
			} else if(now.getDayOfWeek == 4){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Donnerstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Donnerstag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Donnerstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Donnerstag.state as Number).intValue
			} else if(now.getDayOfWeek == 5){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Freitag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Freitag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Freitag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Freitag.state as Number).intValue
			} else if(now.getDayOfWeek == 6){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Samstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Samstag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Samstag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Samstag.state as Number).intValue
			} else if(now.getDayOfWeek == 7){
				upTime = (Rolladen_EG_Kueche_Hoch_Stunde_Sonntag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Hoch_Minute_Sonntag.state as Number).intValue
				downTime = (Rolladen_EG_Kueche_Runter_Stunde_Sonntag.state as Number).intValue * 60 + (Rolladen_EG_Kueche_Runter_Minute_Sonntag.state as Number).intValue
			}
			Nachtmodus = true
			//logInfo("Rolladen Kueche","local end")
		}

		//logInfo("Rolladen Kueche","get value start")

		val int currentTime = now.getHourOfDay * 60 + now.getMinuteOfHour
		val int azimuth = (SunAzimuth.state as Number).intValue
		val int actual = (Rolladen_EG_Kueche.state as Number).intValue
		val int max = (Rolladen_EG_Kueche_Sonnenschutz_Stand.state as Number).intValue
		val int left = (Rolladen_EG_Kueche_Sonnenschutz_WinkelLinks.state as Number).intValue
		val int right = (Rolladen_EG_Kueche_Sonnenschutz_WinkelRechts.state as Number).intValue
		val int night = (Rolladen_EG_Kueche_Stand_Nachts.state as Number).intValue
		val int old = (Rolladen_EG_Kueche_Stand_Tagsueber.state as Number).intValue
		val int cloud = (OLDClouds.state as Number).intValue
		val int cloudmax = (Rolladen_EG_Kueche_Sonnenschutz_Wolken.state as Number).intValue

		//logInfo("Rolladen Kueche","get value end")
		//logInfo("Rolladen Kueche","calc random start")

		if((RandomMaxTime.state as Number).intValue != (RandomMinTime.state as Number).intValue){
			var int random = (RandomMaxTime.state as Number).intValue - (RandomMinTime.state as Number).intValue
		
			upTime = upTime + (((new Random).nextInt(random)) + (RandomMinTime.state as Number).intValue)
			downTime = downTime + (((new Random).nextInt(random)) + (RandomMinTime.state as Number).intValue)
		}
		
		//logInfo("Rolladen Kueche","calc random end")
		
		//logInfo("Rolladen Kueche","modus start")
		if(upTime < downTime){
			//logInfo("Rolladen Kueche","1")
			if((currentTime <= downTime && currentTime >= upTime) || Nachtmodus == false){
				//logInfo("Rolladen Kueche","2")
				if(left < right){
					//logInfo("Rolladen Kueche","3")
					if((azimuth > left && azimuth < right) && cloudmax > cloud && actual <= max && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
						//logInfo("Rolladen Kueche", "4")
						if(actual != max){
							//logInfo("Rolladen Kueche","5")
							Rolladen_EG_Kueche.sendCommand(max)
							//logInfo("Rolladen Kueche","6")
						}
						//logInfo("Rolladen Kueche", "7")
					} else if(actual != old){
						//logInfo("Rolladen Kueche","8")
						Rolladen_EG_Kueche.sendCommand(old)
						//logInfo("Rolladen Kueche","9")
					}
					//logInfo("Rolladen Kueche","10")
				} else {
					//logInfo("Rolladen Kueche","11")
					if((azimuth > left || azimuth < right) && cloudmax > cloud && actual <= max && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
						//logInfo("Rolladen Kueche", "12")
						if(actual != max){
							//logInfo("Rolladen Kueche","13")
							Rolladen_EG_Kueche.sendCommand(max)
							//logInfo("Rolladen Kueche","14")
						}
						//logInfo("Rolladen Kueche", "15")
					} else if(actual != old){
						//logInfo("Rolladen Kueche","16")
						Rolladen_EG_Kueche.sendCommand(old)
						//logInfo("Rolladen Kueche","17")
					}
					//logInfo("Rolladen Kueche","18")
				}
				//logInfo("Rolladen Kueche","19")
			} else if(actual < night && Nachtmodus == true){
				//logInfo("Rolladen Kueche","20")
				Rolladen_EG_Kueche.sendCommand(night)
				//logInfo("Rolladen Kueche","21")
			}
			//logInfo("Rolladen Kueche","22")
		} else {
			//logInfo("Rolladen Kueche","23")
			if((currentTime <= downTime || currentTime >= upTime) || Nachtmodus == false){
				//logInfo("Rolladen Kueche","24")
				if(left < right){
					//logInfo("Rolladen Kueche","25")
					if((azimuth > left && azimuth < right) && cloudmax > cloud && actual <= max && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
						//logInfo("Rolladen Kueche", "26")
						if(actual != max){
							//logInfo("Rolladen Kueche","27")
							Rolladen_EG_Kueche.sendCommand(max)
							//logInfo("Rolladen Kueche","28")
						}
						//logInfo("Rolladen Kueche", "29")
					} else if(actual != old){
						//logInfo("Rolladen Kueche","30")
						Rolladen_EG_Kueche.sendCommand(old)
						//logInfo("Rolladen Kueche","31")
					}
					//logInfo("Rolladen Kueche","32")
				} else {
					//logInfo("Rolladen Kueche","33")
					if((azimuth > left || azimuth < right) && cloudmax > cloud && actual <= max && Rolladen_EG_Kueche_Sonnenschutz_Modus.state == ON){
						//logInfo("Rolladen Kueche", "34")
						if(actual != max){
							//logInfo("Rolladen Kueche","35")
							Rolladen_EG_Kueche.sendCommand(max)
							//logInfo("Rolladen Kueche","36")
						}
						//logInfo("Rolladen Kueche", "37")
					} else if(actual != old){
						//logInfo("Rolladen Kueche","38")
						Rolladen_EG_Kueche.sendCommand(old)
						//logInfo("Rolladen Kueche","39")
					}
					//logInfo("Rolladen Kueche","40")
				}
				//logInfo("Rolladen Kueche","41")
			} else if(actual < night && Nachtmodus == true){
				//logInfo("Rolladen Kueche","42")
				Rolladen_EG_Kueche.sendCommand(night)
				//logInfo("Rolladen Kueche","43")
			}
			//logInfo("Rolladen Kueche","44")
		}
		//logInfo("Rolladen Kueche","modus end")
	}
end

So many var int
Use Number instead where possible

If you are on an RPi this is known and expected behavior.

You can speed things up a tad by avoiding the use of primitives in your Rules. I’ve seen some reports of that saving several minutes by itself. I see a whole lot of primitives in those Rules.

A RPi 1 is not recommended for use as it doesn’t have enough RAM to run OH properly. A RPi 3 is probably the most popular host for OH right now, though in the coming months I expect the RPi 4 with at least 2 gig to replace that as most used. For most users and most uses the RPis are perfectly adequate, though the startup times are exaggerated.

Also, this may be obvious but it should be stated anyway, long Rules will require more effort by the computer to parse than shorter Rules. I see lots and lots of ways you can shrink this code by at least 50%. For example:

import org.eclipse.smarthome.model.script.ScriptServiceUtil

rule "Rollershutter Kueche Init"
when
	System started
then
    // Wait for everything to be loaded and parsed before trying to initialize stuff
    createTimer(now.plusMinutes(30), [ |
        RollerShuttersInitialize.members.forEach[ rsItem |
            val initVal = ScriptServiceUtil.getItemRegistry.getItem(rsItem.name+"_Init")
            rsItem.postUpdate(initVal.state)
        ]
    ])
end

Make sure that the Init Items are restoreOnStartup.

That takes a rule from 112 lines to 13 lines, including the comment.

The second Rule is probably a nightmare for the Rules Parser to handle. You ints on almost every line of code. And you don’t need a one of them. As rossko57 suggest, just use Number. It is far easier for the Rules engine to figure out the type of stuff at runtime than it is for it to parse and ensure the type of everything at compile time. When you use primitives you give the engine no choice but to figure it out at compile time greatly increasing your Rules parsing time.

A lot of this second Rule also looks like it could benefit from Design Pattern: How to Structure a Rule and Design Pattern: DRY, How Not to Repeat Yourself in Rules DSL and perhaps Design Pattern: Separation of Behaviors which can separate some of the calculations into another Rule which will simplify both sets of logic. This is especially the case as it appears that the second and third Rule are very similar in parts. For example, move all the stuff at the top of both Rules where you calculate the upTime and downTime into their own Rule that gets triggered when Rolladen_EG_Kueche_Nighttime_Mode changes and store the result in a Items. Then your second and third Rule don’t need to duplicate that logic and can just use those Items.

I realize that most of the triggers are commented out in the third Rule, but they could all be replaced with a Group and the Member of trigger.

Member of Rolladens changed

Thanks for the advice.

Before I write a new rule with timers and a state machine, I will change the old rules to get more familiar with the rule engine. The Rule is 2 years old and needs to be updated, and was used to have a working system and to play with the system.

For now, I want to reduce the rule with the use for groups, “forEach” and name patterns.
To use rules as functions, items as gobal variables and triggers as function calls, are things I still have to learn.

I will work through the links.

To avoid primitives, which is the best type to come across with openhab, and how are the casting guidelines.

Should I use Double/Integer or Number for my calculations?
Number is the superclass of Integer and Double, when I use “as Number”, “as DecimalType” or “as QuantityType” which instance of subclass is used in Number?

Almost all of the time the Rules engine is able to figure out the type on it’s own. So don’t use a type at all.

val MyNumberVariable = 25

In some rare cases the Rules engine is not able to figure out the type on it’s own. In that case you need to help.

For example

val Timer myTimer = null

Without the type, there is nothing to tell the Rules engine that myTimer needs to be of type Timer.

logInfo("test", MyItem.state.toString)

There is nothing to tell the Rules engine that you want .state as a String so you have to call it yourself.

logInfo("test", "The state is " + MyItem.state) will work because the Rules engine can see that it *must* convert MyItem.state to a String to build up the String to log.

When dealing with Number states, cast the state to Number.

if(MyNumberItem.state as Number > 25)

Sometimes you need the as Number and sometimes you don’t. It all depends on the order of operations so I suggest always casting NumberItem states to Number.

Finally, there are a few rare cases where a primitive is required, for example the now.plus*() methods. In those cases leave it as a Number and convert it to an int at the last moment.

now.plusSeconds((MyItem.state as Number).intValue)

Use Number. By default, the Rules Engine will use BigDecimal for all Numbers unless you specify otherwise.

Actually I think it’s only an Interface. But anyway, BigDecimal is the class that is used.

QuantityType is a whole other beast. To cast that to a Number you need to do something a little different.

MyQuantityTypeNumber.state as QuantityType<Number>

I usually see it then converted to a primitive

(MyQuantityTypeNumber.state as QuantityType<Number>).intValue

but I bet you could cast it to a Number

(MyQuantityTypeNumber.state as QuantityType<Number>) as Number

If all you are doing is comparing a QuantityType to a constant, than you can avoid the conversions and just define your constant as a QuantityType

if(MyTemp.state > 20|°C)