šŸŒ”ļø 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

:arrow_right: 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