Add unit_of_measurement to climate and water_heater#168747
Add unit_of_measurement to climate and water_heater#168747jhenkens wants to merge 12 commits intohome-assistant:devfrom
Conversation
(cherry picked from commit 82dec48)
|
Hey there @jesserockz, @kbx81, @bdraco, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
There was a problem hiding this comment.
Pull request overview
This PR updates the ESPHome integration’s climate and water_heater entities to expose the temperature unit_of_measurement from the device’s static info, enabling native Fahrenheit (and other units) end-to-end.
Changes:
- Add
TemperatureUnit→UnitOfTemperaturemapping for ESPHome climate entities. - Add
TemperatureUnit→UnitOfTemperaturemapping for ESPHome water_heater entities. - Set
_attr_temperature_unitfrom ESPHome static info during entity info updates.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
homeassistant/components/esphome/climate.py |
Maps ESPHome-reported temperature units onto HA’s climate entity unit handling. |
homeassistant/components/esphome/water_heater.py |
Maps ESPHome-reported temperature units onto HA’s water heater entity unit handling. |
| _WATER_HEATER_TEMPERATURE_UNIT_MAP: dict[TemperatureUnit, UnitOfTemperature] = { | ||
| TemperatureUnit.CELSIUS: UnitOfTemperature.CELSIUS, | ||
| TemperatureUnit.FAHRENHEIT: UnitOfTemperature.FAHRENHEIT, | ||
| TemperatureUnit.KELVIN: UnitOfTemperature.KELVIN, | ||
| } |
There was a problem hiding this comment.
Deduplicate the TemperatureUnit→UnitOfTemperature mapping by reusing a shared constant (instead of defining a second map here) to keep behavior consistent across ESPHome platforms.
| self._attr_temperature_unit = _CLIMATE_TEMPERATURE_UNIT_MAP[ | ||
| static_info.temperature_unit | ||
| ] |
There was a problem hiding this comment.
Add unit tests that validate the entity’s temperature unit is set from the ESPHome static info (e.g., Fahrenheit) and that service calls/state attributes behave correctly with that unit.
| self._attr_temperature_unit = _WATER_HEATER_TEMPERATURE_UNIT_MAP[ | ||
| static_info.temperature_unit | ||
| ] |
There was a problem hiding this comment.
Add unit tests that validate the water heater’s temperature unit is set from the ESPHome static info (e.g., Fahrenheit) and that min/max/step and service calls are interpreted in that unit.
| _CLIMATE_TEMPERATURE_UNIT_MAP: dict[TemperatureUnit, UnitOfTemperature] = { | ||
| TemperatureUnit.CELSIUS: UnitOfTemperature.CELSIUS, | ||
| TemperatureUnit.FAHRENHEIT: UnitOfTemperature.FAHRENHEIT, | ||
| TemperatureUnit.KELVIN: UnitOfTemperature.KELVIN, | ||
| } |
There was a problem hiding this comment.
Deduplicate the TemperatureUnit→UnitOfTemperature mapping by moving it to a shared constant (e.g., in the ESPHome integration module) so climate and water_heater can’t drift in behavior over time.
|
Would be good to do a separate PR to bump aioesphomeapi first |
|
| self._feature_flags = ClimateFeature( | ||
| static_info.supported_feature_flags_compat(self._api_version) | ||
| ) | ||
| self._attr_temperature_unit = TEMPERATURE_UNIT_MAP[static_info.temperature_unit] |
There was a problem hiding this comment.
Add test coverage that sets temperature_unit in ClimateInfo (e.g., Fahrenheit) and asserts the entity reports the correct temperature unit and that service calls pass the raw temperature values without unintended conversion.
| """Set attrs from static info.""" | ||
| super()._on_static_info_update(static_info) | ||
| static_info = self._static_info | ||
| self._attr_temperature_unit = TEMPERATURE_UNIT_MAP[static_info.temperature_unit] |
There was a problem hiding this comment.
Add test coverage that sets temperature_unit in WaterHeaterInfo (e.g., Fahrenheit) and asserts the entity exposes the correct temperature unit and that async_set_temperature forwards the intended value in that unit.
Co-authored-by: J. Nick Koston <nick+github@koston.org>
| """Set attrs from static info.""" | ||
| super()._on_static_info_update(static_info) | ||
| static_info = self._static_info | ||
| self._attr_temperature_unit = TEMPERATURE_UNIT_MAP.get(static_info.temperature_unit, UnitOfTemperature.CELSIUS) |
There was a problem hiding this comment.
Import UnitOfTemperature (or avoid referencing it) so _on_static_info_update doesn’t raise NameError when setting _attr_temperature_unit.
|
Retested this change with my custom build of ESPHome - easier now that aioesphomeapi is merged - and can confirm this still works as desired. |
…-to-climate-and-water-heater
…and-water-heater' into add-temperature-unit-to-climate-and-water-heater
| ( | ||
| 3, | ||
| UnitOfTemperature.CELSIUS, | ||
| ), # unknown value maps to Celsius via aioesphomeapi |
| ( | ||
| 3, | ||
| UnitOfTemperature.CELSIUS, | ||
| ), # unknown value maps to Celsius via aioesphomeapi |
Breaking change
Proposed change
Exposes temperature unit for climate and water_heater, with corresponding changes in home-assistant/core, aioesphome, esphome, and esphome-docs, to enable native Fahrenheit measurements on those entities. Usecase is to enable accurate temperature settings on a Fahrenheit hot tub, controlled via RS485-UART. Rather than round tripped from F -> C -> C, with various floating point errors and weirdnesses, this just makes it stay F the entire way and work much more reliably.
Tests still need to be added where appropriate - that's on the todo - but the code has been validated.
When esphome is updated, but core is not, as long as you do not set the temperature unit on a climate/water heater, everything works the same as it currently is. If you do set it, you will convert from F -> "F", as home assistant will think the incoming value from ESPHome is C, without reading the UOM. If ESPHome does not have F specified, it continues to default to C.
When HA is updated, but ESPHome is on an old version, it maintains legacy behavior of treating all climate/water_heaters as using C.
There are still some todo's, namely adding tests in every repo, and some other PR workitems, but the code is working and ready for early review.
Type of change
Additional information
esphome/aioesphomeapi#1600
esphome/esphome#15815
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: