AsyncResponse Documentation

Hi all, I'm working on an app that will log things in Google Sheets. I figured it was wise to use asynchttpPost. The post is working fine but I can't seem to figure out the error handling.

I've tried many of the methods documented here but everything but getStatus() and getHeaders() throws java.lang.Exception

Here's my code:


def sendAsynchttpPost(args) {
    def postParams = [
		uri: baseUrl(),
		requestContentType: 'application/json',
		contentType: 'application/json',
		body : args.value
	]
    log.debug ("sendAsynchttpPost: sending: ${args}")
	asynchttpPost('httpPostCallback', postParams, [requestKey: args.key])
}

def httpPostCallback(response, data) {
    log.debug "status of post call is: ${response.getStatus()} and data is: ${data}"
    if(response.hasError()) {
        try{
            log.debug "getHeaders()	: ${response.getHeaders()}"
            log.debug "getData()	: ${response.getData()}"
            log.debug "getData()	: ${response.getData()}"
            log.debug "getErrorData()	: ${response.getErrorData()}"
            log.debug "getErrorMessage()	: ${response.getErrorMessage()}"
            log.debug "getJson()	: ${response.getJson()}"
        }
        catch(e) {
            log.debug e.toString()
        }
    }
 }

I can't

you can get a full list of the return post using "response.properties" . This will identify the available data fields (i.e., data, json, etc) in the response as well as data that may point you to an error in the original message. That will help to guide what is in the response.

below is some working code using httpPost and (if an error) resp.properties. note that my url is an https://..... If yours url is an https, you will need the "ignoreSSLIssues: true" in the parameters.

def asyncSend(cmdBody, method, action) {
	Map cmdData = [cmdBody: cmdBody, method: method, action: action]
	Map logData = [method: "asyncSend", cmdData: cmdData]
	state.lastCmd = cmdData
	def reqParams = [
		uri: "${getDataValue("baseUrl")}/?token=${token}",
		body: cmdBody,
		contentType: "application/json",
		requestContentType: "application/json",
		ignoreSSLIssues: true,
		timeout: 4
	]
	try {
		asynchttpPost(action, reqParams, [data: method])
		logData << [status: "OK"]
		logDebug(logData)
	} catch (err) {
		logData << [status: "FAILED", error: err, ]
		logWarn(logData)
	}
}

def refreshParse(resp, data=null) {
	Map logData = [method: "refreshParse"]
	try {

		def respData = parseData(resp)
      catch(e) {}
//  Deleted code that generates attributes from the respData
}

def parseData(resp) {
	def logData = [method: "parseData"]
	def cmdResp = "ERROR"
	if (resp.status == 200) {
		cmdResp = resp.json
		logData << [status: "OK", cmdResp: cmdResp]
		if (device.currentValue("commsError") == "true") {
			logData << [resetError: setCommsError(false)]
		}
		state.errorCount = 0
	} else {
		logData << [status: "httpFailure(timeout)", data: resp.properties]
		handleCommsError("httpFailure")
	}
	logDebug(logData)
	return cmdResp
}
1 Like

Thx as always @djgutheinz for the quick and helpful response. I will give this a shot and see if it works.

I'm curious why you have both parseData and refreshParse methods. Could you explain?

I use the same method to send the HTTP Sync method from all commands (on, off, set color, turn start vacuuming, etc) with different parse methods (action) depending on the expected return data. Then the "action" method call the parse method (all responses from these devices require the same decoding/formatting prior to actually extracting the response data).

Reduces code to develop and validate as well as troubleshoot. If there is an error raised from parseData method, I only have to fix it once. May not be necessary in your implementation!