Posting to a private server from a spark using HTTP,JSON and TCP

Hello again,
I’m currently trying to post too my own private RPi server running [www.emoncms.org][1]. The required format for the server to recieve is:

emoncms/post.json?json={power:789}&apikey=3b172c8064620d9de6dcb4550b4xxxx

I’ve run:

192.168.xxx.xxxemoncms/post.json?json={power:789}&apikey=3b172c8064620d9de6dcb4550b4xxxx 

In my browser and that posts to emoncms as expected. However when I try and do the same using the spark I’m getting nothing at the other end and there’s very limited availible error checking as I’m one of th first people to try and implement wifi into their system.

Here’s my code:

byte server[] = { 192, 168, xxx, xxx }; //dos
/*String line1("http://192.168.1.75/emoncms");
String line2("/input/post.json?apikey=");
String line3("3b172c8064620d9de6dcb4550b49d73c");
String line4("&node=");
String line5("15");
String line7("&csv=");
String line8("789");
*/
//FUNCTION TO TRANSMIT DATA TO DATABASE

void setup()
{
    Serial.begin(9600);
  // start listening for clients
    while(!Serial.available()) SPARK_WLAN_Loop();
    Serial.println("Started");

    transmit();
}
void transmit() {

    String message = "/emoncms/input/post.json?json={power:111}&apikey=3b172c8064620d9de6dcb4550b49xxxx";
    //String line7(message.length()); 
    TCPClient client;
    if(client.connect(server, 80)) {
        Serial.println("connected");
        /*
        message.concat(line1);
        message.concat(line2);
        message.concat(line3);
        message.concat(line4);
        message.concat(line5);
        message.concat(line7);
        message.concat(line8);
        */
        int writeReply = client.write( (uint8_t*)message.c_str(), message.length() );
        delay(20);
        Serial.println("Data Sent");
        Serial.println(writeReply);
        Serial.println(message);

    }

    client.flush();
    client.stop();
    Serial.println(message);
}

Any help would be much appreciated.
[1]: http://www.emoncms.org


I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy

You are calling your web server on PORT 80, so you have to speak in the correct language, wich is HTTP.
So the Bytes you should send to him are something like

HTTP/1.0
GET …

You can make your life much easier if you use the HTTPClient lib from the community libarys

Thanks for the response. Just tried, here’s the serial response:

Application>    Start of Loop.
HttpClient>     Connecting to: 192.168.1.75:80
HttpClient>     Start of HTTP Request.
GET /emoncms/input/post.json?json={power:456}&apikey=3b172c8064620d9de6dcb4550b49xxxx HTTP/1.0
Connection: close
HOST: 192.168.xxx.xxx
Accept: */*
HttpClient>     End of HTTP Request.

HttpClient>     Error: Timeout while reading response.

HttpClient>     End of HTTP Response (5055ms).
HttpClient>     Status Code:
HttpClient>     Error: Can't find HTTP response body.
Application>    Response status: -1
Application>    HTTP Response Body:

Code:

#include "application.h"
#include "HttpClient/HttpClient.h"

/**
* Declaring the variables.
*/
unsigned int nextTime = 0;    // Next time to contact the server
HttpClient http;

// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    //  { "Content-Type", "application/json" },
    //  { "Accept" , "application/json" },
    { "Accept" , "*/*"},
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;

void setup() {
    Serial.begin(9600);
}

void loop() {
    if (nextTime > millis()) {
        return;
    }

    Serial.println();
    Serial.println("Application>\tStart of Loop.");
    // Request path and body can be set at runtime or at setup.
    request.hostname = "192.168.xxx.xxx";
    request.port = 80;
    request.path = "/emoncms/input/post.json?json={power:456}&apikey=3b172c8064620d9de6dcb4550b49xxxx";

    // The library also supports sending a body with your request:
    //request.body = "{\"key\":\"value\"}";

    // Get request
    http.get(request, response, headers);
    Serial.print("Application>\tResponse status: ");
    Serial.println(response.status);

    Serial.print("Application>\tHTTP Response Body: ");
    Serial.println(response.body);

    nextTime = millis() + 10000;
}

Thanks for your input


I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy

Thats an easy problem!
Don’t use hostname with IP. There is a special construct for this!

request.ip = {192,168,xxx,xxx};

will do the trick.

request.hostname uses DNS an does not support the IP4-Dot Syntax

Ok, I tried to update this yesterday but my sparks where refusing to flash. Here’s the serial output when I run my code now. Thanks for your help.

Application>    Start of Loop.
Wales
HttpClient>     Connecting to IP: 192.168.xxx.xxx:80
HttpClient>     Start of HTTP Request.
GET /emoncms/input/post.json?json={power:456}&apikey=3b172c8064620d9de6dcb4550b49xxxx HTTP/1.0
Connection: close
Accept: */*
HttpClient>     End of HTTP Request.

HttpClient>     Error: Timeout while reading response.

HttpClient>     End of HTTP Response (5056ms).
HttpClient>     Status Code:
HttpClient>     Error: Can't find HTTP response body.
Application>    Response status: -1
Application>    HTTP Response Body:

To re-iterate that was after the changes you recommended.

Everything should be ok. Now it looks like a Network problem:
Are you sure, your web server is running. To ensure, try the following:
Make a Telnet connection (on windows there is a command line for this)

telnet 192.168.xxx.xxx 80

The Screen should be BLACK after this. Now Type (blind)

GET

and press return (two times). Now you should see some http stuff as an answer from the server

This is exactly what your spark is trying to do

Ok, I did it using curl because telnet wasn’t working (I have a linux laptop and a win7 desktop) and I got:

curl 192.168.xxx.xxx 80
curl: (56) Recv failure: Connection reset by peer

Ok, this is the same Problem your spark sees. There is something at the other side, but it kills the connection after you send something (Connection Reset by peer).

can you open the URL from a browser?

Yeah I get exactly what I expected back and when I check the server side it shows the data I’m sending.

curl doesn’t work but browser works?

Please check if you Server is configured to

  • only except http 1.1
  • use https
  • requires Authorization (like NTLM or something, you don’t see in your Browser if it happens)
  • spark and Server are NOT on the same network (WLAN)
    All these can result in connection refused

This may sound stupid but, they have to be on the same network!? It’s always been my intention that this will eventually be the case but I didn’t know this needed to be done yet.

As far as I know none of the others are needed and I haven’t found any specifications on thier website. I do however know a developer there so I will try and get in contact with him today.

Thanks again for your help

No, means simply: They have to be on the same network (or on a network which is routable). If server and spark are on different network there needs to be a route (including open ports) to reach each other. (like it is in the whole internet).

Ok, well as I have a spare router lying around and that’s how I intend to run it when It’s finished anyway, I’ll try that now. Thanks again