o6 Automation
Tous les articles

Dossier · 8 avril 2026

API événementielle améliorée dans open62541 v1.5

Une meilleure ergonomie pour le puissant mécanisme événementiel d’OPC UA

Panneau d’alarme et de commande éclairé sur un ancien système informatique
Introduction

Les événements constituent une fonctionnalité puissante d’OPC UA et présentent plusieurs avantages par rapport à la surveillance des changements de données :

  • Aucun intervalle d’échantillonnage nécessaire
  • Des contenus structurés et riches plutôt que des valeurs isolées
  • Une sémantique forte grâce aux EventTypes
  • Propagation et agrégation au sein de la hiérarchie du modèle d’information
  • Filtrage intégré côté serveur pour réduire le trafic réseau

Malgré ces avantages, les événements restent souvent sous-utilisés en raison de leur complexité supposée. Avec la version 1.5 du SDK open62541, nous nous sommes attachés à améliorer sensiblement la facilité d’utilisation et l’ergonomie de l’API événementielle. Cet article présente les principales évolutions côté client et côté serveur.

Syntaxe lisible pour les champs d’événement

Le contenu d’un événement, composé de ses champs, est défini par des EventTypes qui sont des ObjectTypes spécialisés du modèle d’information OPC UA. De nombreuses Companion Specifications définissent leurs propres EventTypes pour leur domaine d’application. La Companion Specification AutoID définit par exemple des EventTypes pour la détection des codes-barres et des étiquettes RFID.

L’illustration suivante donne un aperçu des champs d’événement standard du BaseEventType. Toujours disponibles, ils constituent le socle de tous les événements.

/EventId: ByteString to uniquely identify the event instance
/EventType: NodeId of the EventType
/SourceNode: NodeId of the emitting node
/SourceName: LocalizedText with the DisplayName of the source node
/Time: DateTime with the timestamp when the event occurred
/ReceiveTime: DateTime when the server received the information about the event
/Message: LocalizedText with a human-readable description of the event
/Severity: UInt16 for the urgency of the event between 1 (lowest) and 1000 (catastrophic)

Côté client, les champs pertinents sont sélectionnés au moyen de la clause Select d’un EventFilter. Cette clause se compose d’entrées SimpleAttributeOperand qui correspondent à des BrowsePaths enrichis de métadonnées d’attribut et de plage d’indices.

La version v1.5 introduit une syntaxe concise et lisible pour définir ces opérandes. Au lieu de structures verbeuses, les champs d’événement peuvent désormais être exprimés sous forme de simples chemins.
Par exemple :

  • /1:Robot/2:Axis1/2:Angle
  • /2:Line/2:VisualInspection/3:Camera/3:CapturedImage#Value[0:100,0:100]

Les nœuds de l’EventType sont adressés par leur BrowseName, avec un préfixe facultatif séparé par deux-points pour l’indice du Namespace. Les barres obliques délimitent les niveaux de la hiérarchie. Pour plus de détails, consultez la documentation d’open62541 ainsi que notre article ETFA 2024 sur les filtres d’événements.

Cette représentation est maintenant utilisée de manière cohérente dans les API client et serveur. Elle fournit ainsi un modèle unifié pour définir, transmettre et exploiter les données événementielles.

Côté client : s’abonner à la surveillance des événements

L’abonnement à la surveillance des événements côté client a été considérablement simplifié. Auparavant, la construction de la clause Select nécessitait plusieurs lignes de code répétitif. Avec la version v1.5, la clause entière peut être analysée directement à partir d’une seule chaîne lisible.

/* EventFilter */
typedef struct {
    size_t selectClausesSize;
    UA_SimpleAttributeOperand *selectClauses;
    UA_ContentFilter whereClause;
} UA_EventFilter;

/* Parse Event-Field Description for the Select-Clause */
UA_StatusCode
UA_SimpleAttributeOperand_parse(UA_SimpleAttributeOperand *sao,
                                const UA_String input);

/* Callback for Event Notifications */
typedef void (*UA_Client_EventNotificationCallback)
    (UA_Client *client, UA_UInt32 subId, void *subContext,
     UA_UInt32 monId, void *monContext,
     const UA_KeyValueMap eventFields);

/* Register for Event Monitoring */
UA_MonitoredItemCreateResult
UA_Client_MonitoredItems_createEvent(UA_Client *client,
    UA_UInt32 subscriptionId,
    const UA_MonitoredItemCreateRequest item,
    void *context, UA_Client_EventNotificationCallback callback,
    UA_Client_DeleteMonitoredItemCallback deleteCallback);

Une fois la surveillance active, le serveur envoie les notifications d’événements au client. Elles sont transmises à un callback défini par l’utilisateur. Comme le montre l’extrait de code ci-dessus, les champs d’événement arrivent dans le callback sous la forme d’une table clé-valeur. Les clés utilisent la syntaxe lisible de chaque champ. L’ordre des champs de la clause Select d’origine est également conservé, ce qui permet toujours un accès indexé efficace en ressources. Ce double mode d’accès, par clé ou par indice, associe lisibilité et performance.

Génération d’événements côté serveur dans open62541

Côté serveur, la création d’événements a été regroupée dans UA_Server_createEvent sous la forme d’une API unique et expressive. Cette fonction exploite elle aussi la syntaxe lisible des champs d’événement.

/* Create an event in the server. It gets filtered and sent to the
 * monitoring clients, as well as locally registered callbacks. */
UA_StatusCode
UA_Server_createEvent(UA_Server *server, const UA_NodeId sourceNode,
                      const UA_NodeId eventType, UA_UInt16 severity,
                      const UA_LocalizedText message,
                      const UA_KeyValueMap *eventFields,
                      const UA_NodeId *eventInstance,
                      UA_ByteString *outEventId);

Lors de la génération d’un événement, les valeurs des champs peuvent provenir de quatre sources :

  1. Paramètres directs (obligatoires) : les principaux champs d’événement sont transmis directement lors de l’appel de UA_Server_createEvent.
  2. Table de champs (facultative) : la table clé-valeur de l’argument eventFields associe les définitions lisibles des champs d’événement à leur valeur Variant.
  3. Instance d’événement (facultative) : si un champ n’a pas pu être résolu à partir des sources précédentes, l’argument eventInstance désigne un ObjectNode du modèle d’information. Cet objet instancie généralement l’EventType de l’événement. Le serveur utilise alors les membres de cet objet pour résoudre le contenu des champs.
  4. Valeurs par défaut (internes) : si des champs obligatoires du BaseEventType restent indéfinis, des valeurs par défaut sont créées en interne. Le champ /Time reçoit par exemple l’heure actuelle, tandis qu’un ByteString aléatoire est utilisé pour le champ unique /EventId.

Ce modèle de résolution en plusieurs niveaux offre de la souplesse tout en restant clair.

Résumé

Les événements OPC UA constituent un mécanisme particulièrement expressif et efficace pour transmettre des informations structurées. Avec la version 1.5, l’API open62541 réduit nettement les obstacles à leur adoption grâce aux améliorations suivantes :

  • Introduction d’une syntaxe lisible pour les champs
  • Simplification de la construction des filtres côté client
  • Données de callback structurées et intuitives
  • Unification et simplification de la création d’événements côté serveur

Ces évolutions rendent les architectures événementielles plus accessibles et plus faciles à déployer dans des applications réelles.

Actualités OPC UA et open62541.

Articles techniques, nouveautés, dates de formation et actualités d’o6 Automation.