Une alternative à AWS IoT TwinMaker a tout son sens lorsque vous voulez des jumeaux numériques 3D interactifs tout en préférant les formats ouverts, les protocoles standard et la liberté de tourner n'importe où. Ce guide compare les alternatives réalistes, des autres plateformes aux stacks web entièrement ouvertes, puis présente la technique centrale : lier des données MQTT en direct aux nœuds d'un modèle glTF dans le navigateur. Vous repartirez avec un schéma fonctionnel que vous pourrez étendre en un jumeau 3D complet.
Pour le contexte général sur les jumeaux, consultez le guide de la technologie du jumeau numérique.
Ce que TwinMaker regroupe
AWS IoT TwinMaker combine plusieurs éléments dont un jumeau 3D a besoin :
- Des entités et des composants qui modélisent vos actifs et les relient à des sources de données.
- Des connecteurs vers d'autres services de données AWS pour les séries temporelles, la vidéo et les documents.
- Un éditeur de scènes pour placer des modèles 3D et y attacher des étiquettes et des règles de couleur pilotées par les données.
- Une visualisation via un plugin Grafana ou un kit applicatif pour des applications web sur mesure.
Lorsque vos données se trouvent déjà dans ces services AWS, c'est pratique. La contrepartie est que le jumeau, ses scènes et ses liaisons de données s'expriment dans des concepts propres au service. Passer à un autre cloud, ou au réseau d'une usine sur site, implique de tout reconstruire. Les feuilles de route des plateformes évoluent aussi avec le temps : vérifiez donc le statut actuel de tout service de jumeau managé avant d'y engager un projet de longue durée.
Ce dont un jumeau 3D portable a besoin
Au-delà des marques, tout jumeau 3D comporte les mêmes cinq couches :
| Couche | Rôle | Options portables |
|---|---|---|
| Géométrie | Le modèle 3D de l'usine ou de la machine | glTF/GLB exporté depuis la CAO ou Blender |
| Rendu | Afficher la scène et interagir avec elle dans un navigateur | Three.js, Babylon.js, CesiumJS pour le géospatial |
| Données en direct | Transmettre les valeurs actuelles à la scène | MQTT sur WebSocket sécurisé |
| Liaison | Associer les champs de données aux nœuds, couleurs, étiquettes, animations | Un petit fichier de mapping JSON plus votre code |
| Historique | Tendances, relecture, analyses | Base de séries temporelles plus Grafana ou vos propres graphiques |
Chaque couche dispose de choix ouverts et matures, et chacune peut être remplacée sans toucher aux autres. C'est cette indépendance qui constitue la vraie réponse à la dépendance fournisseur.
Comparaison des alternatives
| Approche | Création 3D | Chemin des données | Dépendance | Effort |
|---|---|---|---|---|
| Autres services de jumeau cloud | Éditeur de scènes du fournisseur | Services IoT et données du fournisseur | Forte | Faible à moyen |
| Moteurs de jeu (Unity, Unreal) | Éditeur complet du moteur | Plugins ou clients MQTT sur mesure | Moyenne (licences du moteur, runtimes) | Moyen à élevé |
| Three.js + MQTT | Code, glTF depuis n'importe quel outil | MQTT sur WSS directement dans le navigateur | Faible | Moyen |
| Babylon.js + MQTT | Code plus outils Babylon | MQTT sur WSS | Faible | Moyen |
| Grafana + panneaux + base alimentée par MQTT | 3D limitée, graphiques puissants | Telegraf ou un abonné écrit dans une base | Faible | Faible |
Les moteurs de jeu excellent pour la formation photoréaliste et la VR ; consultez le guide du jumeau numérique Unity. Pour des tableaux de bord d'exploitation que chacun peut ouvrir dans un navigateur, les bibliothèques web conviennent généralement mieux. Le guide du jumeau numérique 3D web compare Three.js et Babylon.js plus en détail.
Lier des données MQTT à un modèle glTF
Le cœur de tout remplaçant de TwinMaker est la couche de liaison : « quand ce topic change, mettre à jour ce nœud 3D ». Gardez la liaison dans les données, pas dans le code, pour que des non-développeurs puissent la maintenir.
Voici un fichier de mapping. Chaque entrée relie un topic et un champ du payload à un nœud nommé de la scène glTF et indique quoi faire de la valeur :
[
{ "topic": "furnace1/state", "field": "temp_c", "node": "Furnace_Body",
"action": "color", "ranges": [[0, 600, "#4caf50"], [600, 900, "#ff9800"], [900, 2000, "#f44336"]] },
{ "topic": "conveyor1/state", "field": "running", "node": "Conveyor_Belt",
"action": "visible-flag" },
{ "topic": "tank3/state", "field": "level_pct", "node": "Tank3_Liquid",
"action": "scale-y", "max": 100 }
]
Et le module navigateur qui l'applique. Installez three et mqtt avec npm et empaquetez avec Vite ou un outil équivalent. Le modèle plant.glb doit contenir des nœuds portant les noms utilisés dans le mapping.
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import mqtt from "mqtt";
import bindings from "./bindings.json";
const PREFIX = "connectmq/demo/tm-alt-2h7/site1";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 500);
camera.position.set(20, 15, 20);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
new OrbitControls(camera, renderer.domElement);
scene.add(new THREE.HemisphereLight(0xffffff, 0x404040, 3));
const nodes = {};
new GLTFLoader().load("/plant.glb", (gltf) => {
scene.add(gltf.scene);
for (const b of bindings) {
const obj = gltf.scene.getObjectByName(b.node);
if (!obj) { console.warn("Missing node", b.node); continue; }
obj.traverse((o) => { if (o.isMesh) o.material = o.material.clone(); });
nodes[b.node] = obj;
}
});
function apply(b, value) {
const obj = nodes[b.node];
if (!obj) return;
if (b.action === "color") {
const hit = b.ranges.find(([lo, hi]) => value >= lo && value < hi);
if (hit) obj.traverse((o) => o.isMesh && o.material.color.set(hit[2]));
} else if (b.action === "visible-flag") {
obj.traverse((o) => o.isMesh && o.material.emissive?.set(value ? 0x224422 : 0x000000));
} else if (b.action === "scale-y") {
obj.scale.y = Math.max(0.01, value / b.max);
}
}
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId: "tm-alt-2h7-view-" + Math.random().toString(16).slice(2, 8),
protocolVersion: 5,
});
client.on("connect", () => client.subscribe(`${PREFIX}/+/state`));
client.on("message", (topic, payload) => {
const rel = topic.slice(PREFIX.length + 1);
const data = JSON.parse(payload.toString());
for (const b of bindings) if (b.topic === rel && b.field in data) apply(b, data[b.field]);
});
renderer.setAnimationLoop(() => renderer.render(scene, camera));
Testez-le en publiant des états retenus sur le serveur MQTT public gratuit, réservé aux tests et aux données factices :
mosquitto_pub -h broker.connectmq.com -p 1883 -i tm-alt-2h7-pub -r \
-t "connectmq/demo/tm-alt-2h7/site1/furnace1/state" -m '{"temp_c":935}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i tm-alt-2h7-pub2 -r \
-t "connectmq/demo/tm-alt-2h7/site1/tank3/state" -m '{"level_pct":62}'
Comme les états sont retenus, la scène affiche les bonnes couleurs et les bons niveaux dès son chargement, puis se met à jour en direct. C'est la même expérience qu'offre un éditeur de scènes managé, construite à partir de briques ouvertes. Le guide pour lier des données IoT à un modèle 3D couvre d'autres actions comme les animations, les étiquettes et le clignotement des alarmes, et la documentation de Three.js fait référence pour la partie rendu.
Les pièges quand on quitte un service de jumeau managé
- Les noms de nœuds dérivent. Réexporter un modèle CAO peut renommer des nœuds et casser silencieusement les liaisons. Journalisez les nœuds manquants au chargement, comme le fait le code ci-dessus, et gardez des noms stables dans votre chaîne d'export.
- Les matériaux partagés. En glTF, de nombreux maillages partagent souvent un même matériau : colorer un nœud les colore tous. Clonez les matériaux des nœuds liés.
- Les modèles lourds. Les exports CAO peuvent être énormes. Décimez la géométrie, fusionnez les maillages statiques et utilisez du glTF compressé pour garder des temps de chargement raisonnables.
- L'historique est à part. Les données MQTT en direct pilotent la scène, mais les tendances et la relecture nécessitent une base de données. Abonnez un service d'écriture ou Telegraf aux mêmes topics.
- Les identifiants côté navigateur. Tout ce qui est livré à un navigateur peut être lu par son utilisateur. Donnez aux visionneuses des identifiants orientés lecture, distincts de ceux des passerelles qui publient.
- L'état manquant au premier chargement. Si les passerelles ne publient que les changements, une scène fraîchement ouverte reste vide jusqu'à ce que quelque chose change. Publiez des messages d'état complets avec le flag retain pour que chaque visionneuse parte de l'image actuelle.
- Le rendu à chaque message. Une télémétrie à haute fréquence peut déclencher plus de mises à jour de scène que l'écran ne peut en afficher. Stockez les dernières valeurs à l'arrivée des messages et appliquez-les une fois par image d'animation.
Un chemin de migration en quatre étapes
Si vous remplacez un jumeau managé existant plutôt que de partir de zéro, avancez par petites étapes réversibles :
- Exportez vos assets 3D en glTF et vérifiez les noms de nœuds nécessaires aux liaisons.
- Faites publier les passerelles vers un broker MQTT en parallèle du chemin de données existant.
- Reconstruisez les liaisons de scène sous forme de fichier de mapping et comparez côte à côte la nouvelle visionneuse et l'ancienne.
- Transférez l'historique vers une base de séries temporelles alimentée par les mêmes topics, puis retirez l'ancien chemin.
Héberger la couche de données
La couche de données en direct est le seul élément qui doit être toujours disponible et joignable à la fois par l'usine et par le navigateur. Un broker MQTT managé prenant en charge le WebSocket sécurisé règle ce point sans ouvrir de ports dans l'usine : les passerelles se connectent en sortant via TLS, les navigateurs via WSS.
ConnectMQ fournit exactement cela : TLS sur le port 8883 pour les passerelles, WebSocket sécurisé sur le port 8084 au chemin /mqtt pour les navigateurs, prise en charge de MQTT 5 et un portail avec un explorateur de topics en direct. ConnectMQ propose aussi une démo web publique de jumeau numérique 3D, une usine avec une machine CNC, un bras robotique, un four, une cuve, un convoyeur et une pompe mis à jour en direct via WSS, construite sur ce même schéma navigateur plus MQTT. En production, remplacez le serveur MQTT public gratuit par les identifiants de votre broker privé issus du portail : YOUR_USERNAME, YOUR_PASSWORD et YOUR_CLIENT_ID.
Construisez votre jumeau 3D sur ConnectMQ
Des bibliothèques 3D web ouvertes associées à un broker MQTT standard vous donnent un jumeau interactif que vous maîtrisez entièrement. Démarrez avec un broker ConnectMQ Serverless gratuit, sans carte bancaire, et connectez dès aujourd'hui votre première scène glTF à des données en direct.
Questions fréquentes
Quelle est une bonne alternative à AWS IoT TwinMaker pour la 3D ?
Pour des jumeaux d'exploitation dans le navigateur, Three.js ou Babylon.js avec des modèles glTF et MQTT sur WebSocket sécurisé constituent un choix flexible et portable. Les moteurs de jeu comme Unity conviennent aux expériences photoréalistes ou en VR.
Peut-on réutiliser ses modèles 3D de TwinMaker ?
Généralement oui, s'ils sont au format glTF ou GLB. Vous devrez recréer les liaisons de données et le placement des étiquettes, ce qui est plus simple si vous les conservez dans un fichier de mapping comme ci-dessus.
Les navigateurs se connectent-ils directement à MQTT ?
Oui. MQTT.js se connecte via WebSocket ou WebSocket sécurisé : une page web peut donc s'abonner à des topics sans relais backend. Utilisez TLS et des identifiants de visionneuse distincts en production.
Où vont les données historiques sans TwinMaker ?
Utilisez une base de séries temporelles alimentée par un abonné MQTT comme Telegraf ou un petit script, et visualisez-la dans Grafana ou dans des graphiques au sein de la page de votre jumeau.



