mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add Sensibo Climate React (#78221)
This commit is contained in:
parent
746bdb44ac
commit
b04165b495
@ -38,6 +38,12 @@ ATTR_MINUTES = "minutes"
|
||||
SERVICE_ENABLE_PURE_BOOST = "enable_pure_boost"
|
||||
SERVICE_DISABLE_PURE_BOOST = "disable_pure_boost"
|
||||
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_GEO_INTEGRATION = "geo_integration"
|
||||
@ -140,6 +146,20 @@ async def async_setup_entry(
|
||||
"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):
|
||||
"""Representation of a Sensibo device."""
|
||||
@ -430,6 +450,42 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
|
||||
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 def async_send_api_call(
|
||||
self,
|
||||
@ -470,6 +526,17 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
|
||||
result = await self._client.async_set_pureboost(self._device_id, data)
|
||||
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 def api_call_custom_service_full_ac_state(
|
||||
self,
|
||||
|
@ -155,6 +155,32 @@ DEVICE_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
|
||||
extra_fn=None,
|
||||
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,
|
||||
)
|
||||
|
||||
@ -281,7 +307,10 @@ class SensiboDeviceSensor(SensiboDeviceBaseEntity, SensorEntity):
|
||||
@property
|
||||
def native_value(self) -> StateType | datetime:
|
||||
"""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
|
||||
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
||||
|
@ -146,3 +146,56 @@ full_state:
|
||||
options:
|
||||
- "on"
|
||||
- "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"
|
||||
|
@ -3,6 +3,11 @@
|
||||
"sensibo__sensitivity": {
|
||||
"n": "Normal",
|
||||
"s": "Sensitive"
|
||||
},
|
||||
"sensibo__smart_type": {
|
||||
"temperature": "Temperature",
|
||||
"feelslike": "Feels like",
|
||||
"humidity": "Humidity"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ from homeassistant.components.switch import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
@ -53,6 +54,17 @@ DEVICE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = (
|
||||
command_off="async_turn_off_timer",
|
||||
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, ...] = (
|
||||
@ -166,3 +178,15 @@ class SensiboDeviceSwitch(SensiboDeviceBaseEntity, SwitchEntity):
|
||||
data["primeIntegration"] = False
|
||||
result = await self._client.async_set_pureboost(self._device_id, data)
|
||||
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")
|
||||
|
@ -3,6 +3,11 @@
|
||||
"sensibo__sensitivity": {
|
||||
"n": "Normal",
|
||||
"s": "Sensitive"
|
||||
},
|
||||
"sensibo__smart_type": {
|
||||
"feelslike": "Feels like",
|
||||
"humidity": "Humidity",
|
||||
"temperature": "Temperature"
|
||||
}
|
||||
}
|
||||
}
|
@ -23,14 +23,20 @@ from homeassistant.components.climate import (
|
||||
from homeassistant.components.sensibo.climate import (
|
||||
ATTR_AC_INTEGRATION,
|
||||
ATTR_GEO_INTEGRATION,
|
||||
ATTR_HIGH_TEMPERATURE_STATE,
|
||||
ATTR_HIGH_TEMPERATURE_THRESHOLD,
|
||||
ATTR_HORIZONTAL_SWING_MODE,
|
||||
ATTR_INDOOR_INTEGRATION,
|
||||
ATTR_LIGHT,
|
||||
ATTR_LOW_TEMPERATURE_STATE,
|
||||
ATTR_LOW_TEMPERATURE_THRESHOLD,
|
||||
ATTR_MINUTES,
|
||||
ATTR_OUTDOOR_INTEGRATION,
|
||||
ATTR_SENSITIVITY,
|
||||
ATTR_SMART_TYPE,
|
||||
ATTR_TARGET_TEMPERATURE,
|
||||
SERVICE_ASSUME_STATE,
|
||||
SERVICE_ENABLE_CLIMATE_REACT,
|
||||
SERVICE_ENABLE_PURE_BOOST,
|
||||
SERVICE_ENABLE_TIMER,
|
||||
SERVICE_FULL_STATE,
|
||||
@ -923,6 +929,311 @@ async def test_climate_pure_boost(
|
||||
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(
|
||||
hass: HomeAssistant,
|
||||
entity_registry_enabled_by_default: AsyncMock,
|
||||
|
@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from pysensibo.model import SensiboData
|
||||
from pytest import MonkeyPatch
|
||||
@ -16,6 +16,7 @@ from tests.common import async_fire_time_changed
|
||||
|
||||
async def test_sensor(
|
||||
hass: HomeAssistant,
|
||||
entity_registry_enabled_by_default: AsyncMock,
|
||||
load_int: ConfigEntry,
|
||||
monkeypatch: MonkeyPatch,
|
||||
get_data: SensiboData,
|
||||
@ -25,9 +26,11 @@ async def test_sensor(
|
||||
state1 = hass.states.get("sensor.hallway_motion_sensor_battery_voltage")
|
||||
state2 = hass.states.get("sensor.kitchen_pm2_5")
|
||||
state3 = hass.states.get("sensor.kitchen_pure_sensitivity")
|
||||
state4 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
|
||||
assert state1.state == "3000"
|
||||
assert state2.state == "1"
|
||||
assert state3.state == "n"
|
||||
assert state4.state == "0.0"
|
||||
assert state2.attributes == {
|
||||
"state_class": "measurement",
|
||||
"unit_of_measurement": "µg/m³",
|
||||
@ -35,6 +38,20 @@ async def test_sensor(
|
||||
"icon": "mdi:air-filter",
|
||||
"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)
|
||||
|
||||
|
@ -223,3 +223,113 @@ async def test_switch_command_failure(
|
||||
},
|
||||
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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user