Using Telegram with ESP8266 or ESP32

Telegram is a ‘Whatsapp’ like app for mobile phones to exchange messages.
An advantage over Whatsapp or Viber is that it also allows you to communicate with your (micro)computer.
That means your phone can receive messages sent from your ESP8266 or ESP32, but also that your phone can be used to control your ESP8266 or ESP32.

In order to do so you need to have the telegram app installed, create your own bot to handle the traffic, get an API_key and the chat_id for your bot

Install Telegram
Visit Telegram official website and download the official application for your smartphone, or get it from the playstore

Create your Bot
Create your bot by using a bot called “BotFather”. To do this, add BotFather to your contacts or visit telegram.me/botfather and follow the instructions to create your own bot.

Get your API
When your bot is created, BotFather gives you the HTTP API token which follows a pattern like 123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz. You need this token to send messages.

Get your chat_id
You will need this ID to send messages, you do not need it to receive messages. Getting this ID is not straightforward and most of the methods i have seen on the internet do not work (anymore).
The only ones I found working is to the IDBot (and follow the instructions). and the get_id_bot. The latter can be a bit slow though. (I will mention a 3rd option further down)

Getting your chat ID with IDBot
Getting your chat ID with get_id bot

The id is an integer and it follows a pattern like 123456789

Now it is time to test your bot.
You can do that with cURL

curl --data chat_id="892915001" --data "text=Hello World" "https://api.telegram.org/bot977142506:AAGYWypUbMN8BCthML-tFM25M403r2yCsFj/sendMessage

from your commandline prompt

or with a GET URL in a browser like this:

https://api.telegram.org/bot977142506:AAGYWypUbMN8BCthML-tFM25M403r2yCsFj/sendMessage?chat_id=892915001&text=Hello-World

There is an other element that can be added at the end and that is &parse_mode=, but for normal operations we can leave that out or make it “&parse_mode=HTML”.  A bit more on this further down

Using GET
So now we have our communication with Telegram working, we can go do something useful with it.
The fact that the API can be reached with a GET message opens up possibilities for an ESP8266, ESP32, Raspberry Pi or other controller that is connected to internet.

You would do that with

botclient.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");

in which

const char* host = "api.telegram.org"

and the
String url is the sum of the strings and variables you want to send

In your declaration section you would be stating:

WiFiClientSecure botclient;

The reason I am not putting a complete and ready “Telegram via GET” program here is because there is actually a pretty decent library program available, so if you insist on using your own GET statements rather than a library, I presume you do that to make very lean code in which case I presume you are versed enough in coding to build your own routine with the help of the above info.
If you use a GET URL to connect your ESP to Telegram and you are sure your code is correct, you may have a secure connection problem. Read On

Using a library
There are several libraries for Telegram available and you probably already find them in your library manager. The “UniversalTelegramBot” is a pretty decent one and the examples should get you up and running fast, even if from first glance it is not always clear what they do 🙂 .
So, install the library via library manager and lets have a look at the “PhotoFromURL”example.

When you fill in your WiFi credentials and Telegram API, you may wonder “where the heck goes my chat_id”.
Well, remember earlier I said you only needed the chat_id when you wanted to send something from yr micro to your phone? Well, that’s the case right here.
“Yes, but this program IS supposed to send me something and I clearly see a variable called chat_id, so where do I put mine” I hear you say.
Well this program will send you a picture ONLY when you tell it to do that and then the program will just read your chat_id from the incoming message and use that. This is also the 3rd method of finding your client ID

So here is  what you do to use that example: After you upload it to your ESP8266, go to your Telegram app on your phone. select the bot you just created to send a message to and message /start.

After a few moments the bot responds with an overview of the commands you can give (only one in this case). Tap on that command to execute it.

It is not working
If nothing happens, it is time to open the serial monitor.
You should see the IP number being printed. Make sure you type the correct command in your Telegram app and make sure you are sending it to the proper bot.

