Historisation : allers-retours brefs de la borne et du contacteur retrouves dans l'historique HA (echange VW -> JEEP de 20 s)
This commit is contained in:
43
HANDOFF.md
43
HANDOFF.md
@@ -1847,6 +1847,47 @@ orange-cloture (verifie par SPARK : envoye le 05/10 a 17:42).
|
|||||||
de 90 % de SOC, EDF a midi des que le surplus prevu ne couvre pas le besoin ; plus de
|
de 90 % de SOC, EDF a midi des que le surplus prevu ne couvre pas le besoin ; plus de
|
||||||
`force_grid_now` a la main. ⚠️ La session ne vaut que dans la fenetre HC de midi (12:24-14:24) :
|
`force_grid_now` a la main. ⚠️ La session ne vaut que dans la fenetre HC de midi (12:24-14:24) :
|
||||||
une voiture branchee apres 14:24 n'est pas couverte.
|
une voiture branchee apres 14:24 n'est pas couverte.
|
||||||
|
- ⚠️ **Defaut decouvert apres coup, a traiter** : `force_grid_now` n'a donne que **2,0 kWh** (13:18 -> 14:22).
|
||||||
|
Deux arrets « batterie trop sollicitee » (13:46 -41,9 A, 14:22 -47,3 A) sur des pointes de la maison a
|
||||||
|
7,1-7,7 kW (voiture 3,5 kW + cuisine ~4 kW) alors que le reseau ne fournissait que ~3,9 kW ; la garde
|
||||||
|
batterie du mode reseau juge sur UN echantillon, et le blocage anti-cliquetis de 20 min a coute ~40 min
|
||||||
|
de charge. Deux pistes soumises au proprietaire (tolerance de duree en mode reseau ; brider a 6 A au
|
||||||
|
lieu de couper), decision en attente.
|
||||||
|
- 14:24:00 echeance de `force_grid_now` en reel (trace « retour auto_solar_plus (sortie de la fenetre
|
||||||
|
d'heures creuses), SOC 57 % »), EDF ouvert 14:25:03.
|
||||||
|
|
||||||
|
### 06/10 soir — Production 14,5 kWh, et un echange VW -> JEEP de 20 s que personne n'a vu
|
||||||
|
- **Production reelle 14,5 kWh** a 18:06 (journee finie) pour VRM 22,1 (matin), ECMWF ~25-28,
|
||||||
|
Meteo-France ~25-29, ICON ~15-18 : ICON le plus juste, VRM -34 %.
|
||||||
|
- VW branchee 16:16:11 (question concierge 16:40 apres deux cycles d'attente Uconnect) ; reponses
|
||||||
|
WhatsApp 18:08 « VW », 18:09 « 0% » -> l'agent a fusionne (premier appel annule par OpenClaw),
|
||||||
|
« ✅ Noté : VW … 🔋 Niveau noté : 0 % » a 18:10:30. J'avais ecrit a 18:10:21 le selecteur VW,
|
||||||
|
l'etiquette (source proprietaire) et le mode de nuit **complete** (proprietaire : EDF de toute facon
|
||||||
|
cette nuit pour la batterie, SOC 62 pour 71,4 requis) ; le concierge a reecrit l'etiquette 9 s apres.
|
||||||
|
- **19:52:36 off / 19:52:56 on : echange VW -> JEEP en 20 s, JAMAIS journalise.** Le service lit l'etat
|
||||||
|
une fois par cycle (~75 s) : etat identique avant et apres -> aucune transition dans `evenement`,
|
||||||
|
donc ni branchement neuf, ni question du concierge (SPARK : son SQL_TRANS ne voyait qu'un branchement
|
||||||
|
depuis 16:16), ni regle « fin de trajet » JEEP (Uconnect 19:52:17, 28 %, 112 831 km). A 22:34 « J'ai
|
||||||
|
branche la JEEP » a donc relabellise le branchement de 16:16 en JEEP. Aucune session depuis 16:16 :
|
||||||
|
aucun kWh mal attribue.
|
||||||
|
- **Correctif (accord du proprietaire, deploye 23:26)** : `detecterEvenements` garde le `last_changed`
|
||||||
|
de chaque entite ; sur `ALLERS_RETOURS_SUIVIS` (borne branchee, contacteur EDF), si l'etat est
|
||||||
|
identique mais que `last_changed` a avance, il relit l'historique HA de l'intervalle et journalise
|
||||||
|
chaque transition A SON HORODATAGE HA (`journaliser(..., ts)`, colonne ts explicite, detail
|
||||||
|
`aller_retour: true`). Fonction pure `transitionsDansSerie` dans `tools/allers-retours.mjs`, tests
|
||||||
|
`node tests/allers-retours/run.mjs` 4/4 (dont le cas reel), mutation « indisponible compte » qui mord ;
|
||||||
|
kilometrage 21/21. Sauvegarde `historise-evcs.mjs.bak-20261006` (scratchpad) ; retour = `git revert`
|
||||||
|
+ `docker restart evcs-historisation`.
|
||||||
|
- **Rattrapage en base** : les deux transitions de 19:52 inserees a leur heure HA ; etiquette du
|
||||||
|
branchement 16:16 remise a **VW** ; helper concierge pointe le branchement **19:52:56 = JEEP**.
|
||||||
|
Au cycle suivant (23:28) la regle « fin de trajet » a joue seule : « Branchement identifie : JEEP
|
||||||
|
(fin de trajet juste avant le branchement, Uconnect), niveau 28 % ». Niveau HA saisi a 28 % par moi
|
||||||
|
a 23:24 (reference du compteur 4069,9 = compteur courant, rien de livre depuis 19:52).
|
||||||
|
- **Nuit 06->07** : SOC 37 % a 23:14 (soiree lourde, 62 -> 37 % depuis 18:06), requis 48,8 / 61,8 ;
|
||||||
|
EDF a 01:24 (~7,3 kWh maison + batterie) + JEEP 28 % -> plein (~7,2 kWh), mode complete. A verifier
|
||||||
|
le 07/10 : session JEEP comptee sur le branchement de 19:52:56, capacite estimee JEEP (28 % -> plein),
|
||||||
|
SOC a 9 h. Mode de nuit dans HA : EVCS Master onglet Vehicules, carte « Vehicule branche et cette
|
||||||
|
nuit » (« Charge cette nuit ») ; Bilan energetique onglet Production, carte « Voiture cette nuit ».
|
||||||
|
|
||||||
---
|
---
|
||||||
*Document mis a jour le : 06/10/2026 (~13:35) — voiture a midi : la batterie n'est plus comptee comme du solaire (EDF automatique les jours de depart si le surplus ne couvre pas) ; nuit 05->06 : JEEP chargee sur EDF en complete (6,32 kWh), budget 0 du a la prevision, Windy/ECMWF contre VRM, a comparer ce soir ; concierge aligne sur la preuve fin de trajet ; a verifier : nuit 05->06 et mardi faible, comparaison VRM/Forecast.Solar ; JEEP identifiee aussi par sa fin de trajet, prevision de la nuit 05->06 ; identification JEEP reussie en reel, correction humaine qui prime (refus supprime), session du 04/10 coupee ; EVCS Master en quatre onglets ; Jeep lue par Uconnect et identifiee seule, capacite JEEP 10 kWh, concierge variante (a) ; releve par photo (SPARK), hass-uconnect en attente ; ecart semaine/week-end mesure (pas de profil week-end la nuit) ; nuit du budget : budget borne au plancher prudent, sans EDF = voiture bloquee meme EDF ferme (batterie seule) ; Energie : sauts corriges ; tableau Energie complete (Sud/Ouest, batterie par integration, borne ; aucun redemarrage HA) ; 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*
|
*Document mis a jour le : 06/10/2026 (~23:35) — allers-retours brefs de la borne retrouves dans l'historique HA (echange VW -> JEEP de 20 s), production 14,5 kWh contre 22 prevus, defaut garde batterie en mode reseau a trancher ; voiture a midi : la batterie n'est plus comptee comme du solaire (EDF automatique les jours de depart si le surplus ne couvre pas) ; nuit 05->06 : JEEP chargee sur EDF en complete (6,32 kWh), budget 0 du a la prevision, Windy/ECMWF contre VRM, a comparer ce soir ; concierge aligne sur la preuve fin de trajet ; a verifier : nuit 05->06 et mardi faible, comparaison VRM/Forecast.Solar ; JEEP identifiee aussi par sa fin de trajet, prevision de la nuit 05->06 ; identification JEEP reussie en reel, correction humaine qui prime (refus supprime), session du 04/10 coupee ; EVCS Master en quatre onglets ; Jeep lue par Uconnect et identifiee seule, capacite JEEP 10 kWh, concierge variante (a) ; releve par photo (SPARK), hass-uconnect en attente ; ecart semaine/week-end mesure (pas de profil week-end la nuit) ; nuit du budget : budget borne au plancher prudent, sans EDF = voiture bloquee meme EDF ferme (batterie seule) ; Energie : sauts corriges ; tableau Energie complete (Sud/Ouest, batterie par integration, borne ; aucun redemarrage HA) ; 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*
|
||||||
|
|||||||
44
tests/allers-retours/run.mjs
Normal file
44
tests/allers-retours/run.mjs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// Allers-retours brefs retrouves dans l'historique HA (06/10/2026).
|
||||||
|
// Usage : node tests/allers-retours/run.mjs
|
||||||
|
import { transitionsDansSerie } from '../../tools/allers-retours.mjs';
|
||||||
|
|
||||||
|
let ok = 0, ko = 0;
|
||||||
|
function verifie(nom, obtenu, attendu) {
|
||||||
|
const a = JSON.stringify(obtenu), b = JSON.stringify(attendu);
|
||||||
|
if (a === b) { ok++; console.log(`✅ ${nom}`); }
|
||||||
|
else { ko++; console.log(`❌ ${nom}\n attendu ${b}\n obtenu ${a}`); }
|
||||||
|
}
|
||||||
|
const s = (state, last_changed) => ({ state, last_changed });
|
||||||
|
|
||||||
|
// Cas reel du 06/10 : echange VW -> JEEP en 20 s, entre deux cycles.
|
||||||
|
// L'historique HA commence par l'etat a l'instant de debut (16:16:10).
|
||||||
|
const reel = [
|
||||||
|
s('on', '2026-10-06T14:16:10.124Z'),
|
||||||
|
s('off', '2026-10-06T17:52:36.000Z'),
|
||||||
|
s('on', '2026-10-06T17:52:56.474Z'),
|
||||||
|
];
|
||||||
|
verifie('echange-20s-du-06-10',
|
||||||
|
transitionsDansSerie(reel, 'on', '2026-10-06T14:16:10.124Z', '2026-10-06T17:52:56.474Z'),
|
||||||
|
[{ avant: 'on', apres: 'off', a: '2026-10-06T17:52:36.000Z' },
|
||||||
|
{ avant: 'off', apres: 'on', a: '2026-10-06T17:52:56.474Z' }]);
|
||||||
|
|
||||||
|
// Un hoquet d'indisponibilite n'est pas un branchement.
|
||||||
|
verifie('indisponible-ignore',
|
||||||
|
transitionsDansSerie([s('on', '2026-10-06T14:16:10Z'), s('unavailable', '2026-10-06T15:00:00Z'), s('on', '2026-10-06T15:00:05Z')],
|
||||||
|
'on', '2026-10-06T14:16:10Z', '2026-10-06T15:00:05Z'),
|
||||||
|
[]);
|
||||||
|
|
||||||
|
// L'entree de depart (= dernier changement deja vu) n'est pas rejouee.
|
||||||
|
verifie('point-de-depart-exclu',
|
||||||
|
transitionsDansSerie([s('on', '2026-10-06T14:16:10Z')], 'on', '2026-10-06T14:16:10Z', '2026-10-06T14:16:10Z'),
|
||||||
|
[]);
|
||||||
|
|
||||||
|
// Deux allers-retours dans le meme intervalle : les quatre transitions, dans l'ordre.
|
||||||
|
verifie('deux-allers-retours',
|
||||||
|
transitionsDansSerie([s('on', '2026-10-06T10:00:00Z'), s('off', '2026-10-06T10:00:10Z'), s('on', '2026-10-06T10:00:20Z'),
|
||||||
|
s('off', '2026-10-06T10:00:40Z'), s('on', '2026-10-06T10:00:50Z')], 'on', '2026-10-06T10:00:00Z', '2026-10-06T10:00:50Z').length,
|
||||||
|
4);
|
||||||
|
|
||||||
|
console.log(ko ? `\n${ko} ECHEC(S)` : `\nALLERS-RETOURS OK — ${ok}/${ok}`);
|
||||||
|
process.exit(ko ? 1 : 0);
|
||||||
24
tools/allers-retours.mjs
Normal file
24
tools/allers-retours.mjs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Transitions d'etat retrouvees dans l'historique HA (06/10/2026).
|
||||||
|
// Voir ALLERS_RETOURS_SUIVIS dans historise-evcs.mjs : un aller-retour plus
|
||||||
|
// bref qu'un cycle du service ne se voit que par le `last_changed` de HA.
|
||||||
|
const txt = (s) => (s ?? '').toString().trim();
|
||||||
|
export const ETATS_ABSENTS = new Set(['', 'unavailable', 'unknown']);
|
||||||
|
|
||||||
|
// Transitions reelles entre `depuisIso` (exclu) et `jusquaIso` (inclus), en
|
||||||
|
// partant de l'etat `depart`. Les lectures indisponibles ne comptent pas.
|
||||||
|
// Pure (testee) : `serie` = reponse de /api/history/period pour une entite.
|
||||||
|
export function transitionsDansSerie(serie, depart, depuisIso, jusquaIso) {
|
||||||
|
const depuis = Date.parse(depuisIso), jusqua = Date.parse(jusquaIso);
|
||||||
|
const res = [];
|
||||||
|
let courant = depart;
|
||||||
|
for (const e of serie || []) {
|
||||||
|
const t = Date.parse(e.last_changed);
|
||||||
|
if (!(t > depuis && t <= jusqua)) continue;
|
||||||
|
const etat = txt(e.state);
|
||||||
|
if (ETATS_ABSENTS.has(etat) || etat === courant) continue;
|
||||||
|
res.push({ avant: courant, apres: etat, a: e.last_changed });
|
||||||
|
courant = etat;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ import pg from 'pg';
|
|||||||
import { creerSchemaKm, ingererReleves, ingererNiveauSaisi, ingererJeep } from './kilometrage.mjs';
|
import { creerSchemaKm, ingererReleves, ingererNiveauSaisi, ingererJeep } from './kilometrage.mjs';
|
||||||
import { texteRapport, envoyer, donneesNuit, texteDepuis } from './rapport-nuit.mjs';
|
import { texteRapport, envoyer, donneesNuit, texteDepuis } from './rapport-nuit.mjs';
|
||||||
import { diagnosticPv, etatCellules, productionJour, chargeSolaire, bilanNuit, etatReseau, importJour, minuitLocal, COMPTEURS_IMPORT, COMPTEUR_EDF, consoJour, COMPTEURS_CONSO, projectionSoir, previsionNuit, vrmVersCourbes, nuitMaisonPrevue } from './diagnostics-agent.mjs';
|
import { diagnosticPv, etatCellules, productionJour, chargeSolaire, bilanNuit, etatReseau, importJour, minuitLocal, COMPTEURS_IMPORT, COMPTEUR_EDF, consoJour, COMPTEURS_CONSO, projectionSoir, previsionNuit, vrmVersCourbes, nuitMaisonPrevue } from './diagnostics-agent.mjs';
|
||||||
|
import { transitionsDansSerie } from './allers-retours.mjs';
|
||||||
|
|
||||||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
const ONCE = process.argv.includes('--once');
|
const ONCE = process.argv.includes('--once');
|
||||||
@@ -158,10 +159,13 @@ function demarrageHaMs(st) {
|
|||||||
return n >= 10 ? meilleur * 1000 : null;
|
return n >= 10 ? meilleur * 1000 : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function journaliser(sql, genre, resume, detail) {
|
async function journaliser(sql, genre, resume, detail, ts = null) {
|
||||||
|
// `ts` : horodatage HA d'une transition retrouvee apres coup (aller-retour
|
||||||
|
// bref, cf. detecterEvenements) ; sinon l'heure d'ecriture (defaut de la table).
|
||||||
await sql(
|
await sql(
|
||||||
`INSERT INTO evenement (genre, source, resume, detail) VALUES ($1, $2, $3, $4)`,
|
`INSERT INTO evenement (ts, genre, source, resume, detail)
|
||||||
[genre, 'historisation', resume, JSON.stringify(detail || {})]
|
VALUES (COALESCE($5::timestamptz, now()), $1, $2, $3, $4)`,
|
||||||
|
[genre, 'historisation', resume, JSON.stringify(detail || {}), ts]
|
||||||
);
|
);
|
||||||
console.log(` evenement [${genre}] ${resume}`);
|
console.log(` evenement [${genre}] ${resume}`);
|
||||||
}
|
}
|
||||||
@@ -430,13 +434,37 @@ async function ecrirePrevision(sql, st) {
|
|||||||
// Memoire entre cycles. Au PREMIER passage on enregistre l'etat sans rien
|
// Memoire entre cycles. Au PREMIER passage on enregistre l'etat sans rien
|
||||||
// journaliser : sinon chaque redemarrage du service produirait douze fausses
|
// journaliser : sinon chaque redemarrage du service produirait douze fausses
|
||||||
// transitions. Seul le demarrage du service lui-meme est consigne.
|
// transitions. Seul le demarrage du service lui-meme est consigne.
|
||||||
const memoire = { amorce: false, demarrageHa: null, valeurs: new Map() };
|
const memoire = { amorce: false, demarrageHa: null, valeurs: new Map(), changes: new Map() };
|
||||||
|
|
||||||
|
// ALLERS-RETOURS BREFS (06/10/2026). Le service lit l'etat une fois par cycle
|
||||||
|
// (~75 s) : un debranchement-rebranchement de 20 s (echange VW -> JEEP a
|
||||||
|
// 19:52:36 / 19:52:56 le 06/10) tombe entre deux lectures, l'etat est le meme
|
||||||
|
// avant et apres, et AUCUN branchement n'etait vu — ni par l'etiquetage, ni par
|
||||||
|
// le concierge qui lit cette table. Le `last_changed` de HA, lui, avance : sur
|
||||||
|
// ces entites, s'il a bouge alors que l'etat est identique, on relit
|
||||||
|
// l'historique HA de l'intervalle et on journalise chaque transition a SON
|
||||||
|
// horodatage. C'est la signature d'un echange de vehicule.
|
||||||
|
const ALLERS_RETOURS_SUIVIS = new Set([
|
||||||
|
'binary_sensor.victron_evcs_vehicle_connected',
|
||||||
|
'switch.edf_general_ok_switch',
|
||||||
|
]);
|
||||||
|
async function transitionsCachees(id, depart, depuisIso, jusquaIso) {
|
||||||
|
const r = await fetch(
|
||||||
|
`${HA_URL}/api/history/period/${encodeURIComponent(depuisIso)}?end_time=` +
|
||||||
|
`${encodeURIComponent(new Date(Date.parse(jusquaIso) + 1000).toISOString())}` +
|
||||||
|
`&filter_entity_id=${id}&minimal_response&no_attributes`,
|
||||||
|
{ headers: { Authorization: `Bearer ${HA_TOKEN}` }, signal: AbortSignal.timeout(15000) },
|
||||||
|
);
|
||||||
|
if (!r.ok) throw new Error(`historique HA ${r.status}`);
|
||||||
|
const series = await r.json();
|
||||||
|
return transitionsDansSerie(series[0], depart, depuisIso, jusquaIso);
|
||||||
|
}
|
||||||
|
|
||||||
async function detecterEvenements(sql, st) {
|
async function detecterEvenements(sql, st) {
|
||||||
if (!memoire.amorce) {
|
if (!memoire.amorce) {
|
||||||
for (const [id] of TRANSITIONS_SUIVIES.map((t) => [t[0]])) {
|
for (const [id] of TRANSITIONS_SUIVIES.map((t) => [t[0]])) {
|
||||||
const e = st.get(id);
|
const e = st.get(id);
|
||||||
if (e) memoire.valeurs.set(id, txt(e.state));
|
if (e) { memoire.valeurs.set(id, txt(e.state)); memoire.changes.set(id, e.last_changed); }
|
||||||
}
|
}
|
||||||
memoire.demarrageHa = demarrageHaMs(st);
|
memoire.demarrageHa = demarrageHaMs(st);
|
||||||
memoire.amorce = true;
|
memoire.amorce = true;
|
||||||
@@ -473,8 +501,30 @@ async function detecterEvenements(sql, st) {
|
|||||||
// lecture. La consigner ferait deux lignes de bruit a chaque hoquet MQTT.
|
// lecture. La consigner ferait deux lignes de bruit a chaque hoquet MQTT.
|
||||||
if (cur === '' || cur === 'unavailable' || cur === 'unknown') continue;
|
if (cur === '' || cur === 'unavailable' || cur === 'unknown') continue;
|
||||||
const prec = memoire.valeurs.get(id);
|
const prec = memoire.valeurs.get(id);
|
||||||
|
const changePrec = memoire.changes.get(id);
|
||||||
|
memoire.changes.set(id, e.last_changed);
|
||||||
if (prec === undefined) { memoire.valeurs.set(id, cur); continue; }
|
if (prec === undefined) { memoire.valeurs.set(id, cur); continue; }
|
||||||
if (prec === cur) continue;
|
if (prec === cur) {
|
||||||
|
if (!ALLERS_RETOURS_SUIVIS.has(id) || !changePrec
|
||||||
|
|| !(Date.parse(e.last_changed) > Date.parse(changePrec))) continue;
|
||||||
|
let cachees = [];
|
||||||
|
try {
|
||||||
|
cachees = await transitionsCachees(id, prec, changePrec, e.last_changed);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` aller-retour ${id} : historique illisible (${err.message})`);
|
||||||
|
}
|
||||||
|
for (const tr of cachees) {
|
||||||
|
const quiC = await auteurDeLaTransition(id, tr.a);
|
||||||
|
const resumeC = `${libelle} : ${tr.avant} -> ${tr.apres} (aller-retour bref, retrouve dans l historique HA)`
|
||||||
|
+ (quiC ? (quiC.type === 'derivation' ? ` — derive de ${quiC.nom}` : ` — par ${quiC.nom}`) : '');
|
||||||
|
await journaliser(sql, genre, resumeC, {
|
||||||
|
entite: id, avant: tr.avant, apres: tr.apres, horodatage_ha: tr.a, aller_retour: true,
|
||||||
|
...(quiC ? { auteur: quiC.auteur, auteur_nom: quiC.nom, auteur_type: quiC.type, declencheur: quiC.declencheur } : {}),
|
||||||
|
}, tr.a);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const qui = await auteurDeLaTransition(id, e.last_changed);
|
const qui = await auteurDeLaTransition(id, e.last_changed);
|
||||||
// L auteur est colle au RESUME, pas seulement au detail : c est le resume
|
// L auteur est colle au RESUME, pas seulement au detail : c est le resume
|
||||||
// que Grafana affiche en annotation sur tous les tableaux et dans les
|
// que Grafana affiche en annotation sur tous les tableaux et dans les
|
||||||
|
|||||||
Reference in New Issue
Block a user