Run "something" at certain time -tile?

This would be great as a native feature! Can we make this a feature request?

The request still isn’t super clear to me, so I’m unlikely to convert this thread into a feature request. Having vague requests as the first post in a feature request yield less-than-ideal results as people tend to vote based on what they have in their head rather than a formally scoped / written request.

That being said, if someone wants to clarify the scope and create a feature request, that’s certainly fine.

From what I understand, it’s a request for a time-picker type UI in tiles… but I’m not sure what the rest of the expectations are around how to use it. It seems like it would require rules for it to work since it requires being able to schedule something. So my gut tells me it would make the most sense as a new ‘Time’ type of variable… then you could add that variable to your dashboard - which of course would have a new ‘Date/Time’ Variable Tile Layout (much like the current number, text, and true/false types) which would probably have some settings around what’s displayed*. Then you could use that variable changing as a Trigger in your rules to schedule the device running.

*The features of the Date/Time variable tile probably needs some scoping too. I suspect it would be a Date/Time variable type and then you could control which parts of the variable are displayed/set within the tile settings. For example, you could pick to show just the Date, just the Time, or the Date + Time. But I would need to think through the implications of that and if another approach might be better (eg. being able to subtype the variable type).

Hi! I think you got that right. My use case would be an automation for electric shades. I would like the user to set the time when shades go up or down. That would require a UI to set the time, a variable to store it and a rule to execute at the given time. I can think of other use cases but all similar.

@josh,

I am looking to do something similar to what I believe the initial request on this is asking.

First off, I am a new person to trying to setup a smart hub. I have an Aeotec hub and switches that work with it.

Here is what I am looking to do:

  1. have a tile that allows an individual to select a date and time to turn on a switched outlet and have it stay on for two hours and then turn off.
  2. In addition to that, I have a tile set to turn on that switched outlet manually but I only want it to run for two hours each time it is turned on.

Help? Guide me?

Thank you,

Dave

Hi @FNI_heater - welcome to the community. As mentioned further up in the thread, there’s not a dedicated UI control for selecting a date/time from a dashboard, but there are different approaches you could take depending on your needs. For example, some people have used variables as inputs to their rules while others have created dedicated dashboards to display a ‘list’ of preset times they could select. If you really wanted a clock-like UI, you could use a Custom Tile to accomplish that but you would need the requisite developer skills for that approach. (And you’re always welcome to create a feature request as noted further up in the thread)

As for the second request, you might consider posting your own thread for that with a relevant title so other community members can see it and chime in. You could create a rule that you run to turn on the outlet and then turn it off after a delay… or if you always wanted the outlet to turn off after a set time, you could setup a rule to react to the switch itself turning and then set the timer based on that.

@josh,

We used to have an app (?)/site that we could go to under herokuapp that we could manually enter a date and time to turn a switch on. Is there a way to do that under smarttools? I might be able to get the old code but I am also trying to learn this for myself as well.

Or, could you point me towards how to learn how to create a manual date and time entry to start a process? I have successfully created a tile/rule that will turn the outlet on for a timeframe and turn it off.

Thank you,

Dave

If you still have the app hosted, you could embed it into your dashboard using a URL Custom Tile. Alternatively, if you have the requisite developer skills, you might be able to use the HTML Custom Tile to have it all run natively within SharpTools.

Can you share what you’ve tried so far? There’s a few different approaches you could take for this. @Jason_K_Jennings shared an approach that worked for them further up in the thread which allows a fixed set of times.

Another approach would be to store the desired time in a variable, then use that variable changing as the trigger to start the rule, and use an expression to calculate how long you want to delay before running the action.

This approach would involve writing an expression to parse the input date, then calculating the number of seconds between now and your target time to determine how long to delay for.

One downside to the ‘delay’ approach is there’s not a native concept of ‘cancellation’, so if you wanted a cancellation feature that would require some more involved logic for snapshotting your ‘timers’ and being able to flag them for cancellation.

Here’s an example of a dynamic rule + expression that you could adapt to your needs.

And here’s the raw expression in case you wanted to copy-paste and tweak:

