Telegram: Control ESP32/ESP8266 Outputs (Arduino IDE)

This guide shows how to control the ESP32 or ESP8266 NodeMCU GPIOs from anywhere in the world using Telegram. As an example, we’ll control an LED, but you can control any other output. You just need to send a message to your Telegram Bot to set your outputs HIGH or LOW. The ESP boards will be programmed using Arduino IDE.

ESP32 ESP8266 NodeMCU Control Outputs LED Telegram Arduino

Project Overview

In this tutorial we’ll build a simple project that allows you to control ESP32 or ESP8266 NodeMCU GPIOs using Telegram. You can also control a relay module.

ESP32 ESP8266 NodeMCU Telegram Control Outputs Overview
  • You’ll create a Telegram bot for your ESP32/ESP8266 board;
  • You can start a conversation with the bot;
  • When you send the message /led_on to the bot, the ESP board receives the message and turns GPIO 2 on;
  • Similarly, when you send the message /led_off, it turns GPIO 2 off;
  • Additionally, you can also send the message /state to request the current GPIO state. When the ESP receives that message, the bot responds with the current GPIO state;
  • You can send the /start message to receive a welcome message with the commands to control the board.

This is a simple project, but shows how you can use Telegram in your IoT and Home Automation projects. The idea is to apply the concepts learned in your own projects.

Introducing Telegram

Telegram Messenger is a cloud-based instant messaging and voice over IP service. You can easily install it in your smartphone (Android and iPhone) or computer (PC, Mac and Linux). It is free and without any ads. Telegram allows you to create bots that you can interact with.

Bots are third-party applications that run inside Telegram. Users can interact with bots by sending them messages, commands and inline requests. You control your bots using HTTPS requests to Telegram Bot API“.

The ESP32/ESP8266 will interact with the Telegram bot to receive and handle the messages, and send responses. In this tutorial you’ll learn how to use Telegram to send messages to your bot to control the ESP outputs from anywhere (you just need Telegram and access to the internet).

Creating a Telegram Bot

Go to Google Play or App Store, download and install Telegram.

Install and Download Telegram

Open Telegram and follow the next steps to create a Telegram Bot. First, search for “botfather” and click the BotFather as shown below. Or open this link t.me/botfather in your smartphone.

botfather

The following window should open and you’ll be prompted to click the start button.

Telegram Start BotFather to Create a new Bot

Type /newbot and follow the instructions to create your bot. Give it a name and username.

Telegram BotFather Create a New Bot

If your bot is successfully created, you’ll receive a message with a link to access the bot and the bot token. Save the bot token because you’ll need it so that the ESP32/ESP8266 can interact with the bot.

Telegram BotFather Get Bot Token

Get Your Telegram User ID

Anyone that knows your bot username can interact with it. To make sure that we ignore messages that are not from our Telegram account (or any authorized users), you can get your Telegram User ID. Then, when your telegram bot receives a message, the ESP can check whether the sender ID corresponds to your User ID and handle the message or ignore it.

In your Telegram account, search for “IDBot” or open this link t.me/myidbot in your smartphone.

Telegram Get Chat ID with IDBot

Start a conversation with that bot and type /getid. You will get a reply back with your user ID. Save that user ID, because you’ll need it later in this tutorial.

Telegram Get Chat ID with IDBot getid

Preparing Arduino IDE

We’ll program the ESP32 and ESP8266 boards using Arduino IDE, so make sure you have them installed in your Arduino IDE.

Universal Telegram Bot Library

To interact with the Telegram bot, we’ll use the Universal Telegram Bot Library created by Brian Lough that provides an easy interface for the Telegram Bot API.

Follow the next steps to install the latest release of the library.

  1. Click here to download the Universal Arduino Telegram Bot library.
  2. Go to Sketch > Include Library > Add.ZIP Library...
  3. Add the library you’ve just downloaded.

And that’s it. The library is installed.

Important: don’t install the library through the Arduino Library Manager because it might install a deprecated version.

For all the details about the library, take a look at the Universal Arduino Telegram Bot Library GitHub page.

