SmartThings Labs and LAN Devices

So, SmartThings Labs launched today, which is way exciting – but did anyone else notice that the source for the new stuff was added to the device type example list in the IDE? Or that those device types appear to include code that talks to devices over the local network? =D

Since I’ve had a bit of a hard time figuring out exactly what the example code was doing, I thought I’d post a quick tutorial for getting a basic local IP rest call to work. This is inside a SmartApp, as I haven’t yet been able to get a device working yet.

Take a look at the example code for the Sonos Connect app in the SmartApps section of the IDE. You’ll a bunch of discovery code, but also this REST call -

sendHubCommand(new physicalgraph.device.HubAction("""GET /xml/device_description.xml HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))

As far as I can tell, ip should contain a normal IP address and port such as 10.0.0.123:80, which is simple enough. deviceNetworkId however, needs to contain a hex encoded IP address and port. There are example functions in the app that convert hex IP addresses to decimal, but not the other way around, so I used this tool to convert 10.0.0.123 to 0A00007B, and then converted the port 80 to it’s hex 50, giving me 0A00007B:50.

I haven’t setup any code to actually read the response yet, so this is assuming that you have a web server running where you can observe incoming requests. You should be able to see them come in using this code.

def deviceNetworkId = "0A00007B:50" // "10.0.0.123:8080"
 def ip = "10.0.0.123:8080"

 sendHubCommand(new physicalgraph.device.HubAction("""GET /hello HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))

It’s worth noting that I believe you’ll need to have version 000.011.00069 of the firmware for this to work correctly. Hopefully it’s helpful to someone, very excited about all the possibilities LAN functionality holds :smiley:

I’m also trying to get local IP controlled devices - namely my Foscam, so I can close down the port forwarding. The hex value of the IP didn’t seem to work for me, so I tried dabbling a bit, but still no luck. Here’s what I have so far:

https://github.com/imbrianj/secure_my_foscam_local/blob/master/secure_my_foscam_local.groovy

Hah, this makes me feel like we need an ‘unofficial wiki’ to document how things are hacked together when SmartThings wont give us the documentation/how-to’s…

Yeah, that would actually be really nice.

Just figured out something, the code won’t actually work without a port. Also, the code I posted above is actually wrong - the hex port must be four digits, even if it’s a two digit port. So for port 80, instead of it being 50 as I listed above, it would be 0050.

def deviceNetworkId = "0A00007B:0050" // "10.0.0.123:80"
 def ip = "10.0.0.123:80"

 sendHubCommand(new physicalgraph.device.HubAction("""GET /hello HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))

I’d been using the code with port 8080 before, but then as soon as I tried to connect to port 80, nothing happened.

I don’t have access to smartthings labs yet (email sent), so I can’t see the code for sonos. I’ve written a basic smartapp trying to ping a server on my LAN, but I’m not getting anything. Any suggestions?

I created the smartapp, installed it on my phone and run it there. The console logs say its running but my server doesn’t register anyone trying to access it (I have a dummy ‘hello world’ page setup).

It’s weird that you can’t see the code… maybe they changed that? But since labs involves a firmware update on the hub, I think that this sort of code won’t work until labs is enabled. According to the Sonos code, it requires a hub firmware of 000.011.00069 - which I guess is what they upgrade you to?

@alexking Ah, bummer. I guess I’ll be waiting…

Does the method you use provide a response that can be parsed?

It doesn’t directly – basically what you have to do is subscribe to the location, and tell it not to filter any of the events. Then you can watch for HTTP responses. It’s a little tricky processing it though, I don’t actually fully understand it yet. Here’s the work in progress app I’ve been experimenting with (for controlling TCP bulbs) – you can see the response being processed on line 61.

@alexking and whoever is lurking…

so, I just got LABs access… I have my smartapp pointed at my computer that is hosting a simple “hello world” app. I’m using this code:

def installed() {
	log.debug "Installed with settings: ${settings}"

	initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"

	unsubscribe()
	initialize()
}

def initialize() {
	// TODO: subscribe to attributes, devices, locations, etc.
	subscribe(location, null, locationHandler, [filterEvents:false])
	subscribe(app, changeMode)
}

def changeMode(evt) {
  def deviceNetworkId = "0A000005:0BB8" // "10.0.0.5:3000"
  
  sendHubCommand(new physicalgraph.device.HubAction("""GET / HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))
  
  log.debug location.hubs*.firmwareVersionString.findAll { it }
}

