Chat with your room on Telegram

Make a Telegram bot that answers /status with your room's temperature, humidity and light, switches a night light on command and warns you when it gets too warm.
  • Level:Intermediate
  • Duration: 1 h
  • Ages 13+
  • Platform: ESP32

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Chat with your room on Telegram – EEMENTOR STEM™ lesson

A chat bot is a program that you talk to in a messaging app. In this lesson you create your own Telegram bot, and the ESP32 runs it. Send /status and it tells you the temperature, humidity and light in your room; send /light_on and a night light glows in its printed dome. If the room gets warmer than the limit you set with /alert 27, the bot messages you first. Because Telegram's servers pass the messages on, it works from anywhere.

What you'll learn

  • How a bot receives commands by checking for new messages
  • How to read a number that follows a command
  • How to make sure only you can control your device
  • How to send a message when something changes, not every time

What you need

  • ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
  • DHT11 temperature and humidity module (45-in-1 Sensor Kit)
  • Photoresistor module (45-in-1 Sensor Kit)
  • RGB LED module (45-in-1 Sensor Kit)
  • 3 resistors, 220 Ω (ESP32 IoT Starter Kit)
  • A phone with Telegram
  • A 2.4 GHz Wi-Fi network
  • The printed parts from the 3D printing box below (light dome and module stand), or the cardboard version described there
  • Breadboard and jumper wires (ESP32 IoT Starter Kit)

Wiring

Breadboard wiring diagram: Chat with your room on Telegram
Breadboard view. Check each connection against the wiring table below.
From To
DHT11 module S ESP32 GPIO 27
Photoresistor module S ESP32 GPIO 34
Both modules + and − 3V3 and GND
RGB module R 220 Ω resistor, then GPIO 25
RGB module G 220 Ω resistor, then GPIO 26
RGB module B 220 Ω resistor, then GPIO 33
RGB module − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

Create your Telegram bot

  1. Install Telegram on your phone and sign in. Telegram is for ages 13 and up (16 in some countries), so younger makers should ask a parent or teacher to create the bot and run it on their account.
  2. Search for @BotFather (the official bot with a blue tick), send /newbot and follow the questions. Call it something like My Room Bot; the username must end in bot.
  3. BotFather answers with a token, a long code such as 712345678:AAE…. It works like a password for your bot: put it in the sketch and never share it.
  4. Search for @userinfobot, start it and copy the number it shows as your Id. That is your chat ID. The sketch only obeys messages from this ID.
  5. Open a chat with your new bot and press Start, so it is allowed to send you messages.

The sketch

Replace YOUR_WIFI_NAME and YOUR_WIFI_PASSWORD with your own network details (2.4 GHz only).

In the Arduino IDE, open Library Manager and install UniversalTelegramBot (by Brian Lough), ArduinoJson (by Benoit Blanchon) and the DHT sensor library by Adafruit.

Put your bot token in BOT_TOKEN and your chat ID in CHAT_ID.

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

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* BOT_TOKEN = "YOUR_BOT_TOKEN";
const String CHAT_ID = "YOUR_CHAT_ID";

const int LIGHT_PIN = 34;
const int RED_PIN = 25, GREEN_PIN = 26, BLUE_PIN = 33;

WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);
DHT dht(27, DHT11);

float alertAbove = 28.0;          // change it with /alert 26
bool tooWarm = false;
unsigned long lastCheck = 0;

void colour(int r, int g, int b) {
  analogWrite(RED_PIN, r);
  analogWrite(GREEN_PIN, g);
  analogWrite(BLUE_PIN, b);
}

String status() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();
  int light = analogRead(LIGHT_PIN) * 100 / 4095;
  if (isnan(t) || isnan(h)) return "The temperature sensor didn't answer. Check its wiring.";
  return "Temperature: " + String(t, 1) + " °C\nHumidity: " + String(h, 0) + " %\nLight: " + String(light) +
         " %\nWarm alert above " + String(alertAbove, 1) + " °C";
}

