Location Mode not switching to Away after 4 hour wait


#1

1) Give a description of the problem
I use a virtual switch that is tied to each family member’s iPhone presence sensor. The piston is invoked whenever one of the virtual switches is activated (ON=Home; OFF=Away from Home). I use the virtual switches so I can easily see in the new Smartthings app if family members are home or not since the new app doesn’t show you the presence sensor status. Anyway, when all household members presence virtual switches are OFF, a 4-hour wait period is invoked as I do not want to adjust thermostats up and down with people coming and gong all day. After the 4-hour wait period, Location mode is set to Away and thermostats are adjusted down. A global variable called @locationMode is used as a proxy for testing Location Mode. A second global variable called @previousLocationMode is used to record the previous Location Mode. These variables are set according to this new status. The problem is, the global variable @locationMode is not being set to Away. The thermostats are adjusted though, which is odd (why did it skip the set variable @locationMode command but executed the Good Bye scenes for the thermostat?). Upon someone returning home, the piston checks the @ocationMode variable before invoking scenes to reset thermostats upward–No sense resetting thermostats if @locationMode remained Home (people not gone for more than 4 hours) and thermostats were never adjusted down? However, in my case, thermostats were adjusted down. So now because @locationMode stayed in Home, the thermostats are not adjusted back up when someone arrives home and the house stays chilly.

2) What is the expected behaviour?
@locationMode should store Away after a 4 hour wait with all family members away from home for 4 hours.

3) What is happening/not happening?
@locationMode is retaining value ‘Home’. Referring to logs, last person leaves home at 8:33 am. Piston enters a 4-hour wait period. At 12:33 pm, the piston wakes up, says it’s adjusting the location mode and turns the thermostats down. I know the thermostats went down because I checked them on my app while I was at work. At 1:17 pm, my wife returns home and the piston registers false for both @locationMode = ‘Away’ or @locationMode = ‘Extended Absence’ (+238 ms to +246 ms). The thermostats are never adjusted back to daytime heating because it thinks nobody was gone for more than 4 hours.

**4) Post a Green Snapshot of the piston![image|45x37]

5) Attach logs after turning logging level to Full

