Customizable command timeout (#15442)

* Customizable command timeout

* Change string to int

* update the tests. Do the same thing on the binary_sensor.command_line.
This commit is contained in:
lich 2018-07-18 04:58:30 +08:00 committed by Fabian Affolter
parent 4ab502a691
commit 7d7c2104ea
4 changed files with 27 additions and 11 deletions

View File

@ -25,6 +25,9 @@ DEFAULT_PAYLOAD_OFF = 'OFF'
SCAN_INTERVAL = timedelta(seconds=60) SCAN_INTERVAL = timedelta(seconds=60)
CONF_COMMAND_TIMEOUT = 'command_timeout'
DEFAULT_TIMEOUT = 15
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COMMAND): cv.string, vol.Required(CONF_COMMAND): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): 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_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template, 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) payload_on = config.get(CONF_PAYLOAD_ON)
device_class = config.get(CONF_DEVICE_CLASS) device_class = config.get(CONF_DEVICE_CLASS)
value_template = config.get(CONF_VALUE_TEMPLATE) value_template = config.get(CONF_VALUE_TEMPLATE)
command_timeout = config.get(CONF_COMMAND_TIMEOUT)
if value_template is not None: if value_template is not None:
value_template.hass = hass value_template.hass = hass
data = CommandSensorData(hass, command) data = CommandSensorData(hass, command, command_timeout)
add_devices([CommandBinarySensor( add_devices([CommandBinarySensor(
hass, data, name, device_class, payload_on, payload_off, hass, data, name, device_class, payload_on, payload_off,

View File

@ -27,11 +27,16 @@ DEFAULT_NAME = 'Command Sensor'
SCAN_INTERVAL = timedelta(seconds=60) SCAN_INTERVAL = timedelta(seconds=60)
CONF_COMMAND_TIMEOUT = 'command_timeout'
DEFAULT_TIMEOUT = 15
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COMMAND): cv.string, vol.Required(CONF_COMMAND): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template, 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) command = config.get(CONF_COMMAND)
unit = config.get(CONF_UNIT_OF_MEASUREMENT) unit = config.get(CONF_UNIT_OF_MEASUREMENT)
value_template = config.get(CONF_VALUE_TEMPLATE) value_template = config.get(CONF_VALUE_TEMPLATE)
command_timeout = config.get(CONF_COMMAND_TIMEOUT)
if value_template is not None: if value_template is not None:
value_template.hass = hass value_template.hass = hass
data = CommandSensorData(hass, command) data = CommandSensorData(hass, command, command_timeout)
add_devices([CommandSensor(hass, data, name, unit, value_template)], True) add_devices([CommandSensor(hass, data, name, unit, value_template)], True)
@ -92,11 +98,12 @@ class CommandSensor(Entity):
class CommandSensorData(object): class CommandSensorData(object):
"""The class for handling the data retrieval.""" """The class for handling the data retrieval."""
def __init__(self, hass, command): def __init__(self, hass, command, command_timeout):
"""Initialize the data object.""" """Initialize the data object."""
self.value = None self.value = None
self.hass = hass self.hass = hass
self.command = command self.command = command
self.timeout = command_timeout
def update(self): def update(self):
"""Get the latest data with a shell command.""" """Get the latest data with a shell command."""
@ -135,7 +142,7 @@ class CommandSensorData(object):
try: try:
_LOGGER.info("Running command: %s", command) _LOGGER.info("Running command: %s", command)
return_value = subprocess.check_output( return_value = subprocess.check_output(
command, shell=shell, timeout=15) command, shell=shell, timeout=self.timeout)
self.value = return_value.strip().decode('utf-8') self.value = return_value.strip().decode('utf-8')
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
_LOGGER.error("Command failed: %s", command) _LOGGER.error("Command failed: %s", command)

View File

@ -24,7 +24,9 @@ class TestCommandSensorBinarySensor(unittest.TestCase):
config = {'name': 'Test', config = {'name': 'Test',
'command': 'echo 1', 'command': 'echo 1',
'payload_on': '1', 'payload_on': '1',
'payload_off': '0'} 'payload_off': '0',
'command_timeout': 15
}
devices = [] devices = []
@ -43,7 +45,7 @@ class TestCommandSensorBinarySensor(unittest.TestCase):
def test_template(self): def test_template(self):
"""Test setting the state with a template.""" """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( entity = command_line.CommandBinarySensor(
self.hass, data, 'test', None, '1.0', '0', self.hass, data, 'test', None, '1.0', '0',
@ -53,7 +55,7 @@ class TestCommandSensorBinarySensor(unittest.TestCase):
def test_sensor_off(self): def test_sensor_off(self):
"""Test setting the state with a template.""" """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( entity = command_line.CommandBinarySensor(
self.hass, data, 'test', None, '1', '0', None) self.hass, data, 'test', None, '1', '0', None)

View File

@ -21,7 +21,8 @@ class TestCommandSensorSensor(unittest.TestCase):
"""Test sensor setup.""" """Test sensor setup."""
config = {'name': 'Test', config = {'name': 'Test',
'unit_of_measurement': 'in', 'unit_of_measurement': 'in',
'command': 'echo 5' 'command': 'echo 5',
'command_timeout': 15
} }
devices = [] devices = []
@ -41,7 +42,7 @@ class TestCommandSensorSensor(unittest.TestCase):
def test_template(self): def test_template(self):
"""Test command sensor with template.""" """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( entity = command_line.CommandSensor(
self.hass, data, 'test', 'in', self.hass, data, 'test', 'in',
@ -55,7 +56,7 @@ class TestCommandSensorSensor(unittest.TestCase):
self.hass.states.set('sensor.test_state', 'Works') self.hass.states.set('sensor.test_state', 'Works')
data = command_line.CommandSensorData( data = command_line.CommandSensorData(
self.hass, self.hass,
'echo {{ states.sensor.test_state.state }}' 'echo {{ states.sensor.test_state.state }}', 15
) )
data.update() data.update()
@ -63,7 +64,7 @@ class TestCommandSensorSensor(unittest.TestCase):
def test_bad_command(self): def test_bad_command(self):
"""Test bad command.""" """Test bad command."""
data = command_line.CommandSensorData(self.hass, 'asdfasdf') data = command_line.CommandSensorData(self.hass, 'asdfasdf', 15)
data.update() data.update()
self.assertEqual(None, data.value) self.assertEqual(None, data.value)