Skip to content

Commit

Permalink
Handle alexa invalid climate temp adjustment (#99740)
Browse files Browse the repository at this point in the history
* Handle temp adjust when target state not set

* Update homeassistant/components/alexa/errors.py

Co-authored-by: Robert Resch <robert@resch.dev>

* black

---------

Co-authored-by: Robert Resch <robert@resch.dev>
  • Loading branch information
jbouwh and edenhaus committed Sep 6, 2023
1 parent 7a6c876 commit 7c7456d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 1 deletion.
7 changes: 7 additions & 0 deletions homeassistant/components/alexa/errors.py
Expand Up @@ -90,6 +90,13 @@ class AlexaUnsupportedThermostatModeError(AlexaError):
error_type = "UNSUPPORTED_THERMOSTAT_MODE"


class AlexaUnsupportedThermostatTargetStateError(AlexaError):
"""Class to represent unsupported climate target state error."""

namespace = "Alexa.ThermostatController"
error_type = "INVALID_TARGET_STATE"


class AlexaTempRangeError(AlexaError):
"""Class to represent TempRange errors."""

Expand Down
9 changes: 8 additions & 1 deletion homeassistant/components/alexa/handlers.py
Expand Up @@ -73,6 +73,7 @@
AlexaSecurityPanelAuthorizationRequired,
AlexaTempRangeError,
AlexaUnsupportedThermostatModeError,
AlexaUnsupportedThermostatTargetStateError,
AlexaVideoActionNotPermittedForContentError,
)
from .state_report import AlexaDirective, AlexaResponse, async_enable_proactive_mode
Expand Down Expand Up @@ -911,7 +912,13 @@ async def async_api_adjust_target_temp(
}
)
else:
target_temp = float(entity.attributes[ATTR_TEMPERATURE]) + temp_delta
current_target_temp: str | None = entity.attributes.get(ATTR_TEMPERATURE)
if current_target_temp is None:
raise AlexaUnsupportedThermostatTargetStateError(
"The current target temperature is not set, "
"cannot adjust target temperature"
)
target_temp = float(current_target_temp) + temp_delta

if target_temp < min_temp or target_temp > max_temp:
raise AlexaTempRangeError(hass, target_temp, min_temp, max_temp)
Expand Down
69 changes: 69 additions & 0 deletions tests/components/alexa/test_smart_home.py
Expand Up @@ -2471,6 +2471,75 @@ async def test_thermostat(hass: HomeAssistant) -> None:
assert call.data["preset_mode"] == "eco"


async def test_no_current_target_temp_adjusting_temp(hass: HomeAssistant) -> None:
"""Test thermostat adjusting temp with no initial target temperature."""
hass.config.units = US_CUSTOMARY_SYSTEM
device = (
"climate.test_thermostat",
"cool",
{
"temperature": None,
"target_temp_high": None,
"target_temp_low": None,
"current_temperature": 75.0,
"friendly_name": "Test Thermostat",
"supported_features": 1 | 2 | 4 | 128,
"hvac_modes": ["off", "heat", "cool", "auto", "dry", "fan_only"],
"preset_mode": None,
"preset_modes": ["eco"],
"min_temp": 50,
"max_temp": 90,
},
)
appliance = await discovery_test(device, hass)

assert appliance["endpointId"] == "climate#test_thermostat"
assert appliance["displayCategories"][0] == "THERMOSTAT"
assert appliance["friendlyName"] == "Test Thermostat"

capabilities = assert_endpoint_capabilities(
appliance,
"Alexa.PowerController",
"Alexa.ThermostatController",
"Alexa.TemperatureSensor",
"Alexa.EndpointHealth",
"Alexa",
)

properties = await reported_properties(hass, "climate#test_thermostat")
properties.assert_equal("Alexa.ThermostatController", "thermostatMode", "COOL")
properties.assert_not_has_property(
"Alexa.ThermostatController",
"targetSetpoint",
)
properties.assert_equal(
"Alexa.TemperatureSensor", "temperature", {"value": 75.0, "scale": "FAHRENHEIT"}
)

thermostat_capability = get_capability(capabilities, "Alexa.ThermostatController")
assert thermostat_capability is not None
configuration = thermostat_capability["configuration"]
assert configuration["supportsScheduling"] is False

supported_modes = ["OFF", "HEAT", "COOL", "AUTO", "ECO", "CUSTOM"]
for mode in supported_modes:
assert mode in configuration["supportedModes"]

# Adjust temperature where target temp is not set
msg = await assert_request_fails(
"Alexa.ThermostatController",
"AdjustTargetTemperature",
"climate#test_thermostat",
"climate.set_temperature",
hass,
payload={"targetSetpointDelta": {"value": -5.0, "scale": "KELVIN"}},
)
assert msg["event"]["payload"]["type"] == "INVALID_TARGET_STATE"
assert msg["event"]["payload"]["message"] == (
"The current target temperature is not set, cannot adjust target temperature"
)


async def test_thermostat_dual(hass: HomeAssistant) -> None:
"""Test thermostat discovery with auto mode, with upper and lower target temperatures."""
hass.config.units = US_CUSTOMARY_SYSTEM
Expand Down

0 comments on commit 7c7456d

Please sign in to comment.