Aller au contenu
JelinaJelina DocumentationDocumentation technique
Retour au site officiel

Diffusion temps réel et contrôle direct pour l’interface

L’étape d’exécution de l’architecture comprend écritures de points, alarmes et MQTT, mais aussi le service direct de l’interface. Edge-EMS Builder fournit deux canaux WebSocket permettant à une interface personnalisée de recevoir les données en temps réel et d’envoyer directement des commandes aux équipements, sans couche intermédiaire supplémentaire.

Canal Chemin Authentification Usage
Diffusion vers l’interface ws://<host>:<port>/front Token de connexion obtenu par nom d’utilisateur et mot de passe Interfaces personnalisées : contrôle des droits par rôle, abonnements et écriture directe
Lecture/écriture des données ws://<host>:<port>/data/rw data-rw-token statique configuré dans ems.yaml Intégration backend : lecture/écriture à faible latence sans connexion utilisateur, adaptée aux échanges entre systèmes

Les messages des deux canaux ont le même format ; seuls l’authentification et le niveau de contrôle des droits diffèrent. Cette page présente principalement /front ; l’usage de /data/rw est analogue.

Les paramètres sont transmis dans la query à la connexion :

ws://<host>:<port>/front?socketId=<ID-connexion-personnalisé>&token=<token-connexion>
ws://<host>:<port>/data/rw?socketId=<ID-connexion-personnalisé>&token=<data-rw-token>

Structure commune d’une trame de requête, de l’interface vers Edge-EMS Builder :

{
"topic": "read | write | clear",
"messageId": "ID unique personnalisé pour associer la réponse",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" }
]
}

Trame de réponse, d’Edge-EMS Builder vers l’interface, associée à une requête par messageId :

{
"code": "200",
"message": "Processed successfully",
"topic": "read",
"messageId": "...",
"time": "2026-07-23T10:00:00+08:00",
"data": { "...": "..." }
}

3. Recevoir les données en temps réel : abonnement = read + keep

Section intitulée « 3. Recevoir les données en temps réel : abonnement = read + keep »

Le modèle de diffusion d’Edge-EMS Builder repose sur une configuration de diffusion déclarée par chaque connexion, plutôt que sur un abonnement à un topic :

  1. L’interface envoie topic: "read", liste dans content les dataKey suivis, ou utilise groupCode pour tout un groupe, et définit keep à true.
  2. Edge-EMS Builder conserve ce content comme configuration de diffusion de la connexion (socketId) et renvoie immédiatement les valeurs courantes.
  3. Une tâche en arrière-plan parcourt ensuite chaque seconde tous les sockets encore connectés et leur transmet les dernières valeurs de leur configuration. L’interface n’a pas à répéter les requêtes d’interrogation.
  4. Si la diffusion continue n’est pas requise, définissez keep à false ou omettez-le ; Edge-EMS Builder ne diffuse alors que pendant 30s.
  5. Pour supprimer la configuration de diffusion d’une connexion, envoyez topic: "clear".
// Abonnement continu aux dernières valeurs de pcsActivePower et bmsSOC
{
"topic": "read",
"messageId": "sub-001",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" },
{ "dataKey": "bmsSOC" }
]
}
// Ou abonnement par groupe, incluant tous ses points et sous-groupes
{
"topic": "read",
"messageId": "sub-002",
"keep": true,
"content": [
{ "groupCode": "pcs-group-01" }
]
}

Une connexion peut envoyer plusieurs fois read + keep:true pour compléter ou actualiser sa configuration. Au moins un champ parmi dataKey et groupCode est obligatoire.

L’interface envoie topic: "write" avec dataKey et dataValue dans content, sans préciser le type de données. Edge-EMS Builder déduit de dataKey s’il s’agit de Collection, Aggregation ou Customization, puis utilise la logique d’écriture correspondante :

{
"topic": "write",
"messageId": "ctrl-001",
"content": [
{ "dataKey": "pcsActivePower", "dataValue": "300" }
]
}

Une écriture de données par plage horaire (Customization) peut préciser la période de validité :

