Fix temperature setting for multi-setpoint z-wave device (#102395)
* Fix temperature setting for multi-setpoint z-wave device * Add missing fixture file * Apply suggestions from code review --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/102408/head
parent
3cfcffc6f2
commit
c7affa75d4
|
@ -259,9 +259,11 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
|
|||
def _current_mode_setpoint_enums(self) -> list[ThermostatSetpointType]:
|
||||
"""Return the list of enums that are relevant to the current thermostat mode."""
|
||||
if self._current_mode is None or self._current_mode.value is None:
|
||||
# Thermostat(valve) with no support for setting a mode
|
||||
# is considered heating-only
|
||||
return [ThermostatSetpointType.HEATING]
|
||||
# Thermostat with no support for setting a mode is just a setpoint
|
||||
if self.info.primary_value.property_key is None:
|
||||
return []
|
||||
return [ThermostatSetpointType(int(self.info.primary_value.property_key))]
|
||||
|
||||
return THERMOSTAT_MODE_SETPOINT_MAP.get(int(self._current_mode.value), [])
|
||||
|
||||
@property
|
||||
|
|
|
@ -662,6 +662,12 @@ def logic_group_zdb5100_state_fixture():
|
|||
return json.loads(load_fixture("zwave_js/logic_group_zdb5100_state.json"))
|
||||
|
||||
|
||||
@pytest.fixture(name="climate_intermatic_pe653_state", scope="session")
|
||||
def climate_intermatic_pe653_state_fixture():
|
||||
"""Load Intermatic PE653 Pool Control node state fixture data."""
|
||||
return json.loads(load_fixture("zwave_js/climate_intermatic_pe653_state.json"))
|
||||
|
||||
|
||||
# model fixtures
|
||||
|
||||
|
||||
|
@ -1290,3 +1296,11 @@ def logic_group_zdb5100_fixture(client, logic_group_zdb5100_state):
|
|||
node = Node(client, copy.deepcopy(logic_group_zdb5100_state))
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
return node
|
||||
|
||||
|
||||
@pytest.fixture(name="climate_intermatic_pe653")
|
||||
def climate_intermatic_pe653_fixture(client, climate_intermatic_pe653_state):
|
||||
"""Mock an Intermatic PE653 node."""
|
||||
node = Node(client, copy.deepcopy(climate_intermatic_pe653_state))
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
return node
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -792,3 +792,196 @@ async def test_thermostat_raise_repair_issue_and_warning_when_setting_fan_preset
|
|||
"Dry and Fan preset modes are deprecated and will be removed in Home Assistant 2024.2. Please use the corresponding Dry and Fan HVAC modes instead"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_multi_setpoint_thermostat(
|
||||
hass: HomeAssistant, client, climate_intermatic_pe653, integration
|
||||
) -> None:
|
||||
"""Test a thermostat with multiple setpoints."""
|
||||
node = climate_intermatic_pe653
|
||||
|
||||
heating_entity_id = "climate.pool_control_2"
|
||||
heating = hass.states.get(heating_entity_id)
|
||||
assert heating
|
||||
assert heating.state == HVACMode.HEAT
|
||||
assert heating.attributes[ATTR_TEMPERATURE] == 3.9
|
||||
assert heating.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT]
|
||||
assert (
|
||||
heating.attributes[ATTR_SUPPORTED_FEATURES]
|
||||
== ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
)
|
||||
|
||||
furnace_entity_id = "climate.pool_control"
|
||||
furnace = hass.states.get(furnace_entity_id)
|
||||
assert furnace
|
||||
assert furnace.state == HVACMode.HEAT
|
||||
assert furnace.attributes[ATTR_TEMPERATURE] == 15.6
|
||||
assert furnace.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT]
|
||||
assert (
|
||||
furnace.attributes[ATTR_SUPPORTED_FEATURES]
|
||||
== ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
)
|
||||
|
||||
client.async_send_command_no_wait.reset_mock()
|
||||
|
||||
# Test setting temperature of heating setpoint
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_TEMPERATURE,
|
||||
{
|
||||
ATTR_ENTITY_ID: heating_entity_id,
|
||||
ATTR_TEMPERATURE: 20.0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Test setting temperature of furnace setpoint
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_TEMPERATURE,
|
||||
{
|
||||
ATTR_ENTITY_ID: furnace_entity_id,
|
||||
ATTR_TEMPERATURE: 2.0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Test setting illegal mode raises an error
|
||||
with pytest.raises(ValueError):
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: heating_entity_id,
|
||||
ATTR_HVAC_MODE: HVACMode.COOL,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: furnace_entity_id,
|
||||
ATTR_HVAC_MODE: HVACMode.COOL,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# this is a no-op since there's no mode
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: heating_entity_id,
|
||||
ATTR_HVAC_MODE: HVACMode.HEAT,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# this is a no-op since there's no mode
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: furnace_entity_id,
|
||||
ATTR_HVAC_MODE: HVACMode.HEAT,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 2
|
||||
args = client.async_send_command.call_args_list[0][0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == 19
|
||||
assert args["valueId"] == {
|
||||
"endpoint": 1,
|
||||
"commandClass": 67,
|
||||
"property": "setpoint",
|
||||
"propertyKey": 1,
|
||||
}
|
||||
assert args["value"] == 68.0
|
||||
|
||||
args = client.async_send_command.call_args_list[1][0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == 19
|
||||
assert args["valueId"] == {
|
||||
"endpoint": 0,
|
||||
"commandClass": 67,
|
||||
"property": "setpoint",
|
||||
"propertyKey": 7,
|
||||
}
|
||||
assert args["value"] == 35.6
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
# Test heating setpoint value update from value updated event
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": 19,
|
||||
"args": {
|
||||
"commandClassName": "Thermostat Setpoint",
|
||||
"commandClass": 67,
|
||||
"endpoint": 1,
|
||||
"property": "setpoint",
|
||||
"propertyKey": 1,
|
||||
"propertyKeyName": "Heating",
|
||||
"propertyName": "setpoint",
|
||||
"newValue": 23,
|
||||
"prevValue": 21.5,
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
|
||||
state = hass.states.get(heating_entity_id)
|
||||
assert state
|
||||
assert state.state == HVACMode.HEAT
|
||||
assert state.attributes[ATTR_TEMPERATURE] == -5
|
||||
|
||||
# furnace not changed
|
||||
state = hass.states.get(furnace_entity_id)
|
||||
assert state
|
||||
assert state.state == HVACMode.HEAT
|
||||
assert state.attributes[ATTR_TEMPERATURE] == 15.6
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
# Test furnace setpoint value update from value updated event
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": 19,
|
||||
"args": {
|
||||
"commandClassName": "Thermostat Setpoint",
|
||||
"commandClass": 67,
|
||||
"endpoint": 0,
|
||||
"property": "setpoint",
|
||||
"propertyKey": 7,
|
||||
"propertyKeyName": "Furnace",
|
||||
"propertyName": "setpoint",
|
||||
"newValue": 68,
|
||||
"prevValue": 21.5,
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
|
||||
# heating not changed
|
||||
state = hass.states.get(heating_entity_id)
|
||||
assert state
|
||||
assert state.state == HVACMode.HEAT
|
||||
assert state.attributes[ATTR_TEMPERATURE] == -5
|
||||
|
||||
state = hass.states.get(furnace_entity_id)
|
||||
assert state
|
||||
assert state.state == HVACMode.HEAT
|
||||
assert state.attributes[ATTR_TEMPERATURE] == 20
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
|
Loading…
Reference in New Issue