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.

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.

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.

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.

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é.

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



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).

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.
- IOMZB-110 FRIENT : Excellent mais 60€.
- Smart Switch ZG-005-RF : 4 sorties à 18€ mais pas d’entrée.
- NODON SIN-4-1-20 : Pas d’entrée contact sec.
- MOES ZM-102-M choisi à 17,90€.
- QS-Zigbee-S10-C03 : Déconnexions fréquentes, abandonné.
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.

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 câblage complet portail

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.

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


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.

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

- 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

Mes boutons dashboard portail

Version simple 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


- 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.
- Paramètres → Assistants vocaux → « x entité(s) à exposer ».
- Sélectionner
cover.portail. - Commandes : « Alexa, ouvre le portail », « Alexa, ferme le portail ».



Bonus impulsion visuelle

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.

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.
