[SOLVED] Errors while sending messages using UniversalTelegramBot

Hello!

I'm using an espressif esp32 Dev Module on Arduino IDE and I'm having some problems using the lib UniversalTelegramBot alongside WiFiClientSecure.

My intent is to have a HCSR04 sensor that sends a message through telegram whenever an object is detected. Moreover I also would like to control its activation and a buzzer using the telegram bot message update.

I'm using Tasks to organize the code and sometimes the esp32 crashes and reboots while attempting to send a message. Checking the decoded error, it looks like the function mbedtls_ssl_handshake_client_step is stucking.

How to handle this? I tried a try-catch to deal if the exception, but it does not work.
Also monitored the stack and heap usage using uxTaskGetStackHighWaterMark(NULL) and xPortGetFreeHeapSize(), but they did not reached their limits.

Code reference:

#include <HCSR04.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#define TELEGRAM_DEBUG true

TaskHandle_t listener_handle;
TaskHandle_t sensor_handle;

//alterar pinos
const byte on_led_pin = 13;
const byte sensor_led_pin = 12;
const byte buzzer_led_pin = 14;
const byte buzzer_pin = 27;
const byte echo_pin = 26;
const byte trigger_pin = 25;

bool sensor_on = true;
bool buzzer_on = false;

float last_distance;
float current_distance;
float distance_treshold = 10.0;
UltraSonicDistanceSensor distanceSensor(trigger_pin, echo_pin);

const char* ssid = "ssid";
const char* password = "password";

const String chat_id = "chad_id";
const String bot_token = "bot_token";
WiFiClientSecure secured_client;
UniversalTelegramBot bot(bot_token, secured_client);

bool door_is_open = false;
bool door_was_open = false;
bool is_sending_message = false;

void setup() {
  Serial.begin(9600);
  setup_pins();
  setup_wifi();
  setup_tasks();
}

void loop() {}

void setup_pins() {
  pinMode(on_led_pin, OUTPUT);
  pinMode(sensor_led_pin, OUTPUT);
  pinMode(buzzer_led_pin, OUTPUT);
  pinMode(buzzer_pin, OUTPUT);
}

void setup_wifi() {
  Serial.println("Conectando...");
  delay(100);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT);
  secured_client.setHandshakeTimeout(5);
  //secured_client.setTimeout(5);
  WiFi.setSleep(false);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Falha ao conectar, tentando novamente...");
    delay(1000);
  }
  Serial.println("Conectou");
  Serial.println(WiFi.localIP());
  send_message("Robozinho conectado ๐Ÿค–๐ŸŒ");
}

void setup_tasks() {
  const int stack_size = 32 * 1024;
  xTaskCreatePinnedToCore(listener_task, "listener", stack_size, NULL, 1, &listener_handle, 1);
  delay(500);
  xTaskCreatePinnedToCore(sensor_task, "sensor", 2048, NULL, 2, &sensor_handle, 1);
  delay(500);
  xTaskCreatePinnedToCore(maybe_notify_task, "maybe notify", stack_size, NULL, 1, NULL, 1);
  delay(100);
  xTaskCreate(maybe_buzz_task, "maybe buzz", 1024, NULL, 2, NULL);
  delay(100);
  xTaskCreate(maybe_blink_task, "maybe blink", 1024, NULL, 2, NULL);
}

