From 7d7c2104ead967a186ea9d7408e9f6399883809f Mon Sep 17 00:00:00 2001 From: lich Date: Wed, 18 Jul 2018 04:58:30 +0800 Subject: [PATCH] Customizable command timeout (#15442) * Customizable command timeout * Change string to int * update the tests. Do the same thing on the binary_sensor.command_line. --- .../components/binary_sensor/command_line.py | 8 +++++++- homeassistant/components/sensor/command_line.py | 13 ++++++++++--- tests/components/binary_sensor/test_command_line.py | 8 +++++--- tests/components/sensor/test_command_line.py | 9 +++++---- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/binary_sensor/command_line.py b/homeassistant/components/binary_sensor/command_line.py index 480786b2c2c..c2045c2df5e 100644 --- a/homeassistant/components/binary_sensor/command_line.py +++ b/homeassistant/components/binary_sensor/command_line.py @@ -25,6 +25,9 @@ DEFAULT_PAYLOAD_OFF = 'OFF' SCAN_INTERVAL = timedelta(seconds=60) +CONF_COMMAND_TIMEOUT = 'command_timeout' +DEFAULT_TIMEOUT = 15 + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_COMMAND): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, @@ -32,6 +35,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string, vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, + vol.Optional( + CONF_COMMAND_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, }) @@ -43,9 +48,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): payload_on = config.get(CONF_PAYLOAD_ON) device_class = config.get(CONF_DEVICE_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) + command_timeout = config.get(CONF_COMMAND_TIMEOUT) if value_template is not None: value_template.hass = hass - data = CommandSensorData(hass, command) + data = CommandSensorData(hass, command, command_timeout) add_devices([CommandBinarySensor( hass, data, name, device_class, payload_on, payload_off, diff --git a/homeassistant/components/sensor/command_line.py b/homeassistant/components/sensor/command_line.py index 4a26a1dc9fc..2003b1b41c9 100644 --- a/homeassistant/components/sensor/command_line.py +++ b/homeassistant/components/sensor/command_line.py @@ -27,11 +27,16 @@ DEFAULT_NAME = 'Command Sensor' SCAN_INTERVAL = timedelta(seconds=60) +CONF_COMMAND_TIMEOUT = 'command_timeout' +DEFAULT_TIMEOUT = 15 + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_COMMAND): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, + vol.Optional( + CONF_COMMAND_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, }) @@ -41,9 +46,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): command = config.get(CONF_COMMAND) unit = config.get(CONF_UNIT_OF_MEASUREMENT) value_template = config.get(CONF_VALUE_TEMPLATE) + command_timeout = config.get(CONF_COMMAND_TIMEOUT) if value_template is not None: value_template.hass = hass - data = CommandSensorData(hass, command) + data = CommandSensorData(hass, command, command_timeout) add_devices([CommandSensor(hass, data, name, unit, value_template)], True) @@ -92,11 +98,12 @@ class CommandSensor(Entity): class CommandSensorData(object): """The class for handling the data retrieval.""" - def __init__(self, hass, command): + def __init__(self, hass, command, command_timeout): """Initialize the data object.""" self.value = None self.hass = hass self.command = command + self.timeout = command_timeout def update(self): """Get the latest data with a shell command.""" @@ -135,7 +142,7 @@ class CommandSensorData(object): try: _LOGGER.info("Running command: %s", command) return_value = subprocess.check_output( - command, shell=shell, timeout=15) + command, shell=shell, timeout=self.timeout) self.value = return_value.strip().decode('utf-8') except subprocess.CalledProcessError: _LOGGER.error("Command failed: %s", command) diff --git a/tests/components/binary_sensor/test_command_line.py b/tests/components/binary_sensor/test_command_line.py index d01b62e4c12..07389c7c8a9 100644 --- a/tests/components/binary_sensor/test_command_line.py +++ b/tests/components/binary_sensor/test_command_line.py @@ -24,7 +24,9 @@ class TestCommandSensorBinarySensor(unittest.TestCase): config = {'name': 'Test', 'command': 'echo 1', 'payload_on': '1', - 'payload_off': '0'} + 'payload_off': '0', + 'command_timeout': 15 + } devices = [] @@ -43,7 +45,7 @@ class TestCommandSensorBinarySensor(unittest.TestCase): def test_template(self): """Test setting the state with a template.""" - data = command_line.CommandSensorData(self.hass, 'echo 10') + data = command_line.CommandSensorData(self.hass, 'echo 10', 15) entity = command_line.CommandBinarySensor( self.hass, data, 'test', None, '1.0', '0', @@ -53,7 +55,7 @@ class TestCommandSensorBinarySensor(unittest.TestCase): def test_sensor_off(self): """Test setting the state with a template.""" - data = command_line.CommandSensorData(self.hass, 'echo 0') + data = command_line.CommandSensorData(self.hass, 'echo 0', 15) entity = command_line.CommandBinarySensor( self.hass, data, 'test', None, '1', '0', None) diff --git a/tests/components/sensor/test_command_line.py b/tests/components/sensor/test_command_line.py index bc073a04c47..3104ce897a1 100644 --- a/tests/components/sensor/test_command_line.py +++ b/tests/components/sensor/test_command_line.py @@ -21,7 +21,8 @@ class TestCommandSensorSensor(unittest.TestCase): """Test sensor setup.""" config = {'name': 'Test', 'unit_of_measurement': 'in', - 'command': 'echo 5' + 'command': 'echo 5', + 'command_timeout': 15 } devices = [] @@ -41,7 +42,7 @@ class TestCommandSensorSensor(unittest.TestCase): def test_template(self): """Test command sensor with template.""" - data = command_line.CommandSensorData(self.hass, 'echo 50') + data = command_line.CommandSensorData(self.hass, 'echo 50', 15) entity = command_line.CommandSensor( self.hass, data, 'test', 'in', @@ -55,7 +56,7 @@ class TestCommandSensorSensor(unittest.TestCase): self.hass.states.set('sensor.test_state', 'Works') data = command_line.CommandSensorData( self.hass, - 'echo {{ states.sensor.test_state.state }}' + 'echo {{ states.sensor.test_state.state }}', 15 ) data.update() @@ -63,7 +64,7 @@ class TestCommandSensorSensor(unittest.TestCase): def test_bad_command(self): """Test bad command.""" - data = command_line.CommandSensorData(self.hass, 'asdfasdf') + data = command_line.CommandSensorData(self.hass, 'asdfasdf', 15) data.update() self.assertEqual(None, data.value)