ESP32 Door Status Monitor with Email Notifications (IFTTT)

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 an email notification whenever the door changes state: opened or closed. The email notifications will be sent using IFTTT, and the ESP32 board will be programmed using Arduino IDE.

ESP32 Door Status Monitor with Email Notifications IFTTT Arduino IDE

Instead of sending email notifications with IFTTT, you can use an SMTP server instead. To learn how to send emails with the ESP32 using an SMTP server, you can follow the next tutorial:

If you prefer, you can also send notifications to your Telegram account. Learn how to use Telegram with the ESP32 on the following tutorial:

We have a similar tutorial for the ESP8266 board: Door Status Monitor with Email Notifications (IFTTT)

Project Overview

In this project, you’ll send an email notification whenever a door changes state. To detect the change, we’ll use a magnetic contact switch. To send an email, we’ll use IFTTT.

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 the door is open or closed.

magnetic contact switch reed switch

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.

magnetic reed switch how i tworks

We can connect the reed switch to an ESP32 GPIO to detect changes in its state.

Sending Emails with IFTTT

To send emails with the ESP32, we’ll use a free* service called IFTTT, which stands for “If This Then That”.

IFTTT is a platform that gives you creative control over dozens of products and apps. You can make apps work together. For example, sending a particular request to IFTTT triggers an applet that makes something happen, like sending you an email alert.

I like IFTTT service and once you understand how it works, it is easy to use. However, I’m not too fond of the layout of their website and the fact that it is constantly changing.

* currently, you can have three active applets simultaneously in the free version.

Creating an IFTTT Account

Creating an account on IFTTT is free!

Go to the official site: https://ifttt.com/ and click the Get Started button at the top of the page or Signup if you already have an account.

IFTTT Get Started Web Page

Creating an Applet

First, you need to create an Applet in IFTTT. An Applet connects two or more apps or devices together (like the ESP32 and sending an email).

Applets are composed of triggers and actions:

  • Triggers tell an Applet to start. The ESP32 will send a request (webhooks) that will trigger the Applet.
  • Actions are the end result of an Applet run. In our case, sending an email.

Follow the next instructions to create your applet.

1) Click on this link to start creating an Applet.

2) Click on the Add button.

IFTTT Create your applet

3) Search for “Webhooks” and select it.

IFTTT Create your applet choose a service

4) Select the option “Receive a web request”.

IFTTT Create your applet webhooks receive a web request

5) Enter the event name, for example, door_status. You can call it any other name, but if you change it, you’ll also need to change it in the code provided later on.

IFTTT Create your applet receive a web request

6) Then, you need to click the Add button on the “Then that” menu to select what happens when the previous event is triggered.

IFTTT Create your applet create your own

7) Search for email and select the email option.

IFTTT Create your applet choose a service email

8) Click on Send me an email.

IFTTT Create your applet choose an action

9) Then, write the email subject and body. You can leave the default message or change it to whatever you want. The {{EventName}} is a placeholder for the event name, in this case, it’s door_status. The {{OccuredAt}} is a placeholder for the timestamp of when the event was triggered. The {{Value1}} is a placeholder for the actual door status. So, you can play with those placeholders to write your own message. When you’re done, click on Create action.

IFTTT Create your applet eventName set action fields

10) Now, you can click on Continue.

IFTTT Create your applet create your own

11) Finally, click on Finish.

IFTTT Create your applet review and finish

12) You’ll be redirected to a similar page—as shown below.

IFTTT Create your applet connected

Your Applet was successfully created. Now, let’s test it.

Testing your Applet

Go to this URL: https://ifttt.com/maker_webhooks and open the “Documentation” tab.

You’ll access a web page where you can trigger an event to test it and get access to your API key (highlighted in red). Save your API key to a safe place because you’ll need it later.

IFTTT testing your applet

Now, let’s trigger the event to test it. In the {event} placeholder, write the event you created previously. In our case, it is door_status. Additionally, add a value in the value1 field, for example open. Then, click the Test It button.

IFTTT testing your applet

You should get a success message saying “Event has been triggered” and you should get an email in your inbox informing you that the event has been triggered.

IFTTT Applet tested successfully

If you received the email, your Applet is working as expected. You can proceed to the next section. We’ll program the ESP32 to trigger your Applet when the door changes state.

Parts List

Here’s the hardware that you need to complete this project:

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.

Schematic ESP8266 NodeMCU with Reed Switch wiring circuit diagram

Code

Copy the sketch below to your Arduino IDE. Replace the SSID, password, and the IFTTT API Key with your own credentials.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-door-status-monitor-email/
  
  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>

// 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";
const char* host = "maker.ifttt.com";
const char* apiKey = "REPLACE_WITH_YOUR_IFTTT_API_KEY";

// 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.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");  
}

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 email
      Serial.print("connecting to ");
      Serial.println(host);
      WiFiClient client;
      const int httpPort = 80;
      if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
      }

      String url = "/trigger/door_status/with/key/";
      url += apiKey;

      Serial.print("Requesting URL: ");
      Serial.println(url);
      client.print(String("POST ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" + 
                     "Content-Type: application/x-www-form-urlencoded\r\n" + 
                     "Content-Length: 13\r\n\r\n" +
                     "value1=" + doorState + "\r\n");
    }  
  }
}

View raw code

You must have the ESP32 board add-on installed in your Arduino IDE. If you don’t, follow the next tutorial:

How the Code Works

Continue reading to learn how the code works, or proceed to the Demonstration section.

First, you need to include the WiFi library so that the ESP32 can connect to your network to communicate with the IFTTT services.

#include <WiFi.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 own IFTTT API key on the apiKey variable—the one you’ve gotten in this step.

const char* apiKey = "REPLACE_WITH_YOUR_IFTTT_API_KEY";

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 an email).

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 or 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.

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");  

loop()

In the loop(), we’ll read the changeState variable and if a change has occurred, we’ll send an email using IFTTT.

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 lines make a request to IFTTT with the current door status on the event (door_status) that we created previously.

// Send email
Serial.print("connecting to ");
Serial.println(host);
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
  Serial.println("connection failed");
  return;
}

String url = "/trigger/door_status/with/key/";
url += apiKey;
          
Serial.print("Requesting URL: ");
Serial.println(url);
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Content-Type: application/x-www-form-urlencoded\r\n" + 
               "Content-Length: 13\r\n\r\n" +
               "value1=" + doorState + "\r\n");

When the IFTTT receives this request, it will trigger the action to send an email.

Demonstration

After modifying the sketch to include your network credentials and API key, 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 and if the ESP32 can connect to IFTTT.

Testing ifttt with ESP32

For prototyping/testing you can apply the magnetic reed switch to your door using Velcro.

Testing ifttt with ESP8266 NodeMCU

Now when someone opens/closes your door you get notified via email.

Door Status Received Email IFTTT ESP8266 NodeMCU

Wrapping Up

In this tutorial you’ve learned how to trigger an event when the reed switch changes state. This can be useful to detect if a door, window, or drawer was opened or closed. You’ve also learned how to use IFTTT to send an email when an event is triggered.

Instead of sending an email, you may want to send a message to Telegram, for example.

If you want to learn more about the ESP32, check our courses:

Thanks for reading.



Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our newsletter!

21 thoughts on “ESP32 Door Status Monitor with Email Notifications (IFTTT)”

  1. if you want to save battery, make ESP32 go to sleep and wake up on door opening rather than have ESP32 in the continuous loop – it is at least 50mA of the current so no battery can do it for long. If you use sleep, the current will be around 1000 times less, and connecting to WiFi will take max 4 seconds – that should not be an issue

    Reply
      • all my sensors on ESP32 go to sleep and wake up just to provide readings and send them over MQTT to Home Assistant. Then sleep for few minutes and again and again 😉
        This way battery stays ok for more than a month.
        By adding small solar panels the battery is always full – even in rainy UK battery gets full in 1 day.

        Reply
    • another possibility is to use an ESP8266-01 (not the ESP8266-01S) and have the door switch, switch the CH_PD pin. That saves a lot of power too.
      I presume that is basically possible with and ESP32 as well, but then one should be sure there are no other components on the board…which would basically mean a bare ESP32 chip

      Reply
  2. Hi, been a fan of your great tutorials since I started learning ESP8266 Arduino programming, and you’re really doing a great job! 👍

    Just wondering if this would be portable to 8266? Thanks!

    Always stay safe guys!

    Reply
  3. Hi guys, it’s a very exciting project; ad maiora semper!
    By the way, can I ask to “zygfryd” a question?
    I am using the Home Assistance on top of other network at my home (ie. Souliss).
    I would like to know how looks the codes for all your sensors on ESP32 going to sleep and wake up then; if you can share it, I would appreciate very much. I am using the ESPhome too to code all the network nodes, awaiting for your reply, thanks in advance.

    Reply
    • here you are – example of both: setup and loop:
      if you need more contact me by email – I don’t have github (yet)

      void setup() {
      Serial.begin(115200);
      //LEDs for beautification
      pinMode(led_red, OUTPUT);
      pinMode(led_green, OUTPUT);
      pinMode(led_blue, OUTPUT);
      //LEDs for showing if solar panel is charging battery or not
      pinMode(CHARGING, INPUT);
      pinMode(POWER, INPUT);

      esp_sleep_enable_timer_wakeup(SLEEP_TIME * uS_TO_S_FACTOR);

      // checking if battery not below LOW (actuall < battery_off – cut off) – don’t connect to WiFi if battery is CRITICAL
      String volts[3]; // array with 3 strings: V, read_raw and state[CRITICAL/LOW/OK]
      measure_volt(ADC1_0,adc_bits,500, adc1_0_factor * adc1_0_factor_resistors, volts);
      Serial.println(“Input voltage before turning ON WiFi: “+String(volts[0])+”V”);
      if (volts[2] == “OFF”){
      Serial.println(“THIS IS BELOW “+String(battery_off)+”V THRESHOLD – NOT STARTING – GOING TO SLEEP UNTIL NOT CHARGED”);
      blink_one(led_red,3,50); // int led, int times, int how_long
      esp_deep_sleep_start();
      }

      digitalWrite(led_green, HIGH);
      ++bootCount;
      if (bootCount > periodic_reboot) { // restart ESP after periodic_reboot times
      Serial.println(“_____________________________________________________________________________________________________”);
      Serial.println(“periodic REBOOT as this is boot number “+String(bootCount));
      Serial.println(“_____________________________________________________________________________________________________”);
      Serial.println();
      Serial.flush();
      blink_all(3,50); //times, how long
      ESP.restart();
      }
      Serial.println();
      Serial.println(“********************************************”);
      Serial.println(“Script version: ” + String(version));
      Serial.println(“wifi timeout: ” + String(wifi_timeout));
      Serial.println(“Sleep time: ” + String(SLEEP_TIME));
      Serial.println(“boot number: “+String(bootCount));
      Serial.println(“********************************************”);
      Serial.println();
      Serial.println(“woke up at: ” + String(start_time) + “ms”);

      setup_wifi();
      mqttc.setServer(mqtt_server, 1883);
      mqttc.setCallback(mqtt_callback);

      // configure npt time
      configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
      ntp_date_time(); //once this is successful, all next calls are without connecting to server

      //sht: temp and humid
      if (! sht31.begin(0x44)) {
      Serial.println(“Couldn’t find SHT31”);
      while (1) delay(1);
      } else {
      Serial.println(“SHT31 OK”);
      }
      //sht end

      //TSL2561 light in lux
      if(!tsl.begin())
      {
      Serial.print(“Ooops, no TSL2561 detected … Check your wiring or I2C ADDR!”);
      while(1) delay(1);
      }
      else {
      Serial.println(“TSL2561 OK”);
      }
      tsl.enableAutoRange(true);
      tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);
      //TSL2561 end

      //OTA in Setup
      server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request) {
      String introtxt = “This is: “+hostname +” Version: ” + version;
      request->send(200, “text/plain”, String(introtxt));
      });
      AsyncElegantOTA.begin(&server, “my-user”,”my-password”);
      server.begin();
      //OTA in Setup END
      }

      void loop() {
      if (!mqttc.connected()) {
      Serial.println(“reconnecting MQTT…”);
      mqtt_reconnect();
      }
      mqttc.loop();
      mqtt_publish_data(); // all measurements are inside publish

      long now_time = millis();
      // here sleeping in case all condistions are met: timer, ota_mode=0 and sleep_enabled=true (for debugging make it false)
      if ((now_time > (WORK_TIME)) and (ota_mode == 0) and (sleep_enabled)){
      go_to_sleep();
      }
      }

      Reply
    • I started with ESPHome but decided to program all my sensors manually – more control etc.
      More fun as well 😉
      So idea is:
      1- start
      2- connect to wifi and mqtt
      3- if no success go to sleep
      4- if ok, gather data (both env sensors (temp, hum, light) as well as battery, rssi, solar panel state, charging etc.)
      5- send over MQTT to broker on Home Assistant
      6- wait extra 3-4 seconds in case MQTT sends message (i.e. to perform OTA)
      7 – after max-time-of-running go to sleep for specific time (majority go to sleep for 10min but few for 5min, some also are always ON so no sleeping)
      8- wakeup, check if boot_number is > max – if so, ESP.restart() to clean the brain 😉
      9- again and again

      Reply
  4. Sara:
    More great ideas from you guys, thanks for all the great explanations that you take so much time to explain. I haven’t worked on any ESP 8266 programs in quite some time so I am almost basically starting over.
    My question here is how far will this mailbox sensor transmit ? My mail box is over 700’ from my house and also concerning the battery life when it get to the winter months. I live in upstate New York and we get some pretty cold weather here.

    Reply
    • Sorry to step in (question was to Sara) but small solar panel 10x7cm charges my battery (1000mAh) within around 3h every day and such battery is in the morning at 4V still
      Sensor wakes up every 5min for 10s to send data.
      But exactly for the door opened sensor – I would propose not to use ESP always ON (this will kill your battery – around 50mA without WiFi) but send ESP to sleep and wake up on GPIO

      Reply
    • Hi.
      The range will depend on the wi-fi range of your board and of your router.
      If the ESP32 can catch a wi-fi signal from the inbox, it will work fine.
      Regards,
      Sara

      Reply
  5. It would seem that the 10K resistor is not needed if you connect the switch from input to ground. You already setup the input pin to INPUT_PULLUP. (If you have an external pullup, then you probably want it to be a plain input, otherwise the internal pullup and external 10K to ground fight each other.) With the switch connected to ground, the open/close reverses – open is 1, close 0.

    It’s good to teach people about the internal pullups. I see lots of designs with unnecessary external pullups.

    Thanks for a nice tutorial

    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.