Can SmartThings generate a https request?


(Chrisb) #1

I know there’s a thread…

…that is kinda talking about this, but after reading though that thread it seems my question is a little different and doesn’t seem to be answered in that thread.

Ubi has recently opened up to allow HTTPS requests and to before actions based on those. There appears that parameters can be sent with this HTTPS request as well (though no confirmation of if or how).

What I’m envisioning is an example like this: When a window is opened, a SmartApp would trigger an app that do a request like:

https://portal.theubi.com/webapi/behaviour?access_token=*token*&parameter=${contact.displayName}

Then the custom behavior in Ubi would be something like:

"The %paramater window was opened."

So this is a two part question, I guess:

First: Can SmartThing generate a request like that? If so, how?

Second: if I put ${contact.displayName} in that https request, will SmartThings insert the name of my device there?


(Patrick Stuart [@pstuart]) #2

Yikes, this could be really tough to accomplish without accepting SSL certs, etc.

So there must be a process to get the access_token first, I don’t see why the httpget function that sends the cloud to cloud couldn’t (maybe already does) send an SSL request.

I haven’t played with the OAUTH stuff yet, but it appears that this also maybe a vector to access their API?


(Chrisb) #3

Well, I already have the token. That would be supplied either in the code or at time of install by user (depends on how fancy I wanna get with the coding), it’s more a question of how I send the command.

I’ll look at the documentation of the httpget.


(Convinced ST will never be unbroken…) #4

OAuth endpoint commands are in fact sent over https so it may be possible. Maybe the hub has embedded certs.


(Chrisb) #5

Okay… never tried doing any sort of http command through a SmartApp. I have a url that when I punch it in my webbrowser will successfully hit the UBI portal, which passes the command to Ubi and makes her say what I want.

But how do I tell a SmartApp to go out and hit this url?


(Patrick Stuart [@pstuart]) #6

How do you want the smart app to trigger the command? A switch, motion? a button press? on a schedule?

The documentation does have some decent examples on how to wire up these to events. The IDE has a really good simulator to test with as well.

I’m learning as well, not sure of the proper way, but if you need examples, look at the smartapp templates in the IDE.


(Chrisb) #7

Okay, looks like I can do this with a simple httpget command. I just whipped up a simple test app. When I turn on a switch, it calls this:

def switchOnHandler(evt) {
    httpGet("https://portal.theubi.com/webapi/behaviour?access_token=*token here*&variable=ten%20eleven%20twelve")
}

In the simulator when I hit my switch, my Ubi replies with “ten eleven twelve”!

So, that answers part one. Now for more testing: Can I embed strings like .displayName?

Stay tuned for more!


(Patrick Stuart [@pstuart]) #8

Yes, that is basic Groovy syntax… It’s a bit different then other languages.

just a $varname in the string, like this “https://$url/$path?$command” would return and example of “https://google.com/search?1=1

Please someone correct me if this syntax isn’t correct, but from memory it was working that way last night :smile:

log.debug is also your friend in testing in the console.


(Chrisb) #9

Okay… good news/bad news.

So, when I used the httpGet command with the display name variable:

httpGet("https://portal.theubi.com/webapi/behaviour?access_token=*token here*&variable=${trigger.displayName}")

It worked perfectly as long as the device name was one word (no spaces). But when I used a device that was two or more words, I got an error:

“java.lang.reflect.UndeclaredThrowableException @ line 53”

It would appear that the space is throwing an error. Anyone know of a way to force that space to appear as %20?


(Chrisb) #10

How do you want the smart app to trigger the command? A switch, motion? a button press? on a schedule?

The overall design is thus:

I say “Goodnight” to my Ubi. This triggers Ubi to turn on a Virtual Tile in SmartThings.

I have an app setup in SmartThings that watches for that tile to turn on. Once it does, it performs a series of events which includes checking to see if any doors or windows on the main floor have been left open. When SmartThings finds a window or door open, it will run that httpGet command substituting the device name at the end.

Ubi when it receives this http request will say: “Wait, you left [Device name] open.”

I’ve got the program mostly set already. I currently just say “a door” or “a window” is open rather than naming the window or door. I’ve got it running through the “open check” and then flipping a flag if it finds something open. I have to figure out yet how to set the httpGet with the particular device that it found open… that parts coming yet.

But before that I have to figure out how to handle device names that have a space in them. If I can’t get that part working then there’s no sense on figuring out the other part.

But the rest all works… I can start the problem from Ubi. I can send httpGets with (one word) device names.


(Patrick Stuart [@pstuart]) #11

