mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Mediaroom (#11864)
* make port mapping optional * dependencies + improvements * Added bytes and packets sensors from IGD * flake8 check * new sensor with upnp counters * checks * whitespaces in blank line * requirements update * added sensor.upnp to .coveragerc * downgrade miniupnpc Latest version of miniupnpc is 2.0, but pypi only has 1.9 Fortunately it is enough * revert to non async miniupnpc will do network calls, so this component can’t be moved to coroutine * hof hof forgot to remove import ot asyncio * Add baudrate option * merge * Added Mediaroom media_player component * Updated header Works with MEO and VDF set-top boxes in Portugal * formatting * Development Checklist (done) * fix formatting according to houndci-bot * more format fixing (tks houndci-bot) * more fixes * too much cleanup... * too much * pylint check * Initial commit Basic configuration testing * flake8 and lint
This commit is contained in:
parent
f7c9787418
commit
880f18a37e
@ -439,6 +439,7 @@ omit =
|
|||||||
homeassistant/components/media_player/kodi.py
|
homeassistant/components/media_player/kodi.py
|
||||||
homeassistant/components/media_player/lg_netcast.py
|
homeassistant/components/media_player/lg_netcast.py
|
||||||
homeassistant/components/media_player/liveboxplaytv.py
|
homeassistant/components/media_player/liveboxplaytv.py
|
||||||
|
homeassistant/components/media_player/mediaroom.py
|
||||||
homeassistant/components/media_player/mpchc.py
|
homeassistant/components/media_player/mpchc.py
|
||||||
homeassistant/components/media_player/mpd.py
|
homeassistant/components/media_player/mpd.py
|
||||||
homeassistant/components/media_player/nad.py
|
homeassistant/components/media_player/nad.py
|
||||||
|
199
homeassistant/components/media_player/mediaroom.py
Normal file
199
homeassistant/components/media_player/mediaroom.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
"""
|
||||||
|
Support for the Mediaroom Set-up-box.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/media_player.mediaroom/
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.media_player import (
|
||||||
|
MEDIA_TYPE_CHANNEL, SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA,
|
||||||
|
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_STOP, PLATFORM_SCHEMA,
|
||||||
|
SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK, SUPPORT_PLAY,
|
||||||
|
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_MUTE,
|
||||||
|
MediaPlayerDevice)
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_HOST, CONF_NAME, CONF_OPTIMISTIC, CONF_TIMEOUT,
|
||||||
|
STATE_PAUSED, STATE_PLAYING, STATE_STANDBY,
|
||||||
|
STATE_ON)
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
REQUIREMENTS = ['pymediaroom==0.5']
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
NOTIFICATION_TITLE = 'Mediaroom Media Player Setup'
|
||||||
|
NOTIFICATION_ID = 'mediaroom_notification'
|
||||||
|
DEFAULT_NAME = 'Mediaroom STB'
|
||||||
|
DEFAULT_TIMEOUT = 9
|
||||||
|
|
||||||
|
KNOWN_HOSTS = []
|
||||||
|
|
||||||
|
SUPPORT_MEDIAROOM = SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \
|
||||||
|
SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE | \
|
||||||
|
SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_NEXT_TRACK | \
|
||||||
|
SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_HOST): cv.string,
|
||||||
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||||
|
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
|
"""Set up the Mediaroom platform."""
|
||||||
|
hosts = []
|
||||||
|
|
||||||
|
host = config.get(CONF_HOST, None)
|
||||||
|
if host is None:
|
||||||
|
_LOGGER.info("Trying to discover Mediaroom STB")
|
||||||
|
|
||||||
|
from pymediaroom import Remote
|
||||||
|
|
||||||
|
host = Remote.discover(KNOWN_HOSTS)
|
||||||
|
if host is None:
|
||||||
|
# Can't find any STB
|
||||||
|
return False
|
||||||
|
hosts.append(host)
|
||||||
|
KNOWN_HOSTS.append(host)
|
||||||
|
|
||||||
|
stbs = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
for host in hosts:
|
||||||
|
stbs.append(MediaroomDevice(
|
||||||
|
config.get(CONF_NAME),
|
||||||
|
host,
|
||||||
|
config.get(CONF_OPTIMISTIC),
|
||||||
|
config.get(CONF_TIMEOUT)
|
||||||
|
))
|
||||||
|
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
hass.components.persistent_notification.create(
|
||||||
|
'Error: Unable to initialize mediaroom at {}<br />'
|
||||||
|
'Check its network connection or consider '
|
||||||
|
'using auto discovery.<br />'
|
||||||
|
'You will need to restart hass after fixing.'
|
||||||
|
''.format(host),
|
||||||
|
title=NOTIFICATION_TITLE,
|
||||||
|
notification_id=NOTIFICATION_ID)
|
||||||
|
|
||||||
|
add_devices(stbs)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class MediaroomDevice(MediaPlayerDevice):
|
||||||
|
"""Representation of a Mediaroom set-up-box on the network."""
|
||||||
|
|
||||||
|
def __init__(self, name, host, optimistic=False, timeout=DEFAULT_TIMEOUT):
|
||||||
|
"""Initialize the device."""
|
||||||
|
from pymediaroom import Remote
|
||||||
|
|
||||||
|
self.stb = Remote(host, timeout=timeout)
|
||||||
|
_LOGGER.info(
|
||||||
|
"Found %s at %s%s", name, host,
|
||||||
|
" - I'm optimistic" if optimistic else "")
|
||||||
|
self._name = name
|
||||||
|
self._is_standby = not optimistic
|
||||||
|
self._current = None
|
||||||
|
self._optimistic = optimistic
|
||||||
|
self._state = STATE_STANDBY
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Retrieve latest state."""
|
||||||
|
if not self._optimistic:
|
||||||
|
self._is_standby = self.stb.get_standby()
|
||||||
|
if self._is_standby:
|
||||||
|
self._state = STATE_STANDBY
|
||||||
|
elif self._state not in [STATE_PLAYING, STATE_PAUSED]:
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s(%s) is [%s]",
|
||||||
|
self._name, self.stb.stb_ip, self._state)
|
||||||
|
|
||||||
|
def play_media(self, media_type, media_id, **kwargs):
|
||||||
|
"""Play media."""
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s(%s) Play media: %s (%s)",
|
||||||
|
self._name, self.stb.stb_ip, media_id, media_type)
|
||||||
|
if media_type != MEDIA_TYPE_CHANNEL:
|
||||||
|
_LOGGER.error('invalid media type')
|
||||||
|
return
|
||||||
|
if media_id.isdigit():
|
||||||
|
media_id = int(media_id)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
self.stb.send_cmd(media_id)
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return the name of the device."""
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
# MediaPlayerDevice properties and methods
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
"""Return the state of the device."""
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self):
|
||||||
|
"""Flag media player features that are supported."""
|
||||||
|
return SUPPORT_MEDIAROOM
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_content_type(self):
|
||||||
|
"""Return the content type of current playing media."""
|
||||||
|
return MEDIA_TYPE_CHANNEL
|
||||||
|
|
||||||
|
def turn_on(self):
|
||||||
|
"""Turn on the receiver."""
|
||||||
|
self.stb.send_cmd('Power')
|
||||||
|
self._state = STATE_ON
|
||||||
|
|
||||||
|
def turn_off(self):
|
||||||
|
"""Turn off the receiver."""
|
||||||
|
self.stb.send_cmd('Power')
|
||||||
|
self._state = STATE_STANDBY
|
||||||
|
|
||||||
|
def media_play(self):
|
||||||
|
"""Send play command."""
|
||||||
|
_LOGGER.debug("media_play()")
|
||||||
|
self.stb.send_cmd('PlayPause')
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
|
||||||
|
def media_pause(self):
|
||||||
|
"""Send pause command."""
|
||||||
|
self.stb.send_cmd('PlayPause')
|
||||||
|
self._state = STATE_PAUSED
|
||||||
|
|
||||||
|
def media_stop(self):
|
||||||
|
"""Send stop command."""
|
||||||
|
self.stb.send_cmd('Stop')
|
||||||
|
self._state = STATE_PAUSED
|
||||||
|
|
||||||
|
def media_previous_track(self):
|
||||||
|
"""Send Program Down command."""
|
||||||
|
self.stb.send_cmd('ProgDown')
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
|
||||||
|
def media_next_track(self):
|
||||||
|
"""Send Program Up command."""
|
||||||
|
self.stb.send_cmd('ProgUp')
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
|
||||||
|
def volume_up(self):
|
||||||
|
"""Send volume up command."""
|
||||||
|
self.stb.send_cmd('VolUp')
|
||||||
|
|
||||||
|
def volume_down(self):
|
||||||
|
"""Send volume up command."""
|
||||||
|
self.stb.send_cmd('VolDown')
|
||||||
|
|
||||||
|
def mute_volume(self, mute):
|
||||||
|
"""Send mute command."""
|
||||||
|
self.stb.send_cmd('Mute')
|
@ -789,6 +789,9 @@ pylutron==0.1.0
|
|||||||
# homeassistant.components.notify.mailgun
|
# homeassistant.components.notify.mailgun
|
||||||
pymailgunner==1.4
|
pymailgunner==1.4
|
||||||
|
|
||||||
|
# homeassistant.components.media_player.mediaroom
|
||||||
|
pymediaroom==0.5
|
||||||
|
|
||||||
# homeassistant.components.mochad
|
# homeassistant.components.mochad
|
||||||
pymochad==0.2.0
|
pymochad==0.2.0
|
||||||
|
|
||||||
|
32
tests/components/media_player/test_mediaroom.py
Normal file
32
tests/components/media_player/test_mediaroom.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""The tests for the mediaroom media_player."""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from homeassistant.setup import setup_component
|
||||||
|
import homeassistant.components.media_player as media_player
|
||||||
|
from tests.common import (
|
||||||
|
assert_setup_component, get_test_home_assistant)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMediaroom(unittest.TestCase):
|
||||||
|
"""Tests the Mediaroom Component."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Initialize values for this test case class."""
|
||||||
|
self.hass = get_test_home_assistant()
|
||||||
|
|
||||||
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
|
"""Stop everything that we started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
|
def test_mediaroom_config(self):
|
||||||
|
"""Test set up the platform with basic configuration."""
|
||||||
|
config = {
|
||||||
|
media_player.DOMAIN: {
|
||||||
|
'platform': 'mediaroom',
|
||||||
|
'name': 'Living Room'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with assert_setup_component(1, media_player.DOMAIN) as result_config:
|
||||||
|
assert setup_component(self.hass, media_player.DOMAIN, config)
|
||||||
|
assert result_config[media_player.DOMAIN]
|
Loading…
x
Reference in New Issue
Block a user