{
"topic": "write",
"messageId": "ctrl-002",
"resetCustomValue": true,
"content": [
{
"dataKey": "import_price",
"dataValue": "0.85",
"availableDate": "2026-06-25T00:00:00+08:00",
"expiredDate": "2026-06-25T08:00:00+08:00"
}
]
}
  • resetCustomValue: true efface d’abord les valeurs existantes avant d’écrire les nouvelles. Ce réglage permet de remplacer un programme complet en évitant les chevauchements entre anciennes et nouvelles plages.
  • Pour écrire un point sur un autre équipement partagé, ajoutez deviceCode à l’élément content. Edge-EMS Builder reconnaît une écriture partagée et l’achemine vers la cible.
  • Connexion à /data/rw par data-rw-token statique : accès direct sans vérification de rôle, adapté aux intégrations backend entre systèmes.
  • Connexion à /front par token utilisateur : le rôle doit être superadministrateur, administrateur ou opérateur. Un observateur ne peut pas écrire. Les règles sont identiques à celles de l’interface, sans voie d’écriture contournant ses droits.

DAILY_REPEAT utilise availableTime / expiredTime, par exemple de 08:00:00 à 12:00:00, avec une période globale de dates configurée sur le point horaire. DAILY_CHANGE utilise des intervalles complets de date et heure. Ne mélangez pas les paramètres ; scindez les plages traversant minuit.

/front vérifie la connexion par heartbeat Ping/Pong. Le client doit traiter le code/message de fermeture et rétablir ses abonnements après reconnexion. Ne rejouez pas automatiquement les écritures avec les abonnements.

Le résultat d’une écriture dépend de la réponse CommBridge ou de l’expiration, pas du seul envoi réussi. Les journaux de contrôle montrent les états en cours, réussi et échoué. CommBridge applique la conversion inverse des coefficients d’écriture ; l’appelant ne doit pas la répéter.

Pendant le gel de maintenance, les écritures protégées renvoient 200162. Ne désactivez pas automatiquement le gel pour retenter.

5. Exemple complet d’intégration de l’interface

Section intitulée « 5. Exemple complet d’intégration de l’interface »
const ws = new WebSocket(`ws://<host>:<port>/front?socketId=web-ui-01&token=${loginToken}`);
ws.onopen = () => {
// Abonnement temps réel à la puissance active PCS et au SOC
ws.send(JSON.stringify({
topic: 'read',
messageId: 'sub-' + Date.now(),
keep: true,
content: [
{ dataKey: 'pcsActivePower' },
{ dataKey: 'bmsSOC' }
]
}));
};
ws.onmessage = (event) => {
const resp = JSON.parse(event.data);
if (resp.topic === 'read') {
// Réception des dernières valeurs chaque seconde pour actualiser les instruments/graphiques de l’interface
renderDashboard(resp.data);
}
if (resp.topic === 'write') {
// Résultat d’écriture : resp.successContent / resp.errorContent
showWriteResult(resp);
}
};
// Lorsque l’utilisateur clique sur le bouton « Régler la puissance à 300kW » :
function setPower(value) {
ws.send(JSON.stringify({
topic: 'write',
messageId: 'ctrl-' + Date.now(),
content: [{ dataKey: 'pcsActivePower', dataValue: String(value) }]
}));
}

Ce code couvre la boucle typique : abonnement au chargement de la page → actualisation chaque seconde → commande directe à la demande de l’utilisateur → réception du résultat d’écriture. Aucun service backend de relais supplémentaire n’est nécessaire.

  • Les données écrites via /front ou /data/rw sont les mêmes que celles lues par les plans de déclenchement et le moteur d’expressions. Après relecture par l’acquisition, les résultats du contrôle depuis l’interface peuvent participer aux calculs agrégés et aux conditions. Consultez Modèle de données.
  • Pour alimenter aussi un tableau de bord cloud, utilisez simultanément /front pour votre interface et la coordination MQTT pour remonter les mêmes données au cloud.
  • Le Skill de configuration IA aems-write-data encapsule /data/rw et /front et permet à un agent IA d’aider à tester les instructions d’écriture à partir de demandes en langage naturel.