Skip to content

ESP32 google sheets error (Failed to initlalize the SSL layer.) #103

Description

@cesarruiz730

I have a code in an ESP32-C3 in ARDUINO-IDE where I read humidity in a plant and then I send it to google sheets so that I can store it and analyze it there. However, I have a problem. If the span of time between messages to google sheets is araound 1 miniute, then there is no problem, but if I put 10 minutes or bigger then it will stop sending data to google sheets.

I read that it could be because the token is not renovating correctly but I do not know how to solve it.

Also, the code uses almost all the memory of the esp32, i do not know if it is related. I does not explain why it works with 1 min, but not 10 or longer.

Thank you.

ERROR:

Append spreadsheet values...

WARN.mRunUntil: Terminating because the ssl engine closed.
ERROR.mConnectSSL: Failed to initlalize the SSL layer.
ERROR.mConnectSSL: Validation time is unknown.
unknown error

CODE:
#include <Arduino.h>
#include "time.h"
#include <ESP_Google_Sheet_Client.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include <ArduinoJson.h>

AsyncWebServer server(80);

#define WIFI_SSID ""
#define WIFI_PASSWORD "
"

// ID del Proyecto de Google
#define PROJECT_ID "**"

// Correo electrónico del cliente de la Cuenta de Servicio
#define CLIENT_EMAIL "**"

// Clave privada de la Cuenta de Servicio
const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----**\n-----END PRIVATE KEY-----\n";

// El ID de la hoja de cálculo donde se publicarán los datos
const char spreadsheetId[] = "**";

int valorHumedad, humedad;
int referencia = 65;
int Amplitud = 10;
int referencia_superior = referencia + Amplitud;
int referencia_inferior = referencia - Amplitud;

int motorEstado = 0; // Variable para almacenar el estado de la bomba de agua

unsigned long lastTime = 0;
const unsigned long interval = 1000; // 1 segundo

unsigned long lastUpdate = 0;
const unsigned long updateInterval = 1800000; // 30 minutos

// Servidor NTP para solicitar la hora
const char* ntpServer = "pool.ntp.org";

// Función que obtiene la hora actual
String getTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return "Fallo al obtener la hora";
}
char timeStringBuff[50];
strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%d %H:%M:%S", &timeinfo);
return String(timeStringBuff);
}

void handleRoot(AsyncWebServerRequest *request) {
String html = "";
html += "";
html += "<style>";
html += "body { font-family: Arial, sans-serif; text-align: center; margin: 0; padding: 20px; }";
html += "h1 { font-size: 28px; margin-bottom: 20px; }";
html += "p { font-size: 22px; margin-bottom: 20px; }";
html += "form { margin: 20px 0; }";
html += "input[type='submit'] { font-size: 22px; padding: 15px 30px; margin: 5px; }";
html += "</style>";
html += "";
html += "

Control ESP32

";
html += "

Referencia actual: " + String(referencia) + "

";
html += "";
html += "";
html += "";
html += "";
html += "";
html += "";
html += "";
html += "";
html += "";
request->send(200, "text/html", html);
}

void handleSetReferencia(AsyncWebServerRequest *request) {
String html = "";
html += "";
html += "<style>";
html += "body { font-family: Arial, sans-serif; text-align: center; margin: 0; padding: 20px; }";
html += "h1 { font-size: 28px; margin-bottom: 20px; }";
html += "a { font-size: 22px; text-decoration: none; color: #0000EE; }";
html += "</style>";
html += "";

if (request->hasParam("action", true)) {
String action = request->getParam("action", true)->value();
if (action == "increase") {
referencia += 10;
} else if (action == "decrease") {
referencia -= 10;
}
html += "

Referencia actualizada!

";
} else {
html += "

Error: ¡Acción no proporcionada!

";
}
html += "Volver";
html += "";
request->send(200, "text/html", html);
}

void enviarDatosGoogleSheets(int humedad, int motorEstado, int referencia_superior, int referencia_inferior, int referencia) {
FirebaseJson response;
Serial.println("\nAñadiendo valores a la hoja de cálculo...");
Serial.println("----------------------------");

FirebaseJson valueRange;
String currentTime = getTime();
valueRange.add("majorDimension", "COLUMNS");
valueRange.set("values/[0]/[0]", currentTime); // Enviar la fecha y hora combinadas
valueRange.set("values/[1]/[0]", humedad);
valueRange.set("values/[2]/[0]", motorEstado);
valueRange.set("values/[3]/[0]", referencia);
valueRange.set("values/[4]/[0]", referencia_inferior);
valueRange.set("values/[5]/[0]", referencia_superior);

// Añadir valores a la hoja de cálculo
bool success = GSheet.values.append(&response, spreadsheetId, "Hoja1!A1", &valueRange);
if (success) {
response.toString(Serial, true);
valueRange.clear();
} else {
Serial.println(GSheet.errorReason());
}
Serial.println();
Serial.println(ESP.getFreeHeap());
}

void reconnectWiFi() {
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Reconectando a Wi-Fi");
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println();
Serial.print("Reconectado con IP: ");
Serial.println(WiFi.localIP());
Serial.println();
}
}

void reconnectGoogleSheet() {
if (!GSheet.ready()) {
Serial.println("Reconectando a Google Sheets...");
ESP.restart();
}
}

void tokenStatusCallback(TokenInfo info) {
if (info.status == token_status_error) {
Serial.printf("Información del token: tipo = %s, estado = %s\n", GSheet.getTokenType(info).c_str(), GSheet.getTokenStatus(info).c_str());
Serial.printf("Error del token: %s\n", GSheet.getTokenError(info).c_str());
} else {
Serial.printf("Información del token: tipo = %s, estado = %s\n", GSheet.getTokenType(info).c_str(), GSheet.getTokenStatus(info).c_str());
}
}

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

pinMode(7, OUTPUT); // Configurar el pin de salida para el motor

// Para UTC+2 (horario de verano en España):
configTime(7200, 0, ntpServer);

GSheet.printf("Cliente ESP Google Sheet v%s\n\n", ESP_GOOGLE_SHEET_CLIENT_VERSION);

// Conectar a Wi-Fi
WiFi.setAutoReconnect(true);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

Serial.print("Conectando a Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println();
Serial.print("Conectado con IP: "); Serial.println(WiFi.localIP());
Serial.println();

// Configurar el callback para la generación del token de acceso de Google API
GSheet.setTokenCallback(tokenStatusCallback);

// Configurar el tiempo de refresco del token de acceso antes de expirar
GSheet.setPrerefreshSeconds(10 * 60);

// Iniciar la generación del token de acceso para la autenticación de Google API
GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY);

// Iniciar el servidor web
server.on("/", HTTP_GET, handleRoot);
server.on("/setReferencia", HTTP_POST, handleSetReferencia);
server.begin();
}

void loop() {
int referencia_superior = referencia + Amplitud;
int referencia_inferior = referencia - Amplitud;

// Llamar a ready() repetidamente en el bucle para verificar la autenticación y el procesamiento
bool ready = GSheet.ready();

reconnectWiFi();
reconnectGoogleSheet();

valorHumedad = analogRead(4); // Leer el valor del sensor de humedad
humedad = map(valorHumedad, 0, 4095, 0, 100); // Mapear el valor del sensor a un porcentaje

// Control por histéresis
if (humedad < referencia_inferior) {
while (humedad < referencia_superior) {
// Enviar datos a Google Sheets
enviarDatosGoogleSheets(humedad, motorEstado, referencia_superior, referencia_inferior, referencia);

  digitalWrite(7, HIGH); // Encender el pin de salida
  motorEstado = 1; // Actualizar el estado del motor

  realizarDelayConHandleClient(1); // Tiempo de muestreo 1 seg si el motor está en ON

  valorHumedad = analogRead(4); // Lectura de la humedad
  humedad = map(valorHumedad, 0, 4095, 0, 100);

  // Para depuración: imprimir valores
  Serial.println("Ajustando humedad");
  Serial.print("Humedad: "); Serial.println(humedad);
  Serial.println("Encendiendo bomba de agua: humedad baja");
}
digitalWrite(7, LOW); // Apagar el pin de salida
motorEstado = 0; // Actualizar el estado del motor
Serial.println("Apagando salida: humedad alcanzada");

// Enviar datos a Google Sheets
enviarDatosGoogleSheets(humedad, motorEstado, referencia_superior, referencia_inferior, referencia);

realizarDelayConHandleClient(60); // 1800 segundos (media hora) de delay comprobando el servidor

} else {
digitalWrite(7, LOW); // Apagar el pin de salida
motorEstado = 0; // Actualizar el estado del motor

Serial.println("Humedad correcta");
Serial.print("Valor humedad = "); Serial.println(humedad); // Imprimir valor de humedad en el monitor serie

// Enviar datos a Google Sheets
enviarDatosGoogleSheets(humedad, motorEstado, referencia_superior, referencia_inferior, referencia);

realizarDelayConHandleClient(60); // 1800 segundos (media hora) de delay comprobando el servidor

}
}

void realizarDelayConHandleClient(int segundos) {
int contador = 0;
while (contador < segundos * 10) { // Multiplicamos por 10 para tener iteraciones de 0.1 segundos
delay(100); // Reducimos el delay a 100 ms
contador++;
yield(); // Permitir que el sistema haga sus tareas de mantenimiento
}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions