Skip to content

HomeKit Local Control & Smart Valve Control

Choose a tag to compare

@hiall-fyi hiall-fyi released this 23 May 09:21

The first stable 4.0 release. Sixteen betas of work landing as one tag, focused on three things: real-time control via the Tado Internet Bridge, automatic compensation for inaccurate TRV readings, and a quieter integration that uses fewer API calls. Existing v3.5.3 installs upgrade in place — data, schedules, and HomeKit pairings migrate automatically.

⚠️ Upgrade Notes

  • Requires Home Assistant 2025.11+ — needed for the smarter rate limit handling and storage APIs.
  • Upgrading from v3.5.3 — automatic. Zone states, weather, schedules, and per-zone settings migrate from JSON files to HA Store on first startup; old files are renamed to .json.migrated as backups so you can roll back.
  • Upgrading from any v4.0.0 beta — also automatic, no extra steps. Settings carry over as-is.
  • Coming from v2.x? Upgrade to v3.3.1 first, then v3.5.3, then v4.0.0. Going straight from v2.x to v4.0.0 will fail to load — v3.3.1 was the last version with v2.x migration support.
  • Two entity-platform changes (auto-migration runs, but automations need updating):
    • sensor.tado_ce_*_connectionbinary_sensor.tado_ce_*_connection
    • sensor.tado_ce_*_powerbinary_sensor.tado_ce_*_power

Features

  • HomeKit Local Control for Tado Internet Bridge — Pair your Tado bridge via HomeKit and temperature / mode changes go through your local network instead of Tado's cloud, with sensor pushes arriving within ~2 seconds (cloud-only mode is bound by your polling interval, typically 5–30 minutes). The integration tracks how many API calls HomeKit saves you per day. If HomeKit becomes unavailable, the integration automatically falls back to the cloud and tries to recover in the background. Set up under Settings → Tado CE → Configure → General Settings → enable HomeKit.

  • Smart Valve Control — two modes for compensating inaccurate TRV readings (Discussion #231 - @Si-Hill, @wrowlands3, #221 - @simonotter) — TRV built-in sensors sit on the radiator and read warmer than the room, so Tado closes the valve before the room reaches target. With an external temperature sensor configured for a zone, you can now choose how to compensate:

    • Offset Sync (recommended) — Writes a device temperature offset so the Tado app and Tado's own modulation see your external sensor's reading.
    • Valve Target (advanced) — Directly overrides the TRV setpoint. Use only when Offset Sync isn't enough.

    Mutually exclusive per zone. Configure under Settings → Tado CE → Configure → Zone Configuration → External Sensors → Smart Valve Control Mode. Adjustments go via HomeKit when available (no API cost), with cloud as fallback. The controller backs off on manual changes and resumes on the next schedule block.

  • tado_ce_ready event for startup automations (#246 - @Newreader) — Trigger startup automations on the tado_ce_ready event instead of guessing timing with delays or wait_template chains. The event fires once all climate entities have real data — temperature, offset, overlay mode, the lot. Payload includes home_id, entry_id, and zone_count for multi-home filtering.

  • Climate entity exposes Offset Sync clamp state (#262 - @simonotter) — When the gap between your external sensor and the TRV needs a correction larger than ±10°C, Tado clamps the offset at the limit. The climate entity now exposes offset_clamped: true and offset_clamp_direction: hit_max | hit_min so dashboards and automations can react. A warning fires in the log so you know to check for draughts, a cold external wall behind the TRV, or an external sensor placed somewhere warmer than the radiator.

Bug Fixes

  • Tado app changes now reach Home Assistant within seconds when HomeKit is connected (#253 - @apilone, #261 - @apilone) — Changing temperature or HVAC mode in the Tado phone app used to take up to one cloud poll cycle to show in HA. With HomeKit connected, target temperature and mode now update from bridge events in real time, including when you flip a zone from OFF to HEAT or set a temperature on an OFF zone.
  • Climate card now shows OFF correctly (#258 - @Newreader, @apilone, Discussion #219 - @dragorex71) — When a zone was off — via schedule, Away mode, or set_hvac_mode: off — the card showed the previous heat target (e.g. 23°C) and HVAC mode "auto" while Tado was actually running frost protection at 5°C. The card now shows 5°C and "off" to match Tado's actual state.
  • HomeKit no longer overwrites your changes with stale cached values (#253 - @apilone) — After changing temperature or mode, the bridge could push a stale value within seconds and undo your change. There's now a 3-minute write protection window after any HomeKit or cloud write — during this window, the bridge's stale target temperature and mode are ignored until the cloud confirms the actual state.
  • Heating controls no longer get stuck after a silent HomeKit failure — If a HomeKit write completed locally but never reached Tado's servers, the integration could keep showing "heating" indefinitely and skip subsequent commands. Writes are now verified against Tado's cloud, the stale state is cleared if not confirmed, and future writes for that zone fall through to cloud until HomeKit recovers.
  • Service calls now refresh the entity immediately (Discussion #219 - @jeverley) — set_open_window_mode, restore_previous_state, resume_schedule, set_climate_timer, and set_water_heater_timer used to update the Tado app instantly but leave the HA entity stale until the next poll. They now trigger an immediate refresh.
  • Failed service calls now surface as errors instead of silent successset_temperature_offset, set_climate_timer, and set_water_heater_timer used to swallow per-zone failures and report overall success even when no write actually landed. They now raise an error visible in the HA UI when every zone fails, and log a warning for partial failures.
  • Early Start and Child Lock switches roll back on failed writes — If the API rejected a switch write (e.g. during a rate-limit window), the switch used to stay in the optimistic new state until the next refresh. The switch now reverts when the underlying API call reports failure.
  • Presence Mode "Auto" no longer briefly shows "Home" when you're away — Switching to Auto used to overwrite the cached presence with "Home" for one poll cycle. Auto now leaves the cached presence alone and lets the next poll fill in the real value from geofencing.
  • Presence labels match across the Hub select and climate cards (Discussion #219 - @dragorex71) — On non-English Home Assistant installations, the Hub presence select and the climate card preset showed different translations (e.g. "Casa" vs "In casa" in Italian). All six supported languages now match.
  • Adaptive Preheat works with non-ASCII zone names — Zones with accented characters or special characters (e.g. "Büro", "Salle-à-manger") were silently failing to find their matching entities, breaking Adaptive Preheat, water heater resume buttons, and thermal analytics. All zone-name lookups now use Home Assistant's standard slug method.
  • Weather Compensation no longer latches into "paused" overnight (#249 - @driagi) — On long night-polling intervals (≥ 60 min, including auto night polling at 120 min), the engine could latch into "paused" forever even though the outdoor temperature source was reporting fresh values. The redundant guard causing this has been removed. The engine also holds the last known outdoor temperature for up to 30 minutes during transient outages instead of pausing on a single missed reading.
  • Token rotations no longer drop in-flight writes — When Tado's auth servers rotate a session mid-request, the API returns 401. Read requests already retried with a fresh token; writes (temperature, mode, schedule resume) now do too. A transient 401 during normal token refresh also no longer deletes your refresh token — Home Assistant's reauth flow handles real auth failures, transient glitches recover on the next refresh.
  • Mold risk and surface temperature attributes are now translated — The temperature_source attribute on Mold Risk / Mold Risk % sensors and the calculation_method attribute on the Surface Temp sensor used to display raw English values regardless of your Home Assistant language. They now show translated labels in German, Spanish, French, Italian, Dutch, and Portuguese alongside English.
  • Integration recovers from corrupt auxiliary storage files — If one of several auxiliary storage files (weather compensation, bridge health, HomeKit savings, window detection state, state-restore) became corrupt after a crash or SD card issue, every entity could go unavailable. The integration now logs a warning and continues with defaults, healing the file on the next successful save.
  • Daily API usage no longer spikes when HomeKit is connected (#268 - @wrowlands3) — A periodic offset drift refresh added during the 4.0 cycle fired every 30 minutes regardless of your HomeKit Cloud Refresh setting, pulling one cloud call per climate zone per cycle. On a home with eight zones at a 60-minute Cloud Refresh, that meant ~16 unexpected calls every hour. With HomeKit connected, the drift refresh now follows the same dial as the rest of cloud sync — set 60 minutes and it runs every 60 minutes. HomeKit-off installs keep the 30-minute floor as a safety net.
  • Weather fetches now follow your HomeKit Cloud Refresh setting — Same shape as the drift-refresh bug above with a smaller blast radius (one call per cycle rather than per zone): the 30-minute weather skip floor was hardcoded and ignored the Cloud Refresh dial. Both paths are now driven by a single user-facing setting.
  • Adaptive Preheat tolerates incomplete cycle metrics — When the heating cycle store had a partially-recorded cycle with a missing inertia time or heating rate, the preheat estimator could raise an error in the log instead of skipping. It now returns no estimate and lets the next valid cycle take over.

Improvements

  • All data now uses Home Assistant's built-in storage — Zone states, weather, rate limits, schedules, HomeKit pairings, and per-zone state files moved from custom JSON files to HA's native Store system. The migration runs once on first startup; old files are renamed (not deleted) so you can roll back if needed. No more blocking file reads on the main thread.
  • Token refreshes ~50% less often — The integration used to refresh access tokens every 5 minutes, but Tado issues them for roughly 10 minutes. It now reads the actual expiry from Tado's response and only refreshes when the token is about to expire.
  • Boiler flow temperature updates every 60 seconds (#237 - @ChrisMarriott38) — The boiler flow sensor used to be tied to your cloud polling interval (up to 30 minutes between updates). It now polls the bridge independently every 60 seconds. The bridge API doesn't count against your Tado quota.
  • Custom polling interval applies everywhere (#239 - @ChrisMarriott38) — If you set a custom day or night polling interval, all data (zone states, humidity, heating power, weather, boiler flow temperature) refreshes at that rate. Previously, HomeKit's Cloud Data Refresh setting could override your custom interval for some data.
  • Smarter polling when HomeKit is connected — When HomeKit is providing live data, the integration skips redundant cloud fetches and stretches the polling interval. Weather data is fetched every 30 minutes instead of every poll. Cloud outages no longer make entities unavailable when HomeKit is still working.
  • Insight history writes drop ~50% — The insight history file used to write once per polling cycle (up to 2,880 writes/day with 30-second polling). Writes are now debounced to once per minute, reducing SD card wear without losing data on shutdown.
  • API call history attributes capped to 10 entries (was 100) — The API usage, limit, and call history sensors used to expose up to 100 entries each in their attributes, bloating the recorder database over time. Dashboards only show the most recent few, so the cap is now 10.
  • Less CPU work per poll on homes with many zones — Zone insights are now computed once per polling cycle and cached for every zone sensor and the home sensor to read, instead of each sensor collecting independently.
  • Smarter HTTP error handling — 404 on overlay deletion (already gone) is no longer logged as an error. 422 (Tado API rejection) is logged as a warning with the actual rejection reason. 429 reads the Retry-After header to know when to try again. 500 / 502 / 503 / 504 are retried automatically with backoff.
  • Settings UI reorganised — General Settings now grouped by what each toggle does (Tado Features / Hardware Connections / Smart Automations / Advanced). Zone Configuration reordered to match how you think about a zone (Temperature Limits → Heating System → External Sensors → Smart Features → Manual Temperature Override). Internet Bridge gets its own settings section instead of living under "Weather Compensation" (#240 - @ChrisMarriott38). Existing entity IDs and config keys unchanged.
  • External sensor toggles renamed for clarity — "Use External Temperature/Humidity Sensor" → "Override Tado's Temperature/Humidity Sensor". Turning the toggle off keeps your sensor selection saved, so you can pause without losing the configuration.
  • Hot Water Timer default moved to Polling & API — Lived under Smart Comfort by accident; now lives next to the other service defaults. Config key unchanged.
  • Smart Comfort defaults to Light on first enable — Used to default to None, which left the feature doing nothing.
  • Device serial numbers masked across logs and entity attributes — Battery sensors, connection sensors, device tracker entities, log messages, and HomeKit mappings now show the first 6 characters followed by . The bridge serial is printed on the device and the auth code is only 4 digits, so a leaked serial in a shared log could enable brute-force pairing.
  • Diagnostics dump redacts more sensitive fields — Bridge serial, additional Tado API response fields, and other sensitive values are scrubbed from Settings → Devices → Tado CE → Download Diagnostics. Diagnostics also include a data_flow_health section with last cloud fetch timestamp, HomeKit and bridge connection status, and persistence state.
  • Climate entities show where their data comes fromtemperature_source and humidity_source attributes show cloud, homekit, or external instead of the legacy tado label. A new last_write_source attribute shows whether the most recent change went through HomeKit or the cloud.
  • Window Predicted, heating rate, and insights now react to real-time HomeKit data — Window detection, heating cycle tracking, mold risk, comfort level, humidity trends, and heating anomalies were using cloud data even when HomeKit had fresher readings. They now use the same live data as the rest of the integration.
  • Plain-English log messages, with consistent prefixes and recovery hints — Internal terms (backed-off, bang-bang fallback, optimistic state expired, ROLLBACK) replaced with plain-English equivalents. Every line now starts with a clear subsystem label (Coordinator:, Climate AC:, HomeKit:, Smart Valve:, etc.) so you can filter by feature when something goes wrong. Failures explain what the integration did about it ("rolling back optimistic state", "will retry on the next poll", "captured baseline preserved so you can retry"), so a log paste is enough to diagnose without a back-and-forth. Per-write chatter that used to flood multi-zone homes at info level is now debug; once-per-startup / shutdown summaries stay at info. Device serials and home IDs are masked everywhere so logs are safe to share publicly.

Known Issues

  • register_detection_callback() is deprecated warning if HomeKit is enabled — The warning comes from the aiohomekit library's internal BLE scanning code, not from Tado CE. It does not affect functionality and will disappear when aiohomekit releases an update. You can safely ignore it.

How to Update

HACS → Tado CE → ⋮ → Redownload → tick "Need a different version?" → select v4.0.0 → Restart HA

After Restart, give the integration ~10 seconds to migrate your data and re-pair HomeKit (if previously paired). Check Settings → Devices → Tado CE Hub afterwards to confirm everything came back online.


Thanks to everyone who supported the project through Buy Me a Coffee — it genuinely helps. Special thanks to the contributors who carried the 4.0 cycle: @simonotter, @ChrisMarriott38, @Si-Hill, @wrowlands3, @apilone, @driagi, @Newreader, @dragorex71, @jeverley, @mpartington, @hapklaar, and @Thilas — your reports, screenshots, debug logs, and patience across 16 betas are why this release exists.

Full changelog: v3.5.3...v4.0.0