IoT Doorbell through Telegram on ESP8266


this is a ESP8266 Nodemcu lolin v3. i plan on using a wemos d1 mini instead for future projects.
when powering esp boards over usb, it’s necessary to add a capacitor to the 5V rail.


the 433MHz doorbell button.


the optional receiver. simply playing a doorbell sound when the button gets pressed.


a 433MHz receiver decoder with 4 outputs based on a EV1527 chip. the TX button directly triggers the RX’s output D1.
practical receivers/transmitter which do not need any manual software decoding.


5V and 3.3V capacitors, although the 3.3V capacitor isn’t necessary.


drilling the case.


fitting everything into the case.


the finished product.
pressing the button sends a telegram (push IM) message to all registered smartphones/users.

This project utilized the Universal-Arduino-Telegram-Bot Library by witnessmenow

some technical information (like output current and reserved pins) for esp8266

some more technical information about the “wifi” library.

the source code:


 /*
  * Author:   Dejan Lauber
  * Date:     6.2017
  * File:     klingeling_bot.ino
  * Version:  V1
  * 
  * Telegram Doorbell Bot
  * chats have to "authorize" themself
  * when the doorbell button is pressed, a message is sent to all registered chats
  * 
  * apparently the following gpio pins are not to be used on nodemcu lolin v3:
  * gpio0  D3  boot and flash
  * gpio2  D4  (onboard led) boot and flash
  * gpio15  D8  boot and flash and sd
  * gpio9,10 (sd2,sd3) are used for the sd interface
  * gpio1,3 (D9,D10) are used for the serial usb communicatiom  
  * 
  * gpio6 to gpio11 could be used for something something flash
  * lolin v3 hardware doesnt give acces to gpio6,7,8 and gpio11, maybe those are reserved for flash
  * 
  * lolin v3 ok pins:
  * D0-D2
  * (D3)
  * D5-D7
  * (D8)
  * A0  //only analog input
  * 
  * EEPROM:
  * 0-3   kCounter (32bit)
  * 4     ledBuf
  * 100-350  Registered ChatIds
  * chat_ids are saved as strings because 64bit variables aren't supported.
  * (64 bit probably is supported on esp8266, because it is a 32 bit mcu)
  * 
  */
  
//ADC_MODE(ADC_VCC);
 
#include <Pushbutton.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

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

// Initialize Telegram BOT
#define BOTtoken "xxxx"  // Telegram Bot Token (Get from Botfather)

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

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

const byte ledRed = D6; //error led
const byte buttonLPin = D5;  //local button
const byte buttonRFPin = D2;  //remote button

const byte authNumber = 10;

Pushbutton buttonL(buttonLPin, PULL_UP_ENABLED, DEFAULT_STATE_HIGH);
Pushbutton buttonRF(buttonRFPin, PULL_UP_DISABLED, DEFAULT_STATE_LOW); //PULL_UP_DISABLED

String auth_ids[authNumber] = {};
byte auth = 0, ledBuf;
word kCounter = 0;


