core/homeassistant/components/icloud/services.py

140 lines
4.3 KiB
Python

"""The iCloud component."""
from __future__ import annotations
import voluptuous as vol
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.util import slugify
from .account import IcloudAccount, IcloudConfigEntry
from .const import (
ATTR_ACCOUNT,
ATTR_DEVICE_NAME,
ATTR_LOST_DEVICE_MESSAGE,
ATTR_LOST_DEVICE_NUMBER,
ATTR_LOST_DEVICE_SOUND,
DOMAIN,
)
# services
SERVICE_ICLOUD_PLAY_SOUND = "play_sound"
SERVICE_ICLOUD_DISPLAY_MESSAGE = "display_message"
SERVICE_ICLOUD_LOST_DEVICE = "lost_device"
SERVICE_ICLOUD_UPDATE = "update"
SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ACCOUNT): cv.string})
SERVICE_SCHEMA_PLAY_SOUND = vol.Schema(
{vol.Required(ATTR_ACCOUNT): cv.string, vol.Required(ATTR_DEVICE_NAME): cv.string}
)
SERVICE_SCHEMA_DISPLAY_MESSAGE = vol.Schema(
{
vol.Required(ATTR_ACCOUNT): cv.string,
vol.Required(ATTR_DEVICE_NAME): cv.string,
vol.Required(ATTR_LOST_DEVICE_MESSAGE): cv.string,
vol.Optional(ATTR_LOST_DEVICE_SOUND): cv.boolean,
}
)
SERVICE_SCHEMA_LOST_DEVICE = vol.Schema(
{
vol.Required(ATTR_ACCOUNT): cv.string,
vol.Required(ATTR_DEVICE_NAME): cv.string,
vol.Required(ATTR_LOST_DEVICE_NUMBER): cv.string,
vol.Required(ATTR_LOST_DEVICE_MESSAGE): cv.string,
}
)
def play_sound(service: ServiceCall) -> None:
"""Play sound on the device."""
account = service.data[ATTR_ACCOUNT]
device_name: str = service.data[ATTR_DEVICE_NAME]
device_name = slugify(device_name.replace(" ", "", 99))
for device in _get_account(service.hass, account).get_devices_with_name(
device_name
):
device.play_sound()
def display_message(service: ServiceCall) -> None:
"""Display a message on the device."""
account = service.data[ATTR_ACCOUNT]
device_name: str = service.data[ATTR_DEVICE_NAME]
device_name = slugify(device_name.replace(" ", "", 99))
message = service.data.get(ATTR_LOST_DEVICE_MESSAGE)
sound = service.data.get(ATTR_LOST_DEVICE_SOUND, False)
for device in _get_account(service.hass, account).get_devices_with_name(
device_name
):
device.display_message(message, sound)
def lost_device(service: ServiceCall) -> None:
"""Make the device in lost state."""
account = service.data[ATTR_ACCOUNT]
device_name: str = service.data[ATTR_DEVICE_NAME]
device_name = slugify(device_name.replace(" ", "", 99))
number = service.data.get(ATTR_LOST_DEVICE_NUMBER)
message = service.data.get(ATTR_LOST_DEVICE_MESSAGE)
for device in _get_account(service.hass, account).get_devices_with_name(
device_name
):
device.lost_device(number, message)
def update_account(service: ServiceCall) -> None:
"""Call the update function of an iCloud account."""
if (account := service.data.get(ATTR_ACCOUNT)) is None:
# Update all accounts when no specific account is provided
entry: IcloudConfigEntry
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
entry.runtime_data.keep_alive()
else:
_get_account(service.hass, account).keep_alive()
def _get_account(hass: HomeAssistant, account_identifier: str) -> IcloudAccount:
if account_identifier is None:
return None
entry: IcloudConfigEntry
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
if entry.runtime_data.username == account_identifier:
return entry.runtime_data
raise ValueError(f"No iCloud account with username or name {account_identifier}")
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Register iCloud services."""
hass.services.async_register(
DOMAIN, SERVICE_ICLOUD_PLAY_SOUND, play_sound, schema=SERVICE_SCHEMA_PLAY_SOUND
)
hass.services.async_register(
DOMAIN,
SERVICE_ICLOUD_DISPLAY_MESSAGE,
display_message,
schema=SERVICE_SCHEMA_DISPLAY_MESSAGE,
)
hass.services.async_register(
DOMAIN,
SERVICE_ICLOUD_LOST_DEVICE,
lost_device,
schema=SERVICE_SCHEMA_LOST_DEVICE,
)
hass.services.async_register(
DOMAIN, SERVICE_ICLOUD_UPDATE, update_account, schema=SERVICE_SCHEMA
)