ArduinoJson Library

You also have to install the ArduinoJson library. Follow the next steps to install the library.

  1. Go to Skech > Include Library > Manage Libraries.
  2. Search for “ArduinoJson”.
  3. Install the library.

We’re using ArduinoJson library version 6.15.2.

Parts Required

For this example we’ll control the ESP on-board LEDs:

Control Outputs using Telegram – ESP32/ESP8266 Sketch

The following code allows you to control your ESP32 or ESP8266 NodeMCU GPIOs by sending messages to a Telegram Bot. To make it work for you, you need to insert your network credentials (SSID and password), the Telegram Bot Token and your Telegram User ID.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/telegram-control-esp32-esp8266-nodemcu-outputs/
  
  Project created using Brian Lough's Universal Telegram Bot Library: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
  Example based on the Universal Arduino Telegram Bot Library: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/FlashLED/FlashLED.ino
*/

#ifdef ESP32
  #include <WiFi.h>
#else
  #include <ESP8266WiFi.h>
#endif
#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 = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Initialize Telegram BOT
#define BOTtoken "XXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  // 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 "XXXXXXXXXX"

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

// Checks for new messages every 1 second.
int botRequestDelay = 1000;
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 += "/led_on to turn GPIO ON \n";
      welcome += "/led_off to turn GPIO OFF \n";
      welcome += "/state to request current GPIO state \n";
      bot.sendMessage(chat_id, welcome, "");
    }

    if (text == "/led_on") {
      bot.sendMessage(chat_id, "LED state set to ON", "");
      ledState = HIGH;
      digitalWrite(ledPin, ledState);
    }
    
    if (text == "/led_off") {
      bot.sendMessage(chat_id, "LED state set to OFF", "");
      ledState = LOW;
      digitalWrite(ledPin, ledState);
    }
    
    if (text == "/state") {
      if (digitalRead(ledPin)){
        bot.sendMessage(chat_id, "LED is ON", "");
      }
      else{
        bot.sendMessage(chat_id, "LED is OFF", "");
      }
    }
  }
}

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

  #ifdef ESP8266
    client.setInsecure();
  #endif

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, ledState);
  
  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  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();
  }
}

View raw code

The code is compatible with ESP32 and ESP8266 NodeMCU boards (it’s based on the Universal Arduino Telegram Bot library example). The code will load the right libraries accordingly to the selected board.

How the Code Works

This sections explain how the code works. Continue reading or skip to the Demonstration section.

Start by importing the required libraries.

#ifdef ESP32
  #include <WiFi.h>
#else
  #include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>

Network Credentials

Insert your network credentials in the following variables.

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

Define Output

Set the GPIO you want to control. In our case, we’ll control GPIO 2 (built-in LED) and its state is LOW by default.

const int ledPin = 2;
bool ledState = LOW;

Note: if you’re using an ESP8266, the built-in LED works with inverted logic. So, you should send a LOW signal to turn the LED on and a HIGH signal to turn it off.

Telegram Bot Token

Insert your Telegram Bot token you’ve got from Botfather on the BOTtoken variable.

#define BOTtoken "XXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  // your Bot Token (Get from Botfather)

Telegram User ID

Insert your chat ID. The one you’ve got from the IDBot.

#define CHAT_ID "XXXXXXXXXX"

Create a new WiFi client with WiFiClientSecure.

WiFiClientSecure client;

Create a bot with the token and client defined earlier.

UniversalTelegramBot bot(BOTtoken, client);

The botRequestDelay and lastTimeBotRan are used to check for new Telegram messages every x number of seconds. In this case, the code will check for new messages every second (1000 milliseconds). You can change that delay time in the botRequestDelay variable.

int botRequestDelay = 1000;
unsigned long lastTimeBotRan;

handleNewMessages()

The handleNewMessages() function handles what happens when new messages arrive.

void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

It checks the available messages:

