Skip to Content

Control ESP32 from Telegram

Control ESP32 from Telegram

Learn how to control an ESP32 from the Telegram app on your phone. With this code you can, for instance, switch on lights and request the status of sensors or switches by sending messages from your Telegram app to an ESP32.

The demo code will show you how to turn an LED on and off, and how to read the state of a switch connected to your ESP32.

Required Parts

Below you will find the components required. I used an older ESP32 board, which has been deprecated but you can still get it for a very low price. However, any other ESP32 will work just fine as well.

You also will need an LED, a 220 Ohm resistor and a switch or push button.

ESP32 lite Lolin32

ESP32 lite

USB data cable

USB Data Cable

Dupont wire set

Dupont Wire Set

Half_breadboard56a

Breadboard

Resistor & LED kit

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Connecting LED and Switch to ESP32

We want to use the Telegram app on our phone to set or read GPIO pins on an ESP32. To demonstrate how this works we are going to connect an LED and a switch to the ESP32. The following picture shows the circuit:

Connecting LED and Switch to ESP32
Connecting LED and Switch to ESP32

The LED is connected to GPIO 33 and the Switch to GPIO 14. You can pick other pins but make sure to adjust the constants in the following code, accordingly. The picture below shows how I wired it on a breadboard:

ESP32 with LED and Switch on Breadboard
ESP32 with LED and Switch on Breadboard

Create Telegram Bot

Before you can send messages from the Telegram app on your phone to an ESP32 you will need to create a Telegram bot. If you haven’t done this before the ESP32 send Telegram Message tutorial explains it in detail.

Most importantly we will need the token of the bot, which looks something like this 1234567811:fakeIodw9023sjjoj982qe23dSSDCDDDSSxx and your user ID, which looks like this 7221435846. Both these constants will be needed in the code and will be specific for your bot.

Resetting the Bot

If you have already created a bot and want to reset its chat history then open the menu in the right upper corner and click on Clear History:

Bot menu with Clear History item
Bot menu with Clear History item

This will open the a dialog, where you need to confirm the action. The name of my bot is Marvin4, which is what you see in the following screenshot of the dialog:

Clear History dialog
Clear History dialog

After that, the bot shows a Start button at the bottom you can click. When started the bot will show the available commands again.

Start Button for bot
Start Button for bot

Code to control ESP32 via Telegram

Before you can run the following code on the ESP32 you will need to install the UniversalTelegramBot Library. It simplifies the code needed for the communication between Telegram and the ESP32.

To install the library open the LIBRARY MANAGER of the Arduino IDE, search for ‘UniversalTelegramBot’ and then click the INSTALL button. After a successful installation you should see the installed library:

The Arduino sketch below shows you how to use an ESP32 to communicate with a Telegram bot that can control an LED and read a switch state remotely via Telegram messages.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

const char* SSID = "xxxx";
const char* PASSWORD = "xxxx";

const String BOT_TOKEN = "xxxxxxxx:xxxxxxxxxxxxxxxxxxxx";
const String CHAT_ID = "xxxx";

const byte LED_PIN = 33;
const byte SW_PIN = 14;

const char* info =
  "Commands:\n\n"
  "/led_on set LED on\n"
  "/led_off set LED off\n"
  "/led_toggle toggle LED\n"
  "/sw_state get switch state\n";

WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);

int getNumMessages() {
  return bot.getUpdates(bot.last_message_received + 1);
}

void handleNewMessages(int numMessages) {
  for (int i = 0; i < numMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) continue;

    String text = bot.messages[i].text;
    Serial.println(text);

    if (text == "/start") {
      bot.sendMessage(chat_id, info, "");
    }

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

    if (text == "/led_off") {
      bot.sendMessage(chat_id, "LED is OFF", "");
      digitalWrite(LED_PIN, LOW);
    }

    if (text == "/led_toggle") {
      bool state = digitalRead(LED_PIN);
      const char* message = state ? "LED off" : "LED on";
      bot.sendMessage(chat_id, message, "");
      digitalWrite(LED_PIN, state ? LOW : HIGH);
    }

    if (text == "/sw_state") {
      bool state = digitalRead(SW_PIN);
      const char* message = state ? "Switch is ON" : "Switch is OFF";
      bot.sendMessage(chat_id, message, "");
    }
  }
}

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

  pinMode(LED_PIN, OUTPUT);
  pinMode(SW_PIN, INPUT_PULLUP);

  client.setCACert(TELEGRAM_CERTIFICATE_ROOT);

  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) delay(100);
}

void loop() {
  while (int numMessages = getNumMessages()) {
    handleNewMessages(numMessages);
  }
  delay(1000);
}

Including Required Libraries

The first lines of the code include the necessary libraries:

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

