Rule Triggering Itself

Hey All,
My kids have ADHD. And they're kids, lacking all concept of the passing of time. I decided I wanted to create a timer function for my kid bathroom lights. The idea is that the lights (and fan) blink off for 1s once for each 5 minutes of time passed since the lights came on. So at 10 mins into the shower, it should blink off for 1s, then on for 1s, then off 1s then on. Then at 15m, it would blink 3x. If the switch is used to turn off the lights, I want it to interrupt the whole thing and stop. Right now, for testing, I have the durations set shorter, so disregard the times. Here's my draft:


I'm getting stuck because the trigger is also the action in the blinking, so I think it's firing concurrent instances of the rule. I tried working around that with the local variable, but clearly it isn't working for me. Ultimately, the light just starts going berserk on and off, and I'm not getting the intended timer behavior. Any guidance?

I'm pasting some log below. At the start (bottom), you can see where I fire the first trigger. The local variable (alreadyrunning) was set to true because I had to interrupt the prior run. So that first trigger just evaluated to my else statement, set the alreadyrunning variable to false, cancelled repeated and scheduled actions, and ended. Then I fired the light a second time, and you see it just go nuts from there.

Here's my log:

Summary

app:5882025-10-10 02:20:00.399 PM

info

Action: END-REP (waiting for next)

app:5882025-10-10 02:20:00.380 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01

app:5882025-10-10 02:20:00.376 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on)

app:5882025-10-10 02:20:00.356 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:59.204 PM

info

Delay Over: Restore: Kid bath fan, Kid bath light

app:5882025-10-10 02:19:59.137 PM

info

Action: END-REP (waiting for next)

app:5882025-10-10 02:19:59.121 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01

app:5882025-10-10 02:19:59.100 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on)

app:5882025-10-10 02:19:59.083 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:58.035 PM

info

Delay Over: Restore: Kid bath fan, Kid bath light

app:5882025-10-10 02:19:57.984 PM

info

Action: END-REP (waiting for next)

app:5882025-10-10 02:19:57.969 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01

app:5882025-10-10 02:19:57.946 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on)

app:5882025-10-10 02:19:57.931 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:57.518 PM

info

Action: Delay 0:00:05 (cancelable)

app:5882025-10-10 02:19:57.506 PM

info

Action: Set Timer to 0

app:5882025-10-10 02:19:57.480 PM

info

Action: Set alreadyrunning to true

app:5882025-10-10 02:19:57.471 PM

info

Action: IF (Variable alreadyrunning(false) is = true FALSE) Exit Rule (skipped)

app:5882025-10-10 02:19:57.465 PM

info

Action: IF (Kid bath light(on) is on(T) [TRUE]) THEN

app:5882025-10-10 02:19:57.437 PM

info

Triggered: Kid bath light(on) turns changed

app:5882025-10-10 02:19:57.401 PM

info

Event: Kid bath light switch on

app:5882025-10-10 02:19:56.897 PM

info

Delay Over: Restore: Kid bath fan, Kid bath light

app:5882025-10-10 02:19:56.818 PM

info

Action: END-REP (waiting for next)

app:5882025-10-10 02:19:56.794 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01

app:5882025-10-10 02:19:56.790 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on)

app:5882025-10-10 02:19:56.769 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:56.369 PM

info

Action: Exit Rule

app:5882025-10-10 02:19:56.340 PM

info

Action: Cancel Delayed Actions

app:5882025-10-10 02:19:56.276 PM

info

Action: Stop Repeating Actions

app:5882025-10-10 02:19:56.264 PM

info

Action: Set alreadyrunning to false

app:5882025-10-10 02:19:56.252 PM

info

Action: ELSE (do actions)

app:5882025-10-10 02:19:56.249 PM

info

Action: END-REP (skipped)

app:5882025-10-10 02:19:56.246 PM

info

Action: END-REP (skipped)

app:5882025-10-10 02:19:56.243 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01 (skipped)

app:5882025-10-10 02:19:56.239 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on) (skipped)