I can’t test if this is supported or not, but here’s what I found quickly on google…

Remember, this language is groovy, lots of great resources on the net on how to use groovy. FYI groovy isn’t that much different than Apple’s new language Swift :smile:

another option would just do a replace on " " to “%20”

http://groovy.codehaus.org/groovy-jdk/java/lang/String.html#replaceAll(java.util.regex.Pattern,%20groovy.lang.Closure)


(Convinced ST will never be unbroken…) #12

@pstuart Your first link won’t do it as it will escape spaces with +

Second link is on the money:

def toEncode = "http://se.com/Two Words"
def replaced = toEncode.replaceAll(' ', '%20')
log.debug replaced

(Chrisb) #13

Thanks guys… you’ve been very helpful so far. I really appreciate the help. So, here’s the final piece of the puzzle: checking doors and windows to see if one of them is open, and if so, running the url.

Right now my program does this:

def checkDoors() {
	def open = doors.findAll { it?.latestValue("contact") == "open" }
    if(open) {
    	doorCheck.on()
    }
}

Basically it looks at all the doors selected (an unknown number), and if any of them are open, then the “open” flag is turned on. Then, if the open flag is turned on, it turns on a virtual tile.

So what I need to do it replace it with a procedure that looks at door individually (one after the other) and if it finds one open it’ll run a series of commands. If not, it’ll proceed to the next door and check that.


(Patrick Stuart [@pstuart]) #14

hate trying to do this on a phone, but if I remember correct (50/50 chance) there is a .each command works similar to the above .findall…

So, something like this, def open = doors.each { it?.latestValue(“contact”) == “open” } would loop through each, it?.name (or something like this could get you the name of each device.

I haven’t done this yet in groovy, but that is the basic concept, my syntax is probably wrong.

this has some help, might be doors.each { item -> log.debug item } this would log all item objects


(Convinced ST will never be unbroken…) #15

This should help:


(Chrisb) #16

Okay, so I’m getting my test app REALLY close to working here.

It appears to be cycling through my selected devices properly and spits out a trace line for each open device properly. So it’s seeing the multiple items open and translating them to proper HTML characters properly. The FIRST httpget runs without issues, but any subsequent httpget commands produce this error:

8:20:09 AM: error groovyx.net.http.HttpResponseException: Forbidden @ line 58

I think I’m running into one of two problems, and maybe both.

First off, I know that I have to separate HTTP requests to Ubi by 10 seconds. If you do them faster than that you get a rejection. So I know that I need to space these out. But I can’t find the right command in groovy to get the program to pause for a few seconds. I tried wait(10000), but that doesn’t seem to work. There was another command I tried as well, though I’ve since forgotten which that was. It also didn’t work.

Secondly, I’m wondering if my app is expecting a reply from the address that it sends the httpget command to. And if this is the case is attempting to send a second httpget causing problems because it’s in an “open, waiting for response” mode.

Any ideas?


(Chrisb) #17

Woot!!

No idea why I didn’t think of it sooner, but “pause” appears to be the command:

pause(11000)

This command will pause the program for 11 seconds.


(Chrisb) #18

@scottinpollock, @pstuart, @Dianoga,

Just want to say thanks again for your help in this thread and others guys. I think I’ve got my (near) final code written up. I’ll have to do a little testing yet tonight and maybe some language cleanup in the prefs sections as well as some tweaks in documentation, but my simulator test have gone flawlessly.

I touched on what this apps does a number of places, but for a summary, here’s how it works:

The user setups a custom behavior on Ubi and makes the trigger an HTTP request. This will give him/her a token that will need to be used in the SmartApp. The user sets the action to be an utterance by Ubi: “Hold on, you left ${variable} open”

The user also needs to setup a custom behavior so that when he/she says: “Goodnight” to Ubi, ubi then turns on a virtual on/off button tile in SmartThings.

On the SmartThing side, when installing the app it will ask for the Ubi token as well as the Virtual tile that it’s using as the trigger mechanism.

Additionally, the App will ask for:

  • Which doors or windows the program should monitor
  • Which lights (if any) the program should turn off
  • How long of a delay (in minutes) to wait before turning off the lights
  • Whether or not the program should same “goodnight” to Hello Home.

The program watches for that virtual tile to be turn on. When that happens it will check the doors and windows and report back to Ubi if it finds any. Ubi will then say (for example): “Hold on, you left the Back Door, the East Den Window, and the Kitchen Window open”

Finally, of course, the program will turn off the selected light after the given number of minutes have passed.