Maintain a dim setting between certain hours


#1

Hello All,

Been around ST for awhile and found the need to get into a Rule engine. I have coding background (.NET, VB, etc.); however, I’m having a learning curve here in regards to the behaviour of a piston.

1) Give a description of the problem
I have lights under my kitchen cabinets controlled through a Leviton Decora ZWave Plus switch. I have a DTH for it which provides multiple states for consumption. I want the lights to come on (if they weren’t on already) by 11p everyday and held to 10% brightness. When I test the piston, it works properly, but automatically it does not work. In addition, the way I’m interpreting how I wrote the code, if someone were to adjust the dimmer, it shouldn’t allow it and hold the brightness to what I have set it to in the piston. This is not happening. In addition, if someone were to turn the lights off or adjust the brightness, the piston doesn’t seem to reverse the change.

2) What is the expected behavior?
See #1; in addition, I’d like the lights to turn off @ 7a each day (the If nest at the end of the piston)

3) What is happening/not happening?
See #1

**4) Post a Green Snapshot of the piston!

5) Attach any logs (From ST IDE and by turning logging level to Full)

24/11/2018, 06:59:59 +110ms
+1ms ╔Received event [Home].time = 1543060800000 with a delay of -891ms
+201ms ║RunTime Analysis CS > 51ms > PS > 103ms > PE > 48ms > CE
+205ms ║Runtime (37197 bytes) successfully initialized in 103ms (v0.3.108.20180906) (200ms)
+207ms ║╔Execution stage started
+246ms ║║Comparison (time) 25199331 is_between (time) 82800000 .. (time) 25200000 = false (20ms)
+250ms ║║Cancelling condition #11's schedules...
+253ms ║║Condition #11 evaluated false (32ms)
+255ms ║║Cancelling statement #11's schedules...
+268ms ║║Requesting time schedule wake up at Sat, Nov 24 2018 @ 11:00:00 PM EST
+274ms ║║Cancelling condition #10's schedules...
+276ms ║║Condition group #10 evaluated false (state changed) (56ms)
+301ms ║║Comparison (time) 25199393 is_after (time) 25200000 = true (14ms)
+304ms ║║Time restriction check passed
+308ms ║║Cancelling condition #4's schedules...
+310ms ║║Condition #4 evaluated true (27ms)
+313ms ║║Cancelling statement #4's schedules...
+322ms ║║Requesting time schedule wake up at Sun, Nov 25 2018 @ 12:00:00 AM EST
+329ms ║║Cancelling condition #3's schedules...
+331ms ║║Condition group #3 evaluated true (state changed) (49ms)
+338ms ║║Cancelling statement #5's schedules...
+12725ms ║║Executed physical command [Under Cabinet Lights].off() (12377ms)
+12726ms ║║Executed [Under Cabinet Lights].off (12381ms)
+12730ms ║╚Execution stage complete. (12524ms)
+12733ms ║Setting up scheduled job for Sat, Nov 24 2018 @ 11:00:00 PM EST (in 57588.158s), with 1 more job pending
+12743ms ╚Event processed successfully (12743ms)

I’m having difficulty understanding how the piston executes. Is it constantly based on the timeframe I’ve coded? Or does it always need an event to trigger?

Appreciate the help and guidance!


#2

The easiest way you can do this is:

IF
Time happens daily at 11pm
OR
Time is between 11pm and 7am
With xxx Lights
Set level to 10%

IF time happens daily at 7am
With xxx Lights
Turn off

The ‘while’ loop is not necessary because your pistons if you make your piston ‘subscribe’ to your lights. That means every time you lights change (level or switch) it will trigger your piston to run. If the time is between 11pm and 7am and someone adjust the lights, your piston will force it back to 10%. If you want to ensure nobody can turn it on between 7am and 11pm, just add a line to the 2nd IF block…
OR
Time is between 7am and 11pm.

To make your piston subscribe to your lights, when you’re making the DO/WITH block of your piston, click on the lights and then on the far right of your screen you’ll see Subscription - you can set to Always, Auto, or Never. In this case, switch it to Auto.

To confirm this worked, after you save your piston and you’re in VIEW mode (not edit mode), you’ll see a little orange lightning bolt next to the device you subscribed to:

image

Hope this helps!


#3

Hi michicago,

Thanks for the quick reply. I should of shared, I originally had the piston with an IF block nest instead of the while. I was thinking ‘while’ might be more persistent.

