mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Simplify maxcube integration (#48403)
* Simplify maxcube integration Device objects returned by maxcube-api dependency are stable, so we do not need to resolve from the device address every time. Also, refactor and unify how maxcube integration sets temperature & mode. * Raise ValueError if missing parameters for set_temperature method Raise a ValueError exception If set_temperature does not receive a temperature parameter. Also, document properly _set_target method. * Use Type | None instead of Optional[Type] annotation * Protect set_hvac_mode and set_preset_mode from unsupported parameters
This commit is contained in:
parent
ffdfc521b9
commit
0706ae70dc
@ -11,13 +11,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
"""Iterate through all MAX! Devices and add window shutters."""
|
"""Iterate through all MAX! Devices and add window shutters."""
|
||||||
devices = []
|
devices = []
|
||||||
for handler in hass.data[DATA_KEY].values():
|
for handler in hass.data[DATA_KEY].values():
|
||||||
cube = handler.cube
|
for device in handler.cube.devices:
|
||||||
for device in cube.devices:
|
|
||||||
name = f"{cube.room_by_id(device.room_id).name} {device.name}"
|
|
||||||
|
|
||||||
# Only add Window Shutters
|
# Only add Window Shutters
|
||||||
if device.is_windowshutter():
|
if device.is_windowshutter():
|
||||||
devices.append(MaxCubeShutter(handler, name, device.rf_address))
|
devices.append(MaxCubeShutter(handler, device))
|
||||||
|
|
||||||
if devices:
|
if devices:
|
||||||
add_entities(devices)
|
add_entities(devices)
|
||||||
@ -26,13 +23,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
class MaxCubeShutter(BinarySensorEntity):
|
class MaxCubeShutter(BinarySensorEntity):
|
||||||
"""Representation of a MAX! Cube Binary Sensor device."""
|
"""Representation of a MAX! Cube Binary Sensor device."""
|
||||||
|
|
||||||
def __init__(self, handler, name, rf_address):
|
def __init__(self, handler, device):
|
||||||
"""Initialize MAX! Cube BinarySensorEntity."""
|
"""Initialize MAX! Cube BinarySensorEntity."""
|
||||||
self._name = name
|
room = handler.cube.room_by_id(device.room_id)
|
||||||
self._sensor_type = DEVICE_CLASS_WINDOW
|
self._name = f"{room.name} {device.name}"
|
||||||
self._rf_address = rf_address
|
|
||||||
self._cubehandle = handler
|
self._cubehandle = handler
|
||||||
self._state = None
|
self._device = device
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -42,15 +38,13 @@ class MaxCubeShutter(BinarySensorEntity):
|
|||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
"""Return the class of this sensor."""
|
"""Return the class of this sensor."""
|
||||||
return self._sensor_type
|
return DEVICE_CLASS_WINDOW
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return true if the binary sensor is on/open."""
|
"""Return true if the binary sensor is on/open."""
|
||||||
return self._state
|
return self._device.is_open
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Get latest data from MAX! Cube."""
|
"""Get latest data from MAX! Cube."""
|
||||||
self._cubehandle.update()
|
self._cubehandle.update()
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
|
||||||
self._state = device.is_open
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
"""Support for MAX! Thermostats via MAX! Cube."""
|
"""Support for MAX! Thermostats via MAX! Cube."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
@ -47,31 +49,14 @@ MAX_TEMPERATURE = 30.0
|
|||||||
|
|
||||||
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
|
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
|
||||||
|
|
||||||
HASS_PRESET_TO_MAX_MODE = {
|
|
||||||
PRESET_AWAY: MAX_DEVICE_MODE_VACATION,
|
|
||||||
PRESET_BOOST: MAX_DEVICE_MODE_BOOST,
|
|
||||||
PRESET_NONE: MAX_DEVICE_MODE_AUTOMATIC,
|
|
||||||
PRESET_ON: MAX_DEVICE_MODE_MANUAL,
|
|
||||||
}
|
|
||||||
|
|
||||||
MAX_MODE_TO_HASS_PRESET = {
|
|
||||||
MAX_DEVICE_MODE_AUTOMATIC: PRESET_NONE,
|
|
||||||
MAX_DEVICE_MODE_BOOST: PRESET_BOOST,
|
|
||||||
MAX_DEVICE_MODE_MANUAL: PRESET_NONE,
|
|
||||||
MAX_DEVICE_MODE_VACATION: PRESET_AWAY,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Iterate through all MAX! Devices and add thermostats."""
|
"""Iterate through all MAX! Devices and add thermostats."""
|
||||||
devices = []
|
devices = []
|
||||||
for handler in hass.data[DATA_KEY].values():
|
for handler in hass.data[DATA_KEY].values():
|
||||||
cube = handler.cube
|
for device in handler.cube.devices:
|
||||||
for device in cube.devices:
|
|
||||||
name = f"{cube.room_by_id(device.room_id).name} {device.name}"
|
|
||||||
|
|
||||||
if device.is_thermostat() or device.is_wallthermostat():
|
if device.is_thermostat() or device.is_wallthermostat():
|
||||||
devices.append(MaxCubeClimate(handler, name, device.rf_address))
|
devices.append(MaxCubeClimate(handler, device))
|
||||||
|
|
||||||
if devices:
|
if devices:
|
||||||
add_entities(devices)
|
add_entities(devices)
|
||||||
@ -80,11 +65,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
class MaxCubeClimate(ClimateEntity):
|
class MaxCubeClimate(ClimateEntity):
|
||||||
"""MAX! Cube ClimateEntity."""
|
"""MAX! Cube ClimateEntity."""
|
||||||
|
|
||||||
def __init__(self, handler, name, rf_address):
|
def __init__(self, handler, device):
|
||||||
"""Initialize MAX! Cube ClimateEntity."""
|
"""Initialize MAX! Cube ClimateEntity."""
|
||||||
self._name = name
|
room = handler.cube.room_by_id(device.room_id)
|
||||||
self._rf_address = rf_address
|
self._name = f"{room.name} {device.name}"
|
||||||
self._cubehandle = handler
|
self._cubehandle = handler
|
||||||
|
self._device = device
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
@ -104,20 +90,15 @@ class MaxCubeClimate(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self):
|
||||||
"""Return the minimum temperature."""
|
"""Return the minimum temperature."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
temp = self._device.min_temperature or MIN_TEMPERATURE
|
||||||
if device.min_temperature is None:
|
|
||||||
return MIN_TEMPERATURE
|
|
||||||
# OFF_TEMPERATURE (always off) a is valid temperature to maxcube but not to Home Assistant.
|
# OFF_TEMPERATURE (always off) a is valid temperature to maxcube but not to Home Assistant.
|
||||||
# We use HVAC_MODE_OFF instead to represent a turned off thermostat.
|
# We use HVAC_MODE_OFF instead to represent a turned off thermostat.
|
||||||
return max(device.min_temperature, MIN_TEMPERATURE)
|
return max(temp, MIN_TEMPERATURE)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_temp(self):
|
def max_temp(self):
|
||||||
"""Return the maximum temperature."""
|
"""Return the maximum temperature."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
return self._device.max_temperature or MAX_TEMPERATURE
|
||||||
if device.max_temperature is None:
|
|
||||||
return MAX_TEMPERATURE
|
|
||||||
return device.max_temperature
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def temperature_unit(self):
|
def temperature_unit(self):
|
||||||
@ -127,18 +108,17 @@ class MaxCubeClimate(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def current_temperature(self):
|
def current_temperature(self):
|
||||||
"""Return the current temperature."""
|
"""Return the current temperature."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
return self._device.actual_temperature
|
||||||
return device.actual_temperature
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self):
|
def hvac_mode(self):
|
||||||
"""Return current operation mode."""
|
"""Return current operation mode."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
mode = self._device.mode
|
||||||
if device.mode in [MAX_DEVICE_MODE_AUTOMATIC, MAX_DEVICE_MODE_BOOST]:
|
if mode in [MAX_DEVICE_MODE_AUTOMATIC, MAX_DEVICE_MODE_BOOST]:
|
||||||
return HVAC_MODE_AUTO
|
return HVAC_MODE_AUTO
|
||||||
if (
|
if (
|
||||||
device.mode == MAX_DEVICE_MODE_MANUAL
|
mode == MAX_DEVICE_MODE_MANUAL
|
||||||
and device.target_temperature == OFF_TEMPERATURE
|
and self._device.target_temperature == OFF_TEMPERATURE
|
||||||
):
|
):
|
||||||
return HVAC_MODE_OFF
|
return HVAC_MODE_OFF
|
||||||
|
|
||||||
@ -151,37 +131,46 @@ class MaxCubeClimate(ClimateEntity):
|
|||||||
|
|
||||||
def set_hvac_mode(self, hvac_mode: str):
|
def set_hvac_mode(self, hvac_mode: str):
|
||||||
"""Set new target hvac mode."""
|
"""Set new target hvac mode."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
|
||||||
temp = device.target_temperature
|
|
||||||
mode = MAX_DEVICE_MODE_MANUAL
|
|
||||||
|
|
||||||
if hvac_mode == HVAC_MODE_OFF:
|
if hvac_mode == HVAC_MODE_OFF:
|
||||||
temp = OFF_TEMPERATURE
|
self._set_target(MAX_DEVICE_MODE_MANUAL, OFF_TEMPERATURE)
|
||||||
elif hvac_mode == HVAC_MODE_HEAT:
|
elif hvac_mode == HVAC_MODE_HEAT:
|
||||||
temp = max(temp, self.min_temp)
|
temp = max(self._device.target_temperature, self.min_temp)
|
||||||
|
self._set_target(MAX_DEVICE_MODE_MANUAL, temp)
|
||||||
|
elif hvac_mode == HVAC_MODE_AUTO:
|
||||||
|
self._set_target(MAX_DEVICE_MODE_AUTOMATIC, None)
|
||||||
else:
|
else:
|
||||||
temp = None
|
raise ValueError(f"unsupported HVAC mode {hvac_mode}")
|
||||||
mode = MAX_DEVICE_MODE_AUTOMATIC
|
|
||||||
|
|
||||||
cube = self._cubehandle.cube
|
def _set_target(self, mode: int | None, temp: float | None) -> None:
|
||||||
|
"""
|
||||||
|
Set the mode and/or temperature of the thermostat.
|
||||||
|
|
||||||
|
@param mode: this is the mode to change to.
|
||||||
|
@param temp: the temperature to target.
|
||||||
|
|
||||||
|
Both parameters are optional. When mode is undefined, it keeps
|
||||||
|
the previous mode. When temp is undefined, it fetches the
|
||||||
|
temperature from the weekly schedule when mode is
|
||||||
|
MAX_DEVICE_MODE_AUTOMATIC and keeps the previous
|
||||||
|
temperature otherwise.
|
||||||
|
"""
|
||||||
with self._cubehandle.mutex:
|
with self._cubehandle.mutex:
|
||||||
try:
|
try:
|
||||||
cube.set_temperature_mode(device, temp, mode)
|
self._cubehandle.cube.set_temperature_mode(self._device, temp, mode)
|
||||||
except (socket.timeout, OSError):
|
except (socket.timeout, OSError):
|
||||||
_LOGGER.error("Setting HVAC mode failed")
|
_LOGGER.error("Setting HVAC mode failed")
|
||||||
return
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self):
|
def hvac_action(self):
|
||||||
"""Return the current running hvac operation if supported."""
|
"""Return the current running hvac operation if supported."""
|
||||||
cube = self._cubehandle.cube
|
|
||||||
device = cube.device_by_rf(self._rf_address)
|
|
||||||
valve = 0
|
valve = 0
|
||||||
|
|
||||||
if device.is_thermostat():
|
if self._device.is_thermostat():
|
||||||
valve = device.valve_position
|
valve = self._device.valve_position
|
||||||
elif device.is_wallthermostat():
|
elif self._device.is_wallthermostat():
|
||||||
for device in cube.devices_by_room(cube.room_by_id(device.room_id)):
|
cube = self._cubehandle.cube
|
||||||
|
room = cube.room_by_id(self._device.room_id)
|
||||||
|
for device in cube.devices_by_room(room):
|
||||||
if device.is_thermostat() and device.valve_position > 0:
|
if device.is_thermostat() and device.valve_position > 0:
|
||||||
valve = device.valve_position
|
valve = device.valve_position
|
||||||
break
|
break
|
||||||
@ -199,50 +188,36 @@ class MaxCubeClimate(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def target_temperature(self):
|
def target_temperature(self):
|
||||||
"""Return the temperature we try to reach."""
|
"""Return the temperature we try to reach."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
temp = self._device.target_temperature
|
||||||
if (
|
if temp is None or temp < self.min_temp or temp > self.max_temp:
|
||||||
device.target_temperature is None
|
|
||||||
or device.target_temperature < self.min_temp
|
|
||||||
or device.target_temperature > self.max_temp
|
|
||||||
):
|
|
||||||
return None
|
return None
|
||||||
return device.target_temperature
|
return temp
|
||||||
|
|
||||||
def set_temperature(self, **kwargs):
|
def set_temperature(self, **kwargs):
|
||||||
"""Set new target temperatures."""
|
"""Set new target temperatures."""
|
||||||
if kwargs.get(ATTR_TEMPERATURE) is None:
|
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||||
return False
|
if temp is None:
|
||||||
|
raise ValueError(
|
||||||
target_temperature = kwargs.get(ATTR_TEMPERATURE)
|
f"No {ATTR_TEMPERATURE} parameter passed to set_temperature method."
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
)
|
||||||
|
self._set_target(None, temp)
|
||||||
cube = self._cubehandle.cube
|
|
||||||
|
|
||||||
with self._cubehandle.mutex:
|
|
||||||
try:
|
|
||||||
cube.set_target_temperature(device, target_temperature)
|
|
||||||
except (socket.timeout, OSError):
|
|
||||||
_LOGGER.error("Setting target temperature failed")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_mode(self):
|
def preset_mode(self):
|
||||||
"""Return the current preset mode."""
|
"""Return the current preset mode."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
if self._device.mode == MAX_DEVICE_MODE_MANUAL:
|
||||||
if self.hvac_mode == HVAC_MODE_OFF:
|
if self._device.target_temperature == self._device.comfort_temperature:
|
||||||
return PRESET_NONE
|
|
||||||
|
|
||||||
if device.mode == MAX_DEVICE_MODE_MANUAL:
|
|
||||||
if device.target_temperature == device.comfort_temperature:
|
|
||||||
return PRESET_COMFORT
|
return PRESET_COMFORT
|
||||||
if device.target_temperature == device.eco_temperature:
|
if self._device.target_temperature == self._device.eco_temperature:
|
||||||
return PRESET_ECO
|
return PRESET_ECO
|
||||||
if device.target_temperature == ON_TEMPERATURE:
|
if self._device.target_temperature == ON_TEMPERATURE:
|
||||||
return PRESET_ON
|
return PRESET_ON
|
||||||
|
elif self._device.mode == MAX_DEVICE_MODE_BOOST:
|
||||||
|
return PRESET_BOOST
|
||||||
|
elif self._device.mode == MAX_DEVICE_MODE_VACATION:
|
||||||
|
return PRESET_AWAY
|
||||||
return PRESET_NONE
|
return PRESET_NONE
|
||||||
|
|
||||||
return MAX_MODE_TO_HASS_PRESET[device.mode]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_modes(self):
|
def preset_modes(self):
|
||||||
"""Return available preset modes."""
|
"""Return available preset modes."""
|
||||||
@ -257,37 +232,27 @@ class MaxCubeClimate(ClimateEntity):
|
|||||||
|
|
||||||
def set_preset_mode(self, preset_mode):
|
def set_preset_mode(self, preset_mode):
|
||||||
"""Set new operation mode."""
|
"""Set new operation mode."""
|
||||||
device = self._cubehandle.cube.device_by_rf(self._rf_address)
|
|
||||||
temp = None
|
|
||||||
mode = MAX_DEVICE_MODE_AUTOMATIC
|
|
||||||
|
|
||||||
if preset_mode in [PRESET_COMFORT, PRESET_ECO, PRESET_ON]:
|
|
||||||
mode = MAX_DEVICE_MODE_MANUAL
|
|
||||||
if preset_mode == PRESET_COMFORT:
|
if preset_mode == PRESET_COMFORT:
|
||||||
temp = device.comfort_temperature
|
self._set_target(MAX_DEVICE_MODE_MANUAL, self._device.comfort_temperature)
|
||||||
elif preset_mode == PRESET_ECO:
|
elif preset_mode == PRESET_ECO:
|
||||||
temp = device.eco_temperature
|
self._set_target(MAX_DEVICE_MODE_MANUAL, self._device.eco_temperature)
|
||||||
|
elif preset_mode == PRESET_ON:
|
||||||
|
self._set_target(MAX_DEVICE_MODE_MANUAL, ON_TEMPERATURE)
|
||||||
|
elif preset_mode == PRESET_AWAY:
|
||||||
|
self._set_target(MAX_DEVICE_MODE_VACATION, None)
|
||||||
|
elif preset_mode == PRESET_BOOST:
|
||||||
|
self._set_target(MAX_DEVICE_MODE_BOOST, None)
|
||||||
|
elif preset_mode == PRESET_NONE:
|
||||||
|
self._set_target(MAX_DEVICE_MODE_AUTOMATIC, None)
|
||||||
else:
|
else:
|
||||||
temp = ON_TEMPERATURE
|
raise ValueError(f"unsupported preset mode {preset_mode}")
|
||||||
else:
|
|
||||||
mode = HASS_PRESET_TO_MAX_MODE[preset_mode] or MAX_DEVICE_MODE_AUTOMATIC
|
|
||||||
|
|
||||||
with self._cubehandle.mutex:
|
|
||||||
try:
|
|
||||||
self._cubehandle.cube.set_temperature_mode(device, temp, mode)
|
|
||||||
except (socket.timeout, OSError):
|
|
||||||
_LOGGER.error("Setting operation mode failed")
|
|
||||||
return
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self):
|
def extra_state_attributes(self):
|
||||||
"""Return the optional state attributes."""
|
"""Return the optional state attributes."""
|
||||||
cube = self._cubehandle.cube
|
if not self._device.is_thermostat():
|
||||||
device = cube.device_by_rf(self._rf_address)
|
|
||||||
|
|
||||||
if not device.is_thermostat():
|
|
||||||
return {}
|
return {}
|
||||||
return {ATTR_VALVE_POSITION: device.valve_position}
|
return {ATTR_VALVE_POSITION: self._device.valve_position}
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Get latest data from MAX! Cube."""
|
"""Get latest data from MAX! Cube."""
|
||||||
|
@ -102,7 +102,6 @@ async def cube(hass, hass_config, room, thermostat, wallthermostat, windowshutte
|
|||||||
cube.devices = [thermostat, wallthermostat, windowshutter]
|
cube.devices = [thermostat, wallthermostat, windowshutter]
|
||||||
cube.room_by_id.return_value = room
|
cube.room_by_id.return_value = room
|
||||||
cube.devices_by_room.return_value = [thermostat, wallthermostat, windowshutter]
|
cube.devices_by_room.return_value = [thermostat, wallthermostat, windowshutter]
|
||||||
cube.device_by_rf.side_effect = {d.rf_address: d for d in cube.devices}.get
|
|
||||||
assert await async_setup_component(hass, DOMAIN, hass_config)
|
assert await async_setup_component(hass, DOMAIN, hass_config)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
gateway = hass_config[DOMAIN]["gateways"][0]
|
gateway = hass_config[DOMAIN]["gateways"][0]
|
||||||
|
@ -20,9 +20,6 @@ ENTITY_ID = "binary_sensor.testroom_testshutter"
|
|||||||
|
|
||||||
async def test_window_shuttler(hass, cube: MaxCube, windowshutter: MaxWindowShutter):
|
async def test_window_shuttler(hass, cube: MaxCube, windowshutter: MaxWindowShutter):
|
||||||
"""Test a successful setup with a shuttler device."""
|
"""Test a successful setup with a shuttler device."""
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(minutes=5))
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get(ENTITY_ID)
|
state = hass.states.get(ENTITY_ID)
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
|
@ -10,6 +10,7 @@ from maxcube.device import (
|
|||||||
)
|
)
|
||||||
from maxcube.thermostat import MaxThermostat
|
from maxcube.thermostat import MaxThermostat
|
||||||
from maxcube.wallthermostat import MaxWallThermostat
|
from maxcube.wallthermostat import MaxWallThermostat
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
ATTR_CURRENT_TEMPERATURE,
|
ATTR_CURRENT_TEMPERATURE,
|
||||||
@ -20,11 +21,14 @@ from homeassistant.components.climate.const import (
|
|||||||
ATTR_MIN_TEMP,
|
ATTR_MIN_TEMP,
|
||||||
ATTR_PRESET_MODE,
|
ATTR_PRESET_MODE,
|
||||||
ATTR_PRESET_MODES,
|
ATTR_PRESET_MODES,
|
||||||
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
|
ATTR_TARGET_TEMP_LOW,
|
||||||
CURRENT_HVAC_HEAT,
|
CURRENT_HVAC_HEAT,
|
||||||
CURRENT_HVAC_IDLE,
|
CURRENT_HVAC_IDLE,
|
||||||
CURRENT_HVAC_OFF,
|
CURRENT_HVAC_OFF,
|
||||||
DOMAIN as CLIMATE_DOMAIN,
|
DOMAIN as CLIMATE_DOMAIN,
|
||||||
HVAC_MODE_AUTO,
|
HVAC_MODE_AUTO,
|
||||||
|
HVAC_MODE_DRY,
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
PRESET_AWAY,
|
PRESET_AWAY,
|
||||||
@ -155,6 +159,20 @@ async def test_thermostat_set_hvac_mode_heat(
|
|||||||
assert state.state == HVAC_MODE_HEAT
|
assert state.state == HVAC_MODE_HEAT
|
||||||
|
|
||||||
|
|
||||||
|
async def test_thermostat_set_invalid_hvac_mode(
|
||||||
|
hass, cube: MaxCube, thermostat: MaxThermostat
|
||||||
|
):
|
||||||
|
"""Set hvac mode to heat."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_HVAC_MODE,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVAC_MODE_DRY},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
cube.set_temperature_mode.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_thermostat_set_temperature(
|
async def test_thermostat_set_temperature(
|
||||||
hass, cube: MaxCube, thermostat: MaxThermostat
|
hass, cube: MaxCube, thermostat: MaxThermostat
|
||||||
):
|
):
|
||||||
@ -165,7 +183,7 @@ async def test_thermostat_set_temperature(
|
|||||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 10.0},
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 10.0},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
cube.set_target_temperature.assert_called_once_with(thermostat, 10.0)
|
cube.set_temperature_mode.assert_called_once_with(thermostat, 10.0, None)
|
||||||
thermostat.target_temperature = 10.0
|
thermostat.target_temperature = 10.0
|
||||||
thermostat.valve_position = 0
|
thermostat.valve_position = 0
|
||||||
|
|
||||||
@ -178,6 +196,24 @@ async def test_thermostat_set_temperature(
|
|||||||
assert state.attributes.get(ATTR_HVAC_ACTION) == CURRENT_HVAC_IDLE
|
assert state.attributes.get(ATTR_HVAC_ACTION) == CURRENT_HVAC_IDLE
|
||||||
|
|
||||||
|
|
||||||
|
async def test_thermostat_set_no_temperature(
|
||||||
|
hass, cube: MaxCube, thermostat: MaxThermostat
|
||||||
|
):
|
||||||
|
"""Set hvac mode to heat."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: ENTITY_ID,
|
||||||
|
ATTR_TARGET_TEMP_HIGH: 29.0,
|
||||||
|
ATTR_TARGET_TEMP_LOW: 10.0,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
cube.set_temperature_mode.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_thermostat_set_preset_on(hass, cube: MaxCube, thermostat: MaxThermostat):
|
async def test_thermostat_set_preset_on(hass, cube: MaxCube, thermostat: MaxThermostat):
|
||||||
"""Set preset mode to on."""
|
"""Set preset mode to on."""
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
@ -317,6 +353,20 @@ async def test_thermostat_set_preset_none(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_thermostat_set_invalid_preset(
|
||||||
|
hass, cube: MaxCube, thermostat: MaxThermostat
|
||||||
|
):
|
||||||
|
"""Set hvac mode to heat."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_PRESET_MODE,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: "invalid"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
cube.set_temperature_mode.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_wallthermostat_set_hvac_mode_heat(
|
async def test_wallthermostat_set_hvac_mode_heat(
|
||||||
hass, cube: MaxCube, wallthermostat: MaxWallThermostat
|
hass, cube: MaxCube, wallthermostat: MaxWallThermostat
|
||||||
):
|
):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user