void sensor_task(void* params) {
  while (true) {
    if (sensor_on) {
      read_distance();
    }
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void listener_task(void* params) {
  while (true) {
    get_updates();
    vTaskDelay(4000 / portTICK_PERIOD_MS);
  }
}

void maybe_buzz_task(void* params) {
  while(true){
    if (door_is_open && buzzer_on) {
      digitalWrite(buzzer_pin, HIGH);
      vTaskDelay(250 / portTICK_PERIOD_MS);
      digitalWrite(buzzer_pin, LOW);
    }
    vTaskDelay(250 / portTICK_PERIOD_MS);
  }
}

void maybe_blink_task(void* params){
  while(true){
    if (sensor_on) {
      digitalWrite(on_led_pin, HIGH);
      vTaskDelay(250 / portTICK_PERIOD_MS);
      digitalWrite(on_led_pin, LOW);
    }
    vTaskDelay(250 / portTICK_PERIOD_MS);
  }
}

void maybe_notify_task(void* params){
  while(true){
    if (door_is_open != door_was_open) {
      show_memory_info("notify");
      if (door_is_open) {
        Serial.println("Porta aberta");
        send_message("Porta aberta ๐ŸšชโŒ");
      } else {
        Serial.println("Porta fechada");
        send_message("Porta fechada ๐Ÿšชโœ…");
      }
    }
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void show_memory_info(String task){
  Serial.print(task);
  Serial.print(" Stack: ");
  Serial.println(uxTaskGetStackHighWaterMark(NULL));
  Serial.print(task);
  Serial.print(" Heap: ");
  Serial.println(xPortGetFreeHeapSize());
  Serial.println();
}

void get_updates(){
  int messages_quantity = bot.getUpdates(bot.last_message_received + 1);
    while (messages_quantity)
    {
      handle_new_messages(messages_quantity);
      messages_quantity = bot.getUpdates(bot.last_message_received + 1);
    }
}

void handle_new_messages(int messages_quantity){
  for (int i = 0; i < messages_quantity; i++)
  {
    select_command(bot.messages[i].text);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void select_command(String command) {
  Serial.println("Comando recebido: " + command);
  if (command == "/ativar_sensor") {
    sensor_on = true;
    send_message("Sensor ativado ๐Ÿ’กโœ…");
  } else if (command == "/desativar_sensor") {
    sensor_on = false;
    send_message("Sensor desativado ๐Ÿ’กโŒ");
  } else if (command == "/ativar_alarme") {
    buzzer_on = true;
    send_message("Alarme ativado ๐Ÿ”Šโœ…");
  } else if (command == "/desativar_alarme") {
    buzzer_on = false;
    send_message("Alarme desativado ๐Ÿ”ˆโŒ");
  } else {
    send_message("Comando desconhecido ๐Ÿง๐Ÿค”: " + command);
  }
}

void send_message(String message) {
  if(is_sending_message) return;

  is_sending_message = true;
  Serial.println("Enviando mensage: " + message);
  try {
    bot.sendMessage(chat_id, message, "");
  }
  catch (...) {
    is_sending_message = false;
    Serial.println("Falha ao enviar mensagem: " + message);
  }
  
  is_sending_message = false;
  Serial.println("Mensagem enviada");
}

void read_distance() {
  last_distance = current_distance;
  current_distance = distanceSensor.measureDistanceCm();
  //Serial.printf("Current distance: %.2f \n", current_distance);
  if (current_distance < 0) return;
  door_was_open = door_is_open;
  door_is_open = is_door_open(current_distance);
}

bool is_door_open(float distance) {
  return distance >= distance_treshold;
}

Error:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x4011f45c  PS      : 0x00060630  A0      : 0x8011d648  A1      : 0x3fff4080  
A2      : 0x00000008  A3      : 0x00000000  A4      : 0x0000019c  A5      : 0x3ffd7340  
A6      : 0x3ffb9d14  A7      : 0x0000002a  A8      : 0x00000000  A9      : 0x3ff5f078  
A10     : 0x3ffd71a4  A11     : 0x3f41f6d8  A12     : 0x00000000  A13     : 0x3ffd7194  
A14     : 0x0000414d  A15     : 0x0000000d  SAR     : 0x0000000a  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x0000000a  LBEG    : 0x400844a1  LEND    : 0x400844a9  LCOUNT  : 0x00000027  


Backtrace: 0x4011f459:0x3fff4080 0x4011d645:0x3fff4130 0x4011d6ab:0x3fff4150 0x400d6d89:0x3fff4170 0x400d6425:0x3fff43a0 0x400d64c1:0x3fff43e0 0x400d658a:0x3fff4450 0x400d90ba:0x3fff4470 0x400da7d5:0x3fff44d0 0x400da909:0x3fff4550 0x400d2987:0x3fff45d0 0x400d2a89:0x3fff4610 0x4008e786:0x3fff4650

Decoded error:

PC: 0x4011f45c: mbedtls_ssl_handshake_client_step at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls12_client.c:2752
EXCVADDR: 0x0000000a

Decoding stack results
0x4011f459: mbedtls_ssl_handshake_client_step at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls12_client.c:2709
0x4011d645: mbedtls_ssl_handshake_step at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls.c:4546
0x4011d6ab: mbedtls_ssl_handshake at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls.c:4610
0x400d6d89: ssl_starttls_handshake(sslclient_context*) at /home/daegonny/.arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/NetworkClientSecure/src/ssl_client.cpp:311
0x400d6425:  is in NetworkClientSecure::connect(IPAddress, unsigned short, char const*, char const*, char const*, char const*) (/home/daegonny/.arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp:151).
0x400d64c1:  is in NetworkClientSecure::connect(char const*, unsigned short, char const*, char const*, char const*) (/home/daegonny/.arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp:144).
0x400d658a:  is in NetworkClientSecure::connect(char const*, unsigned short) (/home/daegonny/.arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp:126).
0x400d90ba:  is in UniversalTelegramBot::sendPostToTelegram(String const&, ArduinoJson::V710PB22::JsonObject) (/home/daegonny/Arduino/libraries/UniversalTelegramBot/src/UniversalTelegramBot.cpp:150).
0x400da7d5:  is in UniversalTelegramBot::sendPostMessage(ArduinoJson::V710PB22::JsonObject, bool) (/home/daegonny/Arduino/libraries/UniversalTelegramBot/src/UniversalTelegramBot.cpp:644).
0x400da909:  is in UniversalTelegramBot::sendMessage(String const&, String const&, String const&, int) (/home/daegonny/Arduino/libraries/UniversalTelegramBot/src/UniversalTelegramBot.cpp:575).
0x400d2987: send_message(String) at /home/daegonny/Arduino/thms_pxt/thms_pxt.ino:191
0x400d2a89: maybe_notify_task(void*) at /home/daegonny/Arduino/thms_pxt/thms_pxt.ino:129
0x4008e786: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162

I figured out the problem. That Telegram library is not thread safe, so I created a mutex and used it every time the code needs to send or fetch a message.

Would you please tell me, how to do mutex. I googled it but not found anything..
I have the same problem.
I need to create a MAX7219 based LED Internet Clock, where it will shows , TIME, TEmprature, Date, DAY and at last if there any telegram message, it should shows. BUT it is not working..

see my code.

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include "Font_Data.h"

#define BOT_TOKEN "7078596485:AAHSWfgsOiTKEV5FC9gTG2EMnD79J2j087Q"

WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);




#define ThermistorPin 35
#define positivePin 33
#define negativePin 32
#define buzzer 2
#define NUM_ZONES 3
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define DATA_PIN 13    // pin connection in esp32
#define CLK_PIN 14     // pin connection in esp32
#define CS_PIN 12      // pin connection in esp32
#define MAX_DEVICES 4  //maximum max7219 module connected in chain
MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

#define SPEED_TIME 50  // Speed of the transition
#define PAUSE_TIME 1000

unsigned long previousMillis = 0;         // Timer for Telegram polling
unsigned long displayPreviousMillis = 0;  // Timer for display refresh
const long telegramInterval = 1000;       // Poll Telegram every 15 seconds
// Global variables
float temp = 0;
char message[100] = "";
char szMesg[50] = "";
uint8_t degC[] = { 6, 3, 3, 28, 34, 34, 34 };  // Deg C
uint8_t clear = 0x00;
bool isPM;
String text;
String msg = "0";
char second[3], minute[3], hour[3], day[10], date[3], month[10], year[5];
const char* ssid = "HomeFiber_4g";       // SSID of local network
const char* password = "Hima@nilu123";   //Password of wifi
const char* ntpServer = "pool.ntp.org";  //NTP server for getting time
const long gmtOffset_sec = 19800;        //Set your timezone in second, Here I used for India(GMT+ 5.30hr)
const int daylightOffset_sec = 0;        //Daylight saving is off here for India
const long intervalo = 1000;             //Time interval between checking messages (in milliseconds)
int lastMinute = -1;

//getting time from NTP Server
void printLocalTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    P.print("error");
    return;
  }
  strftime(day, sizeof(day), "%A", &timeinfo);
  strftime(month, sizeof(month), "%B", &timeinfo);
  strftime(date, sizeof(date), "%d", &timeinfo);
  strftime(year, sizeof(year), "%Y", &timeinfo);
  strftime(hour, sizeof(hour), "%H", &timeinfo);
  strftime(minute, sizeof(minute), "%M", &timeinfo);
  strftime(second, sizeof(second), "%S", &timeinfo);
}

void getTime(char* psz, bool f = true) {
  int hourInt = atoi(hour);
  int hour12 = hourInt % 12;
  if (hour12 == 0) {
    hour12 = 12;
  }
  isPM = hourInt >= 12;
  sprintf(psz, "%02d%c%02d", hour12, (f ? ':' : ' '), atoi(minute));
}
void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = bot.messages[i].chat_id;
    text = bot.messages[i].text;
    String from_name = bot.messages[i].from_name;
    msg = "Hello, " + from_name + ",\n" + text + "\ndisplayed.";
    Serial.println(msg);
    bot.sendMessage(chat_id, msg, "");
    // Mark that a new message is available and hasn't been displayed yet
  }
}

void setup() {
  P.begin();
  P.setIntensity(0);
  P.addChar('$', degC);
  P.displayText(szMesg, PA_CENTER, SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT);
  pinMode(buzzer, OUTPUT);
  pinMode(positivePin, OUTPUT);
  pinMode(negativePin, OUTPUT);
  digitalWrite(positivePin, HIGH);
  digitalWrite(negativePin, LOW);
  Serial.begin(115200);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);                           // Connect to Wi-Fi
  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT);  // Add root certificate for Telegram
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected.");


  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer, "time.nist.gov");
  delay(100);
  printLocalTime();
}