If you don’t see the ‘got response’ message appearing and you are sure you have inserted the right API, then apparently something else is keeping the program from opening a socket to the bot.

Could it be that you are still using the 2.5.0 ESP8266 core? There are plenty good reasons to use that core, but apparently it has a problem with secure connections. But not all is lost. Here is what you do:

Go to setup() and add

client.setInsecure();

and then compile and upload the file again.

Beware! In this example the WiFiSecure() client IS called client. That maybe different in other examples (in the Bulkmessages example it is called ‘secured_client’. Change your setInsecure statement accordingly.

Controlling your ESP8266/ESP32 via Telegram
It is possible to control your ESP via your Telegram App. In fact, that is what the previous example was already doing: we  instructed it to send a photo.

The FlashLed example shows very clear how to control your ESP. If for testing you want to use the inbuild led from the Wemos, the ledPin should be ‘2’, the ledon routine should make the pin LOW and the ledoff routine should make the pin HIGH.

You could combine functions like so:

/*******************************************************************
 *  How to use basic functiond of a Telegrambot
 *  A completely changed example based on a sketch from  
 *      Vadim Sinitski
 *******************************************************************/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Initialize Wifi connection to the router
char ssid[] = "NETGEAR1";     // your network SSID (name)
char password[] = "SECRET"; // your network key

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

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 1000; //mean time between scan messages
long Bot_lasttime;   //last time messages' scan has been done
bool Start = false;

const int ledPin = 2;
int ledStatus = 0;

String test_photo_url = "https://img.srgcdn.com/e/w:750/cjh2NWp4S0FiNWxJQVNsQ3JUU28uanBn.jpg"; // can insert any picture URL

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


  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    if (text == "/get_photo") {
      bot.sendPhoto(chat_id, test_photo_url, "Who");
    }

    //-------------
    //add more commands here
    //-------------
    
    if (text == "/ledon") {
      digitalWrite(ledPin, LOW);   // turn the LED on (HIGH is the voltage level)
      ledStatus = 1;
      bot.sendMessage(chat_id, "Led is ON", "");
    }

    if (text == "/ledoff") {
      ledStatus = 0;
      digitalWrite(ledPin, HIGH);    // turn the LED off (LOW is the voltage level)
      bot.sendMessage(chat_id, "Led is OFF", "");
    }

    if (text == "/status") {
      if (ledStatus) {
        bot.sendMessage(chat_id, "Led is ON", "");
      } else {
        bot.sendMessage(chat_id, "Led is OFF", "");
      }
    }
    

    if (text == "/start") {
      String welcome = "Welcome to Telegram Bot, " + from_name + ".\n";
      welcome += "This will show several properies.\n\n";
      welcome += "/get_photo : getting photo\n";
      welcome += "/ledon : to switch the Led ON\n";
      welcome += "/ledoff : to switch the Led OFF\n";
      welcome += "/status : Returns current status of LED\n";


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

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

  // Set WiFi to station mode and disconnect from an AP if it was Previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  // attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  client.setInsecure(); // if yr core cannot handle secure connections

  pinMode(ledPin, OUTPUT); // initialize digital ledPin as an output.
  delay(10);
  digitalWrite(ledPin, HIGH); // initialize pin as off

}

void loop() {
  if (millis() > Bot_lasttime + Bot_mtbs)  {
    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);
    }

    Bot_lasttime = millis();
  }
}

Or download here.

I just want to have my ESP send notifications
Well in fact the previous examples kinda did that, but if you really just want to have notifications sent to your phone from your ESP, then the only command you will need from the library is

bot.sendMessage(chat_id, "My message", "");

Provided of course you called your library object ‘bot’. Those empty quotes at the end are there for the parse_mode (read on).
Instead of “my message” you can also insert a String variable in which you add text and variables and you can even use simple HTML coding in that string.  In that case the command needs to be:

bot.sendMessage(chat_id, messagestring, "HTML");

your messagestring could for instance be:

String messagestring="The temperature is  <b>"+String(tempreading+ "</b>Celsius";

more about the API here!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.