- src/nodes/*.js (6 nodes + template snapshot) = source de vérité unique. - n8n-push.mjs reconstruit le JSON depuis src/ avant syntaxe+golden+PUT (src gagne toujours; n8n-extract.mjs pour resynchroniser si édition UI). - n8n-build.mjs --check pour vérifier la synchro. - Copies historiques déplacées dans archive/ (mortes, dérivées de la prod). - .gitignore: backups locaux de rollback. - AGENTS.md: règle R2 pour toutes les futures sessions (dont Qwen local). - Validé: idempotence, mutation/restauration, pipeline push complet en réel.
157 lines
5.8 KiB
JavaScript
157 lines
5.8 KiB
JavaScript
}
|
|
else if (activeSourceMode === 'solar_only' || activeSourceMode === 'solar_potential') { // Potentiel autorise step up aussi
|
|
desiredCharging = true;
|
|
desiredPermission = true;
|
|
desiredLatch = true;
|
|
desiredCurrentA = clamp(currentReferenceA + currentStepUpA, currentMinA, physicalCapA);
|
|
state = probeSuccessNow
|
|
? 'probe_success_step_up'
|
|
: (batteryPriorityMode ? 'charging_step_up_battery' : 'charging_step_up_forecast');
|
|
currentDecision = 'step_up';
|
|
dynamicOk = true;
|
|
reason.push("Hausse prudente du courant");
|
|
}
|
|
else {
|
|
desiredCharging = true;
|
|
desiredPermission = true;
|
|
desiredLatch = true;
|
|
desiredCurrentA = clamp(Math.min(currentReferenceA, physicalCapA), currentMinA, physicalCapA);
|
|
state =
|
|
probeSuccessNow ? 'probe_success_hold' :
|
|
activeSourceMode === 'grid_hc_allowed' ? 'charging_hold_grid_hc' :
|
|
cloudDebtActive ? 'charging_hold_cloud_tolerance' :
|
|
'charging_hold';
|
|
currentDecision = 'hold';
|
|
dynamicOk = true;
|
|
mustStop = false;
|
|
reason.push("Maintien du courant");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
const startConditionsOk =
|
|
(sourceMode === 'grid_hc_allowed' || sourceMode === 'grid_forced') ? gridStartOk : // Ajout de 'grid_forced'
|
|
sourceMode === 'solar_only' || sourceMode === 'solar_potential' ? solarStartOk : // Potentiel autorise démarrage aussi
|
|
sourceMode === 'hybrid_probe' ? probeStartOk :
|
|
false;
|
|
if (profile === 'outside_window') {
|
|
// outside_window n'est plus un mur absolu en mode force ou avec potentiel
|
|
if (sourceMode === 'solar_potential' || isForceMode) {
|
|
// Continue à chercher startConditionsOk...
|
|
} else {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = 'blocked_outside_window';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
nextBlockReason = 'outside_window';
|
|
nextBlockedUntilStamp =
|
|
nextAllowedWindowStartMs !== null
|
|
? formatParisStampFromMs(nextAllowedWindowStartMs)
|
|
: now.stamp;
|
|
reason.push("Hors fenêtre autorisée (pas de potentiel confirmé ni forcé)");
|
|
}
|
|
}
|
|
else if (!canRunAtMinCurrent) {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = 'blocked_by_capacity_min_current';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
nextBlockReason = 'battery_protection_stop';
|
|
nextBlockedUntilStamp = formatParisStampFromMs(nowMs + 10 * 60000);
|
|
reason.push("Capacité insuffisante pour courant mini");
|
|
}
|
|
else if (sourceMode === 'blocked') {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = profile === 'night_hc' ? 'night_no_grid_hc_lock' : 'idle_wait_source';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
nextBlockReason = profile === 'night_hc' ? 'outside_window' : 'source_unavailable';
|
|
nextBlockedUntilStamp =
|
|
profile === 'night_hc' && nextAllowedWindowStartMs !== null
|
|
? formatParisStampFromMs(nextAllowedWindowStartMs)
|
|
: formatParisStampFromMs(nowMs + 15 * 60000);
|
|
reason.push(profile === 'night_hc' ? "Nuit sans autorisation HC réseau" : "Source non autorisée ou insuffisante");
|
|
}
|
|
else if (startBlockedByReason) {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = 'wait_reason_lock';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
nextBlockReason = lastBlockReason;
|
|
nextBlockedUntilStamp = blockedUntilAt || now.stamp;
|
|
reason.push(`Blocage anti-cliquetis: ${lastBlockReason}`);
|
|
}
|
|
else if (!startConditionsOk) {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = 'idle_wait_conditions';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
reason.push("Conditions de démarrage non réunies");
|
|
}
|
|
else if (!minStopElapsed) {
|
|
desiredCharging = false;
|
|
desiredPermission = false;
|
|
desiredLatch = false;
|
|
desiredCurrentA = currentMinA;
|
|
state = 'wait_min_stop';
|
|
currentDecision = 'hold';
|
|
dynamicOk = false;
|
|
mustStop = false;
|
|
reason.push("Temps mini OFF non écoulé");
|
|
}
|
|
else {
|
|
desiredCharging = true;
|
|
desiredPermission = true;
|
|
desiredLatch = true;
|
|
desiredCurrentA = sourceMode === 'hybrid_probe'
|
|
? clamp(probeCurrentA, currentMinA, physicalCapA)
|
|
: currentMinA;
|
|
state =
|
|
sourceMode === 'grid_hc_allowed' ? 'start_grid_hc_min_current' :
|
|
sourceMode === 'hybrid_probe' ? 'probe_start_6a' :
|
|
sourceMode === 'solar_potential' ? 'start_forecast_solar_potential' : // NOUVEAU STATE
|
|
batteryFullHarvestMode ? 'start_min_current_battery_full_harvest' :
|
|
forecastCommitMode ? 'start_min_current_forecast_commit' :
|
|
'start_min_current';
|
|
currentDecision = 'start';
|
|
dynamicOk = true;
|
|
mustStop = false;
|
|
nextBlockReason = 'none'; // Clean blocking logic: set reason to none on start
|
|
nextBlockedUntilStamp = now.stamp;
|
|
setProbeStartedAt = sourceMode === 'hybrid_probe';
|
|
reason.push(
|
|
sourceMode === 'grid_hc_allowed'
|
|
? "Démarrage en fenêtre HC réseau"
|
|
: sourceMode === 'hybrid_probe'
|
|
? "Démarrage en mode sonde"
|
|
: sourceMode === 'solar_potential'
|
|
? "Démarrage par potentiel solaire confirmé (SOC>=85%)" // NOUVEAU REASON TEXT
|
|
: batteryFullHarvestMode
|
|
? "Démarrage harvest solaire"
|
|
: forecastCommitMode
|
|
? "Démarrage forecast commit"
|
|
: "Démarrage prudent à courant mini"
|
|
);
|
|
}
|
|
}
|