mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add get device capabilities action call for Sensibo (#134596)
* Add get device capabilities action call for Sensibo * Tests * Mod * Fix services --------- Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
acd95975e4
commit
eafbf1d1fd
@ -9,6 +9,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
ATTR_FAN_MODE,
|
ATTR_FAN_MODE,
|
||||||
|
ATTR_HVAC_MODE,
|
||||||
ATTR_SWING_MODE,
|
ATTR_SWING_MODE,
|
||||||
ClimateEntity,
|
ClimateEntity,
|
||||||
ClimateEntityFeature,
|
ClimateEntityFeature,
|
||||||
@ -21,8 +22,8 @@ from homeassistant.const import (
|
|||||||
PRECISION_TENTHS,
|
PRECISION_TENTHS,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, SupportsResponse
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.unit_conversion import TemperatureConverter
|
from homeassistant.util.unit_conversion import TemperatureConverter
|
||||||
@ -39,6 +40,7 @@ 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"
|
SERVICE_ENABLE_CLIMATE_REACT = "enable_climate_react"
|
||||||
|
SERVICE_GET_DEVICE_CAPABILITIES = "get_device_capabilities"
|
||||||
ATTR_HIGH_TEMPERATURE_THRESHOLD = "high_temperature_threshold"
|
ATTR_HIGH_TEMPERATURE_THRESHOLD = "high_temperature_threshold"
|
||||||
ATTR_HIGH_TEMPERATURE_STATE = "high_temperature_state"
|
ATTR_HIGH_TEMPERATURE_STATE = "high_temperature_state"
|
||||||
ATTR_LOW_TEMPERATURE_THRESHOLD = "low_temperature_threshold"
|
ATTR_LOW_TEMPERATURE_THRESHOLD = "low_temperature_threshold"
|
||||||
@ -172,7 +174,6 @@ async def async_setup_entry(
|
|||||||
},
|
},
|
||||||
"async_full_ac_state",
|
"async_full_ac_state",
|
||||||
)
|
)
|
||||||
|
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_ENABLE_CLIMATE_REACT,
|
SERVICE_ENABLE_CLIMATE_REACT,
|
||||||
{
|
{
|
||||||
@ -186,6 +187,12 @@ async def async_setup_entry(
|
|||||||
},
|
},
|
||||||
"async_enable_climate_react",
|
"async_enable_climate_react",
|
||||||
)
|
)
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_GET_DEVICE_CAPABILITIES,
|
||||||
|
{vol.Required(ATTR_HVAC_MODE): vol.Coerce(HVACMode)},
|
||||||
|
"async_get_device_capabilities",
|
||||||
|
supports_response=SupportsResponse.ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
|
class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
|
||||||
@ -390,6 +397,26 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
|
|||||||
assumed_state=False,
|
assumed_state=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def async_get_device_capabilities(
|
||||||
|
self, hvac_mode: HVACMode
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Get capabilities from device."""
|
||||||
|
active_features = self.device_data.active_features
|
||||||
|
mode_capabilities: dict[str, Any] | None = self.device_data.full_capabilities[
|
||||||
|
"modes"
|
||||||
|
].get(hvac_mode.value)
|
||||||
|
if not mode_capabilities:
|
||||||
|
raise ServiceValidationError(
|
||||||
|
translation_domain=DOMAIN, translation_key="mode_not_exist"
|
||||||
|
)
|
||||||
|
remote_capabilities: dict[str, Any] = {}
|
||||||
|
for active_feature in active_features:
|
||||||
|
if active_feature in mode_capabilities:
|
||||||
|
remote_capabilities[active_feature.lower()] = mode_capabilities[
|
||||||
|
active_feature
|
||||||
|
]
|
||||||
|
return remote_capabilities
|
||||||
|
|
||||||
async def async_assume_state(self, state: str) -> None:
|
async def async_assume_state(self, state: str) -> None:
|
||||||
"""Sync state with api."""
|
"""Sync state with api."""
|
||||||
await self.async_send_api_call(
|
await self.async_send_api_call(
|
||||||
|
@ -59,6 +59,9 @@
|
|||||||
},
|
},
|
||||||
"enable_climate_react": {
|
"enable_climate_react": {
|
||||||
"service": "mdi:wizard-hat"
|
"service": "mdi:wizard-hat"
|
||||||
|
},
|
||||||
|
"get_device_capabilities": {
|
||||||
|
"service": "mdi:shape-outline"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,3 +159,21 @@ enable_climate_react:
|
|||||||
- "feelslike"
|
- "feelslike"
|
||||||
- "humidity"
|
- "humidity"
|
||||||
translation_key: smart_type
|
translation_key: smart_type
|
||||||
|
get_device_capabilities:
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: sensibo
|
||||||
|
domain: climate
|
||||||
|
fields:
|
||||||
|
hvac_mode:
|
||||||
|
required: true
|
||||||
|
example: "heat"
|
||||||
|
selector:
|
||||||
|
select:
|
||||||
|
options:
|
||||||
|
- "auto"
|
||||||
|
- "cool"
|
||||||
|
- "dry"
|
||||||
|
- "fan"
|
||||||
|
- "heat"
|
||||||
|
translation_key: hvac_mode
|
||||||
|
@ -494,6 +494,16 @@
|
|||||||
"description": "Choose between temperature/feels like/humidity."
|
"description": "Choose between temperature/feels like/humidity."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"get_device_capabilities": {
|
||||||
|
"name": "Get device mode capabilities",
|
||||||
|
"description": "Retrieve the device capabilities for a specific device according to api requirements.",
|
||||||
|
"fields": {
|
||||||
|
"hvac_mode": {
|
||||||
|
"name": "[%key:component::climate::services::set_hvac_mode::fields::hvac_mode::name%]",
|
||||||
|
"description": "[%key:component::climate::services::set_hvac_mode::fields::hvac_mode::description%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
@ -561,6 +571,9 @@
|
|||||||
},
|
},
|
||||||
"no_data": {
|
"no_data": {
|
||||||
"message": "[%key:component::sensibo::config::error::no_devices%]"
|
"message": "[%key:component::sensibo::config::error::no_devices%]"
|
||||||
|
},
|
||||||
|
"mode_not_exist": {
|
||||||
|
"message": "The entity does not support the chosen mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,3 +227,23 @@
|
|||||||
'state': 'off',
|
'state': 'off',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_climate_get_device_capabilities
|
||||||
|
dict({
|
||||||
|
'climate.hallway': dict({
|
||||||
|
'horizontalswing': list([
|
||||||
|
'stopped',
|
||||||
|
'fixedLeft',
|
||||||
|
'fixedCenterLeft',
|
||||||
|
]),
|
||||||
|
'light': list([
|
||||||
|
'on',
|
||||||
|
'off',
|
||||||
|
]),
|
||||||
|
'swing': list([
|
||||||
|
'stopped',
|
||||||
|
'fixedTop',
|
||||||
|
'fixedMiddleTop',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
@ -43,6 +43,7 @@ from homeassistant.components.sensibo.climate import (
|
|||||||
SERVICE_ENABLE_PURE_BOOST,
|
SERVICE_ENABLE_PURE_BOOST,
|
||||||
SERVICE_ENABLE_TIMER,
|
SERVICE_ENABLE_TIMER,
|
||||||
SERVICE_FULL_STATE,
|
SERVICE_FULL_STATE,
|
||||||
|
SERVICE_GET_DEVICE_CAPABILITIES,
|
||||||
_find_valid_target_temp,
|
_find_valid_target_temp,
|
||||||
)
|
)
|
||||||
from homeassistant.components.sensibo.const import DOMAIN
|
from homeassistant.components.sensibo.const import DOMAIN
|
||||||
@ -1187,3 +1188,33 @@ async def test_climate_fan_mode_and_swing_mode_not_supported(
|
|||||||
state = hass.states.get("climate.hallway")
|
state = hass.states.get("climate.hallway")
|
||||||
assert state.attributes["fan_mode"] == "high"
|
assert state.attributes["fan_mode"] == "high"
|
||||||
assert state.attributes["swing_mode"] == "stopped"
|
assert state.attributes["swing_mode"] == "stopped"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_climate_get_device_capabilities(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
load_int: ConfigEntry,
|
||||||
|
mock_client: MagicMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test the Sensibo climate Get device capabilitites service."""
|
||||||
|
|
||||||
|
response = await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_GET_DEVICE_CAPABILITIES,
|
||||||
|
{ATTR_ENTITY_ID: "climate.hallway", ATTR_HVAC_MODE: "heat"},
|
||||||
|
blocking=True,
|
||||||
|
return_response=True,
|
||||||
|
)
|
||||||
|
assert response == snapshot
|
||||||
|
|
||||||
|
with pytest.raises(
|
||||||
|
ServiceValidationError, match="The entity does not support the chosen mode"
|
||||||
|
):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_GET_DEVICE_CAPABILITIES,
|
||||||
|
{ATTR_ENTITY_ID: "climate.hallway", ATTR_HVAC_MODE: "heat_cool"},
|
||||||
|
blocking=True,
|
||||||
|
return_response=True,
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user