Sun (raised / set) indicator

What would be a good way of testing the Range daylight is happening, but not raised by the triggered START but another event e.g. if a switch is made, then check if it is daylight and then perform an action?

Do you mean something like this?

I see what you did there, but as I see astro can give you an string of either if it is spring, or winter, how come it will not just give you a string if it is daylight, night, etcā€¦

Because it wasnā€™t coded that way. Most people use the events to trigger things to happen.

@gerrieg People are continuously asking about that feature. I would also be happy to see a simple channel updated with something similar to ā€œSunrise, Morning, Daytime, Evening, Sunset, Nightā€. What do you think?

added new sun channel with this PR: phase#name

4 Likes

Amazing @gerrieg, thank you!

Hi @ThomDietrich,

I know Iā€™m digging up an old thread here but I would ask if you can cast an expert eye on my system startup rule, which I see is similar to yoursā€¦

In the Smarthome Designer Iā€™m seeing red markers trying to declare the sunrise and sunset variables based on them being defined in my Astro.items file.

According to the log the rule worked though (i.e. 3 minutes later the updates were made)

Here is a screenshot of the code in Designer:

The issue:

This seems to show up in the openhab.log when I restart OH2:

2017-06-07 17:09:01.633 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Astro.items'
2017-06-07 17:09:01.748 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'rrd4j.persist'
2017-06-07 17:09:01.772 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Kodi.items'
2017-06-07 17:09:01.826 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Light.items'
2017-06-07 17:09:01.855 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Presence.items'
2017-06-07 17:09:01.868 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Virtual.items'
2017-06-07 17:09:01.903 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Weather.items'
2017-06-07 17:09:01.977 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Zoneminder.items'
2017-06-07 17:09:04.552 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Presence.rules'
2017-06-07 17:09:05.038 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Lighting.rules'
2017-06-07 17:09:05.487 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'DayNight.rules'
2017-06-07 17:09:06.365 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Startup.rules', using it anyway:
Cannot reference the field 'Sunrise_Start' before it is defined
Cannot reference the field 'Sunset_Start' before it is defined
2017-06-07 17:09:06.367 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Startup.rules'
2017-06-07 17:09:07.081 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Windows.sitemap', using it anyway:
Frames must not contain other frames
2017-06-07 17:09:07.083 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'Windows.sitemap'
2017-06-07 17:09:09.108 [INFO ] [.dashboard.internal.DashboardService] - Started dashboard at /start
2017-06-07 17:09:09.263 [INFO ] [basic.internal.servlet.WebAppServlet] - Started Basic UI at /basicui/app
2017-06-07 17:09:09.295 [INFO ] [arthome.ui.paper.internal.PaperUIApp] - Started Paper UI at /paperui
2017-06-07 17:09:09.327 [INFO ] [panel.internal.HABPanelDashboardTile] - Started HABPanel at /habpanel
2017-06-07 17:09:12.407 [INFO ] [ding.astro.handler.AstroThingHandler] - Scheduled astro job-daily-sun at midnight for thing astro:sun:f3c3056b
2017-06-07 17:09:15.359 [WARN ] [me.internal.engine.RuleContextHelper] - Variable 'sunrise' on rule file 'Startup.rules' cannot be initialized with value 'org.eclipse.xtext.xbase.impl.XConstructorCallImplCustom@1c8d8b2 (invalidFeatureIssueCode: null, validFeature: false, explicitConstructorCall: true, anonymousClassConstructorCall: false)': org.eclipse.smarthome.core.library.types.DateTimeType
2017-06-07 17:09:15.361 [WARN ] [me.internal.engine.RuleContextHelper] - Variable 'sunset' on rule file 'Startup.rules' cannot be initialized with value 'org.eclipse.xtext.xbase.impl.XConstructorCallImplCustom@1a9d429 (invalidFeatureIssueCode: null, validFeature: false, explicitConstructorCall: true, anonymousClassConstructorCall: false)': org.eclipse.smarthome.core.library.types.DateTimeType
2017-06-07 17:09:15.583 [INFO ] [.astro.internal.job.AbstractDailyJob] - Scheduled astro event-jobs for thing astro:sun:f3c3056b
2017-06-07 17:11:19.880 [INFO ] [.model.script.Craig presence updated] - Craig is AWAY
2017-06-07 17:12:10.206 [INFO ] [.model.script.Craig presence updated] - Craig is HOME
2017-06-07 17:12:15.457 [INFO ] [home.model.script.NightState updated] - --> NightState set to OFF
2017-06-07 17:12:15.469 [INFO ] [.model.script.LateNightState updated] - --> LateNightState set to OFF


