Add Sensibo Climate React (#78221)

This commit is contained in:
G Johansson 2022-10-23 22:22:14 +02:00 committed by GitHub
parent 746bdb44ac
commit b04165b495
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 623 additions and 2 deletions

View File

@ -38,6 +38,12 @@ ATTR_MINUTES = "minutes"
SERVICE_ENABLE_PURE_BOOST = "enable_pure_boost" SERVICE_ENABLE_PURE_BOOST = "enable_pure_boost"
SERVICE_DISABLE_PURE_BOOST = "disable_pure_boost" SERVICE_DISABLE_PURE_BOOST = "disable_pure_boost"
SERVICE_FULL_STATE = "full_state" SERVICE_FULL_STATE = "full_state"
SERVICE_ENABLE_CLIMATE_REACT = "enable_climate_react"
ATTR_HIGH_TEMPERATURE_THRESHOLD = "high_temperature_threshold"
ATTR_HIGH_TEMPERATURE_STATE = "high_temperature_state"
ATTR_LOW_TEMPERATURE_THRESHOLD = "low_temperature_threshold"
ATTR_LOW_TEMPERATURE_STATE = "low_temperature_state"
ATTR_SMART_TYPE = "smart_type"
ATTR_AC_INTEGRATION = "ac_integration" ATTR_AC_INTEGRATION = "ac_integration"
ATTR_GEO_INTEGRATION = "geo_integration" ATTR_GEO_INTEGRATION = "geo_integration"
@ -140,6 +146,20 @@ async def async_setup_entry(
"async_full_ac_state", "async_full_ac_state",
) )
platform.async_register_entity_service(
SERVICE_ENABLE_CLIMATE_REACT,
{
vol.Required(ATTR_HIGH_TEMPERATURE_THRESHOLD): float,
vol.Required(ATTR_HIGH_TEMPERATURE_STATE): dict,
vol.Required(ATTR_LOW_TEMPERATURE_THRESHOLD): float,
vol.Required(ATTR_LOW_TEMPERATURE_STATE): dict,
vol.Required(ATTR_SMART_TYPE): vol.In(
["temperature", "feelsLike", "humidity"]
),
},
"async_enable_climate_react",
)
class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity): class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
"""Representation of a Sensibo device.""" """Representation of a Sensibo device."""
@ -430,6 +450,42 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
data=params, data=params,
) )
async def async_enable_climate_react(
self,
high_temperature_threshold: float,
high_temperature_state: dict[str, Any],
low_temperature_threshold: float,
low_temperature_state: dict[str, Any],
smart_type: str,
) -> None:
"""Enable Climate React Configuration."""
high_temp = high_temperature_threshold
low_temp = low_temperature_threshold
if high_temperature_state.get("temperatureUnit") == "F":
high_temp = TemperatureConverter.convert(
high_temperature_threshold, TEMP_FAHRENHEIT, TEMP_CELSIUS
)
low_temp = TemperatureConverter.convert(
low_temperature_threshold, TEMP_FAHRENHEIT, TEMP_CELSIUS
)
params: dict[str, str | bool | float | dict] = {
"enabled": True,
"deviceUid": self._device_id,
"highTemperatureState": high_temperature_state,
"highTemperatureThreshold": high_temp,
"lowTemperatureState": low_temperature_state,
"lowTemperatureThreshold": low_temp,
"type": smart_type,
}
await self.api_call_custom_service_climate_react(
key="smart_on",
value=True,
data=params,
)
@async_handle_api_call @async_handle_api_call
async def async_send_api_call( async def async_send_api_call(
self, self,
@ -470,6 +526,17 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
result = await self._client.async_set_pureboost(self._device_id, data) result = await self._client.async_set_pureboost(self._device_id, data)
return bool(result.get("status") == "success") return bool(result.get("status") == "success")
@async_handle_api_call
async def api_call_custom_service_climate_react(
self,
key: str,
value: Any,
data: dict,
) -> bool:
"""Make service call to api."""
result = await self._client.async_set_climate_react(self._device_id, data)
return bool(result.get("status") == "success")
@async_handle_api_call @async_handle_api_call
async def api_call_custom_service_full_ac_state( async def api_call_custom_service_full_ac_state(
self, self,

View File

@ -155,6 +155,32 @@ DEVICE_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
extra_fn=None, extra_fn=None,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensiboDeviceSensorEntityDescription(
key="climate_react_low",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Climate React low temperature threshold",
value_fn=lambda data: data.smart_low_temp_threshold,
extra_fn=lambda data: data.smart_low_state,
entity_registry_enabled_default=False,
),
SensiboDeviceSensorEntityDescription(
key="climate_react_high",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Climate React high temperature threshold",
value_fn=lambda data: data.smart_high_temp_threshold,
extra_fn=lambda data: data.smart_high_state,
entity_registry_enabled_default=False,
),
SensiboDeviceSensorEntityDescription(
key="climate_react_type",
device_class="sensibo__smart_type",
name="Climate React type",
value_fn=lambda data: data.smart_type,
extra_fn=None,
entity_registry_enabled_default=False,
),
FILTER_LAST_RESET_DESCRIPTION, FILTER_LAST_RESET_DESCRIPTION,
) )
@ -281,7 +307,10 @@ class SensiboDeviceSensor(SensiboDeviceBaseEntity, SensorEntity):
@property @property
def native_value(self) -> StateType | datetime: def native_value(self) -> StateType | datetime:
"""Return value of sensor.""" """Return value of sensor."""
return self.entity_description.value_fn(self.device_data) state = self.entity_description.value_fn(self.device_data)
if isinstance(state, str):
return state.lower()
return state
@property @property
def extra_state_attributes(self) -> Mapping[str, Any] | None: def extra_state_attributes(self) -> Mapping[str, Any] | None:

View File

@ -146,3 +146,56 @@ full_state:
options: options:
- "on" - "on"
- "off" - "off"
enable_climate_react:
name: Enable Climate React
description: Enable and configure Climate React
target:
entity:
integration: sensibo
domain: climate
fields:
high_temperature_threshold:
name: Threshold high
description: When temp/humidity goes above
required: true
example: 24
selector:
number:
min: 0
max: 150
step: 0.1
mode: box
high_temperature_state:
name: State high threshold
description: What should happen at high threshold. Requires full state
required: true
selector:
object:
low_temperature_threshold:
name: Threshold low
description: When temp/humidity goes below
required: true
example: 19
selector:
number:
min: 0
max: 150
step: 0.1
mode: box
low_temperature_state:
name: State low threshold
description: What should happen at low threshold. Requires full state
required: true
selector:
object:
smart_type:
name: Trigger type
description: Choose between temperature/feels like/humidity
required: true
example: "temperature"
selector:
select:
options:
- "temperature"
- "feelsLike"
- "humidity"

View File

@ -3,6 +3,11 @@
"sensibo__sensitivity": { "sensibo__sensitivity": {
"n": "Normal", "n": "Normal",
"s": "Sensitive" "s": "Sensitive"
},
"sensibo__smart_type": {
"temperature": "Temperature",
"feelslike": "Feels like",
"humidity": "Humidity"
} }
} }
} }

