UV Sensor Data Upload Problem

Going through the link above @PaulRB - I've made a basic test file before incorporating into my existing UV sensor code.

This is the test code (a copy and paste of the HTTPS Requests link you've sent):

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>


// Replace with your network credentials
const char* ssid = "removed";
const char* password = "removed";

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    // Ignore SSL certificate validation
    client->setInsecure();
    
    //create an HTTPClient instance
    HTTPClient https;
    
    //Initializing an HTTPS communication using the secure client
    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }
  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(120000);
}

When compiling, I get this error:

UV_2023:4:37: fatal error: WiFiClientSecureBearSSL.h: No such file or directory
 #include <WiFiClientSecureBearSSL.h>
                                     ^
compilation terminated.
exit status 1
WiFiClientSecureBearSSL.h: No such file or directory

Fair enough.

I can't find the WiFiClientSecureBearSSL library when searching in Library Manager.

Any idea how I can install it via a .zip file or whatever? Thanks.

I think it's supposed to be installed as part of the esp8266 boards package.

Maybe use the library manager to check if the esp8266 libraries you have installed are the latest versions?

@PaulRB

Is it this one?

I note this one too:

Installing both makes no difference however.

My bad, when I said library manager, I meant to say boards manager.


I am on 3.0.2, which is quite out-of-date now, latest version is 3.1.2

@PaulRB - all updated in the board manager and it's working.

So the test code is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>


// Replace with your network credentials
const char* ssid = "removed";
const char* password = "removed";

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    // Ignore SSL certificate validation
    client->setInsecure();
    
    //create an HTTPClient instance
    HTTPClient https;
    
    //Initializing an HTTPS communication using the secure client
    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }
  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(120000);
}

I need to start incorporating the existing code into it (below):

extern "C" {
#include "user_interface.h"
}

#include <ESP8266WiFi.h>
#include <Wire.h>
#include <SoftwareSerial.h>

#define SLAVE_RX D3
#define SLAVE_TX D4

int UVOUT = A0; //Output from the sensor
const byte REF_3V3 = A0; //3.3V power on the Arduino board

// Use WiFiClient class to create TCP connections
WiFiClient wsClient;

// Serial connection with slave MCU
SoftwareSerial slaveMCU(SLAVE_RX, SLAVE_TX, false, 64);

const char ssid[]     = "";
const char password[] = "";
const char host[]     =  "";

IPAddress ip();
IPAddress gateway(192,168,0,1);
IPAddress subnet(255,255,255,0);

const double e = 2.71828;

int readSerialWord() {
  
  byte h = slaveMCU.read();
  byte l = slaveMCU.read();
  return word(h, l);
  
}

void setup() {

  Serial.begin(115200);

  pinMode(UVOUT, INPUT);
  pinMode(REF_3V3, INPUT);

  pinMode(2, OUTPUT);
  
}

void loop() {

    digitalWrite(2, LOW);
    delay(500);
    digitalWrite(2, HIGH);
    delay(500);

  Serial.println();
  Serial.println("Calculating sensor values...");
  Serial.println();

   int uvLevel = averageAnalogRead(UVOUT);
 
  //Use the 3.3V power pin as a reference to get a very accurate output value from sensor
  float outputVoltage = 3.3 / 1000 * uvLevel;
 
  float uvIntensity = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0);

  Serial.print("ML8511 output: ");
  Serial.print(uvLevel);

  Serial.print(" | ML8511 voltage: ");
  Serial.print(outputVoltage);

  Serial.print(" | UV Intensity (mW/cm^2): ");
  Serial.print(uvIntensity);

  Serial.println();

  Serial.println();
  Serial.print("Connecting to WiFi");

  unsigned long startTime = millis();
  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED && millis() - startTime < 30000UL) {
    delay(100);
    Serial.print(".");
  }

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println();
    Serial.println("WiFi connection failed");
    delay (3000);
    ESP.restart();
  }
  else {
    digitalWrite(2, LOW);
    delay(100);
    digitalWrite(2, HIGH);
    delay(100);
    digitalWrite(2, LOW);
    delay(100);
    digitalWrite(2, HIGH);
    delay(100);

    Serial.println();
    
    Serial.println();
    Serial.print("WiFi connected. SSID: ");
    Serial.print(WiFi.SSID());
    Serial.print(" | Signal: ");
    Serial.print(WiFi.RSSI());
    Serial.print(" | IP address: ");
    Serial.println(WiFi.localIP());

    Serial.println();
    Serial.print("connecting to ");
    Serial.println(host);

    const int httpPort = 80;
    if (!wsClient.connect(host, httpPort)) {
      Serial.println("Host connection failed");
    }
    else {

      String sensors, values;

        if (uvLevel >= 0 && uvLevel <= 65000) {
        sensors += "UV";
        values += uvIntensity;
      }

      // We now create a URL for the request
      String url = "/script.php";
      url += "?sensor=";
      url += sensors;
      url += "&value=";
      url += values;

      Serial.print("Requesting URL: ");
      Serial.println(url);

      // This will send the request to the server
      wsClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");

      while (!wsClient.available()) {
        if (millis() - startTime > 30000UL) {
          Serial.println("request failed");
          break;
        }
        delay(1000);
      }
      Serial.println();
      Serial.println("Response from server:");
      Serial.println("-----------------------------------------------------------------------");
      // Read all the lines of the reply from server and print them to Serial
      while (wsClient.available()) {
        String line = wsClient.readStringUntil('\r');
        Serial.print(line);
      }
      
      Serial.println("-----------------------------------------------------------------------");
      Serial.print("Time taken: ");
      Serial.println( millis() - startTime);

    }
    Serial.println("Disconnecting Wifi");
    WiFi.disconnect();
  }

  Serial.println("Sleeping...");
  delay(60000);

}

//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(int pinToRead)
{
  byte numberOfReadings = 8;
  unsigned int runningValue = 0;

  for (int x = 0 ; x < numberOfReadings ; x++)
    runningValue += analogRead(pinToRead);
  runningValue /= numberOfReadings;

  return (runningValue);
}

//The Arduino Map function but for floats
//From: http://forum.arduino.cc/index.php?topic=3922.0
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

I shall start soon. Any hints?

The existing code is larger, so I would integrate the relevant parts of the test code into it.

Also I would recommend auto-formatting your code regularly. Bad indentation can easily lead to mistakes.

@PaulRB this is what I have so far. I've had many attempts at this tonight. It needs looking at further and doesn't compile.

My guess is the main problem begins on line 124.

New code:

extern "C" {
#include "user_interface.h"
}

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <Arduino.h>

#define SLAVE_RX D3
#define SLAVE_TX D4

int UVOUT = A0; //Output from the sensor
const byte REF_3V3 = A0; //3.3V power on the Arduino board

// Use WiFiClient class to create TCP connections
WiFiClient wsClient;

// Serial connection with slave MCU
SoftwareSerial slaveMCU(SLAVE_RX, SLAVE_TX, false, 64);

const char ssid[]     = "";
const char password[] = "";
const char host[]     =  "";

IPAddress ip(192, 168, 0, 45);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

const double e = 2.71828;

int readSerialWord() {

  byte h = slaveMCU.read();
  byte l = slaveMCU.read();
  return word(h, l);

}

void setup() {

  Serial.begin(115200);

  pinMode(UVOUT, INPUT);
  pinMode(REF_3V3, INPUT);

  pinMode(2, OUTPUT);

}

void loop() {

  digitalWrite(2, LOW);
  delay(500);
  digitalWrite(2, HIGH);
  delay(500);

  Serial.println();
  Serial.println("Calculating sensor values...");
  Serial.println();

  int uvLevel = averageAnalogRead(UVOUT);

  //Use the 3.3V power pin as a reference to get a very accurate output value from sensor
  float outputVoltage = 3.3 / 1000 * uvLevel;

  float uvIntensity = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0);

  Serial.print("ML8511 output: ");
  Serial.print(uvLevel);

  Serial.print(" | ML8511 voltage: ");
  Serial.print(outputVoltage);

  Serial.print(" | UV Intensity (mW/cm^2): ");
  Serial.print(uvIntensity);

  Serial.println();

  Serial.println();
  Serial.print("Connecting to WiFi");

  unsigned long startTime = millis();
  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED && millis() - startTime < 30000UL) {
    delay(100);
    Serial.print(".");
  }

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println();
    Serial.println("WiFi connection failed");
    delay (3000);
    ESP.restart();
  }
  else {
    digitalWrite(2, LOW);
    delay(100);
    digitalWrite(2, HIGH);
    delay(100);
    digitalWrite(2, LOW);
    delay(100);
    digitalWrite(2, HIGH);
    delay(100);

    Serial.println();

    Serial.println();
    Serial.print("WiFi connected. SSID: ");
    Serial.print(WiFi.SSID());
    Serial.print(" | Signal: ");
    Serial.print(WiFi.RSSI());
    Serial.print(" | IP address: ");
    Serial.println(WiFi.localIP());

    Serial.println();
    Serial.print("connecting to ");
    Serial.println(host);

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    // Ignore SSL certificate validation
    client->setInsecure();

    //create an HTTPClient instance
    HTTPClient https;

    //Initializing an HTTPS communication using the secure client
    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "https://")) {  // HTTPS
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }
  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(120000);

  else {

    String sensors, values;

    if (uvLevel >= 0 && uvLevel <= 65000) {
      sensors += "UV";
      values += uvIntensity;
    }

    // We now create a URL for the request
    String url = "/script.php";
    url += "?sensor=";
    url += sensors;
    url += "&value=";
    url += values;

    Serial.print("Requesting URL: ");
    Serial.println(url);

    // This will send the request to the server
    wsClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n\r\n");

    while (!wsClient.available()) {
      if (millis() - startTime > 30000UL) {
        Serial.println("request failed");
        break;
      }
      delay(1000);
    }
    Serial.println();
    Serial.println("Response from server:");
    Serial.println("-----------------------------------------------------------------------");
    // Read all the lines of the reply from server and print them to Serial
    while (wsClient.available()) {
      String line = wsClient.readStringUntil('\r');
      Serial.print(line);
    }

    Serial.println("-----------------------------------------------------------------------");
    Serial.print("Time taken: ");
    Serial.println( millis() - startTime);

  }
  Serial.println("Disconnecting Wifi");
  WiFi.disconnect();
}

Serial.println("Sleeping...");
delay(60000);

}

//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(int pinToRead)
{
  byte numberOfReadings = 8;
  unsigned int runningValue = 0;

  for (int x = 0 ; x < numberOfReadings ; x++)
    runningValue += analogRead(pinToRead);
  runningValue /= numberOfReadings;

  return (runningValue);
}

//The Arduino Map function but for floats
//From: http://forum.arduino.cc/index.php?topic=3922.0
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Errors:











C:\Users\OTronics\Documents\Arduino\UV_2023\UV_2023.ino: In function 'void loop()':
UV_2023:64:40: error: 'averageAnalogRead' was not declared in this scope
   int uvLevel = averageAnalogRead(UVOUT);
                                        ^
UV_2023:69:67: error: 'mapfloat' was not declared in this scope
   float uvIntensity = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0);
                                                                   ^
UV_2023:160:3: error: 'else' without a previous 'if'
   else {
   ^
C:\Users\OTronics\Documents\Arduino\UV_2023\UV_2023.ino: At global scope:
UV_2023:209:1: error: 'Serial' does not name a type
 Serial.println("Sleeping...");
 ^
UV_2023:210:6: error: expected constructor, destructor, or type conversion before '(' token
 delay(60000);
      ^
UV_2023:212:1: error: expected declaration before '}' token
 }
 ^
exit status 1
'averageAnalogRead' was not declared in this scope

Assuming you are following my advice about using Auto Format, then the fact that these two } are at the same level of indentation:

}

Serial.println("Sleeping...");
delay(60000);

}

indicates that the code structure has gone wrong somewhere in loop(). Either a missing { or an unwanted } somewhere.

This error confirms that the code structure has gone wrong:

