Files
media-player-mixed/haos-integration/custom_components/remote_media_player/button.py
alexei.dolgolyov e26df64e4b Refactor project into two standalone components
Split monorepo into separate units for future independent repositories:
- media-server/: Standalone FastAPI server with own README, requirements,
  config example, and CLAUDE.md
- haos-integration/: HACS-ready Home Assistant integration with hacs.json,
  own README, and CLAUDE.md

Both components now have their own .gitignore files and can be easily
extracted into separate repositories.

Also adds custom icon support for scripts configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:36:23 +03:00

135 lines
4.3 KiB
Python

"""Button platform for Remote Media Player integration."""
from __future__ import annotations
import logging
from typing import Any
from homeassistant.components.button import ButtonEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .api_client import MediaServerClient, MediaServerError
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up script buttons from a config entry."""
client: MediaServerClient = hass.data[DOMAIN][entry.entry_id]["client"]
try:
scripts = await client.list_scripts()
except MediaServerError as err:
_LOGGER.error("Failed to fetch scripts list: %s", err)
return
entities = [
ScriptButtonEntity(
client=client,
entry=entry,
script_name=script["name"],
script_label=script["label"],
script_description=script.get("description", ""),
script_icon=script.get("icon"),
)
for script in scripts
]
if entities:
async_add_entities(entities)
_LOGGER.info("Added %d script button entities", len(entities))
class ScriptButtonEntity(ButtonEntity):
"""Button entity for executing a script on the media server."""
_attr_has_entity_name = True
def __init__(
self,
client: MediaServerClient,
entry: ConfigEntry,
script_name: str,
script_label: str,
script_description: str,
script_icon: str | None = None,
) -> None:
"""Initialize the script button."""
self._client = client
self._entry = entry
self._script_name = script_name
self._script_label = script_label
self._script_description = script_description
# Entity attributes
self._attr_unique_id = f"{entry.entry_id}_script_{script_name}"
self._attr_name = script_label
# Use custom icon if provided, otherwise auto-resolve from script name
self._attr_icon = script_icon or self._get_icon_for_script(script_name)
def _get_icon_for_script(self, script_name: str) -> str:
"""Get an appropriate icon based on script name."""
icon_map = {
"lock": "mdi:lock",
"unlock": "mdi:lock-open",
"shutdown": "mdi:power",
"restart": "mdi:restart",
"sleep": "mdi:sleep",
"hibernate": "mdi:power-sleep",
"cancel": "mdi:cancel",
}
script_lower = script_name.lower()
for keyword, icon in icon_map.items():
if keyword in script_lower:
return icon
return "mdi:script-text"
@property
def device_info(self) -> DeviceInfo:
"""Return device info."""
return DeviceInfo(
identifiers={(DOMAIN, self._entry.entry_id)},
name=self._entry.title,
manufacturer="Remote Media Player",
model="Media Server",
)
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return extra state attributes."""
return {
"script_name": self._script_name,
"description": self._script_description,
}
async def async_press(self) -> None:
"""Handle button press - execute the script."""
_LOGGER.info("Executing script: %s", self._script_name)
try:
result = await self._client.execute_script(self._script_name)
if result.get("success"):
_LOGGER.info(
"Script '%s' executed successfully (exit_code=%s)",
self._script_name,
result.get("exit_code"),
)
else:
_LOGGER.warning(
"Script '%s' failed: %s",
self._script_name,
result.get("stderr") or result.get("error"),
)
except MediaServerError as err:
_LOGGER.error("Failed to execute script '%s': %s", self._script_name, err)
raise