Home Assistant Unofficial Reference 2024.12.1
services.py
Go to the documentation of this file.
1 """Services for ScreenLogic integration."""
2 
3 import logging
4 from typing import cast
5 
6 from screenlogicpy import ScreenLogicError
7 from screenlogicpy.device_const.system import EQUIPMENT_FLAG
8 import voluptuous as vol
9 
10 from homeassistant.config_entries import ConfigEntryState
11 from homeassistant.core import HomeAssistant, ServiceCall, callback
12 from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
13 from homeassistant.helpers import selector
14 
15 from .const import (
16  ATTR_COLOR_MODE,
17  ATTR_CONFIG_ENTRY,
18  ATTR_RUNTIME,
19  DOMAIN,
20  MAX_RUNTIME,
21  MIN_RUNTIME,
22  SERVICE_SET_COLOR_MODE,
23  SERVICE_START_SUPER_CHLORINATION,
24  SERVICE_STOP_SUPER_CHLORINATION,
25  SUPPORTED_COLOR_MODES,
26 )
27 from .coordinator import ScreenlogicDataUpdateCoordinator
28 from .types import ScreenLogicConfigEntry
29 
30 _LOGGER = logging.getLogger(__name__)
31 
32 BASE_SERVICE_SCHEMA = vol.Schema(
33  {
34  vol.Required(ATTR_CONFIG_ENTRY): selector.ConfigEntrySelector(
35  {
36  "integration": DOMAIN,
37  }
38  )
39  }
40 )
41 
42 SET_COLOR_MODE_SCHEMA = BASE_SERVICE_SCHEMA.extend(
43  {
44  vol.Required(ATTR_COLOR_MODE): vol.In(SUPPORTED_COLOR_MODES),
45  }
46 )
47 
48 TURN_ON_SUPER_CHLOR_SCHEMA = BASE_SERVICE_SCHEMA.extend(
49  {
50  vol.Optional(ATTR_RUNTIME, default=24): vol.All(
51  vol.Coerce(int), vol.Clamp(min=MIN_RUNTIME, max=MAX_RUNTIME)
52  ),
53  }
54 )
55 
56 
57 @callback
58 def async_load_screenlogic_services(hass: HomeAssistant):
59  """Set up services for the ScreenLogic integration."""
60 
61  async def get_coordinators(
62  service_call: ServiceCall,
63  ) -> list[ScreenlogicDataUpdateCoordinator]:
64  entry_ids = {service_call.data[ATTR_CONFIG_ENTRY]}
65  coordinators: list[ScreenlogicDataUpdateCoordinator] = []
66  for entry_id in entry_ids:
67  config_entry = cast(
68  ScreenLogicConfigEntry | None,
69  hass.config_entries.async_get_entry(entry_id),
70  )
71  if not config_entry:
73  f"Failed to call service '{service_call.service}'. Config entry "
74  f"'{entry_id}' not found"
75  )
76  if not config_entry.domain == DOMAIN:
78  f"Failed to call service '{service_call.service}'. Config entry "
79  f"'{entry_id}' is not a {DOMAIN} config"
80  )
81  if not config_entry.state == ConfigEntryState.LOADED:
83  f"Failed to call service '{service_call.service}'. Config entry "
84  f"'{entry_id}' not loaded"
85  )
86  coordinators.append(config_entry.runtime_data)
87 
88  return coordinators
89 
90  async def async_set_color_mode(service_call: ServiceCall) -> None:
91  color_num = SUPPORTED_COLOR_MODES[service_call.data[ATTR_COLOR_MODE]]
92  coordinator: ScreenlogicDataUpdateCoordinator
93  for coordinator in await get_coordinators(service_call):
94  _LOGGER.debug(
95  "Service %s called on %s with mode %s",
96  SERVICE_SET_COLOR_MODE,
97  coordinator.gateway.name,
98  color_num,
99  )
100  try:
101  await coordinator.gateway.async_set_color_lights(color_num)
102  # Debounced refresh to catch any secondary changes in the device
103  await coordinator.async_request_refresh()
104  except ScreenLogicError as error:
105  raise HomeAssistantError(error) from error
106 
107  async def async_set_super_chlor(
108  service_call: ServiceCall,
109  is_on: bool,
110  runtime: int | None = None,
111  ) -> None:
112  coordinator: ScreenlogicDataUpdateCoordinator
113  for coordinator in await get_coordinators(service_call):
114  if EQUIPMENT_FLAG.CHLORINATOR not in coordinator.gateway.equipment_flags:
116  f"Equipment configuration for {coordinator.gateway.name} does not"
117  f" support {service_call.service}"
118  )
119  rt_log = f" with runtime {runtime}" if runtime else ""
120  _LOGGER.debug(
121  "Service %s called on %s%s",
122  service_call.service,
123  coordinator.gateway.name,
124  rt_log,
125  )
126  try:
127  await coordinator.gateway.async_set_scg_config(
128  super_chlor_timer=runtime, super_chlorinate=is_on
129  )
130  # Debounced refresh to catch any secondary changes in the device
131  await coordinator.async_request_refresh()
132  except ScreenLogicError as error:
133  raise HomeAssistantError(error) from error
134 
135  async def async_start_super_chlor(service_call: ServiceCall) -> None:
136  runtime = service_call.data[ATTR_RUNTIME]
137  await async_set_super_chlor(service_call, True, runtime)
138 
139  async def async_stop_super_chlor(service_call: ServiceCall) -> None:
140  await async_set_super_chlor(service_call, False)
141 
142  hass.services.async_register(
143  DOMAIN, SERVICE_SET_COLOR_MODE, async_set_color_mode, SET_COLOR_MODE_SCHEMA
144  )
145 
146  hass.services.async_register(
147  DOMAIN,
148  SERVICE_START_SUPER_CHLORINATION,
149  async_start_super_chlor,
150  TURN_ON_SUPER_CHLOR_SCHEMA,
151  )
152 
153  hass.services.async_register(
154  DOMAIN,
155  SERVICE_STOP_SUPER_CHLORINATION,
156  async_stop_super_chlor,
157  BASE_SERVICE_SCHEMA,
158  )
def async_load_screenlogic_services(HomeAssistant hass)
Definition: services.py:58