In this project, you’re going to monitor the status of a door using an ESP32 board and a magnetic reed switch. You’ll receive a message in your Telegram account whenever the door changes state: opened or closed. As long as you have access to the internet on your smartphone, you’ll be notified no matter where you are. The ESP32 board will be programmed using Arduino IDE.
We have a similar tutorial that sends emails instead of Telegram messages:
Read the ESP8266 Guide: Door Status Monitor with Telegram Notifications
Project Overview
In this project, we’ll create a Telegram Bot that will send messages to your Telegram account whenever a door changes state. To detect the change, we’ll use a magnetic contact switch.
A magnetic contact switch is basically a reed switch encased in a plastic shell so that you can easily apply it to a door, a window, or a drawer to detect if it is open or closed.
The electrical circuit is closed when a magnet is near the switch—door closed. When the magnet is far away from the switch—door open—the circuit is open. See the figure below.
We can connect the reed switch to an ESP32 GPIO to detect changes in its state.
Introducing Telegram
Telegram Messenger is a cloud-based instant messaging and voice over IP service. You can easily install it on 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 send messages to your Telegram account. Whenever the door changes state, you’ll receive a notification on your smartphone (as long as you have 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. Or open this link t.me/botfather on your smartphone.
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. Mine is called Door Sensor, and the username is ESPDoorSensorBot.
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.
Sending a Message to the Bot
This step is very important. Don’t miss it. Otherwise, the project will not work.
You must send a message to your Telegram Bot from your Telegram account before it can send you messages.
1) Go back to the chats tab, and in the search field, type the username of your bot.
2) Select your bot to start a conversation.
3) Click on the Start link.
And that’s it! You can proceed to the next section.
Get Your Telegram User ID
To send a message to your Telegram account, the bot needs to know your user ID.
In your Telegram account, search for “myidbot” or open this link t.me/myidbot on your smartphone.
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.
Preparing Arduino IDE
We’ll program the ESP32 board using Arduino IDE, so make sure you have it 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.
- Click here to download the Universal Arduino Telegram Bot library.
- Go to Sketch > Include Library > Add.ZIP Library...
- Add the library you’ve just downloaded.
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.
- Go to Skech > Include Library > Manage Libraries.
- Search for “ArduinoJson”.
- Install the library.
We’re using ArduinoJson library version 6.5.12.
Parts Required
Here’s the hardware that you need to complete this project:
- ESP32 – read Best ESP32 Development Boards
- 1× Magnetic Reed Switch
- 1× 10kΩ resistor
- 1× breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic – ESP32 with Reed Switch
We wired the reed switch to GPIO 4, but you can connect it to any suitable GPIO.
Code
Copy the sketch below to your Arduino IDE. Replace the SSID, password, BOT token, and user ID with your credentials.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-door-status-telegram/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
// Set GPIOs for LED and reedswitch
const int reedSwitch = 4;
const int led = 2; //optional
// Detects whenever the door changed state
bool changeState = false;
// Holds reedswitch state (1=opened, 0=close)
bool state;
String doorState;
// Auxiliary variables (it will only detect changes that are 1500 milliseconds apart)
unsigned long previousMillis = 0;
const long interval = 1500;
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);
// Runs whenever the reedswitch changes state
ICACHE_RAM_ATTR void changeDoorStatus() {
Serial.println("State changed");
changeState = true;
}
void setup() {
// Serial port for debugging purposes
Serial.begin(115200);
// Read the current door state
pinMode(reedSwitch, INPUT_PULLUP);
state = digitalRead(reedSwitch);
// Set LED state to match door state
pinMode(led, OUTPUT);
digitalWrite(led, !state);
// Set the reedswitch pin as interrupt, assign interrupt function and set CHANGE mode
attachInterrupt(digitalPinToInterrupt(reedSwitch), changeDoorStatus, CHANGE);
// Connect to Wi-Fi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
bot.sendMessage(CHAT_ID, "Bot started up", "");
}
void loop() {
if (changeState){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// If a state has occured, invert the current door state
state = !state;
if(state) {
doorState = "closed";
}
else{
doorState = "open";
}
digitalWrite(led, !state);
changeState = false;
Serial.println(state);
Serial.println(doorState);
//Send notification
bot.sendMessage(CHAT_ID, "The door is " + doorState, "");
}
}
}
How the Code Works
Continue reading to learn how the code works, or proceed to the Demonstration section.
First, include the required libraries.
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
Set the GPIOs for the reed switch and LED (the on-board LED is GPIO 2). We’ll light up the on-board LED when the door is open.
const int reedSwitch = 4;
const int led = 2; //optional
The changeState boolean variable indicates whether the door has changed state.
bool changeState = false;
The state variable will hold the reed switch state, and the doorState, as the name suggests, will hold the door state—closed or opened.
bool state;
String doorState;
The following timer variables allow us to debounce the switch. Only changes that have occurred with at least 1500 milliseconds between them will be considered.
unsigned long previousMillis = 0;
const long interval = 1500;
Insert your SSID and password in the following variables so that the ESP32 can connect to the internet.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Insert your Telegram Bot Token—the one you’ve gotten in this step.
#define BOTtoken "XXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Insert your chat ID—the one you’ve gotten in this step.
#define CHAT_ID "XXXXXXXXXX"
Create a new Wi-Fi client with WiFiClientSecure.
WiFiClientSecure client;
Create a bot with the token and client defined earlier.
UniversalTelegramBot bot(BOTtoken, client);
The changeDoorStatus() function will run whenever a change is detected on the door state. This function simply changes the changeState variable to true. Then, in the loop(), we’ll handle what happens when the state changes (invert the previous door state and send a message to your Telegram account).
ICACHE_RAM_ATTR void changeDoorStatus() {
Serial.println("State changed");
changeState = true;
}
setup()
In the setup(), initialize the Serial Monitor for debugging purposes:
Serial.begin(115200);
Set the reed switch as an INPUT. And save the current state when the ESP32 first starts.
pinMode(reedSwitch, INPUT_PULLUP);
state = digitalRead(reedSwitch);
Set the LED as an OUTPUT and set its state to match the reed switch state (circuit closed and LED off; circuit opened and LED on).
pinMode(led, OUTPUT);
digitalWrite(led, !state);
Setting an interrupt
Set the reed switch as an interrupt.
attachInterrupt(digitalPinToInterrupt(reedSwitch), changeDoorStatus, CHANGE);
To set an interrupt in the Arduino IDE, you use the attachInterrupt() function, which accepts as arguments: the GPIO interrupt pin, the name of the function to be executed, and mode.
The first argument is a GPIO interrupt. You should use digitalPinToInterrupt(GPIO) to set the actual GPIO as an interrupt pin.
The second argument of the attachInterrupt() function is the name of the function that will be called every time the interrupt is triggered – the interrupt service routine (ISR). In this case, it is the changeDoorStatus function.
The ISR function should be as simple as possible, so the processor gets back to the execution of the main program quickly.
The third argument is the mode. We set it to CHANGE to trigger the interrupt whenever the pin changes value – for example, from HIGH to LOW and LOW to HIGH.
To learn more about interrupts with the ESP32, read the following tutorial:
Initialize Wi-Fi
The following lines connect the ESP32 to Wi-Fi and add a root certificate for api.telegram.org.
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Send a message to your Telegram account informing you that the bot started.
bot.sendMessage(CHAT_ID, "Bot started up", "");
loop()
In the loop(), we’ll read the changeState variable, and if a change has occurred, we’ll send a message to your Telegram account.
First, check if a change occurred:
if (changeState){
Then, check if at least 1500 milliseconds have passed since the last state change.
if(currentMillis - previousMillis >= interval) {
If that’s true, reset the timer and invert the current switch state:
state = !state;
If the reed switch state is 1(true), the door is closed. So, we change the doorState variable to closed.
if(state) {
doorState = "closed";
}
If it’s 0(false), the door is opened.
else{
doorState = "open";
}
Set the LED state accordingly and print the door state in the Serial Monitor.
digitalWrite(led, !state);
changeState = false;
Serial.println(state);
Serial.println(doorState);
Finally, the following line sends a notification to your Telegram account with the current door state.
bot.sendMessage(CHAT_ID, "The door is " + doorState, "");
Demonstration
After modifying the sketch to include your network credentials, bot token, and user ID, upload it to your ESP32. Go to Tools > Board and select your ESP32 board. Then, go to Tools > Port and select the COM port the ESP32 is connected to.
Open the Serial Monitor at a baud rate of 115200 to check if the changes are detected.
For prototyping/testing, you can apply the magnetic reed switch to your door using Velcro.
Now when someone opens/closes your door, you receive a message in your Telegram account.
Wrapping Up
In this tutorial, you’ve learned how to send notifications to your Telegram account when the reed switch changes state. This can be useful to detect if a door, window, or drawer was opened or closed.
We have similar tutorials that you may like:
- ESP32 Door Status Monitor with Email Notifications (IFTTT)
- Telegram: ESP32 Motion Detection with Notifications (Arduino IDE)
If you want to learn more about the ESP32, check our courses:
- Learn ESP32 with Arduino IDE (eBook + video course)
- Build Web Servers with ESP32 and ESP8266 eBook (2nd Edition)
- More ESP32 Projects and Tutorials …
Thanks for reading.
Hi,
time ago you published a project to send a photo, triggered by a proximity sensor, a PIR, via telegram: i think you can update that using a reed switch insted of the PIR.
regards
Hi.
Yes, that is a good idea for surveillance too.
This is the project you were referring to: https://randomnerdtutorials.com/esp32-cam-shield-pcb-telegram/
Regards,
Sara
yes,
you only have to change the PIR sensor with a reed relay: this way you can monitor if anyone enter in a space (room etc) without worring about persons or pets already here and walking around the PIR
regards
Buenas tardes Sara
Muy bueno el proyecto. Como hago para agregar mas de un sensor en el codigo??.
Saludos
It seems that the code is not reading the state of the switch in the loop.
Also, it’s not a good idea to put a print statement in the ISR. Just move it to the loop.
I have this working through Telegram but I’ve never used Telegram before.
I am developing a temp sensor device that needs to send alarm messages when the temp is above a threshold. Can the bot send a message to more people than just me?
Hi.
In this example, the switch is set as an interrupt.
Yes, it can.
You just need to add the user IDs that will receive the message.
Additionally, before a user can receive a message from the bot, it must send a message to the bot first. Then, everything is fine.
Alternatively, you can also create a group with several users that will receive the message. See this example: https://randomnerdtutorials.com/telegram-group-esp32-esp8266/
I hope this helps.
Regards,
Sara
Sara, Thanks for the reply. I discovered your group tutorial after I wrote my original message.
I understand that the switch fires an interrupt but ISR only returns the state changed flag but not the state of the switch so the code depends on keeping the state value synchronized since reading the switch once at startup. It might be better to read the switch state on each interrupt to ensure it will always correspond to the actual state of the IO pin. I modified the my test version of the code to do that.
Hi,can you please indicate the code change?
Thank You Ivan
Ivan,
I would be glad to but I don’t see a way to attach files to replies.
PhilG
Philip,thank you for your response.It would carry:Code CTRL-C and CTRL-V to mail to me.
Can you make the home automation project using esp rainmaker Arduino library .and please address the wifi cred reset issue .
Very interesting project, i will try it. Thank you Sara and Rui.
I’d love to something like…
https://randomnerdtutorials.com/esp32-door-status-telegram/ +
https://randomnerdtutorials.com/esp-mesh-esp32-esp8266-painlessmesh/
So then one could have Door sensors with Mesh + TelegramBot = Super 🙂
Hi.
That’s a great idea!
I’ll add that to my list of future tutorials.
Regards,
Sara
Hi,
It is a nice project to learn interrupt.
Thanks,
Pian
You can add a Delay before it kicks in, to give you time to leave the house.
I would connect it to a UPS anyway, in case the thief cuts off the power.
And connect also router to UPS…
Hello,
I follow your instructions, but i always get stuck somewhere. Arduino IDE reports to me the following error:
‘class BearSSL::WiFiClientSecure’ has no member named ‘setCACert’.
There’s no way I’m going to get through this error. I admit, I’m an electronics, I’m not a programmer, but I find the project interesting.
(Before that I had to change the first line to “#include <ESP8266WiFi.h>”)
Thanks in advance
Hi.
This example is not compatible with the ESP8266 board.
To use ESP8266, use this example instead: https://randomnerdtutorials.com/esp8266-nodemcu-door-status-telegram/
Regards,
Sara
Hi,
Thanks, I forgot to mention that I use ESP12F DEVKIT V3.
Regards
Hello,
Telegram isn´t available anymore. I wasn´t able to install it on my Android-Handy. Do you have an alternative?
Thanks
Thomas
Hi.
What do you mean “isn’t available anymore”?
Alternatively, use this tutorial: https://randomnerdtutorials.com/esp32-door-status-monitor-email/
Regards,
Sara
Can you somehow implement this project to work in deep sleep in conjunction with a battery pack?
Hi.
You can check the following example. It uses deep sleep and is powered by a battery.:
https://randomnerdtutorials.com/esp8266-wi-fi-button-diy-amazon-dash-button-clone/
Regards,
Sara
I am using NodemMCU ESP WROOM 32D
In file included from C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\Universal-Arduino-Telegram-Bot-master\src/UniversalTelegramBot.h:31:0,
from C:\Users\Pankaj\Desktop\gastatussketch\gastatussketch.ino:15:
C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\Universal-Arduino-Telegram-Bot-master\src/TelegramCertificate.h:9:38: error: redefinition of ‘const char TELEGRAM_CERTIFICATE_ROOT []’
const char TELEGRAM_CERTIFICATE_ROOT[] = R”=EOF=(
^
In file included from C:\Users\Pankaj\Desktop\gastatussketch\gastatussketch.ino:14:0:
C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\Universal-Arduino-Telegram-Bot-master\src/TelegramCertificate.h:9:12: note: ‘const char TELEGRAM_CERTIFICATE_ROOT [1369]’ previously defined here
const char TELEGRAM_CERTIFICATE_ROOT[] = R”=EOF=(
^
Multiple libraries were found for “ArduinoJson.h”
Used: C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\ArduinoJson
Not used: C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\ArduinoJson-6.x
Multiple libraries were found for “WiFi.h”
Used: C:\Users\Pankaj\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\libraries\WiFi
Not used: C:\Program Files (x86)\Arduino\libraries\WiFi
Using library WiFi at version 1.0 in folder: C:\Users\Pankaj\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\libraries\WiFi
Using library WiFiClientSecure at version 1.0 in folder: C:\Users\Pankaj\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\libraries\WiFiClientSecure
Using library Universal-Arduino-Telegram-Bot-master at version 1.3.0 in folder: C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\Universal-Arduino-Telegram-Bot-master
Using library ArduinoJson at version 6.18.5 in folder: C:\Users\Pankaj\OneDrive\Documents\Arduino\libraries\ArduinoJson
exit status 1
Error compiling for board ESP32 Dev Module.
hola tienen un mejor diagrama para las conexiones?…
Hi Rui,
Thank you very much for this beautiful work.
My ESP wroom 32 card works correctly when powered from USB, but wifi does not connect when Vin 5V is external supplied. Do you have a suggestion?
Hi Ugur
Did you manage to solve your problem? I am struggling with the same thing.
Hi Casper
Do not supply directly with 5 volts. Instead, supply it with 7-8 volts, experimenting with a voltage regulator.
Hello Sara,
I am a newbie and have enjoyed the explanation about this project.
It works perfectly, only I had to adjust the reed relay with a model with position magnets.
I had too many rebonces with a normal reed relay, otherwise no problems and everything works as described in your tutorial.
A question….
Can I bring several contacts with different bots together in one sketch, or do I have to use a different ESP32 for each contact, and how do I do this? bearing in mind that I am a novice.
Thanks in advance.
Hi.
You can add more contacts as long as you connect each one to a different GPIO.
Then, you need to check which switch was triggered and run your code accordingly.
It is similar to detecting pushbutton presses. So, you can search for sketches with multiple pushbuttons and try to adapt accordingly.
Regards,
Sara
Very well. I love your projects and I’m learning a lot from them. Now I was wanting to insert maid two reed switch, I made a mistake in the code and I’m not getting it. I want to insert 2 more reed switches and I can’t.
Hi.
Please provide more details about your issue.
Regards,
Sara
I would like to add 2 more windows and 2 doors to this project and also receive telegram notices of these 2 windows and 2 doors. In total, the monitoring would have 3 doors and two windows. It sounds simple but I can’t think of where to start, especially in the code.
Hi! how does the wiring of the reed switch works? “We wired the reed switch to GPIO 4, but you can connect it to any suitable GPIO”
does one end of the reed swtich go to GPIO 4 and the other end connected with the GND wire?
Guys, I’m trying to put a 1 minute team, for example, to send a message on telegram, when the door is open, can someone give a tip, I’m new to ESP32.
Hello,
I compiled the sketch with Arduino IDE and everything works. If I compile it with VScode, I have no errors, but when it runs on esp32 when changing state on GPIO4, esp32 crash and restart.
I prefer VScode to Arduino IDE.
Best regards
Hi,
first of all Awesome projects, I love your web
Could you tell me why there is a pull up resistor if you activate the internal pull up resistor with the pinmode instruction?
Is that needed?
Hi
I want to ask if I want to add 2 LED, how do I write the coding because I do not know where to put the coding. I hope somebody can help me. Thanks.
Hi, is it possible that I get it in python language? Thx
hi, i would like to have a project, that when i press a button, it sends a notification on telegram, visible to many people.
How can I get this code?
Thank you
I get this error when I am trying to compiling it:
exec: “python”: executable file not found in $PATH
Compilation error: exec: “python”: executable file not found in $PATH
I had the same before and came across the following on a site…
Arduino and other compilations now use the Python3 while Arduino and the likes use Python2
Go to the Synaptic package manager and install ” python3-lib2to3 ”
This package contains the lib2to3 library , a Python2 to Python3 converter
This resolved the issue.
Regards
Bart Crimson
Buenas tardes
Me gustaria que me asesoren o me indiquen. Quisiera hacer el circuito similar a este, pero de sensor magnetico por sensor de luz por la cantidad de 5 (sensores), que me envie un mensaje a telegram, con un mensaje distinto por cada sensor
Desde ya Muchas Gracias
I like this project very much and it initially started well with no problems, however now I receive mainly “Bot started up” notifications and the occasional status. It seems very random.
Any suggestions as to why I should be receiving so many “Bot started up” messages but few actual status?
I have a LiFe PO4 3.2V battery I want to connect to the set up and use as a garage door open/close monitor via Telegram.
As there is only one 3.3v on the ESP32, do I need to splice into the pin connector wire along with the positive of the reed switch (I don’t want to use a breadboard).
Your advice would be appreciated.
Thanks
Boa tarde a todos, estou com uma duvida que está me matando de raiva, já pesquisei já tentei de todas as formas fazer com que quando eu enviar uma mensagem para o Telegram ele pule uma linha, que haja um espaço entre as mensagens para melhor organização, um exemplo:
bot.sendMessage(CHAT_ID,”None_None_None_None_None.”, “”);
bot.sendMessage(CHAT_ID,”None_None_None_None_None_None_None.”, “”);
Onde eu colocaria tipo um \n para que pulasse uma linha entre as mensagens, coloque \ alfabeto inteiro e não pula de linha. alguém filho de DEUS pode ajudar? OBRIGADO !!!
I was wondering why you add an external 10K pulldown resistor. Your code uses an internal pullup resistor on that GPIO with:
pinMode(reedSwitch, INPUT_PULLUP);
and triggering the switch brings the GPIO high. The pulldown and pullup resistors are fighting each other. If you omit the external resistor and reverse the logic (1->0 instead of 0->1) I would think you could do the same thing with less wiring?
A bit of research about the ICACHE_RAM_ATTR attribute, since I was not familiar with it. The research suggested should be used with ESP8266 devices. However, it also suggested that when using an ESP32, the IRAM_ATTR attribute should be used instead. Do you agree with this recommendation? Just curious to know a bit more for future applications.