Sunrise/Sunset Rule

Hello everyone! I need some more help with rules. I have a smart switch installed for my porch light, an I am trying to simply turn the thing on at dusk and off at dawn.

The rule I have so far is:

rule "Sunset Rule"

when
    Channel 'astro:sun:local:civilDuskt#event' triggered START

then
    // Do what you want to do at start of sunset for example:
    // Outside_Lights.sendCommand(ON)
    Porch_Light.sendCommand(ON)
end

rule "Sunrise Rule"

when
    Channel 'astro:sun:local:civilDawn#event' triggered START

then
    // Do what you want to do at start of sunset
    // Outside_Lights.sendCommand(ON)
    Porch_Light.sendCommand(OFF)
end

I installed the Astro binding, and it created the channels, but I am unclear if I have to bind them to an Item or not.

The Item Porch_Light is bound to the Thing’s switch channel, and is teste working A-OK (it is a Zwave switch on Node 013). I also have my location configured in Openhab2 and I got into the thing local sun settings, it shows a location under configurations parameters (which is correct), though the location field under the name is empty.

Log wise the only thing that references the astro binding is this:

2020-03-15 19:42:00.005 [vent.ChannelTriggeredEvent] - astro:sun:local:nauticDusk#event triggered START
2020-03-15 19:42:00.010 [vent.ChannelTriggeredEvent] - astro:sun:local:civilDusk#event triggered END

Thanks in advance for the help, I am sure I am missing something simple here.