UV_2023:160:3: error: 'else' without a previous 'if'
   else {
   ^

Here's another clue:

  Serial.println("Waiting 2min before the next round...");
  delay(120000);

  else {

You would expect to see a } after that delay(), before the else.

This error in the code structure will have caused the other errors. Find and fix that and the other errors will disappear, I'm pretty sure.

I've spotted some worrying things

if (https.begin(*client, "https://")) {  // HTTPS

Where is the server address?

int httpCode = https.GET();

The code above is sending a GET request to the server, using the secure client.

// This will send the request to the server
    wsClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n\r\n");

This code is also sending a GET request, using the insecure client. But at least it is giving the server address and the request parameters, in the 'url' string.

So I think what has happened is that you have simplistically pasted parts of the secure GET code into your original code without understanding it and adapting it, and your existing code, appropriately.

I've removed the server address for security reasons. It is present in the actual code.

Indeed @PaulRB - hence why I am on this forum to get help.

Any idea which bits I need to change to finally get this all working?

Thanks.

Any more thoughts @PaulRB? It would be nice to get this one finished. Thanks

I still think the latest code you posted is an unfinished merge of your previous code and the secure GET example code, with some stuff what should have been removed and therefore maybe stuff missing also.

I have not attempted to upgrade my sensors to use secure HTTP (I have no urgent need to at the moment) so it's not something I can say I have enough experience with.

My advice would be to go through the example secure HTTP example code, understand it better, and check for any other parts of your code which should be removed and keep an eye out for anything that might have been missed or removed accidentally when you merged the code.

Hi @PaulRB. Sorry for the delay.

Do you think it's time to upgrade your sensors to secure HTTP? :wink:

Why, what's changed since October? :wink:

Naff all although secure connections are better... :wink:

In all seriousness, I've reached my limit on coding knowledge but it would be nice to get this finished @PaulRB

Hi @PaulRB

Hope you are well.

Thought I'd go back to basics.

I'm using this guide you posted above: ESP8266 NodeMCU HTTPS Requests (Arduino IDE) | Random Nerd Tutorials

I have added the 'no certificate' code to my Arduino and it connects to howsmyssl with no issues.

I can't get the 'Fingerprint' or 'Root Certificate' code to work though.

Concentrating on the Root Certificate code: I've got the certificate from howsmyssl and pasted it in. The full code:

/*
  Complete project details: https://RandomNerdTutorials.com/esp8266-nodemcu-https-requests/
  Based on the example created by Ivan Grokhotkov, 2015 (File > Examples > ESP8266WiFi > HTTPSRequests)
*/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>

// Root certificate for howsmyssl.com
const char IRG_Root_X1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIDzjCCAragAwIBAgIJQgAAFxJlyruxMA0GCSqGSIb3DQEBCwUAMFQxGTAXBgNV
BAoMEEFPIEthc3BlcnNreSBMYWIxNzA1BgNVBAMMLkthc3BlcnNreSBBbnRpLVZp
cnVzIFBlcnNvbmFsIFJvb3QgQ2VydGlmaWNhdGUwHhcNMjMwODE1MDA0NTM3WhcN
MjQwODEzMDA0NTM3WjAcMRowGAYDVQQDExF3d3cuaG93c215c3NsLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPJoVSSTk11Ooxfv9jMJM1REOa60
+rsUROC3NQkeJi0W6GEnLOxVG1jRPG14NxNju5ULzFidtQmI4v+hfvjrjDt3Pe8R
5V1heFVy4Les8QR9etUStw/g6P0b+m3ctAvEp0KfvrY3AwqvC5mJEWxA8wD87n9F
mRC9h8UOxIiZFBxZPSnVzx9SD6ABF199kHsghX84xBuYPq6NA80Rgoq0YqzJvbRY
jF3HYo8ZwgbidzBD8HL28wiApRf+dbmGeqJa7x2awtOrXL7s5wnCh23NAsxjsK4d
oBemR7Zk9/tMQGNyFtuY6oTrCf0C1/bR419CjQSkuW+7kD2NA2svTJupZ8ECAwEA
AaOB2jCB1zATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwHwYDVR0j
BBgwFoAU2jmj7l5rSw0yVb/vlWAYkK/YBwkwUwYDVR0RBEwwSocEIkctyIIRd3d3
Lmhvd3NteXNzbC5jb22CDWhvd3NteXNzbC5jb22CDWhvd3NteXRscy5jb22CEXd3
dy5ob3dzbXl0bHMuY29tMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9raXMuY3Js
LnNjci5rYXNwZXJza3ktbGFiLmNvbS9jcmwuY3JsMA0GCSqGSIb3DQEBCwUAA4IB
AQDG0xZU3wc8qVr5UEfFHoOm+RYSygo1fCBPUPOPj3TB4i+RWXPdeqLYVDo6/+ak
LnqGXjHxn6Dn1HJx81OdZ8gjINarbkQimdOT/CtjkinXs2t8vqk4CY8z5GgRHP7O
Ty/AKibefqIedtVR+/VO/wJd37/LBbN7wzRFWEbKMC2S68mCpwqnemYfEqBUreEL
m9y5YpAaY3r1p/l6+c+MzxDMi0Wi7VGf/y33UbfTe8v/gPBcoBkhCZZJZB4SQ25I
H9TRRdnSC40H/5QmhYvSsRet5S/iwsgKkMDr0IpnFWh+3iIMsYdwcgYnIV5JHHLN
ZQ4EBsBudMFHVO5v4cbkPZEj
-----END CERTIFICATE-----
)CERT";

// Replace with your network credentials
const char* ssid = "removed for this post";
const char* password = "removed for this post";

// Create a list of certificates with the server certificate
X509List cert(IRG_Root_X1);

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }

  // Set time via NTP, as required for x.509 validation
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
}

void loop() {
  WiFiClientSecure client;

  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    client.setTrustAnchors(&cert);

    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");
    if (https.begin(client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }

  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(10000);
}

The error is get is:

..Waiting for NTP time sync: . Current time: Tue Feb 13 01:19:30 2024 [HTTPS] begin... [HTTPS] GET... [HTTPS] GET... failed, error: connection failed

I've not tried this test code before. Are you able to try it and see if it works on your Arduino? Thanks.

I get the same

16:49:44.212 -> Connecting to WiFi ......Waiting for NTP time sync: .
16:49:49.446 -> Current time: Sat Feb 17 16:49:49 2024
16:49:49.446 -> [HTTPS] begin...
16:49:49.446 -> [HTTPS] GET...
16:49:51.069 -> [HTTPS] GET... failed, error: connection failed
16:49:51.069 -> 
16:49:51.069 -> Waiting 2min before the next round...
16:50:01.074 -> [HTTPS] begin...
16:50:01.074 -> [HTTPS] GET...
16:50:02.765 -> [HTTPS] GET... failed, error: connection failed
16:50:02.765 -> 
16:50:02.765 -> Waiting 2min before the next round...
16:50:12.773 -> [HTTPS] begin...
16:50:12.773 -> [HTTPS] GET...
16:50:18.040 -> [HTTPS] GET... failed, error: connection failed
16:50:18.040 -> 
16:50:18.040 -> Waiting 2min before the next round...

1 Like

If I paste that address into Firefox, I get this response:

{
  "given_cipher_suites": [
    "TLS_AES_128_GCM_SHA256",
    "TLS_CHACHA20_POLY1305_SHA256",
    "TLS_AES_256_GCM_SHA384",
    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
    "TLS_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_RSA_WITH_AES_128_CBC_SHA",
    "TLS_RSA_WITH_AES_256_CBC_SHA"
  ],
  "ephemeral_keys_supported": true,
  "session_ticket_supported": true,
  "tls_compression_supported": false,
  "unknown_cipher_suite_supported": false,
  "beast_vuln": false,
  "able_to_detect_n_minus_one_splitting": false,
  "insecure_cipher_suites": {},
  "tls_version": "TLS 1.3",
  "rating": "Probably Okay"
}

Response headers:

Access-Control-Allow-Origin: *
Connection: close
Content-Encoding: gzip
Content-Length: 325
Content-Type: application/json
Date: Sat, 17 Feb 2024 16:53:23 GMT
Strict-Transport-Security: max-age=631138519; includeSubdomains; preload
Vary: Accept-Encoding

Request headers:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.5
Connection: keep-alive
Host: www.howsmyssl.com
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0

I don't know if any of the request headers are important.

Clutching at straws, I tried this change, which is more appropriate for use here in 'ol Blighty:

configTime("GMT0BST,M3.5.0/1,M10.5.0", "uk.pool.ntp.org");

Made no difference...

1 Like

It's a good bet that someone on this forum has the expertise to figure out this problem.

Question is, who, and how to get their attention.

1 Like

The NTP synchronization is working fine: you get the time, print it and setup() completes successfully.
The problem is that you think you have

// Root certificate for howsmyssl.com

but what the certificate really is

/dev/shm$ cat > tst.crt
-----BEGIN CERTIFICATE-----
MIIDzjCCAragAwIBAgIJQgAAFxJlyruxMA0GCSqGSIb3DQEBCwUAMFQxGTAXBgNV
BAoMEEFPIEthc3BlcnNreSBMYWIxNzA1BgNVBAMMLkthc3BlcnNreSBBbnRpLVZp
cnVzIFBlcnNvbmFsIFJvb3QgQ2VydGlmaWNhdGUwHhcNMjMwODE1MDA0NTM3WhcN
MjQwODEzMDA0NTM3WjAcMRowGAYDVQQDExF3d3cuaG93c215c3NsLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPJoVSSTk11Ooxfv9jMJM1REOa60
+rsUROC3NQkeJi0W6GEnLOxVG1jRPG14NxNju5ULzFidtQmI4v+hfvjrjDt3Pe8R
5V1heFVy4Les8QR9etUStw/g6P0b+m3ctAvEp0KfvrY3AwqvC5mJEWxA8wD87n9F
mRC9h8UOxIiZFBxZPSnVzx9SD6ABF199kHsghX84xBuYPq6NA80Rgoq0YqzJvbRY
jF3HYo8ZwgbidzBD8HL28wiApRf+dbmGeqJa7x2awtOrXL7s5wnCh23NAsxjsK4d
oBemR7Zk9/tMQGNyFtuY6oTrCf0C1/bR419CjQSkuW+7kD2NA2svTJupZ8ECAwEA
AaOB2jCB1zATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwHwYDVR0j
BBgwFoAU2jmj7l5rSw0yVb/vlWAYkK/YBwkwUwYDVR0RBEwwSocEIkctyIIRd3d3
Lmhvd3NteXNzbC5jb22CDWhvd3NteXNzbC5jb22CDWhvd3NteXRscy5jb22CEXd3
dy5ob3dzbXl0bHMuY29tMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9raXMuY3Js
LnNjci5rYXNwZXJza3ktbGFiLmNvbS9jcmwuY3JsMA0GCSqGSIb3DQEBCwUAA4IB
AQDG0xZU3wc8qVr5UEfFHoOm+RYSygo1fCBPUPOPj3TB4i+RWXPdeqLYVDo6/+ak
LnqGXjHxn6Dn1HJx81OdZ8gjINarbkQimdOT/CtjkinXs2t8vqk4CY8z5GgRHP7O
Ty/AKibefqIedtVR+/VO/wJd37/LBbN7wzRFWEbKMC2S68mCpwqnemYfEqBUreEL
m9y5YpAaY3r1p/l6+c+MzxDMi0Wi7VGf/y33UbfTe8v/gPBcoBkhCZZJZB4SQ25I
H9TRRdnSC40H/5QmhYvSsRet5S/iwsgKkMDr0IpnFWh+3iIMsYdwcgYnIV5JHHLN
ZQ4EBsBudMFHVO5v4cbkPZEj
-----END CERTIFICATE-----

/dev/shm$ openssl x509 -in tst.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            42:00:00:17:12:65:ca:bb:b1
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = AO Kaspersky Lab, CN = Kaspersky Anti-Virus Personal Root Certificate
        Validity
            Not Before: Aug 15 00:45:37 2023 GMT
            Not After : Aug 13 00:45:37 2024 GMT
        Subject: CN = www.howsmyssl.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:f2:68:55:24:93:93:5d:4e:a3:17:ef:f6:33:09:
                    33:54:44:39:ae:b4:fa:bb:14:44:e0:b7:35:09:1e:
                    26:2d:16:e8:61:27:2c:ec:55:1b:58:d1:3c:6d:78:
                    37:13:63:bb:95:0b:cc:58:9d:b5:09:88:e2:ff:a1:
                    7e:f8:eb:8c:3b:77:3d:ef:11:e5:5d:61:78:55:72:
                    e0:b7:ac:f1:04:7d:7a:d5:12:b7:0f:e0:e8:fd:1b:
                    fa:6d:dc:b4:0b:c4:a7:42:9f:be:b6:37:03:0a:af:
                    0b:99:89:11:6c:40:f3:00:fc:ee:7f:45:99:10:bd:
                    87:c5:0e:c4:88:99:14:1c:59:3d:29:d5:cf:1f:52:
                    0f:a0:01:17:5f:7d:90:7b:20:85:7f:38:c4:1b:98:
                    3e:ae:8d:03:cd:11:82:8a:b4:62:ac:c9:bd:b4:58:
                    8c:5d:c7:62:8f:19:c2:06:e2:77:30:43:f0:72:f6:
                    f3:08:80:a5:17:fe:75:b9:86:7a:a2:5a:ef:1d:9a:
                    c2:d3:ab:5c:be:ec:e7:09:c2:87:6d:cd:02:cc:63:
                    b0:ae:1d:a0:17:a6:47:b6:64:f7:fb:4c:40:63:72:
                    16:db:98:ea:84:eb:09:fd:02:d7:f6:d1:e3:5f:42:
                    8d:04:a4:b9:6f:bb:90:3d:8d:03:6b:2f:4c:9b:a9:
                    67:c1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Key Usage: 
                Digital Signature, Key Encipherment
            X509v3 Authority Key Identifier: 
                DA:39:A3:EE:5E:6B:4B:0D:32:55:BF:EF:95:60:18:90:AF:D8:07:09
            X509v3 Subject Alternative Name: 
                IP Address:34.71.45.200, DNS:www.howsmyssl.com, DNS:howsmyssl.com, DNS:howsmytls.com, DNS:www.howsmytls.com
            X509v3 CRL Distribution Points: 
                Full Name:
                  URI:http://kis.crl.scr.kaspersky-lab.com/crl.crl
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        c6:d3:16:54:df:07:3c:a9:5a:f9:50:47:c5:1e:83:a6:f9:16:
        12:ca:0a:35:7c:20:4f:50:f3:8f:8f:74:c1:e2:2f:91:59:73:
        dd:7a:a2:d8:54:3a:3a:ff:e6:a4:2e:7a:86:5e:31:f1:9f:a0:
        e7:d4:72:71:f3:53:9d:67:c8:23:20:d6:ab:6e:44:22:99:d3:
        93:fc:2b:63:92:29:d7:b3:6b:7c:be:a9:38:09:8f:33:e4:68:
        11:1c:fe:ce:4f:2f:c0:2a:26:de:7e:a2:1e:76:d5:51:fb:f5:
        4e:ff:02:5d:df:bf:cb:05:b3:7b:c3:34:45:58:46:ca:30:2d:
        92:eb:c9:82:a7:0a:a7:7a:66:1f:12:a0:54:ad:e1:0b:9b:dc:
        b9:62:90:1a:63:7a:f5:a7:f9:7a:f9:cf:8c:cf:10:cc:8b:45:
        a2:ed:51:9f:ff:2d:f7:51:b7:d3:7b:cb:ff:80:f0:5c:a0:19:
        21:09:96:49:64:1e:12:43:6e:48:1f:d4:d1:45:d9:d2:0b:8d:
        07:ff:94:26:85:8b:d2:b1:17:ad:e5:2f:e2:c2:c8:0a:90:c0:
        eb:d0:8a:67:15:68:7e:de:22:0c:b1:87:70:72:06:27:21:5e:
        49:1c:72:cd:65:0e:04:06:c0:6e:74:c1:47:54:ee:6f:e1:c6:
        e4:3d:91:23

/dev/shm$ curl --cacert tst.crt --capath . https://www.howsmyssl.com/a/check -vvv
* Host www.howsmyssl.com:443 was resolved.
* IPv6: (none)
* IPv4: 34.71.45.200
*   Trying 34.71.45.200:443...
* Connected to www.howsmyssl.com (34.71.45.200) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: tst.crt
*  CApath: .
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

What seems to have happened is that you have copied the assumed RootCA from your browser visiting the howsmyssl.com web page but you have the
CN = Kaspersky Anti-Virus Personal Root Certificate
substituted for the actual root certificate of the target page.

The antivirus thing in you computer might be a constant man-in-the-middle intercepting all the certificate exchanges and and establishing the secure transport on its own instead of the browser. In my opinion this is quite dangerous and risky approach. (Perhaps you can check if your banking connection shows the Kaspersky as root certificate authority)

Replace the certificate in your sketch with the real ISRG X1 (or X2) certificate and I think it should work (at least this stage)

2 Likes