Door open sensor - Counting open duration


#1

I’m looking to create a piston that activates when a sensor is opened, counts the duration that it is open, and when the sensor closes it logs the information in a Google Spreadsheet.

I have the piston built including the ‘counting’ portion of it, but it doesn’t seem to be working properly. What happens right now is the @TimeOpened variable appears to be some sequential number between 1 and 10, never increasing beyond 10. If the door is held open for over 10 seconds, it resets back to 1.

I’m hoping that someone can show me another way to do this that would be much better/more efficient/reliable, or perhaps explain why my @TimeOpened integer keeps resetting back to 1.

-Edited for clarity

11/16/2019, 12:31:47 PM +250ms
+2ms ╔Received event [Front Door].contact = closed with a delay of 115ms
+8830ms ║RunTime Analysis CS > 121ms > PS > 8766ms > PE > 34ms > CE
+8831ms ║Piston waited at a semaphore for 8762ms
+8833ms ║Runtime (38290 bytes) successfully initialized in 8766ms (v0.3.110.20191009) (8830ms)
+8834ms ║╔Execution stage started
+8841ms ║║Comparison (enum) closed changes_to (string) open = false (0ms)
+8842ms ║║Cancelling condition #2's schedules...
+8843ms ║║Condition #2 evaluated false (5ms)
+8844ms ║║Cancelling condition #1's schedules...
+8845ms ║║Condition group #1 evaluated false (state changed) (6ms)
+8846ms ║╚Execution stage complete. (12ms)
+8847ms ╚Event processed successfully (8847ms)
11/16/2019, 12:31:45 PM +112ms
+0ms ╔Received event [Home].time = 1573936303459 with a delay of 1652ms
+737ms ║RunTime Analysis CS > 699ms > PS > 6ms > PE > 32ms > CE
+739ms ║Runtime (38209 bytes) successfully initialized in 6ms (v0.3.110.20191009) (738ms)
+740ms ║╔Execution stage started
+755ms ║║Calculating (integer) 0 + (integer) 1 >> (integer) 1
+757ms ║║Executed virtual command setVariable (1ms)
+766ms ║║Comparison (enum) open is (string) open = true (1ms)
+768ms ║║Condition #4 evaluated true (9ms)
+769ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+771ms ║║Cancelling statement #5's schedules...
+774ms ║║Executed virtual command wait (1ms)
+775ms ║║Waiting for 1000ms
+1780ms ║║Calculating (integer) 1 + (integer) 1 >> (integer) 2
+1784ms ║║Executed virtual command setVariable (1ms)
+1792ms ║║Comparison (enum) open is (string) open = true (2ms)
+1793ms ║║Condition #4 evaluated true (8ms)
+1794ms ║║Condition group #3 evaluated true (state did not change) (9ms)
+1796ms ║║Cancelling statement #5's schedules...
+1800ms ║║Executed virtual command wait (0ms)
+1800ms ║║Waiting for 1000ms
+2806ms ║║Calculating (integer) 2 + (integer) 1 >> (integer) 3
+2809ms ║║Executed virtual command setVariable (1ms)
+2816ms ║║Comparison (enum) closed is (string) open = false (1ms)
+2818ms ║║Cancelling condition #4's schedules...
+2819ms ║║Condition #4 evaluated false (8ms)
+2820ms ║║Cancelling condition #3's schedules...
+2821ms ║║Condition group #3 evaluated false (state changed) (11ms)
+2823ms ║║Cancelling statement #7's schedules...
+2913ms ║║Executed virtual command iftttMaker (86ms)
+2918ms ║╚Execution stage complete. (2178ms)
+2920ms ╚Event processed successfully (2920ms)
11/16/2019, 12:31:33 PM +93ms
+0ms ╔Received event [Home].time = 1573936291375 with a delay of 1717ms
+66ms ║RunTime Analysis CS > 37ms > PS > 5ms > PE > 25ms > CE
+69ms ║Runtime (38207 bytes) successfully initialized in 5ms (v0.3.110.20191009) (68ms)
+70ms ║╔Execution stage started
+87ms ║║Calculating (integer) 0 + (integer) 1 >> (integer) 1
+90ms ║║Executed virtual command setVariable (1ms)
+102ms ║║Comparison (enum) open is (string) open = true (2ms)
+104ms ║║Condition #4 evaluated true (12ms)
+105ms ║║Condition group #3 evaluated true (state did not change) (13ms)
+108ms ║║Cancelling statement #5's schedules...
+111ms ║║Executed virtual command wait (1ms)
+112ms ║║Waiting for 1000ms
+1119ms ║║Calculating (integer) 1 + (integer) 1 >> (integer) 2
+1122ms ║║Executed virtual command setVariable (1ms)
+1131ms ║║Comparison (enum) open is (string) open = true (2ms)
+1133ms ║║Condition #4 evaluated true (9ms)
+1134ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+1136ms ║║Cancelling statement #5's schedules...
+1140ms ║║Executed virtual command wait (0ms)
+1141ms ║║Waiting for 1000ms
+2146ms ║║Calculating (integer) 2 + (integer) 1 >> (integer) 3
+2151ms ║║Executed virtual command setVariable (3ms)
+2159ms ║║Comparison (enum) open is (string) open = true (2ms)
+2160ms ║║Condition #4 evaluated true (7ms)
+2161ms ║║Condition group #3 evaluated true (state did not change) (8ms)
+2165ms ║║Cancelling statement #5's schedules...
+2169ms ║║Executed virtual command wait (1ms)
+2170ms ║║Waiting for 1000ms
+3176ms ║║Calculating (integer) 3 + (integer) 1 >> (integer) 4
+3180ms ║║Executed virtual command setVariable (2ms)
+3188ms ║║Comparison (enum) open is (string) open = true (2ms)
+3189ms ║║Condition #4 evaluated true (7ms)
+3190ms ║║Condition group #3 evaluated true (state did not change) (9ms)
+3193ms ║║Cancelling statement #5's schedules...
+3196ms ║║Executed virtual command wait (1ms)
+3197ms ║║Waiting for 1000ms
+4203ms ║║Calculating (integer) 4 + (integer) 1 >> (integer) 5
+4206ms ║║Executed virtual command setVariable (1ms)
+4214ms ║║Comparison (enum) open is (string) open = true (1ms)
+4215ms ║║Condition #4 evaluated true (7ms)
+4216ms ║║Condition group #3 evaluated true (state did not change) (9ms)
+4218ms ║║Cancelling statement #5's schedules...
+4222ms ║║Executed virtual command wait (1ms)
+4223ms ║║Waiting for 1000ms
+5228ms ║║Calculating (integer) 5 + (integer) 1 >> (integer) 6
+5232ms ║║Executed virtual command setVariable (1ms)
+5241ms ║║Comparison (enum) open is (string) open = true (2ms)
+5243ms ║║Condition #4 evaluated true (9ms)
+5244ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+5246ms ║║Cancelling statement #5's schedules...
+5249ms ║║Executed virtual command wait (0ms)
+5250ms ║║Waiting for 1000ms
+6257ms ║║Calculating (integer) 6 + (integer) 1 >> (integer) 7
+6260ms ║║Executed virtual command setVariable (0ms)
+6269ms ║║Comparison (enum) open is (string) open = true (2ms)
+6270ms ║║Condition #4 evaluated true (9ms)
+6271ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+6274ms ║║Cancelling statement #5's schedules...
+6277ms ║║Executed virtual command wait (1ms)
+6278ms ║║Waiting for 1000ms
+7284ms ║║Calculating (integer) 7 + (integer) 1 >> (integer) 8
+7287ms ║║Executed virtual command setVariable (1ms)
+7296ms ║║Comparison (enum) open is (string) open = true (2ms)
+7297ms ║║Condition #4 evaluated true (8ms)
+7298ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+7300ms ║║Cancelling statement #5's schedules...
+7304ms ║║Executed virtual command wait (0ms)
+7305ms ║║Waiting for 1000ms
+8312ms ║║Calculating (integer) 8 + (integer) 1 >> (integer) 9
+8316ms ║║Executed virtual command setVariable (1ms)
+8327ms ║║Comparison (enum) open is (string) open = true (2ms)
+8328ms ║║Condition #4 evaluated true (11ms)
+8329ms ║║Condition group #3 evaluated true (state did not change) (12ms)
+8332ms ║║Cancelling statement #5's schedules...
+8335ms ║║Executed virtual command wait (1ms)
+8336ms ║║Waiting for 1000ms
+9342ms ║║Calculating (integer) 9 + (integer) 1 >> (integer) 10
+9345ms ║║Executed virtual command setVariable (1ms)
+9355ms ║║Comparison (enum) open is (string) open = true (2ms)
+9356ms ║║Condition #4 evaluated true (9ms)
+9358ms ║║Condition group #3 evaluated true (state did not change) (10ms)
+9360ms ║║Cancelling statement #5's schedules...
+9364ms ║║Executed virtual command wait (0ms)
+9365ms ║║Requesting a wake up for Sat, Nov 16 2019 @ 12:31:43 PM PST (in 1.0s)
+9370ms ║╚Execution stage complete. (9301ms)
+9371ms ║Setting up scheduled job for Sat, Nov 16 2019 @ 12:31:43 PM PST (in 1s)
+9381ms ╚Event processed successfully (9381ms)
11/16/2019, 12:31:20 PM +931ms
+2ms ╔Received event [Front Door].contact = open with a delay of 62ms
+58ms ║RunTime Analysis CS > 20ms > PS > 9ms > PE > 29ms > CE
+60ms ║Runtime (38214 bytes) successfully initialized in 9ms (v0.3.110.20191009) (57ms)
+61ms ║╔Execution stage started
+68ms ║║Comparison (enum) open changes_to (string) open = true (1ms)
+70ms ║║Cancelling condition #2's schedules...
+70ms ║║Condition #2 evaluated true (5ms)
+71ms ║║Cancelling condition #1's schedules...
+72ms ║║Condition group #1 evaluated true (state changed) (7ms)
+78ms ║║Comparison (enum) open is (string) open = true (2ms)
+79ms ║║Cancelling condition #4's schedules...
+80ms ║║Condition #4 evaluated true (6ms)
+81ms ║║Cancelling condition #3's schedules...
+82ms ║║Condition group #3 evaluated true (state changed) (8ms)
+84ms ║║Cancelling statement #5's schedules...
+87ms ║║Executed virtual command wait (0ms)
+88ms ║║Waiting for 1000ms
+1095ms ║║Calculating (integer) 0 + (integer) 1 >> (integer) 1
+1097ms ║║Executed virtual command setVariable (1ms)
+1103ms ║║Comparison (enum) open is (string) open = true (1ms)
+1104ms ║║Condition #4 evaluated true (5ms)
+1105ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+1107ms ║║Cancelling statement #5's schedules...
+1110ms ║║Executed virtual command wait (1ms)
+1111ms ║║Waiting for 1000ms
+2116ms ║║Calculating (integer) 1 + (integer) 1 >> (integer) 2
+2119ms ║║Executed virtual command setVariable (1ms)
+2124ms ║║Comparison (enum) open is (string) open = true (1ms)
+2126ms ║║Condition #4 evaluated true (4ms)
+2127ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+2129ms ║║Cancelling statement #5's schedules...
+2132ms ║║Executed virtual command wait (1ms)
+2133ms ║║Waiting for 1000ms
+3138ms ║║Calculating (integer) 2 + (integer) 1 >> (integer) 3
+3141ms ║║Executed virtual command setVariable (1ms)
+3147ms ║║Comparison (enum) open is (string) open = true (1ms)
+3148ms ║║Condition #4 evaluated true (5ms)
+3149ms ║║Condition group #3 evaluated true (state did not change) (7ms)
+3151ms ║║Cancelling statement #5's schedules...
+3155ms ║║Executed virtual command wait (0ms)
+3155ms ║║Waiting for 1000ms
+4161ms ║║Calculating (integer) 3 + (integer) 1 >> (integer) 4
+4164ms ║║Executed virtual command setVariable (1ms)
+4169ms ║║Comparison (enum) open is (string) open = true (1ms)
+4171ms ║║Condition #4 evaluated true (6ms)
+4172ms ║║Condition group #3 evaluated true (state did not change) (7ms)
+4174ms ║║Cancelling statement #5's schedules...
+4178ms ║║Executed virtual command wait (0ms)
+4179ms ║║Waiting for 1000ms
+5335ms ║║Calculating (integer) 4 + (integer) 1 >> (integer) 5
+5339ms ║║Executed virtual command setVariable (0ms)
+5345ms ║║Comparison (enum) open is (string) open = true (1ms)
+5347ms ║║Condition #4 evaluated true (6ms)
+5348ms ║║Condition group #3 evaluated true (state did not change) (7ms)
+5350ms ║║Cancelling statement #5's schedules...
+5353ms ║║Executed virtual command wait (0ms)
+5354ms ║║Waiting for 1000ms
+6359ms ║║Calculating (integer) 5 + (integer) 1 >> (integer) 6
+6362ms ║║Executed virtual command setVariable (1ms)
+6368ms ║║Comparison (enum) open is (string) open = true (1ms)
+6369ms ║║Condition #4 evaluated true (5ms)
+6370ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+6372ms ║║Cancelling statement #5's schedules...
+6375ms ║║Executed virtual command wait (0ms)
+6376ms ║║Waiting for 1000ms
+7381ms ║║Calculating (integer) 6 + (integer) 1 >> (integer) 7
+7384ms ║║Executed virtual command setVariable (1ms)
+7390ms ║║Comparison (enum) open is (string) open = true (2ms)
+7391ms ║║Condition #4 evaluated true (5ms)
+7392ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+7395ms ║║Cancelling statement #5's schedules...
+7398ms ║║Executed virtual command wait (0ms)
+7399ms ║║Waiting for 1000ms
+8404ms ║║Calculating (integer) 7 + (integer) 1 >> (integer) 8
+8406ms ║║Executed virtual command setVariable (1ms)
+8412ms ║║Comparison (enum) open is (string) open = true (2ms)
+8413ms ║║Condition #4 evaluated true (5ms)
+8414ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+8417ms ║║Cancelling statement #5's schedules...
+8420ms ║║Executed virtual command wait (0ms)
+8420ms ║║Waiting for 1000ms
+9426ms ║║Calculating (integer) 8 + (integer) 1 >> (integer) 9
+9428ms ║║Executed virtual command setVariable (1ms)
+9434ms ║║Comparison (enum) open is (string) open = true (2ms)
+9435ms ║║Condition #4 evaluated true (5ms)
+9436ms ║║Condition group #3 evaluated true (state did not change) (6ms)
+9438ms ║║Cancelling statement #5's schedules...
+9442ms ║║Executed virtual command wait (0ms)
+9443ms ║║Requesting a wake up for Sat, Nov 16 2019 @ 12:31:31 PM PST (in 1.0s)
+9447ms ║╚Execution stage complete. (9386ms)
+9448ms ║Setting up scheduled job for Sat, Nov 16 2019 @ 12:31:31 PM PST (in 1s)
+9456ms ╚Event processed successfully (9456ms)

