Automatisation IoT

Ouvre-porte de garage MQTT fait maison avec ESP32, relais et capteur reed

Rendez intelligent le moteur de porte de garage que vous possédez déjà grâce à un ESP32, un relais qui appuie sur le bouton mural à votre place et un capteur reed qui publie l'état réel de la porte sous forme de retained message MQTT.

Ouvre-porte de garage MQTT réalisé avec un ESP32, un module relais et un capteur reed magnétique fixé sur le cadre de la porte
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

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 :

  • OPEN n'actionne le relais que si la porte est lue closed, et CLOSE que si elle est lue open. Comme un appui fait basculer le moteur, envoyer OPEN à 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é

  1. Gardez branchées et fonctionnelles les sécurités propres au moteur (cellules photoélectriques, inversion automatique).
  2. Ne retenez jamais les messages de commande.
  3. N'agissez sur OPEN/CLOSE que lorsque le capteur confirme l'état opposé.
  4. Utilisez TLS et des identifiants privés avant de connecter le moteur.
  5. Ajoutez une notification lorsque la porte reste open plus longtemps que prévu.
  6. Montez le relais dans un boîtier, à l'écart des pièces en mouvement.
  7. 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.

Articles liés

Guide d'installation de Zigbee2MQTT : du coordinateur au tableau de bord

Installez Zigbee2MQTT avec Docker, configurez le coordinateur et la connexion MQTT, appairez et renommez les appareils, pilotez-les via MQTT et affichez leurs états sur un tableau de bord, en testant d'abord sur le serveur MQTT public gratuit.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.