[SOLVED] Light window lights 30 minutes before sunset


I am trying to figure out how to manage my window lights. I find that with trees and surrounding houses in the way of the sun’s trajectory, I would prefer the extra lighting in the garden and in the windows to come on around 30 minutes before sunset and stay on around 30 minutes after sunrise.

The “30 minutes after sunrise” seems relatively easy as I can then just wait for a sunrise event from the Astro binding, wait for 30 minutes and then switch the lights off.

Ok, but the “30 minutes before sunset” seems quite a bit trickier. Can it be done, preferably without setting a -30 offset to sunset items of the Astro binding? I would like to display those times separately on a HABpanel, if possible, and with an offset set they would then not be correct anymore…



I haven’t checked but I believe to use the offset in the astro binding won’t change the displayed time, just the point in time it triggers. If not, you can still use the negative offset, (re-)calculate the ‘real’ time, store it in an item and display that one in your panel instead of the astro-calculated item.
Also, astro binding offers various dawn and dusk start and end events that you can trigger upon as well, see binding docs. I’m using nauticDusk.

Thanks. Perhaps I could just apply an offset of -30 to the sunset event, and leave the other items alone, and then it will work?

Yes, I have had a look at the dusks that are available, but the point is that they all occur after sunset, and I need an event that trigger before sunset.

if you’re not too bothered about exactly 30 minutes, an easy way would be to pick a suitable value of sun elevation (whatever the elevation is about 30 minutes before sunset [I’ve used 5 degrees below]), and then use a rule like this.

rule "30mins sunset"
    Item SunElevation changed
    if(now.getHourOfDay > 12 && SunElevation.state < 5 && SunsetLights.state != ON){

You can do similar for after sunrise.

Here is my rule that gives me a trigger 60min and another 30min before sunset:

import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock
import org.eclipse.smarthome.core.items.GroupItem
import org.eclipse.smarthome.core.library.types.DateTimeType
import org.joda.time.DateTime
// Note: some of the imports may apply to other rules in my file

rule "Get time period for right now"
        System started or
        Item Date received update
var gotLock = lock.tryLock(2000, TimeUnit.MILLISECONDS)		
	try {
		if (gotLock) {
		    Thread::sleep(50) // lets make sure we are just a little past the time transition
		    val morning = now.withTimeAtStartOfDay.plusHours(6).millis
		    val long sunrise = new DateTime((Sunrise_Time.state as DateTimeType).calendar.timeInMillis).millis
		    val long twilight = new DateTime((Sunset_Time.state as DateTimeType).calendar.timeInMillis).millis-60*60*1000 //60 min before real sunet
		    val long evening = new DateTime((Sunset_Time.state as DateTimeType).calendar.timeInMillis).millis-30*60*1000 //30 min before real sunet
		    val night = now.withTimeAtStartOfDay.plusHours(23).millis
		    var currPeriod = "Night"
		    if(now.isAfter(morning) && now.isBefore(sunrise)) currPeriod = "Morning"
		    else if(now.isAfter(sunrise) && now.isBefore(twilight)) currPeriod = "Day"
		    else if(now.isAfter(twilight) && now.isBefore(evening)) currPeriod = "Twilight"
		    else if(now.isAfter(evening) && now.isBefore(night)) currPeriod = "Evening"
//		    logInfo("Time_of_Day", "Current Time of Day {}",  currPeriod)
		    if(TimeOfDay.state.toString != currPeriod) {
		        logInfo("Time_of_Day", "Updating Time of Day {}, Previous Time of Day {}" , currPeriod, TimeOfDay.state.toString)
		else logInfo("Get time period right now", "re-entry lock actived")
	finally {

I use the changes in TimeOfDay to trigger actions I want.
I put most of my rules within a reentrant lock, as I had some issues in the past, however, you may not need this.
The above is based on the great design pattern post here: Design Pattern: Time Of Day (shoutout for @rlkoshak)

I want to use both the event and the time for my 30 minutes before sunset so I created a new Astro Thing with a shifted longitude. Adding 15 degrees moves the sunset time back 60 minutes so to get an Astro Thing that is 30 minutes early just add 7.5 degrees to your longitude.


I made a rule that determines the time of sunrise and sunset there are stored in an item.

rule "Get time period for right now"
    System started or
    Time cron "0 0 4 * * ? *"
    logInfo("Get time testing", "start calculatie")

    Thread::sleep(50) // lets make sure we are just a little past the time transition
    //logInfo("Get time testing", "sunrise time is " + Sunrise_Time.state )
    if (Sunrise_Time.state !== NULL) {
        //Calculate which minute the sun rises and sets
        val sunriseMin = new DateTime((Sunrise_Time.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).getMinuteOfDay
        val sunsetMin =  new DateTime((Sunset_Time.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).getMinuteOfDay
        // set the values to an item
        // show the log it has been done
        logInfo("Get time testing", "sun rise at minute " + sunriseMin )
        logInfo("Get time testing", "Sun set at minute " + sunsetMin )
    } else { 
        logInfo("Get time testing", "There is no sunrise time available")		   

By running a separate script I directly say (sunsetTime.state as Number) - x minutes

No separate rules for each different time