Support half-degree setpoints driven by device metadata#148
Open
jeffscottmtl wants to merge 1 commit into
Open
Support half-degree setpoints driven by device metadata#148jeffscottmtl wants to merge 1 commit into
jeffscottmtl wants to merge 1 commit into
Conversation
Thermostats, heater-coolers, and Home Assistant climate entities now step and display their setpoints in the increment the device advertises, typically 0.5 °C, instead of hardcoded whole degrees. A 21.5° setpoint set from Apple Home finally reads 21.5°, not 22°, and the ± steppers can reach it. How it works: - ServiceData carries step/min/max metadata for target temperature and both thresholds, read from HMCharacteristicMetadata on HomeKit (same pattern as the existing rotation-speed and colour-temperature ranges) and from target_temp_step/min_temp/max_temp on Home Assistant, with Fahrenheit-server values normalized to internal Celsius (the step is a delta, so it scales by 5/9 without the offset). - TemperatureFormatter.uiStep rounds the advertised step up to the nearest 0.5 °C (HomeKit's spec default of 0.1 °C is unusable one click at a time); missing metadata keeps whole-degree stepping. - Celsius stepping snaps to the step grid, so an off-grid 21.3 steps to 21.5 or 21.0. Fahrenheit stepping is untouched and keeps the one displayed-degree-per-click behaviour from nickustinov#137; its regression tests are byte-identical. - Setpoint labels use a new formatSetpoint that shows one decimal only when the value is fractional; clamps use the device's min/max with the previous constants as fallback. The heat/cool gap stays 1 °C (ecobee rejects writes with a smaller spread). - ACMenuItem now steps through TemperatureFormatter.step like the other climate items, fixing its latent Fahrenheit bug where each click moved the raw Celsius value by 1 (1.8 °F per click, the nickustinov#137 class of bug). - Auto-mode range labels widen to 32 pt to fit half-degree strings, with the mode buttons at 34 pt to keep the row inside its 260 pt budget. Tests: 1,023 passing (987 before), 36 added, including mutation-verified regression tests for the AC Fahrenheit fix, metadata codable round trips, grid stepping and formatting tables, HA unit scaling, and real label-text assertions through the menu item views. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RGy77ui93iHqVnNLtrVWF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #60, and covers the Eve Thermo case from #102.
What this does
Temperature setpoints (thermostat target, heater-cooler heating and cooling thresholds, and Home Assistant climate targets) now step and display in the increment the device actually advertises, typically 0.5 °C, instead of hardcoded whole degrees. A 21.5° setpoint set from Apple Home finally reads 21.5° rather than 22°, and the ± steppers can reach it.
It is metadata-driven, so it adapts per device: a 0.5° radiator steps by 0.5°, and a device that only reports whole degrees is completely unchanged.
In Celsius mode, a heat-mode setpoint of 21.5° now displays
21.5°(previously22°), one+click snaps it to22°, and an Auto-mode range of 20.5° / 24.5° shows both halves in the widened labels. Fahrenheit is deliberately untouched: the same 21.5 °C setpoint still reads71°and still steps one displayed degree per click (the #137 behaviour). Happy to attach rendered screenshots if useful.How it works
ServiceDatacarriesstep/min/maxfor the target temperature and both thresholds, following the existingrotationSpeedMin/MaxandcolorTemperatureMin/Maxprecedent. On HomeKit they come fromHMCharacteristicMetadata(stepValue/minimumValue/maximumValue); on Home Assistant fromtarget_temp_step/min_temp/max_temp. HA values are normalized to internal Celsius, and because the step is a delta it scales by 5/9 without the freezing-point offset on Fahrenheit servers.TemperatureFormatter.uiSteprounds the advertised step up to the nearest 0.5 °C. HomeKit's spec default step is 0.1 °C, which is unusable one click at a time, so 0.5 is the floor. Missing metadata falls back to 1.0, i.e. no behaviour change.stepis untouched.formatSetpointshows one decimal only when the value is fractional (21°vs21.5°); the existing whole-degreeformatand itsceilare left exactly as they are, so sensor readouts and Fahrenheit are unaffected.ACMenuItemstepped the raw Celsius value by 1 (1.8 °F per click), the same class of bug as [Bug] Changing Temperature Skips from 72 to 70 #137 but never fixed for heater-coolers. It now goes throughTemperatureFormatter.steplike the other climate items, so Fahrenheit AC stepping moves one displayed degree.Tests
The suite goes from 987 to 1023 (36 added), all green on
xcodebuild test -scheme Itsyhome -destination "platform=macOS". Coverage includes theuiStepderivation table, Celsius grid-stepping and float-noise cases,formatSetpointwhole/half/negative, HA unit scaling,ServiceDatacodable round trips and legacy-JSON decode, and real label-text assertions through the menu-item views. The AC Fahrenheit fix and the new threshold-clamp behaviour are pinned with mutation-verified regression tests (reverting the fix makes them fail).The three existing #137 Fahrenheit regression tests are byte-identical and still pass.
Notes
HAClimateMenuItemintentionally keeps its trailing margin, so its Auto layout differs slightly from the HomeKit items; noted in a comment.EntityMappergenerateSceneActions), so on Fahrenheit servers the scene value is in °F while everything else is Celsius. Happy to send that as a separate PR.🤖 Generated with Claude Code
https://claude.ai/code/session_018RGy77ui93iHqVnNLtrVWF