Help with sunset variable?


#1

1) Give a description of the problem
Sunset variable asks for a date

2) What is the expected behaviour?
I want to compare each day’s sunset to a static time to trigger a light for my chickens if the days are short

Really basic question here:

I’m trying to write a piston that triggers if sunset is before a preset time (8:00PM), to turn on the light in my chicken coop to lure them into the coop for bed and also to extend their “daylight” for egg production.

Here’s my expected workflow:

If: Sunset is before 8:00 PM
Then: turn on Chicken Coop Light at Sunset -60 min.
If: Chicken coop light is on at 10:00PM
Then: Turn off chicken coop light

However, when I set the comparison to “is before” with the $sunset variable, it inputs a date field into the value. I can’t leave the date blank, as it just populates today’s date.

Do I need to do anything to deal with this? I’m assuming if I let it populate today’s date, the comparison will become “If sunset is before 11/25/19 at 8:00 PM”, meaning it will never trigger.

Am I wrong here? How do I resolve this?


#2

I’m not sure what the type of sunset is but it might be date and time which is why it wants to compare to a date. I suggest creating a new time only variable and converting sunset to a time and then doing your comparison.


#3

I would store $sunset into a decimal variable first, then do your comparison based on that variable.

Something like this:

I left out “If Chicken coop light is on at 10PM” because webCoRE is smart enough to not send a command if the light is already off.


#4

Define a variable of type ‘Time’ and set it to the Preset value Sunset. Then create the ‘is before’ condition using that Variable and a Value. You’ll be asked for the Value as a time.


#5

Thanks for that explanation. I’m assuming the 3600000 math is because Webcore reports sunset to the millisecond. Is that right? Just wanting to make sure I understand your logic fully.

Just for the sake of learning, I created a piston using @orangebucket’s recommendation (Thanks for the suggestion). I figured it didn’t many any sense to recreate your piston myself since you shared the backup code.

Would this also work? Any flaws in the logic here? Assuming it will work, what are the advantages in converting the time to decimal like you did?

One other totally random question: Aside from the potential to become a convoluted mess, is there a drawback to putting multiple automations into a single piston? Assuming I only have 2-3 fairly simple automations, is there a reason not to build a single “chicken coop” piston rather than several different ones for each automation?

For example, is there a good reason not to add a notification automation in this piston for humidity levels from my aqara temp/humidity sensor?


#6

Correct. Diving by 3.6 million turns milliseconds into hours.


I often dump data (especially data involving time) into variables before making comparisons. This “forces” it to be written in a very specific way. (IE: $sunset looks very differently when written to a string, or an integer, or a time variable etc)

To see what I mean firsthand, you can run this piston once, and see nine different ways that $sunset appears inside webCoRE… (just press Test after importing)

(It was quite a surprise the first time I saw these results. Most people can only predict about 3 or 4 out of the 9 outcomes)

My logic is, once the data is stored in the exact format I want, then all future maths and comparisons becomes rock solid reliable.

Here is a snippet from the piston above showing $sunset written 4 different ways:

pic

(IE: math on a decimal is very different than math on a string)


If I was being completely honest, I would have to mention that both @orangebucket and myself gave the exact same answer in the previous two posts. The only difference is, I stored $sunset in a time variable inside the body of the code… He did the same in the definitions. It is personal preference really. Personally, I like leaving variables up top as (no value set) because this means I will always have access to the data as seen on the last run. This is immensely valuable to me, so I only force up top when the data rarely changes…


Whenever possible, I try to keep only one trigger (or less) in each piston.
(the lightning bolts in the left margin)

There are many reasons, but some main ones might include:

  • Less network traffic = More reliable executions
  • Less “thinking/processing” required on SmartThings end = More responsive SmartHome
  • Each trigger runs thru the entire piston top to bottom, and executes anything not blocked by conditions. This means that unrelated code is often processed at irrelevant times… Also, code often has to be written differently the moment a second trigger enters the piston.

Pro Tip:

One exception to my above “rule” is with “Every ()...” type commands… These only execute that one single block at the scheduled time… Because of this, I sometimes add a single “real” trigger to a piston with a couple of “Every’s” in place… (still keeping only one lightning bolt per piston, when possible)

In your case, I would say “Yes”, you can add the logic for humidity levels inside your “Every ()…” piston… I would not add any more triggers beyond that one though.


How to get timestamp (EPOCH)
What's wrong with my If/Then/Else?
#7

That makes good sense. I appreciate the comprehensive explanation.