I think I see what you’re saying on the subscription; that links the piston to the device and any event will re-trigger the execution of the piston?

I know I did not ‘set’ the piston to the device, but I do have the lightning bolt. Not sure what that means then.

I’ll give this a shot and report back - thanks!


#4

Glad to help!

Exactly right. You gain nothing from the ‘while’ loop except the additional debug headaches that will come with it, lol.

The only time I’ve used a While loop in webCoRE is when I need to repeat commands to a stubborn device. For example, when I leave the house, while the garage door is open, send ‘close door’ commands.

You don’t need to use while loops to check conditions of a device - thankfully that’s all built into the system.


#5

Ah, thanks for explaining the use on ‘while’.

I see what is different; what is the necessity to start with ‘time happens daily at #’ with ‘time between x & y’? Why isn’t ‘time between x & y’ functional on it’s own? That is how I had it before.


#6

I must be missing something still. I restructured the piston like you suggested; however, there isn’t subscription parameter on the device when it resides in the ‘with’ nest. It looks like you can only subscribe to devices within the conditional statement in the ‘If’ nest. Thoughts?


#7

That’s quite draconian lol

There are people who cannot see well in the dark, or in dim light.
Such pistons might be better served to put time limits on usage, or to allow the light to be however the user set it until a motion sensor indicates no motion in that area - and then to return it to the “officially approved” level.

That said, it’s not my home so you get to write it how you wish.


#8

That worked because it the piston would subscribe to Time, making itself trigger at 11pm. Once you add a subscribed physical device, the subscription to ‘Time’ will go away (you won’t see that telltale orange lightning bolt after you save the piston). Forcing a subscription to Time negated the need for the “If Time Happens Daily at 11pm” trigger.

This piston, odd as it may seem, will do what you want. Time will control the light in the upper IF block, and although the 2nd IF block contains no actions, it will make your piston run from the top to the bottom every time your lights change.


#9

Hahaha, I was waiting for someone to comment like this as I came across other people looking to control lights and comments of the same. For clarification, these are just the lights under the cabinets. No need to brighten them up late at night (i.e. kids and the wife lol). There are 3 other lights they can use instead (over the counter lights, the sink light, the main kitchen are light).

I should add, I will probably allow a brightness setting change for like 5 mins or so. Just want to start with the lock down so I can understand how to do this properly.


#10

How does the if statement at the end of the piston, the one you mocked up, make the piston re-run from the top? That confuses the heck out of me lol


#11

I added the If statement on trigger of switch or level - still doesn’t work. I tried both ‘and’ and ‘or’ between the 2, neither helped.

Here is what happens when the switch is pressed on or off or the dimmer button on the switch from ST logging:

44345b89-3477-4509-b753-840ae1ed815f  14:00:33: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]
44345b89-3477-4509-b753-840ae1ed815f  14:00:18: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]
44345b89-3477-4509-b753-840ae1ed815f  14:00:16: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]
44345b89-3477-4509-b753-840ae1ed815f  14:00:14: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]
44345b89-3477-4509-b753-840ae1ed815f  14:00:09: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]
44345b89-3477-4509-b753-840ae1ed815f  13:59:58: debug Parsed Hail() to [name:hail, value:hail, descriptionText:Switch button was pressed, displayed:false, isStateChange:false, linkText:Under Cabinet Lights]

#12

lol, part of the reason I put it there - it’s completely counter-intuitive but once you understand it, you can anticipate a pistons activities better.

By subscribing to a device (in this case a light’s switch and level) the piston will run every time the device reports a change in its switch or level. When a piston runs, it ALWAYS runs from the top down. So in this case, the last “IF” statement is only there so the piston will run when a change is detected in the light. You could do it with a bunch of nested AND/OR combinations too, but despite it looking odd, this is the most efficient way.


#13

Can you try again with Full logging enabled in webCoRE? Go to the VIEW screen for your piston, scroll to the bottom, and turn it on there:


#14

Interesting; I see what you mean on counter intuitive but I understand the trick! Thanks!


#15

No problem, I have logging already on and at full. Here was the last run I tried:

