Spark Core Http Client Library

Been attempting to use this library (and others) to talk to some Node Red REST services I’ve created.
In this thread I explain entirely and still do not reach a conclusion or solution.
I have three client platforms (Core, Chrome Extension, .net application) to diagnose what is wrong.The web service is simple enough, POST three variables to it and it responds. All three client platforms consume the web service successfully however the Core does not close once it has read the response and proceeds to time out. As the other clients do this successfully I can only assume it is the library having some difficulty parsing the response.

On the other thread I have supplied outputs from the Core and the source code is what @krvarma has supplied which he states works (although he has yet to confirm whether his Core times out too).

I believe that while the client is still available it is not connected (as the response has finished). So the library may need to be altered so that line 190 in is not “while (client.available()){” but is “while (client.connected()){”.

Do you have any ideas as to why this may be occuring?

Has anybody got this library to talk to a server on the local network? For me it only works with publicly accessible ip’s. The same sever works when i connect through the external Ip however if I use the local IP it doesn’t. As if the spark core was actually outside my local network…

I was able to use this library to connect to a local network IP address just fine. The response received was the same that shows up in my browser. All looks good there.

But, I think I found a bug. It doesn't appear like the response buffer is cleared between GETs? If I do a get from a page that only has 32 characters, then do a second GET with more than 32 characters, everything looks fine. But, if I then do a 3rd GET to the original 32 character page, I still have the response after character 32 still in the buffer.

Example: GET 1 from Page 1
12345 12345 12345 12345

GET 2 from Page 2
54321 54321 54321 54321 54321 54321

GET 3 from Page 1 (2nd time)
12345 12345 12345 12345 54321 54321

See how the buffer wasn't cleared and the response from the 1st page on the 3rd try still shows the 2nd GET results?

I have attempted my fix for the timeout but it is still occurring. It seems that this library while functional is not mature enough for sub 5 second request timing. I have edited my web service code to bunch information together to nagate the timeout but this is obviously a workaround and not really wanted.
Hopefully I will get back to it and find a fix for the timeout (or someone else will).

I have used internal and external IPs wihout issue. I connect to a local Node Red installation with weird port number and have no problems. Please post code @1devnull so we can look

Have you looked at the faster HTTPclient thread? I made a few changes a while back to use client.write in the library instead of the client.print. this made a huge difference in actually sending the whole request (which for me was where the delay actually was).

Someone recently added a section to parse the content length header and close the connection based on that instead of waiting for a timeout.

Turning off the cloud connection makes a difference too, as discovered when writing the blynk library which has very very fast TCP connections. Have a look at their forums and search for blynk here too. maybe on their github there may be some clues in their code for the core…

Have you tried just using TCP? The timeout isn’t necessarily caused in the HTTP layer.

Here’s the code:

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

/**
* Declaring the variables.
*/

HttpClient http;

IPAddress remoteIP(192, 168, 178, 47);

char resultstr[64];
int nextTime = 0;
//Headers currently need to be set at init, useful for API keys etc.
 http_header_t headers[] = {
  { "Content-Type", "text/plain" },
  { "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.ip = remoteIP;
    request.port = 8080;
    request.path = "/rest/items/landing_light/";

    // The library also supports sending a body with your request:
    //request.body = "{\"key\":\"value\"}";
    sprintf(resultstr, "ON");
    request.body = resultstr;

    http.post(request, response, headers);

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

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

    nextTime = millis() + 10000;
}

It is now working if I ping the spark. Although it takes maybe half a minute of pinging before I can get the connection to work. Sometimes I get flashing cyans and then blinking red. while the requests are still sent out. So I suppose it has something to do with interference with the cloud connectivity…

1 Like

i fix library it work for big json Please wait a minute, I need rest . i made ​​the full day

while (client.available()) {

// Delete line 189 (&& !Done) is work for Big Json Data <<

Hi, I was using Http client before for an other project and everything was working well. Now I just start a new project (on the Photon) and I also need to use this library. However, I am getting a pretty bad response time (a couple a second) for each request. I use the library include in the Particle online IDE.
Any idea of the problem ?

Thanks !

Thanks for all your work on this library.

Is there a way to pass variables into the request.path? I have some sensors connected to the photon and want to pass sensor data to my home based server. I’m thinking something like this?

request.hostname = “192.168.1.2”;
request.port = 80;
request.path = "/GrabData/New?MCID=PHOTONDEVICEIDHERE&Amps1=SENSORDATA

Am I going about this correctly?

I’m not sure if the IP is a valid hostname.
If you already have the IP you should put it into the IP field of request.

Is that the “http_request_t request;”?

Yup!

I found using this format works but only for the first sensor.

request.path = "/GrabData/New/?MCID=" + myID + "&Amps1=" + Amps1 + "&Amps2=" + Amps2 + "&Amps3" + Amps3 + "&Amps4" + Amps4 + "&Amps5" + Amps5 + "&Amps6" + Amps6 + "&Amps7" + Amps7 + "&Amps8" + Amps8 + "&Amps9" + Amps9 + "&Amps10" + Amps10;

Wireshark only shows the first “Amps1” making it through. Any ideas?

Are you missing the equals sign on the other (Amps3 etc) parameters?
Click on frame1402 in Wireshark to get an expanded view.

Yes you are right @timx. I caught that yesterday and added equals on all “&Amps**=**”. I’m still only seeing the first Amps1 go through on Wireshark. Is it because “request.path” requires a String and I’m concatenating doubles?

Try Serial.print()ing your request.path to see what you actually create.

And for building a complex string you could also (better) use sprintf() or even String::format().

1 Like

Thanks I will try that.

I’ve spent several hours on trying to pass the Photon’s deviceID into sprintf() and can’t seem to get any traction on this. My goal here is to have the microcontroller output:
/GrabData/New/?MCID=PhotonSystemIDHere&Amps1=21.0&Amps2=20

I can’t seem to get the PhotonSystemID into the sprintf() statement correctly. I currently have the test code:

double Amps1 = 21;
double Amps2 = 22;
const char* s = System.deviceID();
//String s = System.deviceID();  //this gives error test_sprintf.cpp:12:61: error: cannot pass objects of non-trivially-copyable type 'class String' through '...'
char buf[50];

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

void loop() {
  sprintf(buf, "/GrabData/New/?MCID=%s&Amps1=%.1f\n",s,Amps1);
  Serial.print(buf);
  delay(1000);
}




//attempt4
//sprintf(/* ... */, "%.*s", (int) strlen(str), str);
//-----------------------------------------------------

//attempt3
//--------------------------------------------------------
 //   To convert and append an integer, use operator += (or member function concat):

 //   String stringOne = "A long integer: ";
 //   stringOne += 123456789;

  //  To get the string as type char[], use toCharArray():

 //   char charBuf[50];
 //   stringOne.toCharArray(charBuf, 50) 



//attempt2
//-------------------------------------------------------
// Define 
//String str = "This is my string"; 

// Length (with one extra character for the null terminator)
//int str_len = str.length() + 1; 

// Prepare the character array (the buffer) 
//char char_array[str_len];

// Copy it over 
//str.toCharArray(char_array, str_len);


//attempt1
//---------------------------------------------------------------------
//     sprintf(buff, "Hi %s int a = %d double d = %f\n", b, a, d);
//                  Hi there int a = 15 double d = 20.550000
//Serial.print(buff);


//         To print out 5.00..., you should use %f instead of %g.

//That gives sprintf(word,"%.9f", (double) 5); as correct syntax.

//char str [10] = "IAmCute";
//printf ("%c",str[4]);

The output from Serial monitor is random!

/GrabData/New/?MCID=d&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=&Amps1=21.0
/GrabData/New/?MCID=&Amps1=21.0
/GrabData/New/?MCID=h½ &Amps1=21.0
/GrabData/New/?MCID=h½ &Amps1=21.0
/GrabData/New/?MCID=h½ &Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=h½ h½ 36002100&Amps1=21.0
/GrabData/New/?MCID=´&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0
/GrabData/New/?MCID=h½ ¬&Amps1=21.0