void loop() {

  getTemperature();
  printLocalTime();
  static uint32_t lastTime = 0;  // millis() memory
  static uint8_t display = 0;    // Current display mode
  static bool flasher = false;   // Seconds passing flasher

  if (atoi(second) == 0 && lastMinute != 0) {
    digitalWrite(buzzer, HIGH);
    delay(100);
    digitalWrite(buzzer, LOW);
  }
  lastMinute = atoi(second);

  if (P.displayAnimate()) {

    switch (display) {
      case 0:  // Temperature deg Celsius
        {
          P.setFont(nullptr);
          P.setPause(1000);
          P.setTextEffect(PA_SCROLL_LEFT, PA_SCROLL_UP);
          display++;
          dtostrf(temp, 3, 1, szMesg);
          strcat(szMesg, "$");
          Serial.print("Temperature: ");
          Serial.println(temp);
          break;
        }
      case 1:  // Clock
        {
          P.setFont(numeric7Seg);
          P.setTextEffect(PA_PRINT, PA_NO_EFFECT);
          P.setPause(0);
          if ((millis() - lastTime) >= 500) {
            lastTime = millis();
            getTime(szMesg, flasher);
            Serial.println(szMesg);
            flasher = !flasher;
          }
          if ((atoi(second) == 5) && (atoi(second) <= 30)) {
            P.setTextEffect(PA_PRINT, PA_WIPE_CURSOR);
            display++;
          }
          break;
        }

      case 2:  // Calendar
        {
          P.setFont(nullptr);
          P.setTextEffect(PA_SCROLL_LEFT, PA_SCROLL_LEFT);
          display++;
          getDays(szMesg);
          P.setPause(1000);
          break;
        }
      case 3:

        {
 if (millis() - previousMillis >= telegramInterval) { 
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    if (numNewMessages) {
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
      // Copy the latest message to the display buffer
    }
    previousMillis = millis();
  }
          strcpy(szMesg, text.c_str());
          display = 0;
          break;
        }
    }
    P.displayReset();
  }
}

float getTemperature() {
  float R1 = 9950;  // value of R1 on board
  float logR2, R2;
  //steinhart-hart coeficients for thermistor
  float c1 = 0.001129148, c2 = 0.000234125, c3 = 0.0000000876741;
  long ADC_Value = analogRead(ThermistorPin);
  R2 = R1 * (4096.0 / (float)ADC_Value - 1.0);  //calculate resistance on thermistor
  logR2 = log(R2);
  temp = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));  // temperature in Kelvin
  temp = temp - 273.15;                                           //convert Kelvin to Celcius
  return temp;
}

void getDays(char* psz) {
  String dayStr = String(day);
  String monthStr = String(month);
  String subStr1 = dayStr.substring(0, 3);
  String subStr2 = monthStr.substring(0, 3);
  strcpy(szMesg, subStr2.c_str());
  strcat(szMesg, " ");
  strcat(szMesg, subStr1.c_str());
  strcat(szMesg, " ");
  strcat(szMesg, date);
  Serial.println(szMesg);
}