Anyway to get around a Timeout Exception?


(Chrisb) #1

Okay, I’m knee deep in a program that checks if windows or doors are open. When it finds one is, it sends an httpget request off. The problem is that there has to be a 10 second pause between httpget requests. So I put in this line after the httpget line:

pause(12000)

So after finding an open door or window, the httpget it fired off, then it waits 12 seconds before returning to do the next check. This worked great for most of my initial testing. However, I just tested over a large number of doors and windows, 4 of which were open. When I did that, I got the following error:

12:53:52 PM: error java.util.concurrent.TimeoutException: Execution timed out after 40 units. Start time: Thu Jul 03 16:53:02 UTC 2014 @ line 72

It would seem that my pauses pushed this beyond this timeout limit of 40 units (seconds?). Is there a way to extend whatever this time out is? It’ll be rare that more than two or three sensors would be open in practice, but certainly it’s possible so I’d like to make sure my program doesn’t die… or worse, seem to work but neglect to report a window or door that’s open.


runIn(), runOnce(), pause(msec) which one to use in this example
Sleep() in smart app?
[BETA RELEASE] Control Your Devices From Homeflow Dashboard
(Brian Steere) #2

Why does there have to be a 10 second pause between requests?

You’ll need to use the scheduling commands. Specifically runOnce. You’ll probably need to keep track of things using state.


(Convinced ST will never be unbroken…) #3

But isn’t there a limit on those as well?


(Brian Steere) #4

You can only have 4 (I think) scheduled events. But you can chain them together. So use runOnce and call it again from within itself.


(Convinced ST will never be unbroken…) #5

Good point. The 10 second requirement I believe is a limitation of the UBI Chris trying to talk to. And IMHO, it shouldn’t be. The UBI has more than enough resources to queue these up; why it can’t seems a bit of an oversight (I mean 10 seconds, really?).


(Chrisb) #6

I believe the 10 second pause is designed to keep the Ubi portal from being overwhelmed with repeated requests rather than the Ubi itself… but I might be wrong there.

Re: using runOnce… I’m not sure how or if I can apply that in my situation. Here’s the bit of code in question. I pulled out the extra formatting stuff to make it easier to see the important bit here:

doors.each { doorOpen ->			
    if (doorOpen.currentContact == "open") {  
       << code for grabbing device name and formatting it removed >>
    httpGet( [insert website here] )
    pause(12000)
    }         

I have pause set for 12 seconds right now just to give it a little more breathing room on the Ubi side. I could drop to 10 seconds, but that wouldn’t really give me significantly better results.

The doors.each command is just cycling through all the doors and windows selected by the user. Anytime an open one is found it runs through the rest of the commands there. Obviously the last one that pauses is the problem child. But without it the http requests beyond the first one aren’t allowed to go through.

How would it be possible to break this into smaller pieces and still get it to cycle through all the devices?


(Patrick Stuart [@pstuart]) #7

Speaking purely hypothetically, couldn’t you build your own basic scheduler?

Build a queue (List / Array) of commands in a function.

Have a scheduler function running an action every ten seconds to check the queue

If queue has any items in it, take the oldest one and send it, clear it off the queue. Might need to create a date/time stamp on any command in the queue to sort on and check against.

Any new requests go into the queue…

I don’t see anything in a smartapp that would stop you from writing this on your own, unless you can’t have a smartapp process running persistently? Even so, the next command would just trigger the oldest command in the queue.

Also, this is assuming I can have a List variable persistent? Maybe also writting out to a text file and read back in, do function write it back out? I thought I saw a code example of reading and writing a text file somewhere?


(Chrisb) #8

That sounds a bit more complicated than I ideally want to get into. Part of the problem here too is that I want timely responses from Ubi. What this program is designed to do is tell me what windows or doors I have open after I say goodnight to Ubi. I don’t really want to sit around for 2-3 minutes waiting for to see if there are any items open.

I re-read through the documentation on the HTTP request process with Ubi. I was trying to find where I read the 10 second deadline. I can’t seem to find it now. There area a number of references to possible delays (up to 10 seconds before Ubi speaks… ~5 seconds before Ubi receives, processes, and speaks…) and one time where the documentation says to avoid sending more than 1 request per Ubi per 15 seconds. But there’s no specific 10 second deadline.

I might play with things in my app a little and see if I can shave down that pause function.


(Brian Steere) #9

Any chance you can send everything in one go?


(Chrisb) #10

Hmmm… I hadn’t really thought of that. Maybe… I’m not sure.

EDIT: Upon further testing, you CAN send more than one variable in the HTTP request. However, at present, there is no logic that can be applied on the Ubi side of things so I can’t tell Ubi: "Don’t utter this phrase if var3 is empty. So I might need to do some careful structuring of things.

Maybe I still send it as one variable, but build it as a phrase in SmartThings… I’ll have to think on this.


(Chrisb) #11

@Dianoga, you’re a genius!

It isn’t, in my opinion, a perfect solution, but it’s dang close! So what my program is doing so far is it’s pulling the name of the device, passing it through a replace procedure to replace spaces with %20 (tip o’ the cap to @scottinpollock for that bit of code). That’s being stored in a variable called replaced.

So then I’m running this as the last command in my little if statement:

 phrase = phrase + ",%20The%20" + replaced

So it’s built up as new devices are found and the end result (when run in the simulator) is this:

,%20The%20Door[1],%20The%20Door[2],%20The%20Door[3]

On the Ubi side I’ll make the utterance for this token be this:

Hold on, I found something open: ${variable}

So, using the above example as the phrase being sent as the variable, Ubi will say this:

Hold on, I found something open: The Door 1, the Door 2, the Door 3.

Now I send it all in one request and no problems with timing out or having to send multiple request quickly. Plus this is the added bonus of not having to hear Ubi say something is open three or four times if that many devices are open. It’s just all in one phrase.