correction logique commande priorisation
This commit is contained in:
364
DECISION/decision_engineP3.js
Normal file
364
DECISION/decision_engineP3.js
Normal file
@@ -0,0 +1,364 @@
|
||||
// =================================================
|
||||
// VEHICLE FULL / PAUSED - NUMERIC FILTER DECISION
|
||||
// IMPORTANT:
|
||||
// - uniquement en session active
|
||||
// - uniquement si la source est réellement livrable
|
||||
// - sans utiliser le PV comme critère
|
||||
// =================================================
|
||||
if (
|
||||
vehicleDemandFilter.evcsVehicleNoDemandSemantic &&
|
||||
vehicleDemandFilter.sourceDeliverableForNoDemand
|
||||
) {
|
||||
setOff({
|
||||
stateName: 'vehicle_full_or_paused',
|
||||
decisionName: 'stop_vehicle_full_or_paused',
|
||||
reasonText: 'Véhicule branché mais ne demande plus réellement de puissance',
|
||||
dynamic: false,
|
||||
mustStopFlag: false,
|
||||
blockReason: 'none',
|
||||
blockedUntilStamp: now.stamp,
|
||||
});
|
||||
|
||||
reason.push(`DeliveryRatioEma=${vehicleDemandFilter.deliveryRatioEma}`);
|
||||
reason.push(`NoiseEma=${vehicleDemandFilter.deliveryNoiseEma}`);
|
||||
reason.push(`NoDemandScore=${vehicleDemandFilter.noDemandScoreEma}`);
|
||||
reason.push(`ScoreOn=${vehicleDemandFilter.noDemandScoreOn}`);
|
||||
reason.push(`ScoreOff=${vehicleDemandFilter.noDemandScoreOff}`);
|
||||
|
||||
if (vehicleDemandFilter.evcsNoDemandSinceMinutes !== null) {
|
||||
reason.push(`NoDemand depuis ${round1(vehicleDemandFilter.evcsNoDemandSinceMinutes)} min`);
|
||||
}
|
||||
}
|
||||
|
||||
else if (activeSourceMode === 'blocked') {
|
||||
if (lifecycle.minRunElapsed) {
|
||||
setOff({
|
||||
stateName: 'stop_source_lost',
|
||||
decisionName: 'stop',
|
||||
reasonText: 'Source autorisée perdue',
|
||||
dynamic: false,
|
||||
mustStopFlag: true,
|
||||
blockReason: context.profile === 'outside_window' ? 'outside_window' : 'source_unavailable',
|
||||
blockedUntilStamp:
|
||||
context.profile === 'outside_window' && Number.isFinite(locks.nextAllowedWindowStartMs)
|
||||
? formatParisStampFromMs(locks.nextAllowedWindowStartMs)
|
||||
: formatParisStampFromMs(nowMs + params.minStopMinutes * 60000),
|
||||
});
|
||||
} else {
|
||||
setOn({
|
||||
stateName: 'hold_min_run_source_lost',
|
||||
decisionName: 'hold',
|
||||
currentA: Math.min(derived.currentReferenceA, derived.physicalCapA),
|
||||
reasonText: "Source perdue mais maintien jusqu'au mini ON",
|
||||
dynamic: false,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'grid_hc_allowed' || activeSourceMode === 'grid_forced') &&
|
||||
!parsed.gridAvailable
|
||||
) {
|
||||
if (lifecycle.minRunElapsed) {
|
||||
setOff({
|
||||
stateName:
|
||||
context.profile === 'night_hc'
|
||||
? 'night_wait_grid_takeover_runtime'
|
||||
: 'wait_grid_source_runtime',
|
||||
decisionName: 'hold',
|
||||
reasonText:
|
||||
context.profile === 'night_hc'
|
||||
? 'Relais réseau demandé pendant la session nuit EVCS'
|
||||
: 'Source réseau demandée mais pas encore disponible',
|
||||
dynamic: false,
|
||||
mustStopFlag: false,
|
||||
blockReason:
|
||||
context.profile === 'night_hc' ? 'grid_hc_unavailable' : 'grid_unavailable',
|
||||
blockedUntilStamp: formatParisStampFromMs(nowMs + 10 * 60000),
|
||||
});
|
||||
} else {
|
||||
setOn({
|
||||
stateName: 'hold_min_run_wait_grid_takeover',
|
||||
decisionName: 'hold',
|
||||
currentA: Math.min(derived.currentReferenceA, derived.physicalCapA),
|
||||
reasonText: "Maintien jusqu'au mini ON en attente du réseau",
|
||||
dynamic: false,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else if (!holdConditionsOk) {
|
||||
if (lifecycle.minRunElapsed) {
|
||||
setOff({
|
||||
stateName: 'stop_conditions_lost',
|
||||
decisionName: 'stop',
|
||||
reasonText: 'Conditions de maintien perdues',
|
||||
dynamic: false,
|
||||
mustStopFlag: true,
|
||||
blockReason: 'hold_conditions_lost',
|
||||
blockedUntilStamp: formatParisStampFromMs(nowMs + 10 * 60000),
|
||||
});
|
||||
} else {
|
||||
setOn({
|
||||
stateName: 'hold_min_run',
|
||||
decisionName: 'hold',
|
||||
currentA: Math.min(derived.currentReferenceA, derived.physicalCapA),
|
||||
reasonText: "Maintien jusqu'au temps mini ON",
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else if ((derived.currentReferenceA > derived.physicalCapA) && lifecycle.currentCooldownElapsed) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_system_cap',
|
||||
decisionName: 'step_down',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - Math.max(params.currentStepDownA, 2),
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Réduction pour respecter la capacité système',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (conditions.shouldStepDownOverload) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_overload',
|
||||
decisionName: 'step_down_fast',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - Math.max(batteryTune.global.overloadStepDownA, params.currentStepDownA),
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Baisse rapide: surcharge convertisseur',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (conditions.shouldStepDownVebusPower) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_vebus_power',
|
||||
decisionName: 'step_down_fast',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - Math.max(params.currentStepDownA + 1, 3),
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Baisse rapide: puissance VE.Bus élevée',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (conditions.shouldStepDownVebusVoltage) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_dc_voltage',
|
||||
decisionName: 'step_down_fast',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - Math.max(params.currentStepDownA + 1, 3),
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Baisse rapide: tension DC basse',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
activeSourceMode === 'battery_assist_night' &&
|
||||
conditions.batteryAssistNightShouldStepDown
|
||||
) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_battery_assist_night',
|
||||
decisionName: 'step_down',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - params.currentStepDownA,
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText:
|
||||
nightEvcs?.batteryRecoveryUrgent
|
||||
? 'Réduction: approche départ, préparation takeover réseau'
|
||||
: 'Réduction: assistance batterie nuit devient trop coûteuse',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'grid_hc_allowed' || activeSourceMode === 'grid_forced') &&
|
||||
conditions.gridShouldStepDownBattery
|
||||
) {
|
||||
setOn({
|
||||
stateName:
|
||||
activeSourceMode === 'grid_forced'
|
||||
? 'charging_step_down_grid_forced_guard'
|
||||
: 'charging_step_down_grid_guard',
|
||||
decisionName: 'step_down',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - params.currentStepDownA,
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText:
|
||||
activeSourceMode === 'grid_forced'
|
||||
? 'Réduction réseau forcé: la batterie commence à participer'
|
||||
: 'Réduction réseau: la batterie commence à participer',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'solar_only' || activeSourceMode === 'solar_potential') &&
|
||||
conditions.solarShouldStepDownCloudDebt
|
||||
) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_cloud_debt',
|
||||
decisionName: 'step_down',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - Math.max(params.currentStepDownA, 2),
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Réduction: dette nuage trop élevée',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'solar_only' || activeSourceMode === 'solar_potential') &&
|
||||
conditions.solarShouldStepDownBattery
|
||||
) {
|
||||
setOn({
|
||||
stateName: 'charging_step_down_battery',
|
||||
decisionName: 'step_down',
|
||||
currentA: Math.max(
|
||||
params.currentMinA,
|
||||
Math.min(
|
||||
derived.currentReferenceA - params.currentStepDownA,
|
||||
derived.physicalCapA
|
||||
)
|
||||
),
|
||||
reasonText: 'Réduction: batterie trop sollicitée',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'grid_hc_allowed' || activeSourceMode === 'grid_forced') &&
|
||||
conditions.gridShouldStepUp
|
||||
) {
|
||||
setOn({
|
||||
stateName:
|
||||
activeSourceMode === 'grid_forced'
|
||||
? (
|
||||
nightEvcs?.batteryRecoveryUrgent
|
||||
? 'night_departure_deadline_grid_forced'
|
||||
: 'charging_step_up_grid_forced'
|
||||
)
|
||||
: 'charging_step_up_grid_hc',
|
||||
decisionName: 'step_up',
|
||||
currentA: clamp(
|
||||
derived.currentReferenceA + params.currentStepUpA,
|
||||
params.currentMinA,
|
||||
derived.physicalCapA
|
||||
),
|
||||
reasonText:
|
||||
activeSourceMode === 'grid_forced'
|
||||
? (
|
||||
nightEvcs?.batteryRecoveryUrgent
|
||||
? 'Hausse prudente: priorité départ, réseau forcé'
|
||||
: 'Hausse prudente du courant en charge réseau forcée'
|
||||
)
|
||||
: 'Hausse prudente du courant en HC réseau',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
activeSourceMode === 'battery_assist_night' &&
|
||||
conditions.batteryAssistNightShouldStepUp
|
||||
) {
|
||||
setOn({
|
||||
stateName: 'charging_step_up_battery_assist_night',
|
||||
decisionName: 'step_up',
|
||||
currentA: clamp(
|
||||
derived.currentReferenceA + params.currentStepUpA,
|
||||
params.currentMinA,
|
||||
derived.physicalCapA
|
||||
),
|
||||
reasonText: 'Hausse prudente du courant en assistance batterie nuit',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else if (
|
||||
(activeSourceMode === 'solar_only' || activeSourceMode === 'solar_potential') &&
|
||||
conditions.solarShouldStepUp
|
||||
) {
|
||||
setOn({
|
||||
stateName:
|
||||
conditions.probeSuccessNow
|
||||
? 'probe_success_step_up'
|
||||
: (modes.batteryPriorityMode
|
||||
? 'charging_step_up_battery'
|
||||
: 'charging_step_up_forecast'),
|
||||
decisionName: 'step_up',
|
||||
currentA: clamp(
|
||||
derived.currentReferenceA + params.currentStepUpA,
|
||||
params.currentMinA,
|
||||
derived.physicalCapA
|
||||
),
|
||||
reasonText: 'Hausse prudente du courant',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
setOn({
|
||||
stateName:
|
||||
conditions.probeSuccessNow ? 'probe_success_hold' :
|
||||
activeSourceMode === 'battery_assist_night' ? 'charging_hold_battery_assist_night' :
|
||||
(activeSourceMode === 'grid_hc_allowed' || activeSourceMode === 'grid_forced') ? 'charging_hold_grid' :
|
||||
cloud.cloudDebtActive ? 'charging_hold_cloud_tolerance' :
|
||||
'charging_hold',
|
||||
decisionName: 'hold',
|
||||
currentA: Math.min(derived.currentReferenceA, derived.physicalCapA),
|
||||
reasonText:
|
||||
activeSourceMode === 'battery_assist_night'
|
||||
? 'Maintien du courant en assistance batterie nuit'
|
||||
: 'Maintien du courant',
|
||||
dynamic: true,
|
||||
mustStopFlag: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user