Skip to content

OpenHab Christmas Rule

Dear Reader,

Update: I posted the basic rules over on the OpenHab community site. The result was a much more elegant version of the rule determining if it’s time to turn on the Christmas Lights or not. Check it out and make sure you say thank you to Rich.

If you read my last post “OpenHab Notify Rule” then you know my latest hobby is home automation using OpenHab. it’s fun and while it still involves computers and programming, it helps me remember why I hate Java so much. :)

As I write this, we are in the midst of the Christmas Season and the Lovely and Talented Kathy lives for this time of year so that she can decorate the house. Since we just moved into a new house, this is a “rebuilding year” for us decoration wise, which is the perfect time to begin automating things. Thankfully, OpenHab makes that real easy. Below is my recipe for automating turning things on a dusk and off at 11:00 PM.

 

Items

I don’t have much in the way of Items yet. We just have the lights on the tree to turn on. So here is my single Item that I have to define.

1
2
3
4
5
6
7
Switch Plug_Christmas_Tree "Christmas Tree"  (christmasLights)
{
    channel="zwave:device:512:node29:switch_binary"
}
 
Group christmasLights
Switch sChristmasLights "Christmas Lights" <switch>  [ "Lighting" ]

All I do it turn on and off the plug. That last one, sChristmasLights, is so that I can expose it to Amazon’s Alexa. Don’t judge me! I don’t expose it directly to my network, it goes through a separate system that has a secure tunnel in to this one service. Trust me, I don’t trust Bezos any more than you do.

Rules

The items weren’t the hard part on this particular project, it was the logic behind turning things on and off and when. Here are the constraints:

  • Turn the lights on a Dusk
  • Turn the lights off at 11:00 PM
  • Regardless of what those liars marketers at Wall-Mart, or Target, or Amazon would have you believe, the Christmas season begins on the Friday after Thanksgiving and goes through the end of December. Don’t execute these actions if we are not ‘in season’.

So with those constraints in mind, here is what I came up with.

Imports

Since this is Java, you need to import a few things. These need to be at the top of whatever rules file you put the rules in.

1
2
3
4
5
6
import java.time.Year
import java.time.Month
import java.time.temporal.TemporalAdjusters
import java.time.temporal.ChronoUnit
import java.time.DayOfWeek
import java.time.LocalDate

Turn Lights on

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
rule "Christmas Lights ON"
when
  Channel "astro:sun:local:civilDusk#event" triggered START
then
  val String currentYear = String::format("%1$tY", new java.util.Date )
 
  val LocalDate thanksgiving = Year.of(Integer.parseInt(currentYear)).atMonth(Month.NOVEMBER).atDay(1)
    .with(TemporalAdjusters.firstInMonth(DayOfWeek.THURSDAY))
    .with(TemporalAdjusters.nextOrSame(DayOfWeek.THURSDAY))
    .with(TemporalAdjusters.next(DayOfWeek.THURSDAY))
    .with(TemporalAdjusters.next(DayOfWeek.THURSDAY))
    .with(TemporalAdjusters.next(DayOfWeek.THURSDAY))
 
  var LocalDate lastDayOfYear = Year.of(Integer.parseInt(currentYear)).atMonth(Month.DECEMBER).atDay(1)
    .with(TemporalAdjusters.lastDayOfYear)
 
  var LocalDate today = LocalDate.now()
 
  if (
    today.until(thanksgiving,ChronoUnit.DAYS)<=0 &&
    thanksgiving.until(lastDayOfYear, ChronoUnit.DAYS)>0
  ) {
    logInfo("LIGHTS","Light the Christmas tree")
    christmasLights.sendCommand(ON)
  } else {
    logInfo("LIGHTS",today.until(thanksgiving,ChronoUnit.DAYS).toString + " days until the Christmas tree is lit.")
  }
 
end

See, now you too can hate on Java. :)

Honestly, DateTime math sucks in any language and DTM is the heart of this problem. Thanksgiving is the 4th Thursday of the month of November in the US. That big ugly thing starting at line 7 computers the 4th Thursday of the month. On line 5, we computer the current year so that the ugly statement knows which Thanksgiving we want computed.

Now that we know the upper bounds of our window, we need to computer the lower bounds. The last day of the year. That one is easy.

From there it’s easy. Are there zero days or less left until Thanksgiving? If so, have we hit the end of the year? If we are between those two dates, LIGHT THE TREE!

This rule runs at dusk every night and depends on the Astro binding. The Astro was the second binding I installed, Z-Wave being the first. When I write my OpenHab book I think I’ll call it “OpenHab from Astro to Z-Wave” :)

Turn off the lights

Now, I could do all of those calculations every night at 11:00 to see if the Christmas lights need turning off. As it turns out, I’m lazy; that and I discovered the cron rule trigger. To turn the lights off I use the cron trigger to fire my rule every night at 11:00 in November and December. Yes, I cheated, deal with it.

Here’s my lights off rule.

1
2
3
4
5
6
7
rule "Christmas Lights OFF"
when
  Time cron "0 0 23 1/1 NOV,DEC ? *"
then
  christmasLights.sendCommand(OFF)
  logInfo("LIGHTS","Christmas, Lights Off")
end

Simple, huh?

That’s it. With those to rules and three items, I never ever have to worry about turning the tree of or on again. Next year, exterior illumination! :)

Hardware

To make the magic happen, I invested in a GE Z-Wave external plug. While I plan on wiring all my plugs in the house with Z-Wave, I’m not ready to do that just yet. With this, I just plug it in and plug the tree into it. Easy Peasy.

Wrapup

I hope that sharing what I know about seasonal illumination enhances your season. Remember, as much fun as it is to get together with family, that’s not the reason for the season.

Until next time,
I <3 K

=C=