🚀 Welcome to Better Thermostat 2.0!
Better Thermostat 2.0 is a generational upgrade re-architected from the ground up for rock-solid reliability, fail-soft safety, and total transparency.
Special Thanks to @cl445, for helping me to build the next level of BT
Your rooms, settings, target temperatures, and learned heating profiles carry over automatically. You do not need to reconfigure anything.
Caution
Beta Pre-Release Warning — Do Not Use in Production Without Care:
This is an early beta release intended for testing and community feedback. While extensively validated, beta software can be unstable and may exhibit unexpected bugs, glitches, or quirks.
Please do not install this version in mission-critical production environments, especially if you depend on guaranteed heating or are uncomfortable gathering diagnostics and submitting bug reports on GitHub.
Always take a full Home Assistant backup before installing this update so you can easily revert if necessary.
Note
Requirements: Home Assistant 2026.9.0 or newer is required.
🏗️ A rock-solid decision engine that never guesses
In earlier releases, sensor event handling, thermal calculations, and device network calls were intertwined, which could cause race conditions or repetitive device writes when multiple sensors updated at the same time.
- Clean separation of decisions and device writes. Better Thermostat now separates a pure decision core from device communication. At each cycle, it captures a single, coherent snapshot of your room and computes exactly what each radiator should do before sending any commands.
- Event bursts coalesce into single decisions. Rapid bursts of sensor updates or manual adjustments are gathered into a single decision rather than hammering your Zigbee or Z-Wave network with repeated writes.
- Built-in flight recorder. The decision engine records exactly why every heating decision was made (e.g. window opened, target reached, or sensor degraded), making troubleshooting and diagnostics transparent and fully reproducible.
🛡️ Smarter fail-soft protection keeps your home warm
When hardware glitches or batteries run out, Better Thermostat 2.0 ensures your home stays comfortable rather than shutting down.
- Offline window and door sensors no longer freeze your room. In 1.9, an unavailable window or door sensor was treated as "open", turning heating completely off. In 2.0, an offline contact sensor is treated as closed, keeping your room heated while gently notifying you with a degraded-mode repair notice in your Home Assistant dashboard.
- Graceful room sensor step-down ladder. If your external room temperature sensor loses connection:
- Better Thermostat first regulates on the average of your radiators' built-in temperature sensors.
- If all sensors become unavailable, it holds the last known valve position instead of shutting off.
- Once your room sensor has reported reliably for five minutes, control returns seamlessly to optimal mode.
- Total visibility into degraded mode. The climate entity now exposes new attributes:
control_mode(optimal,sensor_fallback, orhold),degraded_for_seconds, andcalibrator_health, so you always know when and why a room is running in fallback mode.
☀️ Gentle, time-damped Summer Mode
- No more sudden heating shut-offs on warm afternoons. 1.9 averaged raw calendar-day readings, meaning a sunny afternoon could prematurely stop heating and cause abrupt shifts at midnight. 2.0 damps outdoor temperature readings across a rolling 24-hour time window, providing smooth seasonal transitions.
- 1.0 °C (1.8 °F) switch-back margin. Summer mode now features a built-in hysteresis margin. Once heating turns off for summer, it only turns back on when the outdoor temperature drops a full 1.0 °C below your threshold, preventing annoying day-to-day toggling during spring and autumn.
- Day and night forecast averaging. Weather entity forecasts now average daily highs and lows together rather than only looking at peak daytime temperatures, ensuring your radiators heat on chilly nights.
❄️ Compressor protection for air conditioning & cooling
- 240-second anti-short-cycling hold. To protect cooling compressors from premature wear, Better Thermostat now automatically holds back unchanged mode or temperature commands if the same command was sent less than 240 seconds earlier.
- Graceful retry backoff. Failed cooling commands are retried with an expanding pause (from 30 seconds up to 30 minutes) rather than repeatedly spamming your climate unit.
🧮 Real-time diagnostic sensors for MPC v2
For setups using the advanced Model Predictive Control (MPC v2) algorithm, four new real-time diagnostic sensors provide full visibility into your room's thermal physics:
- Virtual Temperature: The internal estimated thermal state of the radiator.
- Radiator-Room Coupling: The estimated heat transfer rate between the radiator and the room.
- Thermal Disturbance: Estimated extra heat entering the room (such as sunshine or extra occupants).
- Room Time Constant: How slowly or quickly your room loses heat to the outside.
🔌 Native Shelly BLU TRV support & expanded quirks
- Direct Shelly BLU TRV integration. Better Thermostat now communicates directly with Shelly BLU TRVs, commanding valve opening percentages natively without intermediate helper entities.
- Dedicated valve entities. Seamless support for devices that expose dedicated valve position number or valve entities.
- Expanded model quirks. Added dedicated device quirks and fixes for the Sonoff TRV-ZBT (TRV Gen2), Tuya ME167, Z-TRV-V01, COZB0001, and Eurotronic Spirit.
🔄 Seamless settings migration & automatic entity tracking
- Settings moved to options. Configuration is now cleanly stored in config entry
optionsrather thandata, matching modern Home Assistant architecture. - Automatic rename tracking. If you rename a climate entity, room sensor, window contact, or cooler in Home Assistant, Better Thermostat automatically follows the entity to its new ID so your automations and rooms never break.
- Automatic sensor cleanup. Diagnostic sensors that are no longer needed (such as the legacy solar intensity sensor) and old PID sensor entities are automatically cleaned up from your entity registry.
- Self-clearing repairs. Dashboard repair issues are tied directly to config entries and clear themselves automatically as soon as the underlying issue is resolved.
🎨 Modern brand identity & Platinum Quality Scale
- Official brand assets. High-resolution brand icons and logos are now bundled directly within the integration.
- Home Assistant Platinum Quality Scale compliance. Better Thermostat now achieves Home Assistant's highest quality tier (Platinum Quality Scale), featuring strict end-to-end type safety, standard entity categorization, comprehensive error handling, and clean lifecycle management.
🔙 Seamless rollback to 1.9.3
If you ever need to go back to the 1.9 maintenance line, you can safely reinstall 1.9.3 or newer via HACS. 1.9.3 was specifically designed to read settings from the new 2.0 configuration format, so all your rooms and settings remain completely intact.
Full commit-level changelog
What's Changed
- [TASK] bump version v2 by @KartoffelToby in 9147d107
- chore: relink the history the 1.9.0 squash detached by @cl445 in 11e85bda
- Merge PR #2128 (v2) by @KartoffelToby in #2128
- Merge PR #2237 (test/config-and-options-flow) by @cl445 in #2237
- Merge PR #2239 (chore/coderabbit-test-instructions) by @cl445 in #2239
- Merge PR #2238 (test/startup-and-availability-scenarios) by @cl445 in #2238
- Merge PR #2240 (test/device-automation-surface) by @cl445 in #2240
- Merge PR #2241 (docs/issue-to-fixture-rule) by @cl445 in #2241
- Merge PR #2242 (ci/per-module-coverage-floor) by @cl445 in #2242
- Merge PR #2245 (test/multi-trv-end-to-end) by @cl445 in #2245
- Merge PR #2246 (fix/child-lock-missing-key) by @cl445 in #2246
- Merge PR #2249 (chore/ignore-playwright-artifacts) by @cl445 in #2249
- Merge PR #2250 (chore/invert-type-strictness-ratchet) by @cl445 in #2250
- Merge PR #2251 (chore/gate-blind-except) by @cl445 in #2251
- Merge PR #2252 (chore/remove-dead-code) by @cl445 in #2252
- Merge PR #2253 (chore/effective-type-suppressions) by @cl445 in #2253
- Merge PR #2254 (chore/prune-orphaned-linters) by @cl445 in #2254
- Merge PR #2255 (chore/hoist-deferred-imports) by @cl445 in #2255
- Merge PR #2256 (fix/silent-exception-handlers) by @cl445 in #2256
- Merge PR #2260 (fix/mqtt-valve-patch-target) by @cl445 in #2260
- Merge PR #2257 (chore/adapter-host-protocol) by @cl445 in #2257
- Merge PR #2258 (chore/annotate-model-fix-hosts) by @cl445 in #2258
- Merge PR #2259 (chore/annotate-shell-modules) by @cl445 in #2259
- Merge PR #2261 (fix/preset-temperatures-survive-reload) by @cl445 in #2261
- fix: reset an MQTT TRV onto its manual preset instead of "none" by @cl445 in #2274
- fix: restore the HVAC mode after maintenance only when it moved by @cl445 in #2276
- fix: re-send the room temperature to mirroring TRVs on a timer by @cl445 in #2278
- fix: rename BT entity ids only when the thermostat was renamed by @cl445 in #2272
- test: assert the startup registration sets in full and measure branch coverage by @cl445 in #2280
- fix: keep the degradation ladder on a five-minute tick for every calibration mode by @cl445 in #2282
- test: round-trip the settings a user configured (TG12) by @cl445 in #2264
- docs: settle naming on PEP 8, Google §3.16 and a project glossary by @cl445 in #2263
- fix: let the MPC governor follow setpoint reductions by @cl445 in #2293
- fix: debounce internal TRV temperature per device instead of per room by @cl445 in #2292
- fix: apply temperature readings in the order they arrived by @cl445 in #2329
- fix: read "a head is off" the same way at startup and at runtime by @cl445 in #2284
- fix: cancel the plateau timer when the entity is removed by @cl445 in #2294
- fix: wait for the device before reporting an adopted TRV as tweaked by @cl445 in #2334
- test: assert sequence properties on the stateful controllers (TG15) by @cl445 in #2315
- fix: report refused valve writes in the TRVZB quirk by @cl445 in #2320
- fix: write the deCONZ calibration offset in the units deCONZ reads by @cl445 in #2327
- chore: remove unreachable branches and correct stale comments by @cl445 in #2301
- fix: report refused device writes in the model quirks by @cl445 in #2331
- fix: stop reporting valve support for TRVs without a valve quirk by @cl445 in #2307
- feat: allow overriding the target temperature range in the config flow by @cl445 in #2314
- refactor: name the heated entity by its glossary term by @cl445 in #2321
- fix: let the naming gate accept newly added test files by @cl445 in #2324
- chore: re-record four coverage floors against the tree they guard by @cl445 in #2333
- fix: write select-based calibration offsets through the right service by @cl445 in #2300
- fix: acknowledge queue sentinels and stop retrying programming errors by @cl445 in #2303
- fix: keep the control cycle running when a TRV write fails by @cl445 in #2291
- fix: skip unreadable TRV modes when snapshotting for valve maintenance by @cl445 in #2299
- fix: reject non-finite values on the persistence and telemetry paths by @cl445 in #2310
- chore: report the maintenance-line commits that never reached develop by @cl445 in #2311
- fix: let infrastructure errors reach the retry decorator in the adapter delegate by @cl445 in #2316
- fix: fail the coverage gate when a recorded floor leaves the report by @cl445 in #2336
- fix: keep the Kalman covariance symmetric and round valve percentages half up by @cl445 in #2302
- fix: report unusable MPC state and valve caps instead of dropping them by @cl445 in #2326
- fix: clear contact and temperature repair issues once a reading is valid again by @cl445 in #2308
- fix: let the entity cancel the background tasks it started by @cl445 in #2337
- fix: stop cutting TRV write retries short in the control cycle by @cl445 in #2323
- fix: leave the cooler out of the startup heating-member check by @cl445 in #2339
- chore: drop the remaining dead state fields and read humidity once by @cl445 in #2328
- fix: re-read battery levels after a device recovers and log the sensor warning once by @cl445 in #2306
- refactor: read battery levels directly instead of through a background task by @cl445 in #2325
- fix: restore Eurotronic Spirit valve control and deterministic TRVZB sibling lookup by @cl445 in #2312
- test: give the watcher tests real states to read by @cl445 in #2340
- test: state the requirement in a test docstring, not the run by @cl445 in #2309
- Merge master back into develop so the 2.0.0 release PR can merge by @cl445 in #2344
- Re-record the forward-port gaps against both current lines by @cl445 in #2346
- test: refuse a trigger on a device that carries no thermostat by @cl445 in #2343
- fix: restore the temperature range a cooler publishes by @cl445 in #2348
- fix: refresh the cached TRV mode when a control cycle ends by @cl445 in #2350
- fix: offer direct valve control where the model's quirk drives the valve by @cl445 in #2353
- fix: observe a TRV switched back on at its own knob by @cl445 in #2355
- test: run the async tests without a file-local anyio backend by @cl445 in #2351
- fix: link the BT device by via device id by @cl445 in #2362
- chore: record the MQTT offset-bounds fix as carried forward in another shape by @cl445 in #2368
- fix: read the TRV key when migrating a config entry to version 18 by @cl445 in #2370
- fix: pin the setpoint adoption rule in production instead of rebuilding it in tests by @cl445 in #2375
- fix: confirm a calibration offset the device reports a full step away by @cl445 in #2378
- fix: remember the setpoints a device may still echo after an unconfirmed write by @cl445 in #2381
- refactor: finish naming a TRV entity id by its glossary term by @cl445 in #2372
- refactor: tell a TRV entity id apart from its configuration entry by @cl445 in #2374
- refactor: use one name for the TRV behind a real_trvs entry by @cl445 in #2376
- chore: enforce PEP 8 naming with ruff's N rules by @cl445 in #2373
- chore: re-record the naming budget against the current tree by @cl445 in #2369
- chore: re-record the coverage floors against the tree they guard by @cl445 in #2380
- test: state requirements instead of the behaviour a defect produces by @cl445 in #2397
- test: drive every trigger entrance of a room while one TRV is unavailable by @cl445 in #2398
- test: pin device events that arrive during a control cycle or a confirmation wait by @cl445 in #2399
- test: cover the Home Assistant boot order and a host reboot by @cl445 in #2400
- test: pin every temperature write path on a Fahrenheit system by @cl445 in #2401
- test: run MPC v2 under free heat, setpoint steps and airing by @cl445 in #2403
- docs: state the Python 3.14 floor for contributors by @cl445 in #2386
- test: build registry fixtures from the production RegistryEntry type by @cl445 in #2402
- fix: skip disabled and device-less registry entries when looking up TRV siblings by @cl445 in #2412
- fix: plan MPC v2 around free heat without hunting the valve by @cl445 in #2414
- fix: protect the HomematicIP duty cycle on the write side instead of slowing the room sensor by @cl445 in #2415
- fix: keep device reports that arrive during a control cycle by @cl445 in #2408
- fix: keep Fahrenheit writes, bounds and defaults inside what the device accepts by @cl445 in #2407
- fix: resume PID and MPC after a host reboot or clock step and report dropped stored values by @cl445 in #2411
- fix: keep the room heating on a silent forecast and on heat_cool or auto reports by @cl445 in #2413
- fix: read a report held during a cycle against the state it replaced by @cl445 in #2433
- fix: keep a room listening to its window, sensors and ticks while one TRV is unreachable by @cl445 in #2410
- fix: start a room without a TRV that outlasts the startup grace window by @cl445 in #2416
- chore: let CodeRabbit accept prose docstrings on private helpers and properties by @cl445 in #2435
- fix: leave the config entry data untouched when building diagnostics by @cl445 in #2458
- fix: remove the door sensor repair issue with the config entry by @cl445 in #2459
- test: run the MPC v2 contact gates without the daqp wheel by @cl445 in #2431
- fix: keep MPC v2 controlling after the wall clock steps back by @cl445 in #2428
- fix: keep the room target when a device without the swap option reports auto by @cl445 in #2429
- fix: round a preset's cooling target onto the configured step by @cl445 in #2434
- fix: apply room sensor readings in arrival order when a plateau timer fires late by @cl445 in #2430
- fix: watch a setpoint write whose service call raises by @cl445 in #2432
- refactor: drop the saved_temperature slot nothing writes by @cl445 in #2476
- chore: record six maintenance-line fixes develop carries in another shape by @cl445 in #2482
- fix: save the controller state once a failed copy of an unreadable store succeeds by @cl445 in #2440
- fix: report a refused mode write and give an out-of-reach TRV one write attempt per cycle by @cl445 in #2442
- fix: back off a control cycle that keeps failing and stop the loop's timers with the entity by @cl445 in #2443
- fix: bound the weather forecast call so startup cannot stall on it by @cl445 in #2471
- fix: name the thermostat in blueprint notifications from the device input by @cl445 in #2473
- fix: re-read a stored battery level when the battery entity reports a new one by @cl445 in #2477
- Fix the sensor fallback reading stale TRV temperatures and not reacting to rung changes by @cl445 in #2487
- fix: adopt a one-step cooling press, turn a child-locked device back at once, and keep a switched-on room as heat by @cl445 in #2444
- fix: keep each thermostat to one entry and make migration, repairs and settings consistent by @cl445 in #2438
- fix: let platform entities follow algorithm and name changes, and make device triggers fire on the change they name by @cl445 in #2441
- fix: log the setpoint a TRV reported, not only BT's clamped view of it by @cl445 in #2465
- fix: cancel a pending Away on return and apply the battery throttle by @cl445 in #2466
- Write a range-only head's setpoint as its lower bound by @cl445 in #2489
- fix: reuse the outdoor history mean instead of querying the recorder on every update by @cl445 in #2468
- fix: send the cooler its setpoint on its own grid, turn back a locked press during a cycle, and log failed retries once by @cl445 in #2445
- fix: start a room on the TRV temperature when its sensor outlasts the startup grace window by @cl445 in #2483
- fix: keep valve maintenance away from a TRV that is not set up yet by @cl445 in #2447
- chore: re-record the four lowered budgets by @cl445 in #2481
- chore: record seven maintenance-line fixes develop carries in another shape by @cl445 in #2486
- chore: record 28 maintenance-line fixes develop carries in another shape by @cl445 in #2497
- fix: let a TRV speak for the room only on a temperature it reports by @cl445 in #2498
- test: drive the decision kernel through random event sequences by @cl445 in #2493
- fix: evaluate the degradation ladder every minute in every configuration by @cl445 in #2494
- test: hold the timing constants to the relations their comments claim by @cl445 in #2495
- fix: report a stalled control loop only when a device diverges by @cl445 in #2496
- fix: let MPC v2 without daqp command what daqp would, and hold the valve on a non-finite plan by @cl445 in #2446
- fix: start the room at its heads' setpoint and let learning reach the measured rates by @cl445 in #2439
- docs: correct the contributor docs against the tree and CI by @cl445 in #2462
- docs: correct internals against the code, add door-suppression golden by @cl445 in #2463
- docs: correct the user documentation against the code by @cl445 in #2464
- chore: record the controller-state copy develop carries in another shape by @cl445 in #2503
- docs: wrap the long lines in the MPC v2 QP solver docstrings by @cl445 in #2501
- fix: check thermostat ownership again right before an entry is saved by @cl445 in #2504
- fix: read a held-back temperature and a Fahrenheit cooling write on replay by @cl445 in #2505
- fix: restart the room temperature filter when the sensor returns by @cl445 in #2506
- fix: unblock the forward-port gate and let the budget gates see new files by @cl445 in #2437
- fix: retry the quarantine copy on its own timer by @cl445 in #2500
- fix: leave a head that cools out of the startup heating target by @cl445 in #2507
- fix: control on a fallback reading that also confirms an offset write by @cl445 in #2509
- fix: hold each channel of a room with a cooler to its own device range by @cl445 in #2485
- fix: make the advanced config-flow strings match the behaviour by @cl445 in #2480
- chore: record two maintenance fixes develop carries in another shape by @cl445 in #2510
- fix: read a head turned back to its last confirmed setpoint as the user's turn by @cl445 in #2512
- chore: record six maintenance fixes develop carries in another shape by @cl445 in #2519
- fix: restore a preset target as it is applied by @cl445 in #2508
- chore: record the held-report replay develop carries in another shape by @cl445 in #2531
- Fix two sensor fallback gaps: marker reports and a stale ladder observation by @cl445 in #2528
- fix: switching a head on does not adopt a setpoint turned while it was off by @cl445 in #2520
- chore: record the switch-on replay cycle develop carries in another shape by @cl445 in #2532
- fix: judge a later switch-on report held in a cycle against off by @cl445 in #2537
- test(benchmark): run MPC v2 in the calibration benchmark by @cl445 in #2515
- test(benchmark): map indirect-TRV intent onto a setpoint as production does by @cl445 in #2516
- chore: record the sensor fallback develop carries in another shape by @cl445 in #2542
- fix: the v0 migration's save is a task the final flush waits for by @cl445 in #2539
- test(benchmark): close the valve for every controller while a window is open by @cl445 in #2540
- fix: keep a setpoint-steered TRV's opening out of MPC v2's command by @cl445 in #2517
- test: run unit-layer sleeps at a thousandth of their length by @cl445 in #2533
- test: a thermostat stand-in that refuses to invent state by @cl445 in #2534
- fix: correct a head turned to the room's target during a cycle by @cl445 in #2525
- fix: take a setpoint the device already holds as Better Thermostat's own by @cl445 in #2529
- chore: record the quarantine copy and its runtime retry develop carries in another shape by @cl445 in #2543
- test: replay and shrink room event sequences, and search three rooms under four rules by @cl445 in #2514
- test: drive the room search through reloads and restarts, booted like Home Assistant by @cl445 in #2518
- test: drive the room search through the window and the room's mode by @cl445 in #2522
- fix: correct a cooling turn adopted at the cooling target it already had by @cl445 in #2552
- docs: wrap the held-report docstring to the line width by @cl445 in #2545
- fix: take a reading the debounce turned away once the interval is over by @cl445 in #2523
- test: drive the room search through sensor readings and Fahrenheit rooms by @cl445 in #2527
- test: build 38 files' thermostat stand-ins on the strict stand-in by @cl445 in #2535
- test: let the lost-write heal wait for the confirmation instead of a timeout by @cl445 in #2546
- test: run each balance strategy against a real TRV by @cl445 in #2547
- chore: record the debounce fixes develop carries in another shape by @cl445 in #2561
- test: build every remaining thermostat stand-in on the strict stand-in by @cl445 in #2536
- chore: drop the hasattr guards in advance_hvac_action by @cl445 in #2538
- test: sort the suite into unit and gates by @cl445 in #2541
- test: let the control-queue tests wait on the queue instead of the clock by @cl445 in #2548
- refactor: keep the climate entity in the entry's runtime data by @cl445 in #2560
- perf: keep the climate entity's controller telemetry out of the recorder by @cl445 in #2549
- chore: fail the budget and floor gates on unrecorded slack and on a module without a floor by @cl445 in #2558
- Move onto current Home Assistant APIs: device lookup, recorder, dispatcher, dead hooks by @cl445 in #2550
- feat: translate the errors a refused climate service call shows by @cl445 in #2551
- feat: register the services on load and let valve maintenance say why it did not run by @cl445 in #2553
- feat: say why resetting the PID learnings did not do what was asked by @cl445 in #2554
- feat: ship the brand images with the integration by @cl445 in #2556
- feat: put what a bug report needs into the diagnostics download by @cl445 in #2555
- feat: take entity and service icons from icons.json by @cl445 in #2557
- fix: keep idle overheating protection from opening the valve by @cl445 in #2562
- test: hold the idle overheating sweep to equality up to the line by @cl445 in #2564
- docs: add an upgrade page from 1.9 to 2.0 by @cl445 in #2559
- feat: mirror the room temperature into the Sonoff TRV-ZBT (TRV Gen2) by @cl445 in #2499
- feat(shelly): write the valve of a Shelly BLU TRV directly by @cl445 in #2570
- fix: take no valve position as sent while the valve entity has no state by @cl445 in #2572
- chore: update the development toolchain by @cl445 in #2569
- fix: solve the polished MPC v2 plan apart from its multipliers by @cl445 in #2571
- fix: read a device command its library cancelled as a lost connection by @cl445 in #2592
- test: read the device's config entry from config_entry_id by @cl445 in #2593
- refactor: spell out value and config in local names by @cl445 in #2574
- refactor: name temperature differences delta_kelvin in the controllers by @cl445 in #2577
- refactor: name the cooling target cool_target_temperature by @cl445 in #2578
- refactor!: name the learning attributes' temperature difference delta_kelvin by @cl445 in #2581
- refactor: name the heating target heat_target_temperature by @cl445 in #2583
- fix: read the saved thermostat state before Home Assistant starts by @cl445 in #2594
- fix: keep a Shelly TRV (Gen1) from reading a closed valve as off by @cl445 in #2588
- fix: name the device boundaries that keep a broad handler, inline by @cl445 in #2590
- fix: keep an entry's settings in its options by @cl445 in #2596
- fix: never write a TRV setpoint on a finer grid than the device's by @cl445 in #2597
- fix: point a TRVZB at the remote sensor under the new Zigbee2MQTT names by @cl445 in #2598
- fix: compare forward-port gaps against origin/develop by default by @cl445 in #2586
- test: hold calibration.py above 95 % coverage by @cl445 in #2608
- test: raise the coverage floors the suite has outgrown by @cl445 in #2609
- fix: meet the Silver rules of the Integration Quality Scale by @cl445 in #2603
- test: hold the Gold and Platinum rules of the Integration Quality Scale by @cl445 in #2602
- refactor: name the snapshot fields by their glossary terms by @cl445 in #2607
- test: hold the device triggers, conditions and actions to full coverage by @cl445 in #2604
- chore: record the device trigger typing as carried forward by @cl445 in #2621
- fix: match rejected spellings behind a leading underscore by @cl445 in #2615
- feat: publish the filtered room reading, the slope and the degraded time under their terms by @cl445 in #2620
- fix: size the heating-power valve from the effective room temperature by @cl445 in #2624
- refactor: type the model-fix, Trv and state-manager surfaces directly by @cl445 in #2623
- refactor: read guaranteed attributes directly in the entity shell by @cl445 in #2627
- refactor(calibration): direct field access and object-typed debug payloads; drop MPC phantom params by @cl445 in #2628
- refactor: hold the platforms and the config flow to full pyrefly strictness by @cl445 in #2625
- refactor: name the room temperature EMA after the glossary by @cl445 in #2629
- test: let thermostat stand-ins carry constructor attributes and read them directly by @cl445 in #2634
- refactor(adapters): annotate the delegate and drop its pyrefly exemption by @cl445 in #2630
- refactor: type the event handlers and control_cooler strictly by @cl445 in #2632
- refactor: drop the pyrefly exemptions of watcher.py and helpers.py by @cl445 in #2631
- refactor(calibration): type the calibration shell and drop the unused valve calibration hook by @cl445 in #2633
- refactor: name the temperature slope after the glossary by @cl445 in #2636
- chore: drop config flow attributes nothing reads by @cl445 in #2640
- refactor: type utils/weather.py under strict pyrefly by @cl445 in #2641
- refactor: read thermostat attributes directly in watcher, helpers and diagnostics by @cl445 in #2644
- refactor: type Trv.calibration_balance as CalibrationBalance by @cl445 in #2642
- refactor: drop the pyrefly exemption for climate.py by @cl445 in #2643
- Add z-trv-v01 quirk for valve control by @cl445 in #2638
- fix: read the advanced boolean options the way the options flow saves them by @cl445 in #2648
- refactor: type the stored-value coercers on object in a stdlib-only module by @cl445 in #2646
- refactor: spell out the unit of the stored re-identification RMSEs by @cl445 in #2647
- refactor: parse the entry settings into TypedDicts once at setup by @cl445 in #2649
- fix: read the calibration mode and type alike in every reader by @cl445 in #2650
- refactor: accept the control-theory notation by name and place by @cl445 in #2653
- fix: calibrate the COZB0001 on the offset it adds to its setpoint by @cl445 in #2651
- refactor: read the legacy stores as Mapping[str, object] by @cl445 in #2655
- refactor: declare every PEP 8 naming exception in pyproject.toml by @cl445 in #2658
- refactor: read the unified state store and the MPC v2 snapshot as Mapping[str, object] by @cl445 in #2656
- refactor: read other entries' settings through lenient typed accessors by @cl445 in #2659
- refactor: take restored attributes as object and narrow them at each consumer by @cl445 in #2666
- refactor: write the unified state store through typed per-section writers by @cl445 in #2667
- test: hold climate.py at the coverage target and mark test-coverage done by @cl445 in #2664
- fix: compare the options flow's calibration algorithms the way the runtime reads them by @cl445 in #2669
- refactor: clamp the typed thermal stats without reparsing them by @cl445 in #2670
- feat: check rejected word parts and unit suffixes in names by @cl445 in #2671
- test: allow typing.Any only where a foreign signature puts it by @cl445 in #2680
- fix: keep a PID gain set anywhere its number allows by @cl445 in #2677
- feat: categorise, class and disable the sensors as the Gold entity rules ask by @cl445 in #2673
- docs: meet the Gold documentation rules of the quality scale by @cl445 in #2672
- fix: let a TypeError from the climate mode write reach the retrying caller by @cl445 in #2668
- fix: decide summer mode on a damped outdoor temperature with hysteresis by @cl445 in #2678
- refactor: drop the type conversions pyrefly finds redundant and hold them as errors by @cl445 in #2683
- refactor: spell out temperature, percent and time units outside the notation by @cl445 in #2682
- refactor: read the persisted state through typed per-field readers by @cl445 in #2684
- refactor: read attributes directly where their owner declares them by @cl445 in #2686
- feat: drop the sun intensity sensor no controller reads by @cl445 in #2685
- refactor: spell out temperature and percent in the calibration code by @cl445 in #2687
- fix: damp the weather entity's temperature and read daily forecasts as high and low by @cl445 in #2681
- test: type-check scripts and the gate tests by @cl445 in #2688
- refactor: spell out temperature and minutes in the persisted MPC and PID fields by @cl445 in #2689
- test: type-check the integration and benchmark tests by @cl445 in #2692
- fix: check number.py at full type strictness and mark strict-typing done by @cl445 in #2691
- refactor: spell out the remaining word parts in the tests, empty the naming budget by @cl445 in #2690
- fix: refuse a Better Thermostat or a setpoint-less climate as thermostat or cooler by @cl445 in #2701
- test: type-check the unit tests by @cl445 in #2693
- docs: document device trigger parameters and the damped outdoor temperature by @cl445 in #2699
- fix: key repair issues by config entry and drop the confirm-only fix flow by @cl445 in #2700
- test: type-check the shared test factories and the root conftest by @cl445 in #2736
- refactor: drop the MPC cycle temperature that nothing reads by @cl445 in #2702
- fix: hold the naming budget per name, not per file by @cl445 in #2703
- fix: translate the config-flow help texts and correct the PID reset action texts by @cl445 in #2709
- fix: derive the room mode of a head without off mode only from a press by @cl445 in #2706
- fix: stop treating stale inputs as current readings by @cl445 in #2720
- fix: keep the PID integral and the user's PID settings per TRV across target changes by @cl445 in #2724
- fix: keep MPC v2 on its plan, inside the valve cap and across prior changes by @cl445 in #2717
- test: write out pending core store saves before counting listeners after an unload by @cl445 in #2737
- fix: stop re-sending off-grid setpoints and turn TRVs off reliably by @cl445 in #2723
- fix: keep an off cooler's placeholder and a coarser answer out of the cooling target by @cl445 in #2715
- fix: make the device triggers and the hvac action condition work with string batteries, coolers and no threshold by @cl445 in #2711
- fix: keep a knob turn made while a window or door is open as the room's target by @cl445 in #2738
- fix: pick the writable valve entity, skip the closing degree and share the child-lock lookup by @cl445 in #2708
- fix: calibrate the ME167 with the standard offset sign by @cl445 in #2705
- fix: keep the thermostat working after its entity_id is changed by @cl445 in #2710
- perf: keep the filtered room temperature out of the recorder and write the minute EMA tick only on a published change by @cl445 in #2716
- fix: smooth the PID derivative over time and tune Kd only on real overshoots by @cl445 in #2712
- fix: hold a separate cooler to the decided mode, and write it no setpoint while it is off by @cl445 in #2726
- fix: restore and stop background work cleanly when a thermostat is unloaded by @cl445 in #2721
- fix: leave a preset on a manual cooling target and drop its saved cooling target by @cl445 in #2714
- fix: keep a press at a TRV that lands during or right after a control cycle by @cl445 in #2728
- fix: bound TRV, quirk and cooler writes and the initial tweak so one silent device cannot stall the room by @cl445 in #2719
- fix: let the options flow repair a refused entry and prefill only what it offers by @cl445 in #2725
- fix: pause the external temperature keepalive while the room sensor gives no reading by @cl445 in #2704
- fix: convert temperatures at number entities into the unit they publish by @cl445 in #2718
- fix: write a setpoint on the whole degrees a Fahrenheit TRV is shown in by @cl445 in #2713
- fix: carry sensor changes, the room filter and a removed preset correctly through startup by @cl445 in #2722
- fix: follow a configured entity to its new entity id by @cl445 in #2727
- docs: compare the 2.0 upgrade page with 1.9.3 and fix stale pages before the release by @cl445 in #2707
Full Changelog: 1.9.3...2.0.0-Beta-1