MQTT Lock for my garage door

Hi all!

I would like to pick some of your brains…

I have a D1 mini with a relay shield to use for my garage door as an MQTT lock. So, it sets the relay HIGH for 250ms and then LOW with both LOCK and UNLOCK functions, almost as if it is pressing the button to open or close the door.
It also then sends out a message for the state topic, so in Home Assistant it is not optimistic.

My problem is here- when the garage is door is closed physically and it shows locked in home assistant, I tell Google Assistant to close the garage door, it opens the garage door but then still shows locked in Home Assistant… and this way I am going to get house robbed very easily! Anybody got any ideas?

My code for the D1 mini is below.

Cheers!

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>

#define BUTTON 0 // (Don’t Change for Sonoff)
#define RELAY D1 // (Don’t Change for Sonoff)
#define LED 13 // (Don’t Change for Sonoff)

#define MQTT_CLIENT “WeMos_D1Mini_Garage_Door_01” // mqtt client_id (Must be unique for each Sonoff)
#define MQTT_SERVER “192.168.0.1” // mqtt server
#define MQTT_PORT 1883 // mqtt port
#define MQTT_TOPIC “/Home/Garage/Door01” // mqtt topic (Must be unique for each Sonoff)
#define MQTT_USER “” // mqtt user
#define MQTT_PASS “” // mqtt password

#define WIFI_SSID “mywifi” // wifi ssid
#define WIFI_PASS “mypassword” // wifi password

#define VERSION “\n\n------------------ Sonoff Powerpoint v1.0p -------------------”

extern “C” {
#include “user_interface.h”
}

bool sendStatus = false;
bool requestRestart = false;

int kUpdFreq = 1;
int kRetries = 10;

unsigned long TTasks;
unsigned long count = 0;

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient, MQTT_SERVER, MQTT_PORT);
Ticker btn_timer;

void callback(const MQTT::Publish& pub) {
if (pub.payload_string() == “stat”) {
}
else if (pub.payload_string() == “1”) {
digitalWrite(LED, LOW);
digitalWrite(RELAY, HIGH);
delay(250);
digitalWrite(RELAY, LOW);
}
else if (pub.payload_string() == “0”) {
digitalWrite(LED, HIGH);
digitalWrite(RELAY, HIGH);
delay(250);
digitalWrite(RELAY, LOW);
}
else if (pub.payload_string() == “reset”) {
requestRestart = true;
}
sendStatus = true;
}

void setup() {
pinMode(LED, OUTPUT);
pinMode(RELAY, OUTPUT);
pinMode(BUTTON, INPUT);

digitalWrite(LED, HIGH);
digitalWrite(RELAY, LOW);

btn_timer.attach(0.05, button);

mqttClient.set_callback(callback);

WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
Serial.begin(115200);
Serial.println(VERSION);
Serial.print("\nESP ChipID: “);
Serial.print(ESP.getChipId(), HEX);
Serial.print(”\nConnecting to “); Serial.print(WIFI_SSID); Serial.print(” Wifi");
while ((WiFi.status() != WL_CONNECTED) && kRetries --) {
delay(500);
Serial.print(" .");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println(" DONE");
Serial.print(“IP Address is: “); Serial.println(WiFi.localIP());
Serial.print(“Connecting to “); Serial.print(MQTT_SERVER); Serial.print(” Broker . .”);
delay(500);
while (!mqttClient.connect(MQTT::Connect(MQTT_CLIENT).set_keepalive(90).set_auth(MQTT_USER, MQTT_PASS)) && kRetries --) {
Serial.print(” .”);
delay(1000);
}
if (mqttClient.connected()) {
Serial.println(" DONE");
Serial.println("\n---------------------------- Logs ----------------------------");
Serial.println();
mqttClient.subscribe(MQTT_TOPIC);
blinkLED(LED, 40, 8);
digitalWrite(LED, HIGH);
}
else {
Serial.println(" FAILED!");
Serial.println("\n----------------------------------------------------------------");
Serial.println();
}
}
else {
Serial.println(" WiFi FAILED!");
Serial.println("\n----------------------------------------------------------------");
Serial.println();
}
}

void loop() {
mqttClient.loop();
timedTasks();
checkStatus();
}

void blinkLED(int pin, int duration, int n) {
for (int i = 0; i < n; i++) {
digitalWrite(pin, HIGH);
delay(duration);
digitalWrite(pin, LOW);
delay(duration);
}
}

void button() {
if (!digitalRead(BUTTON)) {
count++;
}
else {
if (count > 1 && count <= 40) {
digitalWrite(LED, !digitalRead(LED));
digitalWrite(RELAY, HIGH);
delay(250);
digitalWrite(RELAY, LOW);
// digitalWrite(RELAY, !digitalRead(RELAY));
sendStatus = true;
}
else if (count > 40) {
Serial.println("\n\nSonoff Rebooting . . . . . . . . Please Wait");
requestRestart = true;
}
count = 0;
}
}

void checkConnection() {
if (WiFi.status() == WL_CONNECTED) {
if (mqttClient.connected()) {
Serial.println(“mqtt broker connection . . . . . . . . . . OK”);
}
else {
Serial.println(“mqtt broker connection . . . . . . . . . . LOST”);
requestRestart = true;
}
}
else {
Serial.println(“WiFi connection . . . . . . . . . . LOST”);
requestRestart = true;
}
}

void checkStatus() {
if (sendStatus) {
if (digitalRead(LED) == LOW) {
mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", “1”).set_retain().set_qos(1));
Serial.println(“Relay . . . . . . . . . . . . . . . . . . ON”);
} else {
mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", “0”).set_retain().set_qos(1));
Serial.println(“Relay . . . . . . . . . . . . . . . . . . OFF”);
}
sendStatus = false;
}
if (requestRestart) {
blinkLED(LED, 400, 4);
ESP.restart();
}
}

void timedTasks() {
if ((millis() > TTasks + (kUpdFreq * 60000)) || (millis() < TTasks)) {
TTasks = millis();
checkConnection();
}
}

You need to have a sensor connected to your wemo to determine if the door is shut or not. A magnetic reed sensor would do the job.

Thanks for the reply and advice.

I’m not sure how much you know about the coding and so on for the D1 Mini, but is it possible to have the D1 change some kind of variable everytime you open or close the door, and have it check the variable before opening or closing so that it can then “decide” whether the door is already open or already closed?

Thanks

It is possible, but I wouldn’t rely on it to be accurate all the time. Certainly not for a door shutting application that would expose your garage if it ever got confused, for instance if you told it to shut and it doesn’t.

Would this item be fine?

That would work, but you would need to buy a magnet separately to switch it.

I was thinking of something like this

The magnet is in one box and the reed switch is in another. When the magnet (attached to the door) is close to the switch, it closes the reed. If you connect this to your wemos, you can detect the door is closed.

I would also add one to detect the door is fully open, assuming you have enough pins on the wemos.

Awesome thanks so much. Will give this a try!

In my lock design I used INA219 to check the motor overload. Then it finds it closed or open.
Do you have a solution on how to install a pin code so that it can be opened by voice through google nest?