Je domotise mon portail avec un MOES ZM-102-M Zigbee

Ce tutoriel complet explique le câblage précis, la configuration Zigbee2MQTT, l’intégration Home Assistant et Alexa. Un bouton unique dashboard + retour d’état réel + commande vocale « Alexa ouvre le portail ».

Mes trois objectifs domotisation portail

J’ai fixé trois objectifs précis pour domotiser mon portail battant Came équipé d’une carte de commande ZL180.

  • Un seul bouton sur le dashboard Home Assistant actionne le portail via une séquence impulsionnelle précise : contact sec ON pendant 500 ms, pause 500 ms minimum, puis OFF.
  • Retour d’état réel affichant si le portail est ouvert ou fermé à tout moment, grâce à un capteur de position.
  • Commande vocale simple avec Alexa : « Alexa, ouvre le portail » ou « Alexa, ferme le portail ».

Ce tutoriel remplace l’ancien utilisant le module QS-Zigbee-S10-C03 qui causait des déconnexions fréquentes du réseau Zigbee. Article obsolète : Domotisation QS-Zigbee-S10-C03.

Ma carte de commande Came ZL180

Mon portail battant fonctionne avec la carte électronique Came ZL180 qui gère tous les mouvements, les sécurités et les fins de course.

Notice technique officielle complète : Télécharger PDF ZL180.

Carte de commande ZL180 Came installée dans le boîtier

Borniers commande carte ZL180

Toutes les connexions domotiques se branchent sur les borniers en bas à droite de la carte ZL180. Ces 10 bornes permettent la commande du portail et la lecture des états.

Schéma identification borniers carte ZL180

Commande ouverture/fermeture portail

La carte ZL180 commande l’ouverture/fermeture par un contact sec (sans tension) entre les bornes 2 (COM) et 7 (IMP). Un contact sec signifie simplement fermer le circuit électrique sans appliquer de tension.

  • Fermer le contact bornes 2-7 pendant exactement 500 millisecondes (0,5 seconde).
  • Maintenir une pause d’au moins 500 ms avant nouvelle commande.
  • Ouvrir le contact (OFF) pour terminer l’impulsion.

Cette séquence impulsionnelle est obligatoire et décrite page 8 de la notice ZL180.

Extrait notice ZL180 séquence commande impulsionnelle bornes 2-7

Retour d’état ouvert/fermé portail

La carte ZL180 ne fournit pas de contact sec direct pour l’état du portail. Elle délivre un signal 24V entre les bornes 5 (COM) et 10 (OUV) quand le portail est totalement ouvert.

Extrait notice ZL180 signalisation 24V bornes 5-10

Pour convertir ce signal 0/24V en contact sec compatible domotique, j’installe un relais 24V IEC255 dans le boîtier Came. Le relais isole électriquement les circuits et crée un contact sec simple ouvert/fermé.

Schéma conversion 24V vers contact sec relais IEC255

Voici mon relais IEC255 monté sur support DIN dans le boîtier Came :

Relais IEC255 installé dans boîtier Came
Support DIN relais dans boîtier Came
Relais IEC255 utilisé pour conversion 24V/contact sec

Configuration DIP switches cruciale

Problème fréquent : certaines impulsions ne sont pas prises en compte. La cause est souvent la fonction « Stop » activée sur le DIP switch 2 de la carte ZL180. Cette fonction arrête le portail à chaque impulsion reçue.

Solution : positionner impérativement le DIP2 sur OFF pour permettre les commandes partielles (ouverture/fermeture normale).

Configuration DIP2=OFF carte Came ZL180

Mon choix module Zigbee MOES

J’ai testé plusieurs modules mais choisi le MOES ZM-102-M pour sa stabilité Zigbee, son prix abordable et ses fonctions complètes pour portail.

Le MOES ZM-102-M-MS inclut alimentation 230V, sortie impulsionnelle, entrée contact sec et capteur magnétique. Version ZM-102-M = module seul sans capteur.

Module MOES ZM-102-M connecteurs

Où acheter cet équipement ?

Voici le lien vers la page dédiée au ZM-102-M. J’y ai référencé les vendeurs et les prix.

Brochage précis MOES ZM-102-M

  • L et N : Alimentation 230V phase + neutre.
  • S4-S5 : Entrée contact sec (connecté au relais IEC255 pour état portail).
  • S1-S2 : Sortie impulsionnelle vers bornes 2-7 carte ZL180.
Schéma brochage MOES ZM-102-M
Connecteurs module MOES ZM-102-M

Schéma câblage complet portail

Schéma câblage complet portail Came + MOES ZM-102-M + relais 24V

J’appaire le module Zigbee2MQTT

