mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02: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:
@ -439,6 +439,7 @@ omit =
|
||||
homeassistant/components/media_player/kodi.py
|
||||
homeassistant/components/media_player/lg_netcast.py
|
||||
homeassistant/components/media_player/liveboxplaytv.py
|
||||
homeassistant/components/media_player/mediaroom.py
|
||||
homeassistant/components/media_player/mpchc.py
|
||||
homeassistant/components/media_player/mpd.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
|
||||
pymailgunner==1.4
|
||||
|
||||
# homeassistant.components.media_player.mediaroom
|
||||
pymediaroom==0.5
|
||||
|
||||
# homeassistant.components.mochad
|
||||
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]
|
Reference in New Issue
Block a user