Building and controlling a smart connected Home using Telegram and NodeMCU ESP32 .

Mohamed El Hlafi
12 min readJul 26, 2020

Today we can notice that social media is everywhere so I think it’s great to use it in our real life and not just in virtual life , in this context I would like to share with you some techniques for building and controlling a smart connected home using simple and cheaper electronic tools,and telegram application. This is a simple article , 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.let start !

Required Components :

  • ESP32 Devkit v4.0
  • BME280 sensor
  • telegram application
  • Led

Requests ESP32 NodeMCU temperature and humidity readings using the Telegram app :

As a first example, we’ll request temperature and humidity readings from a BME280 sensor ,We’ll use a BME280 sensor, but you can use any other sensor . You just need to send a message to your Telegram Bot to monitor your sensors or inputs from anywhere in the world. The ESP boards will be programmed using Arduino IDE.

Introducing Telegram App:

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 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 request sensor readings 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:

Open Telegram and follow the next steps to create a Telegram Bot. First, search for “botfather” and click the BotFather as shown below:

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

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

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 can interact with the bot.

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

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 :

Preparing Arduino IDE:

We’ll program the ESP32 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 > Manage Libraries.
  3. Add the library you’ve just downloaded.

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.

BME280 Sensor Libraries

To get readings from the BME280 sensor module, we’ll use the Adafruit_BME280 library. You also need to install the Adafruit_Sensor library. Follow the next steps to install the libraries in your Arduino IDE:

1. Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.

2. Search for “adafruit bme280 ” on the Search box and install the library.

To use the BME280 library, you also need to install the Adafruit Unified Sensor. Follow the next steps to install the library in your Arduino IDE:

3. Search for “Adafruit Unified Sensor“in the search box. Scroll all the way down to find the library and install it.

circuit diagram :

Code (C++):

#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>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// 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"

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

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

//Checks for new messages every 1 second.
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;

// BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
// BME280 connect to ESP8266 I2C (GPIO 4 = SDA, GPIO 5 = SCL)
Adafruit_BME280 bme;

// Get BME280 sensor readings and return them as a String variable
String getReadings(){
float temperature, humidity;
temperature = bme.readTemperature();
humidity = bme.readHumidity();
String message = "Temperature: " + String(temperature) + " ºC \n";
message += "Humidity: " + String (humidity) + " % \n";
return message;
}

//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 command to get current readings.\n\n";
welcome += "/readings \n";
bot.sendMessage(chat_id, welcome, "");
}

if (text == "/readings") {
String readings = getReadings();
bot.sendMessage(chat_id, readings, "");
}
}
}

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

#ifdef ESP8266
client.setInsecure();
#endif

// Init BME280 sensor
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

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

How the Code Works:

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>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.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";

Telegram User ID

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

#define CHAT_ID "XXXXXXXXXX"

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)

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;

BME280 Object

Create an Adafruit_BME280 called bme. This creates an I2C object on the default ESP I2C pins.

Adafruit_BME280 bme;

getReadings()

The getReadings() function requests temperature and humidity from the BME280 sensor and returns the results as a string variable that we can send to the Telegram bot.

String getReadings(){
float temperature, humidity;
temperature = bme.readTemperature();
humidity = bme.readHumidity();
String message = "Temperature: " + String(temperature) + " ºC \n";
message += "Humidity: " + String (humidity) + " % \n";
return message;
}

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 identifies 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 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 command to get current readings.\n\n";
welcome += "/readings \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 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 /readings message, get the current sensor readings by calling the getReadings() function. Then, simply send the message.

if (text == "/readings") {
String readings = getReadings();
bot.sendMessage(chat_id, readings, "");
}

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 Universal Telegram Bot Library library examples for the ESP8266, it says: “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“.

Init BME280

Initialize the BME280 sensor.

if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

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

Demonstration :

Upload the code to your ESP board, open the Tools menu > 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 ESP on-board EN/RST button so that it starts running the code. Then, 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.
  • /readings returns the current temperature and humidity readings from the BME280 sensor.

Control Outputs using Telegram — ESP32 :

we use the same previous steps, just there is a change on the code and the cercuit

The following code allows you to control your ESP32 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.

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

Demonstration :

Upload the code to your ESP32 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.

Conclusion :

I hope the principle was clear , now you can use it in different fields like automobile, smart connected objects … although the majority of people consider that social media has bad effect on society but it can be used in a positive way like this case .

--

--

Mohamed El Hlafi
Mohamed El Hlafi

Written by Mohamed El Hlafi

Embedded software engineer student .

No responses yet