Protocole Push ZKTeco expliqué : pourquoi c'est essentiel pour la pointeuse cloud
Les appareils ZKTeco supportent deux modes de connexion : pull (SDK) et push (cloud). Découvrez comment le mode push élimine les IP statiques, les serveurs locaux et le polling — et comment recevoir les données de pointage en temps réel via une API REST.
Introduction
Vous avez acheté un appareil ZKTeco. Vous l'avez connecté au réseau. Maintenant vous devez récupérer les données de pointage dans votre application cloud. La question est : l'appareil vous envoie-t-il les données, ou allez-vous les chercher sur l'appareil ?
Cette décision architecturale — push vs. pull — détermine si votre intégration fonctionne de manière fiable à grande échelle ou casse dès que vous ajoutez un deuxième bureau. La plupart des développeurs commencent par l'approche pull (bibliothèques SDK), se heurtent à un mur, puis découvrent que le mode push existe. À ce stade, ils ont déjà perdu des semaines.
Cet article explique ce qu'est le mode push, pourquoi il existe, comment il se compare à l'approche SDK, et comment obtenir des données de pointage en temps réel sans toucher aux protocoles bruts des appareils.
Mode Pull : l'approche SDK (et pourquoi ça casse)
La méthode traditionnelle pour récupérer les données d'un appareil ZKTeco est le mode pull. Votre serveur se connecte à l'appareil sur le réseau local, s'authentifie et demande les enregistrements. Des bibliothèques comme pyzk, node-zklib et zklib fonctionnent toutes de cette façon.
Ça paraît simple au début. Écrire un script, se connecter à l'IP de l'appareil, appeler get_attendance(), c'est fait. Mais la simplicité est trompeuse.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 340" fill="none" style="width:100%;max-width:800px;">
<text x="400" y="25" text-anchor="middle" fill="#94a3b8" font-size="17" font-weight="bold" font-family="system-ui">Mode Pull : le serveur se connecte à l'appareil</text>
<rect x="40" y="70" width="180" height="80" rx="12" stroke="#f87171" stroke-width="2" fill="none"/>
<text x="130" y="105" text-anchor="middle" fill="#f87171" font-size="15" font-family="system-ui">💻 Votre serveur</text>
<text x="130" y="127" text-anchor="middle" fill="#f87171" font-size="14" font-family="system-ui">(doit être sur le LAN)</text>
<line x1="220" y1="110" x2="340" y2="110" stroke="#64748b" stroke-width="2" marker-end="url(#ppArrowFr)"/>
<text x="280" y="98" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">connexion + polling</text>
<rect x="340" y="70" width="180" height="80" rx="12" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="430" y="105" text-anchor="middle" fill="#22d3ee" font-size="15" font-family="system-ui">🖐 Appareil ZKTeco</text>
<text x="430" y="127" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">(IP statique requise)</text>
<rect x="40" y="190" width="680" height="130" rx="10" stroke="#f87171" stroke-width="1.5" fill="none" stroke-dasharray="6,4"/>
<text x="60" y="215" fill="#f87171" font-size="15" font-weight="bold" font-family="system-ui">⚠ Limites du mode Pull :</text>
<text x="60" y="240" fill="#94a3b8" font-size="14" font-family="system-ui">• Le serveur doit être sur le même réseau que l'appareil (pas d'apps cloud)</text>
<text x="60" y="262" fill="#94a3b8" font-size="14" font-family="system-ui">• L'appareil nécessite une IP statique — un changement DHCP casse la connexion</text>
<text x="60" y="284" fill="#94a3b8" font-size="14" font-family="system-ui">• Le polling crée des retards (1-5 min) et du gaspillage de bande passante</text>
<text x="60" y="306" fill="#94a3b8" font-size="14" font-family="system-ui">• Chaque appareil = une connexion. 50 appareils = 50 threads qui pollent en continu</text>
<defs>
<marker id="ppArrowFr" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#64748b"/></marker>
</defs>
</svg>
Voici ce qui se passe mal en production :
- Votre application tourne dans le cloud. AWS, OVH, Scaleway, Railway — aucun de ces services ne peut atteindre un appareil derrière un routeur sur un LAN d'entreprise. Il vous faut un serveur local qui tourne 24h/24 comme pont.
- Les appareils changent d'IP. L'informatique réinitialise le routeur, le bail DHCP expire, quelqu'un débranche le switch. Votre chaîne de connexion est maintenant fausse, et vous ne recevez plus de données tant que personne ne s'en aperçoit.
- Le polling n'est pas temps réel. Vous demandez à l'appareil « des nouveaux enregistrements ? » toutes les 30 secondes. C'est de la bande passante gaspillée sur des réponses vides 95% du temps.
- Ça ne passe pas à l'échelle. Gérer des connexions persistantes vers 50+ appareils dans plusieurs bureaux ? C'est un job à plein temps.
Le mode pull fonctionne pour un seul appareil sur un LAN. Dès que vous passez en multi-sites ou en cloud, il vous faut le mode push.
Mode Push : l'appareil se connecte à vous
Le mode push inverse la direction de connexion. L'appareil initie la connexion vers un serveur cloud, pas l'inverse. L'appareil n'a pas besoin d'IP statique. Votre serveur n'a pas besoin d'être sur le même réseau. L'appareil a juste besoin d'un accès internet.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 320" fill="none" style="width:100%;max-width:800px;">
<text x="400" y="25" text-anchor="middle" fill="#94a3b8" font-size="17" font-weight="bold" font-family="system-ui">Mode Push : l'appareil se connecte au cloud</text>
<rect x="20" y="60" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="88" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Bureau A</text>
<text x="105" y="108" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(DHCP — IP quelconque)</text>
<rect x="20" y="145" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="173" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Bureau B</text>
<text x="105" y="193" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(Réseau différent)</text>
<rect x="20" y="230" width="170" height="65" rx="10" stroke="#22d3ee" stroke-width="2" fill="none"/>
<text x="105" y="258" text-anchor="middle" fill="#22d3ee" font-size="14" font-family="system-ui">🖐 Bureau C</text>
<text x="105" y="278" text-anchor="middle" fill="#64748b" font-size="12" font-family="system-ui">(Derrière NAT)</text>
<line x1="190" y1="92" x2="310" y2="160" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Fr)"/>
<line x1="190" y1="177" x2="310" y2="170" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Fr)"/>
<line x1="190" y1="262" x2="310" y2="180" stroke="#34d399" stroke-width="2" marker-end="url(#ppArrow2Fr)"/>
<text x="260" y="140" text-anchor="middle" fill="#34d399" font-size="13" font-family="system-ui">push</text>
<rect x="310" y="130" width="190" height="80" rx="12" stroke="#a78bfa" stroke-width="2" fill="none"/>
<text x="405" y="165" text-anchor="middle" fill="#a78bfa" font-size="15" font-family="system-ui">☁️ Moteur de</text>
<text x="405" y="187" text-anchor="middle" fill="#a78bfa" font-size="15" font-family="system-ui">protocole cloud</text>
<line x1="500" y1="170" x2="580" y2="170" stroke="#64748b" stroke-width="2" marker-end="url(#ppArrow2Fr)"/>
<text x="540" y="158" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">API REST</text>
<rect x="580" y="130" width="190" height="80" rx="12" stroke="#34d399" stroke-width="2" fill="none"/>
<text x="675" y="165" text-anchor="middle" fill="#34d399" font-size="15" font-family="system-ui">💻 Votre App</text>
<text x="675" y="187" text-anchor="middle" fill="#34d399" font-size="14" font-family="system-ui">(N'importe où)</text>
<defs>
<marker id="ppArrow2Fr" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#34d399"/></marker>
</defs>
</svg>
En mode push, c'est l'appareil qui fait le gros du travail. Il se connecte vers le cloud en sortant, envoie les données de pointage en temps réel, reçoit des commandes (synchroniser l'heure, inscrire des employés, redémarrer), et rapporte son statut — tout cela sans que votre serveur n'ait jamais besoin d'initier une connexion.
Pourquoi le mode Push gagne
| Facteur | Pull (SDK) | Push (Cloud) |
|---------|-----------|--------------|
| Réseau requis | Même LAN | Internet uniquement |
| IP de l'appareil | Statique requise | N'importe laquelle (DHCP OK) |
| Latence | 30s–5min de polling | Temps réel (<1s) |
| Apps cloud | ❌ Pont local nécessaire | ✅ Natif |
| Multi-sites | ❌ VPN par site | ✅ Tout converge vers un point |
| Passage à l'échelle | 1 thread par appareil | Événementiel, sans polling |
| Pare-feu | Ports entrants ouverts | Sortant uniquement |
La partie difficile : construire un serveur de protocole push
C'est là que la plupart des équipes coincent. Le mode push est meilleur, mais implémenter le serveur qui reçoit les données push est complexe. L'appareil parle un protocole propriétaire. Il faut :
- Analyser correctement le handshake de connexion de l'appareil
- Gérer l'authentification et l'enregistrement des appareils
- Traiter les enregistrements de pointage dans le format brut
- Mettre en file d'attente et délivrer les commandes aux appareils
- Gérer l'état de connexion de dizaines d'appareils simultanément
- Gérer les reconnexions, les timeouts et la déduplication
Ce n'est pas un projet de week-end. Construire un serveur de protocole push en production a nécessité des mois de travail à notre équipe et des milliers d'heures de tests avec 80+ appareils sur le terrain.
L'approche middleware : protocole en entrée, API REST en sortie
PunchConnect se place entre vos appareils et votre application. Les appareils poussent les données vers le moteur de protocole de PunchConnect. Vous consommez des endpoints REST API et des webhooks propres. Vous ne touchez jamais au protocole brut.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 260" fill="none" style="width:100%;max-width:800px;">
<text x="400" y="25" text-anchor="middle" fill="#94a3b8" font-size="17" font-weight="bold" font-family="system-ui">PunchConnect : couche d'abstraction de protocole</text>
<rect x="20" y="60" width="200" height="170" rx="12" stroke="#f87171" stroke-width="1.5" fill="none" stroke-dasharray="6,4"/>
<text x="120" y="85" text-anchor="middle" fill="#f87171" font-size="14" font-weight="bold" font-family="system-ui">Vous ne touchez pas ça</text>
<text x="120" y="110" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">Handshake de l'appareil</text>
<text x="120" y="130" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">Parsing du protocole brut</text>
<text x="120" y="150" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">File d'attente des commandes</text>
<text x="120" y="170" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">Gestion des connexions</text>
<text x="120" y="190" text-anchor="middle" fill="#64748b" font-size="13" font-family="system-ui">Retry + déduplication</text>
<text x="120" y="215" text-anchor="middle" fill="#f87171" font-size="13" font-family="system-ui">⬅ PunchConnect gère</text>
<line x1="220" y1="145" x2="290" y2="145" stroke="#a78bfa" stroke-width="2" marker-end="url(#ppArrow3Fr)"/>
<rect x="290" y="90" width="180" height="110" rx="12" stroke="#a78bfa" stroke-width="2" fill="none"/>
<text x="380" y="125" text-anchor="middle" fill="#a78bfa" font-size="16" font-weight="bold" font-family="system-ui">PunchConnect</text>
<text x="380" y="148" text-anchor="middle" fill="#a78bfa" font-size="14" font-family="system-ui">Protocole → REST</text>
<text x="380" y="170" text-anchor="middle" fill="#a78bfa" font-size="14" font-family="system-ui">Moteur de conversion</text>
<line x1="470" y1="145" x2="540" y2="145" stroke="#a78bfa" stroke-width="2" marker-end="url(#ppArrow3Fr)"/>
<rect x="540" y="60" width="230" height="170" rx="12" stroke="#34d399" stroke-width="2" fill="none"/>
<text x="655" y="85" text-anchor="middle" fill="#34d399" font-size="14" font-weight="bold" font-family="system-ui">Vous travaillez avec ça</text>
<text x="655" y="110" text-anchor="middle" fill="#94a3b8" font-size="13" font-family="system-ui">GET /api/attendance</text>
<text x="655" y="130" text-anchor="middle" fill="#94a3b8" font-size="13" font-family="system-ui">GET /api/devices</text>
<text x="655" y="150" text-anchor="middle" fill="#94a3b8" font-size="13" font-family="system-ui">POST /api/employees</text>
<text x="655" y="170" text-anchor="middle" fill="#94a3b8" font-size="13" font-family="system-ui">Événements webhook</text>
<text x="655" y="190" text-anchor="middle" fill="#94a3b8" font-size="13" font-family="system-ui">JSON partout</text>
<text x="655" y="215" text-anchor="middle" fill="#34d399" font-size="13" font-family="system-ui">⬅ Votre code utilise ça</text>
<defs>
<marker id="ppArrow3Fr" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#a78bfa"/></marker>
</defs>
</svg>
Obtenir les données de pointage en temps réel (exemples de code)
Une fois votre appareil configuré dans le tableau de bord PunchConnect (environ 5 minutes), vous interagissez exclusivement avec l'API REST :
Récupérer les enregistrements de pointage
# Obtenir les événements de pointage d'aujourd'huicurl -X GET "https://api.punchconnect.com/v1/attendance?from=2026-03-27T00:00:00Z" \-H "Authorization: Bearer VOTRE_CLE_API" \-H "Content-Type: application/json"
Python — Récupérer et traiter le pointage
import requestsfrom datetime import datetime, timezoneAPI_KEY = "VOTRE_CLE_API"BASE_URL = "https://api.punchconnect.com/v1"def get_attendance(from_date: str = None):"""Récupère les enregistrements de pointage depuis PunchConnect."""params = {}if from_date:params["from"] = from_dateresponse = requests.get(f"{BASE_URL}/attendance",headers={"Authorization": f"Bearer {API_KEY}"},params=params,)response.raise_for_status()return response.json()["data"]def sync_vers_votre_systeme(records):"""Envoie les enregistrements de pointage vers votre système RH."""for record in records:print(f"[{record['punch_time']}] "f"{record['employee_id']} — "f"{record['punch_type']} "f"({record['verify_mode']})")if __name__ == "__main__":today = datetime.now(timezone.utc).strftime("%Y-%m-%dT00:00:00Z")records = get_attendance(from_date=today)print(f"{len(records)} enregistrements récupérés")sync_vers_votre_systeme(records)
JavaScript — Écouter les webhooks en temps réel
import express from "express";const app = express();app.use(express.json());app.post("/webhook/attendance", (req, res) => {const event = req.body;console.log(`Nouveau pointage : ${event.employee_id} à ${event.punch_time}`);console.log(` Type : ${event.punch_type} | Méthode : ${event.verify_mode}`);console.log(` Appareil : ${event.device_serial}`);res.status(200).json({ received: true });});app.listen(3000, () => {console.log("Listener webhook en écoute sur le port 3000");});
Quels appareils ZKTeco supportent le mode push ?
La plupart des appareils ZKTeco modernes supportent le mode push. Tout appareil avec le firmware ZMM (la majorité des appareils fabriqués après 2015) a cette capacité. Cela inclut :
- Reconnaissance faciale : SpeedFace V5L, SpeedFace-H5, ProFace X
- Empreinte digitale : UA860, K40, IN01-A, X7
- Multi-modal : SpeedFace V4L, MultiBio 800
- Contrôle d'accès : inBio 160/260, C3-100/200/400
Comment vérifier : Cherchez le réglage « Cloud Server » ou « ADMS Server » dans le menu de configuration réseau de votre appareil. S'il est là, votre appareil supporte le mode push.
Mode push en entreprise française : conformité RGPD
Pour les déploiements en France et dans l'UE, le mode push présente un avantage conformité important : les données biométriques transitent directement de l'appareil vers le cloud, sans serveur intermédiaire local qui ajouterait un point de stockage supplémentaire soumis aux exigences RGPD et CNIL.
PunchConnect chiffre toutes les données en transit (TLS 1.3) et ne stocke que les données nécessaires au fonctionnement du service, conformément au principe de minimisation des données du RGPD.
Questions fréquentes sur le mode push
Faut-il ouvrir des ports pare-feu pour le mode push ?
Non. Le mode push utilise des connexions sortantes depuis l'appareil, comme un navigateur web. Si votre appareil peut accéder à internet, il peut pousser les données. Aucun port entrant, aucune IP statique, aucune redirection de port nécessaire.
Quelle est la latence en temps réel du mode push ?
Moins d'une seconde. Quand un employé pointe sur l'appareil, l'événement atteint PunchConnect et déclenche votre webhook en moins d'une seconde. Comparé au polling SDK (30 secondes à 5 minutes), le mode push est pratiquement instantané.
Que se passe-t-il si internet coupe ?
L'appareil stocke localement. Les appareils ZKTeco gardent les enregistrements en mémoire embarquée (généralement 50 000 à 100 000 enregistrements). Quand la connectivité revient, l'appareil pousse automatiquement tous les enregistrements en tampon. PunchConnect les déduplique pour éviter les doublons.
Peut-on envoyer des commandes aux appareils en mode push ?
Oui. PunchConnect met en file d'attente les commandes (inscrire des employés, synchroniser l'heure, redémarrer, mettre à jour les réglages) et les délivre à l'appareil au prochain cycle push. Vous envoyez les commandes via l'API REST, PunchConnect gère la livraison.
Le mode push est-il compatible avec tous les modèles ZKTeco ?
Le mode push fonctionne avec tout appareil ZKTeco ayant le réglage « Cloud Server » ou « ADMS Server » — soit la grande majorité des appareils fabriqués après 2015. Les anciens appareils (pré-2015) ne supportent que le mode pull, mais ils sont de plus en plus rares en déploiement actif.
Pour commencer
Si vous construisez une intégration biométrique et hésitez entre push et pull :
1. Commencez par le mode push. C'est la bonne architecture pour toute application cloud.
2. Ne construisez pas le serveur de protocole vous-même — sauf si vous avez des mois devant vous et une expérience approfondie des protocoles ZKTeco.
3. Essayez PunchConnect gratuitement pendant 7 jours — enregistrez votre appareil, obtenez votre clé API, et recevez votre premier webhook de pointage en moins de 15 minutes. Sans carte bancaire.
Si vous utilisez déjà une bibliothèque SDK et rencontrez des problèmes de passage à l'échelle, lisez notre comparaison : Pourquoi les bibliothèques open-source ZKTeco ne passent pas à l'échelle. Et si votre principal blocage est l'IP statique, consultez Pointage biométrique sans IP statique.
---
*PunchConnect est un middleware éprouvé en production qui connecte les appareils biométriques ZKTeco à n'importe quel système logiciel. Actuellement utilisé pour le pointage de 24 000+ employés sur 50+ sites.*
Articles connexes
Pourquoi les bibliothèques open-source ZKTeco ne passent pas à l'échelle (et quoi utiliser à la place)
9 min read
TutorialConnecter ZKTeco à Odoo : L'Approche API Cloud (Sans VPN, Sans Logiciel Local)
10 min read
GuidePointage Biométrique Sans IP Fixe : Comment les API Cloud Libèrent Vos Déploiements
11 min read