These are essential for ESP32 to connect to Wi-Fi and communicate with Telegram securely using HTTPS. WiFi.h is used for connecting to the wireless network, WiFiClientSecure.h enables secure HTTPS communication, and UniversalTelegramBot.h provides a convenient interface to interact with the Telegram Bot API.

Defining Credentials and Pins

The code then defines Wi-Fi credentials, the Telegram bot token, and the Telegram chat ID:

const char* SSID = "xxxx";
const char* PASSWORD = "xxxx";

const String BOT_TOKEN = "xxxxxxxx:xxxxxxxxxxxxxxxxxxxx";
const String CHAT_ID = "xxxx";

Replace these placeholders with your actual Wi-Fi name and password, your bot token and the chat ID with your User ID.

Next, we define the GPIO pins for the LED and the switch. GPIO 33 is configured as an output for the LED, and GPIO 14 is used as an input with a pull-up resistor for the switch.

const byte LED_PIN = 33;
const byte SW_PIN = 14;

The following string holds a help message that will be shown when the /start command is received. As you can see we will have commands to turn on, off or toggle the LED and to get the state of the switch:

const char* info =
  "Commands:\n\n"
  "/led_on set LED on\n"
  "/led_off set LED off\n"
  "/led_toggle toggle LED\n"
  "/sw_state get switch state\n";

Initializing the Bot

The bot is created with the token and a secure client:

WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);

WiFiClientSecure allows the bot to securely communicate with Telegram servers over HTTPS.

Fetching New Messages

The getNumMessages() function checks if new messages have been received by the bot:

int getNumMessages() {
  return bot.getUpdates(bot.last_message_received + 1);
}

The bot.getUpdates() method fetches all updates starting from the last received message, ensuring that messages are processed once.

Handling Commands

The handleNewMessages() function is responsible for processing each new message. Only messages from the predefined CHAT_ID are processed to prevent unwanted access.

void handleNewMessages(int numMessages) {
  for (int i = 0; i < numMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) continue;

The bot then compares the command text and performs actions accordingly:

if (text == "/start") {
  bot.sendMessage(chat_id, info, "");
}

When the user sends /start, the bot replies with the available command list.

Command List in Telegram Bot
Command List in Telegram Bot

In the next lines of code we handle the different commands.

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

The /led_on command turns the LED on and confirms the action via a message.

if (text == "/led_off") {
  bot.sendMessage(chat_id, "LED is OFF", "");
  digitalWrite(LED_PIN, LOW);
}

Similarly, the /led_off command turns the LED off.

if (text == "/led_toggle") {
  bool state = digitalRead(LED_PIN);
  const char* message = state ? "LED off" : "LED on";
  bot.sendMessage(chat_id, message, "");
  digitalWrite(LED_PIN, state ? LOW : HIGH);
}

The /led_toggle command essentially combines the /led_on and the /led_off commands. It reads the current state of the LED and inverts it. It then sends a status message to the user.

if (text == "/sw_state") {
  bool state = digitalRead(SW_PIN);
  const char* message = state ? "Switch is ON" : "Switch is OFF";
  bot.sendMessage(chat_id, message, "");
}

Finally, the /sw_state command reads the state of the switch and informs the user whether the switch is open (HIGH) or pressed (LOW, interpreted as OFF due to pull-up).

You can click on the links in the command list to execute these actions. The following screenshot shows how a chat that send commands via Telegram to the ESP32 looks like:

Commands sent from Telegram to ESP32
Commands sent from Telegram to ESP32

You can see the commands I am sending via Telegram on the right and the responses of the ESP32 on the left.

Setup Function

In the setup() function, serial communication is initialized for debugging:

Serial.begin(115200);

Then, the GPIO pins are configured:

pinMode(LED_PIN, OUTPUT);
pinMode(SW_PIN, INPUT_PULLUP);

The switch pin uses INPUT_PULLUP, which means we don’t need an external pull-up resistor when connecting the switch.

The certificate for Telegram is set to ensure secure HTTPS communication:

client.setCACert(TELEGRAM_CERTIFICATE_ROOT);

Then Wi-Fi is connected in a blocking loop:

WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(100);

This ensures the device doesn’t proceed until it has established a network connection.

Main Loop

The loop() function constantly checks for new messages:

while (int numMessages = getNumMessages()) {
  handleNewMessages(numMessages);
}
delay(1000);

It fetches any new Telegram messages, processes them, and then waits 1 second before checking again.

Conclusion

In this post you learned how to control an LED and to read the status of a switch by sending messages from your Telegram app on your mobile phone to an ESP32.

If this is a bit too complex have a look at our ESP32 send Telegram Message tutorial, which explains the basics of sending and receiving messages via Telegram in more detail.

If you have any question, feel free to leave them in the comment section.

Happy Tinkering ; )