[SOLVED] Lights on all month UNTIL fourth Thursday of the month
-
I've a scene for Arming for Xmas Season that works great, starting on Black Friday (Friday after fourth Thursday/Thanksgiving) and it uses
latch
to achieve the goal.Now I want to have DIFFERENT lighting for November 1 - Thanksgiving night, fourth Thu of November. So far I have:
I know that this will only end up with lights coming on ON the fourth Thu, not prior to it. Am I looking at
Output Control
orConstraints
to make my end date/time Thanksgiving night?Solved here: https://smarthome.community/post/10256
-
Heck, does this mean MSR needs a "Movable Feasts Calendar" or "National Holidays" component in addition to Date/Time, so you can simply pick [BEFORE] [THANKSGIVING] [OFFSET: 0 DAYS]? I recall Calendar Creator 2.0 on my Apple //c had something similar. It figured out things like Easter, Lent (and by extension, Mardi Gras) and so forth. Even Google Calendar can't do all that, nearly 35 years later!
-
And geez, thanks for sending me down a huge rabbit hole. I'm back! I contemplated the reasonableness (you be the judge) of using an API of some kind to simply fetch the always-changing annual date of Thanksgiving. Turns out there are many such APIs, but they cost money, so I focused on the tried-and-true Google Calendars API since Google hosts a robust calendar of U.S. holidays which MSR can query.
Let's take a little stroll down the path I traveled lo these past couple of hours (again, thanks!):
STEP 1. Create an API app in Google developer account https://console.developers.google.com
STEP 2. From the "Credentials" tab, create an API key. You get something like this "AIzaSyBcOT_DpEQysiwFmmmZXupKpnrOdJYAhhM"
STEP 3. Then you can pull events from Google's holiday calendar using this URL -
https://www.googleapis.com/calendar/v3/calendars/en.usa%23holiday%40group.v.calendar.google.com/events?key=yourAPIKeySTEP 4. To retrieve only events called "Thanksgiving" -- there are 3 of them... last year, current year and next year -- one must insert a 'q=' modifier, so the URL we will use in MSR looks like -
https://www.googleapis.com/calendar/v3/calendars/en.usa%23holiday%40group.v.calendar.google.com/events?q=Thanksgiving&key=yourAPIKeySTEP 5. Create a new Rule in MSR which (I guess every January 1st) retrieves the next occurrence of Thanksgiving Day and stores that value into a blank expression. The Rule would have (at minimum) the following parts:
CONDITION = Date/Time set to execute on January 1st of each year
SET REACTION = An [HTTP] request that performs a [GET] on the URL from Step 4 and captures the response to expression [Events].
EXPRESSIONS =
'Events' := (blank)
'Items' := Events.items
'TGend' := T = first Occur in Items with (substr(Occur.end.date,0,4) == dateparts(time()).year), T.end.dateThe magic is happening in the 'TGend' expression, which returns a date as string, such as "2021-11-26". You could then, in theory, have your Thanksgiving Lights rule active between November 1 and {{ TGend }}, with some judicious use of an added expression and/or conversion of that end date into epoch time (e.g. (number) 1637884800000) for mathematical purposes. Your call.
BED TIME NOW!
-
And geez, thanks for sending me down a huge rabbit hole. I'm back! I contemplated the reasonableness (you be the judge) of using an API of some kind to simply fetch the always-changing annual date of Thanksgiving. Turns out there are many such APIs, but they cost money, so I focused on the tried-and-true Google Calendars API since Google hosts a robust calendar of U.S. holidays which MSR can query.
Let's take a little stroll down the path I traveled lo these past couple of hours (again, thanks!):
STEP 1. Create an API app in Google developer account https://console.developers.google.com
STEP 2. From the "Credentials" tab, create an API key. You get something like this "AIzaSyBcOT_DpEQysiwFmmmZXupKpnrOdJYAhhM"
STEP 3. Then you can pull events from Google's holiday calendar using this URL -
https://www.googleapis.com/calendar/v3/calendars/en.usa%23holiday%40group.v.calendar.google.com/events?key=yourAPIKeySTEP 4. To retrieve only events called "Thanksgiving" -- there are 3 of them... last year, current year and next year -- one must insert a 'q=' modifier, so the URL we will use in MSR looks like -
https://www.googleapis.com/calendar/v3/calendars/en.usa%23holiday%40group.v.calendar.google.com/events?q=Thanksgiving&key=yourAPIKeySTEP 5. Create a new Rule in MSR which (I guess every January 1st) retrieves the next occurrence of Thanksgiving Day and stores that value into a blank expression. The Rule would have (at minimum) the following parts:
CONDITION = Date/Time set to execute on January 1st of each year
SET REACTION = An [HTTP] request that performs a [GET] on the URL from Step 4 and captures the response to expression [Events].
EXPRESSIONS =
'Events' := (blank)
'Items' := Events.items
'TGend' := T = first Occur in Items with (substr(Occur.end.date,0,4) == dateparts(time()).year), T.end.dateThe magic is happening in the 'TGend' expression, which returns a date as string, such as "2021-11-26". You could then, in theory, have your Thanksgiving Lights rule active between November 1 and {{ TGend }}, with some judicious use of an added expression and/or conversion of that end date into epoch time (e.g. (number) 1637884800000) for mathematical purposes. Your call.
BED TIME NOW!
@librasun Part of me tried, TRIED, to sympathize - but I just couldn't do it. I was poking at various iterations of this rule based off of reading and re-reading the manual and staring endlessly at the xmas rule (which is the opposite, it STARTS on the fourth Friday in November) during an incident bridge at work that did not require me or my team's attention any longer.
-
I've a scene for Arming for Xmas Season that works great, starting on Black Friday (Friday after fourth Thursday/Thanksgiving) and it uses
latch
to achieve the goal.Now I want to have DIFFERENT lighting for November 1 - Thanksgiving night, fourth Thu of November. So far I have:
I know that this will only end up with lights coming on ON the fourth Thu, not prior to it. Am I looking at
Output Control
orConstraints
to make my end date/time Thanksgiving night?Solved here: https://smarthome.community/post/10256
@gwp1 If you want it to end Thanksgiving night, that means you don't want the lights on starting with the 4th Friday (so on from the Nov-1 to the end of the day on the 4th Thursday).
Theory of operation:
The first date/time condition bounds the operating time of the entire thing. It can only be active in the month of November.
For the remainder, I'll work from the inside of the groups out...
The weekday condition obviously selects the 4th Friday of the month. It is set for latching (options), so when that weekday is encountered, it sticks. Because it's latching, it needs another condition partnered with it to tell it when to reset, and that is the purpose of the accompanying date/time condition in the group: it will be true throughout the end of the month, starting with the earliest possible day that a fourth Thursday could be. So when the end of the month rolls off and the date goes to the first of the month, that condition goes false and causes the interior group to go false, and the group going false causes the latch to be released on its child condition. In all, that means this interior group is true from the fourth Friday through the end of the month, and false otherwise.
Now, since we want the rule reset between that fourth Friday and the end of the month, we add a wrapper group with a NOT to invert the state of the interior group. Very important point here: you cannot take a shortcut and make the interior group NOT AND, because of the latched condition. You change the behavior of the group/latch relationship if you do that -- the latch relies on its parent group to go false to reset it, so you need to leave the logic state of that group unaltered to get correct latch and reset behavior for this solution. The wrapper group allows you to change (NOT) the inner group's state as needed for the rule without changing the interrmost group's native logic state.
Key takeaway: the parent group of a latched condition must be a pure AND group (cannot be NOT AND, OR, XOR, NUL).
-
@gwp1 If you want it to end Thanksgiving night, that means you don't want the lights on starting with the 4th Friday (so on from the Nov-1 to the end of the day on the 4th Thursday).
Theory of operation:
The first date/time condition bounds the operating time of the entire thing. It can only be active in the month of November.
For the remainder, I'll work from the inside of the groups out...
The weekday condition obviously selects the 4th Friday of the month. It is set for latching (options), so when that weekday is encountered, it sticks. Because it's latching, it needs another condition partnered with it to tell it when to reset, and that is the purpose of the accompanying date/time condition in the group: it will be true throughout the end of the month, starting with the earliest possible day that a fourth Thursday could be. So when the end of the month rolls off and the date goes to the first of the month, that condition goes false and causes the interior group to go false, and the group going false causes the latch to be released on its child condition. In all, that means this interior group is true from the fourth Friday through the end of the month, and false otherwise.
Now, since we want the rule reset between that fourth Friday and the end of the month, we add a wrapper group with a NOT to invert the state of the interior group. Very important point here: you cannot take a shortcut and make the interior group NOT AND, because of the latched condition. You change the behavior of the group/latch relationship if you do that -- the latch relies on its parent group to go false to reset it, so you need to leave the logic state of that group unaltered to get correct latch and reset behavior for this solution. The wrapper group allows you to change (NOT) the inner group's state as needed for the rule without changing the interrmost group's native logic state.
Key takeaway: the parent group of a latched condition must be a pure AND group (cannot be NOT AND, OR, XOR, NUL).
@toggledbits Ok, unpacking this in my head:
Topmost
trigger
, no brainer: eligible during November. My CDO wants to use the 29th as the end but I get it.The
inverting wrapper
- I'm kicking myself because I completely forgot aboutNOT
even though I've used it several times in various rulesets. Ten demerits for me.Here's where I'm slightly behind the curve -
detect and latch
. Talking aloud,weekday
is Friday. Ok, good. Thetrigger
grouped with it essentially says "eligible during this sub-range of that big ol' trigger range way up top".Got it.
Am I implementing the
latch
because there is a availability of multiple Friday's in that 22-EOMafter
range and latching the extra layer ofweekday
fourth
vs any Friday is what caps the grouped sub-range from going beyond that fourth Friday?Sidenote: when have you ever known me to take a shortcut - if anything, I go the waaaaay long way around lol
@LibraSun - no worries, I did give your method a shot and was successfully up to the point where my mental KB fails me: adding the
{{ TGend }}
expression into the ruleset.The last thing I want to review in my rulesets is to ensure everything tied to Thanksgiving is done/gone at midnight Friday so at sunset Friday the Xmas ruleset kicks in without any race states. I've been a master at creating those these past couple weeks....
Post-script: I did add one additional
trigger
at the top: sunset +10 to sunrise -15. -
@toggledbits Ok, unpacking this in my head:
Topmost
trigger
, no brainer: eligible during November. My CDO wants to use the 29th as the end but I get it.The
inverting wrapper
- I'm kicking myself because I completely forgot aboutNOT
even though I've used it several times in various rulesets. Ten demerits for me.Here's where I'm slightly behind the curve -
detect and latch
. Talking aloud,weekday
is Friday. Ok, good. Thetrigger
grouped with it essentially says "eligible during this sub-range of that big ol' trigger range way up top".Got it.
Am I implementing the
latch
because there is a availability of multiple Friday's in that 22-EOMafter
range and latching the extra layer ofweekday
fourth
vs any Friday is what caps the grouped sub-range from going beyond that fourth Friday?Sidenote: when have you ever known me to take a shortcut - if anything, I go the waaaaay long way around lol
@LibraSun - no worries, I did give your method a shot and was successfully up to the point where my mental KB fails me: adding the
{{ TGend }}
expression into the ruleset.The last thing I want to review in my rulesets is to ensure everything tied to Thanksgiving is done/gone at midnight Friday so at sunset Friday the Xmas ruleset kicks in without any race states. I've been a master at creating those these past couple weeks....
Post-script: I did add one additional
trigger
at the top: sunset +10 to sunrise -15.@gwp1 said in Lights on UNTIL fourth Thursday of the month:
Am I implementing the latch because there is a availability of multiple Friday's in that 22-EOM after range and latching the extra layer of weekday fourth vs any Friday is what caps the grouped sub-range from going beyond that fourth Friday?
No, you're using latch because 6 of 7 days of the week aren't Fridays, and as many as 8 days, including another Friday, or as few as 2 with no Friday, may follow the fourth Friday in November of any given year. So once we encounter the fourth Friday, we want to continue to hold that condition state on Saturday, Sunday, Monday, and every other day that may follow through the end of the month. The latch takes care of that easily.
I know @LibraSun is into expressions, so another possible solution is to use expressions to gin up the timestamp for midnight on the 22nd day of November (the earliest day of the month a fourth Friday could be) of the current year, and then get its day of the week. Knowing that Friday is weekday index 5, you can increment the date to figure out when the fourth Friday occurs. For example, if 11/22 is already weekday 5, you're on target and no offset is needed (that date is the fourth Friday). But if 11/22 is weekday 1 (Monday), you need to add 4 (days, 5-1) to the timestamp to get it to a Friday. I'll leave what to do if 11/22 is a Saturday (weekday index 6) as an exercise for the reader.
Once you've incremented the date, just compare it to the current time to see if you're on or before it.
-
T toggledbits locked this topic on