Ah, another point I missed (and meant to ask about). When I imported your code I noticed the comment in the variable regarding an invalid date, but didn’t catch that your equation in the body completed the variable.

I did notice that you both addressed it in the same core way, which is part of why I wrote the piston using his suggestion. I wanted to make sure I understood the concept well enough to execute it myself for future knowledge. Now with your further explanation, I see that his way is simpler, but yours is ultimately more reliable and/or gives more info for analysis.

Thanks for this explanation. I figured there were good reasons not to do it this way, and even considered the third bullet point you mentioned, but didn’t consider the first two. In the specific example I mentioned, I want it to monitor continuously (or at least more frequently than once a day), so I’ll put it in it’s own piston.

I thought I understood what you mean by this, but I’m realizing I might have understood the exact opposite of what you meant, so I’d like to clarify.

Suppose we’re talking about changing white spectrum bulbs color according to time of day. If I understand correctly, you’re saying It’s okay to write a piston that says

“Every day at sunset (trigger), set (commands) bulb a to warm white and set bulb b to warm white and set bulb c to warm white and set bulb d to warm white.” (I recognize I could do this in one command, but split it into 4 commands for the sake of understanding the concept)

But I shouldn’t also include a 2nd trigger “Every day at sunrise” to issue commands to set the bulbs to daylight, or a “every day at 10PM set bulbs A, B, C, and D to 20% brightness” trigger.

Is that correct? In that scenario, I’d want to run a “daylight light temperature” piston, a “nighttime light temperature” piston, and a “nighttime brightness” piston?

Alternatively, the other way I realized I could interpret this is that it’s okay to say “Every day at 6AM” and “Every day at 9PM” with a single command “turn on my lamp”.

Can you clarify which scenario you meant? (or a third explanation that I totally missed).


#8

Perhaps the best way to summarize my internal thoughts:

I program with the intention of only one thing happeining at any given moment.
So it is totally OK to have multiple timed blocks in the same piston:

execute
    Every day at sunrise + 20 min, do X, END EVERY
    Every day at 5:30PM, do Y, END EVERY
    Every day at sunset - 20 min, do Z, END EVERY
end execute

Each one executes at it’s own unique time, and only executes that specific block. Essentially, “Every day at X” blocks are treated like mini independent pistons. (remember, we are talking about an exception to the rule here)


As to your other question… To allow for future growth, I would normally keep my humidity logic in a separate piston, but adding a single trigger to a piston like this is 99% harmless because:

  • a normal trigger will not execute code inside the “Every day at X” blocks
    and
  • the “Every day at X” block will not execute code outside of itself

Basically, it is one of the few exceptions where the code is not processed from top to bottom…
(well, technically a normal trigger does, but it won’t run code inside those timed blocks)

So it is a tight loophole, with restrictions, but yes, multiple “Every’s” and a single trigger is still treated as a single trigger piston.


Edit:

All that being said, I would personally recommend that you create a single piston for sunrise… and another piston for sunset… (with any offset you like)

My logic is, as your skills progress, those pistons will be “beefed” up quite a bit. They will become more complex & useful, (checking weather, doors etc) and you will want the “elbow-room” to code properly. (since each piston has a max size capacity of 100KB)

I actually have two pistons for sunset… One runs shortly before, and one a bit earlier…


#9

Okay, I think I’m getting it… So both of my examples were actually okay, as is my real world Chicken Coop situation, but I don’t want to run numerous things that are less static inside one piston. For example, I wouldn’t want to attempt to lump 2+ motion sensors triggering different lights in the same piston.

Right?


#10

I don’t often, but some do, and get away with it… Who am I to judge? LOL

I just know from (countless) occasions that the more chatter happening simultaneously, the more likely some commands / signals will get lost along the way… (and motion sensors are some of the “chattiest” devices).

I do my best to streamline in every step of the way so my SmartHome is not impacted negatively…

This is an extreme example, but I have literally seen a single poorly coded piston cripple an entire SmartHome until the power was pulled. (I admit, that was a bad loop though, not a motion sensor)


#11

That makes perfect sense. Thanks for taking the time to help me understand.


#12

I guess another way to think of it:

Keep in mind that subscribing to two motion sensors actually means that the entire piston will run top to bottom every time that:

  • SensorA’s motion changes to active… or
  • SensorA’s motion changes to inactive… or
  • SensorB’s motion changes to active… or
  • SensorB’s motion changes to inactive…

and anything outside an IF block, will execute at all 4 events.