From 65bd7d2326f09c732dea172f5f1ca01c19e7b560 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Fri, 28 Oct 2016 01:34:22 -0400 Subject: [PATCH] Generalized REST switch to enable templating and configurable timeout. (#3329) * successfully tested the "remote temperature mode" switch for the radio thermostat * removed logging and interpreted None as Off. * turn_off value is also templated now -- can depend on state Also, undid accidental removal of error logging. * ensured backward compatibility of config file if value_template is not provided, the update function behaves as before * ran autopep8 --in-place * fixed another complaint of tox * addressed the comments of balloob * undid acccidental log.error to log.info * timeout : 50 -> 10 * added a timeout parameter * removed the stray '-', better names for the failure case * string comparisons after .lower(), as suggested by balloob * addressed balloob's latest requests * making flake happy * value_template --> is_on_template in config file * moved CONF_IS_ON_TEMPLATE to local file * null checks * addressed flake error * properly comparing template text when is_on is not a template. --- homeassistant/components/switch/rest.py | 64 +++++++++++++++++++------ 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/switch/rest.py b/homeassistant/components/switch/rest.py index ee29dd13adb..e6ac231e3e1 100644 --- a/homeassistant/components/switch/rest.py +++ b/homeassistant/components/switch/rest.py @@ -10,7 +10,8 @@ import requests import voluptuous as vol from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) -from homeassistant.const import (CONF_NAME, CONF_RESOURCE) +from homeassistant.const import ( + CONF_NAME, CONF_RESOURCE, CONF_TIMEOUT) import homeassistant.helpers.config_validation as cv CONF_BODY_OFF = 'body_off' @@ -18,12 +19,16 @@ CONF_BODY_ON = 'body_on' DEFAULT_BODY_OFF = 'OFF' DEFAULT_BODY_ON = 'ON' DEFAULT_NAME = 'REST Switch' +DEFAULT_TIMEOUT = 10 +CONF_IS_ON_TEMPLATE = 'is_on_template' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_RESOURCE): cv.url, - vol.Optional(CONF_BODY_OFF, default=DEFAULT_BODY_OFF): cv.string, - vol.Optional(CONF_BODY_ON, default=DEFAULT_BODY_ON): cv.string, + vol.Optional(CONF_BODY_OFF, default=DEFAULT_BODY_OFF): cv.template, + vol.Optional(CONF_BODY_ON, default=DEFAULT_BODY_ON): cv.template, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_IS_ON_TEMPLATE): cv.template, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, }) _LOGGER = logging.getLogger(__name__) @@ -36,6 +41,15 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): resource = config.get(CONF_RESOURCE) body_on = config.get(CONF_BODY_ON) body_off = config.get(CONF_BODY_OFF) + is_on_template = config.get(CONF_IS_ON_TEMPLATE) + + if is_on_template is not None: + is_on_template.hass = hass + if body_on is not None: + body_on.hass = hass + if body_off is not None: + body_off.hass = hass + timeout = config.get(CONF_TIMEOUT) try: requests.get(resource, timeout=10) @@ -47,14 +61,18 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): _LOGGER.error("No route to resource/endpoint: %s", resource) return False - add_devices_callback([RestSwitch(hass, name, resource, body_on, body_off)]) + add_devices_callback( + [RestSwitch(hass, name, resource, + body_on, body_off, is_on_template, timeout)]) # pylint: disable=too-many-arguments class RestSwitch(SwitchDevice): """Representation of a switch that can be toggled using REST.""" - def __init__(self, hass, name, resource, body_on, body_off): + # pylint: disable=too-many-instance-attributes + def __init__(self, hass, name, resource, body_on, body_off, + is_on_template, timeout): """Initialize the REST switch.""" self._state = None self._hass = hass @@ -62,6 +80,8 @@ class RestSwitch(SwitchDevice): self._resource = resource self._body_on = body_on self._body_off = body_off + self._is_on_template = is_on_template + self._timeout = timeout @property def name(self): @@ -75,9 +95,10 @@ class RestSwitch(SwitchDevice): def turn_on(self, **kwargs): """Turn the device on.""" + body_on_t = self._body_on.render() request = requests.post(self._resource, - data=self._body_on, - timeout=10) + data=body_on_t, + timeout=self._timeout) if request.status_code == 200: self._state = True else: @@ -86,9 +107,10 @@ class RestSwitch(SwitchDevice): def turn_off(self, **kwargs): """Turn the device off.""" + body_off_t = self._body_off.render() request = requests.post(self._resource, - data=self._body_off, - timeout=10) + data=body_off_t, + timeout=self._timeout) if request.status_code == 200: self._state = False else: @@ -97,10 +119,22 @@ class RestSwitch(SwitchDevice): def update(self): """Get the latest data from REST API and update the state.""" - request = requests.get(self._resource, timeout=10) - if request.text == self._body_on: - self._state = True - elif request.text == self._body_off: - self._state = False + request = requests.get(self._resource, timeout=self._timeout) + + if self._is_on_template is not None: + response = self._is_on_template.render_with_possible_json_value( + request.text, 'None') + response = response.lower() + if response == 'true': + self._state = True + elif response == 'false': + self._state = False + else: + self._state = None else: - self._state = None + if request.text == self._body_on.template: + self._state = True + elif request.text == self._body_off.template: + self._state = False + else: + self._state = None