It would advise to bind the channels to Things as you may use them in other rules as well:

   Switch		TagNacht				"Wenn Tag, dann An, Wenn Nacht, dann Aus"			<time>		(Home, gVar)
   Switch		Vormittag				"An zum Sonnenaufgang, Aus zum Mittag"				<time>		(Home, gVar)

   String		Tagesanfang				"Beginn der Dämmerung, Sonnenaufgang"				<time>		(Home, gVAR)
   String		Tagesende				"Sonnenuntergang, Ende der Dämmerung"				<time>		(Home, gVAR)
   String		ACT_AZ_SH				"Azimut / Sonnenwinkel [%s]"					<sun>		(Home, gVAR)

   DateTime		Sonnenaufgang_Anfang			"Sonnenaufgang Beginn [%1$tH:%1$tM]"				<sunrise>	(gAstro)	{channel="astro:sun:local:rise#start"}
   DateTime		Sonnenaufgang_Ende			"Sonnenaufgang Ende [%1$tH:%1$tM]"				<sunrise>	(gAstro)	{channel="astro:sun:local:rise#end"}
   Number:Time		Sonnenaufgang_Dauer			"Dauer des Sonnenaufgangs [%.0f Minuten]"			<sunrise>	(gAstro)	{channel="astro:sun:local:rise#duration"}

   DateTime		Sonnenuntergang_Anfang			"Sonnenuntergang Beginn [%1$tH:%1$tM]"				<sunset>	(gAstro)	{channel="astro:sun:local:set#start"}
   DateTime		Sonnenuntergang_Ende			"Sonnenuntergang Ende [%1$tH:%1$tM]"				<sunset>	(gAstro)	{channel="astro:sun:local:set#end"}
   Number:Time		Sonnenuntergang_Dauer			"Dauer des Sonnenuntergangs [%.0f Minuten]"			<sunset>	(gAstro)	{channel="astro:sun:local:set#duration"}

   DateTime     	Mittag_Zeit_Anfang			"Mittag Beginn [%1$tH:%1$tM]"  					<sun>		(gAstro)	{channel="astro:sun:local:noon#start"}
   DateTime     	Mittag_Zeit_Ende			"Mittag Ende [%1$tH:%1$tM]"					<sun>		(gAstro)	{channel="astro:sun:local:noon#end"}
   Number:Time		Mittag_Dauer				"Dauer des Mittags [%.0f Minuten]"				<sun>		(gAstro)	{channel="astro:sun:local:noon#duration"}

   DateTime		Nacht_Zeit_Anfang			"Nacht Beginn [%1$tH:%1$tM]"					<sun>		(gAstro)	{channel="astro:sun:local:night#start"}
   DateTime		Nacht_Zeit_Ende				"Nacht Ende [%1$tH:%1$tM]"					<sun>		(gAstro)	{channel="astro:sun:local:night#end"}
   Number:Time		Nacht_Dauer				"Dauer der Nacht [%.0f Minuten]"				<sun>		(gAstro)	{channel="astro:sun:local:night#duration"}

   DateTime		Morgenliche_Nacht_Anfang		"Morgenliche Nacht Beginn [%1$tH:%1$tM]"			<sun>		(gAstro)	{channel="astro:sun:local:morningNight#start"}
   DateTime		Morgenliche_Nacht_Ende			"Morgenliche Nacht Ende [%1$tH:%1$tM]"				<sun>		(gAstro)	{channel="astro:sun:local:morningNight#end"}
   Number:Time		Morgenliche_Nacht_Dauer			"Dauer der morgenlichen Nacht [%.0f Minuten]"			<sun>		(gAstro)	{channel="astro:sun:local:morningNight#duration"}

   DateTime		Astronomische_Morgendaemmerung_Anfang	"Astronomische Morgendämmerung Beginn [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:astroDawn#start"}
   DateTime		Astronomische_Morgendaemmerung_Ende	"Astronomische Morgendämmerung Ende [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:astroDawn#end"}
   Number:Time		Astronomische_Morgendaemmerung_Dauer	"Dauer der astronomischen Morgendämmerung [%.0f Minuten]"	<sun>		(gAstro)	{channel="astro:sun:local:astroDawn#duration"}

   DateTime		Nautische_Morgendaemmerung_Anfang	"Nautische Morgendämmerung Beginn [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:nauticDawn#start"}
   DateTime		Nautische_Morgendaemmerung_Ende		"Nautische Morgendämmerung Ende [%1$tH:%1$tM]"			<sun>		(gAstro)	{channel="astro:sun:local:nauticDawn#end"}
   Number:Time		Nautische_Morgendaemmerung_Dauer	"Dauer der nautischen Morgendämmerung [%.0f Minuten]"		<sun>		(gAstro)	{channel="astro:sun:local:nauticDawn#duration"}

   DateTime		Buergerliche_Morgendaemmerung_Anfang	"Bürgerliche Morgendämmerung Beginn [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:civilDawn#start"}
   DateTime		Buergerliche_Morgendaemmerung_Ende	"Bürgerliche Morgendämmerung Ende [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:civilDawn#end"}
   Number:Time		Buergerliche_Morgendaemmerung_Dauer	"Dauer der bürgerlichen Morgendämmerung [%.0f Minuten]"		<sun>		(gAstro)	{channel="astro:sun:local:civilDawn#duration"}

   DateTime		Astronomische_Abenddaemmerung_Anfang	"Astronomische Abenddämmerung Beginn [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:astroDusk#start"}
   DateTime		Astronomische_Abenddaemmerung_Ende	"Astronomische Abenddämmerung Ende [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:astroDusk#end"}
   Number:Time		Astronomische_Abenddaemmerung_Dauer	"Dauer der astronomischen Abenddämmerung [%.0f Minuten]"	<sun>		(gAstro)	{channel="astro:sun:local:astroDusk#duration"}

   DateTime		Nautische_Abenddaemmerung_Anfang	"Nautische Abenddämmerung Beginn [%1$tH:%1$tM]"			<sun>		(gAstro)	{channel="astro:sun:local:nauticDusk#start"}
   DateTime		Nautische_Abenddaemmerung_Ende		"Nautische Abenddämmerung Ende [%1$tH:%1$tM]"			<sun>		(gAstro)	{channel="astro:sun:local:nauticDusk#end"}
   Number:Time		Nautische_Abenddaemmerung_Dauer		"Dauer der nautischen Abenddämmerung [%.0f Minuten]"		<sun>		(gAstro)	{channel="astro:sun:local:nauticDusk#duration"}

   DateTime		Buergerliche_Abenddaemmerung_Anfang	"Bürgerliche Abenddämmerung Beginn [%1$tH:%1$tM]"		<sun>		(gAstro)	{channel="astro:sun:local:civilDusk#start"}
   DateTime		Buergerliche_Abenddaemmerung_Ende	"Bürgerliche Abenddämmerung Ende [%1$tH:%1$tM]"			<sun>		(gAstro)	{channel="astro:sun:local:civilDusk#end"}
   Number:Time		Buergerliche_Abenddaemmerung_Dauer	"Dauer der bürgerlichen Abenddämmerung [%.0f Minuten]"		<sun>		(gAstro)	{channel="astro:sun:local:civilDusk#duration"}

