How to send POST request from arduino to PAC


#1

I have an arduino connected to a temp/humidity.pressure sensor and want to send the data to a PAC via an http POST request. I have the PAC configured with http on port 80 and a GET request running successfully. I’m using Postman as a guide to generate code for arduino.

Postman shows the following HTTP code for a Get request.

GET /api/v1/device/strategy/vars/floats/Humidity HTTP/1.1
Host: 192.168.0.40
Authorization: Basic UG9zdDpydzAxMTU=
Cache-Control: no-cache
Postman-Token: d6ff81ea-8066-5923-2cc9-5e365e52daa6

I implemented in arduino (after establishing Ethernet connection) as :

httpClient.println(“GET /api/v1/device/strategy/vars/floats/Humidity HTTP/1.1”);
httpClient.println(“Host: 192.168.0.40”);
httpClient.println(“Authorization: Basic UG9zdDpydzAxMTU=”);
httpClient.println();

and it works successfully to return the current value. Actual return is:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked

0018
{“value”:3.12000008e+01}
0

Now trying to get POST request to work. . .

Postman HTTP code for successful POST is:

POST /api/v1/device/strategy/vars/floats/Humidity HTTP/1.1
Host: 192.168.0.40
Authorization: Basic UG9zdDpydzAxMTU=
Cache-Control: no-cache
Postman-Token: 0df8d1e8-168e-3073-1bcd-d1bf3c152046

{
“value” : 33.3
}

I attempted implementing in arduino as:

httpClient.println(“POST /api/v1/device/strategy/vars/floats/Humidity HTTP/1.1”);
httpClient.println(“Host: 192.168.0.40”);
httpClient.println(“Authorization: Basic UG9zdDpydzAxMTU=”);
httpClient.println();
httpClient.println("{");
httpClient.println("“value” : 33.3");
httpClient.println("}");
httpClient.println();

The following HTTP was returned:

HTTP/1.1 400 Device Request Error
Content-Type: application/json; charset=UTF-8
Content-Length: 87

{“errorCode”:-8,“message”:“See Opto 22 documentation for error code descriptions.”}

HTTP/1.1 501 Not Implemented
Content-Length: 0

Other HTTP code returned from failed POST request

HTTP/1.1 401 Not Authorized
Content-Type: text/html
WWW-Authenticate: Basic realm=“Authorization Required”

I’ve added an additional set of read/write keys and tried them, but no success.

On rare occasion, I’ve received a 200, success from the Post request, but the value of Humidity was notstrong text changed on the PAC.

Can someone please help me identify the problem?


#2

Change the body of your post to skip the CR/LF (spaces are okay).
So instead of:
{
“value” : 33.3
}

Send:
{“value” : 33.3}

There’s a firmware fix coming soon for that, stay tuned…


#3

FYI, here’s the KB85807 that describes this issue, let me know if you’d like beta firmware with the fix. (The official release should be soon.)


#4

I made mstjohn’s suggested change, but I must have an additional problem, because the POST still doesn’ work. I have firmware 9.5c on my PAC.

I switched to trying GET/POST with restpac.groov.com instead of my own PAC. Both were successful with postman.
With arduino code, GET worked fine. Post, not so much. Following is the POST code:

httpClient.println(“POST /api/v1/device/strategy/vars/int32s/nAnInt32 HTTP/1.1”);
httpClient.println(“Host: restpac.groov.com”);
httpClient.println(“Authorization: Basic xxxxxxx”) //x in place of actual creds for forum
httpClient.println();
httpClient.println("“value” : 1989}"); .
httpClient.println();

Following is the result:

TTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked

0027
{“errorCode”:0,“message”:“Success”}

0

HTTP/1.1 501 Not Implemented
Content-Length: 0

It looks like it is a success, at least at first.
Immediately before running this code, I used a postman POST to successfully set nAnint32 to the value of 1975, and then repeatedly sent GET requests while my arduino code started up. The value stayed at 1975 until about the time of the POST (from arduino) and nAnint32 changed to -47. I tried this a few times with the same result.

I’ve tried with and without the null println before and after the “value” line. The results are similar.

Any help is greatly appreciated.


#5

Looks like your POST might be missing an open curly bracket on your payload? Just before your “value”:1989}
But you should get a better error…


#6

Good eyes!
I made the correction so the line is now:

httpClient.println("{ “value” : 1989}");

I’ve also tried it without any spaces in the string. I’ve also saved the literal string to a string variable and did a println of the string variable, I still get the same results with response of 200, then 501 from the same POST request.

A clue may be that nAnInt32 changes to -47 whenever I get a “200 OK” return message from the PAC. I’ve done this enough that I doubt someone else is posting to the PAC immediately after I do.

???


#7

Oh, wait, you’re talking restpac here? (That variable is probably being used in the logic, since -47 sounds like a return code, let me have a look…)


#8

For those following along, the key here was to make sure the whole request/POST got sent in one packet; for example:

httpClient.println("POST /api/v1/device/strategy/vars/int32s/nAnInt32 HTTP/1.1\r\nHost: restpac.groov.com\r\nAuthorization: Basic cnc6cnc=\r\nContent-Length: 16\r\n\r\n{\"value\" :2} \r\n\r\n");

Big thanks to Dennis for helping us figure out this detail!


#9

Update/correction, the one line thing didn’t do it, we were missing the Content-Length.


#10

This is more Arduino specific, rather than Opto, but since you already have the trailing carriage-return/line-feed, and the println appends this as well, you’ll have three CRLFs at end of the message body which won’t match the content-length.

I would recommend building your post request in a string variable first, then sending it for better readability and the ability to calculate the content length.

[CODE]
String postContent = “{“value” :2}”;

String postRequest = “POST /api/v1/device/strategy/vars/int32s/nAnInt32 HTTP/1.1\r\n”;
postRequest += “Host: restpac.groov.com\r\n”;
postRequest += “Authorization: Basic cnc6cnc=\r\n”;
postRequest += "Content-Length: " + String(postContent.length()) + “\r\n”;

postRequest += “\r\n” + postContent;

httpClient.print(postRequest);
[/CODE]