{ "templating": { "list": [] }, "uid": "evcs-vehicules", "title": "Les vehicules", "description": "Ce que chaque voiture encaisse, session par session et sur la periode choisie. L'etiquette vient d'un selecteur manuel : elle peut etre fausse, et rien ne permet de la verifier — les deux vehicules sont electriquement indiscernables et leur routine s'inverse le week-end. Vehicules : VW, JEEP, ZERO (moto) ; « Invite » = tout autre (Megane de service, amis).", "tags": [ "evcs" ], "timezone": "Europe/Paris", "editable": true, "schemaVersion": 39, "version": 1, "refresh": "5m", "time": { "from": "now-7d", "to": "now" }, "timepicker": { "refresh_intervals": [ "30s", "1m", "5m", "15m", "1h" ] }, "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "enable": true, "hide": true, "name": "Annotations & Alerts", "iconColor": "rgba(0, 211, 255, 1)", "type": "dashboard" }, { "name": "Evenements", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "enable": false, "iconColor": "semi-dark-orange", "hide": false, "target": { "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT ts AS time, resume AS text, genre || ',' || coalesce(source,'?') AS tags FROM evenement WHERE $__timeFilter(ts) AND genre <> 'bilan' ORDER BY 1" } } ] }, "panels": [ { "type": "table", "title": "Sur la periode", "description": "kWh charges par vehicule sur la plage choisie (compteur de la borne). « Invite » = tout vehicule hors foyer (Megane de service, amis). « A confirmer » compte les sessions dont l'etiquette vient du selecteur sans confirmation : la seule mesure honnete de l'incertitude.", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'VW'), 0)::numeric, 1) AS \"VW\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'JEEP'), 0)::numeric, 1) AS \"JEEP\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'ZERO'), 0)::numeric, 1) AS \"ZERO\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule NOT IN ('VW', 'JEEP', 'ZERO')), 0)::numeric, 1) AS \"Invite\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule IS NULL), 0)::numeric, 1) AS \"Non etiquete\",\n count(*) AS \"Sessions\",\n count(*) FILTER (WHERE NOT vehicule_sur OR vehicule IS NULL) AS \"A confirmer\"\nFROM session_charge WHERE $__timeFilter(debut)" } ], "gridPos": { "x": 0, "y": 0, "w": 24, "h": 4 }, "fieldConfig": { "defaults": { "custom": { "align": "left", "cellOptions": { "type": "auto" }, "filterable": true } }, "overrides": [ { "matcher": { "id": "byName", "options": "VW" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "decimals", "value": 1 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } } ] }, { "matcher": { "id": "byName", "options": "JEEP" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "decimals", "value": 1 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }, { "matcher": { "id": "byName", "options": "ZERO" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "decimals", "value": 1 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "color", "value": { "mode": "fixed", "fixedColor": "purple" } } ] }, { "matcher": { "id": "byName", "options": "Invite" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "decimals", "value": 1 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "color", "value": { "mode": "fixed", "fixedColor": "yellow" } } ] }, { "matcher": { "id": "byName", "options": "Non etiquete" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "decimals", "value": 1 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } } ] }, { "matcher": { "id": "byName", "options": "A confirmer" }, "properties": [ { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "thresholds", "value": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 } ] } }, { "id": "color", "value": { "mode": "thresholds" } } ] } ] }, "options": { "showHeader": true, "cellHeight": "sm", "footer": { "show": false } } }, { "type": "barchart", "title": "Energie par periode et par vehicule", "description": "Le pas suit la plage choisie : l'heure jusqu'a 4 jours, le jour jusqu'a 70, le mois au-dela. « Non etiquete » est ce qui a ete charge sans que le selecteur soit renseigne — a interpreter, pas a ignorer.", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "WITH bornes AS (\n SELECT $__timeFrom()::timestamptz AS d, $__timeTo()::timestamptz AS f\n),\npas AS (\n SELECT CASE WHEN f - d > interval '70 days' THEN 'month'\n WHEN f - d > interval '4 days' THEN 'day'\n ELSE 'hour' END AS unite,\n CASE WHEN f - d > interval '70 days' THEN 'MM/YYYY'\n WHEN f - d > interval '4 days' THEN 'DD/MM'\n ELSE 'DD/MM HH24' END AS forme\n FROM bornes\n)\nSELECT to_char(date_trunc(pas.unite, debut), pas.forme) AS \"Periode\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'VW'), 0)::numeric, 2) AS \"VW\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'JEEP'), 0)::numeric, 2) AS \"JEEP\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule = 'ZERO'), 0)::numeric, 2) AS \"ZERO\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule NOT IN ('VW', 'JEEP', 'ZERO')), 0)::numeric, 2) AS \"Invite\",\n round(coalesce(sum(coalesce(energie_station_kwh, energie_kwh)) FILTER (WHERE vehicule IS NULL), 0)::numeric, 2) AS \"Non etiquete\"\nFROM session_charge, pas\nWHERE $__timeFilter(debut)\nGROUP BY date_trunc(pas.unite, debut), pas.forme\nORDER BY date_trunc(pas.unite, debut)" } ], "gridPos": { "x": 0, "y": 4, "w": 24, "h": 9 }, "fieldConfig": { "defaults": { "unit": "kwatth", "color": { "mode": "palette-classic" }, "custom": { "lineWidth": 1, "fillOpacity": 80, "gradientMode": "none", "axisBorderShow": false } }, "overrides": [ { "matcher": { "id": "byName", "options": "VW" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } } ] }, { "matcher": { "id": "byName", "options": "JEEP" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }, { "matcher": { "id": "byName", "options": "ZERO" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "purple" } } ] }, { "matcher": { "id": "byName", "options": "Invite" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "yellow" } } ] }, { "matcher": { "id": "byName", "options": "Non etiquete" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } } ] } ] }, "options": { "orientation": "auto", "xTickLabelRotation": -45, "showValue": "never", "stacking": "none", "groupWidth": 0.7, "barWidth": 0.9, "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } } }, { "type": "table", "title": "Les sessions", "description": "« kWh » vient du compteur de la BORNE, qui compte depuis le vrai debut de la session. « kWh integres » est mon propre calcul, qui ne couvre que ce que le service a vu — un ecart entre les deux signale un demarrage ou un redemarrage en cours de session, pas une erreur de mesure. « Debranche » confirme le vehicule apres coup : les deux partent a des heures differentes. « dont reseau » se fonde sur le mode source declare par le controleur — son intention — et non sur la puissance reseau instantanee, qui peut alimenter la maison pendant que le soleil alimente la voiture.", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT to_char(debut, 'Dy DD/MM HH24:MI') AS \"Debut\",\n coalesce(vehicule, '?') AS \"Vehicule\",\n CASE WHEN vehicule_sur THEN 'confirme' ELSE 'a confirmer' END AS \"Etiquette\",\n round((extract(epoch FROM fin - debut) / 60)::numeric) AS \"Minutes\",\n round(coalesce(energie_station_kwh, energie_kwh)::numeric, 2) AS \"kWh\",\n round(energie_kwh::numeric, 2) AS \"kWh integres\",\n round(energie_reseau_kwh::numeric, 2) AS \"dont reseau\",\n round(p_max_w::numeric) AS \"P max\",\n consigne_max_a AS \"Consigne max\",\n source_mode AS \"Source au depart\",\n to_char(debranche_a, 'Dy HH24:MI') AS \"Debranche\"\nFROM session_charge WHERE $__timeFilter(debut) ORDER BY debut DESC" } ], "gridPos": { "x": 0, "y": 13, "w": 24, "h": 11 }, "fieldConfig": { "defaults": { "custom": { "align": "left", "cellOptions": { "type": "auto" }, "filterable": true } }, "overrides": [ { "matcher": { "id": "byName", "options": "Vehicule" }, "properties": [ { "id": "custom.width", "value": 100 }, { "id": "custom.cellOptions", "value": { "type": "color-text" } }, { "id": "mappings", "value": [ { "type": "value", "options": { "VW": { "color": "blue", "index": 0 }, "JEEP": { "color": "green", "index": 1 }, "ZERO": { "color": "purple", "index": 2 }, "?": { "color": "orange", "index": 3 } } } ] } ] }, { "matcher": { "id": "byName", "options": "Doute" }, "properties": [ { "id": "custom.width", "value": 150 } ] }, { "matcher": { "id": "byName", "options": "kWh" }, "properties": [ { "id": "unit", "value": "kwatth" } ] }, { "matcher": { "id": "byName", "options": "kWh integres" }, "properties": [ { "id": "unit", "value": "kwatth" }, { "id": "custom.width", "value": 110 } ] }, { "matcher": { "id": "byName", "options": "dont reseau" }, "properties": [ { "id": "unit", "value": "kwatth" } ] }, { "matcher": { "id": "byName", "options": "P max" }, "properties": [ { "id": "unit", "value": "watt" } ] } ] }, "options": { "showHeader": true, "cellHeight": "sm", "footer": { "show": false } } }, { "type": "xychart", "pluginVersion": "11.3.0", "title": "Kilometres contre kWh : le nuage des trajets", "description": "Un point = l'intervalle entre deux releves du compteur d'un vehicule. kWh consommes = kWh livres par la borne entre les deux releves + (niveau au 1er - niveau au 2nd) x capacite. Les droites sont les references donnees par le proprietaire (JEEP 50 km, VW 42 km, ZERO 200 km pour une charge pleine). Sous la droite : on a roule moins loin par kWh (conduite, froid, chauffage — ou batterie qui s'use). Les intervalles d'une hybride finis batterie vide sont ecartes (km essence possibles).", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "gridPos": { "x": 0, "y": 24, "w": 14, "h": 11 }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "WITH i AS (SELECT * FROM km_intervalle WHERE statut = 'valide'),\ncap AS (SELECT DISTINCT ON (vehicule) capacite_kwh AS c FROM releve_km\n WHERE capacite_kwh > 0 ORDER BY vehicule, ts DESC),\nx AS (SELECT round(kwh_consommes::numeric, 2)::float8 AS x, vehicule, km_parcourus::float8 AS km FROM i\n UNION ALL SELECT 0, NULL, NULL\n UNION ALL SELECT c::float8, NULL, NULL FROM cap)\nSELECT x AS \"kWh consommes\",\n CASE WHEN vehicule = 'JEEP' THEN km END AS \"JEEP\",\n CASE WHEN vehicule = 'VW' THEN km END AS \"VW\",\n CASE WHEN vehicule = 'ZERO' THEN km END AS \"ZERO\",\n round((x * (SELECT autonomie_ref_km / capacite_kwh FROM releve_km\n WHERE vehicule = 'JEEP' AND capacite_kwh > 0 AND autonomie_ref_km > 0 ORDER BY ts DESC LIMIT 1))::numeric, 1)::float8 AS \"Reference JEEP\",\n round((x * (SELECT autonomie_ref_km / capacite_kwh FROM releve_km\n WHERE vehicule = 'VW' AND capacite_kwh > 0 AND autonomie_ref_km > 0 ORDER BY ts DESC LIMIT 1))::numeric, 1)::float8 AS \"Reference VW\",\n round((x * (SELECT autonomie_ref_km / capacite_kwh FROM releve_km\n WHERE vehicule = 'ZERO' AND capacite_kwh > 0 AND autonomie_ref_km > 0 ORDER BY ts DESC LIMIT 1))::numeric, 1)::float8 AS \"Reference ZERO\"\nFROM x ORDER BY 1" } ], "fieldConfig": { "defaults": { "unit": "lengthkm", "color": { "mode": "palette-classic" }, "custom": { "show": "points", "pointSize": { "fixed": 10 }, "pointShape": "circle", "lineWidth": 1, "fillOpacity": 60 } }, "overrides": [ { "matcher": { "id": "byName", "options": "JEEP" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }, { "matcher": { "id": "byName", "options": "VW" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } } ] }, { "matcher": { "id": "byName", "options": "ZERO" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "purple" } } ] }, { "matcher": { "id": "byName", "options": "Reference JEEP" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } }, { "id": "custom.show", "value": "lines" }, { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [ 10, 10 ] } } ] }, { "matcher": { "id": "byName", "options": "Reference VW" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } }, { "id": "custom.show", "value": "lines" }, { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [ 10, 10 ] } } ] }, { "matcher": { "id": "byName", "options": "Reference ZERO" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "purple" } }, { "id": "custom.show", "value": "lines" }, { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [ 10, 10 ] } } ] } ] }, "options": { "mapping": "manual", "series": [ { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "JEEP" } } }, { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "VW" } } }, { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "ZERO" } } }, { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "Reference JEEP" } } }, { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "Reference VW" } } }, { "frame": { "matcher": { "id": "byIndex", "options": 0 } }, "x": { "matcher": { "id": "byName", "options": "kWh consommes" } }, "y": { "matcher": { "id": "byName", "options": "Reference ZERO" } } } ], "legend": { "showLegend": true, "displayMode": "list", "placement": "bottom" }, "tooltip": { "mode": "single", "sort": "none" } } }, { "type": "table", "title": "Les intervalles entre releves", "description": "Tous les intervalles, y compris ceux ecartes du nuage, avec la raison. « niveau manquant » : redonner le releve avec le niveau (« JEEP 112694 km 54 % »).", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT vehicule AS \"Vehicule\",\n to_char(debut AT TIME ZONE 'Europe/Paris', 'Dy DD/MM HH24:MI') AS \"Du\",\n to_char(fin AT TIME ZONE 'Europe/Paris', 'Dy DD/MM HH24:MI') AS \"Au\",\n km_parcourus AS \"km\",\n round(kwh_charges::numeric, 2) AS \"kWh borne\",\n niveau_debut || ' -> ' || niveau_fin || ' %' AS \"Niveau\",\n round(kwh_consommes::numeric, 2) AS \"kWh consommes\",\n round(km_par_kwh::numeric, 1) AS \"km/kWh\",\n round(km_par_kwh_ref::numeric, 1) AS \"Reference\",\n statut AS \"Statut\"\nFROM km_intervalle ORDER BY fin DESC" } ], "gridPos": { "x": 14, "y": 24, "w": 10, "h": 11 }, "fieldConfig": { "defaults": { "custom": { "align": "left", "cellOptions": { "type": "auto" }, "filterable": true } }, "overrides": [ { "matcher": { "id": "byName", "options": "kWh borne" }, "properties": [ { "id": "unit", "value": "kwatth" } ] }, { "matcher": { "id": "byName", "options": "kWh consommes" }, "properties": [ { "id": "unit", "value": "kwatth" } ] } ] }, "options": { "showHeader": true, "cellHeight": "sm", "footer": { "show": false } } }, { "type": "timeseries", "title": "Capacite estimee des batteries (usure)", "description": "Un point = un branchement ou le niveau a ete donne et la charge menee au plein (ou suivie d'un releve « debranche a NN % ») : capacite = kWh livres par la borne depuis le branchement / part manquante. Ce sont des kWh AU COMPTEUR (pertes du chargeur comprises). Une pente descendante sur des mois = usure de la batterie. Le niveau saisi est un entier : sur une petite charge, 1 point d'erreur pese lourd.", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "time_series", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT debranche AS time,\n CASE WHEN vehicule = 'JEEP' THEN capacite_kwh END AS \"JEEP\",\n CASE WHEN vehicule = 'VW' THEN capacite_kwh END AS \"VW\",\n CASE WHEN vehicule = 'ZERO' THEN capacite_kwh END AS \"ZERO\"\nFROM capacite_estimee WHERE capacite_kwh IS NOT NULL AND $__timeFilter(debranche)\nORDER BY 1" } ], "gridPos": { "x": 0, "y": 35, "w": 14, "h": 9 }, "fieldConfig": { "defaults": { "unit": "kwatth", "color": { "mode": "palette-classic" }, "custom": { "lineWidth": 2, "fillOpacity": 8, "showPoints": "always", "spanNulls": false, "axisBorderShow": false, "gradientMode": "opacity", "drawStyle": "points", "pointSize": 10 } }, "overrides": [ { "matcher": { "id": "byName", "options": "JEEP" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }, { "matcher": { "id": "byName", "options": "VW" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } } ] }, { "matcher": { "id": "byName", "options": "ZERO" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "purple" } } ] } ] }, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true, "calcs": [] }, "tooltip": { "mode": "multi", "sort": "desc" } } }, { "type": "table", "title": "Les releves du compteur", "description": "Releves recus par WhatsApp (concierge) ou par le tableau EVCS Master. Un releve fait au branchement est date du branchement : le compteur n'avance pas pendant la charge.", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "targets": [ { "refId": "A", "datasource": { "type": "grafana-postgresql-datasource", "uid": "evcs-pg" }, "format": "table", "rawQuery": true, "editorMode": "code", "rawSql": "SELECT to_char(ts AT TIME ZONE 'Europe/Paris', 'Dy DD/MM HH24:MI') AS \"Quand\",\n vehicule AS \"Vehicule\", km AS \"Compteur\",\n coalesce(niveau_pct || ' %', '?') AS \"Niveau\", source AS \"Source\"\nFROM releve_km ORDER BY ts DESC" } ], "gridPos": { "x": 14, "y": 35, "w": 10, "h": 9 }, "fieldConfig": { "defaults": { "custom": { "align": "left", "cellOptions": { "type": "auto" }, "filterable": true } }, "overrides": [ { "matcher": { "id": "byName", "options": "Compteur" }, "properties": [ { "id": "unit", "value": "lengthkm" } ] } ] }, "options": { "showHeader": true, "cellHeight": "sm", "footer": { "show": false } } } ] }