Name the two ZhongHong fan speeds the climate component does not (#182075)

This commit is contained in:
ruohan.chen
2026-09-14 16:09:57 +02:00
committed by GitHub
parent 9fedf1e252
commit 3e18e6c5d9
3 changed files with 85 additions and 1 deletions
@@ -186,6 +186,9 @@ class ZhongHongClimate(CoordinatorEntity[ZhongHongCoordinator], ClimateEntity):
)
_attr_target_temperature_step = 1
_attr_temperature_unit = UnitOfTemperature.CELSIUS
# Two of the five speeds the gateway addresses have no name of their own in
# the climate component, so they are named here.
_attr_translation_key = "air_conditioner"
def __init__(
self,
@@ -24,6 +24,20 @@
}
}
},
"entity": {
"climate": {
"air_conditioner": {
"state_attributes": {
"fan_mode": {
"state": {
"medium_high": "Medium high",
"medium_low": "Medium low"
}
}
}
}
}
},
"exceptions": {
"cannot_connect": {
"message": "Failed to connect to the ZhongHong gateway at {host}."
+68 -1
View File
@@ -12,7 +12,9 @@ from homeassistant.components.climate import (
ATTR_FAN_MODES,
ATTR_HVAC_MODE,
DOMAIN as CLIMATE_DOMAIN,
FAN_HIGH,
FAN_LOW,
FAN_MIDDLE,
SERVICE_SET_FAN_MODE,
SERVICE_SET_HVAC_MODE,
SERVICE_SET_TEMPERATURE,
@@ -20,7 +22,12 @@ from homeassistant.components.climate import (
SERVICE_TURN_ON,
HVACMode,
)
from homeassistant.components.zhong_hong.const import ALL_FAN_MODES, FAN_MEDIUM_HIGH
from homeassistant.components.zhong_hong.const import (
ALL_FAN_MODES,
DOMAIN,
FAN_MEDIUM_HIGH,
FAN_MEDIUM_LOW,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_TEMPERATURE,
@@ -31,6 +38,7 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.translation import async_get_translations
from . import setup_integration
from .conftest import DEVICE_ADDRESS, ENTITY_ID, FakeGateway, build_status
@@ -385,3 +393,62 @@ async def test_device_address_is_used_for_the_entity(
assert hass.states.get(ENTITY_ID) is not None
assert hass.states.get("climate.ac_1_2") is not None
async def test_every_fan_mode_has_a_name(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_gateway: FakeGateway,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test every speed the entity offers is named in the interface.
The climate component names three of the five speeds the gateway can
address. The other two have to be named here, or they reach the user as
the keys themselves.
"""
await setup_integration(hass, mock_config_entry)
state = hass.states.get(ENTITY_ID)
assert state
entry = entity_registry.async_get(ENTITY_ID)
assert entry
# Asked for one integration at a time, these come back as the cache itself
# rather than a copy of it, so neither is merged into the other.
named_by_component = await async_get_translations(
hass, "en", "entity_component", [CLIMATE_DOMAIN]
)
named_here = await async_get_translations(hass, "en", "entity", [DOMAIN])
by_component = (
f"component.{CLIMATE_DOMAIN}.entity_component._"
".state_attributes.fan_mode.state."
)
by_integration = (
f"component.{DOMAIN}.entity.climate.{entry.translation_key}"
".state_attributes.fan_mode.state."
)
fan_modes = state.attributes[ATTR_FAN_MODES]
assert fan_modes == ALL_FAN_MODES
# The two the component has no name for are named here, and only those
# two: the others are left to it, which is what lets them keep the names
# it gives them.
assert {mode: named_here.get(f"{by_integration}{mode}") for mode in fan_modes} == {
FAN_LOW: None,
FAN_MEDIUM_LOW: "Medium low",
FAN_MIDDLE: None,
FAN_MEDIUM_HIGH: "Medium high",
FAN_HIGH: None,
}
assert {
mode: named_by_component.get(f"{by_component}{mode}") for mode in fan_modes
} == {
FAN_LOW: "Low",
FAN_MEDIUM_LOW: None,
FAN_MIDDLE: "Middle",
FAN_MEDIUM_HIGH: None,
FAN_HIGH: "High",
}