예제 #1
0
async def _async_process_config(hass, config, component):
    """Process script configuration."""
    async def service_handler(service):
        """Execute a service call to script.<script name>."""
        entity_id = ENTITY_ID_FORMAT.format(service.service)
        script = component.get_entity(entity_id)
        if script.is_on:
            _LOGGER.warning("Script %s already running.", entity_id)
            return
        await script.async_turn_on(variables=service.data,
                                   context=service.context)

    scripts = []

    for object_id, cfg in config.get(DOMAIN, {}).items():
        alias = cfg.get(CONF_ALIAS, object_id)
        script = ScriptEntity(hass, object_id, alias, cfg[CONF_SEQUENCE])
        scripts.append(script)
        hass.services.async_register(DOMAIN,
                                     object_id,
                                     service_handler,
                                     schema=SCRIPT_SERVICE_SCHEMA)

        # Register the service description
        service_desc = {
            CONF_DESCRIPTION: cfg[CONF_DESCRIPTION],
            CONF_FIELDS: cfg[CONF_FIELDS],
        }
        async_set_service_schema(hass, DOMAIN, object_id, service_desc)

    await component.async_add_entities(scripts)
예제 #2
0
def discover_scripts(hass):
    """Discover python scripts in folder."""
    path = hass.config.path(FOLDER)

    if not os.path.isdir(path):
        _LOGGER.warning("Folder %s not found in configuration folder", FOLDER)
        return False

    def python_script_service_handler(call):
        """Handle python script service calls."""
        execute_script(hass, call.service, call.data)

    existing = hass.services.services.get(DOMAIN, {}).keys()
    for existing_service in existing:
        if existing_service == SERVICE_RELOAD:
            continue
        hass.services.remove(DOMAIN, existing_service)

    # Load user-provided service descriptions from python_scripts/services.yaml
    services_yaml = os.path.join(path, "services.yaml")
    if os.path.exists(services_yaml):
        services_dict = load_yaml(services_yaml)
    else:
        services_dict = {}

    for fil in glob.iglob(os.path.join(path, "*.py")):
        name = os.path.splitext(os.path.basename(fil))[0]
        hass.services.register(DOMAIN, name, python_script_service_handler)

        service_desc = {
            "description": services_dict.get(name, {}).get("description", ""),
            "fields": services_dict.get(name, {}).get("fields", {}),
        }
        async_set_service_schema(hass, DOMAIN, name, service_desc)
예제 #3
0
    async def async_register_services(self) -> None:
        """Create or update the notify services."""
        assert self.hass

        if hasattr(self, "targets"):
            stale_targets = set(self.registered_targets)

            # pylint: disable=no-member
            for name, target in self.targets.items():  # type: ignore
                target_name = slugify(
                    f"{self._target_service_name_prefix}_{name}")
                if target_name in stale_targets:
                    stale_targets.remove(target_name)
                if (target_name in self.registered_targets
                        and target == self.registered_targets[target_name]):
                    continue
                self.registered_targets[target_name] = target
                self.hass.services.async_register(
                    DOMAIN,
                    target_name,
                    self._async_notify_message_service,
                    schema=NOTIFY_SERVICE_SCHEMA,
                )
                # Register the service description
                service_desc = {
                    CONF_NAME: f"Send a notification via {target_name}",
                    CONF_DESCRIPTION:
                    f"Sends a notification message using the {target_name} integration.",
                    CONF_FIELDS:
                    self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
                }
                async_set_service_schema(self.hass, DOMAIN, target_name,
                                         service_desc)

            for stale_target_name in stale_targets:
                del self.registered_targets[stale_target_name]
                self.hass.services.async_remove(
                    DOMAIN,
                    stale_target_name,
                )

        if self.hass.services.has_service(DOMAIN, self._service_name):
            return

        self.hass.services.async_register(
            DOMAIN,
            self._service_name,
            self._async_notify_message_service,
            schema=NOTIFY_SERVICE_SCHEMA,
        )

        # Register the service description
        service_desc = {
            CONF_NAME: f"Send a notification with {self._service_name}",
            CONF_DESCRIPTION:
            f"Sends a notification message using the {self._service_name} service.",
            CONF_FIELDS: self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
        }
        async_set_service_schema(self.hass, DOMAIN, self._service_name,
                                 service_desc)
