diff --git a/homeassistant/components/blue_current/__init__.py b/homeassistant/components/blue_current/__init__.py index 5d066968873..73255ae7669 100644 --- a/homeassistant/components/blue_current/__init__.py +++ b/homeassistant/components/blue_current/__init__.py @@ -13,32 +13,25 @@ from bluecurrent_api.exceptions import ( RequestLimitReached, WebsocketError, ) -import voluptuous as vol -from homeassistant.config_entries import ConfigEntry, ConfigEntryState -from homeassistant.const import CONF_API_TOKEN, CONF_DEVICE_ID, Platform -from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.exceptions import ( - ConfigEntryAuthFailed, - ConfigEntryNotReady, - ServiceValidationError, -) -from homeassistant.helpers import config_validation as cv, device_registry as dr +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_API_TOKEN, Platform +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady +from homeassistant.helpers import config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.typing import ConfigType from .const import ( - BCU_APP, CHARGEPOINT_SETTINGS, CHARGEPOINT_STATUS, - CHARGING_CARD_ID, DOMAIN, EVSE_ID, LOGGER, PLUG_AND_CHARGE, - SERVICE_START_CHARGE_SESSION, VALUE, ) +from .services import async_setup_services type BlueCurrentConfigEntry = ConfigEntry[Connector] @@ -54,13 +47,12 @@ VALUE_TYPES = [CHARGEPOINT_STATUS, CHARGEPOINT_SETTINGS] CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) -SERVICE_START_CHARGE_SESSION_SCHEMA = vol.Schema( - { - vol.Required(CONF_DEVICE_ID): cv.string, - # When no charging card is provided, use no charging card (BCU_APP = no charging card). - vol.Optional(CHARGING_CARD_ID, default=BCU_APP): cv.string, - } -) + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up Blue Current.""" + + async_setup_services(hass) + return True async def async_setup_entry( @@ -88,66 +80,6 @@ async def async_setup_entry( return True -async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: - """Set up Blue Current.""" - - async def start_charge_session(service_call: ServiceCall) -> None: - """Start a charge session with the provided device and charge card ID.""" - # When no charge card is provided, use the default charge card set in the config flow. - charging_card_id = service_call.data[CHARGING_CARD_ID] - device_id = service_call.data[CONF_DEVICE_ID] - - # Get the device based on the given device ID. - device = dr.async_get(hass).devices.get(device_id) - - if device is None: - raise ServiceValidationError( - translation_domain=DOMAIN, translation_key="invalid_device_id" - ) - - blue_current_config_entry: ConfigEntry | None = None - - for config_entry_id in device.config_entries: - config_entry = hass.config_entries.async_get_entry(config_entry_id) - if not config_entry or config_entry.domain != DOMAIN: - # Not the blue_current config entry. - continue - - if config_entry.state is not ConfigEntryState.LOADED: - raise ServiceValidationError( - translation_domain=DOMAIN, translation_key="config_entry_not_loaded" - ) - - blue_current_config_entry = config_entry - break - - if not blue_current_config_entry: - # The device is not connected to a valid blue_current config entry. - raise ServiceValidationError( - translation_domain=DOMAIN, translation_key="no_config_entry" - ) - - connector = blue_current_config_entry.runtime_data - - # Get the evse_id from the identifier of the device. - evse_id = next( - identifier[1] - for identifier in device.identifiers - if identifier[0] == DOMAIN - ) - - await connector.client.start_session(evse_id, charging_card_id) - - hass.services.async_register( - DOMAIN, - SERVICE_START_CHARGE_SESSION, - start_charge_session, - SERVICE_START_CHARGE_SESSION_SCHEMA, - ) - - return True - - async def async_unload_entry( hass: HomeAssistant, config_entry: BlueCurrentConfigEntry ) -> bool: diff --git a/homeassistant/components/blue_current/services.py b/homeassistant/components/blue_current/services.py new file mode 100644 index 00000000000..8cd133ccdef --- /dev/null +++ b/homeassistant/components/blue_current/services.py @@ -0,0 +1,79 @@ +"""The Blue Current integration.""" + +from __future__ import annotations + +import voluptuous as vol + +from homeassistant.config_entries import ConfigEntry, ConfigEntryState +from homeassistant.const import CONF_DEVICE_ID +from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.exceptions import ServiceValidationError +from homeassistant.helpers import config_validation as cv, device_registry as dr + +from .const import BCU_APP, CHARGING_CARD_ID, DOMAIN, SERVICE_START_CHARGE_SESSION + +SERVICE_START_CHARGE_SESSION_SCHEMA = vol.Schema( + { + vol.Required(CONF_DEVICE_ID): cv.string, + # When no charging card is provided, use no charging card (BCU_APP = no charging card). + vol.Optional(CHARGING_CARD_ID, default=BCU_APP): cv.string, + } +) + + +async def start_charge_session(service_call: ServiceCall) -> None: + """Start a charge session with the provided device and charge card ID.""" + # When no charge card is provided, use the default charge card set in the config flow. + charging_card_id = service_call.data[CHARGING_CARD_ID] + device_id = service_call.data[CONF_DEVICE_ID] + + # Get the device based on the given device ID. + device = dr.async_get(service_call.hass).devices.get(device_id) + + if device is None: + raise ServiceValidationError( + translation_domain=DOMAIN, translation_key="invalid_device_id" + ) + + blue_current_config_entry: ConfigEntry | None = None + + for config_entry_id in device.config_entries: + config_entry = service_call.hass.config_entries.async_get_entry(config_entry_id) + if not config_entry or config_entry.domain != DOMAIN: + # Not the blue_current config entry. + continue + + if config_entry.state is not ConfigEntryState.LOADED: + raise ServiceValidationError( + translation_domain=DOMAIN, translation_key="config_entry_not_loaded" + ) + + blue_current_config_entry = config_entry + break + + if not blue_current_config_entry: + # The device is not connected to a valid blue_current config entry. + raise ServiceValidationError( + translation_domain=DOMAIN, translation_key="no_config_entry" + ) + + connector = blue_current_config_entry.runtime_data + + # Get the evse_id from the identifier of the device. + evse_id = next( + identifier[1] for identifier in device.identifiers if identifier[0] == DOMAIN + ) + + await connector.client.start_session(evse_id, charging_card_id) + + +@callback +def async_setup_services(hass: HomeAssistant) -> None: + """Register the services.""" + + hass.services.async_register( + DOMAIN, + SERVICE_START_CHARGE_SESSION, + start_charge_session, + SERVICE_START_CHARGE_SESSION_SCHEMA, + ) diff --git a/tests/components/blue_current/test_init.py b/tests/components/blue_current/test_init.py index 563a8392dc8..b3a6bdc5ab7 100644 --- a/tests/components/blue_current/test_init.py +++ b/tests/components/blue_current/test_init.py @@ -12,11 +12,11 @@ from bluecurrent_api.exceptions import ( import pytest from voluptuous import MultipleInvalid -from homeassistant.components.blue_current import ( +from homeassistant.components.blue_current import async_setup_entry +from homeassistant.components.blue_current.const import ( CHARGING_CARD_ID, DOMAIN, SERVICE_START_CHARGE_SESSION, - async_setup_entry, ) from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_DEVICE_ID, Platform