first commit

This commit is contained in:
Jérôme Delacotte
2025-03-06 11:15:32 +01:00
commit 7b30d6e298
5276 changed files with 2108927 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
/*
Copyright (c) 2016, 2021 Imre Horvath. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "BridgeHttpClient.h"
BridgeHttpClient::BridgeHttpClient()
: _isInsecureEnabled(false),
_user(NULL),
_passwd(NULL),
_extraHeaderIdx(0) {
}
void BridgeHttpClient::get(const char *url) {
request("GET", url, NULL);
}
void BridgeHttpClient::post(const char *url, const char *data) {
request("POST", url, data);
}
void BridgeHttpClient::put(const char *url, const char *data) {
request("PUT", url, data);
}
void BridgeHttpClient::del(const char *url) {
request("DELETE", url, NULL);
}
void BridgeHttpClient::getAsync(const char *url) {
request("GET", url, NULL, true);
}
void BridgeHttpClient::postAsync(const char *url, const char *data) {
request("POST", url, data, true);
}
void BridgeHttpClient::putAsync(const char *url, const char *data) {
request("PUT", url, data, true);
}
void BridgeHttpClient::delAsync(const char *url) {
request("DELETE", url, NULL, true);
}
bool BridgeHttpClient::finished() {
return !running();
}
unsigned int BridgeHttpClient::getResponseCode() {
Process p;
p.runShellCommand("head -n 1 " + _tempFileName + " | cut -d' ' -f2");
return p.parseInt();
}
String BridgeHttpClient::getResponseHeaders() {
String responseHeaders;
Process p;
p.runShellCommand("tail -n +2 " + _tempFileName);
while (p.available() > 0) {
char c = p.read();
responseHeaders += c;
}
responseHeaders.trim();
return responseHeaders;
}
void BridgeHttpClient::enableInsecure() {
_isInsecureEnabled = true;
}
int BridgeHttpClient::addHeader(const char *header) {
if (_extraHeaderIdx < maxNumberOfExtraHeaders) {
_extraHeaders[_extraHeaderIdx++] = header;
return 0;
}
return -1;
}
void BridgeHttpClient::basicAuth(const char *user, const char *passwd) {
_user = user;
_passwd = passwd;
}
void BridgeHttpClient::clearHeaders() {
_extraHeaderIdx = 0;
}
void BridgeHttpClient::clearAuth() {
_user = _passwd = NULL;
}
bool BridgeHttpClient::getResponseHeaderValue(const String& header, String& value) {
// Cache the response headers for subsequent calls
if (_cachedRespHeaders.length() == 0) {
_cachedRespHeaders = getResponseHeaders();
}
// Handle the case when the header is not found
int startOfHeader = _cachedRespHeaders.indexOf(header);
if (startOfHeader == -1) {
return false; // Return false if the header was not found
}
// Get the header value
int startOfValue = _cachedRespHeaders.indexOf(':', startOfHeader) + 1;
String respValue = _cachedRespHeaders.substring(startOfValue,
_cachedRespHeaders.indexOf('\n', startOfValue));
respValue.trim();
value = respValue;
return true;
}
void BridgeHttpClient::startRequest() {
clearHeaders();
clearAuth();
_isInsecureEnabled = false;
}
void BridgeHttpClient::request(const char *verb, const char *url, const char *data, bool async) {
Process p;
p.runShellCommand("mktemp");
_tempFileName = p.readStringUntil('\n');
clearCachedRespHeaders();
begin("curl");
addParameter("-D");
addParameter(_tempFileName);
if (verb != "GET") {
addParameter("-X");
addParameter(verb);
}
if (_isInsecureEnabled) {
addParameter("-k");
}
if (_user && _passwd) {
String auth;
auth += _user;
auth += ":";
auth += _passwd;
addParameter("-u");
addParameter(auth);
}
for (int i = 0; i < _extraHeaderIdx; i++) {
addParameter("-H");
addParameter(_extraHeaders[i]);
}
if (data != NULL) {
addParameter("-d");
addParameter(data);
}
addParameter(url);
if (async) {
runAsynchronously();
} else {
(void) run();
}
}
void BridgeHttpClient::clearCachedRespHeaders() {
_cachedRespHeaders = "";
}

View File

@@ -0,0 +1,165 @@
/*
Copyright (c) 2016, 2021 Imre Horvath. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BRIDGE_HTTP_CLIENT_H_
#define _BRIDGE_HTTP_CLIENT_H_
#include <Process.h>
class BridgeHttpClient : public Process {
public:
/*
* Constructor
*/
BridgeHttpClient();
/*
* Synchronous methods
*/
void get(const char* url);
void get(const String& url) {get(url.c_str());}
void post(const char* url, const char* data);
void post(const String& url, const char* data) {post(url.c_str(), data);}
void post(const char* url, const String& data) {post(url, data.c_str());}
void post(const String& url, const String& data) {post(url.c_str(), data.c_str());}
void put(const char* url, const char* data);
void put(const String& url, const char* data) {put(url.c_str(), data);}
void put(const char* url, const String& data) {put(url, data.c_str());}
void put(const String& url, const String& data) {put(url.c_str(), data.c_str());}
void del(const char* url);
void del(const String& url) {del(url.c_str());}
/*
* Asynchronous methods
*/
void getAsync(const char* url);
void getAsync(const String& url) {getAsync(url.c_str());}
void postAsync(const char* url, const char* data);
void postAsync(const String& url, const char* data) {postAsync(url.c_str(), data);}
void postAsync(const char* url, const String& data) {postAsync(url, data.c_str());}
void postAsync(const String& url, const String& data) {postAsync(url.c_str(), data.c_str());}
void putAsync(const char* url, const char* data);
void putAsync(const String& url, const char* data) {putAsync(url.c_str(), data);}
void putAsync(const char* url, const String& data) {putAsync(url, data.c_str());}
void putAsync(const String& url, const String& data) {putAsync(url.c_str(), data.c_str());}
void delAsync(const char* url);
void delAsync(const String& url) {delAsync(url.c_str());}
/*
* Method to check, if the async request is still running or has finished.
*/
bool finished();
/*
* Call this method after the request has finished,
* to get the HTTP response code from the server.
*
* Returns the response code eg. 200
*/
unsigned int getResponseCode();
/*
* Call this method after the request has finished,
* to get the response headers received from the server.
*
* Returns a String object with all the response headers included.
*/
String getResponseHeaders();
/*
* Call this method before issuing the requests,
* to allows "insecure" SSL.
*
* Useful in the following case for example:
* Certificate cannot be authenticated with known CA certificates.
*/
void enableInsecure();
/*
* Call this method before issuing the request,
* to add an extra header to the request.
*
* Returns 0 if the header fits into the array of headers. -1 otherwise.
*/
int addHeader(const char* header);
int addHeader(const String& header) {addHeader(header.c_str());}
/*
* Call this method before issuing the request,
* to include basic authorization into the request.
*/
void basicAuth(const char* user, const char* passwd);
void basicAuth(const String& user, const char* passwd) {basicAuth(user.c_str(), passwd);}
void basicAuth(const char* user, const String& passwd) {basicAuth(user, passwd.c_str());}
void basicAuth(const String& user, const String& passwd) {basicAuth(user.c_str(), passwd.c_str());}
/*
* Call this method between the different request calls on the same client,
* to clear/setup the request headers for the next call.
*/
void clearHeaders();
/*
* Call this method between the different request calls on the same client,
* to clear the previously set basic authorization for the subsequent call.
*/
void clearAuth();
/*
* Call this method after the request has finished,
* to get a particular response header value.
*
* Returns true and sets the value parameter if found,
* otherwise return false and doesn't set value parameter at all.
*/
bool getResponseHeaderValue(const String& header, String& value);
/*
* Reset client request settings.
* Clears the request headers, basic auth. settings and the insecure-enabled flag.
*/
void startRequest();
private:
String _tempFileName;
bool _isInsecureEnabled;
const char* _user;
const char* _passwd;
// The library supports up to 16 user addable request headers
static const unsigned maxNumberOfExtraHeaders = 16;
const char* _extraHeaders[maxNumberOfExtraHeaders];
int _extraHeaderIdx;
String _cachedRespHeaders;
/*
* Sends the actual request via cURL on the Linux side
*/
void request(const char* verb, const char* url, const char* data, bool async=false);
/*
* Clears the cached response headers between subsequent requests
*/
void clearCachedRespHeaders();
};
#endif