void handleNewMessages(int numNewMessages) {
  Serial.print("handleNewMessage: ");
  //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;
    
    Serial.println(text);
    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    auth = 0;
    for(byte j=0; j<authNumber; j++) {
      /*
      //debug
      Serial.println(j);
      Serial.println(chat_id);
      Serial.println(chat_id.length());
      Serial.println(int(chat_id[9]));
      Serial.println(auth_ids[j]);
      Serial.println(auth_ids[j].length());
      Serial.println(int(auth_ids[j][9]));
      Serial.println(int(auth_ids[j][10]));
      */
      if(chat_id == auth_ids[j]){
        auth = 1;
        j = authNumber;
      }
    }
    
    if(!auth){
      //Serial.println("unauthorized");
      if ((text == "/status")||(text == "/start")) {
        //String msg = "Türklingeling Tierpension\n";
        String msg = "This is klingeling_bot.\n";
        msg += "This Chat ID is: " + chat_id + "\n\n";
        msg += "/status : Get this Message\n";
        msg += "/test : Get Test Messages";
        bot.sendMessage(chat_id, msg, "");
      }
      if (text == "/admin_xxxx") {  //authorization keyword
        //add chat_id to auth_ids
        for(byte j=0; j<authNumber; j++) {
          if(auth_ids[j] == ""){
            auth_ids[j] = chat_id;
            
            for (byte i = 0; i < chat_id.length()+1; ++i){
              EEPROM.write(100+(25*j)+i, chat_id[i]);
            }
            EEPROM.commit();
            
            auth = 1;
            text = "/status";  //respond with /status
            j = authNumber;
            //bot.sendMessage(chat_id, "You have been registered!", "");
          }
        }
      }
    }
    if(auth){
      //Serial.println("authorized");
      if (text == "/logout") {
        for(byte j=0; j<authNumber; j++) {
          if(chat_id == auth_ids[j]){
            auth_ids[j] = "";
            EEPROM.write(100+(25*j),255);
            EEPROM.commit();
            auth = 0;
            j = authNumber;
          }
        }
        bot.sendMessage(chat_id, "You have been unregistered!", "");
      }
      
      if (text == "/test") {
        for(byte j=0; j<authNumber; j++) {
          if(auth_ids[j] != ""){
            bot.sendMessage(auth_ids[j], "Test Message", "");
          }
        }
      }
      
      
      if (text == "/admin_purge") {
        for(byte j=0; j<authNumber; j++) {
          if(auth_ids[j] != ""){
            bot.sendMessage(auth_ids[j], "You have been unregistered!", "");
            auth_ids[j] = "";
            EEPROM.write(100+(25*j),255);
            auth = 0;
          }
        }
        EEPROM.commit();
        bot.sendMessage(chat_id, "All Admins have been unregistered!", "");
      }
      
      if (text == "/restart") {
        bot.sendMessage(chat_id, "restarting", "");
        delay(1000);
        ESP.restart();
      }
      
      if (text == "/ledon") {
        bot.sendMessage(chat_id, "led on", "");
        ledBuf = 1;
        EEPROM.write(4,ledBuf);
        EEPROM.commit();
        //Serial.println(ledBuf);
      }
      
      if (text == "/ledoff") {
        bot.sendMessage(chat_id, "led off", "");
        ledBuf = 0;
        EEPROM.write(4,ledBuf);
        EEPROM.commit();
        //Serial.println(ledBuf);
      }
  
      if (text == "/tech") {
        String msg = "klingeling_bot Statistics.\n";
        msg += String(ssid) +" : " + String(WiFi.RSSI()) + " dBm\n";
        msg += "IP address : " + WiFi.localIP().toString() + "\n";
        //msg += "Vcc : " + String(ESP.getVcc()) + " mV\n";
        msg += "Klingel Counter : " + String(kCounter) + "\n";
        msg += "uptime : " + String(millis()/(1000*60*60)) + " h\n\n";
        msg += "You are Registered!\n";
        msg += "This Chat ID is : " + chat_id + "\n";
        msg += "Registered Chat IDs:\n";
        for(byte j=0; j<authNumber; j++) {
          msg += auth_ids[j] + " ";
        }
        bot.sendMessage(chat_id, msg, "");
        
      }
      
      if ((text == "/status")||(text == "/start")) {
        //String msg = "Türklingeling Tierpension\n";
        String msg = "This is klingeling_bot.\n";
        msg += "You are Registered!\n\n";
        msg += "/status : Get this Message\n";
        msg += "/tech : Get Statistics\n";
        msg += "/logout : Unregister\n";
        msg += "/test : Get Test Messages\n\n";
        bot.sendMessage(chat_id, msg, "");
      }
    }
    if (text == "/test") {
      for (int i=0; i<5; i++) {
        bot.sendMessage(chat_id, "bel", "");
        delay(0);
      }
    }
  }
}


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

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

  
  EEPROM.begin(512);
  //EEPROM.write(175,'A');
  //EEPROM.write(176,'\0');

  //set kCounter
  //EEPROM.put(0,(word)2);
  //EEPROM.commit();

  ledBuf = EEPROM.read(4);
  //Serial.println(ledBuf);
  EEPROM.get(0,kCounter);
  //Serial.println(ledBuf);
  //Serial.println(kCounter);
  for(byte j=0; j<authNumber; j++) {
    for (byte i = 0; i < 25; ++i){
      
      char tmp = char(EEPROM.read(100+(25*j)+i));
      
      if((tmp == '\0')||(tmp == 255)){
        i=25;
      }
      else{
        auth_ids[j] += tmp;
      }
    }
    //Serial.println(auth_ids[j]);
  }
  
  pinMode(ledRed, OUTPUT); // initialize digital ledPin as an output.
  //pinMode(buttonLPin, INPUT_PULLUP);
  //pinMode(buttonRFPin, INPUT_PULLUP); //INPUT
  
  // 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);
    digitalWrite(ledRed, !digitalRead(ledRed));
  }
  digitalWrite(ledRed, 0);

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());

}

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

  //on error, blink led
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(250);
    digitalWrite(ledRed, !digitalRead(ledRed));
  }
  else{
    if(!ledBuf){
      digitalWrite(ledRed, 0);
    }
    else{
      digitalWrite(ledRed, 1);
    }
  }

  //button press
  if (buttonL.getSingleDebouncedPress()||buttonRF.getSingleDebouncedPress())
    {
      String msg = "";
      switch(random(9)){
      case 0:
        msg = "wuff wuff";
        break;
      case 1:
        msg = "iemand heeft gebeld";
        break;
      case 2:
        msg = "ding dong";
        break;
      case 3:
        msg = "klopf klopf";
        break;
      case 4:
        msg = "dhoru foanukurun kaley";
        break;
      case 5:
        msg = "有人在響";
        break;
      case 6:
        msg = "miau";
        break;
      case 7:
        msg = "klingelingeling";
        break;
      case 8:
        msg = "ey ture machet luti mann!";
        break;
      }
        for(byte j=0; j<authNumber; j++) {
          if(auth_ids[j] != ""){
            bot.sendMessage(auth_ids[j], msg, "");
          }
        }
      //ledBuf = 1;
      kCounter++;
      EEPROM.put(0,kCounter);
      EEPROM.commit();
      Serial.println("Button press detected");
  }
}

4 Replies to “IoT Doorbell through Telegram on ESP8266”

  1. Hi, I’ve tried your program and it works. I understood that it is an experimental program for managing the input status of an esp8266 with response through Telegram_bot. It is what I was looking for but being little able in programming I got lost in the listing. It is interesting because it does not use IFTTT or similar but uses part of the EEPROM. How could I have a cleaner listing where two inputs give me two answers in Telegram_bot? You could illustrate it to all of us, step by step. Thank you. Claude

    1. 2 inputs are already defined (D2 and D5), they both trigger the same response.

      if you just want 2 buttons (connecting the inputs D2 and D5 to ground) you have to change a few things:

      1: change

      Pushbutton buttonRF(buttonRFPin, PULL_UP_DISABLED, DEFAULT_STATE_LOW);

      to

      Pushbutton buttonRF(buttonRFPin, PULL_UP_ENABLED, DEFAULT_STATE_HIGH);

      2: check the last part of the code. that’s where a message gets sent when a button is pressed.
      dublicate the code following the line:

      //button press

      2A: adjust both their if(…..) statements to only one button each

      2B: adjust the content of the ‘msg’ string to your liking.

      sorry I can’t be more specific, i hope that helps.

Comments are closed.