for (int i=0; i<numNewMessages; i++) {

Get the chat ID for that particular message and store it in the chat_id variable. The chat ID allows us to identify who sent the message.

String chat_id = String(bot.messages[i].chat_id);

If the chat_id is different from your chat ID (CHAT_ID), it means that someone (that is not you) has sent a message to your bot. If that’s the case, ignore the message and wait for the next message.

if (chat_id != CHAT_ID) {
  bot.sendMessage(chat_id, "Unauthorized user", "");
  continue;
}

Otherwise, it means that the message was sent from a valid user, so we’ll save it in the text variable and check its content.

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

The from_name variable saves the name of the sender.

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

If it receives the /start message, we’ll send the valid commands to control the ESP32/ESP8266. This is useful if you happen to forget what are the commands to control your board.

if (text == "/start") {
  String welcome = "Welcome, " + from_name + ".\n";
  welcome += "Use the following commands to control your outputs.\n\n";
  welcome += "/led_on to turn GPIO ON \n";
  welcome += "/led_off to turn GPIO OFF \n";
  welcome += "/state to request current GPIO state \n";
  bot.sendMessage(chat_id, welcome, "");
}

Sending a message to the bot is very simply. You just need to use the sendMessage() method on the bot object and pass as arguments the recipient’s chat ID, the message, and the parse mode.

bool sendMessage(String chat_id, String text, String parse_mode = "")

In our particular example, we’ll send the message to the ID stored on the chat_id variable (that corresponds to the person who’ve sent the message) and send the message saved on the welcome variable.

bot.sendMessage(chat_id, welcome, "");

If it receives the /led_on message, turn the LED on and send a message confirming we’ve received the message. Also, update the ledState variable with the new state.

if (text == "/led_on") {
  bot.sendMessage(chat_id, "LED state set to ON", "");
  ledState = HIGH;
  digitalWrite(ledPin, ledState);
}

Do something similar for the /led_off message.

if (text == "/led_off") {
  bot.sendMessage(chat_id, "LED state set to OFF", "");
  ledState = LOW;
  digitalWrite(ledPin, ledState);
}

Note: if you’re using an ESP8266, the built-in LED works with inverted logic. So, you should send a LOW signal to turn the LED on and a HIGH signal to turn it off.

Finally, if the received message is /state, check the current GPIO state and send a message accordingly.

if (text == "/state") {
  if (digitalRead(ledPin)){
    bot.sendMessage(chat_id, "LED is ON", "");
  }
  else{
    bot.sendMessage(chat_id, "LED is OFF", "");
  }
}

setup()

In the setup(), initialize the Serial Monitor.

Serial.begin(115200);

If you’re using the ESP8266, you need to use the following line:

#ifdef ESP8266
  client.setInsecure();
#endif

In the library examples for the ESP8266 they say: “This is the simplest way of getting this working. If you are passing sensitive information, or controlling something important, please either use certStore or at least client.setFingerPrint“.

Set the LED as an output and set it to LOW when the ESP first starts:

pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);

Init Wi-Fi

Initialize Wi-Fi and connect the ESP to your local network with the SSID and password defined earlier.

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Connecting to WiFi..");
}

loop()

In the loop(), check for new messages every second.

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();
  }
}

When a new message arrives, call the handleNewMessages function.

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

That’s pretty much how the code works.

Demonstration

Upload the code to your ESP32 or ESP8266 board. Don’t forget to go to Tools > Board and select the board you’re using. Go to Tools > Port and select the COM port your board is connected to.

After uploading the code, press the ESP32/ESP8266 on-board EN/RST button so that it starts running the code. Then, you can open the Serial Monitor to check what’s happening in the background.

Go to your Telegram account and open a conversation with your bot. Send the following commands and see the bot responding:

  • /start shows the welcome message with the valid commands.
  • /led_on turns the LED on.
  • /led_off turns the LED off.
  • /state requests the current LED state.
Control ESP32 ESP8266 Outputs Telegram

The on-board LED should turn on and turn off accordingly (the ESP8266 on-board LED works in reverse, it’s off when you send /led_on and on when you send /led_off).

ESP32 board Built in LED turned on HIGH

At the same time, on the Serial Monitor you should see that the ESP is receiving the messages.

