diff --git a/homeassistant/components/alexa/capabilities.py b/homeassistant/components/alexa/capabilities.py index 0856c39946b..955502c8149 100644 --- a/homeassistant/components/alexa/capabilities.py +++ b/homeassistant/components/alexa/capabilities.py @@ -19,6 +19,7 @@ from homeassistant.components import ( number, timer, vacuum, + water_heater, ) from homeassistant.components.alarm_control_panel import ( AlarmControlPanelEntityFeature, @@ -435,7 +436,8 @@ class AlexaPowerController(AlexaCapability): is_on = self.entity.state == vacuum.STATE_CLEANING elif self.entity.domain == timer.DOMAIN: is_on = self.entity.state != STATE_IDLE - + elif self.entity.domain == water_heater.DOMAIN: + is_on = self.entity.state not in (STATE_OFF, STATE_UNKNOWN) else: is_on = self.entity.state != STATE_OFF @@ -938,6 +940,9 @@ class AlexaTemperatureSensor(AlexaCapability): if self.entity.domain == climate.DOMAIN: unit = self.hass.config.units.temperature_unit temp = self.entity.attributes.get(climate.ATTR_CURRENT_TEMPERATURE) + elif self.entity.domain == water_heater.DOMAIN: + unit = self.hass.config.units.temperature_unit + temp = self.entity.attributes.get(water_heater.ATTR_CURRENT_TEMPERATURE) if temp is None or temp in (STATE_UNAVAILABLE, STATE_UNKNOWN): return None @@ -1108,6 +1113,8 @@ class AlexaThermostatController(AlexaCapability): supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE: properties.append({"name": "targetSetpoint"}) + if supported & water_heater.WaterHeaterEntityFeature.TARGET_TEMPERATURE: + properties.append({"name": "targetSetpoint"}) if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE: properties.append({"name": "lowerSetpoint"}) properties.append({"name": "upperSetpoint"}) @@ -1127,6 +1134,8 @@ class AlexaThermostatController(AlexaCapability): return None if name == "thermostatMode": + if self.entity.domain == water_heater.DOMAIN: + return None preset = self.entity.attributes.get(climate.ATTR_PRESET_MODE) mode: dict[str, str] | str | None @@ -1176,9 +1185,13 @@ class AlexaThermostatController(AlexaCapability): ThermostatMode Values. ThermostatMode Value must be AUTO, COOL, HEAT, ECO, OFF, or CUSTOM. + Water heater devices do not return thermostat modes. """ + if self.entity.domain == water_heater.DOMAIN: + return None + supported_modes: list[str] = [] - hvac_modes = self.entity.attributes[climate.ATTR_HVAC_MODES] + hvac_modes = self.entity.attributes.get(climate.ATTR_HVAC_MODES, []) for mode in hvac_modes: if thermostat_mode := API_THERMOSTAT_MODES.get(mode): supported_modes.append(thermostat_mode) @@ -1408,6 +1421,16 @@ class AlexaModeController(AlexaCapability): if mode in self.entity.attributes.get(humidifier.ATTR_AVAILABLE_MODES, []): return f"{humidifier.ATTR_MODE}.{mode}" + # Water heater operation mode + if self.instance == f"{water_heater.DOMAIN}.{water_heater.ATTR_OPERATION_MODE}": + operation_mode = self.entity.attributes.get( + water_heater.ATTR_OPERATION_MODE, None + ) + if operation_mode in self.entity.attributes.get( + water_heater.ATTR_OPERATION_LIST, [] + ): + return f"{water_heater.ATTR_OPERATION_MODE}.{operation_mode}" + # Cover Position if self.instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}": # Return state instead of position when using ModeController. @@ -1478,6 +1501,26 @@ class AlexaModeController(AlexaCapability): ) return self._resource.serialize_capability_resources() + # Water heater operation modes + if self.instance == f"{water_heater.DOMAIN}.{water_heater.ATTR_OPERATION_MODE}": + self._resource = AlexaModeResource([AlexaGlobalCatalog.SETTING_MODE], False) + operation_modes = self.entity.attributes.get( + water_heater.ATTR_OPERATION_LIST, [] + ) + for operation_mode in operation_modes: + self._resource.add_mode( + f"{water_heater.ATTR_OPERATION_MODE}.{operation_mode}", + [operation_mode], + ) + # Devices with a single mode completely break Alexa discovery, + # add a fake preset (see issue #53832). + if len(operation_modes) == 1: + self._resource.add_mode( + f"{water_heater.ATTR_OPERATION_MODE}.{PRESET_MODE_NA}", + [PRESET_MODE_NA], + ) + return self._resource.serialize_capability_resources() + # Cover Position Resources if self.instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}": self._resource = AlexaModeResource( diff --git a/homeassistant/components/alexa/entities.py b/homeassistant/components/alexa/entities.py index da0bd8b36aa..2f89058514b 100644 --- a/homeassistant/components/alexa/entities.py +++ b/homeassistant/components/alexa/entities.py @@ -32,6 +32,7 @@ from homeassistant.components import ( switch, timer, vacuum, + water_heater, ) from homeassistant.const import ( ATTR_DEVICE_CLASS, @@ -248,6 +249,9 @@ class DisplayCategory: # Indicates a vacuum cleaner. VACUUM_CLEANER = "VACUUM_CLEANER" + # Indicates a water heater. + WATER_HEATER = "WATER_HEATER" + # Indicates a network-connected wearable device, such as an Apple Watch, # Fitbit, or Samsung Gear. WEARABLE = "WEARABLE" @@ -456,23 +460,46 @@ class ButtonCapabilities(AlexaEntity): @ENTITY_ADAPTERS.register(climate.DOMAIN) +@ENTITY_ADAPTERS.register(water_heater.DOMAIN) class ClimateCapabilities(AlexaEntity): """Class to represent Climate capabilities.""" def default_display_categories(self) -> list[str]: """Return the display categories for this entity.""" + if self.entity.domain == water_heater.DOMAIN: + return [DisplayCategory.WATER_HEATER] return [DisplayCategory.THERMOSTAT] def interfaces(self) -> Generator[AlexaCapability, None, None]: """Yield the supported interfaces.""" # If we support two modes, one being off, we allow turning on too. - if climate.HVACMode.OFF in self.entity.attributes.get( - climate.ATTR_HVAC_MODES, [] + supported_features = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + if ( + self.entity.domain == climate.DOMAIN + and climate.HVACMode.OFF + in self.entity.attributes.get(climate.ATTR_HVAC_MODES, []) + or self.entity.domain == water_heater.DOMAIN + and (supported_features & water_heater.WaterHeaterEntityFeature.ON_OFF) ): yield AlexaPowerController(self.entity) - yield AlexaThermostatController(self.hass, self.entity) - yield AlexaTemperatureSensor(self.hass, self.entity) + if ( + self.entity.domain == climate.DOMAIN + or self.entity.domain == water_heater.DOMAIN + and ( + supported_features + & water_heater.WaterHeaterEntityFeature.OPERATION_MODE + ) + ): + yield AlexaThermostatController(self.hass, self.entity) + yield AlexaTemperatureSensor(self.hass, self.entity) + if self.entity.domain == water_heater.DOMAIN and ( + supported_features & water_heater.WaterHeaterEntityFeature.OPERATION_MODE + ): + yield AlexaModeController( + self.entity, + instance=f"{water_heater.DOMAIN}.{water_heater.ATTR_OPERATION_MODE}", + ) yield AlexaEndpointHealth(self.hass, self.entity) yield Alexa(self.entity) diff --git a/homeassistant/components/alexa/handlers.py b/homeassistant/components/alexa/handlers.py index 2796c10795b..8e81cf1a2c6 100644 --- a/homeassistant/components/alexa/handlers.py +++ b/homeassistant/components/alexa/handlers.py @@ -22,6 +22,7 @@ from homeassistant.components import ( number, timer, vacuum, + water_heater, ) from homeassistant.const import ( ATTR_ENTITY_ID, @@ -80,6 +81,23 @@ from .state_report import AlexaDirective, AlexaResponse, async_enable_proactive_ _LOGGER = logging.getLogger(__name__) DIRECTIVE_NOT_SUPPORTED = "Entity does not support directive" + +MIN_MAX_TEMP = { + climate.DOMAIN: { + "min_temp": climate.ATTR_MIN_TEMP, + "max_temp": climate.ATTR_MAX_TEMP, + }, + water_heater.DOMAIN: { + "min_temp": water_heater.ATTR_MIN_TEMP, + "max_temp": water_heater.ATTR_MAX_TEMP, + }, +} + +SERVICE_SET_TEMPERATURE = { + climate.DOMAIN: climate.SERVICE_SET_TEMPERATURE, + water_heater.DOMAIN: water_heater.SERVICE_SET_TEMPERATURE, +} + HANDLERS: Registry[ tuple[str, str], Callable[ @@ -804,8 +822,10 @@ async def async_api_set_target_temp( ) -> AlexaResponse: """Process a set target temperature request.""" entity = directive.entity - min_temp = entity.attributes[climate.ATTR_MIN_TEMP] - max_temp = entity.attributes[climate.ATTR_MAX_TEMP] + domain = entity.domain + + min_temp = entity.attributes[MIN_MAX_TEMP[domain]["min_temp"]] + max_temp = entity.attributes["max_temp"] unit = hass.config.units.temperature_unit data: dict[str, Any] = {ATTR_ENTITY_ID: entity.entity_id} @@ -849,9 +869,11 @@ async def async_api_set_target_temp( } ) + service = SERVICE_SET_TEMPERATURE[domain] + await hass.services.async_call( entity.domain, - climate.SERVICE_SET_TEMPERATURE, + service, data, blocking=False, context=context, @@ -867,11 +889,12 @@ async def async_api_adjust_target_temp( directive: AlexaDirective, context: ha.Context, ) -> AlexaResponse: - """Process an adjust target temperature request.""" + """Process an adjust target temperature request for climates and water heaters.""" data: dict[str, Any] entity = directive.entity - min_temp = entity.attributes[climate.ATTR_MIN_TEMP] - max_temp = entity.attributes[climate.ATTR_MAX_TEMP] + domain = entity.domain + min_temp = entity.attributes[MIN_MAX_TEMP[domain]["min_temp"]] + max_temp = entity.attributes[MIN_MAX_TEMP[domain]["max_temp"]] unit = hass.config.units.temperature_unit temp_delta = temperature_from_object( @@ -932,9 +955,11 @@ async def async_api_adjust_target_temp( } ) + service = SERVICE_SET_TEMPERATURE[domain] + await hass.services.async_call( entity.domain, - climate.SERVICE_SET_TEMPERATURE, + service, data, blocking=False, context=context, @@ -1163,6 +1188,23 @@ async def async_api_set_mode( msg = f"Entity '{entity.entity_id}' does not support Mode '{mode}'" raise AlexaInvalidValueError(msg) + # Water heater operation mode + elif instance == f"{water_heater.DOMAIN}.{water_heater.ATTR_OPERATION_MODE}": + operation_mode = mode.split(".")[1] + operation_modes: list[str] | None = entity.attributes.get( + water_heater.ATTR_OPERATION_LIST + ) + if ( + operation_mode != PRESET_MODE_NA + and operation_modes + and operation_mode in operation_modes + ): + service = water_heater.SERVICE_SET_OPERATION_MODE + data[water_heater.ATTR_OPERATION_MODE] = operation_mode + else: + msg = f"Entity '{entity.entity_id}' does not support Operation mode '{operation_mode}'" + raise AlexaInvalidValueError(msg) + # Cover Position elif instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}": position = mode.split(".")[1] diff --git a/tests/components/alexa/test_capabilities.py b/tests/components/alexa/test_capabilities.py index 11e39c40cb1..7c39e34ac38 100644 --- a/tests/components/alexa/test_capabilities.py +++ b/tests/components/alexa/test_capabilities.py @@ -8,6 +8,13 @@ from homeassistant.components.alexa import smart_home from homeassistant.components.climate import ATTR_CURRENT_TEMPERATURE, HVACMode from homeassistant.components.lock import STATE_JAMMED, STATE_LOCKING, STATE_UNLOCKING from homeassistant.components.media_player import MediaPlayerEntityFeature +from homeassistant.components.water_heater import ( + ATTR_OPERATION_LIST, + ATTR_OPERATION_MODE, + STATE_ECO, + STATE_GAS, + STATE_HEAT_PUMP, +) from homeassistant.const import ( ATTR_UNIT_OF_MEASUREMENT, STATE_ALARM_ARMED_AWAY, @@ -16,6 +23,7 @@ from homeassistant.const import ( STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_LOCKED, + STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN, STATE_UNLOCKED, @@ -777,6 +785,96 @@ async def test_report_climate_state(hass: HomeAssistant) -> None: assert msg["event"]["payload"]["type"] == "INTERNAL_ERROR" +async def test_report_water_heater_state(hass: HomeAssistant) -> None: + """Test ThermostatController also reports state correctly for water heaters.""" + for operation_mode in (STATE_ECO, STATE_GAS, STATE_HEAT_PUMP): + hass.states.async_set( + "water_heater.boyler", + operation_mode, + { + "friendly_name": "Boyler", + "supported_features": 11, + ATTR_CURRENT_TEMPERATURE: 34, + ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS, + ATTR_OPERATION_LIST: [STATE_ECO, STATE_GAS, STATE_HEAT_PUMP], + ATTR_OPERATION_MODE: operation_mode, + }, + ) + properties = await reported_properties(hass, "water_heater.boyler") + properties.assert_not_has_property( + "Alexa.ThermostatController", "thermostatMode" + ) + properties.assert_equal( + "Alexa.ModeController", "mode", f"operation_mode.{operation_mode}" + ) + properties.assert_equal( + "Alexa.TemperatureSensor", + "temperature", + {"value": 34.0, "scale": "CELSIUS"}, + ) + + for off_mode in [STATE_OFF]: + hass.states.async_set( + "water_heater.boyler", + off_mode, + { + "friendly_name": "Boyler", + "supported_features": 11, + ATTR_CURRENT_TEMPERATURE: 34, + ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS, + }, + ) + properties = await reported_properties(hass, "water_heater.boyler") + properties.assert_not_has_property( + "Alexa.ThermostatController", "thermostatMode" + ) + properties.assert_not_has_property("Alexa.ModeController", "mode") + properties.assert_equal( + "Alexa.TemperatureSensor", + "temperature", + {"value": 34.0, "scale": "CELSIUS"}, + ) + + for state in "unavailable", "unknown": + hass.states.async_set( + f"water_heater.{state}", + state, + {"friendly_name": f"Boyler {state}", "supported_features": 11}, + ) + properties = await reported_properties(hass, f"water_heater.{state}") + properties.assert_not_has_property( + "Alexa.ThermostatController", "thermostatMode" + ) + properties.assert_not_has_property("Alexa.ModeController", "mode") + + +async def test_report_singe_mode_water_heater(hass: HomeAssistant) -> None: + """Test ThermostatController also reports state correctly for water heaters.""" + operation_mode = STATE_ECO + hass.states.async_set( + "water_heater.boyler", + operation_mode, + { + "friendly_name": "Boyler", + "supported_features": 11, + ATTR_CURRENT_TEMPERATURE: 34, + ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS, + ATTR_OPERATION_LIST: [STATE_ECO], + ATTR_OPERATION_MODE: operation_mode, + }, + ) + properties = await reported_properties(hass, "water_heater.boyler") + properties.assert_not_has_property("Alexa.ThermostatController", "thermostatMode") + properties.assert_equal( + "Alexa.ModeController", "mode", f"operation_mode.{operation_mode}" + ) + properties.assert_equal( + "Alexa.TemperatureSensor", + "temperature", + {"value": 34.0, "scale": "CELSIUS"}, + ) + + async def test_temperature_sensor_sensor(hass: HomeAssistant) -> None: """Test TemperatureSensor reports sensor temperature correctly.""" for bad_value in (STATE_UNKNOWN, STATE_UNAVAILABLE, "not-number"): @@ -823,6 +921,29 @@ async def test_temperature_sensor_climate(hass: HomeAssistant) -> None: ) +async def test_temperature_sensor_water_heater(hass: HomeAssistant) -> None: + """Test TemperatureSensor reports climate temperature correctly.""" + for bad_value in (STATE_UNKNOWN, STATE_UNAVAILABLE, "not-number"): + hass.states.async_set( + "water_heater.boyler", + STATE_ECO, + {"supported_features": 11, ATTR_CURRENT_TEMPERATURE: bad_value}, + ) + + properties = await reported_properties(hass, "water_heater.boyler") + properties.assert_not_has_property("Alexa.TemperatureSensor", "temperature") + + hass.states.async_set( + "water_heater.boyler", + STATE_ECO, + {"supported_features": 11, ATTR_CURRENT_TEMPERATURE: 34}, + ) + properties = await reported_properties(hass, "water_heater.boyler") + properties.assert_equal( + "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"} + ) + + async def test_report_alarm_control_panel_state(hass: HomeAssistant) -> None: """Test SecurityPanelController implements armState property.""" hass.states.async_set("alarm_control_panel.armed_away", STATE_ALARM_ARMED_AWAY, {}) diff --git a/tests/components/alexa/test_common.py b/tests/components/alexa/test_common.py index 4cbe112af49..d3ea1bcda3e 100644 --- a/tests/components/alexa/test_common.py +++ b/tests/components/alexa/test_common.py @@ -128,12 +128,14 @@ async def assert_request_calls_service( async def assert_request_fails( - namespace, name, endpoint, service_not_called, hass, payload=None + namespace, name, endpoint, service_not_called, hass, payload=None, instance=None ): """Assert an API request returns an ErrorResponse.""" request = get_new_request(namespace, name, endpoint) if payload: request["directive"]["payload"] = payload + if instance: + request["directive"]["header"]["instance"] = instance domain, service_name = service_not_called.split(".") call = async_mock_service(hass, domain, service_name) diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index 0a5b1f79f72..d025b1586f5 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -2700,6 +2700,181 @@ async def test_thermostat(hass: HomeAssistant) -> None: assert call.data["preset_mode"] == "eco" +async def test_water_heater(hass: HomeAssistant) -> None: + """Test water_heater discovery.""" + hass.config.units = US_CUSTOMARY_SYSTEM + device = ( + "water_heater.boyler", + "gas", + { + "temperature": 70.0, + "target_temp_high": None, + "target_temp_low": None, + "current_temperature": 75.0, + "friendly_name": "Test water heater", + "supported_features": 1 | 2 | 8, + "operation_list": ["off", "gas", "eco"], + "operation_mode": "gas", + "min_temp": 50, + "max_temp": 90, + }, + ) + appliance = await discovery_test(device, hass) + + assert appliance["endpointId"] == "water_heater#boyler" + assert appliance["displayCategories"][0] == "WATER_HEATER" + assert appliance["friendlyName"] == "Test water heater" + + capabilities = assert_endpoint_capabilities( + appliance, + "Alexa.PowerController", + "Alexa.ThermostatController", + "Alexa.ModeController", + "Alexa.TemperatureSensor", + "Alexa.EndpointHealth", + "Alexa", + ) + + properties = await reported_properties(hass, "water_heater#boyler") + properties.assert_equal("Alexa.ModeController", "mode", "operation_mode.gas") + properties.assert_equal( + "Alexa.ThermostatController", + "targetSetpoint", + {"value": 70.0, "scale": "FAHRENHEIT"}, + ) + properties.assert_equal( + "Alexa.TemperatureSensor", "temperature", {"value": 75.0, "scale": "FAHRENHEIT"} + ) + + modes_capability = get_capability(capabilities, "Alexa.ModeController") + assert modes_capability is not None + configuration = modes_capability["configuration"] + + supported_modes = ["operation_mode.off", "operation_mode.gas", "operation_mode.eco"] + for mode in supported_modes: + assert mode in [item["value"] for item in configuration["supportedModes"]] + + call, msg = await assert_request_calls_service( + "Alexa.ThermostatController", + "SetTargetTemperature", + "water_heater#boyler", + "water_heater.set_temperature", + hass, + payload={"targetSetpoint": {"value": 69.0, "scale": "FAHRENHEIT"}}, + ) + assert call.data["temperature"] == 69.0 + properties = ReportedProperties(msg["context"]["properties"]) + properties.assert_equal( + "Alexa.ThermostatController", + "targetSetpoint", + {"value": 69.0, "scale": "FAHRENHEIT"}, + ) + + msg = await assert_request_fails( + "Alexa.ThermostatController", + "SetTargetTemperature", + "water_heater#boyler", + "water_heater.set_temperature", + hass, + payload={"targetSetpoint": {"value": 0.0, "scale": "CELSIUS"}}, + ) + assert msg["event"]["payload"]["type"] == "TEMPERATURE_VALUE_OUT_OF_RANGE" + + call, msg = await assert_request_calls_service( + "Alexa.ThermostatController", + "SetTargetTemperature", + "water_heater#boyler", + "water_heater.set_temperature", + hass, + payload={ + "targetSetpoint": {"value": 30.0, "scale": "CELSIUS"}, + }, + ) + assert call.data["temperature"] == 86.0 + properties = ReportedProperties(msg["context"]["properties"]) + properties.assert_equal( + "Alexa.ThermostatController", + "targetSetpoint", + {"value": 86.0, "scale": "FAHRENHEIT"}, + ) + + call, msg = await assert_request_calls_service( + "Alexa.ThermostatController", + "AdjustTargetTemperature", + "water_heater#boyler", + "water_heater.set_temperature", + hass, + payload={"targetSetpointDelta": {"value": -10.0, "scale": "KELVIN"}}, + ) + assert call.data["temperature"] == 52.0 + properties = ReportedProperties(msg["context"]["properties"]) + properties.assert_equal( + "Alexa.ThermostatController", + "targetSetpoint", + {"value": 52.0, "scale": "FAHRENHEIT"}, + ) + + msg = await assert_request_fails( + "Alexa.ThermostatController", + "AdjustTargetTemperature", + "water_heater#boyler", + "water_heater.set_temperature", + hass, + payload={"targetSetpointDelta": {"value": 20.0, "scale": "CELSIUS"}}, + ) + assert msg["event"]["payload"]["type"] == "TEMPERATURE_VALUE_OUT_OF_RANGE" + + # Setting mode, the payload can be an object with a value attribute... + call, msg = await assert_request_calls_service( + "Alexa.ModeController", + "SetMode", + "water_heater#boyler", + "water_heater.set_operation_mode", + hass, + payload={"mode": "operation_mode.eco"}, + instance="water_heater.operation_mode", + ) + assert call.data["operation_mode"] == "eco" + properties = ReportedProperties(msg["context"]["properties"]) + properties.assert_equal("Alexa.ModeController", "mode", "operation_mode.eco") + + call, msg = await assert_request_calls_service( + "Alexa.ModeController", + "SetMode", + "water_heater#boyler", + "water_heater.set_operation_mode", + hass, + payload={"mode": "operation_mode.gas"}, + instance="water_heater.operation_mode", + ) + assert call.data["operation_mode"] == "gas" + properties = ReportedProperties(msg["context"]["properties"]) + properties.assert_equal("Alexa.ModeController", "mode", "operation_mode.gas") + + # assert unsupported mode + msg = await assert_request_fails( + "Alexa.ModeController", + "SetMode", + "water_heater#boyler", + "water_heater.set_operation_mode", + hass, + payload={"mode": "operation_mode.invalid"}, + instance="water_heater.operation_mode", + ) + assert msg["event"]["payload"]["type"] == "INVALID_VALUE" + + call, _ = await assert_request_calls_service( + "Alexa.ModeController", + "SetMode", + "water_heater#boyler", + "water_heater.set_operation_mode", + hass, + payload={"mode": "operation_mode.off"}, + instance="water_heater.operation_mode", + ) + assert call.data["operation_mode"] == "off" + + 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