docs: contrat de données UI rev.5 — réserve décision-2 levée (cumuls séparés)
Intègre la vérif terrain (sonde .75) : GetPowerBalanceLogs sépare import/export en cumulé (totalAcquisition / totalReturn) → autoconso/autonomie dérivables des logs, la réserve de la décision-2 est levée. Aligne le doc tracké sur le code (seam EnergyRatiosInterim, commit 3821bf3). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3821bf3fdb
commit
f755c727ee
@ -2,6 +2,10 @@
|
||||
|
||||
> Compagnon de `DASHBOARD_SPEC.md`. Tranche la question récurrente
|
||||
> « **qui calcule les valeurs affichées ?** » pour chaque écran.
|
||||
> Rev. 5 — sonde `.75` : réserve décision-2 **levée** (cumuls séparés) ; ajout de
|
||||
> 3 garde-fous : 2 conventions de signe (§7.1), buckets par Δ-de-cumuls (§7.3),
|
||||
> gestion reset compteurs (§2.1/§8.1) ; RP calquées sur le template nymea, Influx
|
||||
> v1.6.7 confirmée.
|
||||
> Rev. 4 — §8.3 corrigé : **réutiliser l'InfluxDB nymea** (pas SQLite), DB ETM
|
||||
> dédié + rollups natifs (retention policies) + checkpoint local pour le contrôle
|
||||
> vivant. Alerte : tag Docker `latest` → InfluxDB 3 Core (72 h de rétention).
|
||||
@ -113,14 +117,16 @@ autonomie = (consommation − import) / consommation
|
||||
autoconsommation = (production − export) / production
|
||||
```
|
||||
|
||||
- **autonomie** : dérivable directement, `import` est dans les logs. ✅
|
||||
- **autoconsommation** : exige **l'export (return) comme cumul DISTINCT**.
|
||||
⚠️ **Point bloquant à vérifier sur la sonde** : `acquisition` est-il *net
|
||||
signé* (import − export en un nombre) ou import/export **séparés** ?
|
||||
- séparés → dérivable depuis logs ;
|
||||
- net → **non récupérable** des logs ⇒ l'energymanager doit **intégrer
|
||||
import et export lui-même** (il voit la P réseau signée en continu, +
|
||||
connaissance Invariant 3). C'est ce qui rend #2 *architecturalement obligé*.
|
||||
- **autonomie** : `import` = Δ `totalAcquisition`. ✅
|
||||
- **autoconsommation** : `export` = Δ `totalReturn`. ✅
|
||||
**RÉSERVE LEVÉE (sonde `.75`)** : le réseau *instantané* est net-signé (un seul
|
||||
champ `acquisition`), MAIS les **cumuls `totalAcquisition` / `totalReturn` sont
|
||||
séparés**. Donc les deux ratios sont dérivables des logs par **deltas de cumuls**
|
||||
— pas besoin que le plugin intègre import/export pour l'historique.
|
||||
- ⚠️ **Compteurs = monotones requis.** Δ d'un cumul n'est valide que si le compteur
|
||||
ne reset jamais. Sur reset (restart nymead, re-add thing, rollover) → Δ < 0 :
|
||||
détecter (`Δ < 0` ⇒ reset, reseed sur la nouvelle valeur, ne pas créer un bucket
|
||||
négatif). À gérer côté plugin **et** dans les CQ de rollup.
|
||||
- Ces formules sont **correctes avec batterie** : import/export au compteur
|
||||
réseau nettent déjà les flux batterie ; PV→batterie→maison compte comme
|
||||
autoconsommé (pas exporté). Pas de correction round-trip.
|
||||
@ -216,9 +222,19 @@ puissance que s'il est un *thing avec un state `currentPower`* (interfaces
|
||||
`smartmeter`/`energymeter`/consumer/producer, `logged: true`).
|
||||
→ **La granularité d'optimisation Héos = la granularité de comptage.**
|
||||
|
||||
⚠️ **Convention de signe nymea** : `currentPower` est toujours du point de vue
|
||||
**consommateur** → **négatif pour un producteur** (le PV a un `currentPower` < 0).
|
||||
Signe canonique, à ne jamais « deviner » côté app (cause du bug autoconso / `.abs()`).
|
||||
⚠️ **DEUX conventions de signe coexistent — ne pas les confondre** (piège « fix »
|
||||
d'un faux bug) :
|
||||
1. **Thing-level `currentPower`** : point de vue **consommateur** → **négatif pour
|
||||
un producteur** (le PV a `currentPower` < 0). C'est la cause du bug autoconso /
|
||||
`.abs()`.
|
||||
2. **Power balance agrégé** (`production` / `consumption` / `acquisition`) :
|
||||
`production` **positif**, `consumption` positif, `acquisition` **net signé**
|
||||
(+ import / − export). (Sonde `.75` : `acquisition = -231`, et un
|
||||
`currentPowerProduction` **positif** au niveau balance — normal, ce n'est PAS
|
||||
le `currentPower` thing-level.)
|
||||
|
||||
Le signe est **canonique des deux côtés** — l'app ne le devine jamais ; elle ne
|
||||
dérive que le *sens* d'un flux à partir du signe (§1.1), rien d'autre.
|
||||
|
||||
### 7.2 Carte de comptage (état du parc)
|
||||
|
||||
@ -249,9 +265,16 @@ Signe canonique, à ne jamais « deviner » côté app (cause du bug autoconso /
|
||||
- **energymanager = série historique canonique** par consommateur/générateur,
|
||||
échantillonnée à la résolution du MPC (buckets 15 min), Invariant-3-correcte.
|
||||
- **logs nymea = filet / contrôle croisé**, pas l'entrée primaire de Héos.
|
||||
- Justification : la Route A (logs nymea) impose le downsampling/rétention de
|
||||
nymea sans contrôle du schéma, et ne sépare pas import/export. Seul le plugin
|
||||
peut scinder import/export depuis la P réseau signée et figer la décomposition.
|
||||
- **Construire les buckets par Δ de compteurs, pas par intégration du signal live**
|
||||
(sonde `.75` : les cumuls sont séparés) :
|
||||
- grid import/export du bucket = Δ `totalAcquisition` / Δ `totalReturn` ;
|
||||
- conso par appareil = Δ `thing.totalEnergyConsumed` ;
|
||||
- exact, pas de drift d'intégration. L'intégration du signal net-signé ne sert
|
||||
qu'au temps réel sous le bucket (affichage), pas à la série stockée.
|
||||
- ⚠️ même gestion de reset qu'en §2.1/§8.1 (Δ < 0 ⇒ reset).
|
||||
- Justification Route B : la Route A (logs nymea bruts) impose le downsampling/
|
||||
rétention de nymea sans contrôle du schéma ; le plugin reste seul à figer la
|
||||
décomposition Invariant-3 dans la série curée.
|
||||
|
||||
---
|
||||
|
||||
@ -263,6 +286,9 @@ Signe canonique, à ne jamais « deviner » côté app (cause du bug autoconso /
|
||||
|
||||
- On stocke le **brut intégrable** par bucket : production, consommation,
|
||||
import, export (séparés !), + par charge pilotée, + charge/décharge batterie.
|
||||
→ obtenu par **Δ de cumuls** (`totalProduction`, `totalReturn`,
|
||||
`totalConsumption`, `totalAcquisition`, `thing.totalEnergyConsumed`), pas par
|
||||
intégration du signal live (§7.3). **Gérer le reset** (Δ < 0 ⇒ reseed).
|
||||
- Les **ratios ne sont JAMAIS stockés** comme donnée primaire — vues dérivées :
|
||||
|
||||
```
|
||||
@ -296,15 +322,18 @@ ses **retention policies + downsampling (CQ 1.x / tasks 2.x)** font les rollups
|
||||
**corrige au passage le « shard accumulation »** qui faisait crash-looper l'instance
|
||||
(les shards s'empilaient faute de purge).
|
||||
|
||||
- **DB / bucket ETM dédié** — pas dans les measurements nymea. Isole ta donnée des
|
||||
upgrades/migrations nymea et te donne ta propre rétention.
|
||||
- **Rollups par paliers** (retention policies dédiées) :
|
||||
- 15 min → ~30 jours · horaire → ~2 ans · journalier → indéfini
|
||||
- ⚠️ **Pinner la version Influx.** Le tag Docker `latest` pointe désormais vers
|
||||
**InfluxDB 3 Core**, qui en OSS impose **72 h de rétention** + limite 5 DB →
|
||||
destruction silencieuse de l'historique. Le diagnostic « shard accumulation »
|
||||
= TSM = on est en **1.x / 2.x** (bonne version). Ne jamais laisser un upgrade
|
||||
auto basculer en 3 Core.
|
||||
- **DB / bucket ETM dédié** — pas dans la base `nymeatest` de nymea. Isole ta
|
||||
donnée des upgrades/migrations nymea et te donne ta propre rétention.
|
||||
- **Calquer les paliers sur le template RP nymea existant** (sonde `.75`) plutôt
|
||||
que d'inventer : `live 24h · minutes 7j · hours 3 ans · days 20 ans`
|
||||
(+ `discrete 1 an`). Cohérence opérationnelle, CQ alignées.
|
||||
- ⚠️ **Ne pas écrire dans `autogen` (DEFAULT, rétention ∞).** C'est le vrai risque
|
||||
de croissance (pas un shard runaway : `nymeatest` n'a que 2 shards aujourd'hui).
|
||||
Router explicitement les writes ETM vers les RP tiers.
|
||||
- ⚠️ **Version Influx** : `.75` est en **v1.6.7** ✓ (pas 3 Core, pas de piège
|
||||
72 h). Le tag Docker `latest` pointe désormais vers **InfluxDB 3 Core**
|
||||
(rétention 72 h + limite 5 DB en OSS) → **pinner**, ne jamais laisser un upgrade
|
||||
auto basculer.
|
||||
- **Checkpoint local minuscule** (fichier / petit SQLite) pour l'**état de contrôle
|
||||
vivant** (plan en cours d'exécution, dernier setpoint). Si Influx tombe, Héos ne
|
||||
doit **ni hard-fail ni perdre le plan exécuté** — dégradé propre, cohérent avec
|
||||
@ -334,9 +363,9 @@ du « Plan de la journée »).
|
||||
(condition : animation respecte les sens figés §1.1, jamais de particule à
|
||||
contre-sens à travers Héos). ✅ tranché.
|
||||
2. Source des ratios : **state du plugin energymanager** (ni app, ni Energy
|
||||
experience). Court terme : dérivation depuis cumuls via §2.1, **sous réserve**
|
||||
que l'export soit loggé séparément — sinon le plugin intègre import/export
|
||||
lui-même. ✅ tranché.
|
||||
experience). Dérivation depuis cumuls via §2.1. **Réserve levée** (sonde `.75` :
|
||||
`totalAcquisition`/`totalReturn` séparés) — dérivable des logs, le plugin n'a
|
||||
pas à intégrer pour l'historique. ✅ tranché.
|
||||
3. Périmètre Things app : **hand-off nymea-app + MVP read-only client** ;
|
||||
**ModbusRTU master en premier** (§6, bloquant pour SDM/abbterra). Wizard
|
||||
ciblé seulement si vraiment nécessaire. ✅ tranché.
|
||||
@ -349,10 +378,18 @@ du « Plan de la journée »).
|
||||
dédié, rollups via retention policies) + **checkpoint local** pour l'état de
|
||||
contrôle vivant. ⚠️ pinner Influx en **1.x/2.x** (pas 3 Core / 72 h). ✅ tranché.
|
||||
|
||||
### Reste ouvert (à lever avant code §2 / §8)
|
||||
### Vérifié sur sonde (`.75`)
|
||||
|
||||
- `acquisition` dans `GetPowerBalanceLogs` = **net signé** ou **import/export
|
||||
séparés** ? Détermine si l'autoconso est dérivable des logs ou doit être
|
||||
intégrée par le plugin (§2.1 / §8.1).
|
||||
- **Carte de comptage §7.2** : décider quels consommateurs non mesurés (PAC,
|
||||
clim) justifient un compteur matériel pour une optim fine.
|
||||
- ✅ **PowerBalance** : instantané net-signé (`acquisition`), cumuls
|
||||
`totalAcquisition`/`totalReturn` **séparés** → ratios dérivables par Δ (§2.1).
|
||||
- ✅ **Influx v1.6.7** (pas 3 Core). DB nymea = `nymeatest`, RP existantes
|
||||
(`live/minutes/hours/days/discrete`), DEFAULT = `autogen` ∞ (le vrai risque).
|
||||
|
||||
### Reste ouvert (vrai)
|
||||
|
||||
- **Confirmer les signes sur box réelle** (`.120`) — `.75` est statique/factice
|
||||
(totaux à 0). L'archi plugin=source rend l'app sign-agnostic, mais valider.
|
||||
- **Carte de comptage §7.2** : décider produit par produit quels consommateurs
|
||||
non mesurés (PAC, clim) justifient un compteur matériel pour une optim fine.
|
||||
- **Gestion reset des compteurs** (§2.1/§7.3/§8.1) : implémenter la détection
|
||||
Δ < 0 côté plugin **et** dans les CQ de rollup.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user