mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 07:25:52 -05:00
Fix ZHA climate hvac_action for Centralite thermostat (#35993)
* Centralite specific control seq of operation * Remove Fan safeguards * Split hvac_action property. * Refactor hvac_action property. Current hvac_action logic is Zen Within thermostat specific and differs a bit from ZCL specs. Implement it as a separate class. * Refactor hvac_action property for default thermostat Follow more closely ZCL specs in parsing hvac state of the thermostat.
This commit is contained in:
@@ -89,7 +89,22 @@ CLIMATE_SINOPE = {
|
||||
"profile_id": 260,
|
||||
},
|
||||
}
|
||||
SINOPE = "Sinope Technologies"
|
||||
|
||||
CLIMATE_ZEN = {
|
||||
1: {
|
||||
"device_type": zigpy.profiles.zha.DeviceType.THERMOSTAT,
|
||||
"in_clusters": [
|
||||
zigpy.zcl.clusters.general.Basic.cluster_id,
|
||||
zigpy.zcl.clusters.general.Identify.cluster_id,
|
||||
zigpy.zcl.clusters.hvac.Fan.cluster_id,
|
||||
zigpy.zcl.clusters.hvac.Thermostat.cluster_id,
|
||||
zigpy.zcl.clusters.hvac.UserInterface.cluster_id,
|
||||
],
|
||||
"out_clusters": [zigpy.zcl.clusters.general.Ota.cluster_id],
|
||||
}
|
||||
}
|
||||
MANUF_SINOPE = "Sinope Technologies"
|
||||
MANUF_ZEN = "Zen Within"
|
||||
|
||||
ZCL_ATTR_PLUG = {
|
||||
"abs_min_heat_setpoint_limit": 800,
|
||||
@@ -169,7 +184,14 @@ async def device_climate_fan(device_climate_mock):
|
||||
async def device_climate_sinope(device_climate_mock):
|
||||
"""Sinope thermostat."""
|
||||
|
||||
return await device_climate_mock(CLIMATE_SINOPE, manuf=SINOPE)
|
||||
return await device_climate_mock(CLIMATE_SINOPE, manuf=MANUF_SINOPE)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def device_climate_zen(device_climate_mock):
|
||||
"""Zen Within thermostat."""
|
||||
|
||||
return await device_climate_mock(CLIMATE_ZEN, manuf=MANUF_ZEN)
|
||||
|
||||
|
||||
def test_sequence_mappings():
|
||||
@@ -201,6 +223,52 @@ async def test_climate_hvac_action_running_state(hass, device_climate):
|
||||
thrm_cluster = device_climate.device.endpoints[1].thermostat
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x001E: Thermostat.RunningMode.Off}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x001C: Thermostat.SystemMode.Auto}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x001E: Thermostat.RunningMode.Cool}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_COOL
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x001E: Thermostat.RunningMode.Heat}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_HEAT
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x001E: Thermostat.RunningMode.Off}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||
|
||||
await send_attributes_report(
|
||||
hass, thrm_cluster, {0x0029: Thermostat.RunningState.Fan_State_On}
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_FAN
|
||||
|
||||
|
||||
async def test_climate_hvac_action_running_state_zen(hass, device_climate_zen):
|
||||
"""Test Zen hvac action via running state."""
|
||||
|
||||
thrm_cluster = device_climate_zen.device.endpoints[1].thermostat
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate_zen, hass)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert ATTR_HVAC_ACTION not in state.attributes
|
||||
|
||||
@@ -266,7 +334,7 @@ async def test_climate_hvac_action_pi_demand(hass, device_climate):
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert ATTR_HVAC_ACTION not in state.attributes
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
|
||||
|
||||
await send_attributes_report(hass, thrm_cluster, {0x0007: 10})
|
||||
state = hass.states.get(entity_id)
|
||||
@@ -381,7 +449,7 @@ async def test_target_temperature(
|
||||
"unoccupied_heating_setpoint": 1600,
|
||||
"unoccupied_cooling_setpoint": 2700,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
if preset:
|
||||
@@ -417,7 +485,7 @@ async def test_target_temperature_high(
|
||||
"system_mode": Thermostat.SystemMode.Auto,
|
||||
"unoccupied_cooling_setpoint": unoccupied,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
if preset:
|
||||
@@ -453,7 +521,7 @@ async def test_target_temperature_low(
|
||||
"system_mode": Thermostat.SystemMode.Auto,
|
||||
"unoccupied_heating_setpoint": unoccupied,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
if preset:
|
||||
@@ -665,7 +733,7 @@ async def test_set_temperature_heat_cool(hass, device_climate_mock):
|
||||
"unoccupied_heating_setpoint": 1600,
|
||||
"unoccupied_cooling_setpoint": 2700,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
thrm_cluster = device_climate.device.endpoints[1].thermostat
|
||||
@@ -755,7 +823,7 @@ async def test_set_temperature_heat(hass, device_climate_mock):
|
||||
"unoccupied_heating_setpoint": 1600,
|
||||
"unoccupied_cooling_setpoint": 2700,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
thrm_cluster = device_climate.device.endpoints[1].thermostat
|
||||
@@ -838,7 +906,7 @@ async def test_set_temperature_cool(hass, device_climate_mock):
|
||||
"unoccupied_cooling_setpoint": 1600,
|
||||
"unoccupied_heating_setpoint": 2700,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
thrm_cluster = device_climate.device.endpoints[1].thermostat
|
||||
@@ -921,7 +989,7 @@ async def test_set_temperature_wrong_mode(hass, device_climate_mock):
|
||||
"unoccupied_cooling_setpoint": 1600,
|
||||
"unoccupied_heating_setpoint": 2700,
|
||||
},
|
||||
manuf=SINOPE,
|
||||
manuf=MANUF_SINOPE,
|
||||
)
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
thrm_cluster = device_climate.device.endpoints[1].thermostat
|
||||
@@ -1000,19 +1068,6 @@ async def test_fan_mode(hass, device_climate_fan):
|
||||
assert state.attributes[ATTR_FAN_MODE] == FAN_ON
|
||||
|
||||
|
||||
async def test_set_fan_mode_no_fan(hass, device_climate):
|
||||
"""Test setting fan mode on fun less climate."""
|
||||
|
||||
entity_id = await find_entity_id(DOMAIN, device_climate, hass)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_FAN_MODE,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_ON},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_set_fan_mode_not_supported(hass, device_climate_fan):
|
||||
"""Test fan setting unsupported mode."""
|
||||
|
||||
|
||||
@@ -3349,7 +3349,7 @@ DEVICES = [
|
||||
},
|
||||
("climate", "00:11:22:33:44:55:66:77-1"): {
|
||||
"channels": ["thermostat", "fan"],
|
||||
"entity_class": "Thermostat",
|
||||
"entity_class": "ZenWithinThermostat",
|
||||
"entity_id": "climate.zen_within_zen_01_77665544_fan_thermostat",
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user