You may then use in rules like the ones you displayed, I am using similar ones to open/close my blinds using g channel triggers as you do. Here are more examples:

rule "Zusammenfassung Daemmerung - Sonnenaufgang"
when
  System started or
  Item Sonnenaufgang_Anfang changed or
  Item Buergerliche_Morgendaemmerung_Anfang changed
then
  val String SUNA = Sonnenaufgang_Anfang.state.format("%1$tH:%1$tM")
  val String BMDA = Buergerliche_Morgendaemmerung_Anfang.state.format("%1$tH:%1$tM")
  var String Ausgabe_D1 = String::format("%s / %s", BMDA, SUNA)
  Tagesanfang.postUpdate(Ausgabe_D1)
end

rule "Zusammenfassung Sonnenuntergang - Daemmerung"
when
  System started or
  Item Sonnenuntergang_Anfang changed or
  Item Nautische_Abenddaemmerung_Anfang changed
then
  val String SUNS = Sonnenuntergang_Anfang.state.format("%1$tH:%1$tM")
  val String BADE = Nautische_Abenddaemmerung_Anfang.state.format("%1$tH:%1$tM")
  var String Ausgabe_D2 = String::format("%s / %s", SUNS, BADE)
  Tagesende.postUpdate(Ausgabe_D2)
end

rule "Azimut und Sonnenhoehe"
when
  System started or
  Item Jahreszeit  changed or
  Item Azimut      changed or
  Item Sonnenhoehe changed
then
  var az	= ((Azimut.state as Number).floatValue)
  var sh	= ((Sonnenhoehe.state as Number).floatValue)
  var String ah	= String::format("%1$.1f° / %2$.1f°", az, sh)
  ACT_AZ_SH.postUpdate(ah)
end

No, you don’t need an Item for the event channels, this is why the channel trigger is there at first place.

However, it is a good idea to use a proxy Item to store the state, e.g. a Switch Item isNight would be set to ON from dusk till dawn :wink: but this Item the is switched by your two rules. (maybe in addition to the Item Porch_Light)
this way you can refer to the state in a rule [if(isNight.state == ON)]

Furthermore, if you use an Item to hold “night” state, you can calculate or persist the state if the system is rebooted between events.

Doesn’t Astro binding provide a simple night state channel already?

Ist does, but one may want to use the different dusk/dawn phases to determine day and night.

Got it, setup an intermediate Item to hold the day night status. Makes sesnse.

But if this rule as written is not working, then I’d also not be able to update that Item so I am thinking to get this rule working, then I can modify it to update the intermediate Item and write a second rule for the porch light.

Well, there’s a typo in the civildusk trigger.

I think the binding is smart enough to create (and events log) only those channels in use.

1 Like

Can you help me out and point it out to me. I just can’t seem to see it.

Double check the Channel name

Another example:

rule "Set to day"
when
  Channel "astro:sun:local:civilDawn#event" triggered START
then
  TagNacht.postUpdate(ON)
end

rule "Set to night"
when
  Channel "astro:sun:local:nauticDusk#event" triggered START
then
  TagNacht.postUpdate(OFF)
end

