Add processes services to System Bridge (#103564)
* Add processes services to System Bridge * Update import and fixes from model updates * Change log level from info to debug for process retrieval * Add exception handling for process not found * Consistency * Change HomeAssistantError to ServiceValidationError * Update homeassistant/components/system_bridge/__init__.py --------- Co-authored-by: Erik Montnemery <erik@montnemery.com>pull/113236/head
parent
0ccd813a99
commit
081a38a21c
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from systembridgeconnector.exceptions import (
|
from systembridgeconnector.exceptions import (
|
||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
|
@ -14,6 +15,7 @@ from systembridgeconnector.exceptions import (
|
||||||
from systembridgeconnector.version import Version
|
from systembridgeconnector.version import Version
|
||||||
from systembridgemodels.keyboard_key import KeyboardKey
|
from systembridgemodels.keyboard_key import KeyboardKey
|
||||||
from systembridgemodels.keyboard_text import KeyboardText
|
from systembridgemodels.keyboard_text import KeyboardText
|
||||||
|
from systembridgemodels.modules.processes import Process
|
||||||
from systembridgemodels.open_path import OpenPath
|
from systembridgemodels.open_path import OpenPath
|
||||||
from systembridgemodels.open_url import OpenUrl
|
from systembridgemodels.open_url import OpenUrl
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -24,6 +26,7 @@ from homeassistant.const import (
|
||||||
CONF_COMMAND,
|
CONF_COMMAND,
|
||||||
CONF_ENTITY_ID,
|
CONF_ENTITY_ID,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
|
CONF_ID,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PATH,
|
CONF_PATH,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
|
@ -37,7 +40,11 @@ from homeassistant.core import (
|
||||||
ServiceResponse,
|
ServiceResponse,
|
||||||
SupportsResponse,
|
SupportsResponse,
|
||||||
)
|
)
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
from homeassistant.exceptions import (
|
||||||
|
ConfigEntryAuthFailed,
|
||||||
|
ConfigEntryNotReady,
|
||||||
|
ServiceValidationError,
|
||||||
|
)
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
device_registry as dr,
|
device_registry as dr,
|
||||||
|
@ -64,6 +71,8 @@ CONF_BRIDGE = "bridge"
|
||||||
CONF_KEY = "key"
|
CONF_KEY = "key"
|
||||||
CONF_TEXT = "text"
|
CONF_TEXT = "text"
|
||||||
|
|
||||||
|
SERVICE_GET_PROCESS_BY_ID = "get_process_by_id"
|
||||||
|
SERVICE_GET_PROCESSES_BY_NAME = "get_processes_by_name"
|
||||||
SERVICE_OPEN_PATH = "open_path"
|
SERVICE_OPEN_PATH = "open_path"
|
||||||
SERVICE_POWER_COMMAND = "power_command"
|
SERVICE_POWER_COMMAND = "power_command"
|
||||||
SERVICE_OPEN_URL = "open_url"
|
SERVICE_OPEN_URL = "open_url"
|
||||||
|
@ -202,6 +211,52 @@ async def async_setup_entry(
|
||||||
raise vol.Invalid(f"Could not find device {device}") from exception
|
raise vol.Invalid(f"Could not find device {device}") from exception
|
||||||
raise vol.Invalid(f"Device {device} does not exist")
|
raise vol.Invalid(f"Device {device} does not exist")
|
||||||
|
|
||||||
|
async def handle_get_process_by_id(service_call: ServiceCall) -> ServiceResponse:
|
||||||
|
"""Handle the get process by id service call."""
|
||||||
|
_LOGGER.debug("Get process by id: %s", service_call.data)
|
||||||
|
coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][
|
||||||
|
service_call.data[CONF_BRIDGE]
|
||||||
|
]
|
||||||
|
processes: list[Process] = coordinator.data.processes
|
||||||
|
|
||||||
|
# Find process.id from list, raise ServiceValidationError if not found
|
||||||
|
try:
|
||||||
|
return asdict(
|
||||||
|
next(
|
||||||
|
process
|
||||||
|
for process in processes
|
||||||
|
if process.id == service_call.data[CONF_ID]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except StopIteration as exception:
|
||||||
|
raise ServiceValidationError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="process_not_found",
|
||||||
|
translation_placeholders={"id": service_call.data[CONF_ID]},
|
||||||
|
) from exception
|
||||||
|
|
||||||
|
async def handle_get_processes_by_name(
|
||||||
|
service_call: ServiceCall,
|
||||||
|
) -> ServiceResponse:
|
||||||
|
"""Handle the get process by name service call."""
|
||||||
|
_LOGGER.debug("Get process by name: %s", service_call.data)
|
||||||
|
coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][
|
||||||
|
service_call.data[CONF_BRIDGE]
|
||||||
|
]
|
||||||
|
processes: list[Process] = coordinator.data.processes
|
||||||
|
# Find processes from list
|
||||||
|
items: list[dict[str, Any]] = [
|
||||||
|
asdict(process)
|
||||||
|
for process in processes
|
||||||
|
if process.name is not None
|
||||||
|
and service_call.data[CONF_NAME].lower() in process.name.lower()
|
||||||
|
]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"count": len(items),
|
||||||
|
"processes": list(items),
|
||||||
|
}
|
||||||
|
|
||||||
async def handle_open_path(service_call: ServiceCall) -> ServiceResponse:
|
async def handle_open_path(service_call: ServiceCall) -> ServiceResponse:
|
||||||
"""Handle the open path service call."""
|
"""Handle the open path service call."""
|
||||||
_LOGGER.debug("Open path: %s", service_call.data)
|
_LOGGER.debug("Open path: %s", service_call.data)
|
||||||
|
@ -256,6 +311,32 @@ async def async_setup_entry(
|
||||||
)
|
)
|
||||||
return asdict(response)
|
return asdict(response)
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_GET_PROCESS_BY_ID,
|
||||||
|
handle_get_process_by_id,
|
||||||
|
schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_BRIDGE): valid_device,
|
||||||
|
vol.Required(CONF_ID): cv.positive_int,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
supports_response=SupportsResponse.ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_GET_PROCESSES_BY_NAME,
|
||||||
|
handle_get_processes_by_name,
|
||||||
|
schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_BRIDGE): valid_device,
|
||||||
|
vol.Required(CONF_NAME): cv.string,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
supports_response=SupportsResponse.ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_OPEN_PATH,
|
SERVICE_OPEN_PATH,
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
get_process_by_id:
|
||||||
|
fields:
|
||||||
|
bridge:
|
||||||
|
required: true
|
||||||
|
selector:
|
||||||
|
device:
|
||||||
|
integration: system_bridge
|
||||||
|
id:
|
||||||
|
required: true
|
||||||
|
example: 1234
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
get_processes_by_name:
|
||||||
|
fields:
|
||||||
|
bridge:
|
||||||
|
required: true
|
||||||
|
selector:
|
||||||
|
device:
|
||||||
|
integration: system_bridge
|
||||||
|
name:
|
||||||
|
required: true
|
||||||
|
example: "chrome.exe"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
open_path:
|
open_path:
|
||||||
fields:
|
fields:
|
||||||
bridge:
|
bridge:
|
||||||
|
|
|
@ -86,6 +86,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"exceptions": {
|
||||||
|
"process_not_found": {
|
||||||
|
"message": "Could not find process with id {id}."
|
||||||
|
}
|
||||||
|
},
|
||||||
"issues": {
|
"issues": {
|
||||||
"unsupported_version": {
|
"unsupported_version": {
|
||||||
"title": "System Bridge Upgrade Required",
|
"title": "System Bridge Upgrade Required",
|
||||||
|
@ -107,6 +112,34 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"get_process_by_id": {
|
||||||
|
"name": "Get process by ID",
|
||||||
|
"description": "Gets a process by the ID.",
|
||||||
|
"fields": {
|
||||||
|
"bridge": {
|
||||||
|
"name": "[%key:component::system_bridge::services::open_path::fields::bridge::name%]",
|
||||||
|
"description": "[%key:component::system_bridge::services::open_path::fields::bridge::description%]"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "ID",
|
||||||
|
"description": "ID of the process to get."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"get_processes_by_name": {
|
||||||
|
"name": "Get processes by name",
|
||||||
|
"description": "Gets a list of processes by the name.",
|
||||||
|
"fields": {
|
||||||
|
"bridge": {
|
||||||
|
"name": "[%key:component::system_bridge::services::open_path::fields::bridge::name%]",
|
||||||
|
"description": "[%key:component::system_bridge::services::open_path::fields::bridge::description%]"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "Name",
|
||||||
|
"description": "Name of the process to get."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"open_url": {
|
"open_url": {
|
||||||
"name": "Open URL",
|
"name": "Open URL",
|
||||||
"description": "Opens a URL on the server using the default application.",
|
"description": "Opens a URL on the server using the default application.",
|
||||||
|
|
Loading…
Reference in New Issue