C/c++ (arduino) PUT request

Gents,

I have an arduino that I’d like to use as an alternative to Zwave. However, it’s too far to hook up with any type of serial. But I have network. So I got the ethernet shield, and I’m communicating (I see all my errors in the console! :stuck_out_tongue: )

IF anyone knows C better than me (I’m very new at arduino) and how OH expects the API call (the CURL example in the docs site doesn’t help me much)… I could use some guidance. I’m just simply trying to push “1” as a test to my item state.

if (client.connect(server,8080)){ client.println("PUT /rest/items/"+item+"/state"); client.println("Host: 192.168.1.100"); client.println("Content-Type: text/plain"); client.println("Accept: application/json"); client.println("Connection: Keep-Alive"); client.println("Content-Length: 1"); client.println("1"); }

The peice itself is a function I’m passing item and state into. Item being string, state being int (currently anyway).

I get this
23:22:36.966 [WARN ] [thome.io.rest.core.item.ItemResource] - Received HTTP PUT request at 'items/temperature/state' with an invalid status value ''.

I’ve tried modifying how the PUT request actually gets built but to no success.

Thanks for any input! I’m happy to share the rest of the arduino sketch if anyone is interested - But my sketch probably looks like childs play compared to people that know what they’re doing.

The reason why curl exists is that it hides a HUGE amount of specially formatted text that makes up an HTTP request.

Things I notice about the above:

  • examples I see include a HTTP version as the second field passed on the PUT line
  • there must be a blank line between Content-Length and the 1
  • in all the examples I’ve seen online there is always a User-Agent.

Based on the result you are seeing I’d venture to guess the main problem is the missing blank line between the header and the body.

A great way to figure this sort of thing out is to use curl with the --trace file.txt argument which will save to file.txt all of the messages sent and received. So make it work with curl, and once it works, look in file.txt to see what the actual message was that was sent and make sure what you are sending is identical, including newlines and blank lines.

Now sure why I didn’t see this reply alert.

Thanks @rlkoshak! I’m going to give that a shot.

Just an FYI for people checking out the REST API via an Arduino. This code can be used to send a command to the Openhab REST API. It sets the item “Wifi_switch” state to ON.

// if there's a successful connection:
  if (client.connect("192.168.1.10", 8080)) {
    Serial.println("connecting...");
    // send the HTTP POST request:
    client.println("POST /rest/items/Wifi_switch HTTP/1.1");
    client.println("Host: 192.168.1.10");
    client.println("User-Agent: Arduino/1.0");
    client.println("Connection: close");
    client.println("Content-Type: text/plain");
    client.println("Content-Length: 2");
    client.println();
    client.println("ON");
    client.println();
    
    Serial.println("Message was sent");
  } else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }

trying this,
however im getting error,

this is my code:
if (httpPost.connect("192.168.1.110", 8080)) {
Serial.println("Server Connected");
httpPost.println("POST /rest/items/Boiler_Switch HTTP/1.1");
httpPost.println("Host: 192.168.1.110");
//httpPost.println("Accept: application/json");
//httpPost.println("cache-control: no-cache");
httpPost.println("User-Agent: Arduino/1.0");
httpPost.println("Connection: close");
httpPost.println("Content-Type: text/plain");
httpPost.print("Content-Length: 2");
//httpPost.println(payload.length());
httpPost.println();
httpPost.println("ON");
httpPost.println();
Serial.println("Message Sucessfully sent to OH Server");
}

and here is debug level errors, not sure where Illegal character LF=\n in state=HEADER applies to…

21:37:52.279 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - parseNext s=START HeapByteBuffer@58777396[p=0,l=157,c=8192,r=157]={<<<POST /rest/items/...ngth: 2\r\nON\r\n\r\n>>>n%2525253A9%25255...\x00\x00\x00\                           x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
21:37:52.280 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - START --> SPACE1
21:37:52.280 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - SPACE1 --> URI
21:37:52.280 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - URI --> SPACE2
21:37:52.280 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - SPACE2 --> REQUEST_VERSION
21:37:52.280 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - REQUEST_VERSION --> HEADER
21:37:52.281 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Host --> VALUE
21:37:52.281 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Host --> IN_VALUE
21:37:52.281 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Host --> FIELD
21:37:52.281 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:User-Agent --> VALUE
21:37:52.281 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:User-Agent --> IN_VALUE
21:37:52.282 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:User-Agent --> FIELD
21:37:52.282 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Connection: close --> IN_VALUE
21:37:52.282 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Connection: close --> FIELD
21:37:52.282 [DEBUG] [se.jetty.util.thread.QueuedThreadPool] - run ReservedThreadExecutor@3800d5cd{s=0/4,p=1}@21102d8d
21:37:52.282 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Content-Type: text/plain --> IN_VALUE
21:37:52.282 [DEBUG] [ty.util.thread.ReservedThreadExecutor] - ReservedThreadExecutor@3800d5cd{s=1/4,p=1}@21102d8d started
21:37:52.283 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Content-Type: text/plain --> FIELD
21:37:52.283 [DEBUG] [ty.util.thread.ReservedThreadExecutor] - ReservedThreadExecutor@3800d5cd{s=1/4,p=0}@21102d8d waiting
21:37:52.283 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Content-Length --> VALUE
21:37:52.283 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Content-Length --> IN_VALUE
21:37:52.283 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER:Content-Length --> FIELD
21:37:52.284 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER: --> IN_NAME
21:37:52.284 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - Illegal character LF=\n in state=HEADER for buffer HeapByteBuffer@58777396[p=155,l=157,c=8192,r=2]={POST /rest/items/...Length: 2\r\nON\r\n<<<\r\n>                           >>n%2525253A9%25255...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
21:37:52.285 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - Parse exception: HttpParser{s=HEADER,0 of 2} for HttpChannelOverHttp@32ea7e37{r=0,c=false,a=IDLE,uri=null,age=0}
org.eclipse.jetty.http.HttpParser$IllegalCharacterException: 400: Illegal character LF=\n
        at org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1363) [74:org.eclipse.jetty.http:9.4.11.v20180605]
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1508) [74:org.eclipse.jetty.http:9.4.11.v20180605]
        at org.eclipse.jetty.server.HttpConnection.parseRequestBuffer(HttpConnection.java:360) [84:org.eclipse.jetty.server:9.4.11.v20180605]
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:250) [84:org.eclipse.jetty.server:9.4.11.v20180605]
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281) [75:org.eclipse.jetty.io:9.4.11.v20180605]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) [75:org.eclipse.jetty.io:9.4.11.v20180605]
        at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) [75:org.eclipse.jetty.io:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680) [87:org.eclipse.jetty.util:9.4.11.v20180605]
        at java.lang.Thread.run(Thread.java:748) [?:?]
21:37:52.285 [DEBUG] [org.eclipse.jetty.http.HttpParser    ] - HEADER --> CLOSE

Maybe you need a ‘println’ here too? So instead of:

Try:

HttpPost.println("Content-Length: 2");

arggg… Missed that!
Works like a charm! thanks