app:5882025-10-10 02:19:56.234 PM

info

Action: Repeat Timer(1) times every 0:00:01 (skipped)

app:5882025-10-10 02:19:56.229 PM

info

Action: Notify Kris’s phone: 'Flashing %Timer% time(s)(Flashing 1 time(s))' (skipped)

app:5882025-10-10 02:19:56.223 PM

info

Action: Capture: Kid bath fan, Kid bath light (skipped)

app:5882025-10-10 02:19:56.219 PM

info

Action: Add 1 to Timer (skipped)

app:5882025-10-10 02:19:56.205 PM

info

Action: Repeat every 0:00:15 (stoppable) (skipped)

app:5882025-10-10 02:19:56.201 PM

info

Action: Delay 0:00:05 (cancelable) (skipped)

app:5882025-10-10 02:19:56.197 PM

info

Action: Set Timer to 0 (skipped)

app:5882025-10-10 02:19:56.185 PM

info

Action: Set alreadyrunning to true (skipped)

app:5882025-10-10 02:19:56.173 PM

info

Action: IF (Variable alreadyrunning(true) is = true TRUE) Exit Rule (skipped)

app:5882025-10-10 02:19:56.166 PM

info

Action: IF (Kid bath light(off) is on(F) [FALSE]) THEN (skipping)

app:5882025-10-10 02:19:56.134 PM

info

Triggered: Kid bath light(off) turns changed

app:5882025-10-10 02:19:56.095 PM

info

Event: Kid bath light switch off

app:5882025-10-10 02:19:55.783 PM

info

Action: END-REP (waiting for next)

app:5882025-10-10 02:19:55.763 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01

app:5882025-10-10 02:19:55.667 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on)

app:5882025-10-10 02:19:55.651 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:55.557 PM

info

Action: Notify Kris’s phone: 'Flashing %Timer% time(s)(Flashing 1 time(s))'

app:5882025-10-10 02:19:55.542 PM

info

Action: Capture: Kid bath fan, Kid bath light

app:5882025-10-10 02:19:55.532 PM

info

Action: Add 1 to Timer

app:5882025-10-10 02:19:55.512 PM

info

Action: Repeating Actions

app:5882025-10-10 02:19:55.422 PM

info

Delay Over: Delay 0:00:05 (cancelable)

app:5882025-10-10 02:19:50.387 PM

info

Action: Delay 0:00:05 (cancelable)

app:5882025-10-10 02:19:50.376 PM

info

Action: Set Timer to 0

app:5882025-10-10 02:19:50.353 PM

info

Action: Set alreadyrunning to true

app:5882025-10-10 02:19:50.344 PM

info

Action: IF (Variable alreadyrunning(false) is = true FALSE) Exit Rule (skipped)

app:5882025-10-10 02:19:50.332 PM

info

Action: IF (Kid bath light(on) is on(T) [TRUE]) THEN

app:5882025-10-10 02:19:50.305 PM

info

Triggered: Kid bath light(on) turns changed

app:5882025-10-10 02:19:50.230 PM

info

Event: Kid bath light switch on

app:5882025-10-10 02:19:43.176 PM

info

Action: Exit Rule

app:5882025-10-10 02:19:43.148 PM

info

Action: Cancel Delayed Actions

app:5882025-10-10 02:19:43.095 PM

info

Action: Stop Repeating Actions

app:5882025-10-10 02:19:43.084 PM

info

Action: Set alreadyrunning to false

app:5882025-10-10 02:19:43.076 PM

info

Action: ELSE (do actions)

app:5882025-10-10 02:19:43.074 PM

info

Action: END-REP (skipped)

app:5882025-10-10 02:19:43.072 PM

info

Action: END-REP (skipped)

app:5882025-10-10 02:19:43.068 PM

info

Action: Restore: Kid bath fan, Kid bath light --> delayed: 0:00:01 (skipped)

app:5882025-10-10 02:19:43.065 PM

info