#2

Try a simple loop that starts at 0 then wait 1 then add 1 to count.

Edit - then I looked at your piston code DOH!!!


#3

Thanks, I made some edits to my post to clarify what the actual problem is. I’m happy to hear that my idea of ‘wait 1 add 1’ isn’t a bad one!


#4

I try to avoid looping whenever possible. Here is the way I calculate how long I slept each night:

define
    time {doorOpened} = (no value set)
    decimal {openDuration} = (no value set)
    decimal {openDurationHours} = (no value set)
end define

execute
    IF Sensor's contact changes to open
    Then 
        Set variable {doorOpened} = $now
    END IF

    IF Sensor's contact changes to closed
    Then 
        Set variable {openDuration} = $now - doorOpened
        Set variable {openDurationHours} = round((openDuration / 3600000),1)
        Log to console = "Door was open for {openDurationHours} hours."
    END IF
end execute

{openDuration} will show the total number of milliseconds that have passed
{openDurationHours} will show the total hours that have passed (rounded to 1 decimal)

  • If you want to count seconds, then divide by 1,000
  • If you want to count minutes, then divide by 60,000
  • If you want to count hours, then divide by 3,600,000 (shown above)

Once you are happy with the base code, you can work on sending {openDurationHours} to your spreadsheet.


Edit:

@Master00Sniper found good results with openDuration set as “time” instead of “decimals” like I use.

For clarification:
The reason why I make {openDuration} either decimal or integer is because I have often encountered errors when doing division with a “time” variable… Because of this, I will usually convert time into a real number before I do complex math.

Your mileage may vary.


#5

Thanks for your suggestion, that seems like a much better way to do it. I believe it should be working, but I’m running into another issue I can’t seem to figure out. I think the 'Set variable {openDuration} = {$now - doorOpened} isn’t working. All my values for openDurationSeconds are huge and don’t make any sense. Does this look right to you?

Also, as I’m new to this, is there an easy way to test/troubleshoot these pistons? I have not figured out yet how to properly work the ‘test’ and ‘trace’ functions. I can’t seem to figure out a way to look up what the variables are at different stages throughout the piston after it ran.


#6

You are missing a set of parenthesis on the last “Set variable”. It should be an Expression:

round((openDuration / 1000),1)

pic


Open the contact sensor… wait a bit, then close it. The variables up top (in the define section) will show the last results.


Alternatively, you can “Log to console” any variable at any time throughout the process…

If you turn on Trace, and set Logging level to Full, you will get LOTS more info at the bottom.


#7

In this particular piston, one variable changes when the door opens, and the other two change when the door shuts.


#8

By the way, Test does nothing on this piston. The only trigger is when the contact changes.


#9

OK, so I made the adjustment and its still the same amount of weird output. But I did find this after more investigating:

Pic1

Pic2

AFAIK the previous doorOpen variable and the $now variable should be significantly closer in value than that. I’m still looking to see if I can figure out which one is wrong and why.

Edit: I think I got it fixed. Now I just need to figure out why it works lol. Will update soon.


#10

The first pic looks right… Here’s mine for reference:

pic


The second pic… openDuration 53,218,029 translates to:

  • 14.8 hours… or
  • 887 minutes… or
  • 53,218 seconds

#11

OK I got it working, here it is:

As far as I can tell, openDuration didn’t like being set to ($now - doorOpened) as a decimal. I don’t know why, but changing it to a time variable has fixed the issue.


#12

Strange… Mine is decimal, and works like a champ.

pic

(Yes, I did not get much sleep last night, LOL)

For those curious, 18,424,151 / 3,600,000 = 5.1… Not 4.9.
I have extra math to subtract 0.2 hours (12 minutes) that it takes me to fall asleep…


I am glad you got it working though…


#13

@WCmore if you believe the change from decimal to time is a correct solution, can you update it in your solution reply (the first reply you made) so it’s visible to anyone else searching for a similar setup.