25/11/2018, 13:56:55 +239ms
+1ms	╔Starting piston... (v0.3.108.20180906)
+987ms	║╔Subscribing to devices...
+1020ms	║║Subscribing to Under Cabinet Lights.switch...
+1044ms	║║Subscribing to Under Cabinet Lights.level...
+1116ms	║╚Finished subscribing (146ms)
+1182ms	║Comparison (time) 50216390 is_between (time) 49920000 .. (time) 25200000 = true (26ms)
+1186ms	║Time restriction check passed
+1191ms	║Cancelling statement #9's schedules...
+1207ms	║Requesting time schedule wake up at Mon, Nov 26 2018 @ 7:00:00 AM EST
+1234ms	║Comparison (time) 50216466 happens_daily_at (time) 25200000 = false (1ms)
+1239ms	║Cancelling statement #4's schedules...
+1249ms	║Requesting time schedule wake up at Mon, Nov 26 2018 @ 7:00:00 AM EST
+1283ms	║Setting up scheduled job for Mon, Nov 26 2018 @ 7:00:00 AM EST (in 61383.48s), with 1 more job pending
+1312ms	╚Piston successfully started (1311ms)

#16

Here is the log when I run ‘test’ on the piston:

25/11/2018, 14:11:13 +217ms
+1ms ╔Received event [Home].test = 1543173073216 with a delay of 0ms
+105ms ║RunTime Analysis CS > 21ms > PS > 60ms > PE > 24ms > CE
+108ms ║Runtime (38396 bytes) successfully initialized in 60ms (v0.3.108.20180906) (105ms)
+109ms ║╔Execution stage started
+134ms ║║Comparison (time) 51073334 is_between (time) 49920000 .. (time) 25200000 = true (14ms)
+136ms ║║Time restriction check passed
+139ms ║║Condition #9 evaluated true (21ms)
+143ms ║║Cancelling statement #9's schedules...
+152ms ║║Requesting time schedule wake up at Mon, Nov 26 2018 @ 7:00:00 AM EST
+157ms ║║Condition group #7 evaluated true (state did not change) (41ms)
+161ms ║║Cancelling statement #10's schedules...
+333ms ║║Executed physical command [Under Cabinet Lights].on() (167ms)
+335ms ║║Executed [Under Cabinet Lights].on (169ms)
+380ms ║║Executed physical command [Under Cabinet Lights].setLevel([10]) (39ms)
+381ms ║║Executed [Under Cabinet Lights].setLevel (42ms)
+392ms ║║Comparison (time) 51073605 happens_daily_at (time) 25200000 = false (1ms)
+395ms ║║Condition #4 evaluated false (6ms)
+400ms ║║Cancelling statement #4's schedules...
+406ms ║║Requesting time schedule wake up at Mon, Nov 26 2018 @ 7:00:00 AM EST
+411ms ║║Condition group #3 evaluated false (state did not change) (23ms)
+421ms ║║Condition #14 evaluated false (6ms)
+428ms ║║Condition #15 evaluated false (5ms)
+430ms ║║Condition group #13 evaluated false (state did not change) (14ms)
+448ms ║╚Execution stage complete. (339ms)
+453ms ║Setting up scheduled job for Mon, Nov 26 2018 @ 7:00:00 AM EST (in 60526.331s), with 1 more job pending
+464ms ╚Event processed successfully (464ms)

#17

From that log it looks like it turned your under cabinet lights on when you tested the piston. Is that what you wanted it to do?

Can you post a green snapshot of the piston you have now? Seems odd the next programmed trigger time is 7am tomorrow, not 11pm tonight.


#18

I changed the time to turn on at 1:52p so I could test it fully. 7am is when it will shut off. With them on at this new time, I still can turn them off and adjust the brightness.


#19

It’d be easier if you used the conditions I did above - just use one “time is between” then either set the lights to 10% or off.

If you adjust the lights now, it doesn’t set them to 10%? Can you post a log when the trigger to the piston is SWITCH or LEVEL, rather than test?


#20

If there’s one thing this home automation process has taught me, it is that despite our well-conceived automations, our co-habitants will not be automatons. That is, they will do as they wish rather than behave according to the way we’ve programmed the house.

Our automations must account for that. If the wife wants to turn up the intensity of the under-cabinet lights for whatever she wants to do at any time, who am I to say “that is not how I programmed it so you can’t do it”??

That said, your approach is correct. Figure out how to get to where you want it to be, then let the other users of the house show you where it needs to be modified… and then figure out the ways to accommodate those while still hitting your target.