Unable to send a POST request from a device type

For some reason in my device type returning a POST HubAction from one of my command handlers does not result in the POST request being made. I have confirmed with Wireshark that no request is ever made to the machine that is targeted by the request.

Below is the source code for my service manager and the device type. Clearly I am doing something wrong. Can anyone spot why my POST isn’t being sent?

I trigger the post by doing the on command.

SmartApp:

`definition(
name: “ISY Service Manager”,
namespace: “rodtoll”,
author: “Rod Toll”,
description: “2 - Service Manager App for ISY 994i. Discovers the ISYs and does status updates to the devices.”,
category: “My Apps”,
iconUrl: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png”,
iconX2Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”,
iconX3Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”)

preferences {
section(“Information”) {

}
}

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

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

//unsubscribe()
//initialize()
}

def unsubscribe() {
log.debug “Uninstalled”
}

def locationHandler(evt) {
log.debug “locationHandler() called”
}

private String makeNetworkId(ipaddr, port) {
String hexIp = ipaddr.tokenize(’.’).collect {
String.format(’%02X’, it.toInteger())
}.join()
String hexPort = String.format(’%04X’, port)
return “${hexIp}:${hexPort}”
}

def initialize() {
log.debug "STARTUP: initialize()"
subscribe(location, null, locationHandler, [filterEvents:false])
def dni = makeNetworkId(“10.0.1.44”,3000)
log.debug "STARTUP: dni: "+dni
def newDevice = addChildDevice(‘rodtoll’, ‘ISY Hub’, dni, null, [label:name.toString(),completedSetup: true])
log.debug “STARTUP: Created new device”
}

def parse(result) {
log.debug “Got a parse() message”
}
`

DeviceType:

metadata {
definition (name: “ISY Hub”, namespace: “rodtoll”, author: “Rod Toll”) {
capability "Polling"
capability "Refresh"
capability “Switch”
}

simulator {
// TODO: define status and reply messages here
}

tiles {
    standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
    state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
    state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
    }
}
main "switch"
details(["switch"])

}

preferences {
section(“Information”) {
}
}

// parse events into attributes
def parse(String description) {
log.debug “Parsing ‘${description}’”
}

// handle commands
def poll() {
log.debug “Executing ‘poll’”
}

def refresh() {
log.debug “Executing ‘refresh’”
}

private getAuthorization() {
def userpassascii = “admin” + “:” + "password"
log.debug 'AUTH: '+userpassascii
"Basic " + userpassascii.encodeAsBase64().toString()
}

def off() {
on()
}

def on() {
def hub = location.hubs[1]
log.debug ‘SUBSCRIBE: Hub: ‘+hub
def localHubIp = hub.localIP
def localPort = hub.localSrvPortTCP
def subscribeUrl = ‘http://’+localHubIp+’:’+localPort+’/'
log.debug ‘SUBSCRIBE: Callback address…’ + subscribeUrl
def bodyText = '<s:Envelope><s:Body><u:Subscribe xmlns:u=“urn:udi-com:service:X_Insteon_Lighting_Service:1”>'
bodyText += ‘’+subscribeUrl+‘infinite</u:Subscribe></s:Body></s:Envelope>’;
log.debug “SUBSCRIBE: Body Text…” + bodyText
def result = new physicalgraph.device.HubAction(
method: “POST”,
path: “/services”,
body: bodyText,
headers: [
HOST: ‘10.0.1.44:3000’,
Authorization: getAuthorization()
]
)
return result
}

Try uuencode your response URL?

I tried taking out the subscribeUrl text completely and it still didn’t send any traffic from the SmartThings hub to the remote host @ 10.0.1.44:3000. I own the host at that address and have a network sniffer running.

Am I building the HubAction correctly? Am I setting the dni correctly for the device? Is returning the HubAction from the on() command the right approach?

Is the host on the lan? Or is it external? Do you have a hub assigned in the device settings in the ide?

Can’t do wan requests with localhubaction use httppost instead.

The host is on the LAN, same subnet as the SmartThings hub.

Checking the IDE no hub is associated with the device. How do I assign the hub? I know there is a hub parameter in the addChildDevice call but in the samples I’ve work with is null. What do you set this to? Is it the location.hub[correct index] or something else?

Setting the hub did it. The call is now headed out.

Incoming callback messages are going to the SmartApp location’s handler but that works just fine for me. :smile:

Thank you for the help!

This worked with my simulated device (software I built to emulate the device) but unfortunately did not work with the actual device. Turns out the device is sending the SmartThings hub HTTP POST messages but SmartThings is rejecting them. Looks like it is because the content-length header doesn’t have a space between the : and the length. Will post a separate message about that issue.

But for future readers of this thread what made it work, at least with my simulated device was:

  1. Created a smartapp which Created a device type to represent the remote hub I want to work with with a dni which is a hex representation of the address and port of the device I wanted to get POST requests from.

  2. Ensure that the device type for the remote hub is created with the hub id specified in the hub parameter. Realized I needed to walk through the location.hubs collection to find the PHYSICAL hub. (There was a virtual one). And specify the hub id in device.

  3. Call into the device type and ask it to send out the broadcast. Make sure I got the callback address and port from the hub properties of the PHYSICAL hub.

  4. The result of my subscription call returned in the device’s parse method.

  5. Incoming POST requests received from the remote hub were sent to the location handler of the smartapp. Needed to of course decode them using parseLanMessage calls. Note that I had a weird problem where the xml content type wasn’t properly specified so I needed to manually use an XmlSlurper with the body content.

Hope this helps someone else struggling with this. I’ll post code at a later date.