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 );
}
}
}