View File

@@ -0,0 +1,15 @@
Copyright (c) 2016 Imre Horvath. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

View File

@@ -0,0 +1,258 @@
A practical and easy to use generic HTTP client library for the Yun
===================================================================
Features
--------
* GET/POST/PUT/DELETE
* Both sync and async requests
* You can access the HTTP response code and headers, not just the body
* Basic authorization
* Multiple extra request headers
* Extraction of a particular response header value
* Designed for efficiency and easy usage
* Built on top of the Bridge library
* Uses cURL on the Linux side
Examples
--------
__List the names and Ids of your Adafruit IO Feeds__
```c++
#include <Bridge.h>
#include <BridgeHttpClient.h>
#include <ArduinoJson.h>
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // Initialize Bridge
digitalWrite(13, HIGH);
SerialUSB.begin(9600);
while (!SerialUSB); // wait for the serial connection
BridgeHttpClient client;
// Add request headers
// REPLACE THE XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX WITH YOUR AIO KEY!!!
client.addHeader("X-AIO-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.addHeader("Accept: application/json");
// Using HTTPS and peer cert. will not be able to auth.
client.enableInsecure();
// Adafruit IO REST API call
client.get("https://io.adafruit.com/api/feeds");
// Collect the response body into this string for parsing
String response;
while (client.available() > 0) {
char c = client.read();
response += c;
}
// Parse the list of feeds and print the name and ids, limited to 4 feeds
const int JSON_BUFFER = JSON_ARRAY_SIZE(4) + 4*JSON_OBJECT_SIZE(14);
StaticJsonBuffer<JSON_BUFFER> jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(response);
if (!array.success()) {
SerialUSB.println("parseArray() failed");
while (1) {}
}
// List the feed names and Ids
SerialUSB.println("Your Adafruit IO Feed Name/Id listing:");
for (JsonArray::iterator it=array.begin(); it!=array.end(); ++it) {
JsonObject& feed = it->as<JsonObject&>();
feed["name"].printTo(SerialUSB);
SerialUSB.print("/");
feed["id"].printTo(SerialUSB);
SerialUSB.println();
}
}
void loop() {
// Do nothing
}
```
__Asynchronous POST example__
```c++
#include <Bridge.h>
#include <BridgeHttpClient.h>
BridgeHttpClient client;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // Initialize Bridge
digitalWrite(13, HIGH);
SerialUSB.begin(9600);
while (!SerialUSB); // wait for a serial connection
client.addHeader("X-Api-Key: 12345");
client.addHeader("Accept: application/json");
client.addHeader("Content-Type: application/json");
client.enableInsecure(); // Using HTTPS and peer cert. will not be able to auth.
String data = "{\"sensorData\":\"";
data += 123;
data += "\"}";
client.postAsync("https://httpbin.org/post", data);
SerialUSB.print("Sending request");
}
void loop() {
if (client.finished()) {
SerialUSB.println();
SerialUSB.println("Response Body:");
while (client.available() > 0) {
char c = client.read();
SerialUSB.print(c);
}
SerialUSB.print("Response Code: ");
SerialUSB.println(client.getResponseCode());
while (1) {} // stop
} else {
// not finished yet, wait and retry
SerialUSB.print(".");
delay(100);
}
}
```
Usage
-----
__First instantiate a client__
```c++
BridgeHttpClient client;
```
__Adding Basic Auth. to your request (optional)__
```c++
client.basicAuth("user", "password");
```
__Adding extra request headers to your request (optional)__
```c++
client.addHeader("X-Api-Key: 12345");
client.addHeader("Accept: application/json");
client.addHeader("Content-Type: application/json");
```
_Note:_ The library supports up to 16 extra user addable request headers.
__When issuing HTTPS requests consider this__
If your HTTPS request fails due to the "certificate cannot be authenticated with known CA certificates" problem, you can circumvent the issue by calling the following method before the request.
```c++
client.enableInsecure();
```
__Synchronous requests__
```c++
// HTTP GET, call won't return until finished
client.get("https://httpbin.org/headers");
// HTTP POST a JSON payload, call won't return until finished
String data = "{\"sensorData\":\"";
data += 123;
data += "\"}";
client.post("https://httpbin.org/post", data);
```
__Asynchronous requests__
To check whether the async request has completed or not, you can use the following method from the parent class.
```c++
// HTTP GET, call returns before completion.
client.getAsync("https://httpbin.org/headers");
// ...
// Later you can check whether the call has finished
if (client.finished()) {
// Request has finished
}
```
__Exit status of the client__
After the sync or async request has finished, you can check the exit status of the client like this.
```c++
if (client.exitValue() == 0) {
// Success, continue processing
} else {
// Error
}
```
__HTTP response code__
If you need the HTTP response code for your application, use the following method.
```c++
if (client.getResponseCode() == 200) {
// HTTP OK
}
```
__HTTP response headers__
To access all the received HTTP response headers, you can use this method.
```c++
String responseHeaders = getResponseHeaders();
// Process response headers by yourself
```
_Note:_ It returns all the headers in one string object. This is useful if you want to process the headers by yourself. If you're interested in a particular header value only, use the next method instead!
__HTTP response header value__
```c++
String server;
if (client.getResponseHeaderValue("Server", server)) {
SerialUSB.print("Header \"Server\" has value: ");
SerialUSB.println(server);
} else {
SerialUSB.println("Header \"Server\" not found");
}
```
__HTTP response body__
```c++
SerialUSB.println("Response Body:");
while (client.available() > 0) {
char c = client.read();
SerialUSB.print(c);
}
```
TODO
----
* Add proxy support
* Provide better description
* Create useful examples

