diff --git a/deploy/historisation/grafana/dashboards/systeme.json b/deploy/historisation/grafana/dashboards/systeme.json index 8bd82ee..2e967b5 100644 --- a/deploy/historisation/grafana/dashboards/systeme.json +++ b/deploy/historisation/grafana/dashboards/systeme.json @@ -242,7 +242,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_consumption_power_l1\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Consommation\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_consumption_power_l1\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Consommation\"})" }, { "refId": "B", @@ -250,7 +250,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"Hz\" and r.entity_id == \"airtria_mpii_v1_output_frequency_l1\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Frequence\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"Hz\" and r.entity_id == \"airtria_mpii_v1_output_frequency_l1\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Frequence\"})" } ], "gridPos": { @@ -343,7 +343,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"%\" and r.entity_id == \"victron_battery_soc\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Charge\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"%\" and r.entity_id == \"victron_battery_soc\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Charge\"})" }, { "refId": "B", @@ -351,7 +351,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_battery_power\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Puissance\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_battery_power\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Puissance\"})" }, { "refId": "C", @@ -359,7 +359,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"V\" and r.entity_id == \"victron_battery_voltage\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Tension\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"V\" and r.entity_id == \"victron_battery_voltage\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Tension\"})" }, { "refId": "D", @@ -367,7 +367,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_battery_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Courant\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_battery_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Courant\"})" }, { "refId": "E", @@ -375,7 +375,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"°C\" and r.entity_id == \"victron_battery_temperature\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Temperature\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"°C\" and r.entity_id == \"victron_battery_temperature\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Temperature\"})" } ], "gridPos": { @@ -544,7 +544,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_evcs_ac_power\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Puissance\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_evcs_ac_power\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Puissance\"})" }, { "refId": "B", @@ -552,7 +552,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_evcs_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Courant\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_evcs_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Courant\"})" }, { "refId": "C", @@ -560,7 +560,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_evcs_set_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Consigne\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"A\" and r.entity_id == \"victron_evcs_set_current\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Consigne\"})" } ], "gridPos": { @@ -669,7 +669,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_pv_power_system\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Production\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_pv_power_system\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Production\"})" }, { "refId": "B", @@ -677,7 +677,7 @@ "type": "influxdb", "uid": "evcs-influx" }, - "query": "from(bucket: \"evcs\")\n |> range(start: -6h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_pv_power_10m_avg\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Moyenne 10 min\"})" + "query": "from(bucket: \"evcs\")\n |> range(start: -24h)\n |> filter(fn: (r) => r._measurement == \"W\" and r.entity_id == \"victron_pv_power_10m_avg\" and r._field == \"value\")\n |> last()\n |> keep(columns: [\"_value\"])\n |> rename(columns: {_value: \"Moyenne 10 min\"})" } ], "gridPos": { diff --git a/docs/MANUEL_COMPLET.md b/docs/MANUEL_COMPLET.md index 21bc0e5..3b37169 100644 --- a/docs/MANUEL_COMPLET.md +++ b/docs/MANUEL_COMPLET.md @@ -125,6 +125,32 @@ de Home Assistant peut l'annuler (constate le 04/09 a 19:44, cf. HANDOFF §47). L'heure de **debranchement** confirme a posteriori, les deux vehicules partant a des heures differentes (JEEP ~06:30, VW ~08:50). +### Un TROISIEME vehicule a venir : la moto + +Le proprietaire possede une **moto electrique Zero Motorcycles SR/F**. Elle +n'est pas chargee actuellement — il s'est ecrase le majeur de la main droite +avec une betonneuse et enfiler un gant est difficile — et il pense reconduire +**fin septembre 2026**. + +A faire a ce moment-la, et rien avant : +1. ajouter `ZERO` aux options de `input_select.victron_evcs_vehicle` + (paquet `victron_evcs_vehicles.yaml`, puis rechargement des entrees) ; +2. creer son heure de depart si elle differe + (`input_datetime.victron_evcs_departure_time_zero`) et l'ajouter au choix + de `departureTimeMin` dans `INPUT_PARSE.js`, a cote de VW et JEEP ; +3. la table `session_charge` n'a rien a changer : elle enregistre la valeur du + selecteur, quelle qu'elle soit. + +⚠️ Une moto a une batterie bien plus petite qu'une voiture (une SR/F est de +l'ordre de 14 a 17 kWh) et un chargeur embarque plus faible. **C'est donc +peut-etre le premier vehicule du foyer qui soit electriquement distinguable +des deux autres** — a verifier le moment venu, en comparant son plateau de +puissance a consigne elevee aux 3 655 / 3 680 W de la JEEP et de la VW. + +NB : un ancien `input_select.victron_evcs_target_vehicle` (None/Jeep/Zero) +existe encore, cree par l'interface et cable nulle part. Ne pas le confondre +avec le selecteur en service, ni le reutiliser. + ### Consommation de la maison — pilotee par les repas, pas par une courbe lisse > Donne par le proprietaire le 03/09/2026. **A ne pas redecouvrir.** diff --git a/tools/gen-grafana-dashboards.py b/tools/gen-grafana-dashboards.py index d23fe05..8dba909 100644 --- a/tools/gen-grafana-dashboards.py +++ b/tools/gen-grafana-dashboards.py @@ -620,35 +620,24 @@ telephone = dashboard("evcs-telephone", "Sur le telephone", ( # variation de -373 kWh sur une heure. Integrer la puissance ignore # completement ce probleme. -def flux_dernier(refid, mesure, entite, libelle, champ="value", fenetre="6h"): +def flux_dernier(refid, mesure, entite, libelle, champ="value", fenetre="24h"): """Derniere valeur connue d'une entite, renommee pour l'affichage.""" - # Fenetre de 6 HEURES : un compromis, et il merite d'etre explique. + # LA FENETRE DEPEND DU COMPORTEMENT DE L'ENTITE AU REPOS, pas d'un + # compromis unique. C'est la lecon de deux erreurs successives : # - # Trop large (7 jours, premiere version), le panneau Reseau affichait le - # 05/09 a minuit « Courant 2,2 A » — une valeur ecrite QUATORZE HEURES plus - # tot, du temps ou le contacteur etait ferme. Les capteurs du reseau - # passent en `unavailable` quand AC-IN disparait ; ils ne tombent pas a - # zero. Leur derniere valeur numerique reste donc celle d'avant, et elle - # ment. + # - trop LARGE partout (7 jours) : le panneau Reseau affichait le 05/09 a + # minuit « Courant 2,2 A », valeur ecrite quatorze heures plus tot. Les + # capteurs du reseau passent en `unavailable` quand AC-IN disparait ; + # ils ne tombent pas a zero, et leur derniere valeur numerique ment. # - # Trop etroite (30 minutes), on efface des valeurs JUSTES : la production - # nulle de la nuit est ecrite une fois au coucher du soleil et reste vraie - # jusqu'a l'aube. + # - trop ETROITE partout (6 heures) : a 03:20 le panneau PV affichait + # « No data » alors que la production est nulle et connue — sa derniere + # ecriture datait du coucher du soleil, 370 minutes plus tot. # - # Six heures couvre une nuit sans soleil et une borne au repos, tout en - # ecartant une lecture vieille de quatorze heures. Au-dela, la case affiche - # un tiret — « aucune mesure recente », jamais un chiffre invente. - # Ancien commentaire : - # tentant — c'est ce que je faisais — mais le 05/09 a minuit le panneau - # Reseau affichait « Courant 2,2 A », valeur ecrite QUATORZE HEURES plus - # tot, du temps ou le contacteur etait ferme. Une case vide dit « aucune - # mesure recente » et c'est vrai ; un chiffre perime dit « voici la - # valeur » et c'est faux. - # Ancienne justification, conservee pour memoire : l'integration InfluxDB - # de Home Assistant n'ecrit QUE sur changement d'etat. Une grandeur stable - # — la borne a 0 A, voiture debranchee — n'a donc aucun point recent, et - # une fenetre courte affiche une case vide la ou la valeur est simplement - # constante. `last()` reste peu couteux sur une fenetre large. + # Regle : une entite qui publie un VRAI zero au repos (production PV, borne + # a l'arret, trackers) supporte une fenetre large, sa derniere valeur restant + # exacte. Une entite qui DISPARAIT au repos exige une fenetre courte — c'est + # le cas des seules grandeurs du reseau, qui passent donc 6h en argument. return flux(refid, f'from(bucket: "evcs")\n' f' |> range(start: -{fenetre})\n' @@ -804,9 +793,11 @@ systeme = dashboard("evcs-systeme", "Le systeme", ( frm="now-24h", refresh="30s", variables=[VARIABLE_VUE], panels=[ stat("Reseau", [ - flux_dernier("A", "W", "victron_grid_power_l1", "Puissance"), - flux_dernier("B", "V", "airtria_mpii_v1_input_voltage_l1", "Tension"), - flux_dernier("C", "A", "gx_device_grid_current_l1", "Courant")], + # 6 h et non 24 : ces trois capteurs DISPARAISSENT quand AC-IN s'ouvre, + # laissant derriere eux une valeur qui ne vaut plus rien. + flux_dernier("A", "W", "victron_grid_power_l1", "Puissance", fenetre="6h"), + flux_dernier("B", "V", "airtria_mpii_v1_input_voltage_l1", "Tension", fenetre="6h"), + flux_dernier("C", "A", "gx_device_grid_current_l1", "Courant", fenetre="6h")], IN, 0, 0, 5, 5, "Positif : le reseau alimente la maison. Le contacteur EDF est pilote par " "le workflow d'hysteresis, pas depuis ici.",