workspace: mode de charge de nuit, concierge sans relais parasite, journaux

- airtria-ha-vehicule.js : option --mode-nuit complete|sans_edf (seul
  input_select.victron_evcs_night_charge_mode, relecture, refus des options
  inconnues) ; libelle « aucune voiture branchee » distinct du selecteur.
- concierge-live.js : message sans vehicule marque « (aucune action concierge »,
  a ne pas relayer.
- AGENTS.md : routage charge voiture de la nuit et budget, regle §5.0.
- Journaux de tri Orange et AIRTRIA.
This commit is contained in:
2026-09-30 23:50:32 +02:00
parent f121f0a196
commit f18ce33d32
5 changed files with 51 additions and 4 deletions

View File

@@ -218,6 +218,12 @@ inventer.
d'AUJOURD'HUI, à venir) ; « non » → rien. « il ne repart plus » → `--depart aucun`. d'AUJOURD'HUI, à venir) ; « non » → rien. « il ne repart plus » → `--depart aucun`.
« refus » ou « erreur » → rapporter, ne pas insister. « refus » ou « erreur » → rapporter, ne pas insister.
Jamais d'écriture sans annonce de Thierry, jamais d'autre entité. Jamais d'écriture sans annonce de Thierry, jamais d'autre entité.
- **Charge voiture de la nuit** : « charge complète / à fond cette nuit » →
`node …/airtria-ha-vehicule.js --mode-nuit complete` ; « sans EDF cette nuit / seulement la
batterie » → `--mode-nuit sans_edf`, À CHAQUE demande, même si tu crois le mode déjà
réglé. Relaie sa ligne MOT POUR MOT : sans la ligne « C'est noté : charge … » de CE script,
le mode N'A PAS changé, ne dis jamais « noté ». Pas de concierge ici. « Combien la voiture
peut prendre cette nuit ? » → `prevision-nuit.js`, relayé tel quel. JAMAIS écrire le budget.
- **SOC batterie maison, AVEC SON SENS** : `sensor.victron_battery_soc` (valeur) ET - **SOC batterie maison, AVEC SON SENS** : `sensor.victron_battery_soc` (valeur) ET
`sensor.victron_battery_power` (signe : négatif = elle DONNE/décharge, positif = `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 PREND/charge). Ne jamais publier l'un sans l'autre — l'oubli a produit le faux « et ça
@@ -357,7 +363,8 @@ ton TOUT PREMIER geste, avant de saluer ou de répondre quoi que ce soit, via `e
`node /home/node/.openclaw/workspace/concierge-live.js answer "<le texte exact du message reçu>"` `node /home/node/.openclaw/workspace/concierge-live.js answer "<le texte exact du message reçu>"`
Il imprime TOUJOURS une ligne (« ✅ Noté : … » ou « Rien n'est noté : … ») : relaie-la 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 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 véhicule est noté ou branché sans cette ligne. Une sortie qui commence par « (aucune action
concierge » ne se relaie PAS : réponds simplement au message. 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 ; 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. ne devine ni n'invente aucune étiquette. Détail : reference-concierge.md.

View File

@@ -5,8 +5,11 @@
// node airtria-ha-vehicule.js --vehicule JEEP --niveau 12 // node airtria-ha-vehicule.js --vehicule JEEP --niveau 12
// node airtria-ha-vehicule.js --niveau 40 → niveau seul (véhicule inchangé) // node airtria-ha-vehicule.js --niveau 40 → niveau seul (véhicule inchangé)
// node airtria-ha-vehicule.js --depart 16:00 → départ ponctuel AUJOURD'HUI (VW, ZERO) ; --depart aucun l'efface // node airtria-ha-vehicule.js --depart 16:00 → départ ponctuel AUJOURD'HUI (VW, ZERO) ; --depart aucun l'efface
// node airtria-ha-vehicule.js --mode-nuit complete|sans_edf → charge voiture de la nuit (remis à sans_edf chaque jour à 12:00 par HA)
// Écrit UNIQUEMENT : input_select (véhicule, option lue dans HA), input_number (niveau, entier 0-100) // Écrit UNIQUEMENT : input_select (véhicule, option lue dans HA), input_number (niveau, entier 0-100)
// et input_datetime (départ ponctuel, toujours daté du JOUR, jamais une autre date). // et input_datetime (départ ponctuel, toujours daté du JOUR, jamais une autre date),
// et input_select.victron_evcs_night_charge_mode (option lue dans HA). JAMAIS le budget
// (input_text.victron_evcs_night_budget, input_number.evcs_balance_night_vehicle_budget_kwh).
// Ne touche JAMAIS victron_evcs_vehicle_level_ref_kwh ni victron_evcs_vehicle_level_at : une automatisation HA // Ne touche JAMAIS victron_evcs_vehicle_level_ref_kwh ni victron_evcs_vehicle_level_at : une automatisation HA
// les mémorise seule à chaque appel (une saisie identique compte aussi). // les mémorise seule à chaque appel (une saisie identique compte aussi).
'use strict'; 'use strict';
@@ -16,10 +19,11 @@ const token = () => fs.readFileSync(process.env.HA_TOKEN_FILE || path.join(__dir
const SEL = 'input_select.victron_evcs_vehicle'; // « Véhicule branché » (désigné par EVCS) const SEL = 'input_select.victron_evcs_vehicle'; // « Véhicule branché » (désigné par EVCS)
const NIV = 'input_number.victron_evcs_vehicle_level_pct'; // niveau saisi, % const NIV = 'input_number.victron_evcs_vehicle_level_pct'; // niveau saisi, %
const DEP = 'input_datetime.victron_evcs_departure_ponctuel'; // départ ponctuel du jour (00:00 = aucun) const DEP = 'input_datetime.victron_evcs_departure_ponctuel'; // départ ponctuel du jour (00:00 = aucun)
const MODE = 'input_select.victron_evcs_night_charge_mode'; // sans_edf | complete
const args = process.argv.slice(2); const args = process.argv.slice(2);
const opt = (n) => { const i = args.indexOf(n); return i >= 0 ? args[i + 1] : undefined; }; const opt = (n) => { const i = args.indexOf(n); return i >= 0 ? args[i + 1] : undefined; };
const vehicule = opt('--vehicule'); const niveauArg = opt('--niveau'); const departArg = opt('--depart'); const vehicule = opt('--vehicule'); const niveauArg = opt('--niveau'); const departArg = opt('--depart'); const modeArg = opt('--mode-nuit');
async function ha(method, url, body) { async function ha(method, url, body) {
const ac = new AbortController(); const t = setTimeout(() => ac.abort(), 10000); const ac = new AbortController(); const t = setTimeout(() => ac.abort(), 10000);
@@ -34,6 +38,19 @@ async function ha(method, url, body) {
const etat = async (e) => ha('GET', `/api/states/${e}`); const etat = async (e) => ha('GET', `/api/states/${e}`);
(async () => { (async () => {
if (modeArg !== undefined) {
const m = await etat(MODE); const opts = m.attributes.options || [];
const o = opts.find((x) => x.toLowerCase() === String(modeArg).toLowerCase());
if (!o) { console.log(`refus : mode « ${modeArg} » inconnu de HA, options : ${opts.join(', ')}`); process.exit(2); }
await ha('POST', '/api/services/input_select/select_option', { entity_id: MODE, option: o });
await new Promise((r) => setTimeout(r, 800));
const lu = (await etat(MODE)).state;
if (lu !== o) { console.log(`erreur : écrit ${o} mais HA relit ${lu}`); process.exit(1); }
console.log(lu === 'complete'
? "C'est noté : charge complète cette nuit (batterie d'abord, puis EDF en heures creuses pour le reste). Retour à « sans EDF » demain à midi."
: "C'est noté : charge sans EDF cette nuit (la voiture s'arrête au budget batterie et attend le soleil).");
return;
}
const sel = await etat(SEL); const niv = await etat(NIV); const sel = await etat(SEL); const niv = await etat(NIV);
const options = sel.attributes.options || []; const options = sel.attributes.options || [];
const aujourdhui = new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().slice(0, 10); const aujourdhui = new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().slice(0, 10);

View File

@@ -75,3 +75,14 @@ Total déplacés : 3
| A3.01 | NVIDIA / Victron → Veille | 2 | Veille | 0 | | A3.01 | NVIDIA / Victron → Veille | 2 | Veille | 0 |
Total déplacés : 4 Total déplacés : 4
## 2026-09-30 19:50:00 — airtria-menage --quotidien
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|---|---|---:|---|---:|
| A1.12 | Audible promos | 1 | Trash | 0 |
| A1.17 | Vertical-Mail | 2 | Trash | 0 |
| A1.28 | Amazon Business (désabo) | 1 | Trash | 0 |
| A3.01 | NVIDIA / Victron → Veille | 1 | Veille | 0 |
Total déplacés : 5

View File

@@ -173,7 +173,7 @@ async function answer(text) {
if (Array.isArray(sel.attributes?.options)) options = sel.attributes.options; if (Array.isArray(sel.attributes?.options)) options = sel.attributes.options;
} catch { /* défaut VW/JEEP */ } } catch { /* défaut VW/JEEP */ }
const label = parseLabel(text, options); const label = parseLabel(text, options);
if (!label) return "Rien n'est noté : ce message ne nomme pas de véhicule."; // non reconnu : on ne publie rien if (!label) return "(aucune action concierge : pas de véhicule nommé — ne relaie pas cette ligne, réponds à la question)"; // non reconnu : on ne publie rien
// Cible de l'étiquette = le branchement à confirmer : // Cible de l'étiquette = le branchement à confirmer :
// - avec question en attente : celui du pending. // - avec question en attente : celui du pending.

View File

@@ -102,3 +102,15 @@ Total déplacés : 5
| O1.22 | Quora (relais Apple) | 2 | INBOX/TRASH | 0 | | O1.22 | Quora (relais Apple) | 2 | INBOX/TRASH | 0 |
Total déplacés : 5 Total déplacés : 5
## 2026-09-30 19:45:00 — orange-menage --quotidien
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|---|---|---:|---|---:|
| O1.01 | Fnac (en entier) | 2 | INBOX/TRASH | 0 |
| O1.05 | Edenred Meyclub/Kadéos | 1 | INBOX/TRASH | 0 |
| O1.09 | Netflix | 1 | INBOX/TRASH | 0 |
| O1.13 | IKEA | 1 | INBOX/TRASH | 0 |
| O1.22 | Quora (relais Apple) | 1 | INBOX/TRASH | 0 |
Total déplacés : 6