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+ unedate(UTC) + des périodes alignées suraggregation_period. - Les noms autorisés sont listés dans
plannings_priorityde 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).OFFsignifie une mise à l'arrêt volontaire. active_powerest uniquement utilisable quandstate = "TARGET"(obligatoire dans ce cas). Les étatsONetOFFne 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 pasaggregation_period, et sadefault_period. - Planning : ensemble de périodes horaires pour une journée UTC donnée.
- Période : clé
HH:MM:SSalignée suraggregation_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_priorityavant de les créer. - Préparez un
default_periodcohérent : par défautstate = "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 }
}
}
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
ONetOFFne permettent pas de régulation de puissance active (active_power). Seul l'étatTARGETpermet de définir une consigne de puissance.
Exemples de périodes
Définition des plannings
- Un planning est unique par (
entity_ident,name,date). datecouvre 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éfautstate = "ON"). - La modification d’un planning déclenche un nouveau calcul d’agrégation.
- Un planning ne peut être créé que si son
nameest présent dansplannings_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)
namedoit exister dansplannings_priorityde la centrale et ne peut pas être "main".- Un planning est unique par (
plant_ident,name,date). - Clés horaires
HH:MM:SSalignées suraggregation_period. active_powerobligatoire sistate = "TARGET", non autorisé pourONouOFF.- Les puissances (
active_power,primary_reserve_power,secondary_reserve_power) sont des floats signés (kW). planning_nameest 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) ouAuthorization: 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}/planningsest idempotent par (plant_ident,name,date) avec versioning automatique.- Statuts possibles :
status = "draft" | "pending" | "applied" | "failed".
Lister les centrales
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
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
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
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_beforeetstop_aftersont 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
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
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
Note : Le paramètre
dateest 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
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)
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_priorityde la centrale. - Les opérations de mise à jour sont atomiques : une modification ne peut pas être partiellement appliquée.
- Contrainte de puissance :
active_powerne peut être utilisé qu'avecstate = "TARGET". Les étatsONetOFFne 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)
Ici, 05:00:00 n'est défini dans aucun planning, donc la
default_periodsera appliquée (avecstate = "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 planning ⇒
default_periods'applique (avecstate = "ON"). - L'API ajoute toujours
planning_nameautomatiquement dans la sortie. active_powerest requis sistate = "TARGET", non autorisé pourONouOFF.- Les puissances (
float) peuvent être signées.