10/23/2020, 1:17:05 PM +76ms
+1ms ╔Received event [Barb's iPhone Flag].switch = on with a delay of 47ms
+200ms ║RunTime Analysis CS > 14ms > PS > 100ms > PE > 86ms > CE
+204ms ║Runtime (73088 bytes) successfully initialized in 100ms (v0.3.10e.20190628) (202ms)
+205ms ║╔Execution stage started
+219ms ║║Comparison (enum) off is (string) off = true (1ms)
+221ms ║║Condition #72 evaluated true (9ms)
+226ms ║║Comparison (enum) on is (string) off = false (1ms)
+228ms ║║Cancelling condition #73's schedules...
+229ms ║║Condition #73 evaluated false (7ms)
+230ms ║║Cancelling condition #71's schedules...
+231ms ║║Condition group #71 evaluated false (state changed) (20ms)
+238ms ║║Comparison (dynamic) Home is (string) Away = false (1ms)
+239ms ║║Condition #83 evaluated false (5ms)
+244ms ║║Comparison (dynamic) Home is (string) Away-Extended Absence = false (2ms)
+246ms ║║Condition #84 evaluated false (5ms)
+247ms ║║Condition group #82 evaluated false (state did not change) (13ms)
+248ms ║║Condition group #81 evaluated false (state did not change) (15ms)
+259ms ║║Comparison (enum) off is (string) off = true (1ms)
+261ms ║║Condition #86 evaluated true (10ms)
+262ms ║║Condition group #85 evaluated true (state did not change) (12ms)
+265ms ║║Cancelling statement #92's schedules...
+267ms ║║Executed virtual command cancelTasks (1ms)
+309ms ║║Executed virtual command setLocationMode (38ms)
+313ms ║║Executed virtual command setVariable (2ms)
+317ms ║║Executed virtual command setVariable (1ms)
+331ms ║╚Execution stage complete. (126ms)
+332ms ╚Event processed successfully (332ms)
10/23/2020, 12:33:47 PM +919ms
+0ms ╔Received event [Home].:6ef6def0f2e8b366d3dc83a1ef0d3eca: = @locationMode with a delay of 51ms
+195ms ║RunTime Analysis CS > 15ms > PS > 100ms > PE > 81ms > CE
+199ms ║Runtime (73113 bytes) successfully initialized in 100ms (v0.3.10e.20190628) (198ms)
+200ms ║╔Execution stage started
+205ms ║╚Execution stage complete. (5ms)
+207ms ║Setting up scheduled job for Sat, Oct 24 2020 @ 8:33:47 AM EDT (in 71999.677s)
+216ms ╚Event processed successfully (216ms)
10/23/2020, 12:33:46 PM +210ms
+0ms ╔Received event [Home].time = 1603470827069 with a delay of -859ms
+213ms ║RunTime Analysis CS > 19ms > PS > 110ms > PE > 84ms > CE
+217ms ║Runtime (73085 bytes) successfully initialized in 110ms (v0.3.10e.20190628) (216ms)
+218ms ║╔Execution stage started
+539ms ║║Executed virtual command setLocationMode (289ms)
+544ms ║║Executed virtual command setVariable (1ms)
+548ms ║║Executed virtual command setVariable (1ms)
+562ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/ + (string) b792c8bf-c675-4379-9c39-f4ff1b78d6e0 >> (string) https://api.smartthings.com/v1/scenes/b792c8bf-c675-4379-9c39-f4ff1b78d6e0
+565ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/b792c8bf-c675-4379-9c39-f4ff1b78d6e0 + (string) /execute >> (string) https://api.smartthings.com/v1/scenes/b792c8bf-c675-4379-9c39-f4ff1b78d6e0/execute
+574ms ║║Calculating (string) Bearer + (string) 5d1320f9-1cd2-4f9d-918c-1e0639f5935a >> (string) Bearer 5d1320f9-1cd2-4f9d-918c-1e0639f5935a
+577ms ║║Sending external web request to: api.smartthings.com/v1/scenes/b792c8bf-c675-4379-9c39-f4ff1b78d6e0/execute
+931ms ║║Executed virtual command httpRequest (354ms)
+938ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/ + (string) b136f458-63d0-4613-8efb-e09b93ca81b4 >> (string) https://api.smartthings.com/v1/scenes/b136f458-63d0-4613-8efb-e09b93ca81b4
+940ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/b136f458-63d0-4613-8efb-e09b93ca81b4 + (string) /execute >> (string) https://api.smartthings.com/v1/scenes/b136f458-63d0-4613-8efb-e09b93ca81b4/execute
+950ms ║║Calculating (string) Bearer + (string) 5d1320f9-1cd2-4f9d-918c-1e0639f5935a >> (string) Bearer 5d1320f9-1cd2-4f9d-918c-1e0639f5935a
+953ms ║║Sending external web request to: api.smartthings.com/v1/scenes/b136f458-63d0-4613-8efb-e09b93ca81b4/execute
+1274ms ║║Executed virtual command httpRequest (321ms)
+1279ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/ + (string) cddafe98-0d24-49c8-9cb5-79fb65b3d288 >> (string) https://api.smartthings.com/v1/scenes/cddafe98-0d24-49c8-9cb5-79fb65b3d288
+1282ms ║║Calculating (string) https://api.smartthings.com/v1/scenes/cddafe98-0d24-49c8-9cb5-79fb65b3d288 + (string) /execute >> (string) https://api.smartthings.com/v1/scenes/cddafe98-0d24-49c8-9cb5-79fb65b3d288/execute
+1292ms ║║Calculating (string) Bearer + (string) 5d1320f9-1cd2-4f9d-918c-1e0639f5935a >> (string) Bearer 5d1320f9-1cd2-4f9d-918c-1e0639f5935a
+1294ms ║║Sending external web request to: api.smartthings.com/v1/scenes/cddafe98-0d24-49c8-9cb5-79fb65b3d288/execute
+1585ms ║║Executed virtual command httpRequest (292ms)
+1590ms ║║Executed virtual command wait (1ms)
+1591ms ║║Requesting a wake up for Sat, Oct 24 2020 @ 8:33:47 AM EDT (in 72000.0s)
+1596ms ║╚Execution stage complete. (1378ms)
+1597ms ║Setting up scheduled job for Sat, Oct 24 2020 @ 8:33:47 AM EDT (in 71999.995s)
+1605ms ╚Event processed successfully (1604ms)
10/23/2020, 8:33:46 AM +806ms
+1ms ╔Received event [Matt's iPhone Flag].switch = off with a delay of 56ms
+218ms ║RunTime Analysis CS > 23ms > PS > 119ms > PE > 76ms > CE
+222ms ║Runtime (73090 bytes) successfully initialized in 119ms (v0.3.10e.20190628) (220ms)
+223ms ║╔Execution stage started
+232ms ║║Comparison (enum) off is (string) off = true (1ms)
+235ms ║║Cancelling condition #72's schedules...
+235ms ║║Condition #72 evaluated true (6ms)
+243ms ║║Comparison (enum) off is (string) off = true (1ms)
+245ms ║║Condition #73 evaluated true (8ms)
+252ms ║║Comparison (enum) off is (string) off = true (1ms)
+253ms ║║Condition #74 evaluated true (8ms)
+255ms ║║Cancelling condition #71's schedules...
+256ms ║║Condition group #71 evaluated true (state changed) (27ms)
+258ms ║║Cancelling statement #75's schedules...
+261ms ║║Executed virtual command wait (0ms)
+262ms ║║Requesting a wake up for Fri, Oct 23 2020 @ 12:33:47 PM EDT (in 14400.0s)
+270ms ║╚Execution stage complete. (47ms)
+271ms ║Setting up scheduled job for Fri, Oct 23 2020 @ 12:33:47 PM EDT (in 14399.992s)
+277ms ╚Event processed successfully (276ms)

.


#2

The log shows this happening, but that action causes another immediate trigger, which starts the piston all over at the top.

12:33:46 = 4 hr timer up = Set @locationMode… which won’t happen until the 20 hour timer starts
12:33:47 = @locationMode changed, so piston started all over at the top

Normally, it is a good habit to avoid this logic:

IF something happens
    Then change @global
END IF

IF @global changes
    Then change @global
END IF

I would also take a closer look at:
[Home].:6ef6def0f2e8b366d3dc83a1ef0d3eca: = @locationMode


#3

I’m not sure I follow your logic when you say the Set @locationMode won’t happen until the 20 hour timer starts. Shouldn’t it happen as soon as the statement is run at 12:33:46 PM +548 ms?


#4

Normally, @global variables are not set until the very last line of code has executed…
(regardless of where that command is placed in the piston)

An exception to this rule is when there is a WAIT over 10 seconds…

So in your case:

  • Lines 48 & 49 is set after line 52 executes…
  • Lines 55, 56, 75, 76, 90, 91, 95 & 96 is set after the entire piston completes
    (although if your POST has a delay, it might set early, but I would not rely on that)

If you need a variable to be accessible immediately (on the next line), then I would recommend using local variables for that. (you can always dump it into a @global at the very end, if needed in another piston)


#5

Reposting for emphasis:

When programming our SmartHome, it is a good habit to avoid this logic

IF something happens
    Then change X
END IF

IF X changes
    Then change X
END IF

Normally, we do not want a piston to control (and be controlled by) the same attribute.
(trigger or command… pick one or the other)

IE: If the piston changes X, then it should not trigger off of a change to X.
Likewise, if the piston triggers when X changes, then no command should change X.

Otherwise, it is potentially like turning a video camera towards a live monitor…