Mit einem MQTT-Garagentoröffner können Sie Ihr Garagentor von überall öffnen, schließen und – vor allem – seinen Zustand prüfen, und zwar mit dem Antrieb, den Sie bereits haben. In diesem Tutorial verdrahten Sie einen ESP32 mit einem Relais, das den Wandtaster „drückt“, und einem Reedkontakt, der meldet, ob das Tor wirklich geschlossen ist. Diesen Zustand veröffentlichen Sie anschließend als retained MQTT-Nachricht, sodass jede App die Wahrheit sieht, sobald sie sich verbindet.
So funktioniert der Öffner
Fast jeder Garagentorantrieb für den Wohnbereich hat Klemmen für einen Wandtaster. Diese beiden Klemmen kurz zu überbrücken entspricht einem Tastendruck: Das Tor fährt an, stoppt oder kehrt um, je nachdem, wo es sich befindet. Dadurch ist die Hardwareseite einfach und ohne Eingriff in den Antrieb umsetzbar:
- Ein Relais, parallel zum Wandtaster verdrahtet, erzeugt einen „Tastendruck“ von 500 ms.
- Ein Reedkontakt am Rahmen, mit einem Magneten am Tor, schließt, wenn das Tor vollständig zu ist.
- Der ESP32 wartet auf Befehle, pulst das Relais und veröffentlicht den Zustand des Reedkontakts.
Die zentrale Designentscheidung: Der Öffner nimmt nie an, was das Tor getan hat. Er veröffentlicht, was der Sensor sieht. Ein Befehl ist eine Anfrage; der Reedkontakt ist die Tatsache. Wer aus der Automatisierungstechnik kommt, kennt das Prinzip von jeder SPS: Ausgänge setzen ist das eine, die Rückmeldung des Endlagenschalters das andere.
Teileliste
| Teil | Zweck |
|---|---|
| ESP32 DevKit | WLAN und MQTT-Client |
| 1-Kanal-Relaismodul, 3,3-V-kompatibel (oder optogekoppeltes 5-V-Modul) | Überbrückt die Klemmen des Wandtasters |
| Magnetischer Reedkontakt, Schließer, Aufputz | Erkennt das vollständig geschlossene Tor |
| Optionaler zweiter Reedkontakt | Erkennt das vollständig geöffnete Tor |
| 5-V-USB-Netzteil und Gehäuse | Stromversorgung und Schutz vor Staub |
| Zweiadrige Klingellitze | Relais zu den Antriebsklemmen, Reedkontakt zum ESP32 |
Bevor Sie etwas verdrahten, prüfen Sie das Handbuch Ihres Antriebs. Manche neueren Antriebe verwenden ein digitales Wandbedienteil statt eines potenzialfreien Kontakts; diese benötigen eine kompatible Schnittstelle oder eine Ersatz-Fernbedienung, deren Taste mit dem Relais verdrahtet wird.
Verdrahtung
| Von | Nach | Hinweise |
|---|---|---|
| Relais IN | GPIO 26 | Aktiver Pegel hängt von Ihrem Modul ab |
| Relais VCC / GND | 5V / GND | Optogekoppelte Module benötigen ggf. ein separates JD-VCC |
| Relais COM und NO | Wandtasterklemmen am Antrieb | Parallel zum vorhandenen Taster |
| Reedkontakt (Position geschlossen) | GPIO 27 und GND | Nutzt den internen Pull-up |
| Reedkontakt (Position offen, optional) | GPIO 25 und GND | Nutzt den internen Pull-up |
Mit INPUT_PULLUP liest ein geschlossener Reedkontakt LOW. Montieren Sie den Reedkontakt für die geschlossene Position so, dass der Magnet nur dann innerhalb von etwa einem Zentimeter sitzt, wenn das Tor ganz unten ist.
Topic-Design für den MQTT-Garagentoröffner
Nach den Konventionen aus unserem Leitfaden zur Smart-Home-MQTT-Topic-Struktur:
<base>/garage/door/state retained: "closed", "open", "opening/closing", "unknown"
<base>/garage/door/state/set command: "OPEN", "CLOSE", "PRESS" (never retained)
<base>/garage/door/availability retained: "online" / "offline" via last will
Wird das Zustands-Topic retained, zeigt das Dashboard auf Ihrem Smartphone beim Verbinden sofort „closed“ an, statt auf die nächste Änderung zu warten. Wird das Befehls-Topic nie retained, kann ein Stromausfall kein altes OPEN erneut abspielen und das Tor von selbst öffnen.
Der ESP32-Sketch
Der Sketch verwendet PubSubClient. Setzen Sie BENCH_TEST auf true, während Sie auf dem öffentlichen MQTT-Broker mit einer LED statt des Antriebs testen; setzen Sie es für Ihren privaten Broker mit TLS auf false.
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#define BENCH_TEST true
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
#if BENCH_TEST
const char* BASE = "connectmq/demo/g4k9t2"; // zufälliges Präfix, öffentlicher Bereich
const char* CLIENT_ID = "garage-g4k9t2";
const char* MQTT_USER = nullptr;
const char* MQTT_PASS = nullptr;
WiFiClient net;
const uint16_t PORT = 1883;
#else
const char* BASE = "home1";
const char* CLIENT_ID = "YOUR_CLIENT_ID";
const char* MQTT_USER = "YOUR_USERNAME";
const char* MQTT_PASS = "YOUR_PASSWORD";
const char* ROOT_CA = R"EOF(
-----BEGIN CERTIFICATE-----
...paste the ISRG Root X1 certificate here...
-----END CERTIFICATE-----
)EOF";
WiFiClientSecure net;
const uint16_t PORT = 8883;
#endif
const int RELAY_PIN = 26;
const int REED_CLOSED_PIN = 27;
const int REED_OPEN_PIN = 25;
const bool RELAY_ACTIVE = HIGH; // für Active-Low-Module auf LOW ändern
const unsigned long PRESS_MS = 500;
const unsigned long TRAVEL_TIMEOUT_MS = 30000;
PubSubClient mqtt(net);
String tState, tSet, tAvail;
String lastState = "";
unsigned long lastPressAt = 0;
String readDoor() {
bool closed = digitalRead(REED_CLOSED_PIN) == LOW;
bool open = digitalRead(REED_OPEN_PIN) == LOW;
if (closed) return "closed";
if (open) return "open";
if (millis() - lastPressAt < TRAVEL_TIMEOUT_MS) return "opening/closing";
return "unknown"; // auf halber Strecke gestoppt oder Sensor für offen fehlt
}
void pressButton() {
if (millis() - lastPressAt < 2000) return; // schnelle Wiederholungen ignorieren
digitalWrite(RELAY_PIN, RELAY_ACTIVE);
delay(PRESS_MS);
digitalWrite(RELAY_PIN, !RELAY_ACTIVE);
lastPressAt = millis();
}
void onMessage(char* topic, byte* payload, unsigned int len) {
String cmd;
for (unsigned int i = 0; i < len; i++) cmd += (char)payload[i];
cmd.trim();
cmd.toUpperCase();
String door = readDoor();
if (cmd == "OPEN" && door == "closed") pressButton();
else if (cmd == "CLOSE" && door == "open") pressButton();
else if (cmd == "PRESS") pressButton();
// OPEN bei offenem oder CLOSE bei geschlossenem Tor wird absichtlich ignoriert
}
void connectMqtt() {
while (!mqtt.connected()) {
if (mqtt.connect(CLIENT_ID, MQTT_USER, MQTT_PASS, tAvail.c_str(), 1, true, "offline")) {
mqtt.publish(tAvail.c_str(), "online", true);
mqtt.subscribe(tSet.c_str(), 1);
lastState = ""; // frischen retained Zustand erzwingen
} else {
delay(5000);
}
}
}
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, !RELAY_ACTIVE);
pinMode(REED_CLOSED_PIN, INPUT_PULLUP);
pinMode(REED_OPEN_PIN, INPUT_PULLUP);
tState = String(BASE) + "/garage/door/state";
tSet = tState + "/set";
tAvail = String(BASE) + "/garage/door/availability";
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
#if !BENCH_TEST
net.setCACert(ROOT_CA);
#endif
mqtt.setServer(BROKER, PORT);
mqtt.setCallback(onMessage);
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
static unsigned long lastCheck = 0;
if (millis() - lastCheck > 200) {
lastCheck = millis();
String s = readDoor();
if (s != lastState) {
mqtt.publish(tState.c_str(), s.c_str(), true); // retained Zustand
lastState = s;
}
}
}
Einige Details sind besonders beachtenswert:
OPENpulst das Relais nur, wenn das Torclosedmeldet, undCLOSEnur, wenn esopenmeldet. Da ein Tastendruck den Antrieb umschaltet, würde einOPENan ein offenes Tor es sonst schließen.- Tastendrücke im Abstand von weniger als zwei Sekunden werden ignoriert. Das verhindert, dass ein doppelt angetippter Button oder eine wiederholte QoS-1-Nachricht das Tor umkehrt.
- Die Abfrage alle 200 ms wirkt als einfache Entprellung für den Reedkontakt.
Test auf dem Labortisch
Schließen Sie eine LED mit Vorwiderstand an den Relaisausgang an (oder achten Sie einfach auf das Klicken des Relais), lassen Sie BENCH_TEST auf true und flashen Sie das Board. Dann in einem Terminal:
B=connectmq/demo/g4k9t2
mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-g4k9t2 -t "$B/garage/#" -v
mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-g4k9t2 -q 1 -t $B/garage/door/state/set -m PRESS
Führen Sie einen Magneten am Reedkontakt vorbei und beobachten Sie, wie sich der Zustand ändert. Trennen Sie den ESP32 vom Strom, und nach Ablauf des Keep-Alive-Timeouts veröffentlicht der Broker offline auf dem Verfügbarkeits-Topic.
Schließen Sie den echten Torantrieb nicht an, solange Sie den öffentlichen MQTT-Broker verwenden. Er ist nur für Tests und Prototypen gedacht. Jeder, der Ihr Topic errät, kann dort mitlesen und veröffentlichen. Wechseln Sie zuerst zu privaten Zugangsdaten.
Live-Betrieb auf einem privaten Broker
Setzen Sie BENCH_TEST auf false, fügen Sie das Zertifikat ISRG Root X1 (die Let's-Encrypt-Root) ein und tragen Sie Benutzername, Passwort und Client-ID ein, die im ConnectMQ-Portal generiert wurden. Jetzt verbindet sich der Öffner über TLS auf Port 8883, und nur Clients mit Ihren Zugangsdaten können ihn steuern. Unser Artikel zu den Best Practices für MQTT-Sicherheit erklärt, warum Zugangsdaten und TLS bei allem, was eine Tür öffnet, nicht verhandelbar sind.
Um ihn aus Home Assistant zu steuern, fügen Sie eine MQTT-Cover-Entität hinzu, die auf dieselben Topics zeigt, oder folgen Sie dem Home-Assistant-MQTT-Leitfaden:
mqtt:
cover:
- name: "Garage Door"
command_topic: "home1/garage/door/state/set"
state_topic: "home1/garage/door/state"
availability_topic: "home1/garage/door/availability"
payload_open: "OPEN"
payload_close: "CLOSE"
payload_stop: "PRESS"
state_open: "open"
state_closed: "closed"
state_opening: "opening/closing"
qos: 1
Sicherheits-Checkliste
- Lassen Sie die eigenen Sicherheitsfunktionen des Antriebs (Lichtschranken, automatische Umkehr) angeschlossen und funktionsfähig.
- Retainen Sie niemals Befehlsnachrichten.
- Reagieren Sie auf
OPEN/CLOSEnur, wenn der Sensor den jeweils entgegengesetzten Zustand bestätigt. - Verwenden Sie TLS und private Zugangsdaten, bevor Sie den Antrieb anschließen.
- Richten Sie eine Benachrichtigung ein, wenn das Tor länger als erwartet
openist. - Montieren Sie das Relais in einem Gehäuse, fern von beweglichen Teilen.
- Testen Sie, was passiert, wenn das WLAN während der Fahrt ausfällt: Das Tor muss seine Bewegung einfach zu Ende führen.
Für die Benachrichtigung „Tor offen gelassen“ können die Grenzwert-Alarmregeln im ConnectMQ-Portal Werte auf einem Topic markieren, oder eine Automatisierung in Home Assistant oder Node-RED überwacht, ob open länger als zehn Minuten anhält.
Fehlerbehebung
Das Relais klickt, aber das Tor bewegt sich nicht. Ihr Antrieb verwendet wahrscheinlich ein digitales Wandbedienteil. Verdrahten Sie das Relais stattdessen mit der Taste einer Ersatz-Fernbedienung.
Der Zustand springt zwischen closed und unknown hin und her. Der Magnet ist zu weit vom Reedkontakt entfernt, oder das Tor klappert. Bringen Sie beide näher zusammen oder verlängern Sie die Entprellung.
Das Tor kehrt um, wenn Sie OPEN senden. Sie senden PRESS, oder der Sensor für geschlossen liest nicht LOW. Prüfen Sie die Verdrahtung des Reedkontakts mit dem seriellen Monitor.
Das Gerät kommt nie wieder online. Prüfen Sie, ob die Client-ID eindeutig ist; zwei Geräte mit derselben ID werfen sich gegenseitig hinaus. Stellen Sie auf einem privaten Broker außerdem sicher, dass Sie genau die mit Ihren Zugangsdaten ausgestellte Client-ID verwenden, denn Client-IDs sind an diese gebunden.
Befehle kommen verspätet oder doppelt an. QoS 1 garantiert mindestens einmalige Zustellung, daher kann eine wiederholte Nachricht nach einem Reconnect ankommen. Die Zwei-Sekunden-Sperre für Tastendrücke und die Zustandsprüfungen in onMessage machen Duplikate harmlos.
Steuern Sie Ihre Garage sicher mit ConnectMQ
Ein Toröffner verdient einen privaten, verschlüsselten Broker statt eines öffentlichen. ConnectMQ ist ein verwalteter MQTT-Broker mit TLS, generierten Zugangsdaten und einem Live-Topic-Explorer, in dem Sie den Zustand Ihres Tors beobachten können. Erstellen Sie einen kostenlosen Serverless-Broker unter app.connectmq.com, ohne Kreditkarte, stellen Sie BENCH_TEST auf false, und Sie sind live. Hintergründe zum Hosting finden Sie im Beitrag zum MQTT-Broker in der Cloud, und weitere Projekte wie die Wasserleck-Erkennung mit IoT entdecken Sie in unserem Leitfaden zur IoT-Automatisierung.
Häufig gestellte Fragen
Funktioniert das mit jedem Garagentorantrieb?
Es funktioniert mit Antrieben, die einen einfachen potenzialfreien Wandtaster akzeptieren, was die meisten Antriebe im Wohnbereich abdeckt. Antriebe mit digitalen Wandbedienteilen benötigen stattdessen eine Ersatz-Fernbedienung, die mit dem Relais verdrahtet wird.
Warum ein Reedkontakt, statt Befehle mitzuverfolgen?
Befehle können fehlschlagen, das Tor kann durch ein Hindernis gestoppt werden, oder jemand nutzt die normale Fernbedienung. Nur ein Sensor sagt Ihnen, wo das Tor tatsächlich steht.
Ist es sicher, ein Garagentor über MQTT zu steuern?
Es ist vertretbar, wenn Sie TLS, private Zugangsdaten und nicht retained Befehle verwenden und die eingebaute Sicherheitsumkehr des Antriebs beibehalten. Verbinden Sie niemals ein echtes Tor mit einem öffentlichen MQTT-Broker.
Kann ich einen zweiten Sensor für die vollständig geöffnete Position hinzufügen?
Ja. Der Sketch liest bereits einen optionalen Reedkontakt für die offene Position an GPIO 25, der aus „unknown“ einen eindeutigen Zustand „open“ macht.



