| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- """Global services file.
- This needs to be viewed with the services.yaml file
- to demonstrate the different setup for using these services in the UI
- IMPORTANT NOTES:
- To ensure your service runs on the event loop, either make service function async
- or decorate with @callback. However, ensure that your function is non blocking or,
- if it is, run in the executor.
- Both examples are shown here. Running services on different threads can cause issues.
- https://developers.home-assistant.io/docs/dev_101_services/
- """
- import voluptuous as vol
- from homeassistant.config_entries import ConfigEntry
- from homeassistant.const import ATTR_DEVICE_ID, ATTR_NAME
- from homeassistant.core import HomeAssistant, ServiceCall, SupportsResponse, callback
- from homeassistant.exceptions import HomeAssistantError
- import homeassistant.helpers.device_registry as dr
- from .const import DOMAIN, RENAME_DEVICE_SERVICE_NAME, RESPONSE_SERVICE_NAME
- from .coordinator import ExampleCoordinator
- ATTR_TEXT = "text"
- # Services schemas
- RENAME_DEVICE_SERVICE_SCHEMA = vol.Schema(
- {
- vol.Required(ATTR_DEVICE_ID): int,
- vol.Required(ATTR_NAME): str,
- }
- )
- RESPONSE_SERVICE_SCHEMA = vol.Schema(
- {
- vol.Required(ATTR_DEVICE_ID): int,
- }
- )
- class ExampleServicesSetup:
- """Class to handle Integration Services."""
- def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
- """Initialise services."""
- self.hass = hass
- self.config_entry = config_entry
- self.coordinator: ExampleCoordinator = config_entry.runtime_data.coordinator
- self.setup_services()
- def setup_services(self):
- """Initialise the services in Hass."""
- # ----------------------------------------------------------------------------
- # A simple definition of a service with 2 parameters, as denoted by the
- # RENAME_DEVICE_SERVICE_SCHEMA
- # ----------------------------------------------------------------------------
- self.hass.services.async_register(
- DOMAIN,
- RENAME_DEVICE_SERVICE_NAME,
- self.rename_device,
- schema=RENAME_DEVICE_SERVICE_SCHEMA,
- )
- # ----------------------------------------------------------------------------
- # The definition here for a response service is the same as before but you
- # must include supports_response = only/optional
- # https://developers.home-assistant.io/docs/dev_101_services/#supporting-response-data
- # ----------------------------------------------------------------------------
- self.hass.services.async_register(
- DOMAIN,
- RESPONSE_SERVICE_NAME,
- self.async_response_service,
- schema=RESPONSE_SERVICE_SCHEMA,
- supports_response=SupportsResponse.ONLY,
- )
- async def rename_device(self, service_call: ServiceCall) -> None:
- """Execute rename device service call function.
- This will send a command to the api which will rename the
- device and then update the device registry to match.
- Data from the service call will be in service_call.data
- as seen below.
- """
- device_id = service_call.data[ATTR_DEVICE_ID]
- device_name = service_call.data[ATTR_NAME]
- # check for valid device id
- try:
- assert self.coordinator.get_device(device_id) is not None
- except AssertionError as ex:
- raise HomeAssistantError(
- "Error calling service: The device ID does not exist"
- ) from ex
- else:
- result = await self.hass.async_add_executor_job(
- self.coordinator.api.set_data, device_id, "device_name", device_name
- )
- if result:
- # ----------------------------------------------------------------------------
- # In this scenario, we would need to update the device registry name here
- # as it will not automatically update.
- # ----------------------------------------------------------------------------
- # Get our device from coordinator data to retrieve its devie_uid as that is
- # what we used in the devices identifiers.
- device = self.coordinator.get_device(device_id)
- # Get the device registry
- device_registry = dr.async_get(self.hass)
- # Get the device entry in the registry by its identifiers. This is the same as
- # we used to set them in base.py
- device_entry = device_registry.async_get_device(
- [(DOMAIN, device["device_uid"])]
- )
- # Update our device entry with the new name. You will see this change in the UI
- device_registry.async_update_device(device_entry.id, name=device_name)
- await self.coordinator.async_request_refresh()
- @callback
- def async_response_service(self, service_call: ServiceCall) -> None:
- """Execute response service call function.
- This will take a device id and return json data for the
- devices info on the api.
- If the device does not exist, it will raise an error.
- """
- device_id = service_call.data[ATTR_DEVICE_ID]
- response = self.coordinator.get_device(device_id)
- try:
- assert response is not None
- except AssertionError as ex:
- raise HomeAssistantError(
- "Error calling service: The device ID does not exist"
- ) from ex
- else:
- return response
|