Files
wled-screen-controller-mixed/custom_components/wled_screen_controller/__init__.py
alexei.dolgolyov d471a40234
Some checks failed
Validate / validate (push) Failing after 1m6s
Initial commit: WLED Screen Controller with FastAPI server and Home Assistant integration
This is a complete WLED ambient lighting controller that captures screen border pixels
and sends them to WLED devices for immersive ambient lighting effects.

## Server Features:
- FastAPI-based REST API with 17+ endpoints
- Real-time screen capture with multi-monitor support
- Advanced LED calibration system with visual GUI
- API key authentication with labeled tokens
- Per-device brightness control (0-100%)
- Configurable FPS (1-60), border width, and color correction
- Persistent device storage (JSON-based)
- Comprehensive Web UI with dark/light themes
- Docker support with docker-compose
- Windows monitor name detection via WMI (shows "LG ULTRAWIDE" etc.)

## Web UI Features:
- Device management (add, configure, remove WLED devices)
- Real-time status monitoring with FPS metrics
- Settings modal for device configuration
- Visual calibration GUI with edge testing
- Brightness slider per device
- Display selection with friendly monitor names
- Token-based authentication with login/logout
- Responsive button layout

## Calibration System:
- Support for any LED strip layout (clockwise/counterclockwise)
- 4 starting position options (corners)
- Per-edge LED count configuration
- Visual preview with starting position indicator
- Test buttons to light up individual edges
- Smart LED ordering based on start position and direction

## Home Assistant Integration:
- Custom HACS integration
- Switch entities for processing control
- Sensor entities for status and FPS
- Select entities for display selection
- Config flow for easy setup
- Auto-discovery of devices from server

## Technical Stack:
- Python 3.11+
- FastAPI + uvicorn
- mss (screen capture)
- httpx (async WLED client)
- Pydantic (validation)
- WMI (Windows monitor detection)
- Structlog (logging)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 16:38:27 +03:00

101 lines
3.3 KiB
Python

"""The WLED Screen Controller integration."""
from __future__ import annotations
import logging
from datetime import timedelta
from urllib.parse import urlparse
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN, CONF_SERVER_URL, DEFAULT_SCAN_INTERVAL
from .coordinator import WLEDScreenControllerCoordinator
_LOGGER = logging.getLogger(__name__)
PLATFORMS: list[Platform] = [
Platform.SWITCH,
Platform.SENSOR,
Platform.SELECT,
]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up WLED Screen Controller from a config entry."""
server_url = entry.data[CONF_SERVER_URL]
server_name = entry.data.get(CONF_NAME, "WLED Screen Controller")
session = async_get_clientsession(hass)
coordinator = WLEDScreenControllerCoordinator(
hass,
session,
server_url,
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
)
# Fetch initial data
await coordinator.async_config_entry_first_refresh()
# Create hub device (the server PC)
device_registry = dr.async_get(hass)
# Parse URL for hub identifier
parsed_url = urlparse(server_url)
hub_identifier = f"{parsed_url.hostname}:{parsed_url.port or (443 if parsed_url.scheme == 'https' else 80)}"
hub_device = device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, hub_identifier)},
name=server_name,
manufacturer="WLED Screen Controller",
model="Server",
sw_version=coordinator.server_version,
configuration_url=server_url,
)
# Create device entries for each WLED device
if coordinator.data and "devices" in coordinator.data:
for device_id, device_data in coordinator.data["devices"].items():
device_info = device_data["info"]
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, device_id)},
name=device_info["name"],
manufacturer="WLED",
model="Screen Ambient Lighting",
sw_version=f"{device_info.get('led_count', 0)} LEDs",
via_device=(DOMAIN, hub_identifier), # Link to hub
configuration_url=device_info.get("url"),
)
# Store coordinator and hub info
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {
"coordinator": coordinator,
"hub_device_id": hub_device.id,
}
# Setup platforms
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload config entry."""
await async_unload_entry(hass, entry)
await async_setup_entry(hass, entry)