Dear Reader,
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
liarsmarketers 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=