Skip to content

Commit c2f7f29

Browse files
Setup platform services during integration start in sensibo (home-assistant#153571)
1 parent b01f5dd commit c2f7f29

File tree

4 files changed

+141
-102
lines changed

4 files changed

+141
-102
lines changed

homeassistant/components/sensibo/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,26 @@
88
from homeassistant.config_entries import ConfigEntry
99
from homeassistant.const import CONF_API_KEY
1010
from homeassistant.core import HomeAssistant
11-
from homeassistant.helpers import entity_registry as er
11+
from homeassistant.helpers import config_validation as cv, entity_registry as er
1212
from homeassistant.helpers.device_registry import DeviceEntry
13+
from homeassistant.helpers.typing import ConfigType
1314

1415
from .const import DOMAIN, LOGGER, PLATFORMS
1516
from .coordinator import SensiboDataUpdateCoordinator
17+
from .services import async_setup_services
1618
from .util import NoDevicesError, NoUsernameError, async_validate_api
1719

1820
type SensiboConfigEntry = ConfigEntry[SensiboDataUpdateCoordinator]
1921

22+
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
23+
24+
25+
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
26+
"""Set up the Sensibo component."""
27+
async_setup_services(hass)
28+
29+
return True
30+
2031

2132
async def async_setup_entry(hass: HomeAssistant, entry: SensiboConfigEntry) -> bool:
2233
"""Set up Sensibo from a config entry."""

homeassistant/components/sensibo/climate.py

Lines changed: 2 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,14 @@
55
from bisect import bisect_left
66
from typing import TYPE_CHECKING, Any
77

8-
import voluptuous as vol
9-
108
from homeassistant.components.climate import (
11-
ATTR_FAN_MODE,
12-
ATTR_HVAC_MODE,
13-
ATTR_SWING_MODE,
149
ClimateEntity,
1510
ClimateEntityFeature,
1611
HVACMode,
1712
)
18-
from homeassistant.const import (
19-
ATTR_MODE,
20-
ATTR_STATE,
21-
ATTR_TEMPERATURE,
22-
PRECISION_TENTHS,
23-
UnitOfTemperature,
24-
)
25-
from homeassistant.core import HomeAssistant, SupportsResponse
13+
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_TENTHS, UnitOfTemperature
14+
from homeassistant.core import HomeAssistant
2615
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
27-
from homeassistant.helpers import config_validation as cv, entity_platform
2816
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
2917
from homeassistant.util.unit_conversion import TemperatureConverter
3018

@@ -33,30 +21,6 @@
3321
from .coordinator import SensiboDataUpdateCoordinator
3422
from .entity import SensiboDeviceBaseEntity, async_handle_api_call
3523

36-
SERVICE_ASSUME_STATE = "assume_state"
37-
SERVICE_ENABLE_TIMER = "enable_timer"
38-
ATTR_MINUTES = "minutes"
39-
SERVICE_ENABLE_PURE_BOOST = "enable_pure_boost"
40-
SERVICE_DISABLE_PURE_BOOST = "disable_pure_boost"
41-
SERVICE_FULL_STATE = "full_state"
42-
SERVICE_ENABLE_CLIMATE_REACT = "enable_climate_react"
43-
SERVICE_GET_DEVICE_CAPABILITIES = "get_device_capabilities"
44-
ATTR_HIGH_TEMPERATURE_THRESHOLD = "high_temperature_threshold"
45-
ATTR_HIGH_TEMPERATURE_STATE = "high_temperature_state"
46-
ATTR_LOW_TEMPERATURE_THRESHOLD = "low_temperature_threshold"
47-
ATTR_LOW_TEMPERATURE_STATE = "low_temperature_state"
48-
ATTR_SMART_TYPE = "smart_type"
49-
50-
ATTR_AC_INTEGRATION = "ac_integration"
51-
ATTR_GEO_INTEGRATION = "geo_integration"
52-
ATTR_INDOOR_INTEGRATION = "indoor_integration"
53-
ATTR_OUTDOOR_INTEGRATION = "outdoor_integration"
54-
ATTR_SENSITIVITY = "sensitivity"
55-
ATTR_TARGET_TEMPERATURE = "target_temperature"
56-
ATTR_HORIZONTAL_SWING_MODE = "horizontal_swing_mode"
57-
ATTR_LIGHT = "light"
58-
BOOST_INCLUSIVE = "boost_inclusive"
59-
6024
AVAILABLE_FAN_MODES = {
6125
"quiet",
6226
"low",
@@ -162,66 +126,6 @@ def _add_remove_devices() -> None:
162126
entry.async_on_unload(coordinator.async_add_listener(_add_remove_devices))
163127
_add_remove_devices()
164128

165-
platform = entity_platform.async_get_current_platform()
166-
platform.async_register_entity_service(
167-
SERVICE_ASSUME_STATE,
168-
{
169-
vol.Required(ATTR_STATE): vol.In(["on", "off"]),
170-
},
171-
"async_assume_state",
172-
)
173-
platform.async_register_entity_service(
174-
SERVICE_ENABLE_TIMER,
175-
{
176-
vol.Required(ATTR_MINUTES): cv.positive_int,
177-
},
178-
"async_enable_timer",
179-
)
180-
platform.async_register_entity_service(
181-
SERVICE_ENABLE_PURE_BOOST,
182-
{
183-
vol.Required(ATTR_AC_INTEGRATION): bool,
184-
vol.Required(ATTR_GEO_INTEGRATION): bool,
185-
vol.Required(ATTR_INDOOR_INTEGRATION): bool,
186-
vol.Required(ATTR_OUTDOOR_INTEGRATION): bool,
187-
vol.Required(ATTR_SENSITIVITY): vol.In(["normal", "sensitive"]),
188-
},
189-
"async_enable_pure_boost",
190-
)
191-
platform.async_register_entity_service(
192-
SERVICE_FULL_STATE,
193-
{
194-
vol.Required(ATTR_MODE): vol.In(
195-
["cool", "heat", "fan", "auto", "dry", "off"]
196-
),
197-
vol.Optional(ATTR_TARGET_TEMPERATURE): int,
198-
vol.Optional(ATTR_FAN_MODE): str,
199-
vol.Optional(ATTR_SWING_MODE): str,
200-
vol.Optional(ATTR_HORIZONTAL_SWING_MODE): str,
201-
vol.Optional(ATTR_LIGHT): vol.In(["on", "off", "dim"]),
202-
},
203-
"async_full_ac_state",
204-
)
205-
platform.async_register_entity_service(
206-
SERVICE_ENABLE_CLIMATE_REACT,
207-
{
208-
vol.Required(ATTR_HIGH_TEMPERATURE_THRESHOLD): vol.Coerce(float),
209-
vol.Required(ATTR_HIGH_TEMPERATURE_STATE): dict,
210-
vol.Required(ATTR_LOW_TEMPERATURE_THRESHOLD): vol.Coerce(float),
211-
vol.Required(ATTR_LOW_TEMPERATURE_STATE): dict,
212-
vol.Required(ATTR_SMART_TYPE): vol.In(
213-
["temperature", "feelslike", "humidity"]
214-
),
215-
},
216-
"async_enable_climate_react",
217-
)
218-
platform.async_register_entity_service(
219-
SERVICE_GET_DEVICE_CAPABILITIES,
220-
{vol.Required(ATTR_HVAC_MODE): vol.Coerce(HVACMode)},
221-
"async_get_device_capabilities",
222-
supports_response=SupportsResponse.ONLY,
223-
)
224-
225129

226130
class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity):
227131
"""Representation of a Sensibo climate device."""
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""Sensibo services."""
2+
3+
from __future__ import annotations
4+
5+
import voluptuous as vol
6+
7+
from homeassistant.components.climate import (
8+
ATTR_FAN_MODE,
9+
ATTR_HVAC_MODE,
10+
ATTR_SWING_MODE,
11+
DOMAIN as CLIMATE_DOMAIN,
12+
HVACMode,
13+
)
14+
from homeassistant.const import ATTR_MODE, ATTR_STATE
15+
from homeassistant.core import HomeAssistant, SupportsResponse, callback
16+
from homeassistant.helpers import config_validation as cv, service
17+
18+
from .const import DOMAIN
19+
20+
SERVICE_ASSUME_STATE = "assume_state"
21+
SERVICE_ENABLE_TIMER = "enable_timer"
22+
ATTR_MINUTES = "minutes"
23+
SERVICE_ENABLE_PURE_BOOST = "enable_pure_boost"
24+
SERVICE_DISABLE_PURE_BOOST = "disable_pure_boost"
25+
SERVICE_FULL_STATE = "full_state"
26+
SERVICE_ENABLE_CLIMATE_REACT = "enable_climate_react"
27+
SERVICE_GET_DEVICE_CAPABILITIES = "get_device_capabilities"
28+
ATTR_HIGH_TEMPERATURE_THRESHOLD = "high_temperature_threshold"
29+
ATTR_HIGH_TEMPERATURE_STATE = "high_temperature_state"
30+
ATTR_LOW_TEMPERATURE_THRESHOLD = "low_temperature_threshold"
31+
ATTR_LOW_TEMPERATURE_STATE = "low_temperature_state"
32+
ATTR_SMART_TYPE = "smart_type"
33+
34+
ATTR_AC_INTEGRATION = "ac_integration"
35+
ATTR_GEO_INTEGRATION = "geo_integration"
36+
ATTR_INDOOR_INTEGRATION = "indoor_integration"
37+
ATTR_OUTDOOR_INTEGRATION = "outdoor_integration"
38+
ATTR_SENSITIVITY = "sensitivity"
39+
ATTR_TARGET_TEMPERATURE = "target_temperature"
40+
ATTR_HORIZONTAL_SWING_MODE = "horizontal_swing_mode"
41+
ATTR_LIGHT = "light"
42+
BOOST_INCLUSIVE = "boost_inclusive"
43+
44+
45+
@callback
46+
def async_setup_services(hass: HomeAssistant) -> None:
47+
"""Register Sensibo services."""
48+
49+
service.async_register_platform_entity_service(
50+
hass,
51+
DOMAIN,
52+
SERVICE_ASSUME_STATE,
53+
entity_domain=CLIMATE_DOMAIN,
54+
schema={
55+
vol.Required(ATTR_STATE): vol.In(["on", "off"]),
56+
},
57+
func="async_assume_state",
58+
)
59+
service.async_register_platform_entity_service(
60+
hass,
61+
DOMAIN,
62+
SERVICE_ENABLE_TIMER,
63+
entity_domain=CLIMATE_DOMAIN,
64+
schema={
65+
vol.Required(ATTR_MINUTES): cv.positive_int,
66+
},
67+
func="async_enable_timer",
68+
)
69+
service.async_register_platform_entity_service(
70+
hass,
71+
DOMAIN,
72+
SERVICE_ENABLE_PURE_BOOST,
73+
entity_domain=CLIMATE_DOMAIN,
74+
schema={
75+
vol.Required(ATTR_AC_INTEGRATION): bool,
76+
vol.Required(ATTR_GEO_INTEGRATION): bool,
77+
vol.Required(ATTR_INDOOR_INTEGRATION): bool,
78+
vol.Required(ATTR_OUTDOOR_INTEGRATION): bool,
79+
vol.Required(ATTR_SENSITIVITY): vol.In(["normal", "sensitive"]),
80+
},
81+
func="async_enable_pure_boost",
82+
)
83+
service.async_register_platform_entity_service(
84+
hass,
85+
DOMAIN,
86+
SERVICE_FULL_STATE,
87+
entity_domain=CLIMATE_DOMAIN,
88+
schema={
89+
vol.Required(ATTR_MODE): vol.In(
90+
["cool", "heat", "fan", "auto", "dry", "off"]
91+
),
92+
vol.Optional(ATTR_TARGET_TEMPERATURE): int,
93+
vol.Optional(ATTR_FAN_MODE): str,
94+
vol.Optional(ATTR_SWING_MODE): str,
95+
vol.Optional(ATTR_HORIZONTAL_SWING_MODE): str,
96+
vol.Optional(ATTR_LIGHT): vol.In(["on", "off", "dim"]),
97+
},
98+
func="async_full_ac_state",
99+
)
100+
service.async_register_platform_entity_service(
101+
hass,
102+
DOMAIN,
103+
SERVICE_ENABLE_CLIMATE_REACT,
104+
entity_domain=CLIMATE_DOMAIN,
105+
schema={
106+
vol.Required(ATTR_HIGH_TEMPERATURE_THRESHOLD): vol.Coerce(float),
107+
vol.Required(ATTR_HIGH_TEMPERATURE_STATE): dict,
108+
vol.Required(ATTR_LOW_TEMPERATURE_THRESHOLD): vol.Coerce(float),
109+
vol.Required(ATTR_LOW_TEMPERATURE_STATE): dict,
110+
vol.Required(ATTR_SMART_TYPE): vol.In(
111+
["temperature", "feelslike", "humidity"]
112+
),
113+
},
114+
func="async_enable_climate_react",
115+
)
116+
service.async_register_platform_entity_service(
117+
hass,
118+
DOMAIN,
119+
SERVICE_GET_DEVICE_CAPABILITIES,
120+
entity_domain=CLIMATE_DOMAIN,
121+
schema={vol.Required(ATTR_HVAC_MODE): vol.Coerce(HVACMode)},
122+
func="async_get_device_capabilities",
123+
supports_response=SupportsResponse.ONLY,
124+
)

tests/components/sensibo/test_climate.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
SERVICE_SET_TEMPERATURE,
2626
HVACMode,
2727
)
28-
from homeassistant.components.sensibo.climate import (
28+
from homeassistant.components.sensibo.climate import _find_valid_target_temp
29+
from homeassistant.components.sensibo.const import DOMAIN
30+
from homeassistant.components.sensibo.services import (
2931
ATTR_AC_INTEGRATION,
3032
ATTR_GEO_INTEGRATION,
3133
ATTR_HIGH_TEMPERATURE_STATE,
@@ -46,9 +48,7 @@
4648
SERVICE_ENABLE_TIMER,
4749
SERVICE_FULL_STATE,
4850
SERVICE_GET_DEVICE_CAPABILITIES,
49-
_find_valid_target_temp,
5051
)
51-
from homeassistant.components.sensibo.const import DOMAIN
5252
from homeassistant.config_entries import ConfigEntry
5353
from homeassistant.const import (
5454
ATTR_ENTITY_ID,

0 commit comments

Comments
 (0)