예제 #4
0
async def _async_process_config(hass, config, component):
    """Process script configuration."""
    async def service_handler(service):
        """Execute a service call to script.<script name>."""
        entity_id = ENTITY_ID_FORMAT.format(service.service)
        script_entity = component.get_entity(entity_id)
        if script_entity.script.is_legacy and script_entity.is_on:
            _LOGGER.warning("Script %s already running.", entity_id)
            return
        await script_entity.async_turn_on(variables=service.data,
                                          context=service.context)

    script_entities = []

    for object_id, cfg in config.get(DOMAIN, {}).items():
        script_entities.append(
            ScriptEntity(
                hass,
                object_id,
                cfg.get(CONF_ALIAS, object_id),
                cfg.get(CONF_ICON),
                cfg[CONF_SEQUENCE],
                cfg[CONF_MODE],
                cfg.get(CONF_QUEUE_MAX, 0),
            ))

    await component.async_add_entities(script_entities)

    # Register services for all entities that were created successfully.
    for script_entity in script_entities:
        object_id = script_entity.object_id
        if component.get_entity(script_entity.entity_id) is None:
            _LOGGER.error("Couldn't load script %s", object_id)
            continue

        cfg = config[DOMAIN][object_id]

        hass.services.async_register(DOMAIN,
                                     object_id,
                                     service_handler,
                                     schema=SCRIPT_SERVICE_SCHEMA)

        # Register the service description
        service_desc = {
            CONF_DESCRIPTION: cfg[CONF_DESCRIPTION],
            CONF_FIELDS: cfg[CONF_FIELDS],
        }
        async_set_service_schema(hass, DOMAIN, object_id, service_desc)
예제 #5
0
async def _register_services(hass, target_name, coordinator):
    async def _async_trigger_service(service: ServiceCall):
        _LOGGER.info("Multiscrape triggered by service: %s", service.__repr__())
        await coordinator.async_request_refresh()

    hass.services.async_register(
        DOMAIN,
        f"trigger_{target_name}",
        _async_trigger_service,
        schema=vol.Schema({}),
    )

    # Register the service description
    service_desc = {
        CONF_NAME: f"Trigger an update of {target_name}",
        CONF_DESCRIPTION: f"Triggers an update for the multiscrape {target_name} integration, independent of the update interval.",
        CONF_FIELDS: {},
    }
    async_set_service_schema(hass, DOMAIN, target_name, service_desc)
예제 #6
0
async def _register_service(hass: HomeAssistant, entry_data: RuntimeEntryData,
                            service: UserService) -> None:
    if entry_data.device_info is None:
        raise ValueError("Device Info needs to be fetched first")
    service_name = f"{entry_data.device_info.name.replace('-', '_')}_{service.name}"
    schema = {}
    fields = {}

    for arg in service.args:
        if arg.type not in ARG_TYPE_METADATA:
            _LOGGER.error(
                "Can't register service %s because %s is of unknown type %s",
                service_name,
                arg.name,
                arg.type,
            )
            return
        metadata = ARG_TYPE_METADATA[arg.type]
        schema[vol.Required(arg.name)] = metadata.validator
        fields[arg.name] = {
            "name": arg.name,
            "required": True,
            "description": metadata.description,
            "example": metadata.example,
            "selector": metadata.selector,
        }

    async def execute_service(call: ServiceCall) -> None:
        await entry_data.client.execute_service(service, call.data
                                                )  # type: ignore[arg-type]

    hass.services.async_register(DOMAIN, service_name, execute_service,
                                 vol.Schema(schema))

    service_desc = {
        "description":
        f"Calls the service {service.name} of the node {entry_data.device_info.name}",
        "fields": fields,
    }

    async_set_service_schema(hass, DOMAIN, service_name, service_desc)
예제 #7
0
async def _async_process_config(hass, config, component):
    """Process script configuration."""

    async def service_handler(service):
        """Execute a service call to script.<script name>."""
        entity_id = ENTITY_ID_FORMAT.format(service.service)
        script_entity = component.get_entity(entity_id)
        await script_entity.async_turn_on(
            variables=service.data, context=service.context
        )

    script_entities = [
        ScriptEntity(hass, object_id, cfg, cfg.raw_config)
        for object_id, cfg in config.get(DOMAIN, {}).items()
    ]

    await component.async_add_entities(script_entities)

    # Register services for all entities that were created successfully.
    for script_entity in script_entities:
        object_id = script_entity.object_id
        if component.get_entity(script_entity.entity_id) is None:
            _LOGGER.error("Couldn't load script %s", object_id)
            continue

        cfg = config[DOMAIN][object_id]

        hass.services.async_register(
            DOMAIN, object_id, service_handler, schema=SCRIPT_SERVICE_SCHEMA
        )

        # Register the service description
        service_desc = {
            CONF_NAME: script_entity.name,
            CONF_DESCRIPTION: cfg[CONF_DESCRIPTION],
            CONF_FIELDS: cfg[CONF_FIELDS],
        }
        async_set_service_schema(hass, DOMAIN, object_id, service_desc)
예제 #8
0
    async def async_setup_platform(p_type, p_config=None, discovery_info=None):
        """Set up a TTS platform."""
        if p_config is None:
            p_config = {}

        platform = await async_prepare_setup_platform(hass, config, DOMAIN, p_type)
        if platform is None:
            return

        try:
            if hasattr(platform, "async_get_engine"):
                provider = await platform.async_get_engine(
                    hass, p_config, discovery_info
                )
            else:
                provider = await hass.async_add_executor_job(
                    platform.get_engine, hass, p_config, discovery_info
                )

            if provider is None:
                _LOGGER.error("Error setting up platform %s", p_type)
                return

            tts.async_register_engine(p_type, provider, p_config)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Error setting up platform: %s", p_type)
            return

        async def async_say_handle(service):
            """Service handle for say."""
            entity_ids = service.data[ATTR_ENTITY_ID]
            message = service.data.get(ATTR_MESSAGE)
            cache = service.data.get(ATTR_CACHE)
            language = service.data.get(ATTR_LANGUAGE)
            options = service.data.get(ATTR_OPTIONS)

            try:
                url = await tts.async_get_url_path(
                    p_type, message, cache=cache, language=language, options=options
                )
            except HomeAssistantError as err:
                _LOGGER.error("Error on init TTS: %s", err)
                return

            base = tts.base_url or get_url(hass)
            url = base + url

            data = {
                ATTR_MEDIA_CONTENT_ID: url,
                ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
                ATTR_ENTITY_ID: entity_ids,
            }

            await hass.services.async_call(
                DOMAIN_MP,
                SERVICE_PLAY_MEDIA,
                data,
                blocking=True,
                context=service.context,
            )

        service_name = p_config.get(CONF_SERVICE_NAME, f"{p_type}_{SERVICE_SAY}")
        hass.services.async_register(
            DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY
        )

        # Register the service description
        service_desc = {
            CONF_NAME: f"Say an TTS message with {p_type}",
            CONF_DESCRIPTION: f"Say something using text-to-speech on a media player with {p_type}.",
            CONF_FIELDS: services_dict[SERVICE_SAY][CONF_FIELDS],
        }
        async_set_service_schema(hass, DOMAIN, service_name, service_desc)
