I am trying to get the Json-Body of a GET request payload extracted.
Normally, I would use, for example, the ArduinoHTTPClient-library's client.responseBody()
method. But in my case, I am using the EthernetSSLClient library and in there, the ArduinoHTTPClient functions do not work.
It is critical that I use SSL since our clients request this level of security. But now I am here with a library that does not seem to offer an easy GET-request json-body extraction.
My code (see below) returns the following response upon my GET-request:
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json; charset=utf-8
Content-Length: 72
Date: Tue, 09 Nov 2021 17:27:49 GMT
Server: DelphiMVCFramework
X-Powered-By: DMVCFramework 3.2.1 (carbon)
{"Version":"1.4.724.2267","Application":"MyApplication Commander"}
As you can see, there is a header upfront and the needed payload is at very end (Json).
Can you tell me how to nicely extract the json-body from this ?
My workarround solution (far from robust as I think) is as follows:
String payload = "";
while (sslClient.available()) {
char c = sslClient.read();
payload += c;
}
int index = payload.indexOf("{");
String body = payload.substring(index);
But I think simply finding the first "{" is not a good solution.
Can you suggest a library that works in combination with the EthernetSSLClient
library that consists of a more robust solution to the json-body extraction problem ?
Or do you have any code example that improves my current solution ?
Thank you.
Here is my entire code:
#include "defines.h"
#include "trust_anchors.h" // You must have SSL Certificates here
#include <ArduinoJson.h>
#define USE_THIS_SS_PIN 5 // default CS/SS pin for MKRWiFi1010 board or MKRZERO board
const uint16_t server_port = 6060;
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x28, 0x9C }; // MAC Adress of Arduino MKR ETH Shield
IPAddress server_host(192, 168, 1, 43);
// IPAddress myDns(192, 168, 1, 1);
// IPAddress gateway(192, 168, 1, 1);
// IPAddress subnet(255, 255, 255, 0);
// Initialize the SSL client library
EthernetClient client;
EthernetSSLClient sslClient(client, TAs, (size_t)TAs_NUM);
// Variables to measure the speed
unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
unsigned long previousMillis = 0;
unsigned long interval = 1000;
unsigned long connectionTime = 0;
unsigned long startTime = 0;
void makeRequest(String cmd) {
sslClient.println(cmd);
sslClient.print("Host: ");
sslClient.println(server_host);
sslClient.println("User-Agent: TriMini Buttons");
sslClient.println();
}
void showReceivedBytes() {
Serial.print("Received ");
Serial.print(byteCount);
Serial.print(" bytes in ");
float seconds = (float)(endMicros - beginMicros) / 1000000.0;
Serial.print(seconds, 4);
float rate = (float)byteCount / seconds / 1000.0;
Serial.print(" s, rate = ");
Serial.print(rate);
Serial.print(" kbytes/second");
Serial.println();
}
void checkVersion() {
// if there are incoming bytes available
// from the server, read them
int len = sslClient.available();
if (len > 0) {
const size_t capacity = 80; // JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
byte buffer[capacity];
if (len > capacity) { len = capacity; }
sslClient.read(buffer, len);
byteCount = byteCount + len;
}
}
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
delay(2000);
Serial.print("\nStart WebClient_SSL on " + String(BOARD_NAME));
Serial.println(" with " + String(SHIELD_TYPE));
Serial.println(ETHERNET_WEBSERVER_SSL_VERSION);
ET_LOGWARN(F("=========== USE_ETHERNET ==========="));
ET_LOGWARN(F("Default SPI pinout:"));
ET_LOGWARN1(F("MOSI:"), MOSI);
ET_LOGWARN1(F("MISO:"), MISO);
ET_LOGWARN1(F("SCK:"), SCK);
ET_LOGWARN1(F("SS:"), SS);
ET_LOGWARN(F("========================="));
ET_LOGWARN3(F("Board :"), BOARD_NAME, F(", setCsPin:"), USE_THIS_SS_PIN);
Serial.print("MAC Adress: ");
Serial.print(mac[0], HEX); Serial.print(" ");
Serial.print(mac[1], HEX); Serial.print(" ");
Serial.print(mac[2], HEX); Serial.print(" ");
Serial.print(mac[3], HEX); Serial.print(" ");
Serial.print(mac[4], HEX); Serial.print(" ");
Serial.println(mac[5], HEX);
Ethernet.init (USE_THIS_SS_PIN);
// start the ethernet connection and the server:
// Use DHCP dynamic IP and random mac
// Ethernet.begin(mac[index], server_host, myDns, gateway, subnet);
Ethernet.begin(mac);
Serial.print(F("Connected! IP address: "));
Serial.println(Ethernet.localIP());
// give the Ethernet shield a second to initialize:
delay(2000);
Serial.print("Connecting to : ");
Serial.print(server_host);
Serial.print(", port : ");
Serial.println(server_port);
// if you get a connection, report back via serial:
startTime = millis();
// specify the server and port, 443 is the standard port for HTTPS
if (sslClient.connect(server_host, server_port)) {
connectionTime = millis() - startTime;
Serial.print("Connected to ");
Serial.println(client.remoteIP());
Serial.print("Connect took: ");
Serial.println(connectionTime);
// Make a HTTP request:
makeRequest("GET /Cmd/GetVersion HTTP/1.1");
} else {
// if you didn't get a connection to the server:
Serial.println("Connection failed");
}
beginMicros = micros();
}
void loop()
{
unsigned long currentMillis = millis();
String payload = "";
while (sslClient.available()) {
char c = sslClient.read();
payload += c;
}
Serial.println(payload);
// ?????????? HOW DO I EXTRACT JSON-BODY OF THIS payload ????????????
// My workarround looks like this:
int index = payload.indexOf("{");
String body = payload.substring(index);
// if the server's disconnected, stop the sslClient:
if (!sslClient.connected()) {
endMicros = micros();
Serial.println();
Serial.println("Disconnecting.");
sslClient.stop();
Serial.print("Received ");
Serial.print(byteCount);
Serial.print(" bytes in ");
float seconds = (float)(endMicros - beginMicros) / 1000000.0;
Serial.print(seconds, 4);
float rate = (float)byteCount / seconds / 1000.0;
Serial.print(" s, rate = ");
Serial.print(rate);
Serial.print(" kbytes/second");
Serial.println();
// do nothing forevermore:
while (true) {
delay(1);
}
}
}