#// add the current date to our timestamp to ensure it is parsed as 'today'
today = formatDate(now(), "YYYY-MM-DD ")
fulltime = concat(today, $targetTime)

#// parse the target time as a timestamp (using the version with today's date concatenated in)
ts = date(fulltime, "YYYY-MM-DD hh:mm A") 

#// if the time is BEFORE now, add a day to it since we probably want that time tomorrow
ts = (ts < now()) ? addDays(ts, 1) : ts

#// calculate how many seconds until our targetTime (it's in millis, so convert to seconds)
(ts - now()) / 1000

In the example rule, the rule is triggered any time the $targetTime variable changes. In my example, I’m setting the variable in the format 7:30 AM.

The first step in the rule flow is a Delay action using an expression as the source for how long the delay will be. The expression is well commented, but here’s a summary:

  1. Parse the variable as a date using the format mentioned above hh:mm A7:30 PM
  2. Adjust the date component if needed: if the time was before now, add one day to it as we mean tomorrow, otherwise use the raw time
    • Since we are only providing the time, the system assumes the date as today. As such, we may have to adjust the date to tomorrow to perform the next calculation
  3. Calculate how many seconds are between now and our target timestamp (in seconds)
    • The dates are in milliseconds by default, so divide by 1000 to get seconds

This is just a starting point and you could adapt the rule to your needs as you see fit. For example, you might want some conditional checks to make sure it’s a valid input time format (otherwise the delay will default to 0).

As mentioned in the original post, this version also just schedules an execution every time the variable is changed, so you might end up with multiple scheduled executions in parallel if you changed the variable multiple times. It would get a bit more involved, but in theory you could keep track of each scheduled execution within a variable which would allow you to ‘cancel’ an execution by adding a condition after the delay which would determine if that particular execution should still run. Or you could adapt the logic as you see fit not to allow parallel executions or whatever your particular needs are.

Josh,

I was able to get access to the github files for the app. Is there any way to copy this over to work under sharptools?

Thank you,

Dave

Without having any insight into what’s in the app, there’s no way to say.

Hi Josh. I am attempting to use this for a project but am having issues. I am trying to enter a time manually in a variable, convert that time to an epoch timestamp in millis and use that timestamp variable in another calculation.

When I enter a targetTime that within the same day, I am getting a timestamp that registers to the next day, not today.

current date 1/23/2024, current time is 7:00 PM
targetTime variable 10:00 PM

#// parse the targetTime variable as a timestamp
ts = date($targetTime, "hh:mm A")  // returns epoch timestamp of 1/24/2024 10:00 PM 

I tried adding this part (which I don’t actually need to do) but get the same result as above.

#// if the time is BEFORE now, add a day to it since we probably want that time tomorrow
ts = (ts < now()) ? addDays(ts, 1) 

It works perfectly if the time is the following day. What am I missing?

Ah, that’s right. I recall running into this in the past. If the rule runs later in the day where it’s potentially already tomorrow in UTC, you can’t parse just the time. One trick is to concatenate in the current date with your time string, so when you parse the time you can be sure it’s the current time today:

So back to our example, that might look like:

#// add the current date to our timestamp to ensure it is parsed as 'today'
today = formatDate(now(), "YYYY-MM-DD ")
fulltime = concat(today, $targetTime)

#// parse the fulltime including today's date concatenated in
ts = date(fulltime, "YYYY-MM-DD hh:mm A") 

#// if the time is BEFORE now, add a day to it since we probably want that time tomorrow
ts = (ts < now()) ? addDays(ts, 1) : ts

#// calculate how many seconds until our targetTime (it's in millis, so convert to seconds)
(ts - now()) / 1000

In case you’re curious about alternative approaches, here’s one:

Alternative approach

Set Date Parts to Today
You have to set the date, month, and year otherwise you could be on the edge of a month or year and tomorrow is actually the next month or year

ts = date($targetTime, "hh:mm A") 

#// set the date, month, and year to today's
ts = setDatePart(ts, 'date', getDatePart(now(), 'date'))
ts = setDatePart(ts, 'month', getDatePart(now(), 'month'))
ts = setDatePart(ts, 'year', getDatePart(now(), 'year'))
1 Like

