From 7ec3bf37a15805ad6412ce9f1511f657abcf5a89 Mon Sep 17 00:00:00 2001 From: Tallagrand Thierry Date: Sun, 4 Oct 2026 01:22:37 +0200 Subject: [PATCH] Tableau Energie : RS 450 separe en Sud et Ouest, historique importe --- HANDOFF.md | 11 ++++++ packages/evcs_energie_trackers.yaml | 32 ++++++++++++++++ tools/ponctuel/20261004-import-sud-ouest.js | 41 +++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100755 packages/evcs_energie_trackers.yaml create mode 100644 tools/ponctuel/20261004-import-sud-ouest.js diff --git a/HANDOFF.md b/HANDOFF.md index 48c1a95..b6e43af 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1597,6 +1597,17 @@ des chargeurs), batterie +19,25 / -20,58, borne 9,30 (= 4,6 + 0,1 + 4,6), reseau arriere = remettre ce fichier HA arrete, ou retirer les sources dans Parametres -> Tableaux de bord -> Energie. ⚠️ La « consommation maison » du tableau Energie est deduite (solaire + reseau + decharge - charge) : elle inclut la borne et les pertes de l'onduleur. +- **Sud et Ouest separes (04/10 ~01:25, proprietaire)** : le RS 450/200 est remplace dans + le tableau Energie par deux capteurs gabarits (`packages/evcs_energie_trackers.yaml`) : + `sensor.pv_rs_450_sud_production_du_jour` (trackers 1-3, 30 panneaux) et + `sensor.pv_rs_450_ouest_production_du_jour` (tracker 4, 9 panneaux), en + `total_increasing`. Sur : les quatre trackers se remettent a zero au MEME instant + (00:23 le 03/10). Historique importe depuis les stats horaires des trackers + (`recorder/import_statistics`, depuis le 28/07, script `tools/ponctuel/20261004-import-sud-ouest.js`). + Recoupement avec le compteur du chargeur : 01/10 28,6 + 3,1 = 31,7 (31,69), 02/10 26,0 + + 2,8 (28,73), 03/10 27,5 + 5,3 (32,72). Sauvegarde `.storage/energy.bak-20261004-sudouest`. + ⚠️ **A verifier le 04/10** : la premiere heure compilee par HA (02:00) doit prolonger la + somme importee sans saut (stats journalieres du 04/10 sud/ouest ~ production reelle). --- *Document mis a jour le : 04/10/2026 (~01:10) — kilometrage des vehicules (km/kWh, capacite, releves de reference, agent cable 15/15) ; a verifier le 04/10 au matin : nuit du budget JEEP ; concierge : vehicule non confirme demande, heure de saisie ; Grafana vehicules en tableau ; Grafana vehicules : ZERO et Invite ajoutes, session 16:46 reetiquetee ZERO ; prevision SOC 10 h ~35 % ; concierge fiable : niveau note par le script, une ligne, dedoublonnage, simulation par drapeau ; agent : message incompris = question, bourse sur demande explicite (banc final 6/6) ; a verifier : nuit du samedi 03 au dimanche 04/10 (budget < besoin JEEP), cron orange-cloture lundi 05/10 apres 17:40, comparaison VRM / Forecast.Solar lundi 05/10* diff --git a/packages/evcs_energie_trackers.yaml b/packages/evcs_energie_trackers.yaml new file mode 100755 index 0000000..41141d1 --- /dev/null +++ b/packages/evcs_energie_trackers.yaml @@ -0,0 +1,32 @@ +# ===================================================== +# EVCS — PRODUCTION SUD / OUEST DU RS 450/200 POUR LE TABLEAU ENERGIE (04/10/2026) +# Le RS 450/200 porte le SUD (trackers 1-3, 3 strings de 10 panneaux, 35°) et +# l'OUEST (tracker 4, 9 panneaux, 45°) — MANUEL §0. Ses trackers ne publient +# qu'une production DU JOUR ; les quatre se remettent a zero au MEME instant +# (verifie le 03/10 a 00:23), donc la somme est sure en total_increasing (la +# remise a zero est vue comme un nouveau cycle de compteur, pas une baisse). +# Historique anterieur importe depuis les statistiques des trackers. +# ===================================================== +template: + - sensor: + - name: "PV RS 450 Sud - production du jour" + unique_id: evcs_pv_rs450_sud_jour + unit_of_measurement: kWh + device_class: energy + state_class: total_increasing + icon: mdi:solar-panel + availability: > + {{ (1, 2, 3) | map('string') | map('regex_replace', '^', 'sensor.mppt_450_200_hq2449yr9pt_tracker_solar_') + | map('regex_replace', '$', '_yield_today') | map('states') | map('is_number') | min }} + state: > + {{ (states('sensor.mppt_450_200_hq2449yr9pt_tracker_solar_1_yield_today') | float + + states('sensor.mppt_450_200_hq2449yr9pt_tracker_solar_2_yield_today') | float + + states('sensor.mppt_450_200_hq2449yr9pt_tracker_solar_3_yield_today') | float) | round(2) }} + - name: "PV RS 450 Ouest - production du jour" + unique_id: evcs_pv_rs450_ouest_jour + unit_of_measurement: kWh + device_class: energy + state_class: total_increasing + icon: mdi:solar-panel + availability: "{{ states('sensor.mppt_450_200_hq2449yr9pt_tracker_solar_4_yield_today') | is_number }}" + state: "{{ states('sensor.mppt_450_200_hq2449yr9pt_tracker_solar_4_yield_today') | float | round(2) }}" diff --git a/tools/ponctuel/20261004-import-sud-ouest.js b/tools/ponctuel/20261004-import-sud-ouest.js new file mode 100644 index 0000000..f1f91d9 --- /dev/null +++ b/tools/ponctuel/20261004-import-sud-ouest.js @@ -0,0 +1,41 @@ +// Calcule (et importe si IMPORT=1) l'historique Sud/Ouest depuis les stats horaires des trackers. +const ws = new WebSocket(process.env.HA_URL.replace(/^http/, 'ws') + '/api/websocket'); +let id = 1; const pend = {}; +const call = (m) => new Promise(r => { const i = id++; pend[i] = r; ws.send(JSON.stringify({ id: i, ...m })); }); +const T = (i) => `sensor.mppt_450_200_hq2449yr9pt_tracker_solar_${i}_yield_today`; +ws.onmessage = async (e) => { + const m = JSON.parse(e.data); + if (m.type === 'auth_required') return ws.send(JSON.stringify({ type: 'auth', access_token: process.env.HA_TOKEN })); + if (m.type !== 'auth_ok') { if (pend[m.id]) { pend[m.id](m); delete pend[m.id]; } return; } + const fin = new Date(); fin.setMinutes(0, 0, 0); + const r = await call({ type: 'recorder/statistics_during_period', start_time: '2025-01-01T00:00:00Z', + end_time: fin.toISOString(), period: 'hour', types: ['state'], statistic_ids: [1, 2, 3, 4].map(T) }); + const st = r.result; + const par = {}; // start -> {1:..,4:..} + for (const i of [1, 2, 3, 4]) for (const x of (st[T(i)] || [])) { (par[x.start] ||= {})[i] = x.state; } + const heures = Object.keys(par).map(Number).sort((a, b) => a - b); + console.log('heures', heures.length, new Date(heures[0]).toISOString(), '->', new Date(heures.at(-1)).toISOString()); + const serie = (ids) => { const out = []; let prev = null, sum = 0, last = {}; + for (const h of heures) { + for (const i of ids) if (par[h][i] !== undefined && par[h][i] !== null) last[i] = par[h][i]; + if (!ids.every(i => last[i] !== undefined)) continue; + const v = Math.round(ids.reduce((a, i) => a + last[i], 0) * 100) / 100; + if (prev !== null) sum += v >= prev ? v - prev : v; + prev = v; out.push({ start: new Date(h).toISOString(), state: v, sum: Math.round(sum * 1000) / 1000 }); + } return out; }; + const sud = serie([1, 2, 3]), ouest = serie([4]); + console.log('sud', sud.length, 'total', sud.at(-1).sum, '| ouest', ouest.length, 'total', ouest.at(-1).sum); + // controle : derniere journee complete + const jour = (s, d0, d1) => { const a = s.filter(x => x.start >= d0 && x.start < d1); return a.length ? (a.at(-1).sum - (s[s.indexOf(a[0]) - 1]?.sum ?? 0)).toFixed(2) : null; }; + console.log('03/10 sud', jour(sud, '2026-10-02T22', '2026-10-03T22'), 'ouest', jour(ouest, '2026-10-02T22', '2026-10-03T22')); + console.log('02/10 sud', jour(sud, '2026-10-01T22', '2026-10-02T22'), 'ouest', jour(ouest, '2026-10-01T22', '2026-10-02T22')); + if (process.env.IMPORT === '1') { + for (const [sid, nom, s] of [['sensor.pv_rs_450_sud_production_du_jour', 'PV RS 450 Sud - production du jour', sud], + ['sensor.pv_rs_450_ouest_production_du_jour', 'PV RS 450 Ouest - production du jour', ouest]]) { + const res = await call({ type: 'recorder/import_statistics', metadata: { has_mean: false, has_sum: true, name: nom, + source: 'recorder', statistic_id: sid, unit_of_measurement: 'kWh' }, stats: s }); + console.log('import', sid, res.success, JSON.stringify(res.error || '')); + } + } + ws.close(); +};