Setting modes based on time of day and presence



Condensed and efficient way of switching between modes based on time of day and presence.

Add as many presence sensors / lights as you wish in the variables.

Change the time of day for each mode threshold in the variables.

Modes are:

  • Sleep
  • Home - Dawn
  • Home - Day
  • Home - Evening
  • Home - Night
  • Away - Dawn
  • Away - Day
  • Away - Night

Edit: Worked around a bug, had to change <= to < as webCoRE was ignoring the 20 second differential, incorrectly calculating ‘20 seconds past 5am’ as 05:00 <= 05:00 as true.

@ady624 @ipaterson can you look into this bug:

$time24 <= 05:00:00 (05:00:20 <= 05:00:00) returns true instead of false.

Would help if we had a variable for time now that formatted as hh:mm:ss instead of just hh:mm


This version will set SHM to Armed/Stay for ‘sleep’ mode

Location Mode and Presence
Location mode else if returns false?
Circadian Schedule - Piston Skipping Lights

I have mine set up almost the same way, however I never broke down away into time modes. What are you doing with yours?


1 Trigger?! Whoa!

I have about 4 or 5 doing the same job!


I’m not… I only have simulated devices to play with and no hub :sob:

Made this example to help a user in a different thread but figured it should also be listed in the examples category.


Odd, I would have expected $time to be equivalent to time($now) but you’re right, while the latter includes seconds and milliseconds the former is only hours and minutes.

(expression) formatDateTime($time, 'hh:mm:ss') »»» (string) 12:52:00
(expression) formatDateTime(time($now), 'hh:mm:ss') »»» (string) 12:52:30


So I guess it’s not technically a bug, $time and $time24 are defined as strings but this is something that could very easily trip people up. For your purposes, time($now) will give you the correct value to compare against your time variables using just < and >


Another issue I had building this piston is that ternary operators don’t recognise / allow for different time formats, for example, the following won’t work:

($time24 <= 05:00 ? true : false)

At 4am, it evaluates this as 14400000 <= 05:00, cant compare apples and oranges!

That’s why I had to put the 05:00 in a time variable {timeDawn}, which outputs 18000000. Then reference that variable in the ternary operator:

($time24 <= {timeDawn ? true : false)

At 4am, it evaluates this as 14400000 <= 18000000, apples and apples!


I don’t know if this is the best or only way, but to make a literal (non-variable) time value I use time(datetime('12:34:56')). The actual value being compared between two times is the number of milliseconds since midnight, which you can see here:

 (expression) time(datetime('13:04:00')) »»» (time) 47040000



Just thinking it would be nice if 12:34:56 was automatically recognised as a time on its own and evaluated as 45240000


btw… does anyone know the correct terminology for daily times displayed as number strings?

I was thinking it could be Epoch or Unix but that refers to a running string starting January 1, 1970, whereas the expressions are using a running string starting at 00:00 daily.

time to decimal (ms)?


Are you referring to 13:12:11 format? That can be called “international standard notation” or more commonly in programming by the name of the standard, “ISO 8601 time format.”


No, I’m referring to 18000000 format (i.e. 5am)


Ah, up to you I suppose. In this context “time” implies “since midnight” so you could refer to it as time in milliseconds, timeMS, etc. just not epoch or unix timestamp since as you mentioned those are different.


Did you guys invent a new language. I’m pretty sure only 10% of that was English :joy:

Routine director piston not firing

:roll_eyes: uhoh, this doesn’t work. This also ignores the seconds, so time(datetime('12:34:05')) is the same as time(datetime('12:34:56')) because datetime('12:34:05') is the same as datetime('12:34:56')… hmm


This seems to trace back to the SmartThings timeToday function only accepting the hh:mm portion. Based on that I’m not sure of any clean way to make a time literal with seconds… we’re left with representing 14:15:16 as something ugly like time(addSeconds(datetime('14:15'), 16))

Lots of mystery surrounding this datetime function.


Anyway, I just changed my ternary operator to use < instead of <= so the seconds no longer matter.


Hey all,

Ok so I need some assistance on how to get the correct expression. Here is what I am hoping to do:

Variable FutureTime = +5 minutes from current time

While time($now) != time(FutureTime) do
…these checksums, etc
end while

Basically I am trying to run a while statement to check for motion sensor changes in a given timeframe to reset my timeout period before turning off the lights. I am using EcoLink Motion Sensors using the test pin and they reset in 30 secs which is great. But if you are sitting idle in the room and it goes inactive during the end of a predetermined wait period it shuts off the lights as your If statement became true. Any help is appreciated!


Can you post your current piston snapshot… sounds like you might be over complicating things.

In a nutshell, this should be all you need:

motion is active
Turn on light
Wait 5 minutes
Turn off light


My issue has been knowing if a room is really occupied or vacant. I believe I just found my solution with Rooms Manager. Does almost everything I need for both security true motion detection and light automation based on true occupancy.