GET on Local Network just not working with HubAction


#1

Ok, I swear I’ve read like a gazillion posts related to this topic. Many are really old, many are just unresolved. But all point to the same solutions that I’ve been trying (in various formats) and it’s simply not working for me. Hopefully someone will see the obvious thing I’m overlooking and maybe this well help future folks hitting this problem.

I’m trying to do something really simple - I have a RPI running a Flask web server. I’m trying to create a Device Handler that with the push of a button will perform a GET request to that server. That’s it. Reading the response would be a bonus but I’m not there yet - ST logs are showing everything as legit but no request is hitting the web server. Of course, a simple browser GET to the address on a different machine on the network indeed hits the server so I’m pretty sure it’s not the RPI’s fault.

Here’s how the device handler looks (I simplified to the least amount of code possible):

metadata {
definition (name: “Garage door Controller”, namespace: “orenaim”, author: “Oren”) {
capability “Switch”
command “door”
}

preferences {
}

tiles(scale:2) {
standardTile(“door”, “device.button”, width: 2, height: 2) {
state “default”, label: “Door”, backgroundColor: “#ffffff”, action: “door”, icon:""
}
}
}

def door() {
log.debug “door2”
def result = new physicalgraph.device.HubAction(
method: “GET”,
path: “/”,
headers: [
HOST: “192.168.86.32:5000”
]
)
log.debug result
return result
}

def parse(physicalgraph.device.HubResponse hubResponse) {
log.debug “Parsing”
def msg = parseLanMessage(description)
log.debug msg.body
}

door action is called but the GET request isn’t actually done. I also tried versions where I invoke the HubAction directly but that didn’t do much either. I tried versions where the host is in hex. And I have the device ID to be the MAC address or host ip in hex too. None of these combinations worked.

So at this point, I’m really out of ideas. It would be AMAZING if someone can tell what’s going wrong here. Thanks!


#2

This is from a similar DTH for a home theater system polled through GET.

def refresh() {

    def hosthex = convertIPtoHex(destIp)
    def porthex = convertPortToHex(destPort)
    device.deviceNetworkId = "$hosthex:$porthex" 

    def hubAction = new physicalgraph.device.HubAction(
   	 		'method': 'GET',
    		'path': "/goform/formMainZone_MainZoneXml.xml",
            'headers': [ HOST: "$destIp:$destPort" ] 
		) 
        
    hubAction
}

def request(body) { 

    def hosthex = convertIPtoHex(destIp)
    def porthex = convertPortToHex(destPort)
    device.deviceNetworkId = "$hosthex:$porthex" 

    def hubAction = new physicalgraph.device.HubAction(
   	 		'method': 'POST',
    		'path': "/MainZone/index.put.asp",
        	'body': body,
        	'headers': [ HOST: "$destIp:$destPort" ]
		) 
              
    hubAction
}


private String convertIPtoHex(ipAddress) { 
    String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02X', it.toInteger() ) }.join()
    return hex
}

private String convertPortToHex(port) {
	String hexport = port.toString().format( '%04X', port.toInteger() )
    return hexport
}

The full text is here:

FYI, if you search for ‘HTTP device type’ here on the forum, it comes back with dozens of posts.


#3

Ryan - thanks so much for replying. I truly appreciate it.

Unfortunately, this didn’t work either. Debug logs all the code did the “right” thing (i.e. device id in proper hex form and hubaction with regular format) but my server is getting nothing.

I did notice something odd though in the device properties page - the “Execution Location” is set to “Cloud”! I’m suspecting that might be the issue and why I’m not reaching my server (i.e. this command isn’t at all running of my hub?). Looking at the ST documentation however, it doesn’t seem like I can do anything about that?

Execution location
With the original SmartThings Hub, all Device handlers execute in the SmartThings cloud. With the new Samsung SmartThings Hub, certain Device handlers may run locally on the Hub or in the SmartThings cloud. Execution location varies depending on a variety of factors, and is managed by the SmartThings internal team.

As a SmartThings developer, you should write your Device Handlers to satisfy their specific use cases, regardless of where the handler executes. There is currently no way to specify or force a certain execution location.

Is there anything I can do about the execution location? Could that really be the crux of the issue?


#4

Ok, so from I read here around the forums there’s no way to create a custom device handler that will run locally. So it’s not that I guess. Presumably even though it runs in the “Cloud” it could reach out to the local network via the hub?


#5

