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>
This commit is contained in:
50
CLAUDE.md
50
CLAUDE.md
@@ -1,50 +0,0 @@
|
||||
# Media Server for Home Assistant
|
||||
|
||||
## Project Overview
|
||||
|
||||
A server-client system to control PC media playback from Home Assistant.
|
||||
|
||||
- **Server**: FastAPI REST API on Windows controlling system-wide media via WinRT
|
||||
- **Client**: Home Assistant custom integration exposing a media player entity
|
||||
|
||||
## Running the Server
|
||||
|
||||
### Manual Start
|
||||
|
||||
```bash
|
||||
cd c:\Users\Alexei\Documents\haos-integration-media-player
|
||||
python -m media_server.main
|
||||
```
|
||||
|
||||
### Auto-Start on Boot (Windows Task Scheduler)
|
||||
|
||||
Run in **Administrator PowerShell** from the project root:
|
||||
|
||||
```powershell
|
||||
.\media_server\service\install_task_windows.ps1
|
||||
```
|
||||
|
||||
To remove the scheduled task:
|
||||
|
||||
```powershell
|
||||
Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false
|
||||
```
|
||||
|
||||
## Home Assistant Integration
|
||||
|
||||
Copy `custom_components/remote_media_player/` to your Home Assistant config folder.
|
||||
|
||||
Integration files location: `U:\custom_components\remote_media_player`
|
||||
|
||||
## API Token
|
||||
|
||||
The API token is generated on first run and displayed in the console output.
|
||||
Configure the same token in Home Assistant integration settings.
|
||||
|
||||
## Server Port
|
||||
|
||||
Default: `8765`
|
||||
|
||||
## Git Rules
|
||||
|
||||
Always ask for user approval before committing changes to git.
|
||||
73
README.md
73
README.md
@@ -1,30 +1,32 @@
|
||||
# Remote Media Player for Home Assistant
|
||||
# Remote Media Player
|
||||
|
||||
Control your PC's media playback from Home Assistant.
|
||||
|
||||
This monorepo contains two separate components designed to be split into independent repositories:
|
||||
|
||||
## Components
|
||||
|
||||
| Component | Description | Documentation |
|
||||
|-----------|-------------|---------------|
|
||||
| [Media Server](media_server/) | REST API server for your PC | [README](media_server/README.md) |
|
||||
| [HAOS Integration](custom_components/remote_media_player/) | Home Assistant custom component | [README](custom_components/remote_media_player/README.md) |
|
||||
| Component | Description | Future Repository |
|
||||
|-----------|-------------|-------------------|
|
||||
| [Media Server](media-server/) | REST API server for your PC | `media-server` |
|
||||
| [HAOS Integration](haos-integration/) | HACS-ready Home Assistant integration | `haos-remote-media-player` |
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
┌─────────────────────┐ HTTP/REST ┌─────────────────────┐
|
||||
│ Home Assistant │◄─────────────────────────►│ Your PC │
|
||||
┌─────────────────────┐ HTTP/WebSocket ┌─────────────────────┐
|
||||
│ Home Assistant │◄────────────────────────►│ Your PC │
|
||||
│ │ (Token Auth) │ │
|
||||
│ ┌───────────────┐ │ │ ┌───────────────┐ │
|
||||
│ │ Media Player │ │ │ │ Media Server │ │
|
||||
│ │ Entity │ │ │ │ (FastAPI) │ │
|
||||
│ └───────────────┘ │ │ └───────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
└─────────────────────┘ │ ┌───────▼───────┐ │
|
||||
│ │ Media Control │ │
|
||||
│ │ - Windows │ │
|
||||
│ │ - Linux │ │
|
||||
│ │ - macOS │ │
|
||||
│ ┌───────────────┐ │ │ │ │
|
||||
│ │ Script Button │ │ │ ┌───────▼───────┐ │
|
||||
│ │ Entities │ │ │ │ Media Control │ │
|
||||
│ └───────────────┘ │ │ │ - Windows │ │
|
||||
│ │ │ │ - Linux │ │
|
||||
└─────────────────────┘ │ │ - macOS │ │
|
||||
│ │ - Android │ │
|
||||
│ └───────────────┘ │
|
||||
└─────────────────────┘
|
||||
@@ -37,56 +39,49 @@ Control your PC's media playback from Home Assistant.
|
||||
- Volume control and mute
|
||||
- Seek within tracks
|
||||
- Display current track info (title, artist, album, artwork)
|
||||
- Real-time updates via WebSocket
|
||||
- Script buttons (shutdown, restart, lock, sleep, hibernate, custom)
|
||||
- Secure token-based authentication
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
| Platform | Media Control | Volume Control | Status |
|
||||
|----------|---------------|----------------|--------|
|
||||
| Windows | WinRT Media Transport | pycaw | Fully tested |
|
||||
| Linux | MPRIS D-Bus | PulseAudio/PipeWire | Not tested |
|
||||
| macOS | AppleScript | System volume | Not tested |
|
||||
| Android | Termux:API | Termux volume | Not tested |
|
||||
|
||||
> **Note:** Windows is the primary supported platform. Linux, macOS, and Android implementations exist but have not been thoroughly tested and may have limited functionality.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Set up the Server (on your PC)
|
||||
### 1. Set up the Media Server (on your PC)
|
||||
|
||||
```bash
|
||||
cd media_server
|
||||
cd media-server
|
||||
pip install -r requirements.txt
|
||||
python -m media_server.main --generate-config
|
||||
python -m media_server.main
|
||||
```
|
||||
|
||||
See [Media Server README](media_server/README.md) for detailed instructions.
|
||||
See [Media Server README](media-server/README.md) for detailed instructions.
|
||||
|
||||
### 2. Set up Home Assistant Integration
|
||||
|
||||
1. Copy `custom_components/remote_media_player/` to your HA config
|
||||
2. Restart Home Assistant
|
||||
3. Add integration via UI with your server's IP and token
|
||||
Copy `haos-integration/custom_components/remote_media_player/` to your HA config folder, or install via HACS.
|
||||
|
||||
See [Integration README](custom_components/remote_media_player/README.md) for detailed instructions.
|
||||
See [HAOS Integration README](haos-integration/README.md) for detailed instructions.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
haos-integration-media-player/
|
||||
├── media_server/ # Server component
|
||||
/
|
||||
├── media-server/ # Standalone Media Server
|
||||
│ ├── README.md # Server documentation
|
||||
│ ├── requirements.txt # Python dependencies
|
||||
│ ├── config.example.yaml # Example configuration
|
||||
│ └── media_server/ # Python package
|
||||
│ ├── main.py # Entry point
|
||||
│ ├── routes/ # API endpoints
|
||||
│ ├── services/ # Platform media controllers
|
||||
│ └── service/ # Service installers
|
||||
│
|
||||
├── custom_components/
|
||||
│ └── remote_media_player/ # HAOS Integration
|
||||
│ ├── media_player.py # Media player entity
|
||||
│ └── config_flow.py # UI configuration
|
||||
├── haos-integration/ # HACS-ready HA Integration
|
||||
│ ├── README.md # Integration documentation
|
||||
│ ├── hacs.json # HACS configuration
|
||||
│ └── custom_components/
|
||||
│ └── remote_media_player/ # Integration code
|
||||
│
|
||||
└── README.md
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
48
haos-integration/.gitignore
vendored
Normal file
48
haos-integration/.gitignore
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Virtual environments
|
||||
venv/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
.claude/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Config files with secrets
|
||||
config.yaml
|
||||
config.json
|
||||
.env
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
25
haos-integration/CLAUDE.md
Normal file
25
haos-integration/CLAUDE.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# HAOS Integration - Development Guide
|
||||
|
||||
## Overview
|
||||
|
||||
HACS-ready Home Assistant custom integration for controlling remote PC media playback.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `custom_components/remote_media_player/` to your Home Assistant config folder.
|
||||
|
||||
Or install via HACS as a custom repository.
|
||||
|
||||
## Requirements
|
||||
|
||||
Requires Media Server running on the target PC.
|
||||
|
||||
Media Server Repository: `TODO: Add repository URL`
|
||||
|
||||
## Integration Location
|
||||
|
||||
Integration files location: `U:\custom_components\remote_media_player`
|
||||
|
||||
## Git Rules
|
||||
|
||||
Always ask for user approval before committing changes to git.
|
||||
98
haos-integration/README.md
Normal file
98
haos-integration/README.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Remote Media Player - Home Assistant Integration
|
||||
|
||||
[](https://github.com/hacs/integration)
|
||||
[](https://github.com/YOUR_USERNAME/haos-remote-media-player/releases)
|
||||
|
||||
A Home Assistant custom integration that allows you to control a remote PC's media playback as a media player entity.
|
||||
|
||||
## Features
|
||||
|
||||
- Full media player controls (play, pause, stop, next, previous)
|
||||
- Volume control and mute
|
||||
- Seek support with smooth timeline updates
|
||||
- Displays current track info (title, artist, album, artwork)
|
||||
- Real-time updates via WebSocket (with HTTP polling fallback)
|
||||
- **Script buttons** - Execute pre-defined scripts (shutdown, restart, lock, sleep, etc.)
|
||||
- Configurable via Home Assistant UI
|
||||
|
||||
## Requirements
|
||||
|
||||
- Home Assistant 2024.1.0 or newer
|
||||
- A running **Media Server** on your PC
|
||||
|
||||
### Media Server
|
||||
|
||||
This integration requires the Media Server to be running on the PC you want to control.
|
||||
|
||||
**Media Server Repository:** `TODO: Add repository URL`
|
||||
|
||||
See the Media Server documentation for installation and setup instructions.
|
||||
|
||||
## Installation
|
||||
|
||||
### HACS (Recommended)
|
||||
|
||||
1. Open HACS in Home Assistant
|
||||
2. Click the three dots menu > **Custom repositories**
|
||||
3. Add this repository URL: `https://github.com/YOUR_USERNAME/haos-remote-media-player`
|
||||
4. Select category: **Integration**
|
||||
5. Click **Add**
|
||||
6. Search for "Remote Media Player" and click **Download**
|
||||
7. Restart Home Assistant
|
||||
|
||||
### Manual Installation
|
||||
|
||||
1. Download the latest release from the [Releases](https://github.com/YOUR_USERNAME/haos-remote-media-player/releases) page
|
||||
2. Extract and copy the `custom_components/remote_media_player` folder to your Home Assistant `config/custom_components/` directory
|
||||
3. Restart Home Assistant
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Go to **Settings** > **Devices & Services**
|
||||
2. Click **+ Add Integration**
|
||||
3. Search for "Remote Media Player"
|
||||
4. Enter the connection details:
|
||||
- **Host**: IP address or hostname of your PC running Media Server
|
||||
- **Port**: Server port (default: 8765)
|
||||
- **API Token**: The authentication token from your Media Server
|
||||
- **Name**: Display name for this media player (optional)
|
||||
|
||||
## Usage
|
||||
|
||||
Once configured, the integration creates:
|
||||
|
||||
### Media Player Entity
|
||||
|
||||
A full-featured media player entity with:
|
||||
- Play/Pause/Stop controls
|
||||
- Next/Previous track
|
||||
- Volume control and mute
|
||||
- Seek functionality
|
||||
- Current track information
|
||||
|
||||
### Script Button Entities
|
||||
|
||||
Button entities for each script defined on your Media Server:
|
||||
- Lock/unlock workstation
|
||||
- Shutdown, restart, sleep, hibernate
|
||||
- Custom scripts
|
||||
|
||||
## Example Lovelace Card
|
||||
|
||||
```yaml
|
||||
type: media-control
|
||||
entity: media_player.remote_media_player
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For detailed documentation, see [custom_components/remote_media_player/README.md](custom_components/remote_media_player/README.md).
|
||||
|
||||
## Support
|
||||
|
||||
- [Report an Issue](https://github.com/YOUR_USERNAME/haos-remote-media-player/issues)
|
||||
- [Media Server Repository](TODO)
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
@@ -14,8 +14,8 @@ A Home Assistant custom component that allows you to control a remote PC's media
|
||||
|
||||
## Requirements
|
||||
|
||||
- Home Assistant 2023.1 or newer
|
||||
- A running [Media Server](../../media_server/README.md) on your PC
|
||||
- Home Assistant 2024.1.0 or newer
|
||||
- A running Media Server on your PC (see Media Server repository)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -38,6 +38,7 @@ async def async_setup_entry(
|
||||
script_name=script["name"],
|
||||
script_label=script["label"],
|
||||
script_description=script.get("description", ""),
|
||||
script_icon=script.get("icon"),
|
||||
)
|
||||
for script in scripts
|
||||
]
|
||||
@@ -59,6 +60,7 @@ class ScriptButtonEntity(ButtonEntity):
|
||||
script_name: str,
|
||||
script_label: str,
|
||||
script_description: str,
|
||||
script_icon: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize the script button."""
|
||||
self._client = client
|
||||
@@ -70,7 +72,8 @@ class ScriptButtonEntity(ButtonEntity):
|
||||
# Entity attributes
|
||||
self._attr_unique_id = f"{entry.entry_id}_script_{script_name}"
|
||||
self._attr_name = script_label
|
||||
self._attr_icon = self._get_icon_for_script(script_name)
|
||||
# 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."""
|
||||
@@ -4,7 +4,7 @@
|
||||
"codeowners": [],
|
||||
"config_flow": true,
|
||||
"dependencies": [],
|
||||
"documentation": "https://github.com/your-username/haos-integration-media-player",
|
||||
"documentation": "https://github.com/YOUR_USERNAME/haos-remote-media-player",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["aiohttp>=3.8.0"],
|
||||
5
haos-integration/hacs.json
Normal file
5
haos-integration/hacs.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Remote Media Player",
|
||||
"render_readme": true,
|
||||
"homeassistant": "2024.1.0"
|
||||
}
|
||||
48
media-server/.gitignore
vendored
Normal file
48
media-server/.gitignore
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Virtual environments
|
||||
venv/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
.claude/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Config files with secrets
|
||||
config.yaml
|
||||
config.json
|
||||
.env
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
39
media-server/CLAUDE.md
Normal file
39
media-server/CLAUDE.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Media Server - Development Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Standalone REST API server (FastAPI) for controlling system-wide media playback on Windows, Linux, macOS, and Android.
|
||||
|
||||
## Running the Server
|
||||
|
||||
### Manual Start
|
||||
|
||||
```bash
|
||||
python -m media_server.main
|
||||
```
|
||||
|
||||
### Auto-Start on Boot (Windows Task Scheduler)
|
||||
|
||||
Run in **Administrator PowerShell** from the media-server directory:
|
||||
|
||||
```powershell
|
||||
.\media_server\service\install_task_windows.ps1
|
||||
```
|
||||
|
||||
To remove the scheduled task:
|
||||
|
||||
```powershell
|
||||
Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Copy `config.example.yaml` to `config.yaml` and customize.
|
||||
|
||||
The API token is generated on first run and displayed in the console output.
|
||||
|
||||
Default port: `8765`
|
||||
|
||||
## Git Rules
|
||||
|
||||
Always ask for user approval before committing changes to git.
|
||||
@@ -258,6 +258,7 @@ Script configuration options:
|
||||
| `command` | Yes | Command to execute |
|
||||
| `label` | No | User-friendly display name (defaults to script name) |
|
||||
| `description` | No | Description of what the script does |
|
||||
| `icon` | No | Custom MDI icon (e.g., `mdi:power`) |
|
||||
| `timeout` | No | Execution timeout in seconds (default: 30, max: 300) |
|
||||
| `working_dir` | No | Working directory for the command |
|
||||
| `shell` | No | Run in shell (default: true) |
|
||||
47
media-server/config.example.yaml
Normal file
47
media-server/config.example.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
# Media Server Configuration
|
||||
# Copy this file to config.yaml and customize as needed.
|
||||
# A secure token will be auto-generated on first run if not specified.
|
||||
|
||||
# API Token (generate a secure random token)
|
||||
api_token: "your-secure-token-here"
|
||||
|
||||
# Server settings
|
||||
host: "0.0.0.0"
|
||||
port: 8765
|
||||
|
||||
# Custom scripts
|
||||
scripts:
|
||||
lock_screen:
|
||||
command: "rundll32.exe user32.dll,LockWorkStation"
|
||||
label: "Lock Screen"
|
||||
description: "Lock the workstation"
|
||||
timeout: 5
|
||||
shell: true
|
||||
|
||||
hibernate:
|
||||
command: "shutdown /h"
|
||||
label: "Hibernate"
|
||||
description: "Hibernate the PC"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
sleep:
|
||||
command: "rundll32.exe powrprof.dll,SetSuspendState 0,1,0"
|
||||
label: "Sleep"
|
||||
description: "Put PC to sleep"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
shutdown:
|
||||
command: "shutdown /s /t 0"
|
||||
label: "Shutdown"
|
||||
description: "Shutdown the PC immediately"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
restart:
|
||||
command: "shutdown /r /t 0"
|
||||
label: "Restart"
|
||||
description: "Restart the PC immediately"
|
||||
timeout: 10
|
||||
shell: true
|
||||
@@ -16,6 +16,7 @@ class ScriptConfig(BaseModel):
|
||||
command: str = Field(..., description="Command or script to execute")
|
||||
label: Optional[str] = Field(default=None, description="User-friendly display label")
|
||||
description: str = Field(default="", description="Script description")
|
||||
icon: Optional[str] = Field(default=None, description="Custom icon (e.g., 'mdi:power')")
|
||||
timeout: int = Field(default=30, description="Execution timeout in seconds", ge=1, le=300)
|
||||
working_dir: Optional[str] = Field(default=None, description="Working directory")
|
||||
shell: bool = Field(default=True, description="Run command in shell")
|
||||
@@ -38,6 +38,7 @@ class ScriptInfo(BaseModel):
|
||||
name: str
|
||||
label: str
|
||||
description: str
|
||||
icon: str | None = None
|
||||
timeout: int
|
||||
|
||||
|
||||
@@ -53,6 +54,7 @@ async def list_scripts(_: str = Depends(verify_token)) -> list[ScriptInfo]:
|
||||
name=name,
|
||||
label=config.label or name.replace("_", " ").title(),
|
||||
description=config.description,
|
||||
icon=config.icon,
|
||||
timeout=config.timeout,
|
||||
)
|
||||
for name, config in settings.scripts.items()
|
||||
Reference in New Issue
Block a user