Le bilan devient un tableau, parce que le panneau stat ne le rendait pas

Quatre tentatives sur le panneau stat : selecteur de champs, unites, bornes de
l'axe, GROUP BY, retrait de la colonne texte et de son override. A chaque fois
sept « — » a l'ecran.

L'acces a l'API Grafana, obtenu entre-temps, a tranche : /api/ds/query montre
que le serveur renvoyait bien sept champs de type number avec leurs valeurs, y
compris sur la fenetre exacte de la derniere capture. Ce n'etait donc ni la
requete, ni le cache du navigateur, ni le provisioning — md5 du fichier servi
et version en base verifies. Le panneau recevait les donnees et ne les rendait
pas.

Le bilan sort desormais en LIGNES, une par grandeur, dans un panneau table :
celui-ci affiche toujours ce qu'il recoit, et le format se lit tres bien pour un
bilan. L'unite est portee par le libelle, ce qui permet de melanger kWh et
pourcentage dans la meme colonne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
Tallagrand Thierry
2026-09-08 00:19:46 +02:00
parent c387415c4f
commit 2569718ddd
2 changed files with 65 additions and 156 deletions

View File

@@ -60,9 +60,9 @@
},
"panels": [
{
"type": "stat",
"type": "table",
"title": "Le bilan depuis minuit",
"description": "Sept chiffres, une ligne. L'autonomie est la part de la consommation de la maison qui n'est PAS venue du reseau. « Batterie rendue » est ce qu'elle a restitue, donc du solaire differe et non une consommation supplementaire.",
"description": "Sept grandeurs, une par ligne. L'autonomie est la part de la consommation de la maison qui n'est PAS venue du reseau. « Batterie rendue » est ce qu'elle a restitue, donc du solaire differe et non une consommation supplementaire.",
"datasource": {
"type": "grafana-postgresql-datasource",
"uid": "evcs-pg"
@@ -77,7 +77,7 @@
"format": "table",
"rawQuery": true,
"editorMode": "code",
"rawSql": "WITH bornes AS (\n SELECT min(ts) AS d, max(ts) AS f FROM mesure WHERE $__timeFilter(ts)\n),\naxe AS (\n SELECT generate_series(date_trunc('minute', (SELECT d FROM bornes)),\n date_trunc('minute', (SELECT f FROM bornes)),\n interval '1 minute') AS t\n),\nreleve AS (\n SELECT date_trunc('minute', ts) AS t,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_pv_power_system') AS pv,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_pv_power_system'))[1] AS d_pv,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_consumption_power_l1') AS maison,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_consumption_power_l1'))[1] AS d_maison,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_grid_power_l1') AS reseau,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_grid_power_l1'))[1] AS d_reseau,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_evcs_ac_power') AS voiture,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_evcs_ac_power'))[1] AS d_voiture,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_battery_power') AS batterie,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_battery_power'))[1] AS d_batterie\n FROM mesure WHERE $__timeFilter(ts) GROUP BY 1\n),\npar_minute AS (\n SELECT axe.t, releve.pv, releve.d_pv, releve.maison, releve.d_maison, releve.reseau, releve.d_reseau, releve.voiture, releve.d_voiture, releve.batterie, releve.d_batterie\n FROM axe LEFT JOIN releve USING (t)\n),\npaliers AS (\n SELECT t, pv, d_pv, maison, d_maison, reseau, d_reseau, voiture, d_voiture, batterie, d_batterie,\n count(d_pv) OVER (ORDER BY t) AS g_pv,\n count(d_maison) OVER (ORDER BY t) AS g_maison,\n count(d_reseau) OVER (ORDER BY t) AS g_reseau,\n count(d_voiture) OVER (ORDER BY t) AS g_voiture,\n count(d_batterie) OVER (ORDER BY t) AS g_batterie\n FROM par_minute\n),\nreport AS (\n SELECT t,\n coalesce(pv, first_value(d_pv) OVER (PARTITION BY g_pv ORDER BY t), 0) AS pv,\n coalesce(maison, first_value(d_maison) OVER (PARTITION BY g_maison ORDER BY t), 0) AS maison,\n coalesce(reseau, first_value(d_reseau) OVER (PARTITION BY g_reseau ORDER BY t), 0) AS reseau,\n coalesce(voiture, first_value(d_voiture) OVER (PARTITION BY g_voiture ORDER BY t), 0) AS voiture,\n coalesce(batterie, first_value(d_batterie) OVER (PARTITION BY g_batterie ORDER BY t), 0) AS batterie\n FROM paliers\n)\nSELECT\n round((sum(pv) / 60.0 / 1000.0)::numeric, 1) AS \"Solaire produit\",\n round((sum(maison) / 60.0 / 1000.0)::numeric, 1) AS \"Maison consommee\",\n round((sum(reseau) / 60.0 / 1000.0)::numeric, 1) AS \"Reseau importe\",\n round((sum(voiture) / 60.0 / 1000.0)::numeric, 1) AS \"Voiture\",\n round((sum(greatest(batterie, 0)) / 60.0 / 1000.0)::numeric, 1) AS \"Batterie chargee\",\n round((sum(greatest(-batterie, 0)) / 60.0 / 1000.0)::numeric, 1) AS \"Batterie rendue\",\n round((100.0 * greatest(sum(maison) - sum(reseau), 0)\n / nullif(sum(maison), 0))::numeric, 0) AS \"Autonomie\"\nFROM report GROUP BY (1 = 1)"
"rawSql": "WITH bornes AS (\n SELECT min(ts) AS d, max(ts) AS f FROM mesure WHERE $__timeFilter(ts)\n),\naxe AS (\n SELECT generate_series(date_trunc('minute', (SELECT d FROM bornes)),\n date_trunc('minute', (SELECT f FROM bornes)),\n interval '1 minute') AS t\n),\nreleve AS (\n SELECT date_trunc('minute', ts) AS t,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_pv_power_system') AS pv,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_pv_power_system'))[1] AS d_pv,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_consumption_power_l1') AS maison,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_consumption_power_l1'))[1] AS d_maison,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_grid_power_l1') AS reseau,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_grid_power_l1'))[1] AS d_reseau,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_evcs_ac_power') AS voiture,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_evcs_ac_power'))[1] AS d_voiture,\n avg(valeur) FILTER (WHERE cle = 'sensor.victron_battery_power') AS batterie,\n (array_agg(valeur ORDER BY ts DESC) FILTER (WHERE cle = 'sensor.victron_battery_power'))[1] AS d_batterie\n FROM mesure WHERE $__timeFilter(ts) GROUP BY 1\n),\npar_minute AS (\n SELECT axe.t, releve.pv, releve.d_pv, releve.maison, releve.d_maison, releve.reseau, releve.d_reseau, releve.voiture, releve.d_voiture, releve.batterie, releve.d_batterie\n FROM axe LEFT JOIN releve USING (t)\n),\npaliers AS (\n SELECT t, pv, d_pv, maison, d_maison, reseau, d_reseau, voiture, d_voiture, batterie, d_batterie,\n count(d_pv) OVER (ORDER BY t) AS g_pv,\n count(d_maison) OVER (ORDER BY t) AS g_maison,\n count(d_reseau) OVER (ORDER BY t) AS g_reseau,\n count(d_voiture) OVER (ORDER BY t) AS g_voiture,\n count(d_batterie) OVER (ORDER BY t) AS g_batterie\n FROM par_minute\n),\nreport AS (\n SELECT t,\n coalesce(pv, first_value(d_pv) OVER (PARTITION BY g_pv ORDER BY t), 0) AS pv,\n coalesce(maison, first_value(d_maison) OVER (PARTITION BY g_maison ORDER BY t), 0) AS maison,\n coalesce(reseau, first_value(d_reseau) OVER (PARTITION BY g_reseau ORDER BY t), 0) AS reseau,\n coalesce(voiture, first_value(d_voiture) OVER (PARTITION BY g_voiture ORDER BY t), 0) AS voiture,\n coalesce(batterie, first_value(d_batterie) OVER (PARTITION BY g_batterie ORDER BY t), 0) AS batterie\n FROM paliers\n)\n,\ntotaux AS (\n SELECT sum(pv) AS pv, sum(maison) AS maison, sum(reseau) AS reseau,\n sum(voiture) AS voiture,\n sum(greatest(batterie, 0)) AS bat_plus,\n sum(greatest(-batterie, 0)) AS bat_moins\n FROM report\n)\nSELECT x.rang, x.grandeur AS \"Grandeur\", x.valeur AS \"Valeur\"\nFROM totaux, LATERAL (VALUES\n (1, 'Solaire produit (kWh)', round((pv / 60.0 / 1000.0)::numeric, 1)),\n (2, 'Maison consommee (kWh)', round((maison / 60.0 / 1000.0)::numeric, 1)),\n (3, 'Reseau importe (kWh)', round((reseau / 60.0 / 1000.0)::numeric, 1)),\n (4, 'Voiture (kWh)', round((voiture / 60.0 / 1000.0)::numeric, 1)),\n (5, 'Batterie chargee (kWh)', round((bat_plus / 60.0 / 1000.0)::numeric, 1)),\n (6, 'Batterie rendue (kWh)', round((bat_moins/ 60.0 / 1000.0)::numeric, 1)),\n (7, 'Autonomie (%)', round((100.0 * greatest(maison - reseau, 0)\n / nullif(maison, 0))::numeric, 0))\n) AS x(rang, grandeur, valeur)\nORDER BY x.rang"
}
],
"gridPos": {
@@ -88,163 +88,65 @@
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "text",
"value": null
}
]
},
"mappings": []
"custom": {
"align": "left",
"cellOptions": {
"type": "auto"
},
"filterable": true
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Solaire produit"
"options": "rang"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
"id": "custom.hidden",
"value": true
}
]
},
{
"matcher": {
"id": "byName",
"options": "Maison consommee"
"options": "Grandeur"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
"id": "custom.width",
"value": 230
}
]
},
{
"matcher": {
"id": "byName",
"options": "Voiture"
"options": "Valeur"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Batterie chargee"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Batterie rendue"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Reseau importe"
},
"properties": [
{
"id": "unit",
"value": "kwatth"
"id": "custom.cellOptions",
"value": {
"type": "color-text"
}
},
{
"id": "thresholds",
"value": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "#EAB839",
"value": 3
},
{
"color": "orange",
"value": 8
}
]
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Autonomie"
},
"properties": [
{
"id": "unit",
"value": "percent"
},
{
"id": "thresholds",
"value": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "#EAB839",
"value": 60
},
{
"color": "green",
"value": 85
}
]
}
"id": "decimals",
"value": 1
}
]
}
]
},
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"orientation": "horizontal",
"textMode": "auto",
"colorMode": "value",
"graphMode": "none",
"justifyMode": "center",
"percentChangeColorMode": "standard",
"noValue": "—",
"wideLayout": true
"showHeader": true,
"cellHeight": "sm",
"footer": {
"show": false
}
}
},
{