Added new commands and functionality to the harmony remote component. (#7113)

* Added new commands and functionality to the harmony remote component.

-This includes the ability to optionally specify a number of times to repeat a specific command, such as pressing the volume button multiple times.
-Also added a new command that allows you to send multiple commands to the harmony at once, such as sending a set of channel numbers.
-Updated the unit tests for these changes.

* Fix flake8 coding violations

* Remove send_commands command and make send_command handle a single or list of commands

* Remove send_commands tests

* Update itach and kira remotes for new send_command structure. Fix pyharmony version in requirements_all.txt

* Fix incorrect variable name

* Fix a couple minor issues with remote tests
This commit is contained in:
everix1992 2017-05-23 19:00:52 -05:00 committed by Paulus Schoutsen
parent 54c45f80c1
commit 3638b21bcb
9 changed files with 49 additions and 20 deletions

View file

@ -26,6 +26,8 @@ _LOGGER = logging.getLogger(__name__)
ATTR_ACTIVITY = 'activity'
ATTR_COMMAND = 'command'
ATTR_DEVICE = 'device'
ATTR_NUM_REPEATS = 'num_repeats'
ATTR_DELAY_SECS = 'delay_secs'
DOMAIN = 'remote'
@ -40,6 +42,9 @@ SCAN_INTERVAL = timedelta(seconds=30)
SERVICE_SEND_COMMAND = 'send_command'
SERVICE_SYNC = 'sync'
DEFAULT_NUM_REPEATS = '1'
DEFAULT_DELAY_SECS = '0.4'
REMOTE_SERVICE_SCHEMA = vol.Schema({
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
})
@ -50,7 +55,9 @@ REMOTE_SERVICE_TURN_ON_SCHEMA = REMOTE_SERVICE_SCHEMA.extend({
REMOTE_SERVICE_SEND_COMMAND_SCHEMA = REMOTE_SERVICE_SCHEMA.extend({
vol.Required(ATTR_DEVICE): cv.string,
vol.Required(ATTR_COMMAND): cv.string,
vol.Required(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(ATTR_NUM_REPEATS, default=DEFAULT_NUM_REPEATS): cv.string,
vol.Optional(ATTR_DELAY_SECS, default=DEFAULT_DELAY_SECS): cv.string
})
@ -74,11 +81,19 @@ def turn_off(hass, entity_id=None):
hass.services.call(DOMAIN, SERVICE_TURN_OFF, data)
def send_command(hass, device, command, entity_id=None):
def send_command(hass, device, command, entity_id=None,
num_repeats=None, delay_secs=None):
"""Send a command to a device."""
data = {ATTR_DEVICE: str(device), ATTR_COMMAND: command}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
if num_repeats:
data[ATTR_NUM_REPEATS] = num_repeats
if delay_secs:
data[ATTR_DELAY_SECS] = delay_secs
hass.services.call(DOMAIN, SERVICE_SEND_COMMAND, data)
@ -97,13 +112,16 @@ def async_setup(hass, config):
activity_id = service.data.get(ATTR_ACTIVITY)
device = service.data.get(ATTR_DEVICE)
command = service.data.get(ATTR_COMMAND)
num_repeats = service.data.get(ATTR_NUM_REPEATS)
delay_secs = service.data.get(ATTR_DELAY_SECS)
for remote in target_remotes:
if service.service == SERVICE_TURN_ON:
yield from remote.async_turn_on(activity=activity_id)
elif service.service == SERVICE_SEND_COMMAND:
yield from remote.async_send_command(
device=device, command=command)
device=device, command=command,
num_repeats=num_repeats, delay_secs=delay_secs)
else:
yield from remote.async_turn_off()

View file

@ -15,11 +15,12 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT, ATTR_ENTITY_ID)
from homeassistant.components.remote import (
PLATFORM_SCHEMA, DOMAIN, ATTR_DEVICE, ATTR_COMMAND, ATTR_ACTIVITY)
PLATFORM_SCHEMA, DOMAIN, ATTR_DEVICE, ATTR_COMMAND,
ATTR_ACTIVITY, ATTR_NUM_REPEATS, ATTR_DELAY_SECS)
from homeassistant.util import slugify
from homeassistant.config import load_yaml_config_file
REQUIREMENTS = ['pyharmony==1.0.12']
REQUIREMENTS = ['pyharmony==1.0.16']
_LOGGER = logging.getLogger(__name__)
@ -170,11 +171,12 @@ class HarmonyRemote(remote.RemoteDevice):
pyharmony.ha_power_off(self._token, self._ip, self._port)
def send_command(self, **kwargs):
"""Send a command to one device."""
"""Send a set of commands to one device."""
import pyharmony
pyharmony.ha_send_command(
pyharmony.ha_send_commands(
self._token, self._ip, self._port, kwargs[ATTR_DEVICE],
kwargs[ATTR_COMMAND])
kwargs[ATTR_COMMAND], int(kwargs[ATTR_NUM_REPEATS]),
float(kwargs[ATTR_DELAY_SECS]))
def sync(self):
"""Sync the Harmony device with the web service."""

View file

@ -104,7 +104,8 @@ class ITachIP2IRRemote(remote.RemoteDevice):
def send_command(self, **kwargs):
"""Send a command to one device."""
self.itachip2ir.send(self._name, kwargs[ATTR_COMMAND], 1)
for command in kwargs[ATTR_COMMAND]:
self.itachip2ir.send(self._name, command, 1)
def update(self):
"""Update the device."""

View file

@ -64,11 +64,11 @@ class KiraRemote(Entity):
def send_command(self, **kwargs):
"""Send a command to one device."""
code_tuple = (kwargs.get(remote.ATTR_COMMAND),
kwargs.get(remote.ATTR_DEVICE))
_LOGGER.info("Sending Command: %s to %s", *code_tuple)
self._kira.sendCode(code_tuple)
for command in kwargs.get(remote.ATTR_COMMAND):
code_tuple = (command,
kwargs.get(remote.ATTR_DEVICE))
_LOGGER.info("Sending Command: %s to %s", *code_tuple)
self._kira.sendCode(code_tuple)
def async_send_command(self, **kwargs):
"""Send a command to a device.

View file

@ -30,8 +30,14 @@ send_command:
description: Device ID to send command to
example: '32756745'
command:
description: Command to send
description: A single command or a list of commands to send.
example: 'Play'
num_repeats:
description: An optional value that specifies the number of times you want to repeat the command(s). If not specified, the command(s) will not be repeated
example: '5'
delay_secs:
description: An optional value that specifies that number of seconds you want to wait in between repeated commands. If not specified, the default of 0.4 seconds will be used
example: '0.75'
harmony_sync:
description: Syncs the remote's configuration

View file

@ -539,7 +539,7 @@ pyfttt==0.3
pygatt==3.1.1
# homeassistant.components.remote.harmony
pyharmony==1.0.12
pyharmony==1.0.16
# homeassistant.components.binary_sensor.hikvision
pyhik==0.1.2

View file

@ -86,7 +86,8 @@ class TestDemoRemote(unittest.TestCase):
remote.send_command(
self.hass, entity_id='entity_id_val',
device='test_device', command='test_command')
device='test_device', command=['test_command'],
num_repeats='2', delay_secs='0.8')
self.hass.block_till_done()

View file

@ -81,7 +81,8 @@ class TestRemote(unittest.TestCase):
remote.send_command(
self.hass, entity_id='entity_id_val',
device='test_device', command='test_command')
device='test_device', command=['test_command'],
num_repeats='4', delay_secs='0.6')
self.hass.block_till_done()

View file

@ -49,9 +49,9 @@ class TestKiraSensor(unittest.TestCase):
assert remote.name == 'kira'
command = "FAKE_COMMAND"
command = ["FAKE_COMMAND"]
device = "FAKE_DEVICE"
commandTuple = (command, device)
commandTuple = (command[0], device)
remote.send_command(device=device, command=command)
self.mock_kira.sendCode.assert_called_with(commandTuple)