Mise sous tension = mode appairage automatique (LED bleue clignote 10 min). Bouton appairage derrière le module. Placer temporairement près du coordinateur Zigbee si distance importante.

LED appairage module MOES ZM-102-M

Dans Zigbee2MQTT en mode « Permit Join », le module apparaît comme _TZE200_fabuwqzo_ts0601. Je le renomme « Portail Came ».

Interface Zigbee2MQTT appairage MOES ZM-102-M
Module renommé Portail Came Zigbee2MQTT

Fonctionnalités exposées MOES

Le module expose ces propriétés essentielles :

  • trigger (binary) : Envoie impulsion S1-S2. true=ouvrir, false=fermer. Intelligence : n’envoie pas si état déjà correct.
  • garage_door_contact (binary) : État S4-S5. true=fermé, false=ouvert.
  • countdown (0-43200s) : Impulsion forcée après délai.
  • run_time (-1 à 120s) : Timeout mouvement. Alarme si dépassé.
  • status : Normal / RunTimeAlarm / OpenTimeAlarm.
Interface Zigbee2MQTT complète Portail Came

Intégration automatique Home Assistant

Les entités apparaissent automatiquement dans Home Assistant après redémarrage ou actualisation Zigbee2MQTT.

Entités Home Assistant module Portail Came
  • binary_sensor.portail_came_garage_door_contact : État réel (off=fermé, on=ouvert).
  • switch.portail_came_trigger : Bouton impulsion (ON 500ms puis auto-OFF).
  • sensor.portail_came_status : Statut module.

Ma configuration Cover Portail

Je crée une entité Cover unifiée combinant l’état réel (binary_sensor) et la commande (switch). Un Cover Home Assistant représente tout élément ouvrable : portail, porte, volet roulant.

Ajouter dans configuration.yaml sous template → cover :

- cover:
  - name: Portail
    unique_id: cover.portail
    device_class: gate
    icon: >
      {% if is_state('binary_sensor.portail_came_garage_door_contact', 'off') %}
        mdi:gate
      {% else %}
        mdi:gate-open
      {% endif %}
    state: >
      {% if is_state('binary_sensor.portail_came_garage_door_contact', 'off') %}
        closed
      {% else %}
        open
      {% endif %}
    open_cover:
      - service: script.actionne_le_portail_toogle
    close_cover:
      - service: script.actionne_le_portail_toogle
Entité Cover Portail Home Assistant

Mes boutons dashboard portail

Bouton contrôle portail dashboard Home Assistant

Version simple button-card

Version simple bouton portail button-card
type: custom:button-card
show_name: false
tap_action:
  action: toggle
  entity: cover.portail
state:
  - value: closed
    color: gray
  - value: open
    color: red

Version avancée picture-elements

Bouton portail picture-elements intégré
Animation bouton portail ouverture
- type: custom:button-card
  color_type: card
  entity: cover.portail
  show_name: false
  tap_action:
    action: toggle
  state:
    - value: open
      color: "#4f010a"
      icon: mdi:gate-open
      styles:
        card:
        - animation: blink 2s ease infinite
    - operator: default
      color: "#49556c"
      icon: mdi:gate
      styles:
        card:
        - height: 110px
        - width: 110px
  style:
    top: 93%
    left: 5%

Alexa commande vocale portail

Exposer l’entité cover.portail vers Alexa pour contrôle vocal.

  1. Paramètres → Assistants vocaux → « x entité(s) à exposer ».
  2. Sélectionner cover.portail.
  3. Commandes : « Alexa, ouvre le portail », « Alexa, ferme le portail ».
Menu assistants vocaux Home Assistant
Exposition entités Alexa Home Assistant
Sélection cover.portail Alexa

Bonus impulsion visuelle

Animation impulsion visuelle confirmation portail

Confirmation visuelle immédiate de l’envoi d’impulsion par icône clignotante. Créer input_boolean.impulsion_portail via Paramètres → Appareils & Services → Helpers → Interrupteur.

Création input_boolean impulsion portail
type: custom:button-card
entity: input_boolean.impulsion_portail
name: Impulsion Portail
show_state: false
show_name: false
icon: mdi:access-point
styles:
  icon:
    - color: |
        [[[
          if (entity.state === 'on') return '#39FF14';
          return 'transparent';
        ]]]
    - animation: |
        [[[
          if (entity.state === 'on') return 'blink 0.4s linear infinite';
          return 'none';
        ]]]
  card:
    - width: 150px
    - height: 150px
    - border-radius: 12px
    - background-color: transparent
    - box-shadow: none

Script actionne_le_portail_toogle (à créer dans scripts.yaml) :

