Add channel changing support to SamsungTV component (#14451)

Add channel changing support to SamsungTV component
This commit is contained in:
Matt LeBrun 2018-06-26 10:22:10 -04:00 committed by Martin Hjelmare
parent c79c94550f
commit 0094fd5c34
2 changed files with 85 additions and 4 deletions

View File

@ -4,6 +4,7 @@ Support for interface with an Samsung TV.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.samsungtv/
"""
import asyncio
import logging
import socket
from datetime import timedelta
@ -15,8 +16,9 @@ import voluptuous as vol
from homeassistant.components.media_player import (
SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK,
SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP,
SUPPORT_PLAY, MediaPlayerDevice, PLATFORM_SCHEMA, SUPPORT_TURN_ON)
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_PLAY,
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_PLAY_MEDIA,
MediaPlayerDevice, PLATFORM_SCHEMA, MEDIA_TYPE_CHANNEL)
from homeassistant.const import (
CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON, STATE_UNKNOWN, CONF_PORT,
CONF_MAC)
@ -32,12 +34,13 @@ CONF_TIMEOUT = 'timeout'
DEFAULT_NAME = 'Samsung TV Remote'
DEFAULT_PORT = 55000
DEFAULT_TIMEOUT = 0
KEY_PRESS_TIMEOUT = 1.2
KNOWN_DEVICES_KEY = 'samsungtv_known_devices'
SUPPORT_SAMSUNGTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \
SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | \
SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF | SUPPORT_PLAY
SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF | SUPPORT_PLAY | SUPPORT_PLAY_MEDIA
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
@ -256,6 +259,23 @@ class SamsungTVDevice(MediaPlayerDevice):
"""Send the previous track command."""
self.send_key('KEY_REWIND')
async def async_play_media(self, media_type, media_id, **kwargs):
"""Support changing a channel."""
if media_type != MEDIA_TYPE_CHANNEL:
_LOGGER.error('Unsupported media type')
return
# media_id should only be a channel number
try:
cv.positive_int(media_id)
except vol.Invalid:
_LOGGER.error('Media ID must be positive integer')
return
for digit in media_id:
await self.hass.async_add_job(self.send_key, 'KEY_' + digit)
await asyncio.sleep(KEY_PRESS_TIMEOUT, self.hass.loop)
def turn_on(self):
"""Turn the media player on."""
if self._mac:

View File

@ -1,11 +1,16 @@
"""Tests for samsungtv Components."""
import asyncio
import unittest
from unittest.mock import call, patch, MagicMock
from subprocess import CalledProcessError
from asynctest import mock
import pytest
import tests.common
from homeassistant.components.media_player import SUPPORT_TURN_ON
from homeassistant.components.media_player import SUPPORT_TURN_ON, \
MEDIA_TYPE_CHANNEL, MEDIA_TYPE_URL
from homeassistant.components.media_player.samsungtv import setup_platform, \
CONF_TIMEOUT, SamsungTVDevice, SUPPORT_SAMSUNGTV
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, STATE_ON, \
@ -301,3 +306,59 @@ class TestSamsungTv(unittest.TestCase):
self.device._mac = "fake"
self.device.turn_on()
self.device._wol.send_magic_packet.assert_called_once_with("fake")
@pytest.fixture
def samsung_mock():
"""Mock samsungctl."""
with patch.dict('sys.modules', {
'samsungctl': MagicMock(),
}):
yield
async def test_play_media(hass, samsung_mock):
"""Test for play_media."""
asyncio_sleep = asyncio.sleep
sleeps = []
async def sleep(duration, loop):
sleeps.append(duration)
await asyncio_sleep(0, loop=loop)
with patch('asyncio.sleep', new=sleep):
device = SamsungTVDevice(**WORKING_CONFIG)
device.hass = hass
device.send_key = mock.Mock()
await device.async_play_media(MEDIA_TYPE_CHANNEL, "576")
exp = [call("KEY_5"), call("KEY_7"), call("KEY_6")]
assert device.send_key.call_args_list == exp
assert len(sleeps) == 3
async def test_play_media_invalid_type(hass, samsung_mock):
"""Test for play_media with invalid media type."""
url = "https://example.com"
device = SamsungTVDevice(**WORKING_CONFIG)
device.send_key = mock.Mock()
await device.async_play_media(MEDIA_TYPE_URL, url)
assert device.send_key.call_count == 0
async def test_play_media_channel_as_string(hass, samsung_mock):
"""Test for play_media with invalid channel as string."""
url = "https://example.com"
device = SamsungTVDevice(**WORKING_CONFIG)
device.send_key = mock.Mock()
await device.async_play_media(MEDIA_TYPE_CHANNEL, url)
assert device.send_key.call_count == 0
async def test_play_media_channel_as_non_positive(hass, samsung_mock):
"""Test for play_media with invalid channel as non positive integer."""
device = SamsungTVDevice(**WORKING_CONFIG)
device.send_key = mock.Mock()
await device.async_play_media(MEDIA_TYPE_CHANNEL, "-4")
assert device.send_key.call_count == 0