Control ESP32 ESP8266 Outputs Telegram Serial Monitor Demonstration

If you try to interact with your bot from another account, you’ll get the the “Unauthorized user” message.

Control ESP32 ESP8266 Outputs Telegram Unauthorized user

Wrapping Up

In this tutorial you’ve learned how to create a Telegram Bot to interact with the ESP32 or ESP8266. With this bot, you can use your Telegram account to send messages to the ESP and control its outputs. The ESP can also interact with the bot to send responses.

We’ve shown you a simple example on how to control an output. The idea is to modify the project to add more commands to execute other tasks. For example, you can request sensor readings or send a message when motion is detected.

The great thing about using Telegram to control your ESP boards, is that as long as you have an internet connection (and your boards too), you can control and monitor them from anywhere in the world.

We hope you’ve found this project interesting. Learn more about the ESP32 and ESP8266 with our resources:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

54 thoughts on “Telegram: Control ESP32/ESP8266 Outputs (Arduino IDE)”

  1. Hi Sara and Rui,

    do you happen to know if the same functionality exists for the messenger Signal?
    I prefer Signal over Telegram.

    Reply
    • We haven’t looked into any libraries or APIs for Signals, but if it offers a similar API you might also be able to do it with that app.

      Reply
      • There are somethings already for Signal. However I don’t know how flexible they are as Telegram is..

        community.signalusers.org/t/signal-bot-framework/6741/5

        Reply
  2. Hi, Sara.

    Congratulations for another amazing project. If I connect a PIR sensor or another sensor, I will be able get the state of that input? It´s possible?

    Reply
    • Telegram is a messaging app that has an API that allows you to interact with your ESP (but it’s all done using messages, you don’t add buttons, sliders, color pickers, etc like you can do with Blynk)

      Reply
  3. Hi, excellent tutorial as usual, thank you.
    In all your tutorials I’ve seen, my network credentials have to be programmed in !
    Would it be an easy mod to replace this with Auto Connect please ?
    Many thanks in advance
    Terry

    Reply
  4. It has a notice “Important: don’t install the library through the Arduino Library Manager because it might install a deprecated version.” but when you go to Github it outlines using the Arduino library manager? Which process is to be used?

    Reply
    • Just ensure that you are installing the latest version and it should be fine (it wasn’t allowing us to install the latest version in Arduino IDE using the libraries manager).

      Reply
  5. Receiving a photo from Esp32cam board via Telegram upon request would be a great project, I have never been able to get it to work but I am sure a great number of people would be interested.

    Thanks

    Reply
  6. Hello, a very good idea. I just scanned the instructions. I should enter my WiFi access (SSID / password) in plain text. What happens to it? Is the password encrypted and stored securely? Or do you recommend setting up a separate WiFi network for the test? Thanks in advance
    ja49

    Reply
    • The ESP stores the password in its firmware, someone would need physical access to your device in order to get it and having quite a bit of knowledge to retrieve the firmware and decode it.

      Reply
  7. Hi Sara and Rui,
    thank you for your tutorial
    I use nodemcu
    I faced to this error:
    ‘class axTLS::WiFiClientSecure’ has no member named ‘setInsecure’
    please help me

    Reply
  8. Hi there, I’ve got this project up and running, excellent tutorial. Thanks.
    I couldn’t get the program to compile with ArduinoJson 6.15.2 so I reverted to v6.11.0 and all was good.

    Reply
  9. Small problem. I did everything as described in step / step. However, I don’t get a response from Telegram in the serial monitor as you show. I also don’t get an error. So I don’t know now what would be wrong. Any idea ?

    Reply
    • Did you get the exact user ID and Bot tokens? Do you have the correct SSID and password in your code? did you select the right baud rate in your Arduino IDE serial monitor (115200)?

      Reply
      • I found that the ESP32 I was using was not good. He came up with the IP address but then stopped. now everything goes as it should with an esp8266 wemos D1.
        Thanks for your comment.
        Greetings Bert

        Reply
  10. I did everything according to your example. it looks like i am not connected to Telegram. I assume ID and token are good because there is no error message. In the Serial monitor I only see the IP address, no further info as you show it in the demo.
    What can I do ?

    Reply
    • Hi Bart, Nothing appears in the serial monitor until you send a message in telegram, i.e. /state. Once you do that then you’ll see the result in the monitor as below

      Before.
      entry 0x400806b8
      Connecting to WiFi..
      192.168.1.112

      After
      entry 0x400806b8
      Connecting to WiFi..
      192.168.1.112
      got response
      handleNewMessages
      1
      /state
      I trust that this helps. Ian

      Reply
  11. I had trouble getting my Telegram User ID following your tutorial.
    Finally I was able to find it by typing ‘@my_id_bot’ in the message box of my new bot which then brought up my user ID.
    I hope this helps
    Ian

    Reply
  12. Good day I happen to have an error. I am using ESP8266, it states “Class, classwifi has no class mode”

    I updated my esp8266 community libraries then I loaded, the second time I tried loading the code the same error came back.

    Is there any way of solving this issue?

    Thanks

    Reply
  13. Hi Sara and Rui,
    If your ESP is connected to the internet through your home network, I am wondering: does the command “client.setInsecure()“ make your home network insecure or vulnerable for attacks?
    Thanks a lot,
    Steven

    Reply
  14. Hi Rui and Sara, I’m using NodeMCU,
    I did everything according to your example. it looks like i am not connected to Telegram. I assume ID and token are good because there is no error message. In the Serial monitor I only see the IP address, no further info as you show it in the demo.
    What can I do ? please help me to find out solution.

    Reply
  15. For a better (safer) approach to client.setinsecure for https requests, see this hackaday post:

    hackaday.com/2020/07/02/easy-secure-https-with-an-esp8266/

    Reply
  16. Hi Ruis,
    this is a good example how to control IoT over a smartfone by using text messages.
    Is it possible to get pictures from an ESP cam too?
    Best regards
    Tom

    Reply
  17. Hi Rui and Sara,
    Excellent tutorial, worked on the first try with bot ESP32 and ESP8266!
    Is it possible to add more users ID’s in the sketch, for example if i want to give another user access to my data (such as temp, humidity, etc..(future project))
    Regards,
    Leon

    Reply
  18. Hello Rui And Sara. i am a big fan of your work. you are just like teacher for me. i have learned a lot from you. thank you for your efforts.
    I was trying to implement it but i don’t know whats the reason i wasn’t able to connect with telegram. can you please tell me the possible reason for it.
    i didn’t get any error but serial says connected to telegram failed.

    Reply
    • Hi.
      Double-check your botToken.
      It is a very long string. So, you may have a small error somewhere in the string.
      Regards,
      Sara

      Reply
  19. hi. Sara, i follow your excellent work. As for this one. I keep having this message when i compile, it gives the same either if it a 32 or a 8266. Have you had this case.

    exit status 1
    Error compilando para la tarjeta WeMos D1 R1.

    Reply
      • Ok, I kept working on this and finally solved it. I found that the problem has to do specifically with the use of a Telegram Library (I tried several) and a combination between the Arduinojson Library Version and the Arduino Ide Version.
        After lot of trying, I found this:
        Arduino Ide Arduinojson Esp8266 Esp32
        1.8.3 5.13.5 ok no ok
        1.8.13 5.13.5 ok ok

        Reply
  20. Thanks Rui and sara , I tried your code for esp 8266 to control single output ie led and it is working good, I am going to implement 4 outputs with relays to control my drip irrigation electro valves with little modification in the code.
    Thanks once again for sharing your knowledge.

    S.Yogaraja.

    Reply
  21. hi,thanks alot
    I install latest version and upload successfully.
    now my board is connected to wifi and show the IP in serial monitor.
    but I cannot control LED from telegram
    there is no response.

    thank you

    Reply
    • Hi.
      When you say you cannot control the LED, what exaclty happens?
      Double-check your bot token. You may have a typo in that long string.
      Regards,
      Sara

      Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.