Action: Off: Kid bath fan, Kid bath light (Command only switches that are on) (skipped)

app:5882025-10-10 02:19:43.062 PM

info

Action: Repeat Timer(1) times every 0:00:01 (skipped)

app:5882025-10-10 02:19:43.058 PM

info

Action: Notify Kris’s phone: 'Flashing %Timer% time(s)(Flashing 1 time(s))' (skipped)

app:5882025-10-10 02:19:43.054 PM

info

Action: Capture: Kid bath fan, Kid bath light (skipped)

app:5882025-10-10 02:19:43.051 PM

info

Action: Add 1 to Timer (skipped)

app:5882025-10-10 02:19:43.038 PM

info

Action: Repeat every 0:00:15 (stoppable) (skipped)

app:5882025-10-10 02:19:43.036 PM

info

Action: Delay 0:00:05 (cancelable) (skipped)

app:5882025-10-10 02:19:43.033 PM

info

Action: Set Timer to 0 (skipped)

app:5882025-10-10 02:19:43.024 PM

info

Action: Set alreadyrunning to true (skipped)

app:5882025-10-10 02:19:43.015 PM

info

Action: IF (Variable alreadyrunning(true) is = true TRUE) Exit Rule (skipped)

app:5882025-10-10 02:19:43.003 PM

info

Action: IF (Kid bath light(off) is on(F) [FALSE]) THEN (skipping)

app:5882025-10-10 02:19:42.973 PM

info

Triggered: Kid bath light(off) turns changed

app:5882025-10-10 02:19:42.943 PM

info

Event: Kid bath light switch off

app:5882025-10-10 02:18:44.122 PM

info

Action: Exit Rule

app:5882025-10-10 02:18:44.110 PM

info

Action: IF (Kid bath light(on) is on(T) [TRUE]) THEN

app:5882025-10-10 02:18:44.027 PM

info

Triggered: Kid bath light(on) turns changed

app:5882025-10-10 02:18:43.989 PM

info

Event: Kid bath light switch on

I should have noted: the switches are hooked up to a zooz zen52 double relay

This would be easier with a dimmer, as ON can trigger the timer to start, but the signal could be a dim and brighten instead of a blink. You can't use the same attribute (switch) as both the trigger and the action without causing a retrigger like you are seeing. Set Level would not retrigger the rule based on ON.

Or use a different device as the signal, like another light or a smart speaker device. Or use a different device like a smart button to turn on the light and start the timers, and base your blink times on when the button was first pushed, not the light switch state.

Another option is to use the isPhysical flag to determine if the light was turned on or off at the switch physically, or digitally by an automation. Only a physical ON starts your blink timer, and only a physical off stops it. The digital on/off events from the blink would not retrigger the rule.

Edit: I don't use Rule Machine, but it looks like in RM you determine a physical On vs a digital On based on if you choose Physical Switch or Digital switch in the rule. I've never played with that in RM though, but in Webcore there is a choice to see if the event isPhysical to make that determination.

1 Like

You could avoid this by wrapping the actions in a Private Boolean. Set the PB to be False as the first action of the Rule, and set it to be True as the last action. Finally, require the PB to be true for the rule to trigger.

The Rule Machine documentation has more information on how to use a Private Boolean.

Also, for future reference, just post a screenshot of logs rather than the log text itself. Screenshots are way easier to read .....

5 Likes

And if really long, wrap that in a Summary. Easier for those on phones. Select item(s), then select the gear, then Hide Details.

Summary

This text will be hidden

3 Likes

Seems like triggering the rule from the physical ON event would be easier, as the blinking will only be digital and not retrigger. No real need for a boolean to be involved here.

1 Like

Thanks! I did the summary

1 Like

You're kind. I just turn the lights out and leave them in the dark :slight_smile:

2 Likes

You have found what I found. RM echos trigger events about 250ish ms later. Make your trigger conditional on a Private bullion then the first action is to disable the trigger and the last action is to enable it. Another way is to wait at the start until say a half second elapses without another trigger wait period event then proceed.