Yes, the processing is in the cloud but issued through your hub to the local IP. I know it’s strange and that hap me confused for a while too. What I don’t understand is why you’re using “HubAction”. Also, the "button"you talk about would have to be the same device…otherwise you’ll need a SmartApp because DTH can’t talk to each other. I’m using a bunch of web-based DTHs. They’re all based around this:


#6

Thanks Ryan. I’m using HubAction because I believe that’s the only way to do an HTTP request on the internal network (i.e. behind my home router), no?

By “button” I was actually referencing the tile in the device page in the SmartThings app, not physical button. I’m creating just a single device handler with a single device instance of it which (at least for now) has just a single tile that when tapped, calls the function with the following code:

def door1() { 
    log.debug "door1 starting"
    def destIp = "192.168.86.32"
    def destPort = 5000
    def hosthex = convertIPtoHex(destIp)
    def porthex = convertPortToHex(destPort)
    device.deviceNetworkId = "$hosthex:$porthex" 
    log.debug "device id is " + device.deviceNetworkId
    def hubAction = new physicalgraph.device.HubAction(
 		'method': 'GET',
		'path': "/",
    	'headers': [ HOST: "$destIp:$destPort" ]
	)       
    log.debug "hubaction is: " + hubAction      
    hubAction
}

Unfortunately, that HTTP request is just ain’t happening… Is there any master setting I should have for the DH perhaps?


(HONGTAT TAN) #7

Is the deviceNetworkId unique in your list of devices?


#8

Yep, it’s set in the code to be the hex version of the IP:port (in my case C0A85620:1388). I confirmed on the device page in the web interface that indeed it’s set to that.


(HONGTAT TAN) #9

Is “C0A85620:1388” unique? No other devices with the same network id? Please post your full code, it’s easier to debug.


#10

Did you even look at the one that I posted?


#11

Yes, it’s unique. Thanks so much for taking a look. Here’s the shortest DH code the reproduces the problem:

metadata {
	definition (name: "Garage", namespace: "orenaim", author: "Oren Naim") {
		capability "Switch"      
        command "door"
	}
	simulator {
	}
	tiles {
		standardTile("door", "device.button", width: 1, height: 1) {
			state "default", label: "Door", backgroundColor: "#ffffff", action: "door", icon:""
		}
	}
}

def door() { 
	log.debug "door starting"
    def destIp = "192.168.86.32"
    def destPort = "5000"
    def hosthex = convertIPtoHex(destIp)
    def porthex = convertPortToHex(destPort)
    device.deviceNetworkId = "$hosthex:$porthex" 
	log.debug "device id is " + device.deviceNetworkId
    
    def hubAction = new physicalgraph.device.HubAction(
   	 		'method': 'GET',
    		'path': "/",
        	'headers': [ HOST: "$destIp:$destPort" ]) 
    log.debug "hubaction is: " + hubAction
    
    hubAction // also tried to "return hubAction"
}

def parse(description) {
    log.debug "parse starting"
    def msg = parseLanMessage(description)
	log.debug msg
}

private String convertIPtoHex(ipAddress) { 
    String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02X', it.toInteger() ) }.join()
    return hex
}

private String convertPortToHex(port) {
	String hexport = port.toString().format( '%04X', port.toInteger() )
    return hexport
}

Logs show:

f8219094-6834-414a-a1da-d646dd72247f 11:18:46 PM: debug hubaction is: GET / HTTP/1.1
Accept: /
User-Agent: Linux UPnP/1.0 SmartThings
HOST: 192.168.86.32:5000

f8219094-6834-414a-a1da-d646dd72247f 11:18:46 PM: debug device id is C0A85620:1388
f8219094-6834-414a-a1da-d646dd72247f 11:18:45 PM: debug door starting
f8219094-6834-414a-a1da-d646dd72247f 11:18:45 PM: debug door starting

Pinging that IP:port from the browser shows both a response (simple hello world) and RPI terminal shows the GET request. That’s not the case when I run the ST command.


#12

Ryan - yes, went through the code. The request building part looks pretty much the same as I did, or am I missing something?


#13

Honestly, all the examples I saw do pretty much the same. That’s what’s driving me nuts here… :frowning:


(HONGTAT TAN) #14

Your code is working fine for me. I’m able to get the response. Is the hub on the same network as your RPi?
Try changing the IP address and port to external website? e.g. google IP address and port 80?


#15

Hongtat - I can’t thank you enough. The moment I saw your note I suspected I might have my hub connected directly to my modem and not behind my router. I just got home and saw indeed that was the case! Fixing the wiring immediately solved the issue.

Thanks again for the time you took to validate my code. :slight_smile: