From 9507f9779809bd077705d1ad54384f714b41c122 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Wed, 25 Feb 2026 15:14:24 +0100 Subject: Add README and QML usage guide for UI designers --- docs/guide-qml.md | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 docs/guide-qml.md (limited to 'docs/guide-qml.md') diff --git a/docs/guide-qml.md b/docs/guide-qml.md new file mode 100644 index 0000000..1bbe0f5 --- /dev/null +++ b/docs/guide-qml.md @@ -0,0 +1,318 @@ +# Guide QML Bobink + +Ce guide explique comment utiliser les composants QML fournis par la bibliothèque Bobink pour se connecter à un serveur OPC UA, lire des valeurs en temps réel et écrire des commandes -- le tout directement depuis vos fichiers QML, sans toucher au C++. + +Une application de démonstration complète est disponible dans le dossier `demo/` du projet. Les fichiers `Main.qml` et `NodePage.qml` illustrent toutes les fonctionnalités décrites ici. N'hésitez pas à vous en servir comme point de départ. + +## Importer le module + +En haut de chaque fichier QML où vous utilisez Bobink : + +```qml +import Bobink +``` + +Cet import rend disponibles trois éléments : + +| Nom | Rôle | +|-----|------| +| `Bobink` | Singleton qui gère la connexion au serveur | +| `OpcUaAuth` | Configuration de l'authentification | +| `OpcUaMonitoredNode` | Surveillance et écriture d'un noeud OPC UA | + +## Connexion au serveur + +### 1. Configurer l'adresse + +```qml +Bobink.serverUrl = "opc.tcp://192.168.1.10:4840" +``` + +### 2. Choisir l'authentification + +Créez un objet `OpcUaAuth` et assignez-le à `Bobink.auth` avant de vous connecter. + +**Connexion anonyme** (aucun identifiant requis) : + +```qml +OpcUaAuth { + id: auth + mode: OpcUaAuth.Anonymous +} +``` + +**Connexion avec identifiants** : + +```qml +OpcUaAuth { + id: auth + mode: OpcUaAuth.UserPass + username: "operateur" + password: "motdepasse" +} +``` + +**Connexion par certificat** : + +```qml +OpcUaAuth { + id: auth + mode: OpcUaAuth.Certificate + certPath: "/chemin/vers/certificat.der" + keyPath: "/chemin/vers/cle.pem" +} +``` + +Ensuite, assignez et connectez : + +```qml +Bobink.auth = auth +Bobink.connectToServer() +``` + +### 3. Réagir aux événements de connexion + +Utilisez un bloc `Connections` pour suivre l'état de la connexion : + +```qml +Connections { + target: Bobink + + function onConnectedChanged() { + if (Bobink.connected) + console.log("Connecté au serveur") + else + console.log("Déconnecté") + } + + function onConnectionError(message) { + console.log("Erreur :", message) + } +} +``` + +### 4. Certificat du serveur inconnu + +Si le serveur présente un certificat que le client ne connaît pas, le signal `certificateTrustRequested` est émis. Vous pouvez afficher une fenêtre de confirmation : + +```qml +Connections { + target: Bobink + function onCertificateTrustRequested(certInfo) { + // Afficher certInfo à l'utilisateur, puis : + Bobink.acceptCertificate() // pour accepter + // ou + Bobink.rejectCertificate() // pour refuser + } +} +``` + +### 5. Déconnexion + +```qml +Bobink.disconnectFromServer() +``` + +## Surveiller un noeud (lecture en temps réel) + +`OpcUaMonitoredNode` est un composant non visuel (comme `Timer` ou `Connections`). Placez-le à l'intérieur de n'importe quel élément QML. Il crée un abonnement OPC UA sur le noeud et reçoit les nouvelles valeurs automatiquement. + +```qml +OpcUaMonitoredNode { + id: temperature + nodeId: "ns=2;s=Temperature" + monitored: true +} + +Text { + text: "Température : " + temperature.value +} +``` + +### Propriétés principales + +| Propriété | Type | Description | +|-----------|------|-------------| +| `nodeId` | string | Identifiant du noeud OPC UA (ex. `"ns=2;s=Temperature"`) | +| `monitored` | bool | Active ou désactive la surveillance. Par défaut : `true` | +| `publishingInterval` | double | Intervalle de mise à jour en millisecondes. Par défaut : 250 | +| `value` | variant | Valeur actuelle du noeud (lecture seule, mise à jour automatique) | +| `writable` | bool | `true` si le noeud autorise l'écriture (lecture seule) | +| `info` | objet | Métadonnées du noeud (voir plus bas) | + +### Activer/désactiver la surveillance + +Il est conseillé de désactiver la surveillance quand le composant n'est pas visible, pour économiser les ressources réseau. Par exemple, avec un `StackView` : + +```qml +OpcUaMonitoredNode { + nodeId: "ns=2;s=Temperature" + monitored: maPage.StackView.status === StackView.Active +} +``` + +Ainsi le noeud n'est surveillé que lorsque la page est affichée. + +### Changer l'intervalle de mise à jour + +```qml +OpcUaMonitoredNode { + nodeId: "ns=2;s=Temperature" + publishingInterval: 1000 // une fois par seconde +} +``` + +**Regroupement des abonnements :** côté serveur, les noeuds qui partagent le même `publishingInterval` sont regroupés dans un même abonnement (subscription) OPC UA. Moins il y a d'abonnements distincts, moins le serveur et le réseau sont sollicités. Essayez donc de donner le même intervalle à autant de noeuds que possible. Par exemple, si la plupart de vos noeuds n'ont pas besoin d'une mise à jour plus rapide que 500 ms, laissez-les tous à 500 ms plutôt que de varier les intervalles sans raison. + +Pour appliquer un changement d'intervalle en cours d'exécution, désactivez puis réactivez la surveillance : + +```qml +temperature.monitored = false +temperature.publishingInterval = 2000 +temperature.monitored = true +``` + +## Écrire une valeur + +### Écriture simple + +```qml +OpcUaMonitoredNode { + id: consigne + nodeId: "ns=2;s=Setpoint" +} + +TextField { + id: champValeur + placeholderText: "Nouvelle valeur..." +} + +Button { + text: "Écrire" + enabled: consigne.writable + onClicked: consigne.writeValue(champValeur.text) +} +``` + +La conversion de type est automatique : la valeur QML (texte, nombre, booléen) est convertie vers le type OPC UA du noeud. + +Pour écrire un tableau, séparez les valeurs par des virgules : + +```qml +consigne.writeValue("10, 20, 30") +``` + +### Écriture partielle dans un tableau (index range) + +Pour modifier uniquement certains éléments d'un tableau sans réécrire le tout : + +```qml +// Modifier le premier élément +consigne.writeValueAtRange("42", "0") + +// Modifier les éléments 0 à 2 +consigne.writeValueAtRange("10, 20, 30", "0:2") +``` + +### Résultat de l'écriture + +Le signal `writeCompleted` indique si l'écriture a réussi : + +```qml +OpcUaMonitoredNode { + id: consigne + nodeId: "ns=2;s=Setpoint" + onWriteCompleted: (success, message) => { + if (success) + console.log("Écriture réussie") + else + console.log("Échec :", message) + } +} +``` + +## Métadonnées d'un noeud + +La propriété `info` donne accès aux métadonnées, lues une seule fois à la connexion : + +```qml +OpcUaMonitoredNode { + id: noeud + nodeId: "ns=2;s=Temperature" +} + +Column { + Text { text: "Nom : " + noeud.info.displayName } + Text { text: "Description : " + noeud.info.description } + Text { text: "Type : " + noeud.info.dataType } +} +``` + +| Champ | Description | +|-------|-------------| +| `displayName` | Nom lisible du noeud | +| `description` | Description textuelle | +| `nodeClass` | Classe du noeud (Variable, Object, etc.) | +| `dataType` | Type de donnée (Int32, Float, String, etc.) | +| `valueRank` | Rang (-1 = scalaire, 1 = tableau 1D, etc.) | +| `arrayDimensions` | Dimensions du tableau | +| `accessLevel` | Niveau d'accès (lecture, écriture) | +| `status` | Code de statut OPC UA | +| `sourceTimestamp` | Horodatage côté source | +| `serverTimestamp` | Horodatage côté serveur | + +## Découverte de serveurs + +Bobink peut interroger un serveur de découverte local (LDS) pour lister les serveurs OPC UA disponibles sur le réseau : + +```qml +Component.onCompleted: { + Bobink.discoveryUrl = "opc.tcp://localhost:4840" + Bobink.startDiscovery() +} + +ListView { + model: Bobink.servers + delegate: ItemDelegate { + required property var modelData + text: modelData.serverName + onClicked: Bobink.serverUrl = modelData.discoveryUrls[0] + } +} +``` + +Chaque élément de `Bobink.servers` contient : + +- `serverName` -- nom du serveur +- `applicationUri` -- identifiant unique de l'application +- `discoveryUrls` -- liste des URL de connexion + +Appelez `Bobink.stopDiscovery()` pour arrêter la recherche (par exemple une fois connecté). + +## Certificats client (PKI) + +Au démarrage, Bobink cherche automatiquement un certificat client dans le dossier PKI par défaut. Si vous devez configurer manuellement : + +```qml +Bobink.pkiDir = "/chemin/vers/pki" +Bobink.certFile = "/chemin/vers/certificat.der" +Bobink.keyFile = "/chemin/vers/cle.pem" +Bobink.applyPki() +``` + +Les propriétés `Bobink.pkiDir`, `Bobink.certFile` et `Bobink.keyFile` sont aussi consultables pour afficher les chemins actuels dans votre interface. + +## Récapitulatif + +| Ce que vous voulez faire | Code | +|--------------------------|------| +| Se connecter | `Bobink.connectToServer()` | +| Se déconnecter | `Bobink.disconnectFromServer()` | +| Lire une valeur en temps réel | `OpcUaMonitoredNode { nodeId: "..." }` puis `monNoeud.value` | +| Écrire une valeur | `monNoeud.writeValue(valeur)` | +| Écrire dans un tableau partiellement | `monNoeud.writeValueAtRange(valeur, "0:2")` | +| Vérifier si un noeud est inscriptible | `monNoeud.writable` | +| Afficher le nom d'un noeud | `monNoeud.info.displayName` | +| Lister les serveurs | `Bobink.startDiscovery()` puis `Bobink.servers` | + +Pour un exemple concret et complet, consultez les fichiers `demo/Main.qml` et `demo/NodePage.qml`. -- cgit v1.2.3