[BETA RELEASE] URI Switch -- Device Handler for controlling items via HTTP calls

I’ve switched from X10 to ZWave but still have a handful of X10 devices that needed control.
I installed Home Genie on a Raspberry Pi which gives me control of my devices via an HTTP call and I wanted a way to control this with SmartThings.

With the help of @tguerena we’ve come up with URI Switch.

URI Switch is a Device Handler that when attached to a Virtual Switch, kicks off a URL (External or Internal) when an On/Off command is sent

Please refer to the following for instructions and usage information

http://thingsthataresmart.wiki/index.php?title=URI_Switch

While this was created for sending ON / OFF commands for my X10 devices, the ON / OFF commands could be a call to anything that takes a URI to control.

Please let us know how this works for you and let us know what we can add or improve.

11 Likes

Great idea…I was actually playing with this as I created an ‘Endpoint creator’ ( also known as Cloud Interface as part of the Alexa Helper SmartApp : http://thingsthataresmart.wiki/index.php?title=Alexa_Helper#Cloud_Interface_Smart_App_Setup). Anyway, what I found is that calling back internally from a smartapp to SmartThings (graph.api,smartthings) may not work, and they (ST) appear to be playing with ‘white list/black listing’ the internal SmartThings addresses. You can work around this be generating a short url for the graph.api.smartthings url (something like goo.gl).

1 Like

Have you tried to confirm this with the Dev advocates?

Using a URL shortener is likely not a long term solution if they trace the route back to the same source & target.

I’m not following your issue. Could this be because it’s from a smartapp vs. ours being a Device Handler?
I only use this for Internal URI calls and it has yet to fail. We did a little bit of testing using External URIs and those worked as well.

Both from a SmartApp and Device Handler.

I did ping @slagle about this, and it appears he did pin this for follow up. I did see this on both SmartApps and a device handler, but haven’t heard back since I first discovered it a couple weeks ago. I realize that a shortener is a short-term solution, but it worked for the specific circumstance I was in at the time.

1 Like

Fantastic work! Any thoughts on how one might integrate this with the Amazon dash button?

This is wonderful! I’m using it to hit an internal php script to find my phone.

Probably a dumb question, but do I need a V2 hub to be able to use an internal IP? If not, I can probably still make use of it by opening a port on my router, but I’d rather not if I don’t have to.

No. Most or all of the rather limited LAN functions available are currently the same in Hub V1 and V2.

1 Like

Could use some help here. Am new to Smart Things and am trying to get this device handler to use Http POST. First - I am not a programmer, but am technical by nature. Like @surge919, I need a mechanism to control my 65 UPB lighting switches that have been installed for years and are bulletproof. I have been supplementing those switches with newer Z-wave devices and need to control all the underlying technology with a single, consistent UI. Previously I was able to successfully map my devices into apps like iRule and Roomie (Simple Control which I still use today), but I have been looking for a way to display the controls on a wall-mounted panel and Roomie doesn’t cut it from a UI perspective.

I have successfully tested the HTTP POST method from an OS X client called Postman, and can control lights like I do in Roomie. Unfortunately due to my lack of programming skills I cant get this working with this device driver. Here is the snippet I modified from URI Switch from GET to POST.

	def result = new physicalgraph.device.HubAction(
			method: "POST",
			path: "${internal_on_path}",
			headers: [
			HOST: "${internal_ip}:${port}",
			authorization: "Basic d210cnVjOnBhc3N3b3Jk",
			contentType: "application/x-www-form-urlencoded"
			],
			body: [
            port: "0",
            command: "${internal_on_command}"
            ]

)

This saves properly without errors, but I have no way to know if code is valid. The actual command is saved as a variable in earlier code, but I tested the hard-coded version and it fails also.

Any help would be greatly appreciated.

Try this:

def json = new JsonBuilder()
json.call("command":"${internal_on_command}",port: 0)
def result = new physicalgraph.device.HubAction(
 			method: "POST",
 			path: "${internal_on_path}",
 			headers: [
 			    HOST: "${internal_ip}:${port}",
 			    authorization: "Basic d210cnVjOnBhc3N3b3Jk",
 			    contentType: "application/json"
 			],
 			body: json
 )

Thanks for quick reply, but device handler will not save – following error:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script1479167978007811371925.groovy: 83: unable to resolve class JsonBuilder
@ line 83, column 12.
def json = new JsonBuilder()
^

1 error

How about this?

def json = new groovy.json.JsonBuilder([ "command":"${internal_on_command}",port: 0 ])
def result = new physicalgraph.device.HubAction(
 			method: "POST",
 			path: "${internal_on_path}",
 			headers: [
 			    HOST: "${internal_ip}:${port}",
 			    authorization: "Basic d210cnVjOnBhc3N3b3Jk",
 			    contentType: "application/json"
 			],
 			body: json
 )

That change did compile properly, but I got the same result as the initial test – lights do not turn on. Without any way to debug, not sure where to go, but let me provide some info regarding the required POST process:

  1. This device (UPB Gateway called RUC-01) requires authorization with the type of: user:pw. This could easily be the trouble spot, if the payload is constructed properly.
  2. Required headers are (1) ContentType = application/x-www-form-urlencoded, and (2) Authorization = Basic d210cnVjOnBhc3N3b3Jk (which I believe is an obfuscation generated by the Postman app for user/pw authorization, but am guessing).
  3. required body key pairs are: (1) port=0 and (2) command=9999999999, where command is a complex value for each device on the network. I have generated all required commands previously.

There is really not too much to this. I was able to get this working in a number of other HA apps, so I know it works in addition to the Postman app.

Hope this helps.

Troy - checking back to see if you have any ideas re: your last suggestion? Attached is log output from the POST request:

47b6bc2e-6756-4107-a29e-c941f06bbca8 11:55:41 AM: debug POST /upbtrans.htm HTTP/1.1
Accept: /
User-Agent: Linux UPnP/1.0 SmartThings
HOST: 192.168.1.11:80
authorization: Basic d210cnVjOnBhc3N3b3Jk
requestContentType: application/json
Content-Type: text/xml; charset="utf-8"
Content-Length: 156

<?xml version="1.0" encoding="UTF-8"?>008040814FF226453

47b6bc2e-6756-4107-a29e-c941f06bbca8 11:55:41 AM: debug Executing ON

I also did some digging, and a lot of folks seem to have had problems with POST via LAN, although GET seems to work OK. Any thoughts or ideas?

[edit] - I decided to fire up Wireshark to check differences in packets between Smart Things hub and Postman app. When I submit a POST from Postman, I am able to see all the packets in both directions, but when using the URI Switch device handler, nothing is coming across network, which makes me wonder if I have handler and associated virtual switch installed properly. Either that, or the device is not actually sending any commands out.

I need to “PUT” a url to a Raspberry Pi to turn something on and off.
The API on the Pi is a Web to Serial bridge, so the PUT method is loading a URL and then transmitting a “state=on” or “state=off” in the body.

Can this be made to do that?

Just getting back from a Vegas conference. I’ll check this out and get back to you.

Thanks Troy.