Aller au contenu

EdgeControl — Guide pratique et rapide

EdgeControl sert à planifier et prioriser plusieurs plannings de pilotage pour une ou plusieurs centrales. À chaque créneau horaire, la consigne retenue vient du planning le plus prioritaire ; si rien n’est défini, on retombe sur la période par défaut.

À retenir en 30 secondes

  • Un planning = un name + une date (UTC) + des périodes alignées sur aggregation_period.
  • Les noms autorisés sont listés dans plannings_priority de la centrale.
  • L'agrégation applique d'abord le planning le plus prioritaire, sinon le suivant, sinon default_period.
  • Par défaut, state = "ON" (centrale en marche). OFF signifie une mise à l'arrêt volontaire.
  • active_power est uniquement utilisable quand state = "TARGET" (obligatoire dans ce cas). Les états ON et OFF ne permettent pas de régulation de puissance active.
  • Pas de suppression : poster un planning vide neutralise l'effet.

Lexique rapide

  • Centrale : entité définie par entity_ident, son pas aggregation_period, et sa default_period.
  • Planning : ensemble de périodes horaires pour une journée UTC donnée.
  • Période : clé HH:MM:SS alignée sur aggregation_period, contenant la consigne.
  • Priorité : ordre décroissant dans plannings_priority (1er = plus fort).
  • États : ON (par défaut, centrale en marche), OFF (mise à l’arrêt), TARGET (consigne explicite).

Avant de commencer

  • Vérifiez le pas horaire (aggregation_period) partagé par tous les plannings d’une centrale.
  • Gardez tous les horaires en UTC et alignés sur ce pas.
  • Listez vos plannings dans plannings_priority avant de les créer.
  • Préparez un default_period cohérent : par défaut state = "ON" pour indiquer une centrale en marche.

Configurer une centrale (3 étapes)

1) Définir aggregation_period, start_before, stop_after, et la default_period (avec state = "ON" par défaut). 2) Lister les plannings autorisés avec leur ordre (plannings_priority). 3) Poster :

PATCH /edgecontrol/plants/{plant_ident}/edge-control
{
  "aggregation_period": 3600,
  "default_period": { "state": "ON", "mode": 0 },
  "plannings_priority": ["Ajustement", "IntraDay", "PSN"]
}

Créer ou mettre à jour un planning (upsert)

1) Choisir un name autorisé (≠ "main") et la date (UTC YYYY-MM-DD). 2) Définir uniquement les périodes qui changent : le reste est complété par default_period. 3) Poster :

POST /edgecontrol/plants/{plant_ident}/plannings
{
  "name": "IntraDay",
  "date": "2025-12-30",
  "planning": {
    "12:00:00": { "state": "OFF" },
    "13:00:00": { "state": "TARGET", "active_power": 750 }
  }
}
L'API renvoie le planning complété (toutes les périodes), ajoute planning_name, et recalcule l'agrégation.

Comment l’agrégation choisit la consigne

  • On collecte tous les plannings de la centrale pour la journée.
  • On les trie selon plannings_priority (ordre décroissant).
  • Pour chaque créneau : valeur du planning le plus prioritaire disponible, sinon planning suivant, sinon default_period.

Référence des structures

Centrale

Clé Type Description
entity_ident string Identifiant unique ALEMCA.
aggregation_period int Durée (s) de chaque période (ex. 3600 = 1h).
start_before float Rampe de montée avant la période (s).
stop_after float Rampe de descente après la période (s).
default_period json Période appliquée si aucune consigne n’est définie (state par défaut à "ON").
plannings_priority array Plannings autorisés, triés du plus prioritaire au moins prioritaire.

Période de planning