View File

@@ -0,0 +1,80 @@
/*
Adafruit AIO REST API example
What it does: Lists your Adafruit IO Feed Name/Ids using the REST API.
Please note that this sketch is Yun-specific!
Works only with Yun and its clones like the Seeeduino Cloud, but not with
an Uno or other Arduinos.
Dependencies: ArduinoJson library
Usage:
1. Make sure you've installed the ArduinoJson library in the Library Manager
2. Replace the placeholder XXXs below with your actual AIO KEY
3. Upload the sketch using a USB cable.
4. Wait for the RED LED to light up on the board.
5. Open the serial monitor in the Arduino IDE.
Written by Imre Horvath, 2017
*/
#include <Bridge.h>
#include <BridgeHttpClient.h>
#include <ArduinoJson.h>
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // Initialize Bridge
digitalWrite(13, HIGH);
SerialUSB.begin(9600);
while (!SerialUSB); // wait for the serial connection
BridgeHttpClient client;
// Add request headers
// REPLACE THE XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX WITH YOUR AIO KEY!!!
client.addHeader("X-AIO-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.addHeader("Accept: application/json");
// Using HTTPS and peer cert. will not be able to auth.
client.enableInsecure();
// Adafruit IO REST API call
client.get("https://io.adafruit.com/api/feeds");
// Collect the response body into this string for parsing
String response;
while (client.available() > 0) {
char c = client.read();
response += c;
}
// Parse the list of feeds and print the name and ids, limited to 4 feeds
const int JSON_BUFFER = JSON_ARRAY_SIZE(4) + 4*JSON_OBJECT_SIZE(14);
StaticJsonBuffer<JSON_BUFFER> jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(response);
if (!array.success()) {
SerialUSB.println("parseArray() failed");
while (1) {}
}
// List the feed names and Ids
SerialUSB.println("Your Adafruit IO Feed Name/Id listing:");
for (JsonArray::iterator it=array.begin(); it!=array.end(); ++it) {
JsonObject& feed = it->as<JsonObject&>();
feed["name"].printTo(SerialUSB);
SerialUSB.print("/");
feed["id"].printTo(SerialUSB);
SerialUSB.println();
}
}
void loop() {
// Do nothing
}

