diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 67e582c358c7..d6edd119cb7b 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -10,19 +10,19 @@ import probatio from propcache.api import cached_property from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( +from homeassistant.const import ( # noqa: F401 SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, ) -from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity import ToggleEntity, ToggleEntityDescription from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.frame import ReportBehavior, report_usage -from homeassistant.helpers.typing import ConfigType, VolDictType +from homeassistant.helpers.typing import ConfigType from homeassistant.util import color as color_util from .const import ( # noqa: F401 @@ -90,6 +90,7 @@ from .helper import ( # noqa: F401 process_turn_on_params, valid_supported_color_modes, ) +from .services import async_setup_services ENTITY_ID_FORMAT = DOMAIN + ".{}" PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA @@ -119,71 +120,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # of the light base platform. hass.async_create_task(profiles.async_initialize(), eager_start=True) - def preprocess_data(data: dict[str, Any]) -> VolDictType: - """Preprocess the service data.""" - base: VolDictType = { - entity_field: data.pop(entity_field) # type: ignore[arg-type] - for entity_field in cv.ENTITY_SERVICE_FIELDS - if entity_field in data - } - - preprocess_turn_on_alternatives(hass, data) - base["params"] = data - return base - - async def async_handle_light_on_service( - light: LightEntity, call: ServiceCall - ) -> None: - """Handle turning a light on. - - If brightness is set to 0, this service will turn the light off. - """ - params = process_turn_on_params(hass, light, call.data["params"]) - - if params.get(ATTR_BRIGHTNESS) == 0 or params.get(ATTR_WHITE) == 0: - await async_handle_light_off_service(light, call) - else: - await light.async_turn_on(**filter_turn_on_params(light, params)) - - async def async_handle_light_off_service( - light: LightEntity, call: ServiceCall - ) -> None: - """Handle turning off a light.""" - params = process_turn_off_params(hass, light, call.data["params"]) - - await light.async_turn_off(**filter_turn_off_params(light, params)) - - async def async_handle_toggle_service( - light: LightEntity, call: ServiceCall - ) -> None: - """Handle toggling a light.""" - await light.async_toggle(**call.data["params"]) - # Listen for light on and light off service calls. - component.async_register_entity_service( - SERVICE_TURN_ON, - probatio.All( - cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA), preprocess_data - ), - async_handle_light_on_service, - ) - - component.async_register_entity_service( - SERVICE_TURN_OFF, - probatio.All( - cv.make_entity_service_schema(LIGHT_TURN_OFF_SCHEMA), preprocess_data - ), - async_handle_light_off_service, - ) - - component.async_register_entity_service( - SERVICE_TOGGLE, - probatio.All( - cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA), preprocess_data - ), - async_handle_toggle_service, - ) + async_setup_services(hass) return True diff --git a/homeassistant/components/light/services.py b/homeassistant/components/light/services.py new file mode 100644 index 000000000000..a202f6970b11 --- /dev/null +++ b/homeassistant/components/light/services.py @@ -0,0 +1,102 @@ +"""Services for the light integration.""" + +from functools import partial +from typing import TYPE_CHECKING, Any + +import probatio + +from homeassistant.const import SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON +from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.typing import VolDictType + +from .const import ( + ATTR_BRIGHTNESS, + ATTR_WHITE, + DATA_COMPONENT, + LIGHT_TURN_OFF_SCHEMA, + LIGHT_TURN_ON_SCHEMA, +) +from .helper import ( + filter_turn_off_params, + filter_turn_on_params, + preprocess_turn_on_alternatives, + process_turn_off_params, + process_turn_on_params, +) + +if TYPE_CHECKING: + from . import LightEntity + + +def _preprocess_data(hass: HomeAssistant, data: dict[str, Any]) -> VolDictType: + """Preprocess the service data.""" + base: VolDictType = { + entity_field: data.pop(entity_field) # type: ignore[arg-type] + for entity_field in cv.ENTITY_SERVICE_FIELDS + if entity_field in data + } + + preprocess_turn_on_alternatives(hass, data) + base["params"] = data + return base + + +async def _async_handle_light_on_service(light: LightEntity, call: ServiceCall) -> None: + """Handle turning a light on. + + If brightness is set to 0, this service will turn the light off. + """ + params = process_turn_on_params(light.hass, light, call.data["params"]) + + if params.get(ATTR_BRIGHTNESS) == 0 or params.get(ATTR_WHITE) == 0: + await _async_handle_light_off_service(light, call) + else: + await light.async_turn_on(**filter_turn_on_params(light, params)) + + +async def _async_handle_light_off_service( + light: LightEntity, call: ServiceCall +) -> None: + """Handle turning off a light.""" + params = process_turn_off_params(light.hass, light, call.data["params"]) + + await light.async_turn_off(**filter_turn_off_params(light, params)) + + +async def _async_handle_toggle_service(light: LightEntity, call: ServiceCall) -> None: + """Handle toggling a light.""" + await light.async_toggle(**call.data["params"]) + + +@callback +def async_setup_services(hass: HomeAssistant) -> None: + """Register the light services.""" + component = hass.data[DATA_COMPONENT] + + component.async_register_entity_service( + SERVICE_TURN_ON, + probatio.All( + cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA), + partial(_preprocess_data, hass), + ), + _async_handle_light_on_service, + ) + + component.async_register_entity_service( + SERVICE_TURN_OFF, + probatio.All( + cv.make_entity_service_schema(LIGHT_TURN_OFF_SCHEMA), + partial(_preprocess_data, hass), + ), + _async_handle_light_off_service, + ) + + component.async_register_entity_service( + SERVICE_TOGGLE, + probatio.All( + cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA), + partial(_preprocess_data, hass), + ), + _async_handle_toggle_service, + )