Un ouvre-porte de garage MQTT vous permet d'ouvrir, de fermer et surtout de vérifier votre porte de garage où que vous soyez, en utilisant le moteur que vous avez déjà. Dans ce tutoriel, vous allez relier un ESP32 à un relais qui « appuie » sur le bouton mural et à un capteur reed qui indique si la porte est réellement fermée, puis publier cet état sous forme de retained message MQTT pour que chaque application connaisse la vérité dès sa connexion.
Fonctionnement de l'ouvre-porte
Presque tous les moteurs de porte de garage résidentiels disposent de bornes pour un bouton-poussoir mural. Court-circuiter brièvement ces deux bornes revient à appuyer sur le bouton : la porte démarre, s'arrête ou repart en sens inverse selon sa position. Le côté matériel est donc simple et non invasif :
- Un relais câblé en parallèle du bouton mural produit un « appui » de 500 ms.
- Un capteur reed fixé sur le cadre, avec un aimant sur la porte, se ferme lorsque la porte est complètement fermée.
- L'ESP32 écoute les commandes, actionne le relais et publie l'état du capteur reed.
Le choix de conception essentiel est que l'ouvre-porte ne suppose jamais ce qu'a fait la porte. Il publie ce que voit le capteur. Une commande est une demande ; le capteur reed est le fait.
Liste du matériel
| Composant | Rôle |
|---|---|
| ESP32 DevKit | Wi-Fi et client MQTT |
| Module relais 1 canal compatible 3,3 V (ou module 5 V optocouplé) | Court-circuite les bornes du bouton mural |
| Capteur reed magnétique normalement ouvert, en saillie | Détecte la porte complètement fermée |
| Second capteur reed facultatif | Détecte la porte complètement ouverte |
| Alimentation USB 5 V et boîtier | Alimentation et protection contre la poussière |
| Fil de sonnette deux conducteurs | Relais vers les bornes du moteur, capteur reed vers l'ESP32 |
Avant de câbler quoi que ce soit, consultez le manuel de votre motorisation. Certains moteurs récents utilisent un panneau mural numérique plutôt qu'un contact sec ; ils nécessitent une interface compatible ou une télécommande de rechange dont le bouton est câblé au relais.
Câblage
| De | Vers | Remarques |
|---|---|---|
| IN du relais | GPIO 26 | Le niveau actif dépend de votre module |
| VCC / GND du relais | 5V / GND | Les modules optocouplés peuvent nécessiter un JD-VCC séparé |
| COM et NO du relais | Bornes du bouton mural sur le moteur | En parallèle du bouton existant |
| Capteur reed (position fermée) | GPIO 27 et GND | Utilise la résistance de pull-up interne |
| Capteur reed (position ouverte, facultatif) | GPIO 25 et GND | Utilise la résistance de pull-up interne |
Avec INPUT_PULLUP, un capteur reed fermé est lu LOW. Positionnez le capteur de position fermée de sorte que l'aimant ne se trouve à environ un centimètre que lorsque la porte est complètement baissée.
Conception des topics de l'ouvre-porte de garage MQTT
En suivant les conventions de notre guide sur la structure des topics MQTT pour la maison connectée :
<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
Retenir le topic d'état permet au tableau de bord de votre téléphone d'afficher « fermée » dès la connexion au lieu d'attendre le prochain changement. Ne jamais retenir le topic de commande garantit qu'une coupure de courant ne peut pas rejouer un ancien OPEN et ouvrir la porte toute seule.
Le sketch ESP32
Le sketch utilise PubSubClient. Réglez BENCH_TEST sur true pendant vos tests sur le serveur MQTT public gratuit avec une LED à la place du moteur ; passez-le à false pour votre broker privé avec TLS.
#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"; // random prefix, public area
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; // change to LOW for active-low modules
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"; // stopped halfway or the open sensor is missing
}
void pressButton() {
if (millis() - lastPressAt < 2000) return; // ignore rapid repeats
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 while open or CLOSE while closed is ignored on purpose
}
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 = ""; // force a fresh retained state
} 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 state
lastState = s;
}
}
}
Quelques détails à remarquer :
OPENn'actionne le relais que si la porte est lueclosed, etCLOSEque si elle est lueopen. Comme un appui fait basculer le moteur, envoyerOPENà une porte déjà ouverte la refermerait sinon.- Les appuis espacés de moins de deux secondes sont ignorés, ce qui empêche un double appui ou un message QoS 1 renvoyé d'inverser le mouvement de la porte.
- L'interrogation toutes les 200 ms fait office d'anti-rebond simple pour le capteur reed.
Tester sur l'établi
Câblez une LED avec une résistance sur la sortie du relais (ou écoutez simplement le clic du relais), laissez BENCH_TEST à true et flashez la carte. Puis, depuis un 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
Passez un aimant devant le capteur reed et observez le changement d'état. Débranchez l'ESP32 : une fois le délai de keep-alive écoulé, le broker publie offline sur le topic de disponibilité.
Ne connectez pas le vrai moteur de porte tant que vous utilisez le serveur public. Quiconque devine votre topic peut y lire et y publier. Passez d'abord à des identifiants privés.
Passer en service sur un broker privé
Réglez BENCH_TEST sur false, collez le certificat ISRG Root X1 (la racine Let's Encrypt) et renseignez le nom d'utilisateur, le mot de passe et le client ID générés dans le portail ConnectMQ. L'ouvre-porte se connecte alors via TLS sur le port 8883, et seuls les clients disposant de vos identifiants peuvent le commander. Notre article sur les bonnes pratiques de sécurité MQTT explique pourquoi identifiants et TLS ne sont pas négociables pour tout ce qui ouvre une porte.
Pour le piloter depuis Home Assistant, ajoutez une entité MQTT cover pointant vers les mêmes topics, ou suivez le guide Home Assistant MQTT :
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
Jeedom et Domoticz savent aussi communiquer en MQTT : ils peuvent s'abonner aux mêmes topics d'état et publier sur le topic de commande.
Check-list de sécurité
- Gardez branchées et fonctionnelles les sécurités propres au moteur (cellules photoélectriques, inversion automatique).
- Ne retenez jamais les messages de commande.
- N'agissez sur
OPEN/CLOSEque lorsque le capteur confirme l'état opposé. - Utilisez TLS et des identifiants privés avant de connecter le moteur.
- Ajoutez une notification lorsque la porte reste
openplus longtemps que prévu. - Montez le relais dans un boîtier, à l'écart des pièces en mouvement.
- Testez ce qui se passe si le Wi-Fi tombe en pleine course : la porte doit simplement terminer son mouvement.
Pour la notification « porte restée ouverte », les règles d'alerte par seuil du portail ConnectMQ peuvent signaler des valeurs sur un topic, ou une automatisation dans Home Assistant ou Node-RED peut surveiller un état open qui dure plus de dix minutes.
Dépannage
Le relais claque mais la porte ne bouge pas. Votre moteur utilise probablement un panneau mural numérique. Câblez plutôt le relais aux bornes du bouton d'une télécommande de rechange.
L'état oscille entre closed et unknown. L'aimant est trop éloigné du capteur reed ou la porte vibre. Rapprochez-les ou allongez l'anti-rebond.
La porte repart en sens inverse quand vous envoyez OPEN. Vous envoyez PRESS, ou le capteur de position fermée n'est pas lu LOW. Vérifiez le câblage du capteur reed avec le moniteur série.
L'appareil ne revient jamais en ligne. Vérifiez que le client ID est unique ; deux appareils avec le même identifiant s'éjectent mutuellement. Sur un broker privé, vérifiez aussi que vous utilisez exactement le client ID délivré avec vos identifiants, car les client IDs y sont liés.
Les commandes arrivent en retard ou en double. La QoS 1 garantit une livraison au moins une fois : un message renvoyé peut donc arriver après une reconnexion. Le verrouillage de deux secondes entre les appuis et les contrôles d'état dans onMessage rendent les doublons inoffensifs.
Pilotez votre garage en toute sécurité avec ConnectMQ
Un ouvre-porte mérite un broker privé et chiffré plutôt que le serveur public. ConnectMQ est un broker MQTT managé avec TLS, identifiants générés et un explorateur de topics en direct pour suivre l'état de votre porte. Créez un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire, passez BENCH_TEST à false et c'est en service. Pour en savoir plus sur l'hébergement, lisez notre article sur le broker MQTT dans le cloud, et découvrez d'autres projets comme la détection de fuite d'eau IoT dans notre guide de l'automatisation IoT.
Questions fréquentes
Cela fonctionne-t-il avec n'importe quel moteur de porte de garage ?
Cela fonctionne avec les moteurs qui acceptent un simple bouton mural à contact sec, ce qui couvre la plupart des motorisations résidentielles. Les moteurs équipés d'un panneau mural numérique nécessitent plutôt une télécommande de rechange câblée au relais.
Pourquoi utiliser un capteur reed plutôt que de suivre les commandes ?
Les commandes peuvent échouer, la porte peut être arrêtée par un obstacle, ou quelqu'un peut utiliser la télécommande habituelle. Seul un capteur indique où se trouve réellement la porte.
Est-il sûr de piloter une porte de garage via MQTT ?
C'est raisonnable si vous utilisez TLS, des identifiants privés, des commandes non retenues et si vous conservez l'inversion de sécurité intégrée au moteur. Ne connectez jamais une vraie porte au serveur MQTT public gratuit.
Puis-je ajouter un second capteur pour la position complètement ouverte ?
Oui. Le sketch lit déjà un capteur reed facultatif de position ouverte sur le GPIO 25, ce qui transforme « unknown » en un état « open » clair.