Clé Type Qualité Description
planning_name string Ajouté par l'API Nom du planning d'origine (ou "default").
state string Obligatoire ON (centrale en marche, valeur par défaut), OFF (mise à l'arrêt), TARGET (consigne de puissance).
active_power float TARGET uniquement kW (peut être négatif). Obligatoire si state = "TARGET". Non autorisé pour ON ou OFF.
primary_reserve_power float Optionnel kW, signé autorisé. Défaut 0.
secondary_reserve_power float Optionnel kW, signé autorisé. Défaut 0.
mode int Optionnel Mode de fonctionnement (ex. 0=PSN, 1=MA, 2=ID). Défaut 0.

Important : Les états ON et OFF ne permettent pas de régulation de puissance active (active_power). Seul l'état TARGET permet de définir une consigne de puissance.

Exemples de périodes

{ "12:00:00": { "planning_name": "intraday", "state": "TARGET", "active_power": 750, "mode": 0 } }

{ "13:00:00": { "planning_name": "PSN", "state": "OFF", "mode": 0 } }
{ "14:00:00": { "planning_name": "PSN", "state": "ON", "mode": 0 } }

Définition des plannings

  • Un planning est unique par (entity_ident, name, date).
  • date couvre la journée complète UTC (00:00:00Z → 23:59:59Z).
  • aggregation_period = 3600 ⇒ 24 points par jour.
  • Les périodes non définies héritent de default_period (par défaut state = "ON").
  • La modification d’un planning déclenche un nouveau calcul d’agrégation.
  • Un planning ne peut être créé que si son name est présent dans plannings_priority.

Exemple de planning complet

{
  "planning_ident": "12345678-1234-1234-1234-123456789123",
  "plant_ident": "<uuid>",
  "name": "PSN",
  "default_period": { "state": "ON", "mode": 0 },
  "status": "applied",
  "aggregation_period": 3600,
  "start_before": 5,
  "stop_after": 5,
  "creation_date": 1761830251,
  "author": "author_ident",
  "date": "2025-12-30",
  "planning": {
    "12:00:00": { "planning_name": "PSN", "state": "OFF", "mode": 0 },
    "13:00:00": { "planning_name": "PSN", "state": "TARGET", "active_power": 750, "mode": 0 },
    "16:00:00": { "planning_name": "PSN", "state": "OFF", "mode": 0 }
  }
}

Rappels de validation (clés)

  • name doit exister dans plannings_priority de la centrale et ne peut pas être "main".
  • Un planning est unique par (plant_ident, name, date).
  • Clés horaires HH:MM:SS alignées sur aggregation_period.
  • active_power obligatoire si state = "TARGET", non autorisé pour ON ou OFF.
  • Les puissances (active_power, primary_reserve_power, secondary_reserve_power) sont des floats signés (kW).
  • planning_name est ajouté par l'API en sortie (output-only).

API — Endpoints EdgeControl

Résumé des endpoints

🔎 Résumé des endpoints

Tous les endpoints répondent en JSON. Authentification via le header api-key: <votre_api_key> (service-to-service) ou Authorization: Bearer <token> (authentification utilisateur).

Plants (centrales)

Méthode Route Objet But Paramètres / Notes
GET /edgecontrol/plants Centrale Lister les centrales avec pagination Query : search, page (1-based), per_page (1-100, défaut: 25), sort, asc
GET /edgecontrol/plants/{plant_ident} Centrale Lire une centrale plant_ident (UUID)
PATCH /edgecontrol/plants/{plant_ident}/edge-control Centrale Mettre à jour la configuration EdgeControl Body : aggregation_period, plannings_priority, default_period

Plannings (une centrale)

Méthode Route Objet But Paramètres / Notes
POST /edgecontrol/plants/{plant_ident}/plannings Planning Créer ou mettre à jour (upsert avec versioning) un planning Body : name (1-120 chars, ≠ "main"), date (UTC YYYY-MM-DD), planning, author (optionnel), start_before, stop_after (optionnels)
GET /edgecontrol/plants/{plant_ident}/plannings Planning Lister les plannings d'une centrale Query : date, name, exclude_main (défaut: true), skip (défaut: 0), limit (1-1000, défaut: 100)
GET /edgecontrol/plants/{plant_ident}/plannings/main Agrégé Récupérer le planning agrégé (fusion prioritaire) Query : date (optionnel, défaut: aujourd'hui)
GET /edgecontrol/plants/{plant_ident}/plannings/{planning_id}/versions Versions Récupérer l'historique des versions d'un planning planning_id (UUID)

Plannings (opérations batch)

Méthode Route Objet But Paramètres / Notes
POST /edgecontrol/plannings Planning Créer le même planning sur plusieurs centrales Body : idents (tableau d'UUIDs), name, date, planning, author (optionnel)
DELETE /edgecontrol/plannings Planning Soft-delete de plusieurs plannings par clé composite Body : clés composites des plannings à supprimer

Idempotence & statuts

  • POST /edgecontrol/plants/{plant_ident}/plannings est idempotent par (plant_ident,name,date) avec versioning automatique.
  • Statuts possibles : status = "draft" | "pending" | "applied" | "failed".

Lister les centrales

GET /edgecontrol/plants

Query params : - search : filtre de recherche (optionnel) - page : numéro de page, 1-based (défaut: 1) - per_page : résultats par page, 1-100 (défaut: 25) - sort : champ de tri (optionnel) - asc : ordre croissant (optionnel)

Réponses possibles : - 200 OK — Liste paginée des centrales - 401 Unauthorized


Lire une centrale

GET /edgecontrol/plants/{plant_ident}

Réponse :

{
  "plant_ident": "<uuid>",
  "entity_ident": "<ident_alemca>",
  "aggregation_period": 3600,
  "start_before": 300,
  "stop_after": 300,
  "default_period": {
      "state": "ON",
      "mode": 0
    },
  "plannings_priority": ["Ajustement", "IntraDay", "PSN"]
}

Réponses possibles : - 200 OK - 404 Not Found


Mettre à jour la configuration EdgeControl

PATCH /edgecontrol/plants/{plant_ident}/edge-control

Body :

{
  "aggregation_period": 3600,
  "plannings_priority": ["Ajustement", "IntraDay", "PSN", "Maintenance"],
  "default_period": { "state": "ON", "mode": 0 }
}

Réponses possibles : - 200 OK — Configuration mise à jour - 400 Bad Request - 404 Not Found - 409 Conflict - si changement d'aggregation_period incompatible avec des plannings existants


Créer ou mettre à jour un planning

POST /edgecontrol/plants/{plant_ident}/plannings

Body :

{
  "name": "IntraDay",
  "date": "2025-12-30",
  "planning": {
    "12:00:00": { "state": "OFF" },
    "13:00:00": { "state": "TARGET", "active_power": 750 }
  },
  "author": "alice@example.com",
  "start_before": 300,
  "stop_after": 300
}

Note : start_before et stop_after sont optionnels et surchargent les valeurs par défaut de la centrale.

Exemple de réponse :

{
  "planning_ident": "8da1d8ee-7f3c-4c5b-9e48-1f2f5e3f1b76",
  "plant_ident": "<uuid>",
  "name": "IntraDay",
  "date": "2025-12-30",
  "aggregation_period": 3600,
  "start_before": 300,
  "stop_after": 300,
  "planning": {
    "00:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "12:00:00": { "planning_name": "IntraDay", "state": "OFF", "mode": 0 },
    "00:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "12:00:00": { "planning_name": "IntraDay", "state": "OFF", "mode": 0 },
    "13:00:00": { "planning_name": "IntraDay", "state": "TARGET", "active_power": 750, "mode": 0 },
    "14:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "14:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "...": {}
  },
  "status": "applied",
  "author": "alice@example.com",
  "creation_date": 1761830251,
  "update_date": 1761830265
}

Réponses possibles : - 200 OK — Planning mis à jour - 201 Created — Nouveau planning selon règles d'unicité - 400 Bad Request — Format JSON incorrect, clé horaire non alignée, active_power manquant en TARGET, ou name = "main" - 404 Not Found — Centrale non trouvée - 409 Conflict - name non autorisé par plannings_priority


Lister les plannings d'une centrale

GET /edgecontrol/plants/{plant_ident}/plannings?date=2025-12-30

Query params : - date : filtre par date (optionnel) - name : filtre par nom de planning (optionnel) - exclude_main : exclure le planning agrégé (défaut: true) - skip : pagination offset (défaut: 0) - limit : nombre max de résultats, 1-1000 (défaut: 100)

Réponse :

[
  {
    "name": "PSN",
    "date": "2025-12-30",
    "planning_ident": "12345678-1234-1234-1234-123456789123"
  },
  {
    "name": "Production",
    "date": "2025-12-30",
    "planning_ident": "12345678-AAAA-BBBB-CCCC-123456789999"
  }
]

L'objet planning est retourné tel que défini en [Exemple de Planning]


Récupérer l'historique des versions d'un planning

GET /edgecontrol/plants/{plant_ident}/plannings/{planning_id}/versions

Réponse : Liste des versions du planning avec auteur et timestamps pour audit.

Réponses possibles : - 200 OK — Historique des versions - 404 Not Found — Planning non trouvé


Récupérer le planning agrégé d'une centrale

GET /edgecontrol/plants/{plant_ident}/plannings/main?date=2025-12-30

Note : Le paramètre date est optionnel et utilise la date du jour par défaut.

Réponse :

{
  "planning_ident": "8da1d8ee-7f3c-4c5b-9e48-1f2f5e3f1b76",
  "plant_ident": "<uuid>",
  "name": "main",
  "date": "2025-12-30",
  "aggregation_period": 3600,
  "start_before": 300,
  "stop_after": 300,
  "planning": {
    "00:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "12:00:00": { "planning_name": "IntraDay", "state": "OFF", "mode": 0 },
    "00:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "12:00:00": { "planning_name": "IntraDay", "state": "OFF", "mode": 0 },
    "13:00:00": { "planning_name": "IntraDay", "state": "TARGET", "active_power": 750, "mode": 0 },
    "14:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "14:00:00": { "planning_name": "IntraDay", "state": "ON", "mode": 0 },
    "...": {}
  },
  "status": "applied",
  "author": "alice@example.com",
  "creation_date": 1761830251,
  "update_date": 1761830265
}

L'ensemble des périodes de la journée seront retournées

Réponses possibles : - 200 OK — Planning agrégé renvoyé - 404 Not Found — Aucune donnée trouvée pour cette centrale/date


Opérations batch

Créer un planning sur plusieurs centrales

POST /edgecontrol/plannings

Body :

{
  "idents": ["<uuid1>", "<uuid2>", "<uuid3>"],
  "name": "IntraDay",
  "date": "2025-12-30",
  "planning": {
    "12:00:00": { "state": "OFF" },
    "13:00:00": { "state": "TARGET", "active_power": 750 }
  },
  "author": "alice@example.com"
}

Réponses possibles : - 200 OK — Plannings créés/mis à jour - 400 Bad Request — Données invalides - 404 Not Found — Une ou plusieurs centrales non trouvées


Supprimer plusieurs plannings (soft-delete)

DELETE /edgecontrol/plannings

Body : Liste des clés composites des plannings à supprimer.

Réponses possibles : - 200 OK — Plannings supprimés (soft-delete) - 404 Not Found — Plannings non trouvés

Règles et Contraintes Techniques

  • La date représente une journée complète en temps universel coordonné (UTC), couvrant la période du YYYY-MM-DDT00:00:00Z au YYYY-MM-DDT23:59:59Z, indépendamment du fuseau horaire local.
  • Un planning est unique par combinaison (plant_ident, name, date).
  • L'ordre de priorité est géré dans plannings_priority de la centrale.
  • Les opérations de mise à jour sont atomiques : une modification ne peut pas être partiellement appliquée.
  • Contrainte de puissance : active_power ne peut être utilisé qu'avec state = "TARGET". Les états ON et OFF ne permettent pas de régulation de puissance.

Exemple d'agrégation — Fenêtre 6h (avec période par défaut)

Paramètres : - aggregation_period: 3600 (1h) - plannings_priority: Ajustement > IntraDay > PSN - default_period: { "state": "ON", "mode": 0 }


Données d'entrée

PSN (priorité 3)

{
  "00:00:00": { "state": "TARGET", "active_power": 300 },
  "01:00:00": { "state": "TARGET", "active_power": 300 },
  "02:00:00": { "state": "OFF" },
  "03:00:00": { "state": "TARGET", "active_power": 500 },
  "04:00:00": { "state": "OFF" }
}

IntraDay (priorité 2)

{
  "01:00:00": { "state": "TARGET", "active_power": 600 },
  "02:00:00": { "state": "TARGET", "active_power": 400 },
  "04:00:00": { "state": "TARGET", "active_power": 200 }
}

Ajustement (priorité 1 — la plus haute)

{
  "02:00:00": { "state": "TARGET", "active_power": 700 },
  "03:00:00": { "state": "OFF" }
}

Ici, 05:00:00 n'est défini dans aucun planning, donc la default_period sera appliquée (avec state = "ON").


Tableau d'agrégation

Heure PSN (P3) IntraDay (P2) Ajustement (P1) Valeur agrégée (source retenue)
00:00 TARGET 300 TARGET 300 (PSN)
01:00 TARGET 300 TARGET 600 TARGET 600 (IntraDay)
02:00 OFF TARGET 400 TARGET 700 TARGET 700 (Ajustement)
03:00 TARGET 500 OFF OFF (Ajustement)
04:00 OFF TARGET 200 TARGET 200 (IntraDay)
05:00 ON (default_period)

Visualisation (Mermaid)

gantt
    title Agrégation 6h (priorité: Ajustement > IntraDay > PSN) — avec période par défaut
    dateFormat  HH:mm
    axisFormat  %H:%M

    section PSN (P3)
    TARGET 300       :00:00, 00:59
    TARGET 300       :01:00, 01:59
    OFF              :02:00, 02:59
    TARGET 500       :03:00, 03:59
    OFF              :04:00, 04:59

    section IntraDay (P2)
    TARGET 600       :01:00, 01:59
    TARGET 400       :02:00, 02:59
    TARGET 200       :04:00, 04:59

    section Ajustement (P1)
    TARGET 700       :02:00, 02:59
    OFF              :03:00, 03:59

    section Agrégé (résultat)
    TARGET 300 (PSN) :00:00, 00:59
    TARGET 600 (ID)  :01:00, 01:59
    TARGET 700 (Adj) :02:00, 02:59
    OFF (Adj)        :03:00, 03:59
    TARGET 200 (ID)  :04:00, 04:59
    ON (default)     :05:00, 05:59

Résultat agrégé

{
  "plant_ident": "<uuid>",
  "date": "2025-12-30",
  "aggregation_period": 3600,
  "planning": {
    "00:00:00": { "planning_name": "PSN", "state": "TARGET", "active_power": 300, "mode": 0 },
    "01:00:00": { "planning_name": "IntraDay", "state": "TARGET", "active_power": 600, "mode": 0 },
    "02:00:00": { "planning_name": "Ajustement", "state": "TARGET", "active_power": 700, "mode": 0 },
    "03:00:00": { "planning_name": "Ajustement", "state": "OFF", "mode": 0 },
    "04:00:00": { "planning_name": "IntraDay", "state": "TARGET", "active_power": 200, "mode": 0 },
    "05:00:00": { "planning_name": "default", "state": "ON", "mode": 0 }
  },
  "status": "applied",
  "last_transmission": { "timestamp": 1761830251, "result": "success" }
}

Points clés

  • Une heure non définie par aucun planningdefault_period s'applique (avec state = "ON").
  • L'API ajoute toujours planning_name automatiquement dans la sortie.
  • active_power est requis si state = "TARGET", non autorisé pour ON ou OFF.
  • Les puissances (float) peuvent être signées.