This commit is contained in:
Mateusz Gruszczyński committed 2026-10-17 20:00:28 +02:00
1 parent ccf85a2fb8
commit f376f0a7b6
32 files changed
+312 -114

No files matched your search

+13 -6
View File
@@ -405,15 +405,20 @@ function buildZoneSimulation(zone, planZone) {
status = demand ? 'demand' : 'satisfied';
}
const standbyOffset = Math.max(simulationNumeric(zone?.standby_offset_c) || 0.5, 0.5);
const assist = current == null || target == null ? 0 : simulationOutdoorAssist(mode, outdoor, current, target);
const anticipation = Math.max(simulationNumeric(zone?.heat_anticipation_c) || 0, 0);
const coastEnter = target == null ? null : target - anticipation;
const heatCoasting = mode === 'heat' && anticipation > 0 && current != null && coastEnter != null
&& (zone?.heat_coasting ? current > coastEnter - 0.4 + 1e-6 : current + 1e-6 >= coastEnter);
const deliveringHeat = demand && !heatCoasting;
const assist = current == null || target == null || zone?.control_source === 'automation.flow' ? 0 : simulationOutdoorAssist(mode, outdoor, current, target);
const activeTarget = current == null || target == null ? null : (mode === 'heat' ? target + assist : target - assist);
const standbyTarget = target == null ? null : (mode === 'heat' ? target - standbyOffset : target + standbyOffset);
const desiredDeviceTarget = current == null || target == null ? null : simulationRoundDeviceSetpoint(mode, demand, demand ? activeTarget : standbyTarget);
const desiredDeviceTarget = current == null || target == null ? null : simulationRoundDeviceSetpoint(mode, deliveringHeat, deliveringHeat ? activeTarget : standbyTarget);
const nightActive = !!app.controlPlan?.night_mode_active;
const nightMaxFan = clamp(Number(app.controlPlan?.night_mode_max_fan_speed || 1), 1, 5);
let fanSpeed = simulationNumeric(device?.fan_speed);
if (mode !== 'off') {
fanSpeed = zone?.smart_fan && current != null && target != null ? simulationSmartFanSpeed(mode, current, target, outdoor, demand) : fanSpeed;
fanSpeed = zone?.smart_fan && current != null && target != null ? simulationSmartFanSpeed(mode, current, target, outdoor, deliveringHeat) : fanSpeed;
if (nightActive) {
if (zone?.smart_fan) fanSpeed = fanSpeed === 0 ? 1 : Math.min(fanSpeed ?? nightMaxFan, nightMaxFan);
else if (fanSpeed === 0 || fanSpeed == null || fanSpeed > nightMaxFan) fanSpeed = nightMaxFan;
@@ -423,7 +428,7 @@ function buildZoneSimulation(zone, planZone) {
? tr('simulation.manual')
: nightActive && app.settings?.night_mode?.force_quiet
? tr('simulation.quietIfSupported')
: (zone?.smart_fan ? (!demand ? tr('simulation.quietIfSupported') : tr('common.off')) : tr('simulation.manual'));
: (zone?.smart_fan ? (!deliveringHeat ? tr('simulation.quietIfSupported') : tr('common.off')) : tr('simulation.manual'));
const nativeSleep = mode !== 'off' && nightActive && app.settings?.night_mode?.use_native_sleep && device?.supports_sleep === true;
const reasoning = !zone?.enabled || planZoneEffectiveEnabled(planZone) === false
? tr('simulation.reasonDisabled')
@@ -431,10 +436,12 @@ function buildZoneSimulation(zone, planZone) {
? tr('simulation.reasonHouseOff')
: current == null || target == null
? tr('simulation.reasonWaiting')
: demand
: heatCoasting
? tr('simulation.reasonCoasting', { target: target.toFixed(1), standby: standbyTarget.toFixed(1) })
: demand
? tr('simulation.reasonDemand', { mode: modeLabel(mode), target: target.toFixed(1), hysteresis: hysteresis.toFixed(1) })
: tr('simulation.reasonSatisfied', { target: target.toFixed(1), standby: standbyTarget.toFixed(1) });
return { device, mode, current, target, demand, status, outdoor, hysteresis, assist, activeTarget, standbyTarget, desiredDeviceTarget, fanSpeed, quiet, nativeSleep, reasoning };
return { device, mode, current, target, demand, heatCoasting, status, outdoor, hysteresis, assist, activeTarget, standbyTarget, desiredDeviceTarget, fanSpeed, quiet, nativeSleep, reasoning };
}
function simulationRuleAction(rule) {