La prevision entre dans « La journee » et sur le telephone

Suite du correctif de l onglet Home Assistant. « La journee » avait le meme
angle mort : cadre sur le jour civil, il s arretait a l heure en cours.

Fenetre portee a la journee ENTIERE (dashboard() gagne un parametre `jusqu`),
serie « Encore attendu » en gris translucide a la suite des barres mesurees,
et colonne « Reste attendu » dans le bandeau du haut, a cote de « Solaire
produit ».

Sur le telephone, aucun panneau ajoute — un panneau de plus y est un ecran de
plus a faire defiler. « Soleil restant » rejoint le bandeau Maintenant, a cote
de Excedent ; « Soleil demain » rejoint La nuit qui vient, puisque c est lui
qui decide jusqu ou la batterie peut descendre.

Trois pieges, tous dans la meme direction. La mesure ne doit pas suivre la
fenetre dans le futur : ENERGIE_SQL construisait son axe entre les deux macros
puis reportait la derniere valeur connue, ce qui aurait rempli les heures a
venir avec la puissance de l instant et gonfle l energie du jour — sa borne
haute est desormais least($__timeTo(), now()). FULL OUTER JOIN et non LEFT :
une periode a venir n a aucune ligne de mesure. Et borne haute stricte, sans
quoi une barre « 18/09 00 h » apparaissait dans La journee.

L heure EN COURS n a volontairement pas de barre de prevision : elle est deja
mesuree pour ses minutes ecoulees.

73/73 requetes valides — mais ce controle prouve l execution, pas la grandeur.
Les deux requetes de La journee ont donc ete rejouees a la main avec la vraie
fenetre : 24 lignes, mesures jusqu a 02 h, prevision de 03 h a 23 h, somme des
barres 36,95 kWh contre 37,0 annonces par le bandeau. C est ce recoupement qui
a fait apparaitre le troisieme piege.

Corrige au passage la note du 08/09 sur l acces a l API Grafana : les
apostrophes du .env sont SIMPLES et non doubles, verifie a l octet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
Tallagrand Thierry
2026-09-17 02:37:43 +02:00
parent a6baad54dc
commit 1541ccf7b4
5 changed files with 316 additions and 37 deletions

View File

@@ -62,7 +62,7 @@
{
"type": "stat",
"title": "Maintenant",
"description": "Marge = ce que la batterie a, moins ce qu'il lui faut pour tenir jusqu'au relais du solaire. Negative, la nuit ne passe pas sans reseau.",
"description": "Marge = ce que la batterie a, moins ce qu'il lui faut pour tenir jusqu'au relais du solaire. Negative, la nuit ne passe pas sans reseau. « Soleil restant » est le seul chiffre de ce bandeau qui ne soit pas une mesure : c'est la derniere prevision pour les heures qui restent aujourd'hui, l'heure en cours exclue.",
"datasource": {
"type": "grafana-postgresql-datasource",
"uid": "evcs-pg"
@@ -77,7 +77,7 @@
"format": "table",
"rawQuery": true,
"editorMode": "code",
"rawSql": "SELECT\n (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_battery_soc'\n ORDER BY ts DESC LIMIT 1) AS \"Batterie\",\n (SELECT soc_pct - soc_requis_pct FROM bilan\n WHERE soc_requis_pct IS NOT NULL ORDER BY ts DESC LIMIT 1) AS \"Marge\",\n (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_pv_power_system'\n ORDER BY ts DESC LIMIT 1)\n- (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_consumption_power_l1'\n ORDER BY ts DESC LIMIT 1) AS \"Excedent\""
"rawSql": "SELECT\n (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_battery_soc'\n ORDER BY ts DESC LIMIT 1) AS \"Batterie\",\n (SELECT soc_pct - soc_requis_pct FROM bilan\n WHERE soc_requis_pct IS NOT NULL ORDER BY ts DESC LIMIT 1) AS \"Marge\",\n (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_pv_power_system'\n ORDER BY ts DESC LIMIT 1)\n- (SELECT valeur FROM mesure WHERE cle = 'sensor.victron_consumption_power_l1'\n ORDER BY ts DESC LIMIT 1) AS \"Excedent\",\n (SELECT round(coalesce(sum(kwh), 0)::numeric, 1)\n FROM (\n SELECT (c.jour + (u.i - 1) * interval '1 hour') AT TIME ZONE 'Europe/Paris' AS heure,\n u.v AS kwh\n FROM (SELECT DISTINCT ON (jour) jour, horaire FROM prevision\n WHERE jour >= current_date ORDER BY jour, publie_a DESC) c,\n unnest(c.horaire) WITH ORDINALITY AS u(v, i)\n WHERE (c.jour + (u.i - 1) * interval '1 hour') AT TIME ZONE 'Europe/Paris'\n > date_trunc('hour', now())\n) p\n WHERE p.heure < date_trunc('day', now()) + interval '1 day')\n AS \"Soleil restant\""
}
],
"gridPos": {
@@ -202,6 +202,29 @@
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Soleil restant"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
},
{
"id": "decimals",
"value": 1
},
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "#9e9e9e"
}
}
]
}
]
},
@@ -226,7 +249,7 @@
{
"type": "stat",
"title": "La nuit qui vient",
"description": "Energie a couvrir d'ici l'heure ou la production repasse au-dessus de la consommation, et le niveau de batterie qu'il faudrait pour y arriver.",
"description": "Energie a couvrir d'ici l'heure ou la production repasse au-dessus de la consommation, et le niveau de batterie qu'il faudrait pour y arriver. « Soleil demain » dit de combien la batterie pourra se refaire une fois la nuit passee : c'est lui qui decide jusqu'ou on peut la laisser descendre.",
"datasource": {
"type": "grafana-postgresql-datasource",
"uid": "evcs-pg"
@@ -241,7 +264,7 @@
"format": "table",
"rawQuery": true,
"editorMode": "code",
"rawSql": "SELECT round(energie_a_couvrir_kwh::numeric, 1) AS \"A couvrir\",\n round(soc_requis_pct::numeric) AS \"SOC requis\",\n heure_croisement AS \"Relais du solaire\"\nFROM bilan ORDER BY ts DESC LIMIT 1"
"rawSql": "SELECT round(energie_a_couvrir_kwh::numeric, 1) AS \"A couvrir\",\n round(soc_requis_pct::numeric) AS \"SOC requis\",\n heure_croisement AS \"Relais du solaire\",\n (SELECT round(coalesce(sum(kwh), 0)::numeric, 1)\n FROM (\n SELECT (c.jour + (u.i - 1) * interval '1 hour') AT TIME ZONE 'Europe/Paris' AS heure,\n u.v AS kwh\n FROM (SELECT DISTINCT ON (jour) jour, horaire FROM prevision\n WHERE jour >= current_date ORDER BY jour, publie_a DESC) c,\n unnest(c.horaire) WITH ORDINALITY AS u(v, i)\n WHERE (c.jour + (u.i - 1) * interval '1 hour') AT TIME ZONE 'Europe/Paris'\n > date_trunc('hour', now())\n) p\n WHERE p.heure >= date_trunc('day', now()) + interval '1 day')\n AS \"Soleil demain\"\nFROM bilan ORDER BY ts DESC LIMIT 1"
}
],
"gridPos": {
@@ -314,6 +337,29 @@
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Soleil demain"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
},
{
"id": "decimals",
"value": 1
},
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "#9e9e9e"
}
}
]
}
]
},