예제 #9
0
    async def trigger_init(self, func):
        """Initialize any decorator triggers for a newly defined function."""
        func_name = func.get_name()
        trig_args = {}
        got_reqd_dec = False
        trig_decorators_reqd = {
            "time_trigger",
            "state_trigger",
            "event_trigger",
        }
        trig_decorators = {
            "time_trigger",
            "state_trigger",
            "event_trigger",
            "state_active",
            "time_active",
        }
        decorator_used = set()
        for dec in func.get_decorators():
            dec_name, dec_args = dec[0], dec[1]
            if dec_name in decorator_used:
                self.logger.error(
                    "%s defined in %s: decorator %s repeated; ignored",
                    func_name,
                    self.name,
                    dec_name,
                )
                continue
            decorator_used.add(dec_name)
            if dec_name in trig_decorators_reqd:
                got_reqd_dec = True
            if dec_name in trig_decorators:
                if dec_name not in trig_args:
                    trig_args[dec_name] = []
                if dec_args is not None:
                    trig_args[dec_name] += dec_args
            elif dec_name == "service":
                if dec_args is not None:
                    self.logger.error(
                        "%s defined in %s: decorator @service takes no arguments; ignored",
                        func_name,
                        self.name,
                    )
                    continue
                if func_name in (SERVICE_RELOAD, SERVICE_JUPYTER_KERNEL_START):
                    self.logger.error(
                        "function '%s' in %s with @service conflicts with builtin service; ignoring (please rename function)",
                        func_name,
                        self.name,
                    )
                    return
                desc = func.get_doc_string()
                if desc is None or desc == "":
                    desc = f"pyscript function {func_name}()"
                desc = desc.lstrip(" \n\r")
                if desc.startswith("yaml"):
                    try:
                        desc = desc[4:].lstrip(" \n\r")
                        file_desc = io.StringIO(desc)
                        service_desc = (yaml.load(file_desc,
                                                  Loader=yaml.BaseLoader)
                                        or OrderedDict())
                        file_desc.close()
                    except Exception as exc:
                        self.logger.error(
                            "Unable to decode yaml doc_string for %s(): %s",
                            func_name, str(exc))
                        raise HomeAssistantError(exc)
                else:
                    fields = OrderedDict()
                    for arg in func.get_positional_args():
                        fields[arg] = OrderedDict(
                            description=f"argument {arg}")
                    service_desc = {"description": desc, "fields": fields}

                def pyscript_service_factory(func_name, func):
                    async def pyscript_service_handler(call):
                        """Handle python script service calls."""
                        # self.logger.debug("service call to %s", func_name)
                        #
                        # use a new AstEval context so it can run fully independently
                        # of other instances (except for global_ctx which is common)
                        #
                        ast_ctx = AstEval(
                            f"{self.name}.{func_name}",
                            global_ctx=self,
                            state_func=self.state_func,
                            event_func=self.event_func,
                            handler_func=self.handler_func,
                        )
                        self.handler_func.install_ast_funcs(ast_ctx)
                        func_args = {
                            "trigger_type": "service",
                        }
                        func_args.update(call.data)

                        async def do_service_call(func, ast_ctx, data):
                            await func.call(ast_ctx, [], call.data)
                            if ast_ctx.get_exception_obj():
                                ast_ctx.get_logger().error(
                                    ast_ctx.get_exception_long())

                        self.handler_func.create_task(
                            do_service_call(func, ast_ctx, func_args))

                    return pyscript_service_handler

                self.hass.services.async_register(
                    DOMAIN,
                    func_name,
                    pyscript_service_factory(func_name, func),
                )
                async_set_service_schema(self.hass, DOMAIN, func_name,
                                         service_desc)
                self.services.add(func_name)
            else:
                self.logger.warning(
                    "%s defined in %s: unknown decorator @%s: ignored",
                    func_name,
                    self.name,
                    dec_name,
                )

        if func_name in self.services and "service" not in decorator_used:
            # function redefined without @service, so remove it
            self.hass.services.async_remove(DOMAIN, func_name)
            self.services.discard(func_name)

        for dec_name in trig_decorators:
            if dec_name in trig_args and len(trig_args[dec_name]) == 0:
                trig_args[dec_name] = None

        arg_check = {
            "state_trigger": {1},
            "state_active": {1},
            "event_trigger": {1, 2},
        }
        for dec_name, arg_cnt in arg_check.items():
            if dec_name not in trig_args or trig_args[dec_name] is None:
                continue
            if len(trig_args[dec_name]) not in arg_cnt:
                self.logger.error(
                    "%s defined in %s: decorator @%s got %d argument%s, expected %s; ignored",
                    func_name,
                    self.name,
                    dec_name,
                    len(trig_args[dec_name]),
                    "s" if len(trig_args[dec_name]) > 1 else "",
                    " or ".join([str(cnt) for cnt in sorted(arg_cnt)]),
                )
                del trig_args[dec_name]
            if arg_cnt == 1:
                trig_args[dec_name] = trig_args[dec_name][0]

        if not got_reqd_dec and len(trig_args) > 0:
            self.logger.error(
                "%s defined in %s: needs at least one trigger decorator (ie: %s)",
                func_name,
                self.name,
                ", ".join(sorted(trig_decorators_reqd)),
            )
            return

        if len(trig_args) == 0:
            #
            # function defined without triggers; remove old one if necessary
            #
            if func_name in self.triggers:
                await self.triggers[func_name].stop()
                del self.triggers[func_name]
            if func_name in self.triggers_new:
                del self.triggers_new[func_name]
            return

        trig_args["action"] = func
        trig_args["action_ast_ctx"] = AstEval(
            f"{self.name}.{func_name}",
            global_ctx=self,
            state_func=self.state_func,
            event_func=self.event_func,
            handler_func=self.handler_func,
        )
        self.handler_func.install_ast_funcs(trig_args["action_ast_ctx"])
        trig_args["global_sym_table"] = self.global_sym_table

        if func_name in self.triggers:
            await self.triggers[func_name].stop()

        self.triggers_new[func_name] = TrigInfo(
            f"{self.name}.{func_name}",
            trig_args,
            event_func=self.event_func,
            state_func=self.state_func,
            handler_func=self.handler_func,
            trig_time=self.trig_time_func,
            global_ctx=self,
        )

        if self.auto_start:
            await self.start()
예제 #10
0
파일: __init__.py 프로젝트: jcgoette/core
    async def async_setup_platform(
        p_type: str,
        p_config: ConfigType | None = None,
        discovery_info: DiscoveryInfoType | None = None,
    ) -> None:
        """Set up a TTS platform."""
        if p_config is None:
            p_config = {}

        platform = await async_prepare_setup_platform(hass, config, DOMAIN,
                                                      p_type)
        if platform is None:
            return

        try:
            if hasattr(platform, "async_get_engine"):
                provider = await platform.async_get_engine(
                    hass, p_config, discovery_info)
            else:
                provider = await hass.async_add_executor_job(
                    platform.get_engine, hass, p_config, discovery_info)

            if provider is None:
                _LOGGER.error("Error setting up platform %s", p_type)
                return

            tts.async_register_engine(p_type, provider, p_config)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Error setting up platform: %s", p_type)
            return

        async def async_say_handle(service: ServiceCall) -> None:
            """Service handle for say."""
            entity_ids = service.data[ATTR_ENTITY_ID]
            message = service.data[ATTR_MESSAGE]
            cache = service.data.get(ATTR_CACHE)
            language = service.data.get(ATTR_LANGUAGE)
            options = service.data.get(ATTR_OPTIONS)

            tts.process_options(p_type, language, options)
            params = {
                "message": message,
            }
            if cache is not None:
                params["cache"] = "true" if cache else "false"
            if language is not None:
                params["language"] = language
            if options is not None:
                params.update(options)

            await hass.services.async_call(
                DOMAIN_MP,
                SERVICE_PLAY_MEDIA,
                {
                    ATTR_ENTITY_ID:
                    entity_ids,
                    ATTR_MEDIA_CONTENT_ID:
                    generate_media_source_id(
                        DOMAIN,
                        str(yarl.URL.build(path=p_type, query=params)),
                    ),
                    ATTR_MEDIA_CONTENT_TYPE:
                    MEDIA_TYPE_MUSIC,
                    ATTR_MEDIA_ANNOUNCE:
                    True,
                },
                blocking=True,
                context=service.context,
            )

        service_name = p_config.get(CONF_SERVICE_NAME,
                                    f"{p_type}_{SERVICE_SAY}")
        hass.services.async_register(DOMAIN,
                                     service_name,
                                     async_say_handle,
                                     schema=SCHEMA_SERVICE_SAY)

        # Register the service description
        service_desc = {
            CONF_NAME: f"Say an TTS message with {p_type}",
            CONF_DESCRIPTION:
            f"Say something using text-to-speech on a media player with {p_type}.",
            CONF_FIELDS: services_dict[SERVICE_SAY][CONF_FIELDS],
        }
        async_set_service_schema(hass, DOMAIN, service_name, service_desc)
