Asynchronous HTTP Beta Feedback Thread

Hi all!

Please use this thread to provide feedback for the ASync HTTP beta.

Documentation on the new API can be found here.

@slagle

This is probably a stupid question, but does it matter where I place

include ‘asynchttp_v1’

?

Do you know of any other examples (other than the one in the documentation) or apps that use this?

Thanks,
Tony

When I call this from a Device Handler, the method returns null (so cannot be returned like HubAction) and it does not invoke any operation on the Web Service nor leave any logs.

Do we have to do anything special to enable this on our hubs?

def SetPositionWithCall(degrees) {

	def params = [
        uri: 'https://' + getHostAddress(),
        path: '/char-write-req',
        query: [value: degrees],
        contentType: 'application/json'
    ]
    log.debug params
	def t = asynchttp_v1.get("setDegreesResponse", params)
    log.debug t

Actually - looking at the API docs it appears this is sent to the SmartThings cloud to execute, can we not execute this locally on our SmartHubs? Even if I execute the call as given by example in the API, making an external call (to GitHub) it does not return.

It doens’t

You cannot at the moment.

Any updates on this? I’ve tried it in a few of my apps, and it’s great stuff. Would love to get it to run on my hub locally and replace some of the hubAction mess I’ve been running.

Would love it even more if it worked locally on hub AND supported HTTPS.

1 Like

It doesn’t support https??? Their example here (https://gist.github.com/jimmyjames/85a1a46fbd7fc077dee78f6ae1d865c0) uses https.

To clarify - yes, the new async method does support https. However, it’s not available to be called from within your hub locally.

There is an async hubAction call currently possible on the local hub, but that one does not support https.

1 Like

Hi some feedback on this API.

We’re seeing that for httpGet API the response.data is of type java.io.StringReader whereas for httpGet asynchronous API the response.data is of type String.

I bring this up for consistency and reuse of code purposes. We’re trying to migrate our code to httpGet async and looking to reuse as much code as possible. So far so good with the exception of this one point.

There is another issue I would like to point out.

With httpGet (sync) when a device (camera) returns an image object the header Content-type contains a value of image.jpeg

When the same data is returned with httpGet (Asynchronous), the header contains null. I don’t know if this is by design of an issue that needs to be fixed.

This is what the response looks like from a camera when it sends an image

Received response from camera to async httpGet, headers=null, status=200, data=[:]

Is there any specific setting that needs to be set while calling httpGet in term of the map parameter contentType or requestContentType?

EDIT: The other difference is that httpGet asynchronous contains a String in response.data when the camera returns an image where as httpGet synchronous contains a byteArrayInputStream for an image response.

EDIT2: Another quirk with httpGet asynchronous, when sending plain text the header contains the key Content-Type

headers=[Content-Type:text/plain, Transfer-Encoding:chunked, Date:Wed, 25 Oct 2017 19:49:32 GMT, Server:lighttpd/1.4.31]
Where as with some images the header contains the key Content-type (the Type has a case difference) and other times it’s null
headers=[Content-type:image/jpeg, Content-Length:151108, Date:Wed, 25 Oct 2017 19:50:49 GMT, Server:lighttpd/1.4.31]

@slagle what’s the encoding using on the string returned in the response.data? Trying to parse some images being returned but appears to be UTF-8 encoded but can’t be certain. Any way to get the raw byte stream returned?

Suppose that myAsyncResponse is the object of type physicalgraph.scheduling.AsyncResponse that the SmartThings platform passes to the response handler during an asynchronous http request for some particular http request. Suppose that myResponse is the object of type groovyx.net.http.HttpResponseDecorator that the Smartthings platform passes to the closure passed to the (synchronous) httpGet method during a synchronous http request. Suppose that both the synchronous http request and the asynchronous http request use the exact same parameter values. In this case, we would expect myAsyncResponse.data to contain the same information as myResponse.data, even if the two might be in different forms. Unfortunately, this does not seem to be the case. It appears that the expression “myAsyncResponse.getData()” evaluates to the same String value as the expression “{def bytes = []; while (myResponse.data.available() > 0){bytes += myResponse.data.read()}; return new String(bytes as byte[]);}()”. The String constructed from an array of bytes generally contains less information than the array of bytes, because most charsets are not able to encode all 256 possible byte values. The String(byte[]) constructor, I think, assumes that the array of bytes represents a string encoded with the system default charset. In cases where the content in the response data is json or html, any character encoding that preserves the US-ASCII code points is likely to be acceptable. However, if the content is a JPEG or a PNG image, than it is critical that we be able to recover all 256 possible byte values from the response data. As far as I can tell, the SmartThings platform makes it impossible to do this with an asynchronous http request.

Hey SmartThings tech support: Is there any way to extract from the AsyncResponse object the array of bytes that were contained in the content of the original http response, with all 256 byte values faithfully represented?

Currently there’s an issue with the platform which is causing it to strip out the body of the response from certain HTTP and UDP device callbacks. ST’s engineers are looking into it, it was due to be fixed about a week ago, hopefully it’ll be fixed soon and may fix this issue as well.

The symptoms I am observing are not so much a missing or empty response body. The symptoms are more consistent with a response body that has been processed by converting the array of bytes in the original response body into a string using the system default charset; when I compare the array of byte values produced by “myAsyncResponse.data.getBytes()” (or “myAsyncResponse.data.getBytes(‘US-ASCII’)” or “myAsyncResponse.data.getBytes(‘ISO-8859-1’)”) with the array of bytes produced by reading the bytes one-by-one from myResponse.data, the two are very nearly the same. The only difference is that myAsyncResponse.data.getBytes() tends to be a bit shorter, and some of the values (particular those between 128 and 255) have been converted to a different value (usually less than 128) or omitted entirely. In my limited test case, I observed that the byte array myAsyncResponse.data.getBytes() was exactly the same as the byte array produced by converting the byte array read out from myResponse.data into a string and then back into a byte array. This makes me suspect that somewhere in the SmartThings platform’s processing of the http response, the raw byte array gets converted into a string (perhaps by being passed to the String(byte[]) constructor). It is this conversion from byte array to String where the original byte values get mucked up.