From a8947579fa48bd79ec72803a8599bdd75fd4567f Mon Sep 17 00:00:00 2001 From: Patrick Schurig Date: Wed, 9 Sep 2026 07:56:31 +0200 Subject: [PATCH] =?UTF-8?q?release:=201.15.2+etm64=20=E2=80=94=20d=C3=A9ge?= =?UTF-8?q?l=20de=20la=20courbe,=20cl=C3=A9=20de=20contenu,=20et=20la=20r?= =?UTF-8?q?=C3=A8gle=20de=20fusion=20=C3=A9crite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p --- debian-qt5/changelog | 22 +++++++++++ docs/DESIGN_PREVISION_PV.md | 52 +++++++++++++++++++++++++ energyplugin/nymeaenergyjsonhandler.cpp | 9 ++++- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/debian-qt5/changelog b/debian-qt5/changelog index 162dc0c..a656b9c 100644 --- a/debian-qt5/changelog +++ b/debian-qt5/changelog @@ -1,3 +1,25 @@ +powersync-energy-plugin-nymea (1.15.2+etm64) trixie; urgency=medium + + * DÉGEL. +etm63 refusait toute réécriture sous un issuedAt inchangé et gelait + donc la courbe sur les valeurs du premier cycle — un écran aurait montré une + prévision périmée sans le dire. La clé de révision devient LE CONTENU : + (targetAt, siteId, empreinte de la courbe). issuedAt et model deviennent des + attributs, et issuedAt peut être NUL. + * Établi par le producteur, mesuré : issuedAt vient d'un domaine AROME qui ne + fournit AUCUNE valeur de la courbe, et le domaine qui les fournit n'expose + pas de meta.json. Le seamless fusionne deux domaines avec une rampe sur les + trois dernières heures du domaine 15 min — les premiers créneaux sont donc + plus FRAIS que le reste, et un seul instant ne peut pas dater la courbe. + * issuedAt == 0 n'est plus un refus : refuser une courbe exploitable parce + qu'un ATTRIBUT manque reviendrait à jeter la donnée pour son étiquette. + * Les instants d'observation passent en millisecondes : deux révisions écrites + dans la même seconde n'étaient pas ordonnables, et la courbe rendait des + doublons. + * Migration v1 -> v2 : la table est REFAITE. Les lignes v1 sont clés sur un run + qui n'identifie pas leur contenu et ont pu être écrasées. + + -- Patrick Schurig Wed, 09 Sep 2026 07:56:31 +0200 + powersync-energy-plugin-nymea (1.15.2+etm63) trixie; urgency=medium * UN RUN EST IMMUABLE. Des valeurs neuves sous une identité de run connue diff --git a/docs/DESIGN_PREVISION_PV.md b/docs/DESIGN_PREVISION_PV.md index 627e2a9..01d0083 100644 --- a/docs/DESIGN_PREVISION_PV.md +++ b/docs/DESIGN_PREVISION_PV.md @@ -951,3 +951,55 @@ satellite, mélange court terme, ou deux domaines sur des runs différents. **Il diverge et sur quelles heures.** L'explication n'est pas acquise, et rien ici n'en dépend : la clé de contenu est correcte quelle qu'en soit la cause. C'est précisément pourquoi elle est préférable — elle n'a pas besoin qu'on comprenne le producteur pour être juste. + + +--- + +## 21. Pourquoi les créneaux proches bougent — la règle de fusion du `seamless` + +Le producteur a établi le mécanisme, **mesuré et non documenté par Open-Meteo** : + +``` +seamless = w · arome_france_15min + (1 − w) · arome_france +``` + +Relevé le 2026-09-09 à 07:45, `w` déduit valeur par valeur : `w = 1,00` de 08:00 à 10:00, +`0,75` à 11:00, `0,50` à 12:00, `0,25` à 13:00, `0` à partir de 14:00. **Rampe linéaire sur les +trois dernières heures de l'horizon du domaine 15 min.** + +**Ce n'est pas un nowcast satellite** — le produit satellite ne sert que le passé, vérifié. Les +premières heures **égalent exactement** `arome_france_15min` : c'est le **même modèle, initialisé +plus récemment**. + +### 21.1 L'ÂGE EST LOCAL AU CRÉNEAU, pas global à la courbe + +Le domaine 15 min se rafraîchit **toutes les heures**, l'horaire **toutes les 3 h**. Les ~5 +premiers créneaux sont donc plus frais que le reste — **et c'est l'unique raison pour laquelle +ils bougent sous un `issuedAt` stable.** + +> **Un seul `issuedAt` ne peut pas dater une courbe dont les parties n'ont pas le même âge.** + +Ce n'est pas une limite de notre modèle : c'est une propriété de la donnée. La clé de contenu s'en +accommode sans rien savoir du mécanisme — **c'est précisément pourquoi elle est préférable.** + +**Conséquence à tenir** : `issuedAt` est stocké comme attribut de la RÉVISION et n'est **pas** +publié par créneau. Il ne doit pas le devenir : le publier point par point affirmerait un âge +uniforme que la fusion dément. Si une indication de fraîcheur est un jour affichée, elle est +**dégradée avec l'horizon**, jamais uniforme. + +### 21.2 L'avertissement qui compte pour l'écran + +L'erreur **météorologique** décroît sur le proche. **Le biais de CONVERSION, lui, ne bouge pas** : +ombrage, encrassement, température de module et écrêtage onduleur se trompent **autant à trois +heures qu'à trente-six**, et tous dans le sens optimiste. + +> **Un horizon proche améliore la météo, jamais la conversion.** Il ne faut pas laisser +> « prévision proche plus fiable » se lire comme « chiffre proche plus juste ». + +C'est le §3 sous un angle neuf, et le plus dangereux : le §3 disait qu'un plafond systématique se +lit comme une contre-performance. Ici s'ajoute qu'une **confiance croissante sur le proche** +donnerait à ce plafond l'apparence d'une mesure. Deux erreurs qui se composent — l'une fait +douter de l'installation, l'autre fait croire au chiffre qui la fait douter. + +Écrit dans la description de `GetPvForecast`, pas seulement ici : c'est un client qui construira +l'écran, et c'est le contrat qu'il lira. diff --git a/energyplugin/nymeaenergyjsonhandler.cpp b/energyplugin/nymeaenergyjsonhandler.cpp index ba3408f..b93fa9a 100644 --- a/energyplugin/nymeaenergyjsonhandler.cpp +++ b/energyplugin/nymeaenergyjsonhandler.cpp @@ -319,7 +319,14 @@ NymeaEnergyJsonHandler::NymeaEnergyJsonHandler(SpotMarketManager *spotMarketMana "none of the curve's values), so revisions are keyed on the content itself. " "'firstSeenAt' is when this content first appeared - it ORDERS revisions; " "'lastSeenAt' is the last time it was republished unchanged - FRESHNESS. " - "Neither is an emission time, and no horizon may be computed from them."; + "Neither is an emission time, and no horizon may be computed from them. " + "The provider blends two model domains, so the FIRST HOURS ARE FRESHER THAN " + "THE REST - a single age cannot date the whole curve, which is why none is " + "published per slot. And beware what a near horizon buys: it reduces the " + "METEOROLOGICAL error, never the CONVERSION bias - shading, soiling, module " + "temperature and inverter clipping are as wrong at three hours as at " + "thirty-six, and all in the optimistic direction. 'Nearer forecast is more " + "reliable' must NOT be shown as 'nearer figure is more accurate'."; registerMethod("GetPvForecast", description, params, returns, Types::PermissionScopeControlThings); // Désignation GLOBALE, sur le modèle d'Energy.SetRootMeter — même nature : une source unique