View File

@ -14,6 +14,7 @@ from homeassistant.components.switch import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
@ -53,6 +54,17 @@ DEVICE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = (
command_off="async_turn_off_timer", command_off="async_turn_off_timer",
data_key="timer_on", data_key="timer_on",
), ),
SensiboDeviceSwitchEntityDescription(
key="climate_react_switch",
device_class=SwitchDeviceClass.SWITCH,
name="Climate React",
icon="mdi:wizard-hat",
value_fn=lambda data: data.smart_on,
extra_fn=lambda data: {"type": data.smart_type},
command_on="async_turn_on_off_smart",
command_off="async_turn_on_off_smart",
data_key="smart_on",
),
) )
PURE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = ( PURE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = (
@ -166,3 +178,15 @@ class SensiboDeviceSwitch(SensiboDeviceBaseEntity, SwitchEntity):
data["primeIntegration"] = False data["primeIntegration"] = False
result = await self._client.async_set_pureboost(self._device_id, data) result = await self._client.async_set_pureboost(self._device_id, data)
return bool(result.get("status") == "success") return bool(result.get("status") == "success")
@async_handle_api_call
async def async_turn_on_off_smart(self, key: str, value: Any) -> bool:
"""Make service call to api for setting Climate React."""
if self.device_data.smart_type is None:
raise HomeAssistantError(
"Use Sensibo Enable Climate React Service once to enable switch or the Sensibo app"
)
new_state = bool(self.device_data.smart_on is False)
data: dict[str, Any] = {"enabled": new_state}
result = await self._client.async_enable_climate_react(self._device_id, data)
return bool(result.get("status") == "success")

View File

@ -3,6 +3,11 @@
"sensibo__sensitivity": { "sensibo__sensitivity": {
"n": "Normal", "n": "Normal",
"s": "Sensitive" "s": "Sensitive"
},
"sensibo__smart_type": {
"feelslike": "Feels like",
"humidity": "Humidity",
"temperature": "Temperature"
} }
} }
} }

