@peterwoolery, yes. You should press on the plus, write exactly the same name and compile. After adding the files you should see the #include line automatically there.
Good luck
@peterwoolery, yes. You should press on the plus, write exactly the same name and compile. After adding the files you should see the #include line automatically there.
Good luck
This still does not work for me!
I’m using a Photon, I tried both importing the library from the web IDE and copy/paste from GitHub the two files: HttpClient.h and HttpClient.cpp
Still get these errors:
HttpClient.cpp: In member function 'void HttpClient::request(http_request_t&, http_response_t&, http_header_t*, const char*)':
HttpClient.cpp:175:37: error: 'millis' was not declared in this scope
unsigned long lastRead = millis();
^
HttpClient.cpp:235:22: error: 'delay' was not declared in this scope
delay(200);
^
HttpClient.cpp:270:47: error: 'atoi' was not declared in this scope
aResponse.status = atoi(statusCode.c_str());
^
HttpClient.cpp:176:19: warning: unused variable 'firstRead' [-Wunused-variable]
unsigned long firstRead = millis();
^
make[1]: *** [../build/target/user/platform-6HttpClient.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.
UPDATE
Here is my (local, cloned from GitHub) HttpClient.cpp header:
#include "HttpClient.h"
#include "application.h"
I still get errors with:
[millis(), delay(), atoi()] was not declared in this scope
Who can help here pls?
Thanks!
Andrea
@scozzy,
I tried to do it again from the beginning and it is working for me.
Try again:
Log out and log in, open new build window
Make new application
Press on the plus and add the CPP and H files with the name HttpClient.
Copy the text.
Try to compile.
HttpClient.cpp:
#include "HttpClient.h"
static const uint16_t TIMEOUT = 5000; // Allow maximum 5s between data packets.
/**
* Constructor.
*/
HttpClient::HttpClient()
{
}
/**
* Method to send a header, should only be called from within the class.
*/
void HttpClient::sendHeader(const char* aHeaderName, const char* aHeaderValue)
{
client.print(aHeaderName);
client.print(": ");
client.println(aHeaderValue);
#ifdef LOGGING
Serial.print(aHeaderName);
Serial.print(": ");
Serial.println(aHeaderValue);
#endif
}
void HttpClient::sendHeader(const char* aHeaderName, const int aHeaderValue)
{
client.print(aHeaderName);
client.print(": ");
client.println(aHeaderValue);
#ifdef LOGGING
Serial.print(aHeaderName);
Serial.print(": ");
Serial.println(aHeaderValue);
#endif
}
void HttpClient::sendHeader(const char* aHeaderName)
{
client.println(aHeaderName);
#ifdef LOGGING
Serial.println(aHeaderName);
#endif
}
/**
* Method to send an HTTP Request. Allocate variables in your application code
* in the aResponse struct and set the headers and the options in the aRequest
* struct.
*/
void HttpClient::request(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[], const char* aHttpMethod)
{
// If a proper response code isn't received it will be set to -1.
aResponse.status = -1;
// NOTE: The default port tertiary statement is unpredictable if the request structure is not initialised
// http_request_t request = {0} or memset(&request, 0, sizeof(http_request_t)) should be used
// to ensure all fields are zero
bool connected = false;
if(aRequest.hostname!=NULL) {
connected = client.connect(aRequest.hostname.c_str(), (aRequest.port) ? aRequest.port : 80 );
} else {
connected = client.connect(aRequest.ip, aRequest.port);
}
#ifdef LOGGING
if (connected) {
if(aRequest.hostname!=NULL) {
Serial.print("HttpClient>\tConnecting to: ");
Serial.print(aRequest.hostname);
} else {
Serial.print("HttpClient>\tConnecting to IP: ");
Serial.print(aRequest.ip);
}
Serial.print(":");
Serial.println(aRequest.port);
} else {
Serial.println("HttpClient>\tConnection failed.");
}
#endif
if (!connected) {
client.stop();
// If TCP Client can't connect to host, exit here.
return;
}
//
// Send HTTP Headers
//
// Send initial headers (only HTTP 1.0 is supported for now).
client.print(aHttpMethod);
client.print(" ");
client.print(aRequest.path);
client.print(" HTTP/1.0\r\n");
#ifdef LOGGING
Serial.println("HttpClient>\tStart of HTTP Request.");
Serial.print(aHttpMethod);
Serial.print(" ");
Serial.print(aRequest.path);
Serial.print(" HTTP/1.0\r\n");
#endif
// Send General and Request Headers.
sendHeader("Connection", "close"); // Not supporting keep-alive for now.
if(aRequest.hostname!=NULL) {
sendHeader("HOST", aRequest.hostname.c_str());
}
//Send Entity Headers
// TODO: Check the standard, currently sending Content-Length : 0 for empty
// POST requests, and no content-length for other types.
if (aRequest.body != NULL) {
sendHeader("Content-Length", (aRequest.body).length());
} else if (strcmp(aHttpMethod, HTTP_METHOD_POST) == 0) { //Check to see if its a Post method.
sendHeader("Content-Length", 0);
}
if (headers != NULL)
{
int i = 0;
while (headers[i].header != NULL)
{
if (headers[i].value != NULL) {
sendHeader(headers[i].header, headers[i].value);
} else {
sendHeader(headers[i].header);
}
i++;
}
}
// Empty line to finish headers
client.println();
client.flush();
//
// Send HTTP Request Body
//
if (aRequest.body != NULL) {
client.println(aRequest.body);
#ifdef LOGGING
Serial.println(aRequest.body);
#endif
}
#ifdef LOGGING
Serial.println("HttpClient>\tEnd of HTTP Request.");
#endif
// clear response buffer
memset(&buffer[0], 0, sizeof(buffer));
//
// Receive HTTP Response
//
// The first value of client.available() might not represent the
// whole response, so after the first chunk of data is received instead
// of terminating the connection there is a delay and another attempt
// to read data.
// The loop exits when the connection is closed, or if there is a
// timeout or an error.
unsigned int bufferPosition = 0;
unsigned long lastRead = millis();
unsigned long firstRead = millis();
bool error = false;
bool timeout = false;
do {
#ifdef LOGGING
int bytes = client.available();
if(bytes) {
Serial.print("\r\nHttpClient>\tReceiving TCP transaction of ");
Serial.print(bytes);
Serial.println(" bytes.");
}
#endif
while (client.available()) {
char c = client.read();
#ifdef LOGGING
Serial.print(c);
#endif
lastRead = millis();
if (c == -1) {
error = true;
#ifdef LOGGING
Serial.println("HttpClient>\tError: No data available.");
#endif
break;
}
// Check that received character fits in buffer before storing.
if (bufferPosition < sizeof(buffer)-1) {
buffer[bufferPosition] = c;
} else if ((bufferPosition == sizeof(buffer)-1)) {
buffer[bufferPosition] = '\0'; // Null-terminate buffer
client.stop();
error = true;
#ifdef LOGGING
Serial.println("HttpClient>\tError: Response body larger than buffer.");
#endif
}
bufferPosition++;
}
buffer[bufferPosition] = '\0'; // Null-terminate buffer
#ifdef LOGGING
if (bytes) {
Serial.print("\r\nHttpClient>\tEnd of TCP transaction.");
}
#endif
// Check that there hasn't been more than 5s since last read.
timeout = millis() - lastRead > TIMEOUT;
// Unless there has been an error or timeout wait 200ms to allow server
// to respond or close connection.
if (!error && !timeout) {
delay(200);
}
} while (client.connected() && !timeout && !error);
#ifdef LOGGING
if (timeout) {
Serial.println("\r\nHttpClient>\tError: Timeout while reading response.");
}
Serial.print("\r\nHttpClient>\tEnd of HTTP Response (");
Serial.print(millis() - firstRead);
Serial.println("ms).");
#endif
client.stop();
String raw_response(buffer);
// Not super elegant way of finding the status code, but it works.
String statusCode = raw_response.substring(9,12);
#ifdef LOGGING
Serial.print("HttpClient>\tStatus Code: ");
Serial.println(statusCode);
#endif
int bodyPos = raw_response.indexOf("\r\n\r\n");
if (bodyPos == -1) {
#ifdef LOGGING
Serial.println("HttpClient>\tError: Can't find HTTP response body.");
#endif
return;
}
// Return the entire message body from bodyPos+4 till end.
aResponse.body = "";
aResponse.body += raw_response.substring(bodyPos+4);
aResponse.status = atoi(statusCode.c_str());
}
HttpClient.h:
#ifndef __HTTP_CLIENT_H_
#define __HTTP_CLIENT_H_
#include "application.h"
#include "spark_wiring_string.h"
#include "spark_wiring_tcpclient.h"
#include "spark_wiring_usbserial.h"
/**
* Defines for the HTTP methods.
*/
static const char* HTTP_METHOD_GET = "GET";
static const char* HTTP_METHOD_POST = "POST";
static const char* HTTP_METHOD_PUT = "PUT";
static const char* HTTP_METHOD_DELETE = "DELETE";
static const char* HTTP_METHOD_PATCH = "PATCH";
/**
* This struct is used to pass additional HTTP headers such as API-keys.
* Normally you pass this as an array. The last entry must have NULL as key.
*/
typedef struct
{
const char* header;
const char* value;
} http_header_t;
/**
* HTTP Request struct.
* hostname request host
* path request path
* port request port
* body request body
*/
typedef struct
{
String hostname;
IPAddress ip;
String path;
// TODO: Look at setting the port by default.
//int port = 80;
int port;
String body;
} http_request_t;
/**
* HTTP Response struct.
* status response status code.
* body response body
*/
typedef struct
{
int status;
String body;
} http_response_t;
class HttpClient {
public:
/**
* Public references to variables.
*/
TCPClient client;
char buffer[1024];
/**
* Constructor.
*/
HttpClient(void);
/**
* HTTP request methods.
* Can't use 'delete' as name since it's a C++ keyword.
*/
void get(http_request_t &aRequest, http_response_t &aResponse)
{
request(aRequest, aResponse, NULL, HTTP_METHOD_GET);
}
void post(http_request_t &aRequest, http_response_t &aResponse)
{
request(aRequest, aResponse, NULL, HTTP_METHOD_POST);
}
void put(http_request_t &aRequest, http_response_t &aResponse)
{
request(aRequest, aResponse, NULL, HTTP_METHOD_PUT);
}
void del(http_request_t &aRequest, http_response_t &aResponse)
{
request(aRequest, aResponse, NULL, HTTP_METHOD_DELETE);
}
void get(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[])
{
request(aRequest, aResponse, headers, HTTP_METHOD_GET);
}
void post(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[])
{
request(aRequest, aResponse, headers, HTTP_METHOD_POST);
}
void put(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[])
{
request(aRequest, aResponse, headers, HTTP_METHOD_PUT);
}
void del(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[])
{
request(aRequest, aResponse, headers, HTTP_METHOD_DELETE);
}
void patch(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[])
{
request(aRequest, aResponse, headers, HTTP_METHOD_PATCH);
}
private:
/**
* Underlying HTTP methods.
*/
void request(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[], const char* aHttpMethod);
void sendHeader(const char* aHeaderName, const char* aHeaderValue);
void sendHeader(const char* aHeaderName, const int aHeaderValue);
void sendHeader(const char* aHeaderName);
};
#endif /* __HTTP_CLIENT_H_ */
Good luck!
Hello @itayd100,
yes, I think you are right, the solution is starting back from scratch!
And I found what happened::
to use the “local” HttpClient.h and .cpp files you need to explicitly remove the HttpClient library from your application! That is (in the Web IDE) on the left side click on the “x” to remove the library and confirm. Otherwise it will continue using the imported official library rather than the copy/paste files!
Thanks for your help!
Andrea
Thanks! This worked for me. I was having the same issue. I do hope we will get a proper library though… because now our code is static.