void handle(int count) {
  for (int i = 0; i < count; i++) {
    String chat = bot.messages[i].chat_id;
    String text = bot.messages[i].text;
    if (chat != CHAT_ID) {                       // only the owner may give orders
      bot.sendMessage(chat, "Sorry, I only answer my owner.", "");
      continue;
    }
    if (text == "/start" || text == "/help") {
      bot.sendMessage(chat, "Commands:\n/status - temperature, humidity and light\n/light_on and /light_off - night light\n/alert 27 - warn me above 27 °C", "");
    } else if (text == "/status") {
      bot.sendMessage(chat, status(), "");
    } else if (text == "/light_on") {
      colour(255, 140, 40);
      bot.sendMessage(chat, "Night light on.", "");
    } else if (text == "/light_off") {
      colour(0, 0, 0);
      bot.sendMessage(chat, "Night light off.", "");
    } else if (text.startsWith("/alert ")) {
      float limit = text.substring(7).toFloat();
      if (limit > 0 && limit < 60) {
        alertAbove = limit;
        tooWarm = false;
        bot.sendMessage(chat, "OK, I'll warn you above " + String(alertAbove, 1) + " °C.", "");
      } else {
        bot.sendMessage(chat, "Send a temperature, for example /alert 27", "");
      }
    } else {
      bot.sendMessage(chat, "I don't know that one. Send /help.", "");
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  dht.begin();
  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT);   // check that we really talk to Telegram
  bot.sendMessage(CHAT_ID, "Hello! Your room bot is online. Send /help.", "");
}

void loop() {
  if (millis() - lastCheck > 2000) {             // look for new messages every 2 s
    lastCheck = millis();
    int count = bot.getUpdates(bot.last_message_received + 1);
    while (count) {
      handle(count);
      count = bot.getUpdates(bot.last_message_received + 1);
    }

    float t = dht.readTemperature();
    if (!isnan(t)) {
      if (!tooWarm && t > alertAbove) {
        tooWarm = true;
        bot.sendMessage(CHAT_ID, "It's getting warm: " + String(t, 1) + " °C.", "");
      } else if (tooWarm && t < alertAbove - 1.0) {
        tooWarm = false;                         // ready to warn again later
      }
    }
  }
}

Try it

  1. Upload the sketch. Your phone gets "Hello! Your room bot is online."
  2. Send /status. The answer arrives within a few seconds.
  3. Send /light_on, then /light_off.
  4. Send /alert 22 and warm the DHT11 with your fingers. When it passes 22 °C, the bot messages you.

How it works

The ESP32 can't receive messages directly from the internet: your router blocks that. So it asks instead. Every two seconds bot.getUpdates() asks Telegram's servers "anything new since the last message I saw?". This is called polling. Each message has a number, and last_message_received + 1 makes sure every message is handled exactly once.

Anyone can find your bot and write to it, so handle() first compares the sender's chat ID with yours and ignores everybody else. The warm alert uses a flag, tooWarm, so it only messages you once when the limit is crossed, and is ready again when the room has cooled by a degree. That gap is called hysteresis.

Try this next

  • Add /colour red, /colour blue and so on for the night light.
  • Send a daily summary at 20:00 with the warmest and coldest temperature of the day.
  • Use Telegram's keyboard buttons (bot.sendMessageWithReplyKeyboard()) so you can tap commands instead of typing them.

Troubleshooting

  • The bot never answers: check the token, and that you pressed Start in the chat with your bot.
  • "Sorry, I only answer my owner" to you: the CHAT_ID is wrong. Get it again from @userinfobot.
  • Answers take a long time: that is normal for polling; they arrive within a few seconds. Don't make the 2000 ms smaller than 1000, or Telegram may slow your bot down.
  • It never connects to Wi-Fi: check the network name and password (both are case-sensitive) and make sure the network is 2.4 GHz.
  • A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

ESP32 IoT Starter Kit | Arduino IDE Compatible | Free Tutorials $57.00

Shop the kit