View File

@ -23,14 +23,20 @@ from homeassistant.components.climate import (
from homeassistant.components.sensibo.climate import ( from homeassistant.components.sensibo.climate import (
ATTR_AC_INTEGRATION, ATTR_AC_INTEGRATION,
ATTR_GEO_INTEGRATION, ATTR_GEO_INTEGRATION,
ATTR_HIGH_TEMPERATURE_STATE,
ATTR_HIGH_TEMPERATURE_THRESHOLD,
ATTR_HORIZONTAL_SWING_MODE, ATTR_HORIZONTAL_SWING_MODE,
ATTR_INDOOR_INTEGRATION, ATTR_INDOOR_INTEGRATION,
ATTR_LIGHT, ATTR_LIGHT,
ATTR_LOW_TEMPERATURE_STATE,
ATTR_LOW_TEMPERATURE_THRESHOLD,
ATTR_MINUTES, ATTR_MINUTES,
ATTR_OUTDOOR_INTEGRATION, ATTR_OUTDOOR_INTEGRATION,
ATTR_SENSITIVITY, ATTR_SENSITIVITY,
ATTR_SMART_TYPE,
ATTR_TARGET_TEMPERATURE, ATTR_TARGET_TEMPERATURE,
SERVICE_ASSUME_STATE, SERVICE_ASSUME_STATE,
SERVICE_ENABLE_CLIMATE_REACT,
SERVICE_ENABLE_PURE_BOOST, SERVICE_ENABLE_PURE_BOOST,
SERVICE_ENABLE_TIMER, SERVICE_ENABLE_TIMER,
SERVICE_FULL_STATE, SERVICE_FULL_STATE,
@ -923,6 +929,311 @@ async def test_climate_pure_boost(
assert state4.state == "s" assert state4.state == "s"
async def test_climate_climate_react(
hass: HomeAssistant,
entity_registry_enabled_by_default: AsyncMock,
load_int: ConfigEntry,
monkeypatch: pytest.MonkeyPatch,
get_data: SensiboData,
) -> None:
"""Test the Sensibo climate react custom service."""
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state_climate = hass.states.get("climate.hallway")
with patch(
"homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
), patch(
"homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
):
with pytest.raises(MultipleInvalid):
await hass.services.async_call(
DOMAIN,
SERVICE_ENABLE_PURE_BOOST,
{
ATTR_ENTITY_ID: state_climate.entity_id,
ATTR_LOW_TEMPERATURE_THRESHOLD: 0.2,
ATTR_HIGH_TEMPERATURE_THRESHOLD: 30.3,
ATTR_SMART_TYPE: "temperature",
},
blocking=True,
)
await hass.async_block_till_done()
with patch(
"homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
return_value=get_data,
), patch(
"homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
return_value={
"status": "success",
"result": {
"enabled": True,
"deviceUid": "ABC999111",
"highTemperatureState": {
"on": True,
"targetTemperature": 15,
"temperatureUnit": "C",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
"highTemperatureThreshold": 30.5,
"lowTemperatureState": {
"on": True,
"targetTemperature": 25,
"temperatureUnit": "C",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
"lowTemperatureThreshold": 5.5,
"type": "temperature",
},
},
):
await hass.services.async_call(
DOMAIN,
SERVICE_ENABLE_CLIMATE_REACT,
{
ATTR_ENTITY_ID: state_climate.entity_id,
ATTR_LOW_TEMPERATURE_THRESHOLD: 5.5,
ATTR_HIGH_TEMPERATURE_THRESHOLD: 30.5,
ATTR_LOW_TEMPERATURE_STATE: {
"on": True,
"targetTemperature": 25,
"temperatureUnit": "C",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
ATTR_HIGH_TEMPERATURE_STATE: {
"on": True,
"targetTemperature": 15,
"temperatureUnit": "C",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
ATTR_SMART_TYPE: "temperature",
},
blocking=True,
)
await hass.async_block_till_done()
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", True)
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_type", "temperature")
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_low_temp_threshold", 5.5)
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_high_temp_threshold", 30.5)
monkeypatch.setattr(
get_data.parsed["ABC999111"],
"smart_low_state",
{
"on": True,
"targetTemperature": 25,
"temperatureUnit": "C",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
)
monkeypatch.setattr(
get_data.parsed["ABC999111"],
"smart_high_state",
{
"on": True,
"targetTemperature": 15,
"temperatureUnit": "C",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
)
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state1 = hass.states.get("switch.hallway_climate_react")
state2 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
state3 = hass.states.get("sensor.hallway_climate_react_high_temperature_threshold")
state4 = hass.states.get("sensor.hallway_climate_react_type")
assert state1.state == "on"
assert state2.state == "5.5"
assert state3.state == "30.5"
assert state4.state == "temperature"
async def test_climate_climate_react_fahrenheit(
hass: HomeAssistant,
entity_registry_enabled_by_default: AsyncMock,
load_int: ConfigEntry,
monkeypatch: pytest.MonkeyPatch,
get_data: SensiboData,
) -> None:
"""Test the Sensibo climate react custom service with fahrenheit."""
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state_climate = hass.states.get("climate.hallway")
with patch(
"homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
return_value=get_data,
), patch(
"homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
return_value={
"status": "success",
"result": {
"enabled": True,
"deviceUid": "ABC999111",
"highTemperatureState": {
"on": True,
"targetTemperature": 65,
"temperatureUnit": "F",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
"highTemperatureThreshold": 77,
"lowTemperatureState": {
"on": True,
"targetTemperature": 85,
"temperatureUnit": "F",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
"lowTemperatureThreshold": 32,
"type": "temperature",
},
},
):
await hass.services.async_call(
DOMAIN,
SERVICE_ENABLE_CLIMATE_REACT,
{
ATTR_ENTITY_ID: state_climate.entity_id,
ATTR_LOW_TEMPERATURE_THRESHOLD: 32.0,
ATTR_HIGH_TEMPERATURE_THRESHOLD: 77.0,
ATTR_LOW_TEMPERATURE_STATE: {
"on": True,
"targetTemperature": 85,
"temperatureUnit": "F",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
ATTR_HIGH_TEMPERATURE_STATE: {
"on": True,
"targetTemperature": 65,
"temperatureUnit": "F",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
ATTR_SMART_TYPE: "temperature",
},
blocking=True,
)
await hass.async_block_till_done()
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", True)
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_type", "temperature")
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_low_temp_threshold", 0)
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_high_temp_threshold", 25)
monkeypatch.setattr(
get_data.parsed["ABC999111"],
"smart_low_state",
{
"on": True,
"targetTemperature": 85,
"temperatureUnit": "F",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
)
monkeypatch.setattr(
get_data.parsed["ABC999111"],
"smart_high_state",
{
"on": True,
"targetTemperature": 65,
"temperatureUnit": "F",
"mode": "cool",
"fanLevel": "high",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
},
)
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state1 = hass.states.get("switch.hallway_climate_react")
state2 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
state3 = hass.states.get("sensor.hallway_climate_react_high_temperature_threshold")
state4 = hass.states.get("sensor.hallway_climate_react_type")
assert state1.state == "on"
assert state2.state == "0"
assert state3.state == "25"
assert state4.state == "temperature"
async def test_climate_full_ac_state( async def test_climate_full_ac_state(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry_enabled_by_default: AsyncMock, entity_registry_enabled_by_default: AsyncMock,

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
from datetime import timedelta from datetime import timedelta
from unittest.mock import patch from unittest.mock import AsyncMock, patch
from pysensibo.model import SensiboData from pysensibo.model import SensiboData
from pytest import MonkeyPatch from pytest import MonkeyPatch
@ -16,6 +16,7 @@ from tests.common import async_fire_time_changed
async def test_sensor( async def test_sensor(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry_enabled_by_default: AsyncMock,
load_int: ConfigEntry, load_int: ConfigEntry,
monkeypatch: MonkeyPatch, monkeypatch: MonkeyPatch,
get_data: SensiboData, get_data: SensiboData,
@ -25,9 +26,11 @@ async def test_sensor(
state1 = hass.states.get("sensor.hallway_motion_sensor_battery_voltage") state1 = hass.states.get("sensor.hallway_motion_sensor_battery_voltage")
state2 = hass.states.get("sensor.kitchen_pm2_5") state2 = hass.states.get("sensor.kitchen_pm2_5")
state3 = hass.states.get("sensor.kitchen_pure_sensitivity") state3 = hass.states.get("sensor.kitchen_pure_sensitivity")
state4 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
assert state1.state == "3000" assert state1.state == "3000"
assert state2.state == "1" assert state2.state == "1"
assert state3.state == "n" assert state3.state == "n"
assert state4.state == "0.0"
assert state2.attributes == { assert state2.attributes == {
"state_class": "measurement", "state_class": "measurement",
"unit_of_measurement": "µg/m³", "unit_of_measurement": "µg/m³",
@ -35,6 +38,20 @@ async def test_sensor(
"icon": "mdi:air-filter", "icon": "mdi:air-filter",
"friendly_name": "Kitchen PM2.5", "friendly_name": "Kitchen PM2.5",
} }
assert state4.attributes == {
"device_class": "temperature",
"friendly_name": "Hallway Climate React low temperature threshold",
"state_class": "measurement",
"unit_of_measurement": "°C",
"on": True,
"targetTemperature": 21,
"temperatureUnit": "C",
"mode": "heat",
"fanLevel": "low",
"swing": "stopped",
"horizontalSwing": "stopped",
"light": "on",
}
monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pm25", 2) monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pm25", 2)

View File

@ -223,3 +223,113 @@ async def test_switch_command_failure(
}, },
blocking=True, blocking=True,
) )
async def test_switch_climate_react(
hass: HomeAssistant,
load_int: ConfigEntry,
monkeypatch: MonkeyPatch,
get_data: SensiboData,
) -> None:
"""Test the Sensibo switch for climate react."""
state1 = hass.states.get("switch.hallway_climate_react")
assert state1.state == STATE_OFF
with patch(
"homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
return_value=get_data,
), patch(
"homeassistant.components.sensibo.util.SensiboClient.async_enable_climate_react",
return_value={"status": "success"},
):
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: state1.entity_id,
},
blocking=True,
)
await hass.async_block_till_done()
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", True)
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state1 = hass.states.get("switch.hallway_climate_react")
assert state1.state == STATE_ON
with patch(
"homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
return_value=get_data,
), patch(
"homeassistant.components.sensibo.util.SensiboClient.async_enable_climate_react",
return_value={"status": "success"},
):
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: state1.entity_id,
},
blocking=True,
)
await hass.async_block_till_done()
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", False)
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state1 = hass.states.get("switch.hallway_climate_react")
assert state1.state == STATE_OFF
async def test_switch_climate_react_no_data(
hass: HomeAssistant,
load_int: ConfigEntry,
monkeypatch: MonkeyPatch,
get_data: SensiboData,
) -> None:
"""Test the Sensibo switch for climate react."""
monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_type", None)
with patch(
"homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
return_value=get_data,
):
async_fire_time_changed(
hass,
dt.utcnow() + timedelta(minutes=5),
)
await hass.async_block_till_done()
state1 = hass.states.get("switch.hallway_climate_react")
assert state1.state == STATE_OFF
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: state1.entity_id,
},
blocking=True,
)
await hass.async_block_till_done()