Add turn_on/turn_off/toggle support

- Add API_TURN_ON, API_TURN_OFF, API_TOGGLE constants
- Add turn_on(), turn_off(), toggle() methods to MediaServerClient
- Implement async_turn_on, async_turn_off, async_toggle in media player
- Add TURN_ON and TURN_OFF to supported features
- Update README with turn on/off/toggle documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 03:44:25 +03:00
parent 37988331eb
commit e66f2f3b36
4 changed files with 79 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ A Home Assistant custom integration that allows you to control a remote PC's med
- Seek support with smooth timeline updates
- Displays current track info (title, artist, album, artwork)
- Real-time updates via WebSocket (with HTTP polling fallback)
- **Turn on/off/toggle support** - Execute custom actions (e.g., lock screen on turn off)
- **Script buttons** - Execute pre-defined scripts (shutdown, restart, lock, sleep, etc.)
- Configurable via Home Assistant UI
@@ -69,6 +70,31 @@ A full-featured media player entity with:
- Volume control and mute
- Seek functionality
- Current track information
- Turn on/off/toggle actions (execute server-side callbacks)
### Turn On/Off/Toggle
The media player supports `media_player.turn_on`, `media_player.turn_off`, and `media_player.toggle` actions. These execute optional callbacks configured on the Media Server (e.g., lock screen on turn off).
Configure callbacks in Media Server's `config.yaml`:
```yaml
callbacks:
on_turn_on:
command: "echo PC turned on"
timeout: 10
shell: true
on_turn_off:
command: "rundll32.exe user32.dll,LockWorkStation"
timeout: 5
shell: true
on_toggle:
command: "echo Toggle triggered"
timeout: 10
shell: true
```
### Script Button Entities

View File

@@ -22,6 +22,9 @@ from .const import (
API_VOLUME,
API_MUTE,
API_SEEK,
API_TURN_ON,
API_TURN_OFF,
API_TOGGLE,
API_SCRIPTS_LIST,
API_SCRIPTS_EXECUTE,
)
@@ -245,6 +248,30 @@ class MediaServerClient:
"""
return await self._request("POST", API_SEEK, {"position": position})
async def turn_on(self) -> dict[str, Any]:
"""Send turn on command.
Returns:
Response data
"""
return await self._request("POST", API_TURN_ON)
async def turn_off(self) -> dict[str, Any]:
"""Send turn off command.
Returns:
Response data
"""
return await self._request("POST", API_TURN_OFF)
async def toggle(self) -> dict[str, Any]:
"""Send toggle command.
Returns:
Response data
"""
return await self._request("POST", API_TOGGLE)
async def list_scripts(self) -> list[dict[str, Any]]:
"""List available scripts on the server.

View File

@@ -28,6 +28,9 @@ API_PREVIOUS = "/api/media/previous"
API_VOLUME = "/api/media/volume"
API_MUTE = "/api/media/mute"
API_SEEK = "/api/media/seek"
API_TURN_ON = "/api/media/turn_on"
API_TURN_OFF = "/api/media/turn_off"
API_TOGGLE = "/api/media/toggle"
API_SCRIPTS_LIST = "/api/scripts/list"
API_SCRIPTS_EXECUTE = "/api/scripts/execute"
API_WEBSOCKET = "/api/media/ws"

View File

@@ -285,6 +285,8 @@ class RemoteMediaPlayerEntity(CoordinatorEntity[MediaPlayerCoordinator], MediaPl
| MediaPlayerEntityFeature.PREVIOUS_TRACK
| MediaPlayerEntityFeature.NEXT_TRACK
| MediaPlayerEntityFeature.SEEK
| MediaPlayerEntityFeature.TURN_ON
| MediaPlayerEntityFeature.TURN_OFF
)
@property
@@ -450,3 +452,24 @@ class RemoteMediaPlayerEntity(CoordinatorEntity[MediaPlayerCoordinator], MediaPl
await self.coordinator.async_request_refresh()
except MediaServerError as err:
_LOGGER.error("Failed to seek: %s", err)
async def async_turn_on(self) -> None:
"""Send turn on command."""
try:
await self.coordinator.client.turn_on()
except MediaServerError as err:
_LOGGER.error("Failed to turn on: %s", err)
async def async_turn_off(self) -> None:
"""Send turn off command."""
try:
await self.coordinator.client.turn_off()
except MediaServerError as err:
_LOGGER.error("Failed to turn off: %s", err)
async def async_toggle(self) -> None:
"""Send toggle command."""
try:
await self.coordinator.client.toggle()
except MediaServerError as err:
_LOGGER.error("Failed to toggle: %s", err)