Accessing previous value (or maybe I'm holding it wrong)


#1

I'm working on a rule that will control a virtual switch that represents the state of a washing machine based on a power monitoring plug. The base logic is essentially:

IF Power Level of Washer - Plug >= 25W for 1 minute THEN
    ON: Washer
ELSE IF Power Level of Washer - Plug < 25W for 2 minutes THEN
    OFF: Washer
END IF

Since I don't believe Rule Machine has a "stays true for duration' logical test I'm doing this via:

IF previousPower < 25 AND Power Level of Washer - Plug >= 25W THEN
    Cancel Delayed Actions
    Delay 1 minute (Cancel)
    ON: Washer
ELSE IF previousPower >= 25 AND Power Level of Washer - Plug < 25W THEN
    Cancel Delayed Actions
    Delay 2 minutes (Cancel)
    OFF: Washer
END IF
Set previousPower to Washer - Plug Power

Is there a better way beyond using local variables to track the previous state?


#2

Here is a RM3.0 rule that does this

going to be a little more complicated in RM4.0 because your trigger will need to be if power level changes. Which it will a lot. So that rule will run many time while the power is changing. Not horrible, but the RM3 is simple.


#3

You need to add Cancel to each of those delays.


#4

Sorry, they do have cancels in the actual rule, I was transcribing them from memory.

I remembered the issue I had is the the delay prevents capturing the previous value. I think I need to rewrite with two local variables so the top of the rule can look like:

Set realPrevValue to prevValue
Set prevValue to Washer - Plug Power
// Do compares on realPrevValue

#5

Delay 2 minutes Cancel

instead of what you have above.


#6

Right, I just edited the original post to add those (they are in the actual rule). The problem again is actually that I need two local variables otherwise the prevValue doesn't get captured until after the delay triggers.

Based on my original post the sequence looks like:

T0.0: Event: Washer - Plug Power 50W
T0.1: IF previousPower(0) < 25 AND Power of Washer - Plug (50) >= 25 (TRUE)
T0.2: Cancel Delayed Actions
T0.3: Delay 1 minute (Cancel)
    // T0 Rule execution is now delaying here

T1.0: Event: Washer - Plug Power 75W
T1.1: IF previousPower(0) < 25 AND Power of Washer - Plug (75) >= 25 (TRUE)
    // previousPower should be 50 here but the delay for the T0 event prevented capture
T1.2: Cancel Delayed Actions
T1.3: Delay 1 minute (Cancel)
    // T1 Rule execution is now delaying here

My fix of having two state variables works, it is just a bit clunky. Any chance RM could expose a pre-trigger value for attributes?

Fixed flow:

T0.0: Event: Washer - Plug Power 50W
T0.1: Set realPreviousPower(0) = previousPower(0)
T0.2: Set previousPower(0) = Power of Washer - Plug (50)
T0.3: IF realPreviousPower(0) < 25 AND Power of Washer - Plug (50) >= 25 (TRUE)
T0.4: Cancel Delayed Actions
T0.5: Delay 1 minute (Cancel)
    // T0 Rule execution is now delaying here

T1.0: Event: Washer - Plug Power 75W
T1.1: Set realPreviousPower(0) = previousPower(50)
T1.2: Set previousPower(50) = Power of Washer - Plug (75)
T1.3: IF realPreviousPower(50) < 25 AND Power of Washer - Plug (75) >= 25 (FALSE)
    // T1 doesn't cancel the existing "turning on" delay

Is there a better approach to do this time-delay change detection besides using two local variables?