🌡️ EN 16798-1 Smart Setpoint Blueprint

:thermometer: EN 16798-1 Smart Setpoint Blueprint (v5.2.0) — “Fire-and-Forget” Room Setpoints

Stop running static heating schedules. This blueprint computes a dynamic target setpoint for each room using EN 16798-1 comfort categories (I–III), ASR A3.5-inspired minimums, and practical building-physics safety logic (window priority, mold/dewpoint guards, radiant correction).

It enforces your setpoint every 15 minutes and reacts instantly to real-world events like window open, presence, sleep, and manual thermostat changes—without fighting the user.

Highlights

  • :white_check_mark: Room profiles mapped to EN 16798-1 Categories I–III
  • :white_check_mark: Optional Adaptive Comfort band using an external Trm input (best with a smoothed/running-mean sensor)
  • :white_check_mark: Window = absolute priority (OFF / preset / frost fallback)
  • :white_check_mark: Manual override friendly (grace period + optional “hold until …”)
  • :white_check_mark: Optional Smart Learning (learns your preferences and shifts the curve)
  • :white_check_mark: Optional Ramp Limiting (reduces valve movement, saves Zigbee/Thread battery)
  • :white_check_mark: Works with systems where OFF isn’t supported (KNX/Tado-style preset fallback)

:warning: Celsius only (°C). If your thermostat reports °F, the automation stops and logs a critical message.

:inbox_tray: Install / Import

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Source / Version

  • Version: 5.2.0
  • Min Home Assistant: 2024.10.0
  • Author: Tobias Paul

:right_arrow: Full guide & configuration walkthrough in Post 2/2 below.

1 Like

EN 16798-1 Smart Setpoint Blueprint (v5.2.0) — Full Guide & Configuration

This post explains how the blueprint works internally, how to configure it quickly, and how to troubleshoot common issues.

Disclaimer: This blueprint is inspired by EN 16798-1 comfort categories and common building automation safety patterns (window shut-off, demand reduction, minimum limits). It is not a certified implementation and not legal advice.


1) What the Blueprint actually does

Instead of time-based schedules (“8:00 → 21 °C”), the automation computes a single “target_to_send” and applies it to your thermostat:

  • every 15 minutes, and
  • instantly when certain sensors change (window / occupancy / sleep / pre-heat), and
  • when manual setpoint changes happen (grace period + optional hold + learning).

2) Triggers (when it runs)

  • Home Assistant start
  • Every 15 minutes (enforcement interval)
  • Manual setpoint change (immediate + debounced “settled” trigger)
  • Optional instant triggers:
    • window open / close
    • occupancy on / off
    • pre-heat on / off
    • sleep on / off

3) Decision Flow (priority order)

