runIn does not run at specific intervals

@Jim great work this is fantasic documentaiton and very helpful.
Couple of things I would like to point out though:

  1. schedule(dateTime, handlerMethod) doesn’t work as expected, see my post here, timeToday returns a date about a month back with current time and if that’s passed to schedule() it doesn’t execute. Thermostat Scheduler App?
    .
  2. Did you see my post earlier about runOnce not being called and it does it doesn’t honor the schedule (e.g. I asked 13 second delay and it executes twice in a second. runIn does not run at specific intervals

It looks to me like it was time zone issues in this case that was causing the time to be wrong, thus the schedule to be wrong. It can be confusing to look at the date string passed to schedule, because you could pass last month, or last year, and it would still schedule based on the time.

This does seem odd. I’ll pass this on to the engineering team. In general, we would expect it to not be that off… but this gets back to the level of precision expected when using the scheduling APIs - in general, expecting precision down to the seconds isn’t something we can fully guarantee at this time.

Regarding runIn behaving differently for values less than 60 seconds, currently we handle this case a little differently, internally. This is part of the reason why runIn might behave differently than runOnce. This may change in the future, however. But to answer @AaronZON’s question, they may behave differently because we have to handle < 60 seconds differently.

@Jim it schedule didn’t work at all until I corrected the date and put today’s date, don’t know if it was a platform bug but I do know that it didn’t schedule any events until the date was current/future.

OK, @Jim, @scottinpollock, So, I created some code to emulate a runIn call with a 30 second delay:

def fireTime = new Date(new Date().time + 30000)
runOnce(fireTime, toHappenInThirtySeconds)

Maybe there is a more elegant way to code this but it works. I tried a few times with different values. Accuracy is all over the place, but, it did fire every time. I tried delays as short as 3 seconds and as long as 60 seconds. Here’s the log I got:

30,000 ms turned into 11 sec.

1 Like

Yeah… I found 3 to 4 seconds to be about the limit on the short side. For the record, I avoid using SmartThings for scheduled tasks wherever I can. I have moved most of them to either the Hue bridge or back to my Indigo server.

And as I am now experiencing missed notifications on a pretty regular basis, I may need to find a replacement for those as well. That will leave very little that SmartThings does for me; probably not enough to bother with it anymore.

3 Likes

I’m trying to do this with a custom dry contact device for a doorbell to “release” the button, but it gets stuck in the pushed state. runIn was barely working. It could be that my code is effed. Anyone mind taking a look?

// "Push" the button when the contact closes
def sensorValueEvent(value) {
	log.debug "Pushing button"
    if (device.currentValue("contact") != "closed") 
    {
		sendEvent( name : "contact", value : "closed", descriptionText: "$device.displayName was Pressed", unit : "" )
		def fireTime = new Date(new Date().time + 7000)
        runOnce(fireTime, "releaseButton")
	}
}

// "Release" the button
void releaseButton() {
	log.debug("Releasing button")
	sendEvent( name : "contact", value: "open", descriptionText: "$device.displayName is Waiting")
}

Try without the quotes . . . .

BTW, I have no experience with the sendEvent() method so if something is effed there, I wouldn’t know

This may explain why this command (and others) aren’t firing on schedule.

I checked in with ST Support today. I’ve been getting a few missed timers myself (events not firing, mostly timers) of late.

I was pleasantly surprised when ST told me that they are aware of the issue and it’s been there for a while. Apparently for some reason the timers in the cloud die or app the die (possibly as a result of timers dying). They are aware but don’t know why it’s happening and the dev’s are looking in it.

@Jim I thought you said the runOnce supports [overwrite:false?]
According to the latest docs http://docs.smartthings.com/en/latest/ref-docs/smartapp-ref.html#runonce

There is no reference to overwrite, only runIn has that reference. Reason I’m asking is that in the code when I try to use runOnce with overwrite false to schedule multiple events it doesn’t seem to work.

Here’s how the code goes:

runEvery5Minutes(function)

… do a few things

runOnce(runTime, function, [overwrite: false])

Now function only gets called once, not every 5 minutes. It ends up overwriting the runEvery5Minutes scheduler.

Is that the intended functionality, something changed or something broke?

@Jim any thoughts on the above?

I’m looking into this today, and will reply when I have an answer. Sorry for the delay!

This is expected behavior.

runOnce() does not currently support the overwrite option, so calls to runOnce() with a handler method already used by another scheduler method will overwrite the other one.

There is support planned for overwrite in runOnce() in the future, but it does not support it currently.

1 Like

Ignore my previous (deleted) comment, the function I was calling was marked private hence runOnce wasn’t able to see it.

Hello,
I have been following this and I understand the runIn limitation for < 60. Now with the hubs with local processing:

  • is it better now with the new v2 hubs? Can we use runIn will < 60 seconds intervals?
  • if not, is there a better method to do an interval of less than 60 seconds and make it run on local hub?

Thanks,

Well… not yet, … but there are some ideas for this frustrating problem.

I’d suggest joining this Topic and/or the ones it references:

Do something less than 60 seconds usually works. It’s just flaky, and not guaranteed (as if anything is).

Thanks… I understood that when it was run on the cloud. But now that it’s local (maybe?) It should be working fine. It is not reliable AT ALL…

Is it that this method still runs in the cloud? Any way to make it fun loally or maybe a different command?

Thanks…

Either the whole SmartApp instance runs locally, or nothing.

Only Smart Lighting (ummm… Maybe also SHM?) are local and only if they are configured only with device types that have local Handlers.

Has there been any movement on this topic? I have been struggling with this for a while now using runIn. Processes seem to run without any regard to the runIn time(seconds) that is specified. The runOnce method suggested above seemed to be a good option as well, but still produces the same results. In my case I am trying to only delay methods for less than 10 seconds, but it’s clear that the methods fire immediately.

Im not sure runin works for times less than a minute.