def locationHandler(evt) {
	def description = evt.description
	def hub = evt?.hubId

	log.debug "cp desc: " + description
	//log.debug description
}

Which yields this in the log:

6:01:38 PM: debug cp desc: headers:SFRUUC8xLjEgMjAwIE9LDQpYLVBvd2VyZWQtQnk6IEV4cHJlc3MNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KQ29udGVudC1MZW5ndGg6IDExDQpEYXRlOiBUdWUsIDA0IEZlYiAyMDE0IDIzOjAxOjMzIEdNVA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0=, body:SGVsbG8gV29ybGQ=, index:01
6:01:31 PM: debug [000.011.00231]
6:01:31 PM: debug Executing GET / HTTP/1.1 
HOST: 10.0.0.5 

on Hub via sendHubCommand

So, nothing usable for me yet… I’ll keep hacking. Hopefully a developer will chime in with some useful info. My goal is to get my DSC alarm system and FOSCAM/HooToo IP Cameras to work, then I’ll be one step away from transferring from my micasaverde vera lite…

Edit: And I’ve verified that it pinged my server

Matt,

The data you got is BASE64 encoded (the = sign is a good hint for that, it’s used as padding). You can use this website to decode by hand: http://www.base64decode.org/ in this case, you headers read:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/plain
Content-Length: 11
Date: Tue, 04 Feb 2014 23:01:33 GMT
Connection: keep-alive

Body: Hello World

Looks like it works. You might be able to find some groovy code for base64 decode, or maybe there’s something already available through the ST platform.

I see from Alex’s code that he’s doing base64 decode already.

def headerString = new String(parsedEvent.headers.decodeBase64())		
def bodyString = new String(parsedEvent.body.decodeBase64())

The code I’m working with…

I tweaked some of the sonos code and changed the lan discovery portion over to what the cameras should be.

When I run this app, I get 5 responses from “cameras” that all of the same IP address on my local LAN. I get 3 “fixed” camera responses and 2 “pan-tilt” which reflects what I have had setup in my MiCasaVerde Vera Lite setup (I’ll move these over to smartthings when I can).

The interesting bit is that I only have 3 cameras turned on at the moment (2 pan-tilt and 1 fixed) and that the IP address I get as a response is to my Vera Lite. I’m not at all familiar on how upnp devices work, but it appears that the Vera Lite has taken ownership of these three cameras.

(hopefully i’m not hijacking the thread)

@eran Thanks, I did eventually figure that out (and kinda face-palmed once I re-looked at the code)

Danny K has a hacked version of the Foscam working right now by opening a port on your router. However we just began looking into routing traffic through the hub.

@urman Yeah, I saw that and was trying to hack that and add the sendHubCommand stuff above in a device (doesn’t seem to work, no pings on my server).

@Urman, any update on how much longer until Foscam is able to get integrated with ST officially?

Thanks

Eh we’re having some issues with passing a larger image through and storing it on S3. Let me check in with the developer who’s working on it for a clearer idea

I would settle for no image and just control. I want to change the preset based on presence (ie when home turn around and face the wall)

I had it working ( external access) but I can’t use it with my reverse proxy setup. I get an error with my self signed cert.

Hi,

I would be keen to hear if anyone has got this working yet.
I’m trying to send a HTTP command to my video server once a change in presence is detected.

I’m done with the presence code (I think) but I need to send the HTTP command to my server in the local lan.
Any help on how to do is this highly appreciated.