예제 #11
0
async def _register_service(hass: HomeAssistant, entry_data: RuntimeEntryData,
                            service: UserService):
    service_name = f"{entry_data.device_info.name.replace('-', '_')}_{service.name}"
    schema = {}
    fields = {}

    for arg in service.args:
        metadata = {
            UserServiceArgType.BOOL: {
                "validator": cv.boolean,
                "example": "False",
                "selector": {
                    "boolean": None
                },
            },
            UserServiceArgType.INT: {
                "validator": vol.Coerce(int),
                "example": "42",
                "selector": {
                    "number": {
                        CONF_MODE: "box"
                    }
                },
            },
            UserServiceArgType.FLOAT: {
                "validator": vol.Coerce(float),
                "example": "12.3",
                "selector": {
                    "number": {
                        CONF_MODE: "box",
                        "step": 1e-3
                    }
                },
            },
            UserServiceArgType.STRING: {
                "validator": cv.string,
                "example": "Example text",
                "selector": {
                    "text": None
                },
            },
            UserServiceArgType.BOOL_ARRAY: {
                "validator": [cv.boolean],
                "description": "A list of boolean values.",
                "example": "[True, False]",
                "selector": {
                    "object": {}
                },
            },
            UserServiceArgType.INT_ARRAY: {
                "validator": [vol.Coerce(int)],
                "description": "A list of integer values.",
                "example": "[42, 34]",
                "selector": {
                    "object": {}
                },
            },
            UserServiceArgType.FLOAT_ARRAY: {
                "validator": [vol.Coerce(float)],
                "description": "A list of floating point numbers.",
                "example": "[ 12.3, 34.5 ]",
                "selector": {
                    "object": {}
                },
            },
            UserServiceArgType.STRING_ARRAY: {
                "validator": [cv.string],
                "description": "A list of strings.",
                "example": "['Example text', 'Another example']",
                "selector": {
                    "object": {}
                },
            },
        }[arg.type_]
        schema[vol.Required(arg.name)] = metadata["validator"]
        fields[arg.name] = {
            "name": arg.name,
            "required": True,
            "description": metadata.get("description"),
            "example": metadata["example"],
            "selector": metadata["selector"],
        }

    async def execute_service(call):
        await entry_data.client.execute_service(service, call.data)

    hass.services.async_register(DOMAIN, service_name, execute_service,
                                 vol.Schema(schema))

    service_desc = {
        "description":
        f"Calls the service {service.name} of the node {entry_data.device_info.name}",
        "fields": fields,
    }

    async_set_service_schema(hass, DOMAIN, service_name, service_desc)
예제 #12
0
async def _async_process_config(hass, config, component) -> bool:
    """Process script configuration.

    Return true, if Blueprints were used.
    """
    entities = []
    blueprints_used = False

    for config_key in extract_domain_configs(config, DOMAIN):
        conf: dict[str, dict[str, Any] | BlueprintInputs] = config[config_key]

        for object_id, config_block in conf.items():
            raw_blueprint_inputs = None
            raw_config = None

            if isinstance(config_block, BlueprintInputs):
                blueprints_used = True
                blueprint_inputs = config_block
                raw_blueprint_inputs = blueprint_inputs.config_with_inputs

                try:
                    raw_config = blueprint_inputs.async_substitute()
                    config_block = cast(
                        Dict[str, Any],
                        await async_validate_config_item(hass, raw_config),
                    )
                except vol.Invalid as err:
                    LOGGER.error(
                        "Blueprint %s generated invalid script with input %s: %s",
                        blueprint_inputs.blueprint.name,
                        blueprint_inputs.inputs,
                        humanize_error(config_block, err),
                    )
                    continue
            else:
                raw_config = cast(ScriptConfig, config_block).raw_config

            entities.append(
                ScriptEntity(hass, object_id, config_block, raw_config,
                             raw_blueprint_inputs))

    await component.async_add_entities(entities)

    async def service_handler(service):
        """Execute a service call to script.<script name>."""
        entity_id = ENTITY_ID_FORMAT.format(service.service)
        script_entity = component.get_entity(entity_id)
        await script_entity.async_turn_on(variables=service.data,
                                          context=service.context)

    # Register services for all entities that were created successfully.
    for entity in entities:
        hass.services.async_register(DOMAIN,
                                     entity.object_id,
                                     service_handler,
                                     schema=SCRIPT_SERVICE_SCHEMA)

        # Register the service description
        service_desc = {
            CONF_NAME: entity.name,
            CONF_DESCRIPTION: entity.description,
            CONF_FIELDS: entity.fields,
        }
        async_set_service_schema(hass, DOMAIN, entity.object_id, service_desc)

    return blueprints_used