Add vlc telnet error handler decorator (#58468)

* Add vlc telnet error handler decorator

* Delint

* Update stale docstring
This commit is contained in:
Martin Hjelmare 2021-10-26 18:43:33 +02:00 committed by GitHub
parent 6b1b8c9880
commit 777589cdcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,7 +2,8 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime
from typing import Any from functools import wraps
from typing import Any, Callable, TypeVar, cast
from aiovlc.client import Client from aiovlc.client import Client
from aiovlc.exceptions import AuthError, CommandError, ConnectError from aiovlc.exceptions import AuthError, CommandError, ConnectError
@ -65,6 +66,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
} }
) )
Func = TypeVar("Func", bound=Callable[..., Any])
async def async_setup_platform( async def async_setup_platform(
hass: HomeAssistant, hass: HomeAssistant,
@ -96,6 +99,25 @@ async def async_setup_entry(
async_add_entities([VlcDevice(entry, vlc, name, available)], True) async_add_entities([VlcDevice(entry, vlc, name, available)], True)
def catch_vlc_errors(func: Func) -> Func:
"""Catch VLC errors."""
@wraps(func)
async def wrapper(self, *args: Any, **kwargs: Any) -> Any:
"""Catch VLC errors and modify availability."""
try:
await func(self, *args, **kwargs)
except CommandError as err:
LOGGER.error("Command error: %s", err)
except ConnectError as err:
# pylint: disable=protected-access
if self._available:
LOGGER.error("Connection error: %s", err)
self._available = False
return cast(Func, wrapper)
class VlcDevice(MediaPlayerEntity): class VlcDevice(MediaPlayerEntity):
"""Representation of a vlc player.""" """Representation of a vlc player."""
@ -125,6 +147,7 @@ class VlcDevice(MediaPlayerEntity):
"entry_type": "service", "entry_type": "service",
} }
@catch_vlc_errors
async def async_update(self) -> None: async def async_update(self) -> None:
"""Get the latest details from the device.""" """Get the latest details from the device."""
if not self._available: if not self._available:
@ -147,7 +170,6 @@ class VlcDevice(MediaPlayerEntity):
self._available = True self._available = True
LOGGER.info("Connected to vlc host: %s", self._vlc.host) LOGGER.info("Connected to vlc host: %s", self._vlc.host)
try:
status = await self._vlc.status() status = await self._vlc.status()
LOGGER.debug("Status: %s", status) LOGGER.debug("Status: %s", status)
@ -182,13 +204,6 @@ class VlcDevice(MediaPlayerEntity):
if data_info := data.get("data"): if data_info := data.get("data"):
self._media_title = data_info["filename"] self._media_title = data_info["filename"]
except CommandError as err:
LOGGER.error("Command error: %s", err)
except ConnectError as err:
if self._available:
LOGGER.error("Connection error: %s", err)
self._available = False
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """Return the name of the device."""
@ -249,10 +264,12 @@ class VlcDevice(MediaPlayerEntity):
"""Artist of current playing media, music track only.""" """Artist of current playing media, music track only."""
return self._media_artist return self._media_artist
@catch_vlc_errors
async def async_media_seek(self, position: float) -> None: async def async_media_seek(self, position: float) -> None:
"""Seek the media to a specific location.""" """Seek the media to a specific location."""
await self._vlc.seek(round(position)) await self._vlc.seek(round(position))
@catch_vlc_errors
async def async_mute_volume(self, mute: bool) -> None: async def async_mute_volume(self, mute: bool) -> None:
"""Mute the volume.""" """Mute the volume."""
assert self._volume is not None assert self._volume is not None
@ -264,6 +281,7 @@ class VlcDevice(MediaPlayerEntity):
self._muted = mute self._muted = mute
@catch_vlc_errors
async def async_set_volume_level(self, volume: float) -> None: async def async_set_volume_level(self, volume: float) -> None:
"""Set volume level, range 0..1.""" """Set volume level, range 0..1."""
await self._vlc.set_volume(round(volume * MAX_VOLUME)) await self._vlc.set_volume(round(volume * MAX_VOLUME))
@ -273,11 +291,13 @@ class VlcDevice(MediaPlayerEntity):
# This can happen if we were muted and then see a volume_up. # This can happen if we were muted and then see a volume_up.
self._muted = False self._muted = False
@catch_vlc_errors
async def async_media_play(self) -> None: async def async_media_play(self) -> None:
"""Send play command.""" """Send play command."""
await self._vlc.play() await self._vlc.play()
self._state = STATE_PLAYING self._state = STATE_PLAYING
@catch_vlc_errors
async def async_media_pause(self) -> None: async def async_media_pause(self) -> None:
"""Send pause command.""" """Send pause command."""
status = await self._vlc.status() status = await self._vlc.status()
@ -288,11 +308,13 @@ class VlcDevice(MediaPlayerEntity):
self._state = STATE_PAUSED self._state = STATE_PAUSED
@catch_vlc_errors
async def async_media_stop(self) -> None: async def async_media_stop(self) -> None:
"""Send stop command.""" """Send stop command."""
await self._vlc.stop() await self._vlc.stop()
self._state = STATE_IDLE self._state = STATE_IDLE
@catch_vlc_errors
async def async_play_media( async def async_play_media(
self, media_type: str, media_id: str, **kwargs: Any self, media_type: str, media_id: str, **kwargs: Any
) -> None: ) -> None:
@ -308,18 +330,22 @@ class VlcDevice(MediaPlayerEntity):
await self._vlc.add(media_id) await self._vlc.add(media_id)
self._state = STATE_PLAYING self._state = STATE_PLAYING
@catch_vlc_errors
async def async_media_previous_track(self) -> None: async def async_media_previous_track(self) -> None:
"""Send previous track command.""" """Send previous track command."""
await self._vlc.prev() await self._vlc.prev()
@catch_vlc_errors
async def async_media_next_track(self) -> None: async def async_media_next_track(self) -> None:
"""Send next track command.""" """Send next track command."""
await self._vlc.next() await self._vlc.next()
@catch_vlc_errors
async def async_clear_playlist(self) -> None: async def async_clear_playlist(self) -> None:
"""Clear players playlist.""" """Clear players playlist."""
await self._vlc.clear() await self._vlc.clear()
@catch_vlc_errors
async def async_set_shuffle(self, shuffle: bool) -> None: async def async_set_shuffle(self, shuffle: bool) -> None:
"""Enable/disable shuffle mode.""" """Enable/disable shuffle mode."""
shuffle_command = "on" if shuffle else "off" shuffle_command = "on" if shuffle else "off"