Thanks for the help, I eventually found it, but it was very hard to see. But why did you both not just tell me there was a “t” at the end if dusk instead of making me feel like a complete idiot? There is a reason we ask others to proof read stuff, and that is precisely because small errors like this are actually impossible to see (there is tons of psych research on this) and I did end my original post saying it was probably something simple.

Anyways, I will see at dusk tonight if this works, if it does, then I’ll do the proxy item, since that does make sense and grants a fair bit of flexibility down the road.

You will probably want to also add a rule to the System started event to set the dummy item (or zwave switch) to the proper value when openHab starts. Something along the lines of:

rule SystemStartUp
when System started  
then 
	 switch now {
   	   case now.isAfter(Datetime(Sunrise.state.toString)) && now.isBefore(Datetime(Sunset.state.toString)):isNight.postUpdate(OFF)
	   default: isNight.postUpdate(ON)
	 }
end

My Items are:

Switch      isNight            "Night"      
DateTime    Sunrise            "Sunrise"     {channel="astro:sun:local:rise#start"}
DateTime    Sunset             "Sunset"      {channel="astro:sun:local:set#end"} 
2 Likes

@JimH

That’s pretty slick. I think I’ll steal that from you. Thanks!

Is Datetime() a built in defined function, or does that need to be defined elsewhere? VSCode is throwing out an “Undefined method” error for it.

I’m new to openHab, but I believe it is built in a Java function converting the Sunset item’s state to a Datetime variable. I’m assuming that you have that entire line of code on one line. I’ve occasionally found that closing VSCode and restarting openHab sometime helps.

I also noticed that i left the “end” off at the end of the rule, I’ve updated the original post.

Try this rule instead

rule SystemStartUp
when System started  
then 
    var vSunrise = new DateTime(Sunrise.state.toString)
	var vSunset  = new DateTime(Sunset.state.toString)
	switch now {
	  case now.isAfter(vSunrise) && now.isBefore(vSunset): isNight.postUpdate(OFF)
	  default: isNight.postUpdate(ON)
	}
end
2 Likes

It was much happier with that. Thanks.

It still does not work.

I create two Items Sunrise and Sunset. I linked sunrise to Civil Dawn Start and I linked sunset to Civil Dusk End. When I go to the control section I see these there, but only Sunset has a value (which looks right), Sunrise shows a - I used @JimH rule from above to get a value into these Items

I fixed the typo, and now the rule looks right (same as I posted above), but the light did not turn on at Sunset. The log shows me nothing of use.

Where do I got to work out if all these pieces are working? Is there another I need to look at to help me trouble shoot rules or the Astro binding?

I have spent and hour googling this to no avail, I read the entire wiki page on the Astro binding and found nothing there that could help.

You have to be very careful with channel linking with Astro binding, it is easy to get it wrong.
Astro channels come in two “flavours”, state channels like
astro:sun:local:civilDawn#start
and trigger event channels like
astro:sun:local:civilDawn#event
You cannot mix which types link to Items and which trigger rules.

Okay, that looks like a simple one to tackle.
Start by double checking the Item definition and channel.
Note this Item is not populated from rule, it is populated by binding channel.
Binding calculates values at midnight and startup time, so if you clear or create an Item inbetween it won’t get repopulated.

Makes sense, the items bound to the state channel both have data now. So that appears to be working.

I am not too sure what you mean. My rule for turning on the light uses the trigger event channel, but the rule I created (separate rule/file) uses the state channel, which is linked to my Sunrise and Sunset *Items. The rule that is not working, has nothing to do with the Sunrise/Sunset Items

This is what it looks like now

 rule "Sunset Rule"
when
    Channel 'astro:sun:local:civilDusk#event' triggered START
then
    // Do what you want to do at start of sunset for example:
    // Outside_Lights.sendCommand(ON)
    Porch_Light.sendCommand(ON)
end

rule "Sunrise Rule"
when
    Channel 'astro:sun:local:civilDawn#event' triggered START
then
    // Do what you want to do at start of sunset
    // Outside_Lights.sendCommand(ON)
    Porch_Light.sendCommand(OFF)
end

I am at a loss as to why it is not working.