#14

Sorry, I can only post what I have personally tested. Decimal works perfectly for me.


#15

No problem, thanks for you help! Much appreciated


#16

The good thing though, if anyone reads this, they will see both of our comments…

Once you are happy with your testing, please mark one of the helpful posts above as a Solution


#17

Marked your first reply as the solution, I’ll keep in mind subtracting the difference in a start and end time as the best solution for getting a duration of an event in the future. This works way better than counting up from 0.

Thanks again!


#18

Excellent!

The good thing about the above method is it only runs the piston once at each open, and once at each close. No loops or waits.


The trick with time based math is… any time of day can be read/write in many different formats. (IE: integer, decimal, string, time, dateTime, just to name a few) It really helps to dump into a variable (or log to console) to see what is happening beneath the hood…


Edit / Addendum / Pro Tip:
Storing as a variable (anything except “dynamic”) is also a great way to “force” the data to be stored in a specific format…


#19

Just to return to your original piston …

A wait of 1 second is normally implemented as a loop in the code and so contributes to the 20 second maximum execution time of the piston. However the piston likes to leave itself some leeway so when it comes to a wait with only ten seconds left it will instead schedule a wake up and exit. In a second it wakes up and starts a new execution, fast forwarding to the end of the wait.

The actual gotcha is the initial value on the TimeOpened variable, which as it warns you when you set it, is used every time the piston executes. So you see the piston count up to ten then start again from 0.

You would need to set the variable to 0 in the execute block. You’ve been given a much better approach though.