Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f31adbc
update vizio component to support latest pyvizio with soundbar support
raman325 Mar 22, 2019
5b9534e
Resolved Hound issues
raman325 Mar 22, 2019
f9f8831
Additional Hound issue
raman325 Mar 22, 2019
25bc0e7
Updated based on feedback
raman325 Mar 23, 2019
d2d799f
Style updates
raman325 Mar 23, 2019
0eaa4f3
Additional code styling changes
raman325 Mar 23, 2019
de734a7
Added check for auth token not being set for tv device_class
raman325 Mar 23, 2019
8fd0a48
Limited lines to 80 characters
raman325 Mar 23, 2019
4f57ae1
moved MAX_VOLUME into base package
raman325 Mar 23, 2019
d7dee4b
fixed supported commands
raman325 Mar 23, 2019
4500669
styling changes
raman325 Mar 23, 2019
b5940b9
fix styling yet again
raman325 Mar 23, 2019
103b190
remove unnecessary elif
raman325 Mar 23, 2019
d52f862
removed play/pause since I can't get current state
raman325 Mar 27, 2019
0ecbd65
changed value access method from config dict
raman325 Apr 11, 2019
04836cd
fixed flake failures
raman325 Apr 16, 2019
d4a1779
try to fix docstring
raman325 Apr 17, 2019
67ce154
try to fix docstring
raman325 Apr 17, 2019
1d17739
fixed auth token validation
raman325 Apr 17, 2019
33f74dd
rebase and regenerate requirements_all.txt
raman325 Apr 17, 2019
3c17053
updated log text
raman325 Apr 17, 2019
29e63ff
line length fix
raman325 Apr 17, 2019
041e407
added config validation to handle conditionally optional parameter
raman325 Apr 17, 2019
330959f
updated validate setup log message and string formatting based on review
raman325 Apr 18, 2019
a85fe41
fix pylint error
raman325 Apr 18, 2019
1096f66
less ugly
raman325 Apr 18, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ homeassistant/components/uptimerobot/* @ludeeus
homeassistant/components/utility_meter/* @dgomes
homeassistant/components/velux/* @Julius2342
homeassistant/components/version/* @fabaff
homeassistant/components/vizio/* @raman325
homeassistant/components/waqi/* @andrey-git
homeassistant/components/weather/* @fabaff
homeassistant/components/weblink/* @home-assistant/core
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/vizio/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"name": "Vizio",
"documentation": "https://www.home-assistant.io/components/vizio",
"requirements": [
"pyvizio==0.0.4"
"pyvizio==0.0.7"
],
"dependencies": [],
"codeowners": []
"codeowners": ["@raman325"]
}
157 changes: 105 additions & 52 deletions homeassistant/components/vizio/media_player.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
"""Vizio SmartCast TV support."""
"""Vizio SmartCast Device support."""
from datetime import timedelta
import logging

import voluptuous as vol

from homeassistant import util
from homeassistant.components.media_player import (
MediaPlayerDevice, PLATFORM_SCHEMA)
MediaPlayerDevice,
PLATFORM_SCHEMA
)
from homeassistant.components.media_player.const import (
SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK,
SUPPORT_SELECT_SOURCE, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP)
SUPPORT_NEXT_TRACK,
SUPPORT_PREVIOUS_TRACK,
SUPPORT_SELECT_SOURCE,
SUPPORT_TURN_OFF,
SUPPORT_TURN_ON,
SUPPORT_VOLUME_MUTE,
SUPPORT_VOLUME_SET,
SUPPORT_VOLUME_STEP
)
from homeassistant.const import (
CONF_ACCESS_TOKEN, CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON)
CONF_ACCESS_TOKEN,
CONF_DEVICE_CLASS,
CONF_HOST,
CONF_NAME,
STATE_OFF,
STATE_ON
)
from homeassistant.helpers import config_validation as cv

_LOGGER = logging.getLogger(__name__)
Expand All @@ -22,6 +34,7 @@

DEFAULT_NAME = 'Vizio SmartCast'
DEFAULT_VOLUME_STEP = 1
DEFAULT_DEVICE_CLASS = 'tv'
DEVICE_ID = 'pyvizio'
DEVICE_NAME = 'Python Vizio'

Expand All @@ -30,36 +43,71 @@
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)

SUPPORTED_COMMANDS = SUPPORT_TURN_ON | SUPPORT_TURN_OFF \
| SUPPORT_SELECT_SOURCE \
| SUPPORT_NEXT_TRACK | SUPPORT_PREVIOUS_TRACK \
| SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_STEP \
| SUPPORT_VOLUME_SET

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_ACCESS_TOKEN): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SUPPRESS_WARNING, default=False): cv.boolean,
vol.Optional(CONF_VOLUME_STEP, default=DEFAULT_VOLUME_STEP):
vol.All(vol.Coerce(int), vol.Range(min=1, max=10)),
})
COMMON_SUPPORTED_COMMANDS = (
SUPPORT_SELECT_SOURCE |
SUPPORT_TURN_ON |
SUPPORT_TURN_OFF |
SUPPORT_VOLUME_MUTE |
SUPPORT_VOLUME_SET |
SUPPORT_VOLUME_STEP
)

SUPPORTED_COMMANDS = {
'soundbar': COMMON_SUPPORTED_COMMANDS,
'tv': (
COMMON_SUPPORTED_COMMANDS |
SUPPORT_NEXT_TRACK |
SUPPORT_PREVIOUS_TRACK
)
}
Comment thread
raman325 marked this conversation as resolved.
Outdated


def validate_auth(config):
"""Validate presence of CONF_ACCESS_TOKEN when CONF_DEVICE_CLASS=tv."""
token = config.get(CONF_ACCESS_TOKEN)
if config[CONF_DEVICE_CLASS] == 'tv' and (token is None or token == ''):
raise vol.Invalid(
"When '{}' is 'tv' then '{}' is required.".format(
CONF_DEVICE_CLASS,
CONF_ACCESS_TOKEN,
),
path=[CONF_ACCESS_TOKEN],
)
return config


PLATFORM_SCHEMA = vol.All(
PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_ACCESS_TOKEN): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SUPPRESS_WARNING, default=False): cv.boolean,
vol.Optional(CONF_DEVICE_CLASS, default=DEFAULT_DEVICE_CLASS):
vol.All(cv.string, vol.Lower, vol.In(['tv', 'soundbar'])),
vol.Optional(CONF_VOLUME_STEP, default=DEFAULT_VOLUME_STEP):
vol.All(vol.Coerce(int), vol.Range(min=1, max=10)),
}),
validate_auth,
)


def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the VizioTV media player platform."""
host = config.get(CONF_HOST)
"""Set up the Vizio media player platform."""
host = config[CONF_HOST]
token = config.get(CONF_ACCESS_TOKEN)
name = config.get(CONF_NAME)
volume_step = config.get(CONF_VOLUME_STEP)

device = VizioDevice(host, token, name, volume_step)
name = config[CONF_NAME]
volume_step = config[CONF_VOLUME_STEP]
device_type = config[CONF_DEVICE_CLASS]
device = VizioDevice(host, token, name, volume_step, device_type)
if device.validate_setup() is False:
_LOGGER.error("Failed to set up Vizio TV platform, "
"please check if host and API key are correct")
fail_auth_msg = ""
if token is not None and token != '':
fail_auth_msg = " and auth token is correct"
_LOGGER.error("Failed to set up Vizio platform, please check if host "
"is valid and available%s", fail_auth_msg)
return

if config.get(CONF_SUPPRESS_WARNING):
if config[CONF_SUPPRESS_WARNING]:
from requests.packages import urllib3
_LOGGER.warning("InsecureRequestWarning is disabled "
"because of Vizio platform configuration")
Expand All @@ -68,30 +116,35 @@ def setup_platform(hass, config, add_entities, discovery_info=None):


class VizioDevice(MediaPlayerDevice):
"""Media Player implementation which performs REST requests to TV."""
"""Media Player implementation which performs REST requests to device."""

def __init__(self, host, token, name, volume_step):
def __init__(self, host, token, name, volume_step, device_type):
"""Initialize Vizio device."""
import pyvizio
self._device = pyvizio.Vizio(DEVICE_ID, host, DEFAULT_NAME, token)

self._name = name
self._state = None
self._volume_level = None
self._volume_step = volume_step
self._current_input = None
self._available_inputs = None
self._device_type = device_type
self._supported_commands = SUPPORTED_COMMANDS[device_type]
self._device = pyvizio.Vizio(DEVICE_ID, host, DEFAULT_NAME, token,
device_type)
self._max_volume = float(self._device.get_max_volume())

@util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
def update(self):
"""Retrieve latest state of the TV."""
"""Retrieve latest state of the device."""
is_on = self._device.get_power_state()

if is_on:
self._state = STATE_ON

volume = self._device.get_current_volume()
if volume is not None:
self._volume_level = float(volume) / 100.
self._volume_level = float(volume) / self._max_volume

input_ = self._device.get_current_input()
if input_ is not None:
Expand All @@ -113,40 +166,40 @@ def update(self):

@property
def state(self):
"""Return the state of the TV."""
"""Return the state of the device."""
return self._state

@property
def name(self):
"""Return the name of the TV."""
"""Return the name of the device."""
return self._name

@property
def volume_level(self):
"""Return the volume level of the TV."""
"""Return the volume level of the device."""
return self._volume_level

@property
def source(self):
"""Return current input of the TV."""
"""Return current input of the device."""
return self._current_input

@property
def source_list(self):
"""Return list of available inputs of the TV."""
"""Return list of available inputs of the device."""
return self._available_inputs

@property
def supported_features(self):
"""Flag TV features that are supported."""
return SUPPORTED_COMMANDS
"""Flag device features that are supported."""
return self._supported_commands

def turn_on(self):
"""Turn the TV player on."""
"""Turn the device on."""
self._device.pow_on()

def turn_off(self):
"""Turn the TV player off."""
"""Turn the device off."""
self._device.pow_off()

def mute_volume(self, mute):
Expand All @@ -169,27 +222,27 @@ def select_source(self, source):
self._device.input_switch(source)

def volume_up(self):
"""Increasing volume of the TV."""
self._volume_level += self._volume_step / 100.
"""Increasing volume of the device."""
self._volume_level += self._volume_step / self._max_volume
self._device.vol_up(num=self._volume_step)

def volume_down(self):
"""Decreasing volume of the TV."""
self._volume_level -= self._volume_step / 100.
"""Decreasing volume of the device."""
self._volume_level -= self._volume_step / self._max_volume
self._device.vol_down(num=self._volume_step)

def validate_setup(self):
"""Validate if host is available and key is correct."""
"""Validate if host is available and auth token is correct."""
return self._device.get_current_volume() is not None

def set_volume_level(self, volume):
"""Set volume level."""
if self._volume_level is not None:
if volume > self._volume_level:
num = int(100*(volume - self._volume_level))
num = int(self._max_volume * (volume - self._volume_level))
self._volume_level = volume
self._device.vol_up(num=num)
elif volume < self._volume_level:
num = int(100*(self._volume_level - volume))
num = int(self._max_volume * (self._volume_level - volume))
self._volume_level = volume
self._device.vol_down(num=num)
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,7 @@ pyvera==0.2.45
pyvesync_v2==0.9.6

# homeassistant.components.vizio
pyvizio==0.0.4
pyvizio==0.0.7

# homeassistant.components.velux
pyvlx==0.2.10
Expand Down