As of lst night, 10pm MST, manually updating my variable will has stopped trigger my rule. Here’s my rule. It was working yesterday.

What do the rule logs say with the debug filter enabled?

And where is AlarmSetTimeClock being set? Based on the other variables that are getting set, it looks like you have some other dependency chain here? I see that a different variable AlarmSetTimeHour is being set to x at the end.

If you want to share the Rule ID, I can take a closer look. Hard to say without additional details / debugging info.

The variables are set on a dashboard tile. I would like the variables set to blank {{}} but settled for x when I couldn’t get blank to work.

Clock manually delete x and enter military time (ex. 0600)
Clock rule id ImcFahEN06isbj1YOMuA

Hour manually delete x and enter single digit (ex. 7)
Hour rule id koNjieEYCspZpRL31OBC

The rule debug logs show

Summary
Message
Rule was not triggered by the variable event. No trigger condition was matched.


Runtime Data
[
  {
    "type": "event",
    "subtype": "variable",
    "data": {
      "platform": "sharptools",
      "uid": "VC92ednwcAb4mZaYu8hlCMsNGh93",
      "variableId": "AlarmSetTimeClock",
      "value": "x",
      "datetime": "2024-01-26T13:35:10.200Z",
      "source": "VARIABLE"
    }
  }

Edit to add details:
I just double checked and both variables are strings. Should they be numbers instead?

I think it’s the format of the input being used rather than the type. It looks like you are inputting the time in the format 0600 rather than 06:00 AM from the original example.

When the actual comparison is done, the 0600 is inferred as numeric. Even with string values, the comparison checks to see if the values are numeric and if so compares them as numeric - this was intended to support cases where numeric strings were compared (eg. “2500” > “35” is false as a string but true when they’re numbers).

So you could either:

  1. Change the Trigger condition to something like is not -1
    • And set the ‘reset’ value to -1 instead of x
       
  2. Change your input format to include the colon (eg. HH:mm)
    • You can still use 24 hour time, but the colon forces the trigger comparison as a string

Thanks for all the help Josh. I was able to get these working by setting the default value of the tiles to 0 and the trigger to if $var changes and is not 0. I can enter the values as a whole number or as 4 digits.

A little context of what I was working on…
A while back when Webcore shutdown for SmartThings, I replicated an alarm clock rule into Sharptools. This wasn’t ideal as I had to use static variables for each possible time. Over time, I ended up with about 20 variables just for times and each variable required 4 rules (80+ rules total). This did not include the other variables used in the rules.
I have now recreated the alarm clock that plays announcements over Alexa, turns stuff on, sets the thermostat an hour before the alarm goes off in the winter and when the alarm goes off the rest of the year. I have maximum flexibility for the timing by using 1 variable where I can select the number of hours before the alarm goes off, i.e. 8 hours, and the other where I can enter the actual time for the alarm to go off, i.e. 6am.

I have now combined this into 15 variables and 12 total rules, including the 2 you are helping me with which simply display the time the alarm will go off on a dashboard (not critical to the alarm function) and a rule that resets everything when I get up.

As I said, I have them working for now and am pretty happy with the outcome but I would still like to understand why setting the trigger as updates and is not {{}} (blank space) or changes to not {{}} (blank space) would not trigger the rule when a value was entered in the variable? I was reading through some older posts and found this exact suggestion.

I tried setting the default variable value to blank space by manual input and from a rule using {{}}, {{ }}, and expression input of "", and " ". The rules would not register a variable change when a number was entered in the variable but would occasionally trigger the rule when the variable was cleared.

Again Josh, thank you for all the help!

I presume you mean a literal empty input in the trigger field (eg. add some text and then delete it so the field is blank) rather than the actual double brackets that are typically used for inline expressions.

It’s the format of the input being used. Since it’s a pure numeric value and doesn’t have the : delimiter in it, the comparison is treating it as numeric.

I have an idea on how this can be improved, but since it’s such a deeply shared part of the engine, it’s not something I want to change on a whim.

I realize this is the same explanation you gave before but this time it somehow made sense. :rofl:
I have it working and am happy with the outcome. Thanks again for all your help!

1 Like

I created a separate thread here to show how my example works for an alarm clock.