14 KiB
Architecture — écosystème ETM-PowerSync
Document de référence transverse. Source de vérité ; les
READMEde dépôt en sont des vues locales. Statut : v0.1 (structuration initiale). Les contrats d'interface sont endraft.
1. Principe directeur : deux frontières alignées
Tout l'écosystème repose sur une seule ligne, qui sépare deux choses à la fois :
| Côté plugin | Côté service | |
|---|---|---|
| Licence | GPL-3.0-or-later | Propriétaire |
| Exécution | dans le processus nymead |
processus séparé |
| Données | scalaire, événementiel (valeur instantanée) | série temporelle (horizon) |
| Rôle | capteurs, données, transport, règles simples | intelligence (prévision, MPC, arbitrage) |
La frontière de licence et la frontière technique coïncident. Un plugin nymea est lié à libnymea (GPL) et chargé dans nymead : il doit être GPL et ne contient donc aucune logique propriétaire. L'intelligence vit dans des services séparés, joints uniquement par API HTTP (« arm's length »), ce qui préserve le propriétaire. Précédent de référence : EOS, optimiseur autonome consommé par HTTP.
2. Vue d'ensemble par couches
┌─ Couche plugins nymea (GPL-3, dans nymead) ───────────────────────────┐
│ openmeteo linky tarif energy-plugin-etm │
│ (Integration) (Integration) (Integration) (Energy) │
│ météo/solaire compteur TIC prix/rank rule-based + LM + │
│ OptimizerManager │
│ + plugins matériel existants : Keba, Eastron, Waveshare │
└────────────┬──────────────┬──────────────┬───────────────┬───────────┘
│ (HTTP) │ (TIC local) │ (HTTP) │ (socket/REST)
┌────────────▼──────────────▼──────────────▼───────────────▼───────────┐
│ Couche services (hors nymea) │
│ Open-Meteo self-hosted tarif-provider powersync-optimizer │
│ (serveur, données) (propriétaire) (PROPRIÉTAIRE) │
│ météo+satellite grille TRV + RTE Tempo MPC, Perez, │
│ → rank/prix ombrage, arbitrage │
└───────────────────────────────────────────────────────────────────────┘
┌─ Couche infrastructure (existante) ───────────────────────────────────┐
│ Proxmox (LXC/VM) · reverse proxy · dépôt APT (reprepro/GPG, 3 canaux) │
└───────────────────────────────────────────────────────────────────────┘
Symétrie à retenir : pour la météo comme pour le tarif, on a un serveur (produit la donnée, maintenu une fois) + un plugin GPL (l'expose dans nymea). Le plugin ne contient jamais la logique du serveur.
3. Composants
Plugins nymea (GPL-3)
| Dépôt | Type (IID) |
Rôle |
|---|---|---|
openmeteo |
io.nymea.IntegrationPlugin |
Conditions météo/solaires actuelles (GHI/DNI/DHI, GTI par pan, satellite) |
linky |
io.nymea.IntegrationPlugin |
Compteur principal (TIC) : option, période HC/HP, ISOUSC, couleur Tempo, puissances |
tarif |
io.nymea.IntegrationPlugin |
Façade nymea du tarif-provider : expose currentMarketPrice + rank |
energy-plugin-etm |
io.nymea.EnergyPlugin |
Energy manager : rule-based surplus, load-management, OptimizerManager |
| (existants) Keba, Eastron, Waveshare | io.nymea.IntegrationPlugin |
Charges et compteurs pilotés |
Services (hors nymea)
| Composant | Licence | Nature | Rôle |
|---|---|---|---|
powersync-optimizer |
propriétaire | FastAPI, service | MPC, transposition Perez, dérating NOCT, masque d'ombrage, arbitrage |
| Open-Meteo self-hosted | AGPLv3 (amont) | serveur | Produit la donnée météo/satellite (prod commerciale) |
tarif-provider |
propriétaire | service | Grille TRV (maj 2×/an) + poll RTE Tempo → prix/rank par client |
Le
powersync-optimizern'est pas un plugin : c'est le cœur de l'écosystème, composant à part entière.
4. Frontière de licence
Ne doit JAMAIS entrer dans un plugin GPL :
- transposition Perez, dérating thermique (NOCT) ;
- modèle de prévision, MPC, scheduling sur horizon ;
- masque d'ombrage appris (grille azimut × élévation) ;
- stratégie de pondération tarifaire ;
- arbitrage économique (revente, coût de stockage).
Peut/doit être dans un plugin GPL :
- lecture des capteurs et de l'équilibre énergétique ;
- rule-based surplus (hystérésis, priorités) ;
- load-management (cf. §6) ;
OptimizerManager= transport pur : sérialise l'état → HTTP → applique les consignes. Aucune mathématique d'optimisation.
Communication arm's length : l'optimiseur et le tarif-provider sont des processus séparés joints par REST/socket. Ils ne lient pas libnymea ni aucun en-tête GPL. Échange de données, jamais de code.
Attributions à conserver :
- code amont : copyright nymea GmbH + chargebyte (fork
energy-plugin-etm), licence GPL-3 ; - données : Météo-France / EUMETSAT / Open-Meteo (CC-BY), RTE / CRE (Tempo, TRV).
(Ceci décrit la mécanique technique, pas un avis juridique formel.)
5. Flux
nymea (energy experience)
│
┌──────────────┬─────────────────┼──────────────────┬──────────────┐
openmeteo linky tarif energy-plugin-etm (Keba,
(weather) (TIC: période, (rank, prix) ├─ rule-based Eastron,
ISOUSC, Tempo) ├─ load-management Waveshare)
│ │ │ └─ OptimizerManager
│ │ │ │ (HTTP, transport)
▼ ▼ ▼ ▼
Open-Meteo (local) tarif-provider ◄─── powersync-optimizer
self-hosted (RTE Tempo, (récupère lui-même
grille TRV) météo + tarif en série)
L'optimiseur récupère lui-même ses séries (météo Open-Meteo, prix/rank du tarif-provider). Les plugins ne lui poussent que l'état temps réel et les contraintes.
6. Conventions partagées
Scalaire vs série
Plugin = valeur instantanée (état nymea). Service = série temporelle (horizon). Aucune série ne transite par un état nymea.
Azimut
Stockage en convention géographique (0=N, 90=E, 180=S, 270=O), cohérent avec les diagrammes de course du soleil et le masque d'ombrage. Conversion vers Open-Meteo au moment de la requête :
azimuth_openmeteo = azimuth_geographique − 180
Vocabulaire tarifaire (states nymea, adopté tel quel)
nymea n'a pas d'interface pricing formelle ; le vocabulaire est conventionnel (cf. plugin Awattar) :
| État | Unité | Rôle |
|---|---|---|
currentMarketPrice |
EuroCentPerKiloWattHour |
prix courant |
rank |
0–100 (plus bas = meilleur) | pondération (classement de l'heure) |
validUntil |
UnixTime |
fraîcheur |
averagePrice / lowestPrice / highestPrice |
EuroCentPerKiloWattHour |
stats ±12 h |
Pondération = rank. Le signal relatif de scheduling se mappe sur le rank natif de nymea ; rule-based et optimiseur le consomment. Tout fournisseur (Awattar, Tibber, tarif) exposant ce vocabulaire est interchangeable du point de vue de l'energy manager.
Load-management = contrainte dure, locale, prioritaire
La surveillance de la puissance souscrite (ISOUSC, protection fusible/disjoncteur) est une fonction de sécurité : elle agit en temps réel, sans dépendre du réseau ni de l'optimiseur, et a priorité absolue sur toute consigne — y compris celles de l'optimiseur. C'est une contrainte appliquée après coup par le plugin, pas une suggestion envoyée à l'optimiseur.
Dégradation gracieuse
Si l'optimiseur est injoignable ou renvoie un planning périmé (valid_until dépassé), OptimizerManager retombe sur le rule-based local. Le plugin fonctionne toujours seul. Résilience et hygiène de licence dans le même mécanisme.
7. Contrats d'interface (draft v0.1, à versionner)
POST {optimizerUrl}/optimize
État temps réel + contraintes → planning. L'optimiseur a déjà ses séries météo/tarif.
// requête
{
"timestamp": 0,
"site": { "gridPower": 0, "pvPower": 0, "batterySoc": 0 },
"loads": [ { "id": "keba1", "type": "evcharger",
"controllable": true, "min": 6, "max": 16, "constraints": {} } ]
}
// réponse
{
"valid_until": 0, // garde de fraîcheur
"setpoints": [ { "id": "keba1", "current": 10, "from": 0, "to": 0 } ]
}
GET {tariffUrl}/tariff/{client}/now et /forecast
// /now → scalaire (consommé par le plugin)
{ "rank": 18, "price": 13.25, "validUntil": 0 } // price en c€/kWh
// /forecast → série (consommée par l'optimiseur)
{ "horizon": [ { "t": 0, "rank": 18, "buy": 13.25, "sell": 10.0 } ] }
Données Open-Meteo
Voir le README/docs du dépôt openmeteo (variables, requêtes, conventions). Endpoint prévision (Météo-France) + endpoint satellite (MTG).
8. Configuration à l'installation
Un écran unique pour l'installateur (paramètres généraux de l'installation), mais deux destinations de données selon la frontière : le tarif va au tarif-provider/config locale, le matériel d'arbitrage va à l'optimiseur.
Tarif consommation
- Manuel : tarif unique ou HC/HP — saisie des prix et des plages horaires.
- Provider : choix du fournisseur et de l'option (EDF + Base/HC-HP/Tempo, Awattar, Tibber…).
- Sortie unifiée :
rank+ prix absolu (même en tarif fixe, via unranktrivial).
Tarif revente
- Même mécanisme (manuel ou provider).
- Cas dominant : OA surplus → constante par client. Le mécanisme identique permet de basculer en série (revente spot) sans changer le modèle.
Coût de stockage
Saisie : prix d'achat batterie, garantie (années), cycles garantis fabricant, DOD.
capacité_utile = capacité_nominale × DOD
cycles_effectifs = min(cycles_garantis, années × cycles_par_an_estimés)
c_batt (€/kWh) = prix_achat / (cycles_effectifs × capacité_utile)
- Attention : les cycles fabricant sont donnés à un DOD ; le DOD qualifie la capacité utile, il ne se multiplie pas une seconde fois.
- La garantie en années plafonne la durée de vie quand le cyclage annuel est faible (d'où le
min).
Rendement
η(aller-retour, défaut ~0,90, ajustable) — paramètre de l'optimiseur, par site.
| Saisie installateur | Stocké dans | Nature |
|---|---|---|
| Tarif conso (manuel/provider) | tarif-provider + config locale | tarif |
| Tarif revente (manuel/provider) | tarif-provider + config locale | tarif |
| Prix, garantie, cycles, DOD | config optimiseur (par install) | matériel |
η |
config optimiseur | matériel |
9. Niveaux d'optimisation (tiers)
| Tier | Optimisation | Données nécessaires | Où |
|---|---|---|---|
| Community | Surplus rule-based + load-management | rank (+ équilibre énergétique) |
plugin GPL |
| Auto / Predict | MPC, prévision, arbitrage | rank + p_achat + p_revente + c_batt + η |
optimiseur propriétaire |
Règle d'arbitrage (optimiseur) — stocker/revendre n'est rentable que si l'écart de prix dépasse le coût de cycle :
p_utilisation_évitée − p_achat(t_charge) > c_batt / η (stockage pour autoconso différée)
p_revente(t_vente) − p_achat(t_charge) > c_batt / η (revente depuis batterie)
Sans le terme c_batt, l'optimiseur sur-cycle la batterie pour des gains inexistants.
La détermination du tier (clé de licence / config) est lue par OptimizerManager, qui active ou non la stratégie distante — avec repli rule-based dans tous les cas.
10. Dépôts
| Dépôt | Contenu | Licence |
|---|---|---|
etm-powersync-docs |
ce document, source de vérité transverse | — |
openmeteo (nymea-plugin) |
plugin météo/solaire | GPL-3 |
linky (nymea-plugin) |
plugin compteur TIC | GPL-3 |
tarif-api (nymea-plugin) |
plugin façade tarif | GPL-3 |
powersync-energy-plugin-etm |
energy manager (fork nymea-energy-plugin-nymea) | GPL-3 |
powersync-optimizer |
service d'optimisation | propriétaire |
tarif-provider |
service tarif central | propriétaire |
Chaque dépôt porte son README (vue locale + renvoi ici), un CLAUDE.md (workflow multi-agent), et ses fichiers de licence/attribution.
Annexe — points encore ouverts
- Schéma exact et versionnement formel des contrats
/optimizeet/tariff(passer dedraftàv1). - Modèle fin de
c_batt(dépendance DOD/vieillissement) — plus tard ; coût plat suffisant pour démarrer. - Cas revente en série (spot) — prévu par le mécanisme, non prioritaire.