Files
alexei.dolgolyov 6ae0ed1787
Release / release (push) Successful in 2s
chore: release v0.2.0
Production-readiness pass: security hardening, performance improvements,
new services (send_message, set_repeat, refresh_library), diagnostics,
reauth flow, image proxy, per-instance device IDs, exponential WS
reconnect backoff, ID validation, stale device cleanup, and supporting
integration plumbing. Three rounds of independent code review applied.

See RELEASE_NOTES.md for the full changelog.
2026-05-26 13:16:36 +03:00

7.5 KiB

v0.2.0 (2026-05-26)

Production-readiness pass: security hardening, performance improvements, new services, and supporting integration plumbing. Three rounds of independent code review applied.

Breaking Changes

  • EmbyApiClient and EmbyWebSocket constructors now require an injected aiohttp.ClientSession and a device_id. Both clients never own or close the session — Home Assistant owns it. Custom integrations or scripts importing these classes directly must update their call sites.

Features

  • WebSocket real-time updates now drive entity state without firing a REST refresh on every PlaybackProgress event. Sessions update in place via dataclasses.replace; REST falls back to a 5-minute safety net while the WS is up.
  • Image proxy: artwork is fetched server-side with the API key in the X-Emby-Token header; the API key never appears in URLs returned to the browser.
  • Per-instance device ID derived from instance_id.async_get(hass) and the config-entry id — multiple Home Assistant installs no longer collide on the same Emby server.
  • Self-signed HTTPS support via a new verify_ssl toggle in the config flow (defaults to verifying).
  • Reauth flow: when the server rejects the API key, Home Assistant prompts for a new one inline instead of leaving the integration broken.
  • Repeat mode control wired through the standard media_player.repeat_set UI; HA MediaPlayerEnqueue mapped explicitly to Emby PlayNow / PlayNext / PlayLast.
  • Per-client device class inferred from the Emby client name (AndroidTV / Kodi / Roku → TV, music clients → Speaker, others → generic).
  • Three new services:
    • emby_player.send_message — display a banner on an Emby client (doorbells, alarms, laundry timers).
    • emby_player.set_repeat — set RepeatNone / RepeatOne / RepeatAll.
    • emby_player.refresh_library — trigger a server-side library scan.
  • Diagnostics: redacted entry + sessions JSON dump from Settings → Integrations → "..." → Download diagnostics. API key is redacted; session / device / user IDs are replaced with stable hashes.
  • Hub device registered for via_device linkage; per-session devices now appear under it.
  • Zeroconf + SSDP discovery hints so Home Assistant can find Emby servers.
  • Stale device cleanup removes devices for sessions absent over 30 minutes (with a 10-minute setup grace period); the coordinator's forget_session helper prevents the last-seen map from growing unbounded.

Bug Fixes

  • WebSocket reconnect uses exponential backoff with jitter (capped at 5 min) instead of a fixed 30 s; auth failures no longer trigger infinite retry; the reconnect task is tracked and cancelled cleanly on unload.
  • media_position_updated_at now reflects the real coordinator update time, eliminating spurious state writes from returning utcnow() on every property read.
  • Authentication failures during a coordinator update now raise ConfigEntryAuthFailed so Home Assistant actually triggers the reauth flow.
  • WebSocket authentication moved into HTTP headers — the API key no longer appears in proxy access logs.
  • MediaPlayerDeviceClass.TV is no longer hardcoded for non-TV clients.
  • _attr_has_entity_name = True combined with _attr_name no longer double-prints the device name in the UI.
  • Browse media now raises BrowseError with context (and wraps unexpected exceptions instead of surfacing 500s).
  • Non-admin API keys fall back to /Users/Public instead of failing setup.
  • All session / item / user IDs are validated against ^[A-Za-z0-9_-]{1,128}$ before interpolation into REST paths (defense-in-depth against path traversal / SSRF).
  • image_type validated against a whitelist (Primary, Backdrop, Thumb, Logo, Banner, Art, Disc, Box).
  • play_media raises ServiceValidationError on bad input (not ValueError); validates media_id format and position type.
  • async_remove_config_entry_device refuses to remove the hub device and any session still present in the coordinator.
  • WebSocket ForceKeepAlive is now echoed as KeepAlive so the server doesn't drop idle connections.
  • PlaySessionId fallback removed from playback-event parsing — only SessionId is matched, eliminating cross-device false positives.
  • _safe_int helper hardens numeric field parsing against null / string / malformed payloads (RunTimeTicks, PositionTicks, VolumeLevel, etc.).
  • Image fetches get a dedicated 30 s timeout, separate from the 15 s REST default.
  • manifest.json codeowners corrected to an empty list (hassfest validates entries against GitHub handles).

Performance

  • WebSocket / REST race resolved: _async_update_data records request_started, then merges REST results with any session whose last_seen is newer (WS state wins for in-flight progress).
  • REST poll interval automatically slows to 5 min while the WebSocket is connected, restoring the user-configured interval if it disconnects.
  • WebSocket callbacks may be sync or async; async ones are detached via asyncio.create_task so a slow consumer can't stall the reader.

Development / Internal

  • Frozen dataclasses (EmbyNowPlaying, EmbyPlayState, EmbySession) across the coordinator state — safer for concurrency and immutability.
  • manifest.json declares integration_type: hub, quality_scale: silver, loggers, and discovery hints.
  • HACS minimum Home Assistant bumped to 2024.10.0.
  • Client version sourced from manifest.json at startup via loader.async_get_integration (no more DEVICE_VERSION drift).
  • New diagnostics.py, services.py, services.yaml.
  • Strings + translations/en.json extended for verify_ssl, reauth_confirm, and the three new services.
  • README.md and CLAUDE.md rewritten to match the v0.2.0 state of the integration.

Files Changed
File Status
CLAUDE.md Modified
README.md Modified
RELEASE_NOTES.md Modified
hacs.json Modified
custom_components/emby_player/__init__.py Modified
custom_components/emby_player/api.py Modified
custom_components/emby_player/browse_media.py Modified
custom_components/emby_player/config_flow.py Modified
custom_components/emby_player/const.py Modified
custom_components/emby_player/coordinator.py Modified
custom_components/emby_player/manifest.json Modified
custom_components/emby_player/media_player.py Modified
custom_components/emby_player/strings.json Modified
custom_components/emby_player/translations/en.json Modified
custom_components/emby_player/websocket.py Modified
custom_components/emby_player/diagnostics.py Added
custom_components/emby_player/services.py Added
custom_components/emby_player/services.yaml Added

v0.1.0 (2026-03-26)

Initial release of the Emby Media Player custom integration for Home Assistant (HACS).

Features

  • Full Emby Server media player integration for Home Assistant (46cb2fb)

All Commits
Hash Message Author
46cb2fb Initial commit for Emby Media Player HAOS HACS integration alexei.dolgolyov