View File

@@ -0,0 +1,78 @@
/*
Adafruit AIO REST API example
What it does: Get your feeds on the Adafruit IO using the REST API.
Please note that this sketch is Yun-specific!
Works only with Yun and its clones like the Seeeduino Cloud, but not with
an Uno or other Arduinos.
Dependencies: ArduinoJson library
Usage:
1. Make sure you've installed the ArduinoJson library in the Library Manager
2. Replace the placeholder XXXs below with your actual AIO KEY
3. Upload the sketch using a USB cable.
4. Wait for the RED LED to light up on the board.
5. Open the serial monitor in the Arduino IDE.
Written by Imre Horvath, 2016
*/
#include <Bridge.h>
#include <BridgeHttpClient.h>
#include <ArduinoJson.h>
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // Initialize Bridge
digitalWrite(13, HIGH);
SerialUSB.begin(9600);
while (!SerialUSB); // wait for the serial connection
BridgeHttpClient client;
// Add request headers
// REPLACE THE XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX WITH YOUR AIO KEY!!!
client.addHeader("X-AIO-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.addHeader("Accept: application/json");
// Using HTTPS and peer cert. will not be able to auth.
client.enableInsecure();
// Adafruit IO REST API call
client.get("https://io.adafruit.com/api/feeds");
// Collect the response body into this string for parsing
String response;
// Collect the response body
while (client.available() > 0) {
char c = client.read();
response += c;
}
// Print the HTTP response code
SerialUSB.print("Response code: ");
SerialUSB.println(client.getResponseCode());
// Parse the list of feeds and print the name and ids, limited to 4 feeds
const int JSON_BUFFER = JSON_ARRAY_SIZE(4) + 4*JSON_OBJECT_SIZE(14);
StaticJsonBuffer<JSON_BUFFER> jsonBuffer;
JsonArray& array = jsonBuffer.parseArray(response);
if (!array.success()) {
SerialUSB.println("parseArray() failed");
while (1) {}
}
// Pretty print the JSON to the serial console
array.prettyPrintTo(SerialUSB);
}
void loop() {
// Do nothing
}

