SDB : seche-serviette et deshumidificateur en consommateurs de surplus solaire (chargeurs brides), arret a 28 °C
This commit is contained in:
@@ -395,6 +395,41 @@ let notifyTitle = 'SDB Climate & Surplus';
|
||||
let notifyMessage = '';
|
||||
let notifyWanted = false;
|
||||
|
||||
// ======================================================
|
||||
// MODE SURPLUS SOLAIRE (10/10/2026, proprietaire)
|
||||
// ======================================================
|
||||
// Les jours de grosse production, le seche-serviette (« radiateur ») ET le
|
||||
// deshumidificateur prennent le solaire que personne ne prend. L'ancien
|
||||
// demarrage exigeait un besoin de chauffage (T < 20 °C) et une batterie en
|
||||
// charge entre 2 et 5 A : dernier demarrage le 05/06 ; le 08/10 la batterie
|
||||
// passait de 162 A (13 h) a 1-2 A (15-17 h, solaire bride) sans jamais tenir
|
||||
// dans la fenetre. Le bon signal est celui des chargeurs eux-memes (HANDOFF §37) :
|
||||
// un chargeur qui se BRIDE prouve un solaire refuse.
|
||||
// Demarrage : >= 1 chargeur bride, SOC >= 90, EDF ouvert, journee, pas de
|
||||
// priorite borne, et pas de voiture branchee qui attend ce surplus (elle passe
|
||||
// d'abord). Maintien : la batterie ne se decharge pas (> -3 A) ou un chargeur
|
||||
// est encore bride, SOC >= 85. Seche-serviette : arret a 28 °C, et pas de
|
||||
// demarrage si la temperature est inconnue.
|
||||
const SURPLUS_SOC_START = 90;
|
||||
const SURPLUS_SOC_HOLD = 85;
|
||||
const SURPLUS_DECHARGE_MAX_A = -3;
|
||||
const SURPLUS_TEMP_MAX_C = 28;
|
||||
const mpptModes = String(input.mppt_operation_modes || '').split(',').map((x) => x.trim().toLowerCase()).filter(Boolean);
|
||||
const mpptLimitedCount = mpptModes.filter((m) => m === 'voltage_current_limited').length;
|
||||
const voitureAttendSurplus =
|
||||
low(input.evcs_vehicle_connected || 'off') === 'on' &&
|
||||
num(input.evcs_ac_power_w, 0) < 100 &&
|
||||
!/full|done|complete|charged/.test(low(input.evcs_surplus_state || ''));
|
||||
const surplusCommun = autoEnabled && inDayWindow && !gridIsOn && !evcsPriorityActive && !voitureAttendSurplus;
|
||||
const surplusStart = surplusCommun && mpptLimitedCount >= 1 && soc >= SURPLUS_SOC_START;
|
||||
const surplusHold = surplusCommun && soc >= SURPLUS_SOC_HOLD &&
|
||||
(mpptLimitedCount >= 1 || (Number.isFinite(batteryCurrentA) && batteryCurrentA > SURPLUS_DECHARGE_MAX_A));
|
||||
const surplusPrecedent = /\|sp=1/.test(lastSignature || '');
|
||||
const radiateurTempOk = Number.isFinite(temperatureC) && temperatureC < SURPLUS_TEMP_MAX_C;
|
||||
const deshumideSurplus = surplusStart || (surplusHold && (deshumideIsOn || deshumideLatchIsOn));
|
||||
const radiateurSurplus = radiatorAutoEnabled && radiateurTempOk &&
|
||||
(surplusStart || (surplusHold && (radiatorIsOn || radiatorLatchIsOn)));
|
||||
|
||||
// Energie disponible pour une charge reportable (calcule apres les entrees).
|
||||
const deshumideEnergyOk =
|
||||
gridIsOn ||
|
||||
@@ -409,6 +444,15 @@ if (!autoEnabled) {
|
||||
desiredDeshumide = deshumideIsOn;
|
||||
dehumActionReason = 'automation_disabled';
|
||||
}
|
||||
else if (deshumideSurplus) {
|
||||
desiredDeshumide = deshumideIsOn || deshumideMinOffElapsed;
|
||||
dehumActionReason = desiredDeshumide ? 'deshumide_surplus_solaire' : 'deshumide_wait_min_off';
|
||||
}
|
||||
else if (surplusPrecedent && !humidityNeed && (deshumideIsOn || deshumideLatchIsOn)) {
|
||||
// Demarre pour le surplus, pas pour l'humidite : il s'arrete avec le surplus.
|
||||
desiredDeshumide = !deshumideMinOnElapsed;
|
||||
dehumActionReason = deshumideMinOnElapsed ? 'deshumide_stop_fin_surplus' : 'deshumide_hold_min_on';
|
||||
}
|
||||
else if (capteurMuet && (deshumideIsOn || deshumideLatchIsOn)) {
|
||||
// Sans mesure, on ne tient plus rien au-dela du temps minimum.
|
||||
desiredDeshumide = !deshumideMinOnElapsed;
|
||||
@@ -485,6 +529,18 @@ else if (evcsPriorityActive) {
|
||||
radiatorActionReason = 'radiator_blocked_by_evcs_priority';
|
||||
}
|
||||
}
|
||||
else if (radiateurSurplus) {
|
||||
desiredRadiator = radiatorIsOn || radiatorMinOffElapsed;
|
||||
radiatorActionReason = desiredRadiator ? 'radiator_surplus_solaire' : 'radiator_wait_min_off';
|
||||
}
|
||||
else if ((radiatorIsOn || radiatorLatchIsOn) && Number.isFinite(temperatureC) && temperatureC >= SURPLUS_TEMP_MAX_C) {
|
||||
desiredRadiator = !radiatorMinOnElapsed;
|
||||
radiatorActionReason = radiatorMinOnElapsed ? 'radiator_stop_temperature_max' : 'radiator_hold_min_on';
|
||||
}
|
||||
else if (surplusPrecedent && !heatNeed && (radiatorIsOn || radiatorLatchIsOn)) {
|
||||
desiredRadiator = !radiatorMinOnElapsed;
|
||||
radiatorActionReason = radiatorMinOnElapsed ? 'radiator_stop_fin_surplus' : 'radiator_hold_min_on';
|
||||
}
|
||||
else if (heatNeed && radiatorStartConditionsOk) {
|
||||
if (radiatorIsOn) {
|
||||
desiredRadiator = true;
|
||||
@@ -592,6 +648,7 @@ reason.push(`Besoin chauffage=${heatNeed ? 'oui' : 'non'} | Rétabli chauffage=$
|
||||
reason.push(`Besoin humidité=${humidityNeed ? 'oui' : 'non'} | Humidité rétablie=${humidityRecovered ? 'oui' : 'non'}`);
|
||||
|
||||
reason.push(`Déshumide: ${dehumActionReason}`);
|
||||
if (deshumideSurplus || radiateurSurplus) reason.push(`☀️ Surplus solaire : ${mpptLimitedCount} chargeur(s) bride(s), SOC ${round1(soc)}% -> ${[deshumideSurplus ? 'deshumidificateur' : '', radiateurSurplus ? 'seche-serviette' : ''].filter(Boolean).join(' + ')}`);
|
||||
if (capteurMuet) reason.push(`⚠️ Capteur SDB muet${Number.isFinite(humidityAgeMin) && humidityAgeMin >= 0 ? ` depuis ${Math.round(humidityAgeMin)} min` : ''} (piles ?)`);
|
||||
if (!deshumideEnergyOk) reason.push(`Batterie reservee : SOC ${round1(soc)}% < ${round1(balanceRequiredPrudent)}% (bilan, prudent), EDF ouvert, pas de surplus`);
|
||||
reason.push(`Radiateur: ${radiatorActionReason}`);
|
||||
@@ -721,6 +778,7 @@ const signature = [
|
||||
`h=${Number.isFinite(humidityPct) ? round1(humidityPct) : 'na'}`,
|
||||
`sx=${Math.round(estimatedSurplusW)}`,
|
||||
`muet=${capteurMuet ? '1' : '0'}`,
|
||||
`sp=${(deshumideSurplus || radiateurSurplus) ? '1' : '0'}`,
|
||||
`nrj=${deshumideEnergyOk ? '1' : '0'}`
|
||||
].join('|');
|
||||
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
"sdb_humidity_age_min": ((as_timestamp(now()) - as_timestamp(states.sensor.sdb_temp_hygro_humidite.last_reported or states.sensor.sdb_temp_hygro_humidite.last_changed)) / 60) | round(0) if states.sensor.sdb_temp_hygro_humidite is not none else -1,
|
||||
"balance_required_soc_prudent": states("input_number.evcs_balance_required_soc_prudent"),
|
||||
"balance_status": states("input_text.evcs_balance_status"),
|
||||
"mppt_operation_modes": states.sensor
|
||||
| selectattr('entity_id','search','mppt')
|
||||
| selectattr('entity_id','search','operation_mode')
|
||||
| map(attribute='state') | join(','),
|
||||
"evcs_vehicle_connected": states("binary_sensor.victron_evcs_vehicle_connected"),
|
||||
"evcs_ac_power_w": states("sensor.victron_evcs_ac_power"),
|
||||
"evcs_surplus_state": states("input_text.victron_evcs_surplus_state"),
|
||||
|
||||
"auto_enabled": states("input_boolean.sdb_climate_surplus_auto_enabled"),
|
||||
"notifications_enabled": states("input_boolean.sdb_climate_surplus_notifications"),
|
||||
|
||||
Reference in New Issue
Block a user