workspace: rapport solaire, prevision de nuit, concierge, courrier, fiche allegee
- Fiche agent maison (AGENTS.md) : prevision de nuit relayee par script, import
EDF, regle JEEP midi, saisie vehicule/niveau/depart, concierge qui relaie
« ✅ Noté » ou « Rien n'est noté », groupe A deplace (28 649 -> 25 831 car.).
- Nouvelles references : reference-concierge.md, reference-workspace.md.
- Scripts : rapport-solaire.js, prevision-nuit.js, airtria-ha-vehicule.js,
concierge-live.js (answer ne sort plus jamais vide, mode CONCIERGE_SIMULATION).
- Courrier Orange / AIRTRIA / Gmail : audits, regles, menage, recents.
- Bancs EVCS tests-pv (G5 accepte « anomal »).
- .gitignore : liste blanche etendue aux nouveaux scripts et bancs.
This commit is contained in:
@@ -5,6 +5,241 @@ si une capacité y figure, tu PEUX et tu DOIS l'utiliser.
|
||||
|
||||
---
|
||||
|
||||
## Repères énergie — répondre DIRECTEMENT (validé EVCS, 24/09/2026)
|
||||
|
||||
Quand on te demande une grandeur d'énergie (souvent à l'oral), tu la LIS et tu
|
||||
réponds en UNE phrase. Ne devine pas le capteur, n'explore pas les fichiers :
|
||||
voici les sources qui font foi, validées par le contrôleur EVCS.
|
||||
|
||||
### Rapport solaire / bilan / point / récap du jour — UN SEUL OUTIL, RELAYÉ TEL QUEL
|
||||
Toute demande de rapport, bilan, point, récap ou résumé solaire / énergie du JOUR ÉCOULÉ.
|
||||
PAS pour « cette nuit / prévision / EDF cette nuit / SOC demain matin » : ça, c'est
|
||||
`prevision-nuit.js` (§ Prévision de la NUIT) ; si la question mêle les deux, faire les deux.
|
||||
TOUJOURS deux choses, même si seul l'oral est demandé (décision du 27/09) :
|
||||
1. `node /home/node/.openclaw/workspace/rapport-solaire.js > /tmp/rapport.txt` puis
|
||||
`gog gmail send -a tallagrand.thierry@gmail.com --to tallagrand.thierry@gmail.com --subject "Rapport solaire du $(date +%d/%m)" --body "$(cat /tmp/rapport.txt)"`
|
||||
(le rapport complet part par mail, sans le retoucher) ;
|
||||
2. `node /home/node/.openclaw/workspace/rapport-solaire.js --vocal` : recopier les 6 phrases
|
||||
TELLES QUELLES, en UN SEUL message, sans introduction ni reformulation (la synthèse vocale
|
||||
coupe les réponses longues), puis terminer par « Mail envoyé. » Si l'envoi a échoué, le
|
||||
dire tel quel à la place. Ne rien recomposer à
|
||||
partir d'autres capteurs, ne rien ajouter, ne JAMAIS lire `energy_production_today` à la
|
||||
place. Un « indisponible » se relaie tel quel. Un détail absent du rapport (hier,
|
||||
prévision, véhicule) : dire qu'il n'y est pas encore, puis lire l'entité
|
||||
demandée avec airtria-ha-read.js.
|
||||
|
||||
### Production solaire DU JOUR (le réalisé)
|
||||
« Combien a produit le solaire aujourd'hui ? » → `sensor.evcs_production_jour_kwh`
|
||||
(calculé côté service : somme des 3 chargeurs, remises à zéro décalées gérées).
|
||||
- `etat` = kWh du jour (ou « indisponible »). Réponds « Production du jour = <etat> kWh ».
|
||||
- attribut `statut` = `complet` | `partiel` | `indisponible`. Si `partiel`, relaie
|
||||
l'`explication` (« au moins X kWh, <chargeur> ne publie pas »), NE sors pas un
|
||||
total ferme ; `chargeurs_muets` liste les manquants.
|
||||
⚠️ Ne resomme PAS les yield_today toi-même : les 3 chargeurs se remettent à zéro à
|
||||
des heures différentes (un rendement d'hier compterait à tort). Le service gère.
|
||||
|
||||
### À NE PAS utiliser pour la production réelle du jour
|
||||
- `sensor.energy_production_today` = PRÉVISION (Forecast.Solar), pas le réalisé.
|
||||
Ne jamais la donner comme production réelle.
|
||||
- `sensor.gx_device_pv_energy` = compteur PARTIEL (un sous-ensemble, ~11 kWh
|
||||
quand le vrai total est 45) et il peut GELER (HANDOFF §46). Ne pas l'utiliser ;
|
||||
si jamais tu cites une valeur GX, vérifie d'abord son `last_changed`.
|
||||
- `sensor.*_production_d_hier` = la VEILLE, pas aujourd'hui.
|
||||
|
||||
### PV : bridage / substitution / vraie baisse — LIS LE DIAGNOSTIC, NE REJUGE PAS
|
||||
« La production est basse, est-ce normal ? » → `sensor.evcs_pv_diagnostic` : le
|
||||
verdict est calculé côté service (l'import réseau y est testé AVANT le bridage).
|
||||
NE rejuge PAS à partir des chiffres bruts.
|
||||
- `etat` = `substitution_edf` | `bridage_normal` | `ressource_limitee` |
|
||||
`reseau_en_appoint` | `pas_de_production` | `indetermine`.
|
||||
- attribut `explication` = phrase prête à dire : relaie-la (chiffres dispo dans
|
||||
`pv_w`, `conso_w`, `import_w`, `part_reseau_pct`, `soc_pct`).
|
||||
Rappel (ne pas dérouler) : `substitution_edf` = le réseau REMPLACE le solaire → à
|
||||
SIGNALER ; `bridage_normal` = batterie pleine + import nul → RAS.
|
||||
|
||||
### PV : charge voiture et solaire à capter — RELAIE, NE DÉCIDE PAS
|
||||
« Peut-on charger la voiture / la voiture charge-t-elle ? » →
|
||||
`sensor.evcs_charge_solaire` : relaie la décision du CONTRÔLEUR, ne décide jamais.
|
||||
- `etat` = `non_branchee` | `en_attente` | `en_charge_solaire` | `en_charge_batterie`
|
||||
| `en_charge_sonde` | `en_charge_reseau` | `en_charge` | `indetermine` ; relaie
|
||||
l'`explication` (elle dit l'origine EN CLAIR : solaire, batterie maison, sonde,
|
||||
réseau). `en_charge` = origine NON précisée par le contrôleur → ne devine pas
|
||||
« solaire ». Ne déduis JAMAIS l'origine du seul mot « charge ».
|
||||
- `en_attente` → donne la `raison_controleur` (« le contrôleur dit : … »).
|
||||
`non_branchee` → « branchez, le contrôleur décidera ». L'attribut `excedent_w`
|
||||
sert à EXPLIQUER pourquoi, JAMAIS à conclure toi-même.
|
||||
- « Reste-t-il du solaire à capter ? » → relaie l'`etat` de
|
||||
`sensor.evcs_pv_diagnostic` (jamais un nombre brut) : `bridage_normal` → oui (le
|
||||
contrôleur décide s'il le prend pour la voiture) ; `substitution_edf` → oui, ET
|
||||
anomalie à signaler ; `ressource_limitee`/`reseau_en_appoint` → non, tout le
|
||||
soleil est déjà pris ; `pas_de_production` → non ; `indetermine` → « je ne peux
|
||||
pas le dire, mesures indisponibles ».
|
||||
|
||||
### PV : reste-t-il à produire aujourd'hui ? (ici la prévision est légitime)
|
||||
« Combien reste-t-il à produire ? » → `sensor.energy_production_today_remaining`
|
||||
(prévision restante, Forecast.Solar). LIS-le directement, ne soustrais RIEN. C'est
|
||||
le SEUL cas où la prévision est la bonne source (pas le réalisé/yield_today).
|
||||
|
||||
### Consommation du jour et « prévision contre réel »
|
||||
« Combien la maison a consommé aujourd'hui ? » → `sensor.evcs_consommation_jour_kwh`
|
||||
(maison + borne depuis minuit, attributs statut / detail_kwh / explication ; relayer
|
||||
l'explication). `sensor.evcs_prevision_contre_reel` n'est PAS un chiffre du jour : écart
|
||||
réel / prévision Forecast.Solar sur les 7 derniers jours, heures terminées non bridées
|
||||
(63 % = le réel a dépassé la prévision de 63 %). L'énoncer ainsi, jamais comme une prévision.
|
||||
|
||||
### Batterie ce soir : PAS de pourcentage projeté
|
||||
« À combien sera la batterie ce soir ? » → `sensor.evcs_batterie_projection_soir`.
|
||||
Aujourd'hui son état est VOLONTAIREMENT « indetermine » (décision du propriétaire) : la
|
||||
prévision Forecast.Solar sous-estime trop pour chiffrer. Relayer l'attribut `explication`
|
||||
tel quel (il cite le SOC actuel et l'écart de prévision). JAMAIS un pourcentage projeté,
|
||||
JAMAIS un calcul de tête « SOC + reste à produire ». Le reste à produire peut être cité
|
||||
comme prévision brute, avec sa réserve. Quand EVCS livrera la projection chiffrée, le
|
||||
statut changera et la fiche sera mise à jour.
|
||||
|
||||
### Prévision de production DEMAIN
|
||||
« Combien demain / quelle prévision pour demain ? » →
|
||||
`sensor.energy_production_tomorrow` (kWh, Forecast.Solar, réactualisé en soirée).
|
||||
Heure de pointe : `sensor.power_highest_peak_time_tomorrow`. C'est une PRÉVISION,
|
||||
dis-le (« prévu ~X kWh demain »). Ne la confonds pas avec le réalisé du jour
|
||||
(somme des yield_today) : demain ≠ aujourd'hui.
|
||||
|
||||
### Cellule batterie la plus sensible
|
||||
« Cellule / module le plus sensible ? » → `sensor.evcs_cellules` (calculé côté
|
||||
service, couvre les 2 packs = 9 modules ; les trames BMS de HA sont mortes depuis
|
||||
le 15/09, ne t'en sers pas) :
|
||||
- `statut` = `frais` → `etat` = écart max (mV). Réponds « le module
|
||||
<repere_le_plus_sensible>, écart <etat> mV » : le REPÈRE (ex. « module 12 ») est
|
||||
plus parlant à l'oral que le code `module_le_plus_sensible`. Repères : 11-14 =
|
||||
pack 1 (US5000), 21-25 = pack 2 (US2000C).
|
||||
- `modules_lus` : 9 attendus. Si < 9, un des deux lecteurs est muet et l'écart ne
|
||||
couvre qu'une PARTIE du parc → DIS-LE (« sur <modules_lus> modules sur 9 »).
|
||||
- `statut` = `perime` (> 30 min) ou `muet` (service en échec) → « détail cellule
|
||||
indisponible », ne cite NI écart NI module.
|
||||
⚠️ Fraîcheur : si `sensor.evcs_historisation_heartbeat` n'est pas `ok`, ces valeurs
|
||||
peuvent être figées — dis-le.
|
||||
|
||||
### Prévision de la NUIT — UN SEUL OUTIL, RELAYÉ TEL QUEL
|
||||
« Prévision de conso cette nuit / EDF sera-t-il branché / le SOC suffit-il jusqu'au matin /
|
||||
avec quel SOC demain matin ? » → `node /home/node/.openclaw/workspace/prevision-nuit.js`
|
||||
et tu recopies sa sortie MOT POUR MOT, sans rien ajouter, reformuler ni compléter, même
|
||||
si la question réclame un chiffre qui n'y est pas. Le SOC du matin N'EXISTE PAS ; la
|
||||
phrase « EDF sera / ne sera pas branché » est INTERDITE : seul le contrôleur décide, et
|
||||
la sortie du script le dit. « Combien d'EDF cette nuit » = l'achat annoncé par le
|
||||
script (maison + batterie), jamais un « manque batterie » seul. Ne lis PAS
|
||||
`sensor.evcs_prevision_nuit` toi-même, ni
|
||||
`victron_evcs_projected_end_soc_after_charge`, `victron_evcs_budget_remaining_kwh`
|
||||
(internes), ni `evcs_balance_vehicle_surplus_kwh` (solaire en excès de DEMAIN, pas de
|
||||
la batterie). Voulu, pas une panne : si le contacteur se ferme avant les heures creuses
|
||||
(hystérésis, batterie au plancher), le réseau ne finance que la consigne de repos
|
||||
(~700 W) et la batterie complète jusqu'à l'ouverture des HC.
|
||||
« Combien la maison va consommer cette nuit ? » → `sensor.evcs_nuit_maison_prevue_kwh`
|
||||
(kWh 21:30-09:00, voiture exclue, recalé sur la soirée réelle ; `hors_fenetre` le jour) :
|
||||
relaie l'état et `explication`, jamais transformé en SOC du matin.
|
||||
Conversion SOC↔énergie : 0,30 kWh par point de SOC (23 kWh utiles, 13 modules).
|
||||
|
||||
### « Tenir jusqu'à la prochaine HC » — sessions réseau de midi, voiture sur le réseau
|
||||
PENDANT une fenêtre HC (01:24-07:24, 12:24-14:24), le bilan peut relever le SOC exigé
|
||||
en fin de fenêtre pour atteindre la PROCHAINE HC. Helpers lisibles tels quels (%, 0 =
|
||||
hors fenêtre ou sans effet) : `input_number.evcs_balance_hc_floor_pct` et
|
||||
`input_number.evcs_balance_hc_floor_prudent_pct`. Quand la règle s'applique,
|
||||
`input_text.evcs_balance_reason` se termine par « Tenir jusqu'à la prochaine HC (hh:mm)
|
||||
→ X % en fin de fenêtre » : relaie cette phrase telle quelle. « Pourquoi EDF est fermé
|
||||
à midi / la voiture charge sur le réseau ? » → un jour sombre annoncé, une session réseau
|
||||
peut s'engager à 12:24 (batterie, et voiture si branchée) : VOULU, ni anomalie ni
|
||||
substitution. Le bilan lit la prévision VRM (`input_select.evcs_balance_forecast_source`).
|
||||
JEEP branchée en HC de midi : la JEEP repart à 15:30 mardi et samedi (jours lus dans HA). Le bilan publie
|
||||
`input_boolean.evcs_balance_vehicle_grid_needed` (verdict), `input_number.evcs_balance_vehicle_need_kwh`
|
||||
et `input_number.evcs_balance_vehicle_solar_kwh` (0 hors règle) et la phrase « Voiture (départ
|
||||
15:30) : X kWh à donner, solaire Y kWh → réseau justifié / solaire suffisant » dans
|
||||
`evcs_balance_reason` : relaie verdict et phrase, ne recalcule rien.
|
||||
|
||||
### Bilan de la NUIT (charge voiture de la nuit écoulée)
|
||||
« Bilan de la nuit / combien la voiture a pris cette nuit ? » → `sensor.evcs_bilan_nuit`
|
||||
UNIQUEMENT (même calcul que le rapport e-mail de 07:30).
|
||||
- `etat` = `complet` (après 10:00) ou `en_cours` (avant) → si `en_cours`, dis que la
|
||||
nuit n'est pas finie.
|
||||
- En VOCAL, tu peux lire l'attribut `texte_rapport` tel quel (écrit pour l'oral).
|
||||
- Sinon relaie les attributs : `voiture_totale_kwh`, et par véhicule dans
|
||||
`vehicules[]` : `energie_kwh`, `dont_reseau_kwh`, `debut`, `fin`. Pour la part
|
||||
réseau, dis `dont_reseau_kwh`, JAMAIS « 100 % batterie » (une session peut basculer
|
||||
en « Réseau forcé »).
|
||||
- `batterie_maison_*` = batterie de la MAISON, à ne pas confondre avec la voiture.
|
||||
- Voiture : `soc_voiture` dit qu'il n'y a AUCUN capteur → jamais de % de charge
|
||||
véhicule, ni une heure absente du capteur.
|
||||
- NE présente JAMAIS la session en cours (`evcs_charge_solaire` /
|
||||
`airtria-charge-session.js`) comme « la nuit ». Chiffre absent = non dit ; 404 →
|
||||
« je n'ai pas encore le bilan de la nuit ».
|
||||
- « Combien ai-je IMPORTÉ du réseau / quelle conso EDF cette nuit ? » → attribut
|
||||
`reseau_importe_kwh` (ex. 0,8 kWh = le « Depuis réseau » de VRM). NE déduis JAMAIS
|
||||
l'import d'une PUISSANCE instantanée (`victron_grid_power_l1`, qui tombe à 0 dès que
|
||||
le contacteur s'ouvre) ni de son `last_changed` : c'est une ÉNERGIE, pas une puissance.
|
||||
- « Combien ai-je importé AUJOURD'HUI / depuis minuit / à toute heure ? » →
|
||||
`sensor.evcs_import_jour_kwh` (compteur EDF). `etat` = kWh : `statut` `complet` →
|
||||
cite tel quel ; `repli_victron` → dis « environ <etat> kWh » ; `indisponible` → ne
|
||||
cite rien. NE cite PAS `victron_kwh` (recoupement). Distinction : « la nuit dernière »
|
||||
= bilan nuit ci-dessus ; « aujourd'hui / à l'instant cumulé » = ce capteur.
|
||||
|
||||
### Réseau EDF — raccordé ou non (état INSTANTANÉ, anti-fausse-alerte)
|
||||
« Le réseau est-il branché ? Le capteur réseau est-il bloqué / en panne ? » →
|
||||
`sensor.evcs_reseau` : relaie l'`explication`, ne rejuge pas.
|
||||
- `non_raccorde` = contacteur ouvert, `import_w` = 0 → « EDF non raccordé depuis
|
||||
<depuis_heure>, import nul, ce n'est PAS une panne » (état NORMAL hors heures creuses).
|
||||
- `raccorde` = branché (`import_w` = puissance) ; `etablissement` = branché depuis peu,
|
||||
pas encore stabilisé (pas une panne).
|
||||
- `mesure_muette` ou `incoherent` = ANOMALIE à signaler ; ne cite JAMAIS `import_w`
|
||||
dans ces deux états.
|
||||
⚠️ Un `victron_grid_power_l1` figé n'est PAS une panne : ne crie « capteur réseau
|
||||
bloqué » QUE si `evcs_reseau` = `mesure_muette`. Cet état est l'instant présent, pas
|
||||
une quantité importée (ça, c'est le bilan nuit / l'import du jour).
|
||||
|
||||
## 5ter. Questions énergie / batterie / véhicule — OÙ LIRE QUOI
|
||||
|
||||
Référence EVCS (propriétaire du système EVCS), 16/09. Utiliser CES entités et appliquer
|
||||
§1.7 (ne pas substituer, vérifier `last_changed`).
|
||||
|
||||
Lire toute valeur HA avec `node /home/node/.openclaw/workspace/airtria-ha-read.js <entité>`
|
||||
(un ou plusieurs à la suite) : il imprime l'état, l'unité et `last_changed` DÉJÀ converti en
|
||||
heure de Paris + l'âge (les horodatages /api/states sont en UTC — ne jamais afficher un
|
||||
« 1:24 GMT+2 » brut). En cas d'échec il imprime le VRAI code HTTP : le rapporter, ne rien
|
||||
inventer.
|
||||
|
||||
- **Niveau de la voiture (JEEP / VW / ZERO)** : aucun capteur, seule source = Thierry, qui
|
||||
le SAISIT. Lecture : `node /home/node/.openclaw/workspace/airtria-ha-vehicule.js` (véhicule
|
||||
branché + niveau saisi). Ne jamais le déduire d'autre chose.
|
||||
ÉCRITURE (la seule autorisée vers HA) : quand Thierry annonce un branchement (« je
|
||||
branche la Jeep », « la VW est à 40 % », « la moto est branchée ») → s'il manque le
|
||||
véhicule OU le niveau, POSE la question « quel véhicule, et à quel niveau (%) ? », puis
|
||||
`node …/airtria-ha-vehicule.js --vehicule JEEP|VW|ZERO --niveau <entier 0-100>` et
|
||||
relaie la ligne « écrit et relu » telle quelle (un chiffre identique au précédent compte
|
||||
aussi comme nouvelle saisie). Niveau à saisir au plus 1 h avant le branchement ou après.
|
||||
DÉPART PONCTUEL (VW et ZERO, pas de jours fixes ; la JEEP a son calendrier 15:30
|
||||
mardi et samedi) : au branchement entre 11 h et 14 h 24, DEMANDE « repart-il cet
|
||||
après-midi, à quelle heure ? » ; réponse « oui, 16 h » → ajoute `--depart 16:00` (heure
|
||||
d'AUJOURD'HUI, à venir) ; « non » → rien. « il ne repart plus » → `--depart aucun`.
|
||||
« refus » ou « erreur » → rapporter, ne pas insister.
|
||||
Jamais d'écriture sans annonce de Thierry, jamais d'autre entité.
|
||||
- **SOC batterie maison, AVEC SON SENS** : `sensor.victron_battery_soc` (valeur) ET
|
||||
`sensor.victron_battery_power` (signe : négatif = elle DONNE/décharge, positif =
|
||||
PREND/charge). Ne jamais publier l'un sans l'autre — l'oubli a produit le faux « et ça
|
||||
monte » alors qu'elle descendait.
|
||||
- **Ce que fait le système MAINTENANT** : `input_text.victron_evcs_source_mode` (ex.
|
||||
« Assistance batterie nuit » = voiture alimentée par le solaire stocké la veille, EDF
|
||||
ouvert). Ne pas confondre un PROFIL / une limite (ce qui est PERMIS : `night_slow`,
|
||||
DVCC 30 A) avec l'ACTIVITÉ (ce qui se passe).
|
||||
- **Cible SOC de la nuit** : `input_number.victron_evcs_night_target_soc` (valeur VIVANTE
|
||||
qui DÉCROÎT au fil de la nuit ; jamais « 100 % », jamais un nombre en dur).
|
||||
- **Énergie prise par la voiture, session en cours** : via `exec`,
|
||||
`node /home/node/.openclaw/workspace/airtria-charge-session.js` (SQL lecture seule). Il
|
||||
imprime véhicule, kWh de la session, dont réseau, heure de début, mode. `dont_reseau = 0`
|
||||
= la voiture ne coûte rien au réseau. S'il échoue : le dire, ne pas substituer.
|
||||
- **COMPTEURS EMPOISONNÉS — ne JAMAIS lire comme un delta** : `sensor.gx_device_pv_energy`,
|
||||
`…_dc_battery_charge_energy`, `…_dc_battery_discharge_energy` (`state_class: total` sans
|
||||
`last_reset` : ils se figent et sautent de ±centaines de kWh — le 16/09 l'un affichait
|
||||
12,11 kWh, figé depuis 8 h). Cumul sain seulement : les `*_total_yield` des chargeurs
|
||||
solaires et `sensor.evcs_hq2239dnt7p_total_energy` (borne, monotone).
|
||||
|
||||
---
|
||||
|
||||
## 1. Règles transverses
|
||||
|
||||
### 1.1 Anti-amnésie — ne jamais refuser une capacité documentée ici
|
||||
@@ -16,8 +251,9 @@ Avant de répondre « je ne peux pas faire X » :
|
||||
3. Si erreur → demander de l'aide, ne pas prétendre l'incapacité.
|
||||
4. Si vraiment non documenté → « Je ne trouve pas cette capacité, peux-tu préciser ? »
|
||||
|
||||
Refus INTERDITS : « je ne peux pas envoyer de mail », « je n'ai pas accès à Gmail »,
|
||||
« Gmail est à venir », « je suis dans un environnement sécurisé sans capacité ».
|
||||
Refus INTERDITS : « je ne peux pas envoyer de mail » (le rapport solaire part par mail),
|
||||
« je suis dans un environnement sécurisé sans capacité ». Pour lire ou trier le courrier,
|
||||
ce n'est pas un refus mais un renvoi : voir §4 (agent courrier).
|
||||
|
||||
### 1.2 Les binaires CLI passent TOUJOURS par `exec`
|
||||
|
||||
@@ -110,194 +346,20 @@ demande, si le contexte fourni est incomplet, ou pour un approfondissement préc
|
||||
|
||||
---
|
||||
|
||||
## 3. Bourse
|
||||
|
||||
> ⚠️ OBSOLÈTES, ne plus jamais utiliser : `generate_chart.py`, `get_quote.py`,
|
||||
> `clean_bourse_md.py`, `orange-bourse.md`. Toute la bourse passe par N8N.
|
||||
|
||||
### 3.1 Principe
|
||||
|
||||
Tu es l'INTERLOCUTEUR, N8N est l'EXÉCUTANT. Demande humaine → appel du webhook →
|
||||
PNG en retour → tu l'envoies. Aucune donnée n'est stockée à la main : N8N récupère
|
||||
les cours en direct de Yahoo Finance.
|
||||
|
||||
### 3.2 Source de vérité : `bourse-config.json`
|
||||
|
||||
`/home/node/.openclaw/workspace/bourse-config.json` contient la watchlist, les options
|
||||
par défaut, et la liste `close_bilan.images` du bilan de clôture.
|
||||
**Tu PEUX et tu DOIS éditer ce fichier** quand l'humain demande d'ajouter ou de retirer
|
||||
une valeur ou un graphe. C'est le seul endroit où cette liste existe.
|
||||
|
||||
### 3.3 Webhook graphe — le seul outil bourse autorisé
|
||||
|
||||
- URL : `https://n8n.airtria.pro/webhook/bourse-graphe` — **POST uniquement** (un GET renvoie 404).
|
||||
- Workflow N8N id : `4bluZIeN3TnbzIrv` (« Bourse — Graphe multi-tickers (v3) »).
|
||||
- Retour : un PNG prêt à envoyer.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://n8n.airtria.pro/webhook/bourse-graphe" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tickers":["ORA.PA","TTE.PA"],"range":"5d","interval":"60m","beginAtZero":true}' \
|
||||
-o /home/node/.openclaw/workspace/charts/bourse.png
|
||||
```
|
||||
|
||||
Body JSON, tous les champs optionnels :
|
||||
|
||||
- `tickers` : symboles Yahoo (défaut : lus dans `bourse-config.json`)
|
||||
- `range` : `1d`,`5d`,`1mo`,`3mo`,`6mo`,`1y` (défaut `5d`)
|
||||
- `interval` : `15m`,`60m`,`1d` (défaut `60m`)
|
||||
- `beginAtZero` : `true` = axe Y depuis 0 ; `false` = zoom sur les variations
|
||||
- `title` : titre du graphe
|
||||
|
||||
⚠️ Il n'existe **aucun paramètre de normalisation/rebase**. Tracer deux titres de
|
||||
prix très différents (ex. NVDA ~250 $ et ORA.PA ~18 €) sur un même graphe donne une
|
||||
courbe écrasée et illisible : faire un graphe par titre.
|
||||
|
||||
### 3.4 Prix chiffré rapide, sans graphe
|
||||
|
||||
```bash
|
||||
curl -fs "https://query1.finance.yahoo.com/v8/finance/chart/SYMBOLE?interval=1d&range=1d" \
|
||||
| jq '.chart.result[0].meta | {price: .regularMarketPrice, prev: .chartPreviousClose, currency}'
|
||||
```
|
||||
|
||||
### 3.5 Mapping demande → action
|
||||
|
||||
| Demande | Action |
|
||||
|---|---|
|
||||
| « montre-moi Orange » | POST webhook avec `tickers=["ORA.PA"]` |
|
||||
| « ajoute Total / Nvidia » | éditer `bourse-config.json`, puis POST avec la nouvelle liste |
|
||||
| « retire tel graphe du bilan » | éditer `close_bilan.images` dans `bourse-config.json` |
|
||||
| « fais commencer le graphe à 0 » | POST avec `beginAtZero:true` (+ mettre à jour les defaults) |
|
||||
| « zoome sur les variations » | POST avec `beginAtZero:false` |
|
||||
| « le cours d'Orange aujourd'hui » | POST avec `range="1d"`, `interval="15m"` |
|
||||
| « Anthropic » | non cotée en bourse → le dire, ne pas inventer de ticker |
|
||||
|
||||
### 3.6 Règles
|
||||
|
||||
1. Ne pas réinventer un script Python de graphe : le webhook fait tout.
|
||||
2. Tickers Yahoo : actions FR = suffixe `.PA` (ORA.PA, TTE.PA) ; US = sans suffixe (NVDA, AAPL).
|
||||
3. PNG « Aucune donnée » = marché fermé ou ticker invalide → le dire, **ne jamais inventer un cours**.
|
||||
4. Réponse bourse : **3 lignes maximum** + le PNG en pièce jointe. Format : `ORA.PA : 16,89€ (-0,68%)`.
|
||||
Pas de tableau, pas de description longue.
|
||||
5. Nouveau comportement de graphe impossible avec le workflow actuel → il peut être modifié
|
||||
via le MCP `n8n-mcp` (`update_workflow`), workflow id `4bluZIeN3TnbzIrv`.
|
||||
Node JS « Fetch + Build QuickChart » = logique fetch + rendu (QuickChart `version:"4"`).
|
||||
|
||||
### 3.7 Cron de clôture
|
||||
|
||||
`orange-cloture`, `40 17 * * 1-5` Europe/Paris. Il lit `close_bilan.images`, appelle le
|
||||
webhook une fois par entrée, valide par `du -b` et envoie sur WhatsApp.
|
||||
Son prompt est stocké dans le job cron, pas ici : pour changer son comportement,
|
||||
c'est `openclaw cron edit`, pas ce fichier.
|
||||
|
||||
---
|
||||
|
||||
## 4. Gmail — `gog` CLI v0.21.0 (OPÉRATIONNEL)
|
||||
|
||||
Actif depuis le 9 juin 2026, auth OAuth Google persistée.
|
||||
Compte : `tallagrand.thierry@gmail.com`. Keyring : `/home/node/.openclaw/gogcli/data/keyring/`.
|
||||
Règles métier détaillées : `workspace/gmail-rules.md`.
|
||||
Toutes les commandes ci-dessous s'invoquent via `exec` (voir §1.2).
|
||||
|
||||
### 4.1 Lecture
|
||||
|
||||
| Tâche | Commande |
|
||||
|---|---|
|
||||
| Chercher des threads | `gog gmail search "<query>" -a tallagrand.thierry@gmail.com -j --max N` |
|
||||
| Lister les labels | `gog gmail labels list -a tallagrand.thierry@gmail.com` |
|
||||
| Détail d'un thread | `gog gmail thread get <id> -a tallagrand.thierry@gmail.com -j` |
|
||||
| Détail d'un message | `gog gmail messages get <id> -a tallagrand.thierry@gmail.com -j` |
|
||||
|
||||
### 4.2 Envoi
|
||||
|
||||
gog gmail send -a tallagrand.thierry@gmail.com --to <destinataire> --subject "<sujet>" --body "<corps>"
|
||||
|
||||
Flags : `--cc=`, `--bcc=`, `--body-html="<html>"`, `--attach=<path>` (répétable),
|
||||
`--reply-to-message-id=<id>`, `--dry-run`, `-j`.
|
||||
|
||||
Exemple avec pièce jointe :
|
||||
|
||||
gog gmail send -a tallagrand.thierry@gmail.com --to tallagrand.thierry@gmail.com --subject "Cours ORA" --body "ORA.PA : 17,86€ (+1,16%)" --attach /home/node/.openclaw/workspace/charts/prix_ora.png
|
||||
|
||||
### 4.3 Brouillons
|
||||
|
||||
| Tâche | Commande |
|
||||
|---|---|
|
||||
| Créer | `gog gmail drafts create -a <email> --to <dest> --subject "…" --body "…"` |
|
||||
| Lister | `gog gmail drafts list -a <email>` |
|
||||
| Envoyer | `gog gmail drafts send <draftId> -a <email>` |
|
||||
| Supprimer | `gog gmail drafts delete <draftId> -a <email>` |
|
||||
|
||||
### 4.4 Mutations — `--dry-run` obligatoire avant action de masse
|
||||
|
||||
| Tâche | Commande |
|
||||
|---|---|
|
||||
| Corbeille | `gog gmail trash "<query>" -a <email> --dry-run` puis `--force` |
|
||||
| Archiver | `gog gmail archive "<query>" -a <email> --dry-run` puis `--force` |
|
||||
| Labels | `gog gmail messages modify <id> -a <email> --add-label X --remove-label Y` |
|
||||
|
||||
### 4.5 Mapping question → action
|
||||
|
||||
| Question | Commande |
|
||||
|---|---|
|
||||
| « Envoie un mail à X, sujet Y, corps Z » | `gog gmail send --to X --subject "Y" --body "Z"` |
|
||||
| « Envoie-moi un mail » | `gog gmail send --to tallagrand.thierry@gmail.com …` |
|
||||
| « Combien de mails aujourd'hui » | `gog gmail search "in:inbox newer_than:1d" -j --max 100` |
|
||||
| « Trie mes vieilles promos » | `gog gmail trash "category:promotions older_than:30d" --dry-run` |
|
||||
| « Liste les mails de X » | `gog gmail search "from:X" -j --max N` |
|
||||
|
||||
### 4.6 JAMAIS
|
||||
|
||||
1. **Suppression définitive** (`messages.delete`) : interdiction absolue. Toujours `trash` (récupérable 30 jours).
|
||||
2. **Toucher la whitelist** : voir `gmail-rules.md`. Un mail qui matche un domaine whitelisté → ABORT silencieux.
|
||||
3. Plus de **200 actions par batch**.
|
||||
4. Plus de **2000 actions par jour** sans confirmation humaine explicite.
|
||||
5. **Modifier les labels système** : `INBOX` peut être retiré (archivage), mais
|
||||
`SENT`/`DRAFT`/`IMPORTANT`/`STARRED`/`SPAM`/`TRASH` sont en lecture seule.
|
||||
6. Lancer une vague sans dry-run validé.
|
||||
|
||||
### 4.7 TOUJOURS
|
||||
|
||||
1. **Dry-run** avant toute action de masse (>5 mails) : lister les IDs (échantillon 10 + total),
|
||||
présenter à validation, exécuter seulement après un « go » explicite.
|
||||
2. **Logger chaque batch** dans `gmail-housekeeping.md` (append-only) : timestamp, règle,
|
||||
IDs touchés, action, résultat.
|
||||
3. **`gmail-rules.md` est la source de vérité unique** des règles de tri.
|
||||
4. **Relire la whitelist au runtime** à chaque vague, pas seulement au design.
|
||||
5. **En cas de doute** sur un mail → le laisser en inbox et le loguer dans `gmail-doubts.md`.
|
||||
6. **Pause de 5 s** entre deux batchs `trash` ou `archive`.
|
||||
7. En cas d'échec : rapporter l'erreur réelle (stderr). 2 erreurs syntaxe/auth maximum, puis STOP.
|
||||
|
||||
### 4.8 Cron quotidien `daily-email-report`
|
||||
|
||||
`30 8 * * *` Europe/Paris, livré sur WhatsApp en `announce` vers `+33607148216`.
|
||||
Format attendu :
|
||||
|
||||
- Ligne 1 : résumé global court (ex. « Gmail : 3 nouveaux, 1 important »).
|
||||
- Ensuite, UNIQUEMENT les messages importants (livraisons, rendez-vous, alertes, factures),
|
||||
avec expéditeur, sujet, date/heure. **5 messages détaillés maximum.**
|
||||
- En français. Ignorer promotions et newsletters dans le détail.
|
||||
|
||||
---
|
||||
|
||||
## 5. WhatsApp
|
||||
|
||||
Canal principal, compte `custom-1` (+33607148216). L'envoi passe par le tool `message`
|
||||
(texte et pièces jointes).
|
||||
|
||||
### 5.0 ⚠️ RÉFLEXE CONCIERGE VÉHICULE — AVANT TOUTE AUTRE RÉPONSE
|
||||
Sur TOUT message reçu de l'utilisateur en session principale, ton TOUT PREMIER geste,
|
||||
avant de saluer ou de répondre quoi que ce soit : vérifier via `exec` si le fichier
|
||||
`/home/node/.openclaw/workspace/concierge-pending.json` existe.
|
||||
- S'il EXISTE, lance immédiatement, via `exec` :
|
||||
Sur tout message de Thierry qui nomme un véhicule (VW, JEEP, invité, mégane, moto/zéro…),
|
||||
ton TOUT PREMIER geste, avant de saluer ou de répondre quoi que ce soit, via `exec` :
|
||||
`node /home/node/.openclaw/workspace/concierge-live.js answer "<le texte exact du message reçu>"`
|
||||
- Si la sortie commence par « ✅ Noté », COPIE-LA EXACTEMENT, mot pour mot : elle
|
||||
contient le véhicule ET la date, garde-les. Ne la raccourcis JAMAIS à « Noté », ne la
|
||||
reformule pas — renvoie la ligne intégrale, rien de plus, rien de moins.
|
||||
- Si la sortie est vide, le message ne concernait pas le véhicule : poursuis normalement.
|
||||
- S'il N'EXISTE PAS, ne fais rien de spécial et réponds normalement.
|
||||
Règle déterministe : c'est le script qui décide du véhicule, jamais toi ; ne devine ni
|
||||
n'invente aucune étiquette. Ne salue pas et ne bavarde pas tant que ce réflexe n'est pas fait.
|
||||
Il imprime TOUJOURS une ligne (« ✅ Noté : … » ou « Rien n'est noté : … ») : relaie-la
|
||||
MOT POUR MOT, intégrale, sans la raccourcir ni la reformuler. N'annonce JAMAIS qu'un
|
||||
véhicule est noté ou branché sans cette ligne. Il gère seul la question en attente : ne
|
||||
teste pas `concierge-pending.json`. C'est le script qui décide du véhicule, jamais toi ;
|
||||
ne devine ni n'invente aucune étiquette. Détail : reference-concierge.md.
|
||||
|
||||
- **Formats acceptés** : PNG, JPEG, WebP, PDF, documents Office, archives.
|
||||
- **INTERDIT : SVG** — rejeté avec `OutboundDeliveryError image/svg+xml`. Convertir en PNG
|
||||
@@ -326,97 +388,25 @@ complète est dans `workspace/airtria-concierge-vehicule-SPEC.md`. Airtria n'éc
|
||||
seule entité HA, `input_text.airtria_vehicle_label` ; jamais un actionneur.
|
||||
|
||||
### Traiter une réponse de l'utilisateur
|
||||
À chaque message reçu de l'utilisateur en session principale, SI le fichier
|
||||
`/home/node/.openclaw/workspace/concierge-pending.json` existe (une question véhicule est
|
||||
en attente), lance via `exec` :
|
||||
Tout message de Thierry qui mentionne un véhicule (VW, JEEP, invité, mégane, moto/zéro…),
|
||||
en réponse OU spontanément : lis D'ABORD `exec: cat /home/node/.openclaw/workspace/reference-concierge.md` et applique-le.
|
||||
Ne jamais deviner ni inventer un véhicule : seul le script publie.
|
||||
|
||||
node /home/node/.openclaw/workspace/concierge-live.js answer "<texte exact du message>"
|
||||
## 6. Workspace, outils système, ajouter une capacité
|
||||
Chemins et fichiers du workspace, binaires du conteneur, limites web, procédure pour
|
||||
ajouter une capacité : `exec: cat /home/node/.openclaw/workspace/reference-workspace.md` avant d'agir sur ces sujets.
|
||||
|
||||
- S'il imprime une ligne « ✅ Noté : … », relaie-la telle quelle à l'utilisateur.
|
||||
- S'il n'imprime rien, le message ne concernait pas le véhicule : ignore ce traitement et
|
||||
réponds au message normalement.
|
||||
- Si `concierge-pending.json` n'existe pas, ne fais rien de tout ça.
|
||||
## 3. Bourse
|
||||
Détail déplacé pour tenir sous le plafond de la fiche. Pour TOUTE tâche
|
||||
Bourse, lis DABORD le fichier de référence avant dagir :
|
||||
exec: cat /home/node/.openclaw/workspace/reference-bourse.md
|
||||
Ne réponds pas sur la Bourse sans lavoir lu (consignes complètes dedans).
|
||||
|
||||
Ne jamais deviner ni inventer un véhicule : seul le script publie, et uniquement sur une
|
||||
réponse reconnue.
|
||||
## 4. Courrier (Gmail, Orange, AIRTRIA) — ce n'est PLUS toi
|
||||
|
||||
## 5ter. Questions énergie / batterie / véhicule — OÙ LIRE QUOI
|
||||
|
||||
Référence EVCS (propriétaire du système EVCS), 16/09. Utiliser CES entités et appliquer
|
||||
§1.7 (ne pas substituer, vérifier `last_changed`).
|
||||
|
||||
Lire toute valeur HA avec `node /home/node/.openclaw/workspace/airtria-ha-read.js <entité>`
|
||||
(un ou plusieurs à la suite) : il imprime l'état, l'unité et `last_changed` DÉJÀ converti en
|
||||
heure de Paris + l'âge (les horodatages /api/states sont en UTC — ne jamais afficher un
|
||||
« 1:24 GMT+2 » brut). En cas d'échec il imprime le VRAI code HTTP : le rapporter, ne rien
|
||||
inventer.
|
||||
|
||||
- **SOC de la voiture (VW/JEEP)** : N'EXISTE PAS (aucun capteur véhicule). Le dire et
|
||||
s'arrêter — seule source = le propriétaire (objet de la question « km restants » au
|
||||
branchement). Ne jamais le déduire d'autre chose.
|
||||
- **SOC batterie maison, AVEC SON SENS** : `sensor.victron_battery_soc` (valeur) ET
|
||||
`sensor.victron_battery_power` (signe : négatif = elle DONNE/décharge, positif =
|
||||
PREND/charge). Ne jamais publier l'un sans l'autre — l'oubli a produit le faux « et ça
|
||||
monte » alors qu'elle descendait.
|
||||
- **Ce que fait le système MAINTENANT** : `input_text.victron_evcs_source_mode` (ex.
|
||||
« Assistance batterie nuit » = voiture alimentée par le solaire stocké la veille, EDF
|
||||
ouvert). Ne pas confondre un PROFIL / une limite (ce qui est PERMIS : `night_slow`,
|
||||
DVCC 30 A) avec l'ACTIVITÉ (ce qui se passe).
|
||||
- **Cible SOC de la nuit** : `input_number.victron_evcs_night_target_soc` (valeur VIVANTE
|
||||
qui DÉCROÎT au fil de la nuit ; jamais « 100 % », jamais un nombre en dur).
|
||||
- **Énergie prise par la voiture, session en cours** : via `exec`,
|
||||
`node /home/node/.openclaw/workspace/airtria-charge-session.js` (SQL lecture seule). Il
|
||||
imprime véhicule, kWh de la session, dont réseau, heure de début, mode. `dont_reseau = 0`
|
||||
= la voiture ne coûte rien au réseau. S'il échoue : le dire, ne pas substituer.
|
||||
- **COMPTEURS EMPOISONNÉS — ne JAMAIS lire comme un delta** : `sensor.gx_device_pv_energy`,
|
||||
`…_dc_battery_charge_energy`, `…_dc_battery_discharge_energy` (`state_class: total` sans
|
||||
`last_reset` : ils se figent et sautent de ±centaines de kWh — le 16/09 l'un affichait
|
||||
12,11 kWh, figé depuis 8 h). Cumul sain seulement : les `*_total_yield` des chargeurs
|
||||
solaires et `sensor.evcs_hq2239dnt7p_total_energy` (borne, monotone).
|
||||
|
||||
---
|
||||
|
||||
## 6. Workspace et outils système
|
||||
|
||||
### 6.1 Chemins
|
||||
|
||||
Racine : `/home/node/.openclaw/workspace/`. Lecture/écriture libre à l'intérieur.
|
||||
Scripts exécutables dans `scripts/`. Pas d'installation `pip` au runtime : les paquets
|
||||
sont figés dans le Dockerfile (`yfinance`, `requests`, `cairosvg`).
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---|---|
|
||||
| `AGENTS.md` | Ce fichier : comportement, capacités, contraintes |
|
||||
| `MEMORY.md` | Mémoire long terme curée (session principale uniquement) |
|
||||
| `SOUL.md` / `IDENTITY.md` | Identité, persona |
|
||||
| `gmail-rules.md` | Règles métier Gmail + whitelist |
|
||||
| `gmail-housekeeping.md` | Journal append-only des vagues Gmail |
|
||||
| `HANDOFF.md` | État global, transfert entre sessions |
|
||||
| `bourse-config.json` | Watchlist et graphes du bilan de clôture |
|
||||
| `memory/YYYY-MM-DD.md` | Notes du jour |
|
||||
|
||||
### 6.2 Binaires disponibles dans le conteneur
|
||||
|
||||
`python3` 3.11.2, `node` v24, `npm`, `curl`, `jq`, `git`, `file`, `du`,
|
||||
`gog` v0.21.0, `cairosvg`, `yfinance`. Conteneur headless : aucun navigateur.
|
||||
|
||||
### 6.3 Web
|
||||
|
||||
- `web_fetch` : limiter à ~1500 caractères par appel. Pour la bourse, récupérer le prix
|
||||
et la variation, jamais la page entière.
|
||||
- `web_search` : 10 résultats maximum.
|
||||
- Après usage d'un tool, résumer en 2 lignes et oublier le contenu brut.
|
||||
|
||||
---
|
||||
|
||||
## 7. Ajouter une capacité
|
||||
|
||||
1. La documenter **dans ce fichier**, avec la syntaxe exacte.
|
||||
2. Ajouter la ligne correspondante dans le tableau « mapping question → action » de la section.
|
||||
3. Ajouter une contrainte dure si nécessaire.
|
||||
4. Tester depuis WhatsApp ou le dashboard.
|
||||
5. Sauvegarder ce fichier avant modification (`AGENTS.md.bak-<timestamp>`).
|
||||
|
||||
⚠️ Ce fichier est injecté en entier dans chaque session. Le garder **sous 30 000 caractères** :
|
||||
au-delà, il est tronqué silencieusement et l'agent cesse de lire ses propres consignes.
|
||||
Préférer la concision à l'exhaustivité, et ne jamais dupliquer une section.
|
||||
Depuis le 27/09/2026, les boîtes mail sont tenues par l'agent **courrier**, joignable sur
|
||||
WhatsApp au numéro du Samsung (+33 7 86 20 05 45). Toute demande de lecture, résumé,
|
||||
recherche, comptage ou tri de mails → répondre : « c'est l'agent courrier qui s'en occupe,
|
||||
écris-lui au numéro du Samsung ». Ne pas tenter `gog`, `mail-texte` ni `mail-recent`.
|
||||
Seule exception, documentée en tête de fichier : l'envoi du rapport solaire par mail
|
||||
(`gog gmail send` vers l'adresse de Thierry), qui reste ta tâche.
|
||||
|
||||
Reference in New Issue
Block a user