Arduino Uno R4 Http communication Issue

Hi Team,

I'm facing an issue accessing a web API from my Arduino Uno R4, but it only occurs with certain servers like "mobile.eautomates.com".
The same code works perfectly with other API links.
I would appreciate any help in resolving this.

https://mobile.eautomates.com/api/IOT/Arduino/GetRotation - Not working

Working API's
https://jsonplaceholder.typicode.com/users/1 - Working
https://fakestoreapi.com/products/1 - Working

What specifically is not working? Can't connect to the host with WiFiSSLClient? Which HTTP client, or performing HTTP manually?

ArduinoHttpClient worked for me

  WiFiSSLClient ssl;
  HttpClient http = HttpClient(ssl, "mobile.eautomates.com", 443);
  http.get("/api/IOT/Arduino/GetRotation");

  int statusCode = http.responseStatusCode();
  Serial.print("Status code: ");
  Serial.println(statusCode);

  while (http.headerAvailable()) {
    Serial.print(http.readHeaderName());
    Serial.print(": ");
    Serial.println(http.readHeaderValue());
  }
   
  String response = http.responseBody();
  Serial.print("Response: ");
  Serial.println(response);

prints

{"steps":100,"direction":"clockwise"}

According to the response header

Transfer-Encoding: chunked

That complicates things if you're reading it manually.

Thank you @ kenb4,

I also tried using ArduinoHttpClient, but no luck. Please check my code below—I tested it with two APIs; one is responding correctly, while the other is not.

Working Sample
#include <WiFiS3.h>
#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>

// WiFi Credentials
const char* ssid = "Juansai";
const char* password = "0123456789";

// Server Info
const char* server = "fakestoreapi.com"; // Sample API
const int port = 443; // HTTPS port

WiFiSSLClient sslClient;
HttpClient httpClient(sslClient, server, port);

void setup() {
Serial.begin(9600);
while (!Serial)
;

Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}

Serial.println("\nWiFi connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

fetchData();
}

void fetchData() {
Serial.println("\nMaking HTTPS GET request with headers...");

String url = "/products/category/jewelery"; // Sample API endpoint

// Set custom headers
httpClient.beginRequest();
httpClient.get(url);
httpClient.sendHeader("Content-Type", "application/json");
httpClient.endRequest();

int statusCode = httpClient.responseStatusCode();
Serial.print("Status code: ");
Serial.println(statusCode);

while (httpClient.headerAvailable()) {
Serial.print(httpClient.readHeaderName());
Serial.print(": ");
Serial.println(httpClient.readHeaderValue());
}

if (statusCode != 200) {
Serial.println("Failed to get a valid response!");
return;
}

String response = httpClient.responseBody();
Serial.println("Response:");
Serial.println(response);
}

void loop() {
// Nothing here
}

Response

Not Working Sample

#include <WiFiS3.h>
#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>

// WiFi Credentials
const char* ssid = "Juansai";
const char* password = "0123456789";

// Server Info
const char* server = "mobile.eautomates.com"; // Sample API
const int port = 443; // HTTPS port

WiFiSSLClient sslClient;
HttpClient httpClient(sslClient, server, port);

void setup() {
Serial.begin(9600);
while (!Serial)
;

Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}

Serial.println("\nWiFi connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

fetchData();
}

void fetchData() {
Serial.println("\nMaking HTTPS GET request with headers...");

String url = "/api/IOT/Arduino/GetRotation"; // Sample API endpoint

// Set custom headers
httpClient.beginRequest();
httpClient.get(url);
httpClient.sendHeader("Content-Type", "application/json");
httpClient.endRequest();

int statusCode = httpClient.responseStatusCode();
Serial.print("Status code: ");
Serial.println(statusCode);

while (httpClient.headerAvailable()) {
Serial.print(httpClient.readHeaderName());
Serial.print(": ");
Serial.println(httpClient.readHeaderValue());
}

if (statusCode != 200) {
Serial.println("Failed to get a valid response!");
return;
}

String response = httpClient.responseBody();
Serial.println("Response:");
Serial.println(response);
}

Response

Please use the <CODE/> button in the toolbar when posting code. For one thing, it preserves indentation, which is hopefully correct when copied for pasting.

The negative numbers returned by responseStatusCode are not HTTP status codes, but custom library codes. They're at the top of the header file

// Spent too long waiting for a reply
static const int HTTP_ERROR_TIMED_OUT =-3;

The timeout defaults to 30 seconds

    // Number of milliseconds that we'll wait in total without receiving any
    // data before returning HTTP_ERROR_TIMED_OUT (during status code and header
    // processing)
    static const int kHttpResponseTimeout = 30*1000;

Is it taking that long? (Turn on the timestamps in the Serial Monitor.)

Your "not working" fetchData worked for me. You can try it with curl to see if we're hitting the same IP

$ curl -v --http1.1 https://mobile.eautomates.com/api/IOT/Arduino/GetRotation
*   Trying 78.46.73.130:443...
* Connected to mobile.eautomates.com (78.46.73.130) port 443 (#0)
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=mobile.eautomates.com
*  start date: Jan 18 18:06:50 2025 GMT
*  expire date: Apr 18 18:06:49 2025 GMT
*  subjectAltName: host "mobile.eautomates.com" matched cert's "mobile.eautomates.com"
*  issuer: C=US; O=Let's Encrypt; CN=R10
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /api/IOT/Arduino/GetRotation HTTP/1.1
> Host: mobile.eautomates.com
> User-Agent: curl/7.81.0
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=utf-8
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< X-Powered-By-Plesk: PleskWin
< Date: Thu, 13 Feb 2025 01:26:34 GMT
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host mobile.eautomates.com left intact
{"steps":0,"direction":"string"}

Probably unrelated, but the Content-Type header refers to the body: the response body, or the request body for like a POST or PUT. But GET does not have a body. You were probably thinking of Accept: application/json, which is a request header for APIs to return JSON. Many APIs return JSON by default, but it shouldn't hurt to be explicit.

Hi Kenb,

Have you change any code, which i shared?, or the same code works for you?

And you know why it is working for the below api links

  1. https://jsonplaceholder.typicode.com/users/1
  2. https://fakestoreapi.com/products/1

Seems like a DNS issue. The domain does not resolve on my computer:

curl -v --http1.1 https://mobile.eautomates.com/api/IOT/Arduino/GetRotation
* Could not resolve host: mobile.eautomates.com
* Closing connection
curl: (6) Could not resolve host: mobile.eautomates.com
nslookup mobile.eautomates.com
Server:		192.168.0.1
Address:	192.168.0.1#53

** server can't find mobile.eautomates.com: SERVFAIL
1 Like

I used the fetchData almost verbatim in an existing sketch I had handy, which already had my WiFi credentials.

I tried connecting to no.such.example.com, and that also took 30 seconds to give up with -3. For "could not resolve host", you'd think that it would fail faster with

// Could not connect to the server
static const int HTTP_ERROR_CONNECTION_FAILED =-1;

but apparently not.

So, if I increase the timeout, it should respond properly, right?, I will try and update.

@kenb4 Could you send the complete code that you tried and received the response for?

Just to update, DNS has started working on my side, and the api also responds through curl

amitabh@Amitabhs-MacBook-Pro ~ % nslookup mobile.eautomates.com
Server:		2401:4900:50:9::7e6
Address:	2401:4900:50:9::7e6#53

Non-authoritative answer:
Name:	mobile.eautomates.com
Address: 78.46.73.130

amitabh@Amitabhs-MacBook-Pro ~ % curl -v --http1.1 https://mobile.eautomates.com/api/IOT/Arduino/GetRotation
* Host mobile.eautomates.com:443 was resolved.
* IPv6: (none)
* IPv4: 78.46.73.130
*   Trying 78.46.73.130:443...
* Connected to mobile.eautomates.com (78.46.73.130) port 443
* ALPN: curl offers http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=mobile.eautomates.com
*  start date: Jan 18 18:06:50 2025 GMT
*  expire date: Apr 18 18:06:49 2025 GMT
*  subjectAltName: host "mobile.eautomates.com" matched cert's "mobile.eautomates.com"
*  issuer: C=US; O=Let's Encrypt; CN=R10
*  SSL certificate verify ok.
* using HTTP/1.x
> GET /api/IOT/Arduino/GetRotation HTTP/1.1
> Host: mobile.eautomates.com
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=utf-8
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< X-Powered-By-Plesk: PleskWin
< Date: Thu, 13 Feb 2025 13:02:09 GMT
< 
* Connection #0 to host mobile.eautomates.com left intact
{"steps":0,"direction":"string"}%  

Here's the working code, using the standard arduino_secrets.h to hold the SECRET_SSID and SSID_PASS macros

#include <WiFi.h>
#include <WiFiSSLClient.h>
#include <ArduinoHttpClient.h>
#include "arduino_secrets.h"

WiFiSSLClient ssl;
HttpClient httpClient(ssl, "mobile.eautomates.com", 443);
// HttpClient httpClient(ssl, "no.such.example.com", 443);

void fetchData() {
  Serial.println("\nMaking HTTPS GET request with headers...");

  String url = "/api/IOT/Arduino/GetRotation";  // Sample API endpoint

  // Set custom headers
  httpClient.beginRequest();
  httpClient.get(url);
  httpClient.sendHeader("Accept", "application/json");
  httpClient.endRequest();

  int statusCode = httpClient.responseStatusCode();
  Serial.print("Status code: ");
  Serial.println(statusCode);

  while (httpClient.headerAvailable()) {
    Serial.print(httpClient.readHeaderName());
    Serial.print(": ");
    Serial.println(httpClient.readHeaderValue());
  }

  if (statusCode != 200) {
    Serial.println("Failed to get a valid response!");
    return;
  }

  String response = httpClient.responseBody();
  Serial.println("Response:");
  Serial.println(response);
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(SECRET_SSID, SECRET_PASS);
  for (int i = 0; WiFi.status() != WL_CONNECTED; i++) {
    Serial.print(i % 10 ? "." : "\n.");
    delay(100);
  }
  Serial.println();
  Serial.println(WiFi.localIP());

  fetchData();
}

void loop() {}

Yesterday I happened upon an R4-specific HTTP client: R4HttpClient, which is also an installable Library in the IDE. One wrinkle: it requires that the response be chunked -- which is the case here

#include <WiFi.h>
#include <WiFiSSLClient.h>
// #include <ArduinoHttpClient.h>
#include <R4HttpClient.h>
#include "arduino_secrets.h"

WiFiSSLClient ssl;
// HttpClient httpClient(ssl, "mobile.eautomates.com", 443);
// HttpClient httpClient(ssl, "no.such.example.com", 443);
R4HttpClient httpClient;

void fetchData() {
  Serial.println("\nMaking HTTPS GET request with headers...");

  String origin = "https://mobile.eautomates.com";
  // String origin = "https://no.such.example.com";
  String url = "/api/IOT/Arduino/GetRotation";  // Sample API endpoint

  // Set custom headers
  // httpClient.beginRequest();
  // httpClient.get(url);
  // httpClient.sendHeader("Accept", "application/json");
  // httpClient.endRequest();
  httpClient.begin(ssl, origin + url, 443);
  httpClient.addHeader("Accept: application/json");

  // int statusCode = httpClient.responseStatusCode();
  int statusCode = httpClient.GET();
  Serial.print("Status code: ");
  Serial.println(statusCode);

  // while (httpClient.headerAvailable()) {
  //   Serial.print(httpClient.readHeaderName());
  //   Serial.print(": ");
  //   Serial.println(httpClient.readHeaderValue());
  // }

  if (statusCode != 200) {
    Serial.println("Failed to get a valid response!");
    return;
  }

  // String response = httpClient.responseBody();
  String response = httpClient.getBody();
  Serial.println("Response:");
  Serial.println(response);
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(SECRET_SSID, SECRET_PASS);
  for (int i = 0; WiFi.status() != WL_CONNECTED; i++) {
    Serial.print(i % 10 ? "." : "\n.");
    delay(100);
  }
  Serial.println();
  Serial.println(WiFi.localIP());

  fetchData();
}

void loop() {}

That worked too. When I then swapped it to try no.such.example.com, it failed immediately with -1

#define R4HTTP_ERROR_CONNECTION_REFUSED    (-1)

Have you tried curl yet?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.