sequence:
  - service: switch.turn_on
    target:
      entity_id: switch.portail_came_trigger
  - service: input_boolean.turn_on
    target:
      entity_id: input_boolean.impulsion_portail
  - delay:
      seconds: 1
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.impulsion_portail
alias: Actionne le portail

Bonus Rustine ouverture

J’ai constaté, pour une raison qui m’échappe encore, qu’environ une fois sur vingt, la commande d’ouverture du portail se déclenche correctement : l’impulsion est bien envoyée au module, aucune erreur n’apparaît… mais rien ne se passe.

Tout laisse penser que le module est en veille au moment de la commande et qu’il ne réagit tout simplement pas.

En revanche, si je renvoie une seconde impulsion dans les secondes qui suivent, le portail s’ouvre immédiatement.

Habituellement, je suis plutôt allergique aux “rustines”. J’aime comprendre et corriger le problème à la source. Mais dans ce cas précis, la solution la plus pragmatique m’a semblé être d’ajouter un mécanisme de rattrapage.

L’idée est simple :
si, après une commande d’ouverture, le portail est toujours détecté comme fermé au bout de quelques secondes, alors le script renvoie automatiquement une seconde impulsion.

Au pire, on perd 2 secondes.
Au mieux, on corrige un aléa invisible pour l’utilisateur.

J’ai donc mis en place le script suivant :

sequence:
  - alias: Enregistre l'état du portail avant impulsion
    variables:
      etat_portail_avant: "{{ states('binary_sensor.portail_came_garage_door_contact') }}"
  - alias: Envoie l'impulsion au portail
    action: switch.toggle
    target:
      entity_id: switch.portail_came_trigger
    data: {}
  - parallel:
      - alias: Fait clignoter l'envoi d'impulsion sur Dashboard
        sequence:
          - action: input_boolean.turn_on
            target:
              entity_id: input_boolean.impulsion_portail
            data: {}
          - delay:
              seconds: 1
          - action: input_boolean.turn_off
            target:
              entity_id: input_boolean.impulsion_portail
            data: {}
      - alias: Rustine uniquement si le portail était fermé
        sequence:
          - if:
              - condition: template
                value_template: "{{ etat_portail_avant == 'off' }}"
            then:
              - alias: Attend maximum 2s que le portail passe à ouvert
                wait_template: >-
                  {{ is_state('binary_sensor.portail_came_garage_door_contact',
                  'on') }}
                timeout:
                  seconds: 2
                continue_on_timeout: true
              - if:
                  - condition: template
                    value_template: "{{ not wait.completed }}"
                then:
                  - alias: Relance l'impulsion si le portail n'a pas réagi
                    action: switch.toggle
                    target:
                      entity_id: switch.portail_came_trigger
                    data: {}
alias: Actionne le portail
description: ""

Ce script met en place un mécanisme simple de vérification après l’envoi d’une impulsion au portail, avec une logique de rattrapage en cas de problème.

La première étape consiste à mémoriser l’état du portail avant toute action. On enregistre s’il est ouvert ou fermé au moment où la commande est envoyée (binary_sensor.portail_came_garage_door_contact). Cette information est importante, car elle permet de savoir ensuite si l’on doit activer ou non la logique de secours.

Une fois cet état sauvegardé, le script envoie l’impulsion au portail via le module (switch.portail_came_trigger), exactement comme dans le fonctionnement normal. En parallèle, un petit indicateur visuel est activé pendant une seconde (input_boolean.impulsion_portail), simplement pour matérialiser l’envoi de l’impulsion sur le tableau de bord.

C’est ensuite que la “rustine” entre en jeu, mais uniquement dans un cas bien précis : si le portail était fermé au moment de la commande. Cette précaution évite des effets indésirables, notamment si le portail est en train de se fermer, car dans ce cas il peut mettre plusieurs secondes à réagir et il ne faut surtout pas renvoyer une impulsion.

Si le portail était bien fermé, le script attend alors jusqu’à deux secondes pour voir s’il passe à l’état “ouvert” (binary_sensor.portail_came_garage_door_contact). Cette attente est active : si le changement se produit rapidement, le script le détecte immédiatement et s’arrête là.

En revanche, si rien ne se passe pendant ces deux secondes, on considère que l’impulsion initiale n’a pas été prise en compte, probablement à cause d’un module encore en veille. Le script envoie alors automatiquement une seconde impulsion via le module (switch.portail_came_trigger).

Au final, ce mécanisme agit comme un filet de sécurité. Dans la majorité des cas, il ne sert à rien et reste invisible. Mais dans les rares situations où le portail ne réagit pas, il permet de corriger le problème sans intervention manuelle, avec un simple délai de deux secondes.

Documentation technique complète

Forum échanges retours expérience

Questions, retours d’expérience, schémas complémentaires : Discussion forum HACF.