Trigger
  |
  |-- Device available? (not unknown/unavailable) -> otherwise stop
  |-- Unit check: °C required -> otherwise stop + Logbook
  |-- Echo filter: ignore our own write-backs -> otherwise stop
  |
  |-- [1] Window open?
  |      |-- If configured preset exists -> set preset -> STOP
  |      |-- Else if hvac_mode "off" supported -> set OFF -> STOP
  |      |-- Else -> set minimum temp (frost) -> STOP
  |
  |-- [2] Window close trigger?
  |      |-- If we were in the window preset -> reset to a safe preset
  |
  |-- [3] Manual change?
  |      |-- Grace period (immediate) -> STOP
  |      |-- Optional persistent hold -> arm timer
  |      |-- Debounced trigger -> optional learning update
  |
  |-- [4] Core calculation:
  |      profile base -> comfort band (static/adaptive) -> learning offset
  |      -> presence/sleep/eco shifts -> radiant correction
  |      -> frost/mold/dewpoint limits -> clamp + step rounding -> optional ramp
  |
  `-- [5] Apply:
         set hvac mode (if needed)
         enforce preset mode (optional)
         set temperature (only if change >= target step)

4) Quick Start (recommended config)

Required

  • Climate Device (climate_entity)
  • Room Category (room_type)

Strongly recommended

  • Window sensor (window_sensor)
  • Outdoor/Trm sensor (trm_sensor)
  • Humidity sensor (humidity_sensor) to enable mold/dewpoint protection

Nice to have

  • Occupancy (occupancy_sensor)
  • Sleep (sleep_sensor)
  • Pre-Heat / Forced Comfort (pre_heat_sensor)
  • Operative/Globe temperature (operative_temp_sensor)
  • Helpers for Learning (input_number) and Manual Hold (input_datetime)

5) Room Profiles (base setpoints)

These are the base targets before comfort bands, offsets, and safety floors apply:

Room Profile Base Setpoint EN Category
Living Room / Office 21.5 °C II
Children’s Room 22.0 °C II
Bedroom 18.5 °C III
Kitchen 20.5 °C II
Bathroom 22.5 °C I
WC / Restroom Office 21.0 °C II
Hallway / Utility 17.5 °C III
Workshop 17.0 °C III
Storage / Frost Protection 16.0 °C III

6) Comfort Band: Static vs. Adaptive

A) Static comfort band

If adaptive is not applicable, the blueprint uses fixed category bands depending on the season (heating/cooling/transition).

B) Adaptive comfort band (optional)

Adaptive is active only if:

  • Trm is numeric and within 10–30 °C
  • If Trm entity is weather.*, band shifting is disabled by default to avoid jumps
    (enable Allow Adaptive from Weather if you really want it)

Neutral temperature:

  • T_neutral = 0.33 * Trm + 18.8 (rounded to 0.1)

Band width by category:

  • Category I: ±2 K
  • Category II: ±3 K
  • Category III: ±4 K

Tip: For stable behavior, feed a smoothed sensor (true running mean) into trm_sensor.


7) Season logic & Summer lockout

Season derived from Trm:

  • Trm < 10 °C → heating
  • Trm > 15 °C → cooling
  • 10–15 °C → transition
  • If Trm missing → Quick Start behavior based on thermostat mode/action

Transition Season Policy

  • Bias Heating / Bias Cooling / Neutral / Auto

Summer Cut-Off (Heating Limit)

  • If Trm exceeds summer_lock_trm (default 19 °C), heating can be shut down (OFF)
  • If the thermostat does not support OFF, the blueprint falls back to the configured minimum temperature

8) Presence / Eco / Sleep behavior

Starting from the comfort target (already clamped into the chosen band):

Absent (Eco)

  • Shift by eco_shift_k (default 2.0 K)
    • heating: lower target
    • cooling: raise target

Sleep

  • Shift by sleep_shift_k (default 2.0 K)
    • heating: always cooler
    • cooling: configurable
      • OFF (default): warmer / less cooling (energy saving)
      • ON: cooler (comfort)

Allow Deep Eco

  • Enabled (default): Eco may drop below strict band limits
  • Disabled: Eco stays within the comfort band

9) Radiant correction (Operative / Globe sensor)

If you provide an operative temperature sensor:

  • rad_offset = clamp(air_temp - operative_temp, -3 … +3)
  • target += rad_offset

This helps compensate for cold/warm surfaces (radiant discomfort).


10) Safety logic (Frost / Mold / Dewpoint)

Frost floor (heating)

  • minimum_limit_temp (default 16 °C)

Mold guard (heating only)

  • If RH > mold_protection_rh (default 65%), minimum becomes 18 °C

Dewpoint guard (cooling only, requires humidity sensor)

The blueprint uses a simple approximation:

  • dp ≈ current_temp - ((100 - RH) / 5)
  • enforces target >= dp + 2 °C

11) Manual Override (don’t fight the user)

Grace period (always)

Manual setpoint changes immediately stop enforcement. Periodic enforcement also respects recent user interaction.

Persistent “Hold until …” (optional)

If Override Behavior = Keep until...:

  • Provide an input_datetime helper (must have date & time)
  • Any manual change arms the hold for manual_hold_minutes (default 75 minutes)
  • While active, the automation will not overwrite setpoints (except window-close wake logic)

Detection sensitivity

  • Strict: dashboard/app changes only (requires user_id context)
  • Lenient (default): best-effort detection of physical/hardware changes

12) Smart Learning (optional)

If enabled and a learning helper is set:

  • On the debounced “settled” manual change trigger, the blueprint adjusts a learned offset
  • Step size: learn_step_k (default 0.5 K)
  • Maximum learned offset: learn_max_k (default 1.0 K)
  • Additional safety: learning is always clamped to the current comfort band

Best practice: Put the helper on your dashboard so you can reset it to 0.0 anytime.


13) Ramp Limiting (optional)

If enabled, setpoint changes happen gradually:

  • Heating ramp speed: ramp_up_kph (°C/h)
  • Cooling ramp speed: ramp_down_kph (°C/h)

This reduces valve movement and can improve battery life, but the system will feel “slower” to react.


14) Recommended Helpers (how to create)

A) Learning Offset Helper (input_number)

  • Settings → Devices & Services → Helpers → Number
  • Example:
    • Name: Heating Learn Offset
    • Min: -3
    • Max: +3
    • Step: 0.1

B) Manual Hold Helper (input_datetime)

  • Helpers → Date and/or Time
  • Enable Date & Time (not date-only)

15) Suggested minimal dashboard

Entities card:

  • Thermostat (climate)
  • Window sensor
  • Occupancy / Sleep
  • Humidity
  • Trm sensor
  • Learn Offset (input_number)
  • Manual Hold until (input_datetime)

Buttons (optional):

  • Reset Learn Offset → set helper to 0
  • Force Comfort (Pre-Heat) toggle

16) Troubleshooting

“It keeps overwriting my manual setpoint.”

  • Enable Keep until… and provide the input_datetime helper
  • Use Lenient detection if you adjust the thermostat physically

“Adaptive comfort jumps around.”

  • Don’t use weather.* for band shifting unless you really want it
  • Feed a smoothed / averaged sensor as Trm

“Thermostat won’t turn OFF.”

  • Some devices don’t support hvac_mode: off → use window_open_preset or rely on min temp fallback

“Too many tiny setpoint changes.”

  • Enable Ramp Limiting
  • Check your thermostat’s target_temp_step

Hi @Ecronika I’ve just set this up in my living room for testing. It’s working well so far. I wondered if you had any recommended weather integration that provides a smoothed temperature weather sensor? And if not then what sort of smoothing profile you’d recommend?

Hi @spencerwebb189,

for myself, I use a currently not published Blueprint that gives me an MQTT Device with several sensors. One of them approximates the running mean outdoor temperature (TRM) using an EWMA logic, which effectively behaves like an average over the last few days.

It takes your source sensor (e.g.sensor.pirateweather_temperature), calculates the daily mean, and then updates the smoothed value once a day. The default alpha is 0.8, which corresponds mathematically to a time constant of about 4-5 days, making it perfect for adaptive comfort calculations (like EN 16798-1 or ASHRAE 55).

I’ll consider making it available, but it needs some tidying up first. In any case, the source at my home is PirateWeather, and at the office it’s a KNX weather station with a temperature sensor, and I’m calculating a long-term average from these.

1 Like

Thanks for the update @Ecronika

I’m currently running a blueprint that takes values from your MRT blueprint and updates my room thermostats dynamically based on the current setpoint and calculated OT etc…

I’m very interested in moving over to a full automated version of this based on this blueprint. One thing I’m finding is that the default temperature of 21.5c for my living room is very warm. I usually get it around 19.5/20c when it’s cold outside. The air temperature is taken from both my rad trvs as well as a couple of sensors in the room and they all seem to marry up within reason but it’s possible that they are all incorrectly measuring the room temperature.

I just wondered if those setpoints were temperatures you were using in your house, and wonder if there was any milage in making these adjustable in the blueprint?

@Ecronika Another query on this one if you have time, I’ve been running it against a virtual thermostat to see how it behaves compared to my OT compensated automation. This morning the thermostat temperature suddenly increased by 1.5c without anything obviously changing, i.e no occupancy or sleep sensor changes…any ideas why this would happen? The jump at 10am was due to occupancy changes.

Hi @spencerwebb189,

Thanks for the feedback! You are spot on with your observations.

1. Where do the temperatures come from? The 21.5°C default strictly follows the EN 16798-1 standard (Category II) which defines the optimal operative temperature for living spaces. That is why strictly standard-compliant values are used as the fixed anchor points.

2. Can this be made adjustable? Yes, and you don’t even need a code change for it! The blueprint supports exactly this use case via the Smart Learning section.

Since you already know your target deviation (approx. 2°C cooler), you can simply “inject” this offset:

  1. Create an input_number helper in Home Assistant (e.g., input_number.living_room_offset).
  • Min: -5, Max: 5, Step: 0.5, Unit: °C
  1. In the Blueprint, enable Smart Learning and select this helper.
  2. The Shortcut: Instead of “training” the system by changing the thermostat multiple times (which learns in small 0.5°C increments), simply go to your dashboard and set the input_number helper directly to -1.5 or -2.0.

The blueprint permanently adds this helper’s value to the standard EN calculation.

21.5°C (Standard) + (-2.0°C Helper) = 19.5°C Target

This effectively gives you the adjustment slider you were looking for, while keeping the automation logic intact.

1 Like

Hi @spencerwebb189,

Without seeing your specific configuration or the history of your other sensors, this is a bit of a guessing game, but I have a very strong theory based on the exact numbers in your graph.

The “Mold Protection” Scenario The start of your graph shows a flat line at exactly 18.0°C. In the blueprint, there is very specific logic that forces a safety floor of 18.0°C if the Indoor Humidity exceeds the limit (default 65%).

Here is a possible timeline:

  1. Before 09:00: Your room was likely in “Sleep” or “Deep Eco” mode, calculating a target that would normally be lower than 18°C (e.g. 17.5°C). However, the Mold Protection kicked in (High Humidity?) and clamped the specific setpoint to 18.0°C. This explains the flat start.
  2. At 09:00: The “Sleep” mode ended (or humidity dropped). The system shifted to standard “Eco / Absent” mode, which targets 19.5°C (21.5°C Base - 2.0°C Shift). Since 19.5°C is higher than the 18.0°C safety floor, the clamp was released, and you see the jump.
  3. At 10:00: Occupancy detected → Shift to Comfort (21.5°C).

To verify this: Could you please share your Blueprint Configuration (YAML) and, if possible, checking the history (Recorder) of you Humidity Sensor and Sleep Sensor inputs around 09:00? That would confirm if the “18°C Safety Clamp” was indeed the invisible actor here.

Here’s the humidity for that room at this time.

And here are the blueprint settings

Thanks

Thanks for the screenshots!

Mold Protection is innocent: Your humidity is perfectly safe (~50-55%), far below the 65% trigger. The Blueprint did not force the 18°C safety floor.

The Real Culprit: A “Ghost” Schedule :ghost: Mathematically, the Blueprint calculates a minimum target of ~20.0°C (Category II) or ~19.5°C (Eco with Shift). It would never autonomously set 18.0°C in this scenario. However, 18.0°C is a classic default value for a native device schedule (Night Setback) on many smart thermostats.

What likely happened:

  1. Your thermostat hardware (or its manufacturer app/cloud like Tado, Fritz, Shelly) likely has an internal schedule active that set the target to 18.0°C overnight.
  2. The Blueprint detected this external change.
  3. Because the change came from the device, the Blueprint interpreted it as a “Manual Override” by you (thinking you turned the knob).
  4. To respect your “wish”, the Blueprint activated the Grace Period / Manual Hold and effectively locked itself out. This explains why the temperature flatlined at 18.0°C until 9:00 AM.

How to verify & fix it:

  1. Check Hardware: Please check your thermostat’s native app/settings and ensure that ALL native schedules are disabled. Set the device to “Manual Mode” or “Permanent Hold”.

  2. Provide Config (YAML): to be absolutely sure, please share your automation config.

  • Go to your Automation in Home Assistant.
  • Click the three dots (top right) → Edit in YAML.
  • Copy the code and paste it here inside a code block (yaml ... ).
  1. Provide Sensor Data (CSV): To analyze exactly who triggered what, a CSV export of the history is best.
  • Go to the History panel.
  • Select all involved entities from the Condig YAML like:
    • climate.YOUR_THERMOSTAT
    • sensor.YOUR_OUTDOOR_TEMP
    • binary_sensor.YOUR_OCCUPANCY
  • Select the timeframe where the drop happened (e.g. 8:00 AM - 10:00 AM).
  • Download the data as CSV (three dots (top right) → Download and Paste it to a Preformatted Text Field.

I was already working on the blueprint to create a new input for Optimal Stop with slightly modified behavior compared to Sleep, which I had previously misused for that purpose.

While I was at it, I also tweaked the timings for various triggers before release and changed the default Detection Sensitivity setting in Manual Override from Lenient to Strict.

This should at least resolve a few odd setpoints I’ve been experiencing. However, since I still can’t explain your 18°C ​​issue, I’m almost certain it won’t fix your jump. Nevertheless, version 5.3.0 is now live.

Changelog

Version: 5.3.0
New Feature: Added “Optimal Stop (Eco-lite)” mode.

  • New inputs: optimal_stop_sensor and optimal_stop_shift_k.
  • Allows “Coasting”: Slightly reduces the setpoint (e.g. -1°C) while you are still present but about to leave/sleep.
  • Yields to deep Sleep and Eco modes.
  • Safety: Default manual_detection_mode changed to Strict to prevent accidental self-locking loops.

Version: 5.2.1
Fix: The default “Grace Period” no longer incorrectly blocks the automation when using the “Keep until…” (Timer) mode.

2 Likes

:hammer_and_wrench: v5.3.1 Bugfix Release — Summer Cut-Off now actually works for heating-only devices

A small but important patch release. If you run this blueprint on heating-only thermostats (TRVs, radiator valves), you should update — and read the recommendation below.

What was broken :bug:

Bug 1 — The Summer Cut-Off was unreachable for heating-only devices.
Once the season detection switched to cooling (warm running-mean outdoor temperature), the mode logic selected cool. For devices that only support [heat, off], this command was silently dropped by the unsupported-mode guard — so the device stayed in heat and kept receiving the (rising!) adaptive cooling-season setpoints. The off branch of the Summer Cut-Off sat behind the cooling branch and could never be reached. Net effect: a TRV could happily heat your bedroom towards the adaptive comfort band in June. :sun::fire:

Bug 2 — The Cut-Off disabled cooling-capable devices entirely.
When the lock engaged, heat_cool devices were switched to off — blocking cooling, although the input is documented as a Heating Limit. Now cooling-capable devices switch to cool instead: heating locked, cooling available.

Both fixes are confined to the target_hvac_mode logic — no changes to the comfort bands, season detection, offsets or any other behavior.

:gear: Input change: Summer Cut-Off range & default

Along with the fixes, the Summer Cut-Off (Heating Limit) input was aligned with the relevant standards:

  • Range is now 10.0–25.0 °C (was 15.0–25.0). The old minimum excluded values that the standards actually prescribe (SIA/ÖNORM heating degree days use 12 °C, DIN V 18599 assumes 12–15 °C, VDI 3807 uses 15 °C, passive houses go down to ~10 °C). The new lower bound of 10.0 °C is the domain boundary of the EN 16798-1 adaptive model itself — setting exactly 10.0 means "heat only within the static heating regime of the norm."
  • Default corrected from 19.0 → 17.0 °C. 17 °C is the common default of weather-compensated heating controllers and a sensible corrected mean for most applications — adjust per room as needed (see table below).

:warning: Heads-up: If you never set this input explicitly, your automations used the old default of 19.0 and will now lock heating from a running mean of 17.0 °C instead. For most heating-only setups this is the better behavior; if you relied on 19.0, set it explicitly.

How to update :up_arrow:

Settings → Automations & Scenes → Blueprints → three-dot menu on EN 16798-1 Smart SetpointRe-import blueprint. Your automations and inputs stay untouched; the fix is active on the next evaluation cycle (≤ 15 min).

:pushpin: Recommendation for heating-only setups: tune the Summer Cut-Off per room

The adaptive band follows 0.33 × TRM + 18.8. For heating-only devices this means: above a certain running-mean outdoor temperature (TRM), the lower band edge climbs above your room profile's base temperature and the room gets heated beyond its profile value — physically pointless in the transition season. The Summer Cut-Off is the designed lever against this.

The crossing point per profile is TRM* = (base + category deviation − 18.8) / 0.33. My suggestion: set the per-room Summer Cut-Off (Heating Limit) close to that value, plus a little margin depending on your building's insulation:

Room profile Base Cat. (dev.) Band floor exceeds base at TRM Suggested Cut-Off
Workshop 17.0 °C III (±4 K) 6.7 °C 10.0
Hallway / Utility 17.5 °C III (±4 K) 8.2 °C 10.0–11.0
Bedroom 18.5 °C III (±4 K) 11.2 °C 13.0
Kitchen 20.5 °C II (±3 K) 14.2 °C 15.5–16.0
WC / Restroom Office 21.0 °C II (±3 K) 15.8 °C 16.0–17.0
Living Room / Office 21.5 °C II (±3 K) 17.3 °C 17.0–19.0
Bathroom 22.5 °C I (±2 K) 17.3 °C 17.0–19.0
Children's Room 22.0 °C II (±3 K) 18.8 °C 19.0

Rule of thumb: low-temperature rooms (workshop, hallway, bedroom) benefit the most — with a global default they sit in a wide "paradox window" where the band floor heats them well above their profile. Rooms with high base temperatures are fine at or slightly above the default.

Two honest footnotes:

  1. Below TRM 10 °C the adaptive model does not apply (EN 16798-1); the blueprint then uses the static heating-season comfort bands. Their Cat. III floor is 19.0 °C — so low-temperature profiles are heated towards the static band floor whenever they heat at all. The cut-off controls when they stop heating, not how low they target.
  2. With aggressive cut-off values, off is commanded more often. For devices supporting off, frost protection is then handled by the device itself — make sure your TRVs have it enabled.

If you have cooling-capable devices, you can leave the Cut-Off alone — rising setpoints in summer are exactly what you want there (no overcooling), and since v5.3.1 the lock no longer takes cooling away from you.

Found and verified on a live system (heat-only TRV, season=cooling, TRM 17.7 °C, device heating towards the band floor — fixed and confirmed off after patching). As always: feedback welcome! :thermometer:

Hello, I'm testing this blueprint on my heat pump and seems to be working just fine, except from I sett it to heating only mode and when the outdoor temp was above 17 degrees it went to cooling mode, is this a bug?
i sett the summer cut-of to max for now

This may seem strange but where i live at 70 degrees north cooling is not so important

Thanks

:new_button: Updates v5.3.2 & v5.3.3 — Heating-only fixes + configurable window delays

Two follow-up releases since the v5.3.1 Summer Cut-Off fix. If you run heating-only devices (TRVs, radiator valves, or a heat pump in heating mode), you'll want both — plus there's a small comfort feature for everyone. :thermometer:


:wrench: v5.3.3

:sparkles: New: configurable Window Open & Close Delay

The window reaction time used to be hardcoded at 2 s. You can now set two separate values in the Window Control section:

  • Window Open Delay — seconds the window must stay open before heating reacts.
  • Window Close Delay — seconds it must stay closed before heating resumes.

The point: quickly stepping onto the balcony — open the door, put something outside, close it again — no longer makes the valve run a full close → open cycle. Set e.g. 20 s open / 5 s close and brief openings are simply ignored.

:white_check_mark: Default is 2 s for both → no behavior change if you leave them alone.

:bug: Fix: "Heating only" could still command cooling — thanks @kandyskull! :folded_hands:

@kandyskull reported that on a heat pump set to "Heating only", the thermostat switched to cool once the outdoor running mean rose above ~15 °C. Verified and confirmed.

Root cause: the cooling decision only looked at the device's supported modes (cool / heat_cool) and ignored the HVAC System Type input. So a cooling-capable device was sent to cool in the cooling season (and on summer lockout) — even when you had explicitly selected Heating only.

Now system_type: heating is respected everywhere: such a device is never commanded to cool — it heats below the Summer Cut-Off and switches off above it.

:warning: Note on the workaround: setting the Summer Cut-Off to max only disabled the lockout branch — the cooling-season branch still commanded cool above ~15 °C. So "cut-off to max" did not fully solve it; v5.3.3 does.


:wrench: v5.3.2

:bug: Fix: eco/sleep set-back was applied upwards on heating-only devices in cooling season

The absence (eco) and sleep offsets were added upwards (+2 K) on heating-only devices during the cooling season — so empty or sleeping rooms were actively heated instead of set back. Offsets on non-cooling devices now only ever reduce the heating target.

If you ever noticed rooms warming up while you were away or asleep in the transition season — that was this. :sun::fire:


:up_arrow: How to update

Settings → Automations & Scenes → Blueprints → ⋮ menu on EN 16798-1 Smart SetpointRe-import blueprint. Your automations and inputs stay untouched; the new window-delay inputs default to 2 s, and the fixes take effect on the next evaluation cycle (≤ 15 min).

As always — feedback welcome! :thermometer:

:hammer_and_wrench: Release v5.3.4 — Maintenance patch: off means off, cooling stays sane, ramp un-freezes

TL;DR: Pure bugfix release. Five fixes, no new inputs, no changed defaults, no breaking changes — your automations and settings stay untouched. Recommended for everyone, especially KNX and Tado users.

What's fixed

1. No more setpoint writes to devices that are (or should be) off.
During summer lockout the blueprint kept sending climate.set_temperature to the switched-off device — every 15 minutes, forever, if the device drops writes while off. Worse: integrations that treat a temperature command as "turn on" (Tado overlays!) could silently undo the lockout. If the target mode is off and the device supports off, nothing is sent anymore.

2. Window-open logic no longer punishes devices that are already off.
If the window opened while the device was already off (e.g. lockout + tilted window at night), the run fell into the "'Off' not supported" fallback and forced the frost-protection setpoint — with a misleading log entry. Already-off devices are now a clean no-op; the frost fallback only fires for devices that truly have no off mode.

3. Summer lockout no longer turns ACs into freezers.
Cooling-capable devices without an off mode (common on KNX climate actuators) received the frost-protection value as their cooling setpoint during lockout — cool @ 16 °C in June. They now keep their normal cooling-band target.

4. "Cooling only" can no longer command heat.
If you declared the system as Cooling only but the device has no cooling mode (misconfiguration), the mode chain fell through to heat. It now resolves to off (or keeps the current mode if off is unsupported) — the mirror image of the v5.3.3 fix.

5. Ramp Limiting no longer freezes the setpoint.
If your device's target_temp_step was larger than the allowed increment per 15-min cycle (e.g. step 1.0 at the default 2.0 °C/h, or step 0.5 below 2.0 °C/h), the ramp computed zero steps and the setpoint never moved again. The ramp now always advances at least one device step per cycle. Note: this implies an effective minimum rate of one step per 15 minutes on coarse-stepped devices.

Plus housekeeping: dead code removed, internals tidied up, and two honest documentation notes added — ① a weather.* entity as TRM source is compared by its instantaneous temperature (no running mean!), so feed a smoothed EMA/24h-mean sensor if you don't want the lockout to flap with the daily cycle; ② a warning that Lenient detection can permanently trigger the Grace Period on integrations that write fresh state contexts (KNX). Both behaviors are unchanged in this patch — proper fixes are on the v5.4 list.

Update

Settings → Automations & Scenes → Blueprints → ⋮ on the blueprint → Re-import blueprint.
Your automations and inputs stay untouched; the fixes are active on the next evaluation cycle (≤ 15 min).

Outlook: v5.4

The next minor will contain the behavior-changing improvements and gets its own announcement: a rebuilt manual-override/grace mechanism (this is also the most likely explanation for the mysterious 18 °C → +1.5 °C jump discussed earlier in this thread), room-type-specific heating-season bands per EN 16798-1 (the current lower bounds are the office table — living spaces, hallways and workshops get their correct, lower limits), adaptive comfort restricted to non-heating operation per CEN/TR 16798-2, corrected adaptive offsets, and a few smaller consistency items around the override options.

As always: feedback and edge cases welcome. :thermometer: