6ae0ed1787
Release / release (push) Successful in 2s
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.
7.5 KiB
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
EmbyApiClientandEmbyWebSocketconstructors now require an injectedaiohttp.ClientSessionand adevice_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
PlaybackProgressevent. Sessions update in place viadataclasses.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-Tokenheader; 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_ssltoggle 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_setUI; HAMediaPlayerEnqueuemapped explicitly to EmbyPlayNow/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_devicelinkage; 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_sessionhelper 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_atnow reflects the real coordinator update time, eliminating spurious state writes from returningutcnow()on every property read.- Authentication failures during a coordinator update now raise
ConfigEntryAuthFailedso Home Assistant actually triggers the reauth flow. - WebSocket authentication moved into HTTP headers — the API key no longer appears in proxy access logs.
MediaPlayerDeviceClass.TVis no longer hardcoded for non-TV clients._attr_has_entity_name = Truecombined with_attr_nameno longer double-prints the device name in the UI.- Browse media now raises
BrowseErrorwith context (and wraps unexpected exceptions instead of surfacing 500s). - Non-admin API keys fall back to
/Users/Publicinstead 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_typevalidated against a whitelist (Primary,Backdrop,Thumb,Logo,Banner,Art,Disc,Box).play_mediaraisesServiceValidationErroron bad input (notValueError); validatesmedia_idformat andpositiontype.async_remove_config_entry_devicerefuses to remove the hub device and any session still present in the coordinator.- WebSocket
ForceKeepAliveis now echoed asKeepAliveso the server doesn't drop idle connections. PlaySessionIdfallback removed from playback-event parsing — onlySessionIdis matched, eliminating cross-device false positives._safe_inthelper hardens numeric field parsing againstnull/ string / malformed payloads (RunTimeTicks,PositionTicks,VolumeLevel, etc.).- Image fetches get a dedicated 30 s timeout, separate from the 15 s REST default.
manifest.jsoncodeownerscorrected to an empty list (hassfest validates entries against GitHub handles).
Performance
- WebSocket / REST race resolved:
_async_update_datarecordsrequest_started, then merges REST results with any session whoselast_seenis 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_taskso 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.jsondeclaresintegration_type: hub,quality_scale: silver,loggers, and discovery hints.- HACS minimum Home Assistant bumped to
2024.10.0. - Client version sourced from
manifest.jsonat startup vialoader.async_get_integration(no moreDEVICE_VERSIONdrift). - New
diagnostics.py,services.py,services.yaml. - Strings +
translations/en.jsonextended forverify_ssl,reauth_confirm, and the three new services. README.mdandCLAUDE.mdrewritten 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 |