View File

@@ -0,0 +1,66 @@
/*
Asynchronous POST example
What it does: Issues a POST request to httpbin using the async API.
Please note that this sketch is Yun-specific!
Works only with Yun and its clones like the Seeeduino Cloud, but not with
an Uno or other Arduinos.
Usage:
1. Upload the sketch using a USB cable.
2. Wait for the RED LED to light up on the board.
3. Open the serial monitor in the Arduino IDE.
Written by Imre Horvath, 2016
*/
#include <Bridge.h>
#include <BridgeHttpClient.h>
BridgeHttpClient client;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin(); // Initialize Bridge
digitalWrite(13, HIGH);
SerialUSB.begin(9600);
while (!SerialUSB); // wait for a serial connection
client.addHeader("X-Api-Key: 12345");
client.addHeader("Accept: application/json");
client.addHeader("Content-Type: application/json");
client.enableInsecure(); // Using HTTPS and peer cert. will not be able to auth.
String data = "{\"sensorData\":\"";
data += 123;
data += "\"}";
client.postAsync("https://httpbin.org/post", data);
SerialUSB.print("Sending request");
}
void loop() {
if (client.finished()) {
SerialUSB.println();
SerialUSB.println("Response Body:");
while (client.available() > 0) {
char c = client.read();
SerialUSB.print(c);
}
SerialUSB.print("Response Code: ");
SerialUSB.println(client.getResponseCode());
while (1) {} // stop
} else {
// not finished yet, wait and retry
SerialUSB.print(".");
delay(100);
}
}

View File

@@ -0,0 +1,32 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
BridgeHttpClient KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
get KEYWORD2
post KEYWORD2
put KEYWORD2
del KEYWORD2
getResponseCode KEYWORD2
getResponseHeaders KEYWORD2
getAsync KEYWORD2
postAsync KEYWORD2
putAsync KEYWORD2
delAsync KEYWORD2
enableInsecure KEYWORD2
addHeader KEYWORD2
basicAuth KEYWORD2
clearHeaders KEYWORD2
clearAuth KEYWORD2
getResponseHeaderValue KEYWORD2
######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,9 @@
name=BridgeHttpClient
version=3.2.1
author=Imre Horvath <imi.horvath@gmail.com>
maintainer=Imre Horvath <imi.horvath@gmail.com>
sentence=A practical and easy to use generic HTTP client library for the Yun.
paragraph=GET/POST/PUT/DELETE, sync/async requests, request/response headers, basic auth and more.
category=Communication
url=https://github.com/imrehorvath/BridgeHttpClient
architectures=*