Iā€™ve tried for ages to find why the designer is unhappy.

Here is the codeā€¦

val sunrise = new DateTime((Sunrise_Start.state as DateTimeType).calendar.timeInMillis)
val sunset = new DateTime((Sunset_Start.state as DateTimeType).calendar.timeInMillis)
val latenight = now.withTimeAtStartOfDay.plusHours(22).millis // 10 PM

rule "Switch NightState and lights on / off depending on night or day"
when
    System started
then
	createTimer(now.plusSeconds(180)) [ |
// Switch NightState to on if it is dark otherwise switch it to off
    	if(now.isAfter(sunset) && now.isBefore(sunrise)){
		postUpdate(NightState, ON)
		logInfo("NightState updated", "--> NightState set to " + NightState.state)
    	}
    	else {
        	postUpdate(NightState, OFF)
			logInfo("NightState updated", "--> NightState set to " + NightState.state)
    	}

// Switch LateNightState on if it is after 22h00 and before sunrise
  		if(now.isAfter(latenight) && now.isBefore(sunrise)){
     	postUpdate(LateNightState, ON)
      	logInfo("LateNightState updated", "--> LateNightState set to " + LateNightState.state)
    	}
    	else {
      	postUpdate(LateNightState, OFF)
      	logInfo("LateNightState updated", "--> LateNightState set to " + LateNightState.state)
    	}
    ]
end

The items definition:

DateTime	Sunrise_Start	"Sunrise Start [%1$tH:%1$tM]"		(gAstro)		{channel="astro:sun:f3c3056b:rise#start"}
DateTime	Sunset_Start	"Sunset Start [%1$tH:%1$tM]"		(gAstro)		{channel="astro:sun:f3c3056b:set#start"}

Also it seems unhappy with my ā€˜IFā€™ statements, here is the issue:

Am I anywhere close to getting it right?

many thanks in advance,

Craig

Hey Craig,
is there any special reason to have these three lines above all? Could you try moving them inside the rule?

@ThomDietrich: not only inside the rule, but inside the lambda right after:

createTimer(now.plusSeconds(180)) [ |
val sunrise = new DateTime((Sunrise_Start.state as DateTimeType).calendar.timeInMillis)
val sunset = new DateTime((Sunset_Start.state as DateTimeType).calendar.timeInMillis)
val latenight = now.withTimeAtStartOfDay.plusHours(22).millis // 10 PM
1 Like

You might like to think about what you are trying to achieve with variables ā€˜sunriseā€™ etc.
Like the Designer warning says, you cannot reference Items outside of rules.
You have also defined them as val meaning they can never be altered - i.e. could never keep track of sunrise tomorrow.
The definition with now in it is also going to go wrong for you eventually - ā€˜nowā€™ would be when the rules file is loaded, and again is one-time-only, would never update for tomorrow.

1 Like

Exactly what I was getting at :thumbsup:

Thank you guys for the advice, itā€™s invaluable :+1:

What Iā€™m trying to achieve is that in case of a power failure, letā€™s say 2 minutes before this sunset event triggers my power goes down and then comes back on 5 minutes after the sunset event would have triggered. Persistence 'restore on startup 'would not help me here.I would imagine just about everyone would would have a similar rule in their setup no?

May I ask for a clarification in @ThomDietrichā€™s example above using the || condition? In order for the system to know that it is night time why not use the && condition? The nightstate must be set to ā€˜ONā€™ if the current time is after sunset AND before sunrise. Does it matter?

I guess part of my requirement is redundant now as I see there is a ā€˜Sun Phaseā€™ channel, so Iā€™ll only need my ā€˜LateAtNightā€™ item maintained, e.g

Iā€™m not sure what the possible ā€˜Sun Phaseā€™ channel values could be so Iā€™ll monitor it.

Now I donā€™t use the Sunset_Start trigger event anymore since I can use the Sun_Phase channel to tell me if itā€™s light or not. Maybe this helps someone out there who want to achieve this (assuming my logic is OK, which it is according to my new friend the Designer :slight_smile:)

Here is my setup:

.items:

DateTime	Sunrise_Start	"Sunrise Start [%1$tH:%1$tM]"	(gAstro)	{channel="astro:sun:f3c3056b:rise#start"}
DateTime	Sunset_Start	"Sunset Start [%1$tH:%1$tM]"	(gAstro)	{channel="astro:sun:f3c3056b:set#start"}
String 		Sun_Phase		"Sun phase"						(gAstro)	{channel="astro:sun:f3c3056b:phase#name"}

Startup rule:

val LateAtNight = now.withTimeAtStartOfDay.plusHours(22).millis // 10 PM

rule "OpenHAB system started - astro"
when
    System started
then
    createTimer(now.plusSeconds(180)) [ |
        logInfo("RULE", "--> astro init")
        if (Sun_Phase.state == 'DAYLIGHT'){
        	logInfo("RULE", "--> Switch all lights off")
        } 
        else {
        	if(now.isAfter(LateAtNight)){
    			postUpdate(LateNightState, ON)
   				logInfo("LateNightState updated", "--> LateNightState set to " + LateNightState.state)
   			}
   			else {
   				postUpdate(LateNightState, OFF)
   				logInfo("LateNightState updated", "--> LateNightState set to " + LateNightState.state)
   			}
        }
    ]
end

And the rule based on the changes in the Sun_Phase channelā€¦

rule "Switch lights on at night"
when
	Item Sun_Phase changed
then
	if (Sun_Phase.state == 'DAYLIGHT'){
		logInfo("Daytime", "--> Lights off")
		sendCommand(Lights_All, OFF)
	} else {
		if (LateNightState.state == ON){
			logInfo("Late at night", "--> Outside lights on full")
			sendCommand(Lights_Outdoor, 100)
			sendCommand(Light_Study, OFF)
		} else {
			logInfo("Night time", "--> Lights on")
			sendCommand(Lights_Outdoor, 40)
			sendCommand(Light_Study, 40)
			}
		}	
end

Not sure how successful Iā€™ll be but Iā€™ll start testing it. If thereā€™s a better way to achieve this I would be glad to hear it.

Thanks again for all your input

Bear in mind that as that is outside of any rule, it only gets executed once at rules file load time, and never gets re-evaluated.

on the other hand I may be able to avoid using the separate startup.rule by including the System started trigger as such:

rule "Switch lights on at night"
when
	System started or
	Item Sun_Phase changed
then
	if (Sun_Phase.state == 'DAYLIGHT'){
		logInfo("Daytime", "--> Lights off")
		sendCommand(Lights_All, OFF)
	} else {
		if (LateNightState.state == ON){
			logInfo("Late at night", "--> Outside lights on full")
			sendCommand(Lights_Outdoor, 100)
			sendCommand(Light_Study, OFF)
		} else {
			logInfo("Night time", "--> Lights on")
			sendCommand(Lights_Outdoor, 40)
			sendCommand(Light_Study, 40)
			}
		}	
end

I would just need to set the LateAtNight value somewhere

And I just saw the DAYLIGHT condition is not going to work since it is now ā€˜NOONā€™. Back to the drawing board :frowning:

It does matter and it must be || because SunsetTime and SunriseTime are calculated at midnight every night. So if the current time is 23:00 6/8/2017 then SunSetTime would be something like 20:30 6/8/2017 and SunriseTime would be 05:30 6/8/2017. The key thing to pay attention to is that the date is included.

The SunsetTime and SunriseTime are for today. In order for the if statement to work using && SunsetTime would need to be for today and SunriseTime needs to be for tomorrow. Since both are calculated for today at midnight the if statement will never evaluate to true if you use &&.

2 Likes

Perfect explanation thanks Rich.

@rlkoshak beat me to it. Excellent, more time for other tasks :wink:

Hello Craig

As I read your post, especially the following part, I asked me a few questionsā€¦

Is it right, that you have every day a power outage when the sun sets?
If yes, have you ever thought about an Ups (uninterruptable power supply)?
Pepending on your hardware (RPIs, Notebook, full PC, Serverā€¦) a small battery pack can solve this problemā€¦

Sorry for this off-topic :slight_smile:

Hi Michael,

Actually if I switch the power off and on again then the lights come on at 100% brightness.So if the power trips during the day and the system powers up, I would be left with the lights burning, hence the rule Iā€™m creating which would purposefully switch them off if it is daytime. OH2 may well receive the updates that the lights are on but I need it to physically switch them off.Iā€™m away from home for a few more weeks and when I get back Iā€™ll test the situation out properly. What happens if you switch you main-power off and on again? My Wemo lights will come one I believe,

I take your point about a UPS but I think the issue is not about keeping the Pi powered up but the actual mains-board going down and coming back up again. Since I live in semi-rural South Africa power outages are likely to happen :slight_smile: Maybe others have this requirement.

My rule works reliably not so Iā€™m looking forward to testing in in reality.