mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Move service definitions to separate module in guardian (#144306)
* Move service definitions to separate module in guardian * docstring
This commit is contained in:
parent
40e3038775
commit
2c34712069
@ -3,28 +3,16 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Callable, Coroutine
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT, Platform
|
||||||
ATTR_DEVICE_ID,
|
from homeassistant.core import HomeAssistant, callback
|
||||||
CONF_DEVICE_ID,
|
|
||||||
CONF_FILENAME,
|
|
||||||
CONF_IP_ADDRESS,
|
|
||||||
CONF_PORT,
|
|
||||||
CONF_URL,
|
|
||||||
Platform,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
|
||||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
API_SENSOR_PAIR_DUMP,
|
API_SENSOR_PAIR_DUMP,
|
||||||
@ -39,40 +27,10 @@ from .const import (
|
|||||||
SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED,
|
SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED,
|
||||||
)
|
)
|
||||||
from .coordinator import GuardianDataUpdateCoordinator
|
from .coordinator import GuardianDataUpdateCoordinator
|
||||||
|
from .services import setup_services
|
||||||
|
|
||||||
DATA_PAIRED_SENSOR_MANAGER = "paired_sensor_manager"
|
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
||||||
|
|
||||||
SERVICE_NAME_PAIR_SENSOR = "pair_sensor"
|
|
||||||
SERVICE_NAME_UNPAIR_SENSOR = "unpair_sensor"
|
|
||||||
SERVICE_NAME_UPGRADE_FIRMWARE = "upgrade_firmware"
|
|
||||||
|
|
||||||
SERVICES = (
|
|
||||||
SERVICE_NAME_PAIR_SENSOR,
|
|
||||||
SERVICE_NAME_UNPAIR_SENSOR,
|
|
||||||
SERVICE_NAME_UPGRADE_FIRMWARE,
|
|
||||||
)
|
|
||||||
|
|
||||||
SERVICE_BASE_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(ATTR_DEVICE_ID): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(ATTR_DEVICE_ID): cv.string,
|
|
||||||
vol.Required(CONF_UID): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SERVICE_UPGRADE_FIRMWARE_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(ATTR_DEVICE_ID): cv.string,
|
|
||||||
vol.Optional(CONF_URL): cv.url,
|
|
||||||
vol.Optional(CONF_PORT): cv.port,
|
|
||||||
vol.Optional(CONF_FILENAME): cv.string,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
@ -93,22 +51,10 @@ class GuardianData:
|
|||||||
paired_sensor_manager: PairedSensorManager
|
paired_sensor_manager: PairedSensorManager
|
||||||
|
|
||||||
|
|
||||||
@callback
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
def async_get_entry_id_for_service_call(hass: HomeAssistant, call: ServiceCall) -> str:
|
"""Set up the Elexa Guardian component."""
|
||||||
"""Get the entry ID related to a service call (by device ID)."""
|
setup_services(hass)
|
||||||
device_id = call.data[CONF_DEVICE_ID]
|
return True
|
||||||
device_registry = dr.async_get(hass)
|
|
||||||
|
|
||||||
if (device_entry := device_registry.async_get(device_id)) is None:
|
|
||||||
raise ValueError(f"Invalid Guardian device ID: {device_id}")
|
|
||||||
|
|
||||||
for entry_id in device_entry.config_entries:
|
|
||||||
if (entry := hass.config_entries.async_get_entry(entry_id)) is None:
|
|
||||||
continue
|
|
||||||
if entry.domain == DOMAIN:
|
|
||||||
return entry_id
|
|
||||||
|
|
||||||
raise ValueError(f"No config entry for device ID: {device_id}")
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
@ -173,71 +119,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
# Set up all of the Guardian entity platforms:
|
# Set up all of the Guardian entity platforms:
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
|
|
||||||
@callback
|
|
||||||
def call_with_data(
|
|
||||||
func: Callable[[ServiceCall, GuardianData], Coroutine[Any, Any, None]],
|
|
||||||
) -> Callable[[ServiceCall], Coroutine[Any, Any, None]]:
|
|
||||||
"""Hydrate a service call with the appropriate GuardianData object."""
|
|
||||||
|
|
||||||
async def wrapper(call: ServiceCall) -> None:
|
|
||||||
"""Wrap the service function."""
|
|
||||||
entry_id = async_get_entry_id_for_service_call(hass, call)
|
|
||||||
data = hass.data[DOMAIN][entry_id]
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with data.client:
|
|
||||||
await func(call, data)
|
|
||||||
except GuardianError as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f"Error while executing {func.__name__}: {err}"
|
|
||||||
) from err
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
@call_with_data
|
|
||||||
async def async_pair_sensor(call: ServiceCall, data: GuardianData) -> None:
|
|
||||||
"""Add a new paired sensor."""
|
|
||||||
uid = call.data[CONF_UID]
|
|
||||||
await data.client.sensor.pair_sensor(uid)
|
|
||||||
await data.paired_sensor_manager.async_pair_sensor(uid)
|
|
||||||
|
|
||||||
@call_with_data
|
|
||||||
async def async_unpair_sensor(call: ServiceCall, data: GuardianData) -> None:
|
|
||||||
"""Remove a paired sensor."""
|
|
||||||
uid = call.data[CONF_UID]
|
|
||||||
await data.client.sensor.unpair_sensor(uid)
|
|
||||||
await data.paired_sensor_manager.async_unpair_sensor(uid)
|
|
||||||
|
|
||||||
@call_with_data
|
|
||||||
async def async_upgrade_firmware(call: ServiceCall, data: GuardianData) -> None:
|
|
||||||
"""Upgrade the device firmware."""
|
|
||||||
await data.client.system.upgrade_firmware(
|
|
||||||
url=call.data[CONF_URL],
|
|
||||||
port=call.data[CONF_PORT],
|
|
||||||
filename=call.data[CONF_FILENAME],
|
|
||||||
)
|
|
||||||
|
|
||||||
for service_name, schema, method in (
|
|
||||||
(
|
|
||||||
SERVICE_NAME_PAIR_SENSOR,
|
|
||||||
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA,
|
|
||||||
async_pair_sensor,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
SERVICE_NAME_UNPAIR_SENSOR,
|
|
||||||
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA,
|
|
||||||
async_unpair_sensor,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
SERVICE_NAME_UPGRADE_FIRMWARE,
|
|
||||||
SERVICE_UPGRADE_FIRMWARE_SCHEMA,
|
|
||||||
async_upgrade_firmware,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
if hass.services.has_service(DOMAIN, service_name):
|
|
||||||
continue
|
|
||||||
hass.services.async_register(DOMAIN, service_name, method, schema=schema)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -247,12 +128,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
if unload_ok:
|
if unload_ok:
|
||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
if not hass.config_entries.async_loaded_entries(DOMAIN):
|
|
||||||
# If this is the last loaded instance of Guardian, deregister any services
|
|
||||||
# defined during integration setup:
|
|
||||||
for service_name in SERVICES:
|
|
||||||
hass.services.async_remove(DOMAIN, service_name)
|
|
||||||
|
|
||||||
return unload_ok
|
return unload_ok
|
||||||
|
|
||||||
|
|
||||||
|
145
homeassistant/components/guardian/services.py
Normal file
145
homeassistant/components/guardian/services.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
"""Support for Guardian services."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable, Coroutine
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
from aioguardian.errors import GuardianError
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_DEVICE_ID,
|
||||||
|
CONF_DEVICE_ID,
|
||||||
|
CONF_FILENAME,
|
||||||
|
CONF_PORT,
|
||||||
|
CONF_URL,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||||
|
|
||||||
|
from .const import CONF_UID, DOMAIN
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import GuardianData
|
||||||
|
|
||||||
|
SERVICE_NAME_PAIR_SENSOR = "pair_sensor"
|
||||||
|
SERVICE_NAME_UNPAIR_SENSOR = "unpair_sensor"
|
||||||
|
SERVICE_NAME_UPGRADE_FIRMWARE = "upgrade_firmware"
|
||||||
|
|
||||||
|
SERVICES = (
|
||||||
|
SERVICE_NAME_PAIR_SENSOR,
|
||||||
|
SERVICE_NAME_UNPAIR_SENSOR,
|
||||||
|
SERVICE_NAME_UPGRADE_FIRMWARE,
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVICE_BASE_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(ATTR_DEVICE_ID): cv.string,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(ATTR_DEVICE_ID): cv.string,
|
||||||
|
vol.Required(CONF_UID): cv.string,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVICE_UPGRADE_FIRMWARE_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(ATTR_DEVICE_ID): cv.string,
|
||||||
|
vol.Optional(CONF_URL): cv.url,
|
||||||
|
vol.Optional(CONF_PORT): cv.port,
|
||||||
|
vol.Optional(CONF_FILENAME): cv.string,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_get_entry_id_for_service_call(call: ServiceCall) -> str:
|
||||||
|
"""Get the entry ID related to a service call (by device ID)."""
|
||||||
|
device_id = call.data[CONF_DEVICE_ID]
|
||||||
|
device_registry = dr.async_get(call.hass)
|
||||||
|
|
||||||
|
if (device_entry := device_registry.async_get(device_id)) is None:
|
||||||
|
raise ValueError(f"Invalid Guardian device ID: {device_id}")
|
||||||
|
|
||||||
|
for entry_id in device_entry.config_entries:
|
||||||
|
if (entry := call.hass.config_entries.async_get_entry(entry_id)) is None:
|
||||||
|
continue
|
||||||
|
if entry.domain == DOMAIN:
|
||||||
|
return entry_id
|
||||||
|
|
||||||
|
raise ValueError(f"No config entry for device ID: {device_id}")
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def call_with_data(
|
||||||
|
func: Callable[[ServiceCall, GuardianData], Coroutine[Any, Any, None]],
|
||||||
|
) -> Callable[[ServiceCall], Coroutine[Any, Any, None]]:
|
||||||
|
"""Hydrate a service call with the appropriate GuardianData object."""
|
||||||
|
|
||||||
|
async def wrapper(call: ServiceCall) -> None:
|
||||||
|
"""Wrap the service function."""
|
||||||
|
entry_id = async_get_entry_id_for_service_call(call)
|
||||||
|
data = call.hass.data[DOMAIN][entry_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with data.client:
|
||||||
|
await func(call, data)
|
||||||
|
except GuardianError as err:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Error while executing {func.__name__}: {err}"
|
||||||
|
) from err
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@call_with_data
|
||||||
|
async def async_pair_sensor(call: ServiceCall, data: GuardianData) -> None:
|
||||||
|
"""Add a new paired sensor."""
|
||||||
|
uid = call.data[CONF_UID]
|
||||||
|
await data.client.sensor.pair_sensor(uid)
|
||||||
|
await data.paired_sensor_manager.async_pair_sensor(uid)
|
||||||
|
|
||||||
|
|
||||||
|
@call_with_data
|
||||||
|
async def async_unpair_sensor(call: ServiceCall, data: GuardianData) -> None:
|
||||||
|
"""Remove a paired sensor."""
|
||||||
|
uid = call.data[CONF_UID]
|
||||||
|
await data.client.sensor.unpair_sensor(uid)
|
||||||
|
await data.paired_sensor_manager.async_unpair_sensor(uid)
|
||||||
|
|
||||||
|
|
||||||
|
@call_with_data
|
||||||
|
async def async_upgrade_firmware(call: ServiceCall, data: GuardianData) -> None:
|
||||||
|
"""Upgrade the device firmware."""
|
||||||
|
await data.client.system.upgrade_firmware(
|
||||||
|
url=call.data[CONF_URL],
|
||||||
|
port=call.data[CONF_PORT],
|
||||||
|
filename=call.data[CONF_FILENAME],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_services(hass: HomeAssistant) -> None:
|
||||||
|
"""Register the Renault services."""
|
||||||
|
for service_name, schema, method in (
|
||||||
|
(
|
||||||
|
SERVICE_NAME_PAIR_SENSOR,
|
||||||
|
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA,
|
||||||
|
async_pair_sensor,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SERVICE_NAME_UNPAIR_SENSOR,
|
||||||
|
SERVICE_PAIR_UNPAIR_SENSOR_SCHEMA,
|
||||||
|
async_unpair_sensor,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SERVICE_NAME_UPGRADE_FIRMWARE,
|
||||||
|
SERVICE_UPGRADE_FIRMWARE_SCHEMA,
|
||||||
|
async_upgrade_firmware,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
hass.services.async_register(DOMAIN, service_name, method, schema=schema)
|
Loading…
x
Reference in New Issue
Block a user