From d719dd72fe0af904737c0411830f21321bfce6de Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 9 Sep 2015 14:22:08 +0200 Subject: [PATCH 1/5] Add arest switch --- homeassistant/components/switch/arest.py | 116 +++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 homeassistant/components/switch/arest.py diff --git a/homeassistant/components/switch/arest.py b/homeassistant/components/switch/arest.py new file mode 100644 index 00000000000..e171e954a12 --- /dev/null +++ b/homeassistant/components/switch/arest.py @@ -0,0 +1,116 @@ +""" +homeassistant.components.switch.arest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The arest switch can control the digital pins of a device running with the +aREST RESTful framework for Arduino, the ESP8266, and the Raspberry Pi. +Only tested with Arduino boards so far. + +Configuration: + +To use the arest switch you will need to add something like the following +to your configuration.yaml file. + +sensor: + platform: arest + resource: http://IP_ADDRESS + pins: + 11: + name: Fan Office + 12: + name: Light Desk + +Variables: + +resource: +*Required +IP address of the device that is exposing an aREST API. + +pins: +The number of the digital pin to switch. + +These are the variables for the pins array: + +name +*Required +The name for the pin that will be used in the frontend. + +Details for the API: http://arest.io +""" +import logging +from requests import get, exceptions + +from homeassistant.components.switch import SwitchDevice +from homeassistant.const import DEVICE_DEFAULT_NAME + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Get the aREST switches. """ + + resource = config.get('resource', None) + + try: + response = get(resource) + except exceptions.MissingSchema: + _LOGGER.error("Missing resource or schema in configuration. " + "Add http:// to your URL.") + return False + except exceptions.ConnectionError: + _LOGGER.error("No route to device. " + "Please check the IP address in the configuration file.") + return False + + dev = [] + pins = config.get('pins') + for pinnum, pin in pins.items(): + dev.append(ArestSwitch(resource, + response.json()['name'], + pin.get('name'), + pinnum)) + add_devices(dev) + + +class ArestSwitch(SwitchDevice): + """ Implements an aREST switch. """ + + def __init__(self, resource, location, name, pin): + self._resource = resource + self._name = '{} {}'.format(location.title(), name.title())\ + or DEVICE_DEFAULT_NAME + self._pin = pin + self._state = None + + request = get('{}/mode/{}/o'.format(self._resource, self._pin)) + if request.status_code is not 200: + _LOGGER.error("Can't set mode. Is device offline?") + + @property + def name(self): + """ The name of the switch. """ + return self._name + + @property + def is_on(self): + """ True if device is on. """ + request = get('{}/digital/{}'.format(self._resource, self._pin)) + if request.json()['return_value'] == 0: + self._state = False + else: + self._state = True + + return self._state + + def turn_on(self, **kwargs): + """ Turn the device on. """ + request = get('{}/digital/{}/1'.format(self._resource, self._pin)) + if request.status_code is not 200: + _LOGGER.error("Can't turn on the pin. Is device offline?") + self._state = True + + def turn_off(self, **kwargs): + """ Turn the device off. """ + request = get('{}/digital/{}/0'.format(self._resource, self._pin)) + if request.status_code is not 200: + _LOGGER.error("Can't turn off the pin. Is device offline?") + self._state = False From 1ec392a49420175187e274e982f474a44d3b20f5 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Sep 2015 19:11:20 +0200 Subject: [PATCH 2/5] Add update --- homeassistant/components/switch/arest.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/switch/arest.py b/homeassistant/components/switch/arest.py index e171e954a12..4f235c3bcd5 100644 --- a/homeassistant/components/switch/arest.py +++ b/homeassistant/components/switch/arest.py @@ -93,12 +93,6 @@ class ArestSwitch(SwitchDevice): @property def is_on(self): """ True if device is on. """ - request = get('{}/digital/{}'.format(self._resource, self._pin)) - if request.json()['return_value'] == 0: - self._state = False - else: - self._state = True - return self._state def turn_on(self, **kwargs): @@ -114,3 +108,8 @@ class ArestSwitch(SwitchDevice): if request.status_code is not 200: _LOGGER.error("Can't turn off the pin. Is device offline?") self._state = False + + def update(self): + """ Gets the latest data from aREST API and updates the state. """ + request = get('{}/digital/{}'.format(self._resource, self._pin)) + self._state = request.json()['return_value'] != 0 From 5d3e92959940f679150accb01d92c99e6b92ba83 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Sep 2015 21:07:06 +0200 Subject: [PATCH 3/5] Add timeout --- homeassistant/components/switch/arest.py | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/switch/arest.py b/homeassistant/components/switch/arest.py index 4f235c3bcd5..553b1be52c5 100644 --- a/homeassistant/components/switch/arest.py +++ b/homeassistant/components/switch/arest.py @@ -51,7 +51,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): resource = config.get('resource', None) try: - response = get(resource) + response = get(resource, timeout=10) except exceptions.MissingSchema: _LOGGER.error("Missing resource or schema in configuration. " "Add http:// to your URL.") @@ -81,7 +81,8 @@ class ArestSwitch(SwitchDevice): self._pin = pin self._state = None - request = get('{}/mode/{}/o'.format(self._resource, self._pin)) + request = get('{}/mode/{}/o'.format(self._resource, self._pin), + timeout=10) if request.status_code is not 200: _LOGGER.error("Can't set mode. Is device offline?") @@ -97,19 +98,26 @@ class ArestSwitch(SwitchDevice): def turn_on(self, **kwargs): """ Turn the device on. """ - request = get('{}/digital/{}/1'.format(self._resource, self._pin)) - if request.status_code is not 200: - _LOGGER.error("Can't turn on the pin. Is device offline?") - self._state = True + request = get('{}/digital/{}/1'.format(self._resource, self._pin), + timeout=10) + if request.status_code == 200: + self._state = True + else: + _LOGGER.error("Can't turn on pin %s at %s. Is device offline?", + self._resource, self._pin) def turn_off(self, **kwargs): """ Turn the device off. """ - request = get('{}/digital/{}/0'.format(self._resource, self._pin)) - if request.status_code is not 200: - _LOGGER.error("Can't turn off the pin. Is device offline?") - self._state = False + request = get('{}/digital/{}/0'.format(self._resource, self._pin), + timeout=10) + if request.status_code == 200: + self._state = False + else: + _LOGGER.error("Can't turn on pin %s at %s. Is device offline?", + self._resource, self._pin) def update(self): """ Gets the latest data from aREST API and updates the state. """ - request = get('{}/digital/{}'.format(self._resource, self._pin)) + request = get('{}/digital/{}'.format(self._resource, self._pin), + timeout=10) self._state = request.json()['return_value'] != 0 From e093abc366fac1f5f4677eb10dbcbc25b03b8cdd Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Sep 2015 21:26:51 +0200 Subject: [PATCH 4/5] Add arest switch --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index 9410611536d..6bfc048f10f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -73,6 +73,7 @@ omit = homeassistant/components/sensor/temper.py homeassistant/components/sensor/time_date.py homeassistant/components/sensor/transmission.py + homeassistant/components/switch/arest.py homeassistant/components/switch/command_switch.py homeassistant/components/switch/edimax.py homeassistant/components/switch/hikvisioncam.py From e2b02f2fd21ef5b5655348c2449acaec7c6d34f8 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 11 Sep 2015 08:07:16 +0200 Subject: [PATCH 5/5] Update error message --- homeassistant/components/switch/arest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/arest.py b/homeassistant/components/switch/arest.py index 553b1be52c5..239e24a4925 100644 --- a/homeassistant/components/switch/arest.py +++ b/homeassistant/components/switch/arest.py @@ -76,7 +76,7 @@ class ArestSwitch(SwitchDevice): def __init__(self, resource, location, name, pin): self._resource = resource - self._name = '{} {}'.format(location.title(), name.title())\ + self._name = '{} {}'.format(location.title(), name.title()) \ or DEVICE_DEFAULT_NAME self._pin = pin self._state = None @@ -113,7 +113,7 @@ class ArestSwitch(SwitchDevice): if request.status_code == 200: self._state = False else: - _LOGGER.error("Can't turn on pin %s at %s. Is device offline?", + _LOGGER.error("Can't turn off pin %s at %s. Is device offline?", self._resource, self._pin) def update(self):