ESP32 and Telegram issue with reboot

Hi all,

I am trying to use Telegram to restart my ESP32. I can get it to restart using ESP.restart(), but the restart keeps rebooting the device all the time. I wonder if there is a way to get it to restart only once?

The code is:

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>   // Universal Telegram Bot Library written by Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
#include <ArduinoJson.h>

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

// Initialize Telegram BOT
#define BOTtoken "mybottoken"  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
#define CHAT_ID "mychatid"


WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

// Checks for new messages every 200 milliseconds.
int botRequestDelay = 200;
unsigned long lastTimeBotRan;

const int ledPin = 2;
bool ledState = LOW;

// Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

  for (int i = 0; i < numNewMessages; i++) {
    // Chat id of the requester
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

    // Print the received message
    String text = bot.messages[i].text;
    Serial.println(text);

    String from_name = bot.messages[i].from_name;

    if (text == "/reboot") {
      bot.sendMessage(chat_id, "ESP will now restart", "");
      ESP.restart();
    }

    void setup() {
      Serial.begin(115200);
      // Connect to Wi-Fi
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
#ifdef ESP32
      client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
#endif
      while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi..");
      }
      // Print ESP32 Local IP Address
      Serial.println(WiFi.localIP());
    }

    void loop() {
      if (millis() > lastTimeBotRan + botRequestDelay)  {
        int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

        while (numNewMessages) {
          Serial.println("got response");
          handleNewMessages(numNewMessages);
          numNewMessages = bot.getUpdates(bot.last_message_received + 1);
        }
        lastTimeBotRan = millis();
      }
    }


I have also tested using pin 13 to be HIGH at the setup, and connect that wire to the EN pin, and then pulling pin 13 LOW when I send the /reboot command, but that doesn't work any better. Somehow ESP32 remembers that I sent a reboot command.

Should I connect the EN pin to the ground through a transistor and use pin 13 to write HIGH to the base of the transistor, causing it to connect to ground?

Any help greatly appreciated. I guess I can always add a servo that physically presses the EN button but gettig it to retract might be tricky.

A goto to get you back to setup() ?

does not compile??
you're brackets are messed in handleNewMessages..

try adding a global to track if you've exec restart command and only do it once..
curious, what do you see on the Serial prints??

good luck.. ~q

I am not sure where you'd put this.

It does compile. What happens is that after the ESP.restart() the system does show the boot routines, but then shows the Telegram command /reboot and restarts again.

You want to restart the device from setup or from loop?

I'd need it to restart when I send the Telegram message /reboot.

Currently it does reboot, but it remembers the last command and reboots again.

I did not see in your code that you are using RTC_ram or any file system to store previous values to be available after a boot, so how does a ESP32 remember after a boot? Could be your transmitter is sending the same command over and over again for the ESP32?

That’s a good point. But I have sent the command /start after the /reboot, but it ignores the /start and goe son to /reboot.

The channel is declared in the setup() so in my mind, it should erase all previous Telegram stuff.

even if you press the reset button on the esp32?

and this code you posted

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>   // Universal Telegram Bot Library written by Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
#include <ArduinoJson.h>

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

// Initialize Telegram BOT
#define BOTtoken "mybottoken"  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
#define CHAT_ID "mychatid"


WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

// Checks for new messages every 200 milliseconds.
int botRequestDelay = 200;
unsigned long lastTimeBotRan;

const int ledPin = 2;
bool ledState = LOW;

// Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

  for (int i = 0; i < numNewMessages; i++) {
    // Chat id of the requester
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

    // Print the received message
    String text = bot.messages[i].text;
    Serial.println(text);

    String from_name = bot.messages[i].from_name;

    if (text == "/reboot") {
      bot.sendMessage(chat_id, "ESP will now restart", "");
      ESP.restart();
    }

    void setup() {
      Serial.begin(115200);
      // Connect to Wi-Fi
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
#ifdef ESP32
      client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
#endif
      while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi..");
      }
      // Print ESP32 Local IP Address
      Serial.println(WiFi.localIP());
    }

    void loop() {
      if (millis() > lastTimeBotRan + botRequestDelay)  {
        int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

        while (numNewMessages) {
          Serial.println("got response");
          handleNewMessages(numNewMessages);
          numNewMessages = bot.getUpdates(bot.last_message_received + 1);
        }
        lastTimeBotRan = millis();
      }
    }

