MQTT Doorbell

Thank you to all above who posted their code! Here is my version with a few additions.
Here’s what was added: OTA update ability, typo fixed that kept MQTT authentication from working, and added a debounce to stop false button pushes caused by EMI picked up on my doorbell wires.

EMI was causing my doorbell to ring randomly. A delay of 250 ms was added after the first button press is detected. If the button is still pressed after 250 ms, the code continues and the relay is trigger. For me, this eliminated all false button pushes. I’m running this on a Wemos D1 Mini with a relay shield.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

//WIFI
const char* wifi_ssid = “WifiSSID”;
const char* wifi_password = “Password”;

//MQTT
const char* mqtt_server = “hassio”;
const int mqtt_port = 1883;
const char* mqtt_user = “username”;
const char* mqtt_password = “password”;
const char* clientID = “Doorbell”;

//VARS
const char* doorbell_topic = “outside/house/doorbell”;
const int doorbellPin = D2;
const int relayPin = D1;
int doorbellState = 0;
// when mqtt is offline, skip, so bell still works
int mqttRetryCount = 0;
int maxMqttRetry = 3;
boolean connectToMqtt = true;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
Serial.begin(115200);
pinMode(doorbellPin, INPUT_PULLUP);
pinMode(relayPin, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output

// Port defaults to 8266
// ArduinoOTA.setPort(8266);

// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname(“doorbell”);

// No authentication by default
ArduinoOTA.setPassword(“password”);

// Password can be set with it’s md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash(“21232f297a57a5a743894a0e4a801fc3”);

setup_wifi();
client.setServer(mqtt_server, mqtt_port);
}

// DEBUG blink, duur 1 sec
void blink_now(){
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
}

// 2de DEBUG blink, duur 500 msec
void quickblink_now(){
digitalWrite(LED_BUILTIN, LOW);
delay(500);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
}