does not compile. Each { must have a } is one issue.

Also, explain to me how does an ESP32 remember its settings or previous programed variables or whatever without using RTC ram or preferences or the file system?

Ok, here's a version that does compile - I snipped off a little too much to save space.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>   // Universal Telegram Bot Library written by Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
#include <ArduinoJson.h>

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

// Initialize Telegram BOT
#define BOTtoken "MY:BOT"  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
#define CHAT_ID "MY:CHAT"


WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

// Checks for new messages every 200 milliseconds.
int botRequestDelay = 200;
unsigned long lastTimeBotRan;

const int ledPin = 2;
bool ledState = LOW;

// Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

  for (int i = 0; i < numNewMessages; i++) {
    // Chat id of the requester
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

    // Print the received message
    String text = bot.messages[i].text;
    Serial.println(text);

    String from_name = bot.messages[i].from_name;

    if (text == "/start") {
      String welcome = "Welcome, " + from_name + ".\n";
      welcome += "Use the following commands to control your outputs.\n\n";
      welcome += "/lon to turn on led \n";
      welcome += "/loff to turn off led\n";
      welcome += "/reboot to reset the ESP32\n";
      bot.sendMessage(chat_id, welcome, "");
    }

    if (text == "/reboot") {
      bot.sendMessage(chat_id, "ESP will now restart", "");
      reBoot();
    }

    if (text == "/lon") {
      digitalWrite(ledPin, HIGH);
      bot.sendMessage(chat_id, "LED is ON", "");
    }

    if (text == "/loff") {
      digitalWrite(ledPin, HIGH);
      bot.sendMessage(chat_id, "LED is OFF", "");
    }
  }
}

void reBoot() {
  delay(5000);
  digitalWrite(13, HIGH);
}

void setup() {
  pinMode (13, OUTPUT);
  digitalWrite(13, LOW);
  Serial.begin(115200);
  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
#ifdef ESP32
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
#endif
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());
}

void loop() {
  if (millis() > lastTimeBotRan + botRequestDelay)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    lastTimeBotRan = millis();
  }
}

As for how it should remember anything, this is my question. I don't see my Telegram sending it many times, but I see the device answering until I unplug it.

I'm not convinced that the ESP32 as per the code above is retaining any information between reboots.

Well, I need to make a video of what happens in that case. I'll try to make one over the weekend.
And yes, the only way I can stop it from sending responses to my Telegram on my phone is to reflash it.

You don't need a GOTO.
setup() can be called by meeting an if() condition --

const byte pIP = 2;
byte poll;

void setup() 
{
  Serial.begin(9600);
  Serial.println("I have been Reset.");
  pinMode(pIP, INPUT_PULLUP);
}

void loop() 
{
  poll = digitalRead(pIP);
  if(!poll)
  {
    delay(500);
    setup();
  }

}

recursion?

Takes it all the way back to the beginning --

if (text == "/reboot")
{
  bot.sendMessage(chat_id, "ESP will now restart", "");
  delay(500);  // ??
  setup(); // ESP.restart()
}

Isn't that the objective ?

The final use for this Telegram reboot is this:

I have a device monitoring environmental parameters. It writes data to a database once a minute. For some reason, which I have not yet solved, the temp sensor will report 179.00 C.

At the time my PHP writes in the database, I want to check this random anomaly, and instead of writing the database, I want to send a reboot from PHP via Telegram so that my sensors are booted too. A setup() won't achieve this.

Why not have the ESP read the thingy being sent and if its over XXXX.XX then reboot?

Better yet, solve the issue?

Mostly because I like doing things the hard way, and I have other uses for the Telegram - ESP32 channel. Debugging the BMP280 has been troublesome so far, but I hope to find out what happens every now and again.

my money's here..
thinking it does reboot, quickly too..
now it's a new bot, the value passed into bot.getUpdates confuses it..
probably just sends the last message till you catch back up??

strange days.. ~q