void setup_wifi() {
//Turn off Access Point
WiFi.mode(WIFI_STA);
delay(10);

// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(wifi_ssid);

WiFi.begin(wifi_ssid, wifi_password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
blink_now();
}

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

ArduinoOTA.onStart( {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = “sketch”;
else // U_SPIFFS
type = “filesystem”;

// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);

});
ArduinoOTA.onEnd( {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf(“Progress: %u%%\r”, (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println(“Auth Failed”);
else if (error == OTA_BEGIN_ERROR) Serial.println(“Begin Failed”);
else if (error == OTA_CONNECT_ERROR) Serial.println(“Connect Failed”);
else if (error == OTA_RECEIVE_ERROR) Serial.println(“Receive Failed”);
else if (error == OTA_END_ERROR) Serial.println(“End Failed”);
});
ArduinoOTA.begin();
Serial.println(“Ready”);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}

void reconnect() {
mqttRetryCount = 0;
// Loop until we’re reconnected
while (mqttRetryCount < maxMqttRetry && !client.connected()) {
Serial.print(“Attempting MQTT connection…”);
quickblink_now();
quickblink_now();
// Attempt to connect
if (client.connect(clientID, mqtt_user, mqtt_password)) {
Serial.println(“connected”);
// Once connected, publish an announcement…
client.publish(doorbell_topic, “Doorbell connected to MQTT”);
connectToMqtt = true;
// set to hundred to jump out of loop
mqttRetryCount = 100;
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.print(" try again in 5 seconds - retry count: ");
Serial.println(mqttRetryCount);
mqttRetryCount++;
connectToMqtt = false;

  // Wait 3 seconds before retrying
  delay(3000);
}

}
}

void loop() {

ArduinoOTA.handle();

if (connectToMqtt && !client.connected()) {
reconnect();
}
client.loop();
doorbellState = digitalRead(doorbellPin); // Reads pin and set variable

if ( doorbellState == LOW ) { // Checks if pin is low
delay( 250 ); // Delay for button debounce
if ( digitalRead(doorbellPin) == LOW ) { // Read pin to see if still low after debounce delay

// Put your code here.  e.g. connect, send, disconnect.
Serial.println("Doorbell is pressed!");
digitalWrite(relayPin, HIGH); // turn on relay with voltage HIGH
delay( 1000 );
digitalWrite(relayPin, LOW);  // turn off relay with voltage LOW

// publish to mqtt
client.publish(doorbell_topic, "ON", true);
blink_now();
delay( 1000 );
client.publish(doorbell_topic, "OFF", true);

// block bell for 4 seconds
delay( 4000 );
}

}
}

5 Likes

Thanks for this great topic and your great schematic. I turned it into a pcb specific for this purpose:

The doorbell wires connect to the screw terminal, while the jack plug connects to 5v. I can program it with the arduino IDE (by plugging a ftdi module into the socket on the right in the back) . I now programmed it to send a MQTT message to hass whenever someone presses the doorbell.

6 Likes

Wish I could buy this! Nice work man.

Both of you, tisgoud and ErikNL great, love it!!

I have ordered the necessary parts mentioned on the github page of tisgoud. Now wait until they arrive. But I’m afraid it won’t be as nice as ErikNL his PCB.
Wish I could buy or make this!

Would love to see your code.

My code is not really anything fancy, I just use it to send a MQTT message with payload “on” whenever someone presses the doorbell, and then send a off message 5 seconds later. You can find the code here:

I use the mqtt message in home assistant to take a camera snapshot and send it over to my phone with pushbullet.

1 Like

well, you can now : https://www.tindie.com/products/ErikLemcke/mqtt--wifi-doorbell-with-esp8266/ :slight_smile:

4 Likes

Hey thanks Erik! I feel like such a putz though, as I can’t even figure out what I should put in my config file to manually enable or disable the door bell. I just used a wemos d1 and relay shield stacked.

I put this in there but I don’t hear the relay click when I turn it on and off in home assistant.

switch:

platform: mqtt
name: “Doorbell”
command_topic: “hal/doorbell”

You probably need a …

  payload_on: "on"
  payload_off: "off"

I just ordered the kit. Thank you!!
One question, why use a seperate 5V power supply instead of a buck converter? That way you can use the power from the doorbell transformer.

Ah, that’s mainly because of my personal preference I guess. I didn’t have easy access to the bell transformer, and I did have a power socket nearby. You can however still use your bell transformer, if you transform the AC power into DC 12v max, you would be ok I think to use it as a input for the board.

I did by the way just add the schematics and board files to the github repository linked on the tindie page, so if anyone wants to tinker around with it, feel free to do so :slight_smile:

1 Like

Mind sharing your home assistant code? Does your code enable you to disable the doorbell entirely?

Thanks for sharing!

Where did you get the pcb made? I only need one (or two, just in case) and the cheapest online option I have found is about 16 US$ because of the shipping costs to The Netherlands.

Why don’t you buy one from ErikNL? https://www.tindie.com/products/ErikLemcke/mqtt--wifi-doorbell-with-esp8266/
He did all the work and is asking a very reasonable price including shipping.

Ok, now I feel dumb… I only read his last post and didn’t see the link :face_with_monocle:.
I will order on his tindie now offcourse. Thanks for pointing me there

1 Like

No problem lxz, but if you want to get them made yourself, I ordered mine at seeed studio this time.

I ordered the kit. Perfect item, I love it! Thanks ErikNL.

These are my tips.
Adruino IDE flash settings: (picture is from ErikNL)

82b27f3dfc5713bd882ff213b0efb5d4df2be2a4_1_313x500

When I connected with the board via the Accesspoint method as ErikNL mentioned in his manual, I have entered the following in the topic: hall / doorbell (when you flashed the board yourself this is the same topic)

My settings in Home Assistant, configuration.yaml are:

Switch:
  - platform: mqtt
    name: "doorbell"
    state_topic: "hal/doorbell"
    command_topic: "hal/doorbell"
    payload_on: "on"
    payload_off: "off"

I still have to find out if the following needs to be added to the configuration.yaml
qos: 1
retain: true

another great approach:

1 Like

Hi Christian, could you please share the script you run for day and night doorbell?
did you solved the false triggering? nice project.

/Martin

Yes, the false triggers was solved by using a resistor between the switch and the wemos
I use two automations, one for daytime and one for nighttime.

- alias: Doorbell ringing daytime
  trigger:
    platform: mqtt
    topic: home/outdoors/doorbell
    payload: 'on'
  condition:
    condition: time
    after: '07:00:00'
    before: '19:00:00'
  action:
    - service: shell_command.sonos_play_doorbell
    - service: notify.iOS
      data:
        message: "Dörrklockan ringer!"
        data:
          attachment:
            content-type: jpeg
            hide-thumbnail: false
          push:
            category: camera
          entity_id: camera.huvudentren

- alias: Doorbell ringing nighttime
  trigger:
    platform: mqtt
    topic: home/outdoors/doorbell
    payload: 'on'
  condition:
    condition: time
    after: '19:00:00'
    before: '07:00:00'
  action:
    - service: shell_command.sonos_play_doorbell_night
    - service: notify.iOS
      data:
        message: "Dörrklockan ringer!"
        data:
          attachment:
            content-type: jpeg
            hide-thumbnail